summaryrefslogtreecommitdiff
path: root/chromium/components
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components')
-rw-r--r--chromium/components/BUILD.gn21
-rw-r--r--chromium/components/OWNERS1
-rw-r--r--chromium/components/app_modal/javascript_dialog_manager.cc5
-rw-r--r--chromium/components/app_modal/javascript_dialog_manager.h2
-rw-r--r--chromium/components/app_modal/javascript_dialog_manager_unittest.cc67
-rw-r--r--chromium/components/app_modal_strings.grdp71
-rw-r--r--chromium/components/arc/BUILD.gn17
-rw-r--r--chromium/components/arc/DEPS1
-rw-r--r--chromium/components/arc/PRESUBMIT.py12
-rw-r--r--chromium/components/arc/arc_bridge_host_impl.cc11
-rw-r--r--chromium/components/arc/arc_bridge_host_impl.h3
-rw-r--r--chromium/components/arc/arc_bridge_service.h21
-rw-r--r--chromium/components/arc/arc_prefs.cc9
-rw-r--r--chromium/components/arc/arc_prefs.h3
-rw-r--r--chromium/components/arc/arc_session.h38
-rw-r--r--chromium/components/arc/arc_session_impl.cc195
-rw-r--r--chromium/components/arc/arc_session_impl.h59
-rw-r--r--chromium/components/arc/arc_session_impl_unittest.cc204
-rw-r--r--chromium/components/arc/arc_session_runner.cc35
-rw-r--r--chromium/components/arc/arc_session_runner.h4
-rw-r--r--chromium/components/arc/arc_session_runner_unittest.cc2
-rw-r--r--chromium/components/arc/common/BUILD.gn2
-rw-r--r--chromium/components/arc/common/accessibility_helper.mojom20
-rw-r--r--chromium/components/arc/common/arc_bridge.mojom12
-rw-r--r--chromium/components/arc/common/ime.mojom29
-rw-r--r--chromium/components/arc/common/notifications.mojom49
-rw-r--r--chromium/components/arc/common/policy.mojom58
-rw-r--r--chromium/components/arc/common/print.mojom183
-rw-r--r--chromium/components/arc/common/print.typemap19
-rw-r--r--chromium/components/arc/common/scale_factor.mojom1
-rw-r--r--chromium/components/arc/common/screen_capture.mojom74
-rw-r--r--chromium/components/arc/common/timer.mojom66
-rw-r--r--chromium/components/arc/common/timer.typemap12
-rw-r--r--chromium/components/arc/common/typemaps.gni2
-rw-r--r--chromium/components/arc/common/usb_host.mojom2
-rw-r--r--chromium/components/arc/common/voice_interaction_arc_home.mojom4
-rw-r--r--chromium/components/arc/common/volume_mounter.mojom15
-rw-r--r--chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc2
-rw-r--r--chromium/components/arc/ime/arc_ime_bridge.h6
-rw-r--r--chromium/components/arc/ime/arc_ime_bridge_impl.cc11
-rw-r--r--chromium/components/arc/ime/arc_ime_bridge_impl.h13
-rw-r--r--chromium/components/arc/ime/arc_ime_service.cc89
-rw-r--r--chromium/components/arc/ime/arc_ime_service.h17
-rw-r--r--chromium/components/arc/ime/arc_ime_service_unittest.cc69
-rw-r--r--chromium/components/arc/intent_helper/DEPS4
-rw-r--r--chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc13
-rw-r--r--chromium/components/arc/midis/arc_midis_bridge.cc6
-rw-r--r--chromium/components/arc/power/arc_power_bridge.cc13
-rw-r--r--chromium/components/arc/power/arc_power_bridge.h2
-rw-r--r--chromium/components/arc/timer/arc_timer.cc76
-rw-r--r--chromium/components/arc/timer/arc_timer.h79
-rw-r--r--chromium/components/arc/timer/arc_timer_bridge.cc248
-rw-r--r--chromium/components/arc/timer/arc_timer_bridge.h111
-rw-r--r--chromium/components/arc/timer/arc_timer_bridge_unittest.cc278
-rw-r--r--chromium/components/arc/timer/arc_timer_traits.cc97
-rw-r--r--chromium/components/arc/timer/arc_timer_traits.h36
-rw-r--r--chromium/components/arc/timer/create_timer_request.cc13
-rw-r--r--chromium/components/arc/timer/create_timer_request.h28
-rw-r--r--chromium/components/arc/usb/usb_host_bridge.cc49
-rw-r--r--chromium/components/arc/usb/usb_host_bridge.h16
-rw-r--r--chromium/components/arc/usb/usb_host_ui_delegate.h58
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc4
-rw-r--r--chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc40
-rw-r--r--chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h11
-rw-r--r--chromium/components/assist_ranker/BUILD.gn3
-rw-r--r--chromium/components/assist_ranker/DEPS3
-rw-r--r--chromium/components/assist_ranker/OWNERS3
-rw-r--r--chromium/components/assist_ranker/base_predictor_unittest.cc5
-rw-r--r--chromium/components/assist_ranker/binary_classifier_predictor.cc22
-rw-r--r--chromium/components/assist_ranker/binary_classifier_predictor_unittest.cc39
-rw-r--r--chromium/components/assist_ranker/example_preprocessing.cc197
-rw-r--r--chromium/components/assist_ranker/example_preprocessing.h143
-rw-r--r--chromium/components/assist_ranker/example_preprocessing_unittest.cc298
-rw-r--r--chromium/components/assist_ranker/generic_logistic_regression_inference.cc94
-rw-r--r--chromium/components/assist_ranker/generic_logistic_regression_inference_unittest.cc132
-rw-r--r--chromium/components/assist_ranker/proto/BUILD.gn1
-rw-r--r--chromium/components/assist_ranker/proto/example_preprocessor.proto26
-rw-r--r--chromium/components/assist_ranker/proto/generic_logistic_regression_model.proto15
-rw-r--r--chromium/components/assist_ranker/proto/ranker_example.proto7
-rw-r--r--chromium/components/assist_ranker/ranker_example_util.cc2
-rw-r--r--chromium/components/assist_ranker/ranker_model.cc7
-rw-r--r--chromium/components/assist_ranker/ranker_model_loader_impl.cc7
-rw-r--r--chromium/components/assist_ranker/ranker_model_loader_impl_unittest.cc5
-rw-r--r--chromium/components/assist_ranker/ranker_model_unittest.cc3
-rw-r--r--chromium/components/autofill/android/java/strings/translations/autofill_strings_ko.xtb2
-rw-r--r--chromium/components/autofill/content/browser/BUILD.gn3
-rw-r--r--chromium/components/autofill/content/browser/DEPS2
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.cc25
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.h4
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_factory.cc6
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_factory.h2
-rw-r--r--chromium/components/autofill/content/browser/risk/fingerprint.cc8
-rw-r--r--chromium/components/autofill/content/browser/risk/fingerprint_browsertest.cc2
-rw-r--r--chromium/components/autofill/content/common/BUILD.gn7
-rw-r--r--chromium/components/autofill/content/common/autofill_agent.mojom18
-rw-r--r--chromium/components/autofill/content/common/autofill_driver.mojom20
-rw-r--r--chromium/components/autofill/content/common/autofill_types.mojom70
-rw-r--r--chromium/components/autofill/content/common/autofill_types_struct_traits.cc81
-rw-r--r--chromium/components/autofill/content/common/autofill_types_struct_traits.h14
-rw-r--r--chromium/components/autofill/content/renderer/DEPS2
-rw-r--r--chromium/components/autofill/content/renderer/autofill_agent.cc9
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util.cc137
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util.h7
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc64
-rw-r--r--chromium/components/autofill/content/renderer/form_classifier.h5
-rw-r--r--chromium/components/autofill/content/renderer/form_tracker.cc22
-rw-r--r--chromium/components/autofill/content/renderer/html_based_username_detector.h5
-rw-r--r--chromium/components/autofill/content/renderer/html_based_username_detector_vocabulary.h5
-rw-r--r--chromium/components/autofill/content/renderer/page_passwords_analyser.cc2
-rw-r--r--chromium/components/autofill/content/renderer/password_autofill_agent.cc28
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils.cc15
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils.h3
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc47
-rw-r--r--chromium/components/autofill/content/renderer/password_generation_agent.cc2
-rw-r--r--chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc3
-rw-r--r--chromium/components/autofill/core/browser/BUILD.gn7
-rw-r--r--chromium/components/autofill/core/browser/DEPS3
-rw-r--r--chromium/components/autofill/core/browser/autocomplete_history_manager.cc1
-rw-r--r--chromium/components/autofill/core/browser/autofill_client.h9
-rw-r--r--chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc5
-rw-r--r--chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.h1
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.cc21
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.h14
-rw-r--r--chromium/components/autofill/core/browser/autofill_field.cc40
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.cc73
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager_unittest.cc151
-rw-r--r--chromium/components/autofill/core/browser/autofill_merge_unittest.cc11
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.cc14
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.h15
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics_unittest.cc55
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc38
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h9
-rw-r--r--chromium/components/autofill/core/browser/autofill_scanner.h3
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.cc23
-rw-r--r--chromium/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/credit_card.cc11
-rw-r--r--chromium/components/autofill/core/browser/credit_card.h10
-rw-r--r--chromium/components/autofill/core/browser/credit_card_field.cc26
-rw-r--r--chromium/components/autofill/core/browser/credit_card_save_manager.cc4
-rw-r--r--chromium/components/autofill/core/browser/credit_card_save_manager_unittest.cc53
-rw-r--r--chromium/components/autofill/core/browser/credit_card_unittest.cc8
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer.cc59
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer.h32
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer_unittest.cc352
-rw-r--r--chromium/components/autofill/core/browser/form_field.h6
-rw-r--r--chromium/components/autofill/core/browser/form_structure.cc66
-rw-r--r--chromium/components/autofill/core/browser/form_structure.h5
-rw-r--r--chromium/components/autofill/core/browser/form_structure_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.cc53
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.h32
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client_unittest.cc38
-rw-r--r--chromium/components/autofill/core/browser/payments/test_payments_client.cc4
-rw-r--r--chromium/components/autofill/core/browser/payments/test_payments_client.h2
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.cc15
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.h27
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager_unittest.cc47
-rw-r--r--chromium/components/autofill/core/browser/state_names.h4
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.cc7
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.h9
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_clock.cc10
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_clock.h4
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_manager.cc2
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc18
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_data_type_controller_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc157
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h26
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc107
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc65
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h3
-rw-r--r--chromium/components/autofill/core/common/autofill_clock.cc22
-rw-r--r--chromium/components/autofill/core/common/autofill_clock.h17
-rw-r--r--chromium/components/autofill/core/common/autofill_features.cc11
-rw-r--r--chromium/components/autofill/core/common/autofill_features.h2
-rw-r--r--chromium/components/autofill/core/common/autofill_regexes.cc25
-rw-r--r--chromium/components/autofill/core/common/form_field_data.cc28
-rw-r--r--chromium/components/autofill/core/common/form_field_data.h18
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.cc4
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.h2
-rw-r--r--chromium/components/autofill/ios/browser/BUILD.gn2
-rw-r--r--chromium/components/autofill/ios/browser/autofill_agent.mm10
-rw-r--r--chromium/components/autofill/ios/browser/autofill_switches.cc16
-rw-r--r--chromium/components/autofill/ios/browser/autofill_switches.h18
-rw-r--r--chromium/components/autofill/ios/browser/js_autofill_manager.h3
-rw-r--r--chromium/components/autofill/ios/browser/js_autofill_manager.mm20
-rw-r--r--chromium/components/autofill/ios/browser/resources/autofill_controller.js429
-rw-r--r--chromium/components/autofill/ios/browser/resources/suggestion_controller.js115
-rw-r--r--chromium/components/autofill/ios/fill/resources/fill.js313
-rw-r--r--chromium/components/autofill_strings.grdp2
-rw-r--r--chromium/components/background_task_scheduler/BUILD.gn2
-rw-r--r--chromium/components/background_task_scheduler/README.md34
-rw-r--r--chromium/components/bookmark_component_strings.grdp9
-rw-r--r--chromium/components/bookmarks/browser/bookmark_codec.cc1
-rw-r--r--chromium/components/bookmarks/browser/bookmark_index_unittest.cc1
-rw-r--r--chromium/components/bookmarks/browser/bookmark_model.cc1
-rw-r--r--chromium/components/bookmarks/browser/bookmark_model_unittest.cc2
-rw-r--r--chromium/components/bookmarks/browser/bookmark_storage.cc19
-rw-r--r--chromium/components/bookmarks/managed/managed_bookmark_service.cc1
-rw-r--r--chromium/components/bookmarks/managed/managed_bookmarks_tracker.cc1
-rw-r--r--chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc1
-rw-r--r--chromium/components/browser_sync/BUILD.gn1
-rw-r--r--chromium/components/browser_sync/profile_sync_components_factory_impl.cc80
-rw-r--r--chromium/components/browser_sync/profile_sync_components_factory_impl.h6
-rw-r--r--chromium/components/browser_sync/profile_sync_service.cc33
-rw-r--r--chromium/components/browser_sync/profile_sync_service.h7
-rw-r--r--chromium/components/browser_sync/profile_sync_service_autofill_unittest.cc15
-rw-r--r--chromium/components/browser_sync/profile_sync_service_mock.cc5
-rw-r--r--chromium/components/browser_sync/profile_sync_service_mock.h8
-rw-r--r--chromium/components/browser_sync/profile_sync_service_typed_url_unittest.cc1044
-rw-r--r--chromium/components/browser_sync/profile_sync_service_unittest.cc7
-rw-r--r--chromium/components/browser_sync/profile_sync_test_util.cc11
-rw-r--r--chromium/components/browser_sync/profile_sync_test_util.h22
-rw-r--r--chromium/components/browser_sync/signin_confirmation_helper.cc1
-rw-r--r--chromium/components/browser_watcher/BUILD.gn7
-rw-r--r--chromium/components/browser_watcher/fetch_system_session_events_main_win.cc14
-rw-r--r--chromium/components/browser_watcher/postmortem_minidump_writer.h4
-rw-r--r--chromium/components/browser_watcher/postmortem_minidump_writer_win.cc87
-rw-r--r--chromium/components/browser_watcher/postmortem_minidump_writer_win_unittest.cc11
-rw-r--r--chromium/components/browser_watcher/postmortem_report_collector.cc17
-rw-r--r--chromium/components/browser_watcher/postmortem_report_collector.h8
-rw-r--r--chromium/components/browser_watcher/postmortem_report_collector_unittest.cc116
-rw-r--r--chromium/components/browser_watcher/stability_debugging_win_unittest.cc9
-rw-r--r--chromium/components/browser_watcher/watcher_metrics_provider_win.cc4
-rw-r--r--chromium/components/browser_watcher/window_hang_monitor_win_unittest.cc7
-rw-r--r--chromium/components/browsing_data/core/BUILD.gn2
-rw-r--r--chromium/components/browsing_data/core/browsing_data_utils.cc14
-rw-r--r--chromium/components/browsing_data/core/browsing_data_utils.h5
-rw-r--r--chromium/components/browsing_data/core/browsing_data_utils_unittest.cc29
-rw-r--r--chromium/components/browsing_data/core/counters/autofill_counter.cc4
-rw-r--r--chromium/components/browsing_data/core/counters/browsing_data_counter.cc14
-rw-r--r--chromium/components/browsing_data/core/counters/history_counter.cc6
-rw-r--r--chromium/components/browsing_data/core/counters/passwords_counter.cc9
-rw-r--r--chromium/components/browsing_data/core/features.cc14
-rw-r--r--chromium/components/browsing_data/core/features.h19
-rw-r--r--chromium/components/captive_portal/BUILD.gn2
-rw-r--r--chromium/components/captive_portal/DEPS3
-rw-r--r--chromium/components/captive_portal/captive_portal_detector.cc85
-rw-r--r--chromium/components/captive_portal/captive_portal_detector.h44
-rw-r--r--chromium/components/captive_portal/captive_portal_detector_unittest.cc12
-rw-r--r--chromium/components/captive_portal/captive_portal_testing_utils.cc19
-rw-r--r--chromium/components/captive_portal/captive_portal_testing_utils.h11
-rw-r--r--chromium/components/cast_certificate/cast_cert_validator.cc3
-rw-r--r--chromium/components/cast_certificate/cast_cert_validator_unittest.cc6
-rw-r--r--chromium/components/cast_certificate/cast_crl.cc4
-rw-r--r--chromium/components/cast_channel/BUILD.gn5
-rw-r--r--chromium/components/cast_channel/cast_message_handler.cc234
-rw-r--r--chromium/components/cast_channel/cast_message_handler.h150
-rw-r--r--chromium/components/cast_channel/cast_message_handler_unittest.cc180
-rw-r--r--chromium/components/cast_channel/cast_message_util.cc82
-rw-r--r--chromium/components/cast_channel/cast_message_util.h25
-rw-r--r--chromium/components/cast_channel/cast_socket.cc39
-rw-r--r--chromium/components/cast_channel/cast_socket_service.h1
-rw-r--r--chromium/components/cast_channel/cast_socket_service_unittest.cc8
-rw-r--r--chromium/components/cast_channel/cast_socket_unittest.cc2
-rw-r--r--chromium/components/cast_channel/cast_test_util.cc6
-rw-r--r--chromium/components/cast_channel/cast_test_util.h21
-rw-r--r--chromium/components/cast_channel/keep_alive_delegate.cc27
-rw-r--r--chromium/components/cast_channel/keep_alive_delegate_unittest.cc4
-rw-r--r--chromium/components/cbor/cbor_binary.h4
-rw-r--r--chromium/components/cbor/cbor_reader.cc165
-rw-r--r--chromium/components/cbor/cbor_reader.h72
-rw-r--r--chromium/components/cbor/cbor_reader_unittest.cc501
-rw-r--r--chromium/components/cbor/cbor_values.cc77
-rw-r--r--chromium/components/cbor/cbor_values.h72
-rw-r--r--chromium/components/cbor/cbor_values_unittest.cc18
-rw-r--r--chromium/components/cbor/cbor_writer_unittest.cc63
-rw-r--r--chromium/components/cdm/browser/cdm_message_filter_android.cc2
-rw-r--r--chromium/components/cdm/browser/media_drm_storage_impl.cc5
-rw-r--r--chromium/components/cdm/browser/media_drm_storage_impl_unittest.cc7
-rw-r--r--chromium/components/certificate_reporting/cert_logger.proto1
-rw-r--r--chromium/components/certificate_reporting/error_report.cc1
-rw-r--r--chromium/components/certificate_reporting/error_report_unittest.cc7
-rw-r--r--chromium/components/certificate_reporting/error_reporter.cc5
-rw-r--r--chromium/components/certificate_reporting/error_reporter_unittest.cc2
-rw-r--r--chromium/components/certificate_transparency/log_dns_client_unittest.cc3
-rw-r--r--chromium/components/certificate_transparency/single_tree_tracker.cc3
-rw-r--r--chromium/components/certificate_transparency/single_tree_tracker_unittest.cc6
-rw-r--r--chromium/components/certificate_transparency/tree_state_tracker.cc5
-rw-r--r--chromium/components/certificate_transparency/tree_state_tracker_unittest.cc5
-rw-r--r--chromium/components/chrome_cleaner/OWNERS5
-rw-r--r--chromium/components/chrome_cleaner/README.md5
-rw-r--r--chromium/components/client_update_protocol/DEPS1
-rw-r--r--chromium/components/cloud_devices/common/description_items_inl.h5
-rw-r--r--chromium/components/cloud_devices/common/printer_description.cc5
-rw-r--r--chromium/components/component_updater/component_installer.cc9
-rw-r--r--chromium/components/component_updater/component_installer.h15
-rw-r--r--chromium/components/component_updater/component_installer_unittest.cc13
-rw-r--r--chromium/components/component_updater/component_updater_service.cc15
-rw-r--r--chromium/components/component_updater/component_updater_service.h3
-rw-r--r--chromium/components/component_updater/component_updater_service_internal.h4
-rw-r--r--chromium/components/component_updater/component_updater_service_unittest.cc7
-rw-r--r--chromium/components/component_updater/configurator_impl.cc13
-rw-r--r--chromium/components/component_updater/configurator_impl.h9
-rw-r--r--chromium/components/component_updater/configurator_impl_unittest.cc6
-rw-r--r--chromium/components/components_strings.grd4
-rw-r--r--chromium/components/consent_auditor/BUILD.gn12
-rw-r--r--chromium/components/consent_auditor/OWNERS1
-rw-r--r--chromium/components/consent_auditor/consent_auditor.cc99
-rw-r--r--chromium/components/consent_auditor/consent_auditor.h45
-rw-r--r--chromium/components/consent_auditor/consent_auditor_unittest.cc35
-rw-r--r--chromium/components/consent_auditor/pref_names.h5
-rw-r--r--chromium/components/constrained_window/constrained_window_views_unittest.cc3
-rw-r--r--chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views_mac.h5
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_default_provider.cc4
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_global_value_map.cc4
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_pref.cc5
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_pref_provider.cc3
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_registry.cc13
-rw-r--r--chromium/components/content_settings/core/browser/cookie_settings.cc14
-rw-r--r--chromium/components/content_settings/core/browser/cookie_settings.h5
-rw-r--r--chromium/components/content_settings/core/browser/cookie_settings_unittest.cc23
-rw-r--r--chromium/components/content_settings/core/browser/host_content_settings_map.cc41
-rw-r--r--chromium/components/content_settings/core/browser/host_content_settings_map.h6
-rw-r--r--chromium/components/content_settings/core/browser/website_settings_registry.cc4
-rw-r--r--chromium/components/content_settings/core/browser/website_settings_registry_unittest.cc7
-rw-r--r--chromium/components/content_settings/core/common/content_settings.cc7
-rw-r--r--chromium/components/content_settings/core/common/content_settings_pattern.cc3
-rw-r--r--chromium/components/content_settings/core/common/content_settings_types.h7
-rw-r--r--chromium/components/content_settings/core/common/content_settings_utils.cc5
-rw-r--r--chromium/components/content_view/BUILD.gn15
-rw-r--r--chromium/components/content_view/DEPS6
-rw-r--r--chromium/components/content_view/OWNERS6
-rw-r--r--chromium/components/content_view/README2
-rw-r--r--chromium/components/contextual_search/BUILD.gn2
-rw-r--r--chromium/components/contextual_search/browser/contextual_search_js_api_service_impl.cc4
-rw-r--r--chromium/components/contextual_search/common/contextual_search_js_api_service.mojom2
-rw-r--r--chromium/components/crash/content/app/BUILD.gn17
-rw-r--r--chromium/components/crash/content/app/breakpad_linux.cc8
-rw-r--r--chromium/components/crash/content/app/breakpad_win.cc3
-rw-r--r--chromium/components/crash/content/app/crash_export_stubs.cc9
-rw-r--r--chromium/components/crash/content/app/crash_export_thunks.cc13
-rw-r--r--chromium/components/crash/content/app/crash_export_thunks.h8
-rw-r--r--chromium/components/crash/content/app/crashpad.cc26
-rw-r--r--chromium/components/crash/content/app/crashpad.h6
-rw-r--r--chromium/components/crash/content/app/dump_hung_process_with_ptype.cc56
-rw-r--r--chromium/components/crash/content/app/dump_hung_process_with_ptype.h23
-rw-r--r--chromium/components/crash/content/app/fallback_crash_handler_win.cc359
-rw-r--r--chromium/components/crash/content/app/minidump_with_crashpad_info.cc376
-rw-r--r--chromium/components/crash/content/app/minidump_with_crashpad_info.h36
-rw-r--r--chromium/components/crash/content/app/run_as_crashpad_handler_win.cc3
-rw-r--r--chromium/components/crash/content/browser/crash_dump_observer_android.cc1
-rw-r--r--chromium/components/crash/content/browser/crash_handler_host_linux.cc41
-rwxr-xr-xchromium/components/crash/content/tools/generate_breakpad_symbols.py3
-rw-r--r--chromium/components/crash/core/common/crash_keys.cc74
-rw-r--r--chromium/components/crash/core/common/crash_keys.h13
-rw-r--r--chromium/components/crash/core/common/crash_keys_unittest.cc6
-rw-r--r--chromium/components/cronet/BUILD.gn50
-rw-r--r--chromium/components/cronet/android/BUILD.gn126
-rw-r--r--chromium/components/cronet/ios/BUILD.gn38
-rw-r--r--chromium/components/cronet/ios/test/BUILD.gn5
-rw-r--r--chromium/components/cronet/native/BUILD.gn92
-rw-r--r--chromium/components/cronet/native/test/BUILD.gn51
-rw-r--r--chromium/components/cronet/test/BUILD.gn61
-rw-r--r--chromium/components/crx_file/crx_verifier.cc5
-rw-r--r--chromium/components/cryptauth/BUILD.gn12
-rw-r--r--chromium/components/cryptauth/background_eid_generator.cc6
-rw-r--r--chromium/components/cryptauth/background_eid_generator_unittest.cc3
-rw-r--r--chromium/components/cryptauth/ble/ble_advertisement_generator.cc4
-rw-r--r--chromium/components/cryptauth/ble/ble_advertisement_generator_unittest.cc12
-rw-r--r--chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc42
-rw-r--r--chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h4
-rw-r--r--chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc96
-rw-r--r--chromium/components/cryptauth/ble/bluetooth_low_energy_weave_packet_generator_unittest.cc18
-rw-r--r--chromium/components/cryptauth/ble/bluetooth_low_energy_weave_packet_receiver_unittest.cc72
-rw-r--r--chromium/components/cryptauth/cryptauth_client_impl.cc3
-rw-r--r--chromium/components/cryptauth/cryptauth_device_manager.cc605
-rw-r--r--chromium/components/cryptauth/cryptauth_device_manager.h129
-rw-r--r--chromium/components/cryptauth/cryptauth_device_manager_impl.cc581
-rw-r--r--chromium/components/cryptauth/cryptauth_device_manager_impl.h112
-rw-r--r--chromium/components/cryptauth/cryptauth_device_manager_impl_unittest.cc (renamed from chromium/components/cryptauth/cryptauth_device_manager_unittest.cc)183
-rw-r--r--chromium/components/cryptauth/cryptauth_enrollment_manager.cc273
-rw-r--r--chromium/components/cryptauth/cryptauth_enrollment_manager.h129
-rw-r--r--chromium/components/cryptauth/cryptauth_enrollment_manager_impl.cc284
-rw-r--r--chromium/components/cryptauth/cryptauth_enrollment_manager_impl.h137
-rw-r--r--chromium/components/cryptauth/cryptauth_enrollment_manager_impl_unittest.cc (renamed from chromium/components/cryptauth/cryptauth_enrollment_manager_unittest.cc)73
-rw-r--r--chromium/components/cryptauth/device_capability_manager_impl.cc10
-rw-r--r--chromium/components/cryptauth/device_capability_manager_impl_unittest.cc7
-rw-r--r--chromium/components/cryptauth/device_to_device_authenticator.cc11
-rw-r--r--chromium/components/cryptauth/device_to_device_authenticator_unittest.cc5
-rw-r--r--chromium/components/cryptauth/device_to_device_operations_unittest.cc5
-rw-r--r--chromium/components/cryptauth/device_to_device_secure_context_unittest.cc8
-rw-r--r--chromium/components/cryptauth/fake_connection.cc4
-rw-r--r--chromium/components/cryptauth/fake_cryptauth_device_manager.cc83
-rw-r--r--chromium/components/cryptauth/fake_cryptauth_device_manager.h106
-rw-r--r--chromium/components/cryptauth/fake_cryptauth_enrollment_manager.cc68
-rw-r--r--chromium/components/cryptauth/fake_cryptauth_enrollment_manager.h85
-rw-r--r--chromium/components/cryptauth/fake_cryptauth_service.cc7
-rw-r--r--chromium/components/cryptauth/fake_secure_channel.cc8
-rw-r--r--chromium/components/cryptauth/fake_secure_message_delegate_unittest.cc1
-rw-r--r--chromium/components/cryptauth/foreground_eid_generator.cc3
-rw-r--r--chromium/components/cryptauth/foreground_eid_generator_unittest.cc5
-rw-r--r--chromium/components/cryptauth/local_device_data_provider_unittest.cc106
-rw-r--r--chromium/components/cryptauth/mock_foreground_eid_generator.cc8
-rw-r--r--chromium/components/cryptauth/remote_beacon_seed_fetcher_unittest.cc35
-rw-r--r--chromium/components/cryptauth/remote_device_loader_unittest.cc5
-rw-r--r--chromium/components/cryptauth/remote_device_provider_impl_unittest.cc100
-rw-r--r--chromium/components/cryptauth/secure_channel.cc10
-rw-r--r--chromium/components/cryptauth/secure_channel.h3
-rw-r--r--chromium/components/cryptauth/secure_channel_unittest.cc51
-rw-r--r--chromium/components/cryptauth/sync_scheduler_impl.cc6
-rw-r--r--chromium/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc4
-rw-r--r--chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc2
-rw-r--r--chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc2
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/BUILD.gn3
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc23
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h9
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc83
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc6
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc14
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc128
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h41
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc8
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc41
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h17
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc76
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc17
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h6
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc42
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc31
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer_unittest.cc26
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc157
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h17
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc204
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc15
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc42
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h7
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc12
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc4
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc14
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h2
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc2
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc15
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h2
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc107
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc2
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h2
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc2
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc28
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h5
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc33
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h5
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc15
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc6
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h2
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.cc (renamed from chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_util.cc)75
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h (renamed from chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_util.h)34
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_util_unittest.cc (renamed from chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_util_unittest.cc)2
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_usage_store.cc1
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/db_data_owner.cc1
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/network_properties_manager.cc67
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/network_properties_manager.h5
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/network_properties_manager_unittest.cc71
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc2
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc8
-rw-r--r--chromium/components/data_reduction_proxy/core/common/BUILD.gn3
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_event_creator.cc2
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc12
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h2
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_headers_unittest.cc2
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc2
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc2
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_server.h2
-rw-r--r--chromium/components/data_use_measurement/core/data_use_ascriber.cc4
-rw-r--r--chromium/components/data_use_measurement/core/data_use_measurement.cc16
-rw-r--r--chromium/components/data_use_measurement/core/data_use_measurement.h5
-rw-r--r--chromium/components/data_use_measurement/core/data_use_measurement_unittest.cc7
-rw-r--r--chromium/components/data_use_measurement/core/data_use_network_delegate_unittest.cc28
-rw-r--r--chromium/components/data_use_measurement/core/data_use_user_data.cc5
-rw-r--r--chromium/components/discardable_memory/client/client_discardable_shared_memory_manager.cc23
-rw-r--r--chromium/components/discardable_memory/common/discardable_shared_memory_heap.cc3
-rw-r--r--chromium/components/discardable_memory/common/discardable_shared_memory_heap_perftest.cc8
-rw-r--r--chromium/components/dom_distiller/content/browser/distillability_driver.cc5
-rw-r--r--chromium/components/dom_distiller/content/browser/distillable_page_utils.cc53
-rw-r--r--chromium/components/dom_distiller/content/browser/distillable_page_utils.h10
-rw-r--r--chromium/components/dom_distiller/content/browser/distillable_page_utils_android.cc27
-rw-r--r--chromium/components/dom_distiller/content/browser/distillable_page_utils_browsertest.cc20
-rw-r--r--chromium/components/dom_distiller/content/browser/distiller_javascript_service_impl.cc4
-rw-r--r--chromium/components/dom_distiller/content/browser/distiller_page_web_contents.cc3
-rw-r--r--chromium/components/dom_distiller/content/browser/web_contents_main_frame_observer_unittest.cc12
-rw-r--r--chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.cc4
-rw-r--r--chromium/components/dom_distiller/content/renderer/distiller_native_javascript.cc6
-rw-r--r--chromium/components/dom_distiller/content/renderer/distiller_native_javascript.h5
-rw-r--r--chromium/components/dom_distiller/core/BUILD.gn2
-rw-r--r--chromium/components/dom_distiller/core/article_attachments_data.cc53
-rw-r--r--chromium/components/dom_distiller/core/article_attachments_data.h53
-rw-r--r--chromium/components/dom_distiller/core/article_entry.cc4
-rw-r--r--chromium/components/dom_distiller/core/data/distillable_page_model.binbin2204 -> 0 bytes
-rw-r--r--chromium/components/dom_distiller/core/distillable_page_detector.cc14
-rw-r--r--chromium/components/dom_distiller/core/distillable_page_detector.h1
-rw-r--r--chromium/components/dom_distiller/core/distillable_page_detector_unittest.cc4
-rw-r--r--chromium/components/dom_distiller/core/distilled_content_store.cc4
-rw-r--r--chromium/components/dom_distiller/core/distiller.cc3
-rw-r--r--chromium/components/dom_distiller/core/distiller_page.cc6
-rw-r--r--chromium/components/dom_distiller/core/distiller_unittest.cc5
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_service.cc4
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_store.cc135
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_store.h47
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_store_unittest.cc63
-rw-r--r--chromium/components/dom_distiller/core/fake_distiller.cc4
-rw-r--r--chromium/components/dom_distiller/core/javascript/is_distillable_trigger.js21
-rw-r--r--chromium/components/dom_distiller/core/url_utils.cc5
-rw-r--r--chromium/components/dom_distiller/core/url_utils.h4
-rw-r--r--chromium/components/dom_distiller/core/url_utils_android.cc15
-rw-r--r--chromium/components/dom_distiller/ios/distiller_page_factory_ios.mm7
-rw-r--r--chromium/components/dom_distiller/webui/dom_distiller_ui.cc5
-rw-r--r--chromium/components/domain_reliability/beacon.cc6
-rw-r--r--chromium/components/domain_reliability/config_unittest.cc9
-rw-r--r--chromium/components/domain_reliability/dispatcher.cc4
-rw-r--r--chromium/components/domain_reliability/google_configs.cc38
-rw-r--r--chromium/components/domain_reliability/header.cc4
-rw-r--r--chromium/components/domain_reliability/monitor.cc4
-rw-r--r--chromium/components/domain_reliability/quic_error_mapping.cc7
-rw-r--r--chromium/components/domain_reliability/scheduler.cc4
-rw-r--r--chromium/components/domain_reliability/service.cc10
-rw-r--r--chromium/components/domain_reliability/service_unittest.cc2
-rw-r--r--chromium/components/domain_reliability/test_util.cc5
-rw-r--r--chromium/components/domain_reliability/util.cc1
-rw-r--r--chromium/components/download/BUILD.gn4
-rw-r--r--chromium/components/download/components_unittests.filter1
-rw-r--r--chromium/components/download/content/factory/BUILD.gn6
-rw-r--r--chromium/components/download/content/factory/download_service_factory.cc116
-rw-r--r--chromium/components/download/content/factory/download_service_factory.h23
-rw-r--r--chromium/components/download/content/factory/navigation_monitor_factory.cc2
-rw-r--r--chromium/components/download/content/internal/BUILD.gn5
-rw-r--r--chromium/components/download/content/internal/download_driver_impl.cc86
-rw-r--r--chromium/components/download/content/internal/download_driver_impl.h12
-rw-r--r--chromium/components/download/content/internal/download_driver_impl_unittest.cc24
-rw-r--r--chromium/components/download/content/public/BUILD.gn2
-rw-r--r--chromium/components/download/content/public/all_download_item_notifier.cc12
-rw-r--r--chromium/components/download/content/public/all_download_item_notifier.h24
-rw-r--r--chromium/components/download/content/public/all_download_item_notifier_unittest.cc14
-rw-r--r--chromium/components/download/content/public/download_navigation_observer.h2
-rw-r--r--chromium/components/download/downloader/in_progress/BUILD.gn2
-rw-r--r--chromium/components/download/downloader/in_progress/DEPS1
-rw-r--r--chromium/components/download/downloader/in_progress/download_entry.h2
-rw-r--r--chromium/components/download/downloader/in_progress/download_source.h30
-rw-r--r--chromium/components/download/downloader/in_progress/proto/download_source.proto2
-rw-r--r--chromium/components/download/internal/background_service/BUILD.gn (renamed from chromium/components/download/internal/BUILD.gn)23
-rw-r--r--chromium/components/download/internal/background_service/DEPS (renamed from chromium/components/download/internal/DEPS)0
-rw-r--r--chromium/components/download/internal/background_service/android/battery_status_listener_android.cc (renamed from chromium/components/download/internal/android/battery_status_listener_android.cc)2
-rw-r--r--chromium/components/download/internal/background_service/android/battery_status_listener_android.h (renamed from chromium/components/download/internal/android/battery_status_listener_android.h)8
-rw-r--r--chromium/components/download/internal/background_service/android/network_status_listener_android.cc (renamed from chromium/components/download/internal/android/network_status_listener_android.cc)2
-rw-r--r--chromium/components/download/internal/background_service/android/network_status_listener_android.h (renamed from chromium/components/download/internal/android/network_status_listener_android.h)8
-rw-r--r--chromium/components/download/internal/background_service/blob_task_proxy.cc (renamed from chromium/components/download/internal/blob_task_proxy.cc)35
-rw-r--r--chromium/components/download/internal/background_service/blob_task_proxy.h (renamed from chromium/components/download/internal/blob_task_proxy.h)8
-rw-r--r--chromium/components/download/internal/background_service/client_set.cc (renamed from chromium/components/download/internal/client_set.cc)4
-rw-r--r--chromium/components/download/internal/background_service/client_set.h (renamed from chromium/components/download/internal/client_set.h)8
-rw-r--r--chromium/components/download/internal/background_service/client_set_unittest.cc (renamed from chromium/components/download/internal/client_set_unittest.cc)6
-rw-r--r--chromium/components/download/internal/background_service/config.cc (renamed from chromium/components/download/internal/config.cc)4
-rw-r--r--chromium/components/download/internal/background_service/config.h (renamed from chromium/components/download/internal/config.h)6
-rw-r--r--chromium/components/download/internal/background_service/controller.h (renamed from chromium/components/download/internal/controller.h)12
-rw-r--r--chromium/components/download/internal/background_service/controller_impl.cc (renamed from chromium/components/download/internal/controller_impl.cc)33
-rw-r--r--chromium/components/download/internal/background_service/controller_impl.h (renamed from chromium/components/download/internal/controller_impl.h)30
-rw-r--r--chromium/components/download/internal/background_service/controller_impl_unittest.cc (renamed from chromium/components/download/internal/controller_impl_unittest.cc)34
-rw-r--r--chromium/components/download/internal/background_service/debugging_client.cc (renamed from chromium/components/download/internal/debugging_client.cc)2
-rw-r--r--chromium/components/download/internal/background_service/debugging_client.h (renamed from chromium/components/download/internal/debugging_client.h)8
-rw-r--r--chromium/components/download/internal/background_service/download_driver.h (renamed from chromium/components/download/internal/download_driver.h)10
-rw-r--r--chromium/components/download/internal/background_service/download_service_impl.cc (renamed from chromium/components/download/internal/download_service_impl.cc)10
-rw-r--r--chromium/components/download/internal/background_service/download_service_impl.h (renamed from chromium/components/download/internal/download_service_impl.h)12
-rw-r--r--chromium/components/download/internal/background_service/download_service_impl_unittest.cc (renamed from chromium/components/download/internal/download_service_impl_unittest.cc)12
-rw-r--r--chromium/components/download/internal/background_service/download_store.cc (renamed from chromium/components/download/internal/download_store.cc)8
-rw-r--r--chromium/components/download/internal/background_service/download_store.h (renamed from chromium/components/download/internal/download_store.h)8
-rw-r--r--chromium/components/download/internal/background_service/download_store_unittest.cc (renamed from chromium/components/download/internal/download_store_unittest.cc)10
-rw-r--r--chromium/components/download/internal/background_service/driver_entry.cc (renamed from chromium/components/download/internal/driver_entry.cc)2
-rw-r--r--chromium/components/download/internal/background_service/driver_entry.h (renamed from chromium/components/download/internal/driver_entry.h)12
-rw-r--r--chromium/components/download/internal/background_service/empty_file_monitor.cc40
-rw-r--r--chromium/components/download/internal/background_service/empty_file_monitor.h42
-rw-r--r--chromium/components/download/internal/background_service/empty_task_scheduler.cc22
-rw-r--r--chromium/components/download/internal/background_service/empty_task_scheduler.h35
-rw-r--r--chromium/components/download/internal/background_service/entry.cc (renamed from chromium/components/download/internal/entry.cc)2
-rw-r--r--chromium/components/download/internal/background_service/entry.h (renamed from chromium/components/download/internal/entry.h)12
-rw-r--r--chromium/components/download/internal/background_service/entry_utils.cc (renamed from chromium/components/download/internal/entry_utils.cc)6
-rw-r--r--chromium/components/download/internal/background_service/entry_utils.h (renamed from chromium/components/download/internal/entry_utils.h)14
-rw-r--r--chromium/components/download/internal/background_service/entry_utils_unittest.cc (renamed from chromium/components/download/internal/entry_utils_unittest.cc)8
-rw-r--r--chromium/components/download/internal/background_service/file_monitor.h (renamed from chromium/components/download/internal/file_monitor.h)10
-rw-r--r--chromium/components/download/internal/background_service/file_monitor_impl.cc (renamed from chromium/components/download/internal/file_monitor_impl.cc)2
-rw-r--r--chromium/components/download/internal/background_service/file_monitor_impl.h (renamed from chromium/components/download/internal/file_monitor_impl.h)14
-rw-r--r--chromium/components/download/internal/background_service/file_monitor_unittest.cc (renamed from chromium/components/download/internal/file_monitor_unittest.cc)8
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download.cc312
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download.h (renamed from chromium/components/download/internal/in_memory_download.h)170
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_driver.cc177
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_driver.h88
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_driver_unittest.cc193
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_unittest.cc231
-rw-r--r--chromium/components/download/internal/background_service/log_sink.h (renamed from chromium/components/download/internal/log_sink.h)12
-rw-r--r--chromium/components/download/internal/background_service/log_source.h (renamed from chromium/components/download/internal/log_source.h)8
-rw-r--r--chromium/components/download/internal/background_service/logger_impl.cc (renamed from chromium/components/download/internal/logger_impl.cc)12
-rw-r--r--chromium/components/download/internal/background_service/logger_impl.h (renamed from chromium/components/download/internal/logger_impl.h)12
-rw-r--r--chromium/components/download/internal/background_service/memory_tracker.h (renamed from chromium/components/download/internal/memory_tracker.h)6
-rw-r--r--chromium/components/download/internal/background_service/model.h (renamed from chromium/components/download/internal/model.h)12
-rw-r--r--chromium/components/download/internal/background_service/model_impl.cc (renamed from chromium/components/download/internal/model_impl.cc)6
-rw-r--r--chromium/components/download/internal/background_service/model_impl.h (renamed from chromium/components/download/internal/model_impl.h)12
-rw-r--r--chromium/components/download/internal/background_service/model_impl_unittest.cc (renamed from chromium/components/download/internal/model_impl_unittest.cc)12
-rw-r--r--chromium/components/download/internal/background_service/navigation_monitor_impl.cc (renamed from chromium/components/download/internal/navigation_monitor_impl.cc)2
-rw-r--r--chromium/components/download/internal/background_service/navigation_monitor_impl.h (renamed from chromium/components/download/internal/navigation_monitor_impl.h)8
-rw-r--r--chromium/components/download/internal/background_service/navigation_monitor_impl_unittests.cc (renamed from chromium/components/download/internal/navigation_monitor_impl_unittests.cc)2
-rw-r--r--chromium/components/download/internal/background_service/noop_store.cc56
-rw-r--r--chromium/components/download/internal/background_service/noop_store.h44
-rw-r--r--chromium/components/download/internal/background_service/proto/BUILD.gn (renamed from chromium/components/download/internal/proto/BUILD.gn)2
-rw-r--r--chromium/components/download/internal/background_service/proto/entry.proto (renamed from chromium/components/download/internal/proto/entry.proto)4
-rw-r--r--chromium/components/download/internal/background_service/proto/request.proto (renamed from chromium/components/download/internal/proto/request.proto)0
-rw-r--r--chromium/components/download/internal/background_service/proto/scheduling.proto (renamed from chromium/components/download/internal/proto/scheduling.proto)6
-rw-r--r--chromium/components/download/internal/background_service/proto_conversions.cc (renamed from chromium/components/download/internal/proto_conversions.cc)2
-rw-r--r--chromium/components/download/internal/background_service/proto_conversions.h (renamed from chromium/components/download/internal/proto_conversions.h)14
-rw-r--r--chromium/components/download/internal/background_service/proto_conversions_unittest.cc (renamed from chromium/components/download/internal/proto_conversions_unittest.cc)6
-rw-r--r--chromium/components/download/internal/background_service/scheduler/device_status.cc (renamed from chromium/components/download/internal/scheduler/device_status.cc)2
-rw-r--r--chromium/components/download/internal/background_service/scheduler/device_status.h (renamed from chromium/components/download/internal/scheduler/device_status.h)8
-rw-r--r--chromium/components/download/internal/background_service/scheduler/device_status_listener.cc (renamed from chromium/components/download/internal/scheduler/device_status_listener.cc)6
-rw-r--r--chromium/components/download/internal/background_service/scheduler/device_status_listener.h (renamed from chromium/components/download/internal/scheduler/device_status_listener.h)10
-rw-r--r--chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc (renamed from chromium/components/download/internal/scheduler/device_status_listener_unittest.cc)4
-rw-r--r--chromium/components/download/internal/background_service/scheduler/network_status_listener.cc (renamed from chromium/components/download/internal/scheduler/network_status_listener.cc)2
-rw-r--r--chromium/components/download/internal/background_service/scheduler/network_status_listener.h (renamed from chromium/components/download/internal/scheduler/network_status_listener.h)6
-rw-r--r--chromium/components/download/internal/background_service/scheduler/scheduler.h (renamed from chromium/components/download/internal/scheduler/scheduler.h)12
-rw-r--r--chromium/components/download/internal/background_service/scheduler/scheduler_impl.cc (renamed from chromium/components/download/internal/scheduler/scheduler_impl.cc)16
-rw-r--r--chromium/components/download/internal/background_service/scheduler/scheduler_impl.h (renamed from chromium/components/download/internal/scheduler/scheduler_impl.h)10
-rw-r--r--chromium/components/download/internal/background_service/scheduler/scheduler_impl_unittest.cc (renamed from chromium/components/download/internal/scheduler/scheduler_impl_unittest.cc)10
-rw-r--r--chromium/components/download/internal/background_service/service_config_impl.cc (renamed from chromium/components/download/internal/service_config_impl.cc)4
-rw-r--r--chromium/components/download/internal/background_service/service_config_impl.h (renamed from chromium/components/download/internal/service_config_impl.h)8
-rw-r--r--chromium/components/download/internal/background_service/service_config_impl_unittest.cc (renamed from chromium/components/download/internal/service_config_impl_unittest.cc)4
-rw-r--r--chromium/components/download/internal/background_service/startup_status.cc (renamed from chromium/components/download/internal/startup_status.cc)2
-rw-r--r--chromium/components/download/internal/background_service/startup_status.h (renamed from chromium/components/download/internal/startup_status.h)6
-rw-r--r--chromium/components/download/internal/background_service/stats.cc (renamed from chromium/components/download/internal/stats.cc)7
-rw-r--r--chromium/components/download/internal/background_service/stats.h (renamed from chromium/components/download/internal/stats.h)21
-rw-r--r--chromium/components/download/internal/background_service/store.h (renamed from chromium/components/download/internal/store.h)6
-rw-r--r--chromium/components/download/internal/background_service/test/BUILD.gn (renamed from chromium/components/download/internal/test/BUILD.gn)13
-rw-r--r--chromium/components/download/internal/common/BUILD.gn46
-rw-r--r--chromium/components/download/internal/common/DEPS9
-rw-r--r--chromium/components/download/internal/common/download_create_info.cc44
-rw-r--r--chromium/components/download/internal/common/download_interrupt_reasons_impl.cc28
-rw-r--r--chromium/components/download/internal/common/download_stats.cc1065
-rw-r--r--chromium/components/download/internal/common/download_stats_unittest.cc39
-rw-r--r--chromium/components/download/internal/common/download_task_runner.cc33
-rw-r--r--chromium/components/download/internal/common/download_ukm_helper.cc86
-rw-r--r--chromium/components/download/internal/common/download_ukm_helper_unittest.cc121
-rw-r--r--chromium/components/download/internal/common/download_utils.cc11
-rw-r--r--chromium/components/download/internal/common/rate_estimator.cc121
-rw-r--r--chromium/components/download/internal/common/rate_estimator_unittest.cc58
-rw-r--r--chromium/components/download/internal/in_memory_download.cc162
-rw-r--r--chromium/components/download/internal/in_memory_download_unittest.cc127
-rw-r--r--chromium/components/download/public/background_service/BUILD.gn (renamed from chromium/components/download/public/BUILD.gn)0
-rw-r--r--chromium/components/download/public/background_service/DEPS (renamed from chromium/components/download/public/DEPS)0
-rw-r--r--chromium/components/download/public/background_service/client.h (renamed from chromium/components/download/public/client.h)6
-rw-r--r--chromium/components/download/public/background_service/clients.h (renamed from chromium/components/download/public/clients.h)8
-rw-r--r--chromium/components/download/public/background_service/download_metadata.cc (renamed from chromium/components/download/public/download_metadata.cc)2
-rw-r--r--chromium/components/download/public/background_service/download_metadata.h (renamed from chromium/components/download/public/download_metadata.h)6
-rw-r--r--chromium/components/download/public/background_service/download_params.cc (renamed from chromium/components/download/public/download_params.cc)4
-rw-r--r--chromium/components/download/public/background_service/download_params.h (renamed from chromium/components/download/public/download_params.h)8
-rw-r--r--chromium/components/download/public/background_service/download_service.h (renamed from chromium/components/download/public/download_service.h)10
-rw-r--r--chromium/components/download/public/background_service/download_task_types.h (renamed from chromium/components/download/public/download_task_types.h)6
-rw-r--r--chromium/components/download/public/background_service/features.cc (renamed from chromium/components/download/public/features.cc)5
-rw-r--r--chromium/components/download/public/background_service/features.h20
-rw-r--r--chromium/components/download/public/background_service/logger.h (renamed from chromium/components/download/public/logger.h)6
-rw-r--r--chromium/components/download/public/background_service/navigation_monitor.h (renamed from chromium/components/download/public/navigation_monitor.h)6
-rw-r--r--chromium/components/download/public/background_service/service_config.h (renamed from chromium/components/download/public/service_config.h)6
-rw-r--r--chromium/components/download/public/background_service/task_scheduler.h (renamed from chromium/components/download/public/task_scheduler.h)8
-rw-r--r--chromium/components/download/public/background_service/test/BUILD.gn (renamed from chromium/components/download/public/test/BUILD.gn)2
-rw-r--r--chromium/components/download/public/common/BUILD.gn87
-rw-r--r--chromium/components/download/public/common/DEPS12
-rw-r--r--chromium/components/download/public/common/OWNERS2
-rw-r--r--chromium/components/download/public/common/download_content.h38
-rw-r--r--chromium/components/download/public/common/download_create_info.h170
-rw-r--r--chromium/components/download/public/common/download_danger_type.h54
-rw-r--r--chromium/components/download/public/common/download_export.h29
-rw-r--r--chromium/components/download/public/common/download_interrupt_reason_values.h139
-rw-r--r--chromium/components/download/public/common/download_interrupt_reasons.h29
-rw-r--r--chromium/components/download/public/common/download_item.h464
-rw-r--r--chromium/components/download/public/common/download_request_handle_interface.h29
-rw-r--r--chromium/components/download/public/common/download_save_info.cc27
-rw-r--r--chromium/components/download/public/common/download_save_info.h78
-rw-r--r--chromium/components/download/public/common/download_source.h48
-rw-r--r--chromium/components/download/public/common/download_stats.h378
-rw-r--r--chromium/components/download/public/common/download_stream.mojom28
-rw-r--r--chromium/components/download/public/common/download_task_runner.h19
-rw-r--r--chromium/components/download/public/common/download_ukm_helper.h64
-rw-r--r--chromium/components/download/public/common/download_url_parameters.cc48
-rw-r--r--chromium/components/download/public/common/download_url_parameters.h331
-rw-r--r--chromium/components/download/public/common/rate_estimator.h54
-rw-r--r--chromium/components/download/public/common/resume_mode.h22
-rw-r--r--chromium/components/download/public/features.h16
-rw-r--r--chromium/components/download/quarantine/BUILD.gn59
-rw-r--r--chromium/components/download/quarantine/DEPS3
-rw-r--r--chromium/components/download/quarantine/quarantine.cc28
-rw-r--r--chromium/components/download/quarantine/quarantine.h103
-rw-r--r--chromium/components/download/quarantine/quarantine_constants_linux.h21
-rw-r--r--chromium/components/download/quarantine/quarantine_linux.cc100
-rw-r--r--chromium/components/download/quarantine/quarantine_linux_unittest.cc183
-rw-r--r--chromium/components/download/quarantine/quarantine_mac.mm342
-rw-r--r--chromium/components/download/quarantine/quarantine_mac_unittest.mm122
-rw-r--r--chromium/components/download/quarantine/quarantine_unittest.cc58
-rw-r--r--chromium/components/download/quarantine/quarantine_win.cc352
-rw-r--r--chromium/components/download/quarantine/quarantine_win_unittest.cc263
-rw-r--r--chromium/components/drive/BUILD.gn2
-rw-r--r--chromium/components/error_page/common/localized_error.cc19
-rw-r--r--chromium/components/exo/buffer.cc3
-rw-r--r--chromium/components/exo/client_controlled_shell_surface.cc121
-rw-r--r--chromium/components/exo/client_controlled_shell_surface.h23
-rw-r--r--chromium/components/exo/client_controlled_shell_surface_unittest.cc122
-rw-r--r--chromium/components/exo/data_device_unittest.cc9
-rw-r--r--chromium/components/exo/data_offer.cc140
-rw-r--r--chromium/components/exo/data_offer.h14
-rw-r--r--chromium/components/exo/data_offer_unittest.cc152
-rw-r--r--chromium/components/exo/display_unittest.cc9
-rw-r--r--chromium/components/exo/file_helper.h18
-rw-r--r--chromium/components/exo/keyboard.cc43
-rw-r--r--chromium/components/exo/keyboard.h7
-rw-r--r--chromium/components/exo/keyboard_unittest.cc3
-rw-r--r--chromium/components/exo/pointer.cc4
-rw-r--r--chromium/components/exo/pointer.h2
-rw-r--r--chromium/components/exo/shell_surface.cc4
-rw-r--r--chromium/components/exo/shell_surface_base.cc9
-rw-r--r--chromium/components/exo/shell_surface_unittest.cc3
-rw-r--r--chromium/components/exo/surface.cc1
-rw-r--r--chromium/components/exo/touch.h2
-rw-r--r--chromium/components/exo/wayland/BUILD.gn3
-rw-r--r--chromium/components/exo/wayland/clients/client_base.cc12
-rw-r--r--chromium/components/exo/wayland/clients/client_base.h1
-rw-r--r--chromium/components/exo/wayland/clients/client_helper.cc4
-rw-r--r--chromium/components/exo/wayland/clients/client_helper.h3
-rw-r--r--chromium/components/exo/wayland/clients/rects.cc78
-rw-r--r--chromium/components/exo/wayland/server.cc281
-rw-r--r--chromium/components/favicon/core/favicon_driver_impl.cc9
-rw-r--r--chromium/components/favicon/core/favicon_handler.cc4
-rw-r--r--chromium/components/favicon/core/favicon_handler_unittest.cc18
-rw-r--r--chromium/components/favicon/core/favicon_service.h14
-rw-r--r--chromium/components/favicon/core/favicon_service_impl.cc15
-rw-r--r--chromium/components/favicon/core/favicon_service_impl.h6
-rw-r--r--chromium/components/favicon/core/large_icon_service.cc4
-rw-r--r--chromium/components/favicon/core/large_icon_service_unittest.cc10
-rw-r--r--chromium/components/favicon/ios/web_favicon_driver.mm1
-rw-r--r--chromium/components/favicon_base/select_favicon_frames.cc4
-rw-r--r--chromium/components/feature_engagement/BUILD.gn6
-rw-r--r--chromium/components/feature_engagement/internal/in_memory_event_store.cc3
-rw-r--r--chromium/components/feature_engagement/internal/tracker_impl_unittest.cc7
-rw-r--r--chromium/components/feature_engagement/public/BUILD.gn2
-rw-r--r--chromium/components/feature_engagement/public/event_constants.cc2
-rw-r--r--chromium/components/feature_engagement/public/event_constants.h2
-rw-r--r--chromium/components/feature_engagement/public/feature_constants.cc2
-rw-r--r--chromium/components/feature_engagement/public/feature_constants.h2
-rw-r--r--chromium/components/feature_engagement/public/feature_list.cc2
-rw-r--r--chromium/components/feature_engagement/public/feature_list.h2
-rw-r--r--chromium/components/feedback/anonymizer_tool.cc4
-rw-r--r--chromium/components/feedback/feedback_data.cc14
-rw-r--r--chromium/components/feedback/feedback_data_unittest.cc3
-rw-r--r--chromium/components/feedback/feedback_report.cc1
-rw-r--r--chromium/components/feedback/feedback_uploader_unittest.cc5
-rw-r--r--chromium/components/feedback/system_logs/system_logs_fetcher.cc6
-rw-r--r--chromium/components/feedback/system_logs/system_logs_fetcher.h4
-rw-r--r--chromium/components/filename_generation/BUILD.gn37
-rw-r--r--chromium/components/filename_generation/DEPS4
-rw-r--r--chromium/components/filename_generation/OWNERS6
-rw-r--r--chromium/components/filename_generation/filename_generation.cc187
-rw-r--r--chromium/components/filename_generation/filename_generation.h48
-rw-r--r--chromium/components/filename_generation/filename_generation_unittest.cc229
-rw-r--r--chromium/components/filesystem/BUILD.gn2
-rw-r--r--chromium/components/filesystem/directory_impl.cc8
-rw-r--r--chromium/components/filesystem/file_impl.cc4
-rw-r--r--chromium/components/filesystem/file_system_app.cc3
-rw-r--r--chromium/components/filesystem/file_system_impl.cc4
-rw-r--r--chromium/components/filesystem/public/interfaces/types.mojom2
-rw-r--r--chromium/components/flags_ui/feature_entry.h8
-rw-r--r--chromium/components/flags_ui/flags_state.cc7
-rw-r--r--chromium/components/font_service/public/cpp/BUILD.gn2
-rw-r--r--chromium/components/gcm_driver/BUILD.gn9
-rw-r--r--chromium/components/gcm_driver/android/BUILD.gn1
-rw-r--r--chromium/components/gcm_driver/crypto/BUILD.gn2
-rw-r--r--chromium/components/gcm_driver/crypto/proto/BUILD.gn5
-rw-r--r--chromium/components/gcm_driver/instance_id/BUILD.gn2
-rw-r--r--chromium/components/grpc_support/bidirectional_stream.cc44
-rw-r--r--chromium/components/grpc_support/bidirectional_stream.h4
-rw-r--r--chromium/components/grpc_support/bidirectional_stream_c.cc12
-rw-r--r--chromium/components/grpc_support/bidirectional_stream_unittest.cc25
-rw-r--r--chromium/components/guest_view/browser/guest_view_base.cc14
-rw-r--r--chromium/components/guest_view/browser/guest_view_base.h3
-rw-r--r--chromium/components/guest_view/browser/guest_view_message_filter.cc5
-rw-r--r--chromium/components/guest_view/browser/test_guest_view_manager.cc4
-rw-r--r--chromium/components/history/content/browser/BUILD.gn1
-rw-r--r--chromium/components/history/content/browser/DEPS1
-rw-r--r--chromium/components/history/content/browser/content_history_backend_db_unittest.cc2
-rw-r--r--chromium/components/history/content/browser/content_visit_delegate.cc2
-rw-r--r--chromium/components/history/content/browser/download_conversions.cc96
-rw-r--r--chromium/components/history/content/browser/download_conversions.h32
-rw-r--r--chromium/components/history/content/browser/download_conversions_unittest.cc10
-rw-r--r--chromium/components/history/content/browser/history_database_helper.cc13
-rw-r--r--chromium/components/history/core/browser/BUILD.gn6
-rw-r--r--chromium/components/history/core/browser/OWNERS7
-rw-r--r--chromium/components/history/core/browser/browsing_history_service_unittest.cc5
-rw-r--r--chromium/components/history/core/browser/delete_directive_handler.cc2
-rw-r--r--chromium/components/history/core/browser/download_database.cc215
-rw-r--r--chromium/components/history/core/browser/download_database.h9
-rw-r--r--chromium/components/history/core/browser/download_slice_info.cc11
-rw-r--r--chromium/components/history/core/browser/download_slice_info.h6
-rw-r--r--chromium/components/history/core/browser/download_slice_info_unittest.cc7
-rw-r--r--chromium/components/history/core/browser/expire_history_backend.cc38
-rw-r--r--chromium/components/history/core/browser/expire_history_backend.h7
-rw-r--r--chromium/components/history/core/browser/expire_history_backend_unittest.cc26
-rw-r--r--chromium/components/history/core/browser/history_backend.cc128
-rw-r--r--chromium/components/history/core/browser/history_backend.h18
-rw-r--r--chromium/components/history/core/browser/history_backend_db_unittest.cc58
-rw-r--r--chromium/components/history/core/browser/history_backend_notifier.h14
-rw-r--r--chromium/components/history/core/browser/history_backend_unittest.cc28
-rw-r--r--chromium/components/history/core/browser/history_database.cc9
-rw-r--r--chromium/components/history/core/browser/history_model_worker.cc11
-rw-r--r--chromium/components/history/core/browser/history_model_worker_unittest.cc16
-rw-r--r--chromium/components/history/core/browser/history_service.cc77
-rw-r--r--chromium/components/history/core/browser/history_service.h23
-rw-r--r--chromium/components/history/core/browser/history_service_observer.h17
-rw-r--r--chromium/components/history/core/browser/history_service_unittest.cc36
-rw-r--r--chromium/components/history/core/browser/history_types.cc18
-rw-r--r--chromium/components/history/core/browser/history_types.h39
-rw-r--r--chromium/components/history/core/browser/history_types_unittest.cc20
-rw-r--r--chromium/components/history/core/browser/thumbnail_database.cc61
-rw-r--r--chromium/components/history/core/browser/thumbnail_database.h5
-rw-r--r--chromium/components/history/core/browser/thumbnail_database_unittest.cc69
-rw-r--r--chromium/components/history/core/browser/top_sites_backend.cc4
-rw-r--r--chromium/components/history/core/browser/top_sites_database_unittest.cc12
-rw-r--r--chromium/components/history/core/browser/top_sites_impl.cc8
-rw-r--r--chromium/components/history/core/browser/typed_url_data_type_controller.cc112
-rw-r--r--chromium/components/history/core/browser/typed_url_data_type_controller.h55
-rw-r--r--chromium/components/history/core/browser/typed_url_model_type_controller.cc6
-rw-r--r--chromium/components/history/core/browser/typed_url_sync_bridge.cc37
-rw-r--r--chromium/components/history/core/browser/typed_url_sync_bridge_unittest.cc6
-rw-r--r--chromium/components/history/core/browser/typed_url_syncable_service.cc1105
-rw-r--r--chromium/components/history/core/browser/typed_url_syncable_service.h249
-rw-r--r--chromium/components/history/core/browser/typed_url_syncable_service_unittest.cc1616
-rw-r--r--chromium/components/history/core/browser/url_database.cc5
-rw-r--r--chromium/components/history/core/browser/url_database_unittest.cc5
-rw-r--r--chromium/components/history/core/browser/url_row.cc8
-rw-r--r--chromium/components/history/core/browser/url_row.h5
-rw-r--r--chromium/components/history/core/browser/visitsegment_database.cc22
-rw-r--r--chromium/components/history/core/browser/visitsegment_database.h11
-rw-r--r--chromium/components/history/ios/browser/history_database_helper.cc3
-rw-r--r--chromium/components/image_fetcher/core/image_data_fetcher.cc4
-rw-r--r--chromium/components/image_fetcher/core/image_data_fetcher.h5
-rw-r--r--chromium/components/image_fetcher/core/image_data_fetcher_unittest.cc36
-rw-r--r--chromium/components/image_fetcher/core/image_fetcher_impl.cc3
-rw-r--r--chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm8
-rw-r--r--chromium/components/image_fetcher/ios/ios_image_decoder_impl.mm5
-rw-r--r--chromium/components/infobars/core/infobar.cc11
-rw-r--r--chromium/components/infobars/core/infobar.h2
-rw-r--r--chromium/components/infobars/core/infobar_delegate.cc10
-rw-r--r--chromium/components/infobars/core/infobar_delegate.h5
-rw-r--r--chromium/components/invalidation/impl/BUILD.gn1
-rw-r--r--chromium/components/json_schema/json_schema_validator.cc3
-rw-r--r--chromium/components/json_schema/json_schema_validator_unittest_base.cc31
-rw-r--r--chromium/components/language/content/browser/BUILD.gn4
-rw-r--r--chromium/components/language/content/browser/DEPS3
-rw-r--r--chromium/components/language/content/browser/geo_language_provider.cc4
-rw-r--r--chromium/components/language/content/browser/geo_language_provider.h2
-rw-r--r--chromium/components/language/content/browser/geo_language_provider_unittest.cc10
-rw-r--r--chromium/components/language/core/common/BUILD.gn28
-rw-r--r--chromium/components/language/core/common/DEPS3
-rw-r--r--chromium/components/language/core/common/locale_util.cc117
-rw-r--r--chromium/components/language/core/common/locale_util.h36
-rw-r--r--chromium/components/language/core/common/locale_util_unittest.cc264
-rw-r--r--chromium/components/leveldb/leveldb_service_impl.cc5
-rw-r--r--chromium/components/leveldb_proto/proto_database_impl.h32
-rw-r--r--chromium/components/leveldb_proto/proto_database_impl_unittest.cc17
-rw-r--r--chromium/components/leveldb_proto/testing/fake_db.h10
-rw-r--r--chromium/components/login/screens/screen_context.cc3
-rw-r--r--chromium/components/login_dialog_strings.grdp15
-rw-r--r--chromium/components/metrics/BUILD.gn8
-rw-r--r--chromium/components/metrics/OWNERS2
-rw-r--r--chromium/components/metrics/call_stack_profile_collector.cc5
-rw-r--r--chromium/components/metrics/call_stack_profile_metrics_provider.cc58
-rw-r--r--chromium/components/metrics/call_stack_profile_metrics_provider.h18
-rw-r--r--chromium/components/metrics/call_stack_profile_params.h9
-rw-r--r--chromium/components/metrics/child_call_stack_profile_collector.cc10
-rw-r--r--chromium/components/metrics/clean_exit_beacon.cc11
-rw-r--r--chromium/components/metrics/clean_exit_beacon.h16
-rw-r--r--chromium/components/metrics/component_metrics_provider.cc40
-rw-r--r--chromium/components/metrics/drive_metrics_provider_linux.cc17
-rw-r--r--chromium/components/metrics/file_metrics_provider.cc66
-rw-r--r--chromium/components/metrics/metrics_log.cc13
-rw-r--r--chromium/components/metrics/metrics_pref_names.cc13
-rw-r--r--chromium/components/metrics/metrics_pref_names.h8
-rw-r--r--chromium/components/metrics/metrics_service.cc29
-rw-r--r--chromium/components/metrics/metrics_service.h6
-rw-r--r--chromium/components/metrics/metrics_service_accessor.cc36
-rw-r--r--chromium/components/metrics/metrics_service_accessor.h7
-rw-r--r--chromium/components/metrics/metrics_service_client.cc4
-rw-r--r--chromium/components/metrics/metrics_service_client.h3
-rw-r--r--chromium/components/metrics/metrics_service_unittest.cc47
-rw-r--r--chromium/components/metrics/metrics_state_manager.cc21
-rw-r--r--chromium/components/metrics/metrics_upload_scheduler.cc19
-rw-r--r--chromium/components/metrics/metrics_upload_scheduler.h2
-rw-r--r--chromium/components/metrics/net/network_metrics_provider_unittest.cc6
-rw-r--r--chromium/components/metrics/persistent_system_profile_unittest.cc21
-rw-r--r--chromium/components/metrics/public/cpp/call_stack_profile_struct_traits.h26
-rw-r--r--chromium/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc15
-rw-r--r--chromium/components/metrics/public/interfaces/call_stack_profile_collector.mojom6
-rw-r--r--chromium/components/metrics/single_sample_metrics.cc8
-rw-r--r--chromium/components/metrics/single_sample_metrics_factory_impl.cc4
-rw-r--r--chromium/components/metrics/stability_metrics_provider.cc76
-rw-r--r--chromium/components/metrics/stability_metrics_provider.h13
-rw-r--r--chromium/components/metrics/stability_metrics_provider_unittest.cc58
-rw-r--r--chromium/components/metrics/system_session_analyzer_win.cc (renamed from chromium/components/browser_watcher/system_session_analyzer_win.cc)207
-rw-r--r--chromium/components/metrics/system_session_analyzer_win.h (renamed from chromium/components/browser_watcher/system_session_analyzer_win.h)57
-rw-r--r--chromium/components/metrics/system_session_analyzer_win_unittest.cc (renamed from chromium/components/browser_watcher/system_session_analyzer_win_unittest.cc)38
-rw-r--r--chromium/components/metrics_services_manager/metrics_services_manager.cc3
-rw-r--r--chromium/components/multidevice/BUILD.gn1
-rw-r--r--chromium/components/multidevice/OWNERS2
-rw-r--r--chromium/components/multidevice/service/BUILD.gn32
-rw-r--r--chromium/components/multidevice/service/DEPS7
-rw-r--r--chromium/components/multidevice/service/cryptauth_client_factory_impl.cc30
-rw-r--r--chromium/components/multidevice/service/cryptauth_client_factory_impl.h42
-rw-r--r--chromium/components/multidevice/service/cryptauth_enroller_factory_impl.cc34
-rw-r--r--chromium/components/multidevice/service/cryptauth_enroller_factory_impl.h48
-rw-r--r--chromium/components/multidevice/service/cryptauth_token_fetcher_impl.cc71
-rw-r--r--chromium/components/multidevice/service/cryptauth_token_fetcher_impl.h49
-rw-r--r--chromium/components/multidevice/service/cryptauth_token_fetcher_impl_unittest.cc126
-rw-r--r--chromium/components/multidevice/service/multidevice_service.cc9
-rw-r--r--chromium/components/multidevice/service/multidevice_service_unittest.cc2
-rw-r--r--chromium/components/multidevice/service/test_main.cc4
-rw-r--r--chromium/components/nacl/browser/BUILD.gn4
-rw-r--r--chromium/components/nacl/common/BUILD.gn4
-rw-r--r--chromium/components/nacl/loader/BUILD.gn13
-rw-r--r--chromium/components/navigation_interception/intercept_navigation_delegate.cc5
-rw-r--r--chromium/components/net_log/OWNERS11
-rw-r--r--chromium/components/net_log/chrome_net_log.cc3
-rw-r--r--chromium/components/net_log/net_export_file_writer.cc10
-rw-r--r--chromium/components/net_log/net_export_file_writer_unittest.cc6
-rw-r--r--chromium/components/neterror/resources/offline.js49
-rw-r--r--chromium/components/network_session_configurator/browser/network_session_configurator.cc23
-rw-r--r--chromium/components/network_session_configurator/browser/network_session_configurator_unittest.cc30
-rw-r--r--chromium/components/network_session_configurator/common/network_features.cc3
-rw-r--r--chromium/components/network_session_configurator/common/network_features.h4
-rw-r--r--chromium/components/network_session_configurator/common/network_switch_list.h3
-rw-r--r--chromium/components/network_time/network_time_test_utils.cc5
-rw-r--r--chromium/components/network_time/network_time_tracker.cc4
-rw-r--r--chromium/components/ntp_snippets/BUILD.gn6
-rw-r--r--chromium/components/ntp_snippets/OWNERS1
-rw-r--r--chromium/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc104
-rw-r--r--chromium/components/ntp_snippets/breaking_news/subscription_json_request.h4
-rw-r--r--chromium/components/ntp_snippets/breaking_news/subscription_manager_impl.cc74
-rw-r--r--chromium/components/ntp_snippets/breaking_news/subscription_manager_impl.h17
-rw-r--r--chromium/components/ntp_snippets/breaking_news/subscription_manager_impl_unittest.cc211
-rw-r--r--chromium/components/ntp_snippets/content_suggestions_service.cc36
-rw-r--r--chromium/components/ntp_snippets/content_suggestions_service.h26
-rw-r--r--chromium/components/ntp_snippets/content_suggestions_service_unittest.cc128
-rw-r--r--chromium/components/ntp_snippets/contextual/contextual_json_request.h1
-rw-r--r--chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc14
-rw-r--r--chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h10
-rw-r--r--chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc73
-rw-r--r--chromium/components/ntp_snippets/features.cc4
-rw-r--r--chromium/components/ntp_snippets/features.h3
-rw-r--r--chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.cc5
-rw-r--r--chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.h1
-rw-r--r--chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc10
-rw-r--r--chromium/components/ntp_snippets/pref_names.cc2
-rw-r--r--chromium/components/ntp_snippets/pref_names.h4
-rw-r--r--chromium/components/ntp_snippets/remote/json_request.h6
-rw-r--r--chromium/components/ntp_snippets/remote/prefetched_pages_tracker.h9
-rw-r--r--chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl.cc23
-rw-r--r--chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl.h7
-rw-r--r--chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl_unittest.cc46
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_database.cc7
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_fetcher.h3
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc103
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h19
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc396
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc73
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.h32
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc130
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl.cc36
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl.h19
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl_unittest.cc151
-rw-r--r--chromium/components/ntp_snippets/remote/test_utils.cc31
-rw-r--r--chromium/components/ntp_snippets/remote/test_utils.h22
-rw-r--r--chromium/components/ntp_tiles/BUILD.gn6
-rw-r--r--chromium/components/ntp_tiles/android/BUILD.gn20
-rw-r--r--chromium/components/ntp_tiles/constants.cc3
-rw-r--r--chromium/components/ntp_tiles/constants.h3
-rw-r--r--chromium/components/ntp_tiles/field_trial.cc54
-rw-r--r--chromium/components/ntp_tiles/field_trial.h14
-rw-r--r--chromium/components/ntp_tiles/icon_cacher_impl_unittest.cc6
-rw-r--r--chromium/components/ntp_tiles/most_visited_sites.cc5
-rw-r--r--chromium/components/ntp_tiles/most_visited_sites_unittest.cc217
-rw-r--r--chromium/components/ntp_tiles/popular_sites_impl.cc6
-rw-r--r--chromium/components/ntp_tiles/popular_sites_impl_unittest.cc15
-rw-r--r--chromium/components/ntp_tiles/switches.cc6
-rw-r--r--chromium/components/ntp_tiles/switches.h3
-rw-r--r--chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc10
-rw-r--r--chromium/components/offline_items_collection/core/BUILD.gn2
-rw-r--r--chromium/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc19
-rw-r--r--chromium/components/offline_items_collection/core/android/offline_content_aggregator_bridge.h3
-rw-r--r--chromium/components/offline_items_collection/core/android/offline_item_bridge.cc3
-rw-r--r--chromium/components/offline_items_collection/core/offline_content_aggregator.cc112
-rw-r--r--chromium/components/offline_items_collection/core/offline_content_aggregator.h64
-rw-r--r--chromium/components/offline_items_collection/core/offline_content_aggregator_unittest.cc223
-rw-r--r--chromium/components/offline_items_collection/core/offline_content_provider.h28
-rw-r--r--chromium/components/offline_items_collection/core/offline_item.h4
-rw-r--r--chromium/components/offline_items_collection/core/pending_state.h22
-rw-r--r--chromium/components/offline_items_collection/core/test_support/mock_offline_content_provider.cc13
-rw-r--r--chromium/components/offline_items_collection/core/test_support/mock_offline_content_provider.h4
-rw-r--r--chromium/components/offline_items_collection/core/throttled_offline_content_provider.cc25
-rw-r--r--chromium/components/offline_items_collection/core/throttled_offline_content_provider.h8
-rw-r--r--chromium/components/offline_items_collection/core/throttled_offline_content_provider_unittest.cc45
-rw-r--r--chromium/components/offline_pages/BUILD.gn1
-rw-r--r--chromium/components/offline_pages/buildflags/BUILD.gn (renamed from chromium/components/offline_pages/features/BUILD.gn)6
-rw-r--r--chromium/components/offline_pages/buildflags/features.gni (renamed from chromium/components/offline_pages/features/features.gni)0
-rw-r--r--chromium/components/offline_pages/content/background_loader/background_loader_contents.cc12
-rw-r--r--chromium/components/offline_pages/content/background_loader/background_loader_contents.h14
-rw-r--r--chromium/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc35
-rw-r--r--chromium/components/offline_pages/core/BUILD.gn16
-rw-r--r--chromium/components/offline_pages/core/DEPS1
-rw-r--r--chromium/components/offline_pages/core/archive_validator.cc25
-rw-r--r--chromium/components/offline_pages/core/archive_validator.h17
-rw-r--r--chromium/components/offline_pages/core/background/BUILD.gn4
-rw-r--r--chromium/components/offline_pages/core/background/offliner.h4
-rw-r--r--chromium/components/offline_pages/core/background/pending_state_updater.cc65
-rw-r--r--chromium/components/offline_pages/core/background/pending_state_updater.h56
-rw-r--r--chromium/components/offline_pages/core/background/pick_request_task.cc30
-rw-r--r--chromium/components/offline_pages/core/background/pick_request_task.h6
-rw-r--r--chromium/components/offline_pages/core/background/pick_request_task_unittest.cc11
-rw-r--r--chromium/components/offline_pages/core/background/request_coordinator.cc60
-rw-r--r--chromium/components/offline_pages/core/background/request_coordinator.h8
-rw-r--r--chromium/components/offline_pages/core/background/request_coordinator_event_logger.cc6
-rw-r--r--chromium/components/offline_pages/core/background/request_coordinator_unittest.cc93
-rw-r--r--chromium/components/offline_pages/core/background/request_notifier.h1
-rw-r--r--chromium/components/offline_pages/core/background/request_queue_in_memory_store.cc10
-rw-r--r--chromium/components/offline_pages/core/background/request_queue_store_sql.cc15
-rw-r--r--chromium/components/offline_pages/core/background/save_page_request.cc1
-rw-r--r--chromium/components/offline_pages/core/background/save_page_request.h11
-rw-r--r--chromium/components/offline_pages/core/client_policy_controller.cc28
-rw-r--r--chromium/components/offline_pages/core/client_policy_controller.h11
-rw-r--r--chromium/components/offline_pages/core/client_policy_controller_unittest.cc26
-rw-r--r--chromium/components/offline_pages/core/downloads/BUILD.gn2
-rw-r--r--chromium/components/offline_pages/core/downloads/download_notifying_observer.cc4
-rw-r--r--chromium/components/offline_pages/core/downloads/download_ui_adapter.cc165
-rw-r--r--chromium/components/offline_pages/core/downloads/download_ui_adapter.h19
-rw-r--r--chromium/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc114
-rw-r--r--chromium/components/offline_pages/core/downloads/offline_item_conversions.cc17
-rw-r--r--chromium/components/offline_pages/core/downloads/offline_item_conversions.h4
-rw-r--r--chromium/components/offline_pages/core/downloads/offline_item_conversions_unittest.cc29
-rw-r--r--chromium/components/offline_pages/core/model/add_page_to_download_manager_task_unittest.cc9
-rw-r--r--chromium/components/offline_pages/core/model/clear_legacy_temporary_pages_task.cc6
-rw-r--r--chromium/components/offline_pages/core/model/clear_storage_task.cc56
-rw-r--r--chromium/components/offline_pages/core/model/clear_storage_task_unittest.cc131
-rw-r--r--chromium/components/offline_pages/core/model/delete_page_task.cc94
-rw-r--r--chromium/components/offline_pages/core/model/delete_page_task.h8
-rw-r--r--chromium/components/offline_pages/core/model/delete_page_task_unittest.cc72
-rw-r--r--chromium/components/offline_pages/core/model/get_pages_task.cc33
-rw-r--r--chromium/components/offline_pages/core/model/get_pages_task.h8
-rw-r--r--chromium/components/offline_pages/core/model/get_pages_task_unittest.cc29
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_item_generator.cc10
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_item_generator.h4
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_model_taskified.cc236
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_model_taskified.h69
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc205
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_model_utils.cc47
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_model_utils.h13
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_model_utils_unittest.cc65
-rw-r--r--chromium/components/offline_pages/core/model/persistent_pages_consistency_check_task.cc23
-rw-r--r--chromium/components/offline_pages/core/model/temporary_pages_consistency_check_task.cc23
-rw-r--r--chromium/components/offline_pages/core/offline_page_archiver.cc87
-rw-r--r--chromium/components/offline_pages/core/offline_page_archiver.h30
-rw-r--r--chromium/components/offline_pages/core/offline_page_archiver_unittest.cc128
-rw-r--r--chromium/components/offline_pages/core/offline_page_client_policy.h21
-rw-r--r--chromium/components/offline_pages/core/offline_page_metadata_store_sql.h21
-rw-r--r--chromium/components/offline_pages/core/offline_page_model.cc2
-rw-r--r--chromium/components/offline_pages/core/offline_page_model.h20
-rw-r--r--chromium/components/offline_pages/core/offline_page_model_impl.cc1189
-rw-r--r--chromium/components/offline_pages/core/offline_page_model_impl.h314
-rw-r--r--chromium/components/offline_pages/core/offline_page_model_impl_unittest.cc1617
-rw-r--r--chromium/components/offline_pages/core/offline_page_model_query.cc314
-rw-r--r--chromium/components/offline_pages/core/offline_page_model_query.h185
-rw-r--r--chromium/components/offline_pages/core/offline_page_model_query_unittest.cc742
-rw-r--r--chromium/components/offline_pages/core/offline_page_storage_manager.cc239
-rw-r--r--chromium/components/offline_pages/core/offline_page_storage_manager.h166
-rw-r--r--chromium/components/offline_pages/core/offline_page_storage_manager_unittest.cc556
-rw-r--r--chromium/components/offline_pages/core/offline_page_test_archiver.cc12
-rw-r--r--chromium/components/offline_pages/core/offline_page_test_archiver.h8
-rw-r--r--chromium/components/offline_pages/core/offline_page_test_store.cc5
-rw-r--r--chromium/components/offline_pages/core/offline_page_types.h5
-rw-r--r--chromium/components/offline_pages/core/prefetch/BUILD.gn15
-rw-r--r--chromium/components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task.cc66
-rw-r--r--chromium/components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task.h39
-rw-r--r--chromium/components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task_unittest.cc105
-rw-r--r--chromium/components/offline_pages/core/prefetch/metrics_finalization_task.cc8
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc16
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc11
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_download_flow_unittest.cc2
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.cc27
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.h2
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl_unittest.cc2
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_network_request_factory_impl.cc16
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_types.h5
-rw-r--r--chromium/components/offline_pages/core/prefetch/store/prefetch_store.h12
-rw-r--r--chromium/components/offline_pages/core/prefetch/suggested_articles_observer.h5
-rw-r--r--chromium/components/offline_pages/core/prefetch/test_download_client.h2
-rw-r--r--chromium/components/offline_pages/core/request_header/BUILD.gn1
-rw-r--r--chromium/components/offline_pages/core/request_header/offline_page_header.cc34
-rw-r--r--chromium/components/offline_pages/core/request_header/offline_page_header.h33
-rw-r--r--chromium/components/offline_pages/core/request_header/offline_page_header_unittest.cc117
-rw-r--r--chromium/components/offline_pages/core/stub_offline_page_model.cc8
-rw-r--r--chromium/components/offline_pages/core/stub_offline_page_model.h12
-rw-r--r--chromium/components/offline_pages/core/system_download_manager_stub.cc7
-rw-r--r--chromium/components/offline_pages/core/system_download_manager_stub.h2
-rw-r--r--chromium/components/omnibox/browser/BUILD.gn7
-rw-r--r--chromium/components/onc/docs/onc_spec.md12
-rw-r--r--chromium/components/onc/onc_constants.cc1
-rw-r--r--chromium/components/onc/onc_constants.h1
-rw-r--r--chromium/components/open_from_clipboard/clipboard_recent_content_ios_unittest.mm3
-rw-r--r--chromium/components/optimization_guide/proto/hints.proto9
-rw-r--r--chromium/components/os_crypt/os_crypt_linux.cc8
-rw-r--r--chromium/components/os_crypt/os_crypt_mac.mm8
-rw-r--r--chromium/components/os_crypt/os_crypt_mocker_linux.cc5
-rw-r--r--chromium/components/page_info_strings.grdp12
-rw-r--r--chromium/components/pairing/BUILD.gn4
-rw-r--r--chromium/components/pairing/DEPS2
-rw-r--r--chromium/components/pairing/bluetooth_host_pairing_controller.cc5
-rw-r--r--chromium/components/pairing/bluetooth_host_pairing_controller.h2
-rw-r--r--chromium/components/password_manager/OWNERS3
-rw-r--r--chromium/components/password_manager/content/browser/content_password_manager_driver.cc4
-rw-r--r--chromium/components/password_manager/content/browser/content_password_manager_driver.h3
-rw-r--r--chromium/components/password_manager/content/common/OWNERS4
-rw-r--r--chromium/components/password_manager/content/common/credential_manager.typemap4
-rw-r--r--chromium/components/password_manager/content/common/credential_manager_mojom_traits.cc (renamed from chromium/components/password_manager/content/common/credential_manager_struct_traits.cc)7
-rw-r--r--chromium/components/password_manager/content/common/credential_manager_mojom_traits.h (renamed from chromium/components/password_manager/content/common/credential_manager_struct_traits.h)6
-rw-r--r--chromium/components/password_manager/core/browser/BUILD.gn3
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/OWNERS3
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.cc8
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc13
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend.h8
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend_unittest.cc18
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc2
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliation_service.cc8
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/facet_manager_unittest.cc2
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_impl_unittest.cc18
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_pending_request_task.cc5
-rw-r--r--chromium/components/password_manager/core/browser/credentials_filter.h3
-rw-r--r--chromium/components/password_manager/core/browser/export/password_manager_exporter.cc171
-rw-r--r--chromium/components/password_manager/core/browser/export/password_manager_exporter.h93
-rw-r--r--chromium/components/password_manager/core/browser/export/password_manager_exporter_unittest.cc226
-rw-r--r--chromium/components/password_manager/core/browser/form_fetcher_impl_unittest.cc5
-rw-r--r--chromium/components/password_manager/core/browser/form_saver_impl.cc2
-rw-r--r--chromium/components/password_manager/core/browser/form_saver_impl_unittest.cc7
-rw-r--r--chromium/components/password_manager/core/browser/http_data_cleaner.cc7
-rw-r--r--chromium/components/password_manager/core/browser/import/password_csv_reader_fuzzer.cc10
-rw-r--r--chromium/components/password_manager/core/browser/login_database_unittest.cc25
-rw-r--r--chromium/components/password_manager/core/browser/mock_password_store.h6
-rw-r--r--chromium/components/password_manager/core/browser/password_autofill_manager.cc2
-rw-r--r--chromium/components/password_manager/core/browser/password_autofill_manager_unittest.cc8
-rw-r--r--chromium/components/password_manager/core/browser/password_form_manager.cc1
-rw-r--r--chromium/components/password_manager/core/browser/password_form_manager_unittest.cc7
-rw-r--r--chromium/components/password_manager/core/browser/password_generation_manager_unittest.cc2
-rw-r--r--chromium/components/password_manager/core/browser/password_manager.cc36
-rw-r--r--chromium/components/password_manager/core/browser/password_manager.h4
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_driver.h5
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_metrics_recorder.cc4
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_metrics_util.h9
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_unittest.cc39
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_util.cc2
-rw-r--r--chromium/components/password_manager/core/browser/password_reuse_detection_manager.cc7
-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.cc9
-rw-r--r--chromium/components/password_manager/core/browser/password_store.cc47
-rw-r--r--chromium/components/password_manager/core/browser/password_store.h9
-rw-r--r--chromium/components/password_manager/core/browser/password_store_signin_notifier.cc9
-rw-r--r--chromium/components/password_manager/core/browser/password_store_unittest.cc4
-rw-r--r--chromium/components/password_manager/core/browser/site_affiliation/asset_link_retriever.cc2
-rw-r--r--chromium/components/password_manager/core/browser/stub_credentials_filter.cc4
-rw-r--r--chromium/components/password_manager/core/browser/stub_credentials_filter.h3
-rw-r--r--chromium/components/password_manager/core/browser/test_password_store.cc19
-rw-r--r--chromium/components/password_manager/core/browser/test_password_store.h8
-rw-r--r--chromium/components/password_manager/core/browser/ui/export_flow.h15
-rw-r--r--chromium/components/password_manager/core/browser/ui/export_progress_status.h20
-rw-r--r--chromium/components/password_manager/core/common/password_manager_features.cc22
-rw-r--r--chromium/components/password_manager/core/common/password_manager_features.h8
-rw-r--r--chromium/components/password_manager/sync/browser/sync_credentials_filter.cc14
-rw-r--r--chromium/components/password_manager/sync/browser/sync_credentials_filter.h3
-rw-r--r--chromium/components/password_manager/sync/browser/sync_credentials_filter_unittest.cc13
-rw-r--r--chromium/components/patch_service/patch_service.cc3
-rw-r--r--chromium/components/payments/content/BUILD.gn6
-rw-r--r--chromium/components/payments/content/android/payment_manifest_parser_android.cc1
-rw-r--r--chromium/components/payments/content/installable_payment_app_crawler.cc187
-rw-r--r--chromium/components/payments/content/installable_payment_app_crawler.h89
-rw-r--r--chromium/components/payments/content/manifest_verifier.cc48
-rw-r--r--chromium/components/payments/content/manifest_verifier.h26
-rw-r--r--chromium/components/payments/content/origin_security_checker.h2
-rw-r--r--chromium/components/payments/content/payment_manifest_web_data_service.h2
-rw-r--r--chromium/components/payments/content/payment_request.cc4
-rw-r--r--chromium/components/payments/content/payment_request.h2
-rw-r--r--chromium/components/payments/content/payment_request_spec.cc2
-rw-r--r--chromium/components/payments/content/payment_request_state.cc30
-rw-r--r--chromium/components/payments/content/payment_request_state.h11
-rw-r--r--chromium/components/payments/content/service_worker_payment_app_factory.cc127
-rw-r--r--chromium/components/payments/content/service_worker_payment_app_factory.h24
-rw-r--r--chromium/components/payments/content/service_worker_payment_instrument.cc109
-rw-r--r--chromium/components/payments/content/service_worker_payment_instrument.h37
-rw-r--r--chromium/components/payments/content/utility/BUILD.gn1
-rw-r--r--chromium/components/payments/content/utility/payment_manifest_parser.cc60
-rw-r--r--chromium/components/payments/content/utility/payment_manifest_parser.h33
-rw-r--r--chromium/components/payments/content/utility/payment_method_manifest_parser_fuzzer.cc13
-rw-r--r--chromium/components/payments/content/utility/payment_web_app_manifest_parser_fuzzer.cc2
-rw-r--r--chromium/components/payments/content/web_app_manifest.cc (renamed from chromium/components/payments/content/web_app_manifest_section.cc)5
-rw-r--r--chromium/components/payments/content/web_app_manifest.h (renamed from chromium/components/payments/content/web_app_manifest_section.h)17
-rw-r--r--chromium/components/payments/content/web_app_manifest_section_table.h2
-rw-r--r--chromium/components/payments/core/payment_details.cc2
-rw-r--r--chromium/components/payments/core/payment_details_validation_unittest.cc13
-rw-r--r--chromium/components/payments/core/payment_manifest_downloader.h46
-rw-r--r--chromium/components/payments/core/payment_request_data_util.cc4
-rw-r--r--chromium/components/payments/core/test_payment_manifest_downloader.cc5
-rw-r--r--chromium/components/payments/core/test_payment_manifest_downloader.h8
-rw-r--r--chromium/components/payments_strings.grdp21
-rw-r--r--chromium/components/pdf/browser/pdf_web_contents_helper.cc2
-rw-r--r--chromium/components/pdf/browser/pdf_web_contents_helper.h1
-rw-r--r--chromium/components/pdf/common/BUILD.gn2
-rw-r--r--chromium/components/pdf/common/pdf.mojom2
-rw-r--r--chromium/components/pdf/renderer/DEPS1
-rw-r--r--chromium/components/pdf/renderer/pdf_accessibility_tree.cc66
-rw-r--r--chromium/components/pdf/renderer/pdf_accessibility_tree.h3
-rw-r--r--chromium/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc3
-rw-r--r--chromium/components/pdf/renderer/pepper_pdf_host.cc7
-rw-r--r--chromium/components/physical_web/data_source/fake_physical_web_data_source.cc8
-rw-r--r--chromium/components/physical_web/webui/physical_web_base_message_handler.cc6
-rw-r--r--chromium/components/plugins/renderer/DEPS2
-rw-r--r--chromium/components/plugins/renderer/webview_plugin.cc2
-rw-r--r--chromium/components/policy/android/BUILD.gn1
-rw-r--r--chromium/components/policy/resources/policy_templates.gni179
-rw-r--r--chromium/components/policy_strings.grdp3
-rw-r--r--chromium/components/prefs/json_pref_store.cc4
-rw-r--r--chromium/components/prefs/json_pref_store_unittest.cc1
-rw-r--r--chromium/components/prefs/pref_change_registrar_unittest.cc6
-rw-r--r--chromium/components/prefs/pref_registry_simple.cc80
-rw-r--r--chromium/components/prefs/pref_registry_simple.h79
-rw-r--r--chromium/components/prefs/pref_service.cc27
-rw-r--r--chromium/components/prefs/pref_service.h17
-rw-r--r--chromium/components/prefs/pref_service_factory.cc15
-rw-r--r--chromium/components/prefs/pref_service_factory.h9
-rw-r--r--chromium/components/previews/content/previews_content_util.cc29
-rw-r--r--chromium/components/previews/content/previews_content_util.h5
-rw-r--r--chromium/components/previews/content/previews_content_util_unittest.cc133
-rw-r--r--chromium/components/previews/content/previews_io_data.cc84
-rw-r--r--chromium/components/previews/content/previews_io_data.h22
-rw-r--r--chromium/components/previews/content/previews_io_data_unittest.cc261
-rw-r--r--chromium/components/previews/content/previews_optimization_guide.cc49
-rw-r--r--chromium/components/previews/content/previews_optimization_guide_unittest.cc12
-rw-r--r--chromium/components/previews/content/previews_ui_service.h10
-rw-r--r--chromium/components/previews/core/BUILD.gn2
-rw-r--r--chromium/components/previews/core/previews_black_list.h6
-rw-r--r--chromium/components/previews/core/previews_black_list_unittest.cc7
-rw-r--r--chromium/components/previews/core/previews_decider.h7
-rw-r--r--chromium/components/previews/core/previews_experiments.cc51
-rw-r--r--chromium/components/previews/core/previews_experiments.h10
-rw-r--r--chromium/components/previews/core/previews_experiments_unittest.cc71
-rw-r--r--chromium/components/previews/core/previews_features.cc27
-rw-r--r--chromium/components/previews/core/previews_features.h1
-rw-r--r--chromium/components/previews/core/previews_logger.cc76
-rw-r--r--chromium/components/previews/core/previews_logger_unittest.cc16
-rw-r--r--chromium/components/previews/core/previews_opt_out_store_sql.cc10
-rw-r--r--chromium/components/previews/core/previews_user_data.cc6
-rw-r--r--chromium/components/previews/core/previews_user_data.h21
-rw-r--r--chromium/components/previews/core/previews_user_data_unittest.cc15
-rw-r--r--chromium/components/previews/core/test_previews_decider.cc33
-rw-r--r--chromium/components/previews/core/test_previews_decider.h36
-rw-r--r--chromium/components/printing/DEPS2
-rw-r--r--chromium/components/printing/browser/BUILD.gn5
-rw-r--r--chromium/components/printing/browser/DEPS1
-rw-r--r--chromium/components/printing/browser/features.cc14
-rw-r--r--chromium/components/printing/browser/features.h19
-rw-r--r--chromium/components/printing/browser/print_composite_client.cc273
-rw-r--r--chromium/components/printing/browser/print_composite_client.h115
-rw-r--r--chromium/components/printing/browser/print_manager_utils.cc39
-rw-r--r--chromium/components/printing/browser/print_manager_utils.h3
-rw-r--r--chromium/components/printing/common/BUILD.gn3
-rw-r--r--chromium/components/printing/common/cloud_print_cdd_conversion.cc129
-rw-r--r--chromium/components/printing/common/cloud_print_cdd_conversion.h24
-rw-r--r--chromium/components/printing/common/print_messages.cc25
-rw-r--r--chromium/components/printing/common/print_messages.h79
-rw-r--r--chromium/components/printing/renderer/BUILD.gn2
-rw-r--r--chromium/components/printing/renderer/print_render_frame_helper.cc232
-rw-r--r--chromium/components/printing/renderer/print_render_frame_helper.h44
-rw-r--r--chromium/components/printing/renderer/print_render_frame_helper_linux.cc7
-rw-r--r--chromium/components/printing/renderer/print_render_frame_helper_mac.mm42
-rw-r--r--chromium/components/printing/service/BUILD.gn2
-rw-r--r--chromium/components/printing/service/DEPS2
-rw-r--r--chromium/components/printing/service/pdf_compositor_impl.cc286
-rw-r--r--chromium/components/printing/service/pdf_compositor_impl.h158
-rw-r--r--chromium/components/printing/service/pdf_compositor_impl_unittest.cc348
-rw-r--r--chromium/components/printing/service/pdf_compositor_service.cc14
-rw-r--r--chromium/components/printing/service/pdf_compositor_service_unittest.cc100
-rw-r--r--chromium/components/printing/service/public/cpp/BUILD.gn12
-rw-r--r--chromium/components/printing/service/public/cpp/pdf_compositor_client.cc60
-rw-r--r--chromium/components/printing/service/public/cpp/pdf_compositor_client.h41
-rw-r--r--chromium/components/printing/service/public/cpp/pdf_service_mojo_types.h17
-rw-r--r--chromium/components/printing/service/public/interfaces/pdf_compositor.mojom50
-rw-r--r--chromium/components/printing_strings.grdp10
-rw-r--r--chromium/components/proxy_config/ios/DEPS2
-rw-r--r--chromium/components/proxy_config/ios/proxy_service_factory.cc24
-rw-r--r--chromium/components/proxy_config/ios/proxy_service_factory.h4
-rw-r--r--chromium/components/proxy_config/pref_proxy_config_tracker_impl.cc2
-rw-r--r--chromium/components/proxy_config/pref_proxy_config_tracker_impl.h4
-rw-r--r--chromium/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc9
-rw-r--r--chromium/components/proxy_config/proxy_config_dictionary.cc6
-rw-r--r--chromium/components/pwg_encoder/BUILD.gn35
-rw-r--r--chromium/components/pwg_encoder/DEPS3
-rw-r--r--chromium/components/pwg_encoder/OWNERS3
-rw-r--r--chromium/components/pwg_encoder/bitmap_image.cc32
-rw-r--r--chromium/components/pwg_encoder/bitmap_image.h48
-rw-r--r--chromium/components/pwg_encoder/pwg_encoder.cc264
-rw-r--r--chromium/components/pwg_encoder/pwg_encoder.h53
-rw-r--r--chromium/components/pwg_encoder/pwg_encoder_unittest.cc83
-rw-r--r--chromium/components/query_parser/OWNERS1
-rw-r--r--chromium/components/query_parser/query_parser.cc6
-rw-r--r--chromium/components/quirks/quirks_manager.cc10
-rw-r--r--chromium/components/quirks/quirks_manager.h2
-rw-r--r--chromium/components/rappor/public/interfaces/BUILD.gn2
-rw-r--r--chromium/components/rappor/public/interfaces/rappor_recorder.mojom2
-rw-r--r--chromium/components/rappor/rappor_recorder_impl.cc5
-rw-r--r--chromium/components/rappor/rappor_service_impl.cc4
-rw-r--r--chromium/components/reading_list/core/reading_list_model_storage.h3
-rw-r--r--chromium/components/reading_list/core/reading_list_store.cc29
-rw-r--r--chromium/components/reading_list/core/reading_list_store.h16
-rw-r--r--chromium/components/reading_list/core/reading_list_store_unittest.cc5
-rw-r--r--chromium/components/reading_list/features/BUILD.gn6
-rw-r--r--chromium/components/reading_list/features/reading_list_switches.cc2
-rw-r--r--chromium/components/renderer_context_menu/context_menu_delegate.cc5
-rw-r--r--chromium/components/resources/BUILD.gn4
-rw-r--r--chromium/components/resources/dom_distiller_resources.grdp2
-rw-r--r--chromium/components/resources/security_interstitials_resources.grdp2
-rw-r--r--chromium/components/safe_browsing/OWNERS3
-rw-r--r--chromium/components/safe_browsing/android/remote_database_manager.cc14
-rw-r--r--chromium/components/safe_browsing/android/remote_database_manager_unittest.cc3
-rw-r--r--chromium/components/safe_browsing/android/safe_browsing_api_handler.h7
-rw-r--r--chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc46
-rw-r--r--chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.h4
-rw-r--r--chromium/components/safe_browsing/base_blocking_page.cc1
-rw-r--r--chromium/components/safe_browsing/browser/DEPS3
-rw-r--r--chromium/components/safe_browsing/browser/base_parallel_resource_throttle.cc3
-rw-r--r--chromium/components/safe_browsing/browser/base_parallel_resource_throttle_unittest.cc9
-rw-r--r--chromium/components/safe_browsing/browser/browser_url_loader_throttle.cc4
-rw-r--r--chromium/components/safe_browsing/browser/mojo_safe_browsing_impl.cc41
-rw-r--r--chromium/components/safe_browsing/browser/mojo_safe_browsing_impl.h19
-rw-r--r--chromium/components/safe_browsing/browser/threat_details.cc84
-rw-r--r--chromium/components/safe_browsing/browser/threat_details.h23
-rw-r--r--chromium/components/safe_browsing/browser/url_checker_delegate.h15
-rw-r--r--chromium/components/safe_browsing/common/BUILD.gn21
-rw-r--r--chromium/components/safe_browsing/common/DEPS1
-rw-r--r--chromium/components/safe_browsing/common/safe_browsing.mojom76
-rw-r--r--chromium/components/safe_browsing/common/safe_browsing_prefs.cc160
-rw-r--r--chromium/components/safe_browsing/common/safe_browsing_prefs.h84
-rw-r--r--chromium/components/safe_browsing/common/safe_browsing_prefs_unittest.cc108
-rw-r--r--chromium/components/safe_browsing/common/safebrowsing_constants.cc2
-rw-r--r--chromium/components/safe_browsing/common/safebrowsing_constants.h6
-rw-r--r--chromium/components/safe_browsing/common/safebrowsing_message_generator.cc33
-rw-r--r--chromium/components/safe_browsing/common/safebrowsing_message_generator.h7
-rw-r--r--chromium/components/safe_browsing/common/safebrowsing_messages.h85
-rw-r--r--chromium/components/safe_browsing/common/safebrowsing_types.h16
-rw-r--r--chromium/components/safe_browsing/db/v4_database.cc14
-rw-r--r--chromium/components/safe_browsing/db/v4_get_hash_protocol_manager.cc7
-rw-r--r--chromium/components/safe_browsing/db/v4_get_hash_protocol_manager.h4
-rw-r--r--chromium/components/safe_browsing/db/v4_get_hash_protocol_manager_unittest.cc6
-rw-r--r--chromium/components/safe_browsing/db/v4_local_database_manager.cc7
-rw-r--r--chromium/components/safe_browsing/db/v4_local_database_manager_unittest.cc13
-rw-r--r--chromium/components/safe_browsing/db/v4_store.cc4
-rw-r--r--chromium/components/safe_browsing/features.cc27
-rw-r--r--chromium/components/safe_browsing/features.h8
-rw-r--r--chromium/components/safe_browsing/password_protection/BUILD.gn1
-rw-r--r--chromium/components/safe_browsing/password_protection/password_protection_service.cc43
-rw-r--r--chromium/components/safe_browsing/password_protection/password_protection_service.h28
-rw-r--r--chromium/components/safe_browsing/password_protection/password_protection_service_unittest.cc143
-rw-r--r--chromium/components/safe_browsing/renderer/DEPS1
-rw-r--r--chromium/components/safe_browsing/renderer/renderer_url_loader_throttle.cc6
-rw-r--r--chromium/components/safe_browsing/renderer/threat_dom_details.cc96
-rw-r--r--chromium/components/safe_browsing/renderer/threat_dom_details.h26
-rw-r--r--chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle.cc3
-rw-r--r--chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle_unittest.cc7
-rw-r--r--chromium/components/safe_browsing/triggers/ad_sampler_trigger.cc33
-rw-r--r--chromium/components/safe_browsing/triggers/ad_sampler_trigger.h21
-rw-r--r--chromium/components/safe_browsing/triggers/ad_sampler_trigger_unittest.cc26
-rw-r--r--chromium/components/safe_browsing/triggers/trigger_manager.cc1
-rw-r--r--chromium/components/safe_browsing/triggers/trigger_manager_unittest.cc18
-rw-r--r--chromium/components/safe_browsing/triggers/trigger_throttler.cc8
-rw-r--r--chromium/components/safe_browsing/triggers/trigger_throttler.h4
-rw-r--r--chromium/components/safe_browsing/triggers/trigger_throttler_unittest.cc16
-rw-r--r--chromium/components/search_engines/BUILD.gn1
-rw-r--r--chromium/components/search_engines/search_terms_data.cc4
-rw-r--r--chromium/components/search_engines/search_terms_data.h4
-rw-r--r--chromium/components/search_engines/template_url.cc93
-rw-r--r--chromium/components/search_engines/template_url.h27
-rw-r--r--chromium/components/search_engines/template_url_data.cc27
-rw-r--r--chromium/components/search_engines/template_url_data.h5
-rw-r--r--chromium/components/search_engines/template_url_data_unittest.cc29
-rw-r--r--chromium/components/search_engines/template_url_fetcher.cc10
-rw-r--r--chromium/components/search_engines/template_url_unittest.cc71
-rw-r--r--chromium/components/search_engines/testing_search_terms_data.cc4
-rw-r--r--chromium/components/search_engines/testing_search_terms_data.h4
-rw-r--r--chromium/components/search_provider_logos/fixed_logo_api.cc5
-rw-r--r--chromium/components/search_provider_logos/google_logo_api.cc4
-rw-r--r--chromium/components/search_provider_logos/logo_cache.cc6
-rw-r--r--chromium/components/search_provider_logos/logo_cache_unittest.cc8
-rw-r--r--chromium/components/search_provider_logos/logo_tracker.cc10
-rw-r--r--chromium/components/security_interstitials/core/bad_clock_ui.cc1
-rw-r--r--chromium/components/security_interstitials/core/base_safe_browsing_error_ui.cc5
-rw-r--r--chromium/components/security_interstitials/core/base_safe_browsing_error_ui.h20
-rw-r--r--chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.css14
-rw-r--r--chromium/components/security_interstitials/core/common/resources/interstitial_common.css1
-rw-r--r--chromium/components/security_interstitials/core/common/resources/interstitial_core.css1
-rw-r--r--chromium/components/security_interstitials/core/metrics_helper.cc2
-rw-r--r--chromium/components/security_interstitials/core/mitm_software_ui.cc1
-rw-r--r--chromium/components/security_interstitials/core/safe_browsing_loud_error_ui.cc3
-rw-r--r--chromium/components/security_interstitials/core/ssl_error_ui.cc1
-rw-r--r--chromium/components/security_interstitials_strings.grdp51
-rw-r--r--chromium/components/security_state/content/content_utils.cc4
-rw-r--r--chromium/components/security_state/content/content_utils_browsertest.cc4
-rw-r--r--chromium/components/security_state/content/ssl_status_input_event_data.cc4
-rw-r--r--chromium/components/security_state/core/security_state.h3
-rw-r--r--chromium/components/security_state/core/security_state_unittest.cc7
-rw-r--r--chromium/components/security_state/ios/ssl_status_input_event_data.mm4
-rw-r--r--chromium/components/sessions/core/base_session_service.cc7
-rw-r--r--chromium/components/sessions/core/in_memory_tab_restore_service.cc5
-rw-r--r--chromium/components/sessions/core/in_memory_tab_restore_service.h1
-rw-r--r--chromium/components/sessions/core/persistent_tab_restore_service.cc17
-rw-r--r--chromium/components/sessions/core/persistent_tab_restore_service.h1
-rw-r--r--chromium/components/sessions/core/tab_restore_service.h6
-rw-r--r--chromium/components/sessions/core/tab_restore_service_helper.cc79
-rw-r--r--chromium/components/sessions/core/tab_restore_service_helper.h15
-rw-r--r--chromium/components/sessions/core/tab_restore_service_observer.h2
-rw-r--r--chromium/components/signin/core/browser/BUILD.gn9
-rw-r--r--chromium/components/signin/core/browser/DEPS2
-rw-r--r--chromium/components/signin/core/browser/about_signin_internals.cc38
-rw-r--r--chromium/components/signin/core/browser/about_signin_internals.h8
-rw-r--r--chromium/components/signin/core/browser/account_fetcher_service.cc69
-rw-r--r--chromium/components/signin/core/browser/account_fetcher_service.h24
-rw-r--r--chromium/components/signin/core/browser/account_info.cc6
-rw-r--r--chromium/components/signin/core/browser/account_info.h5
-rw-r--r--chromium/components/signin/core/browser/account_info_unittest.cc22
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor.h2
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_unittest.cc46
-rw-r--r--chromium/components/signin/core/browser/account_tracker_service.cc138
-rw-r--r--chromium/components/signin/core/browser/account_tracker_service.h41
-rw-r--r--chromium/components/signin/core/browser/account_tracker_service_unittest.cc236
-rw-r--r--chromium/components/signin/core/browser/android/BUILD.gn1
-rw-r--r--chromium/components/signin/core/browser/chrome_connected_header_helper.cc18
-rw-r--r--chromium/components/signin/core/browser/chrome_connected_header_helper.h7
-rw-r--r--chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc31
-rw-r--r--chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h5
-rw-r--r--chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc75
-rw-r--r--chromium/components/signin/core/browser/dice_header_helper.cc45
-rw-r--r--chromium/components/signin/core/browser/dice_header_helper.h16
-rw-r--r--chromium/components/signin/core/browser/fake_account_fetcher_service.cc13
-rw-r--r--chromium/components/signin/core/browser/fake_account_fetcher_service.h21
-rw-r--r--chromium/components/signin/core/browser/fake_signin_manager.cc15
-rw-r--r--chromium/components/signin/core/browser/gaia_cookie_manager_service.cc42
-rw-r--r--chromium/components/signin/core/browser/gaia_cookie_manager_service.h12
-rw-r--r--chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc6
-rw-r--r--chromium/components/signin/core/browser/profile_management_switches.cc57
-rw-r--r--chromium/components/signin/core/browser/profile_management_switches.h24
-rw-r--r--chromium/components/signin/core/browser/profile_management_switches_unittest.cc37
-rw-r--r--chromium/components/signin/core/browser/resources/signin_index.css10
-rw-r--r--chromium/components/signin/core/browser/resources/signin_index.html17
-rw-r--r--chromium/components/signin/core/browser/resources/signin_internals.js40
-rw-r--r--chromium/components/signin/core/browser/scoped_account_consistency.cc11
-rw-r--r--chromium/components/signin/core/browser/scoped_account_consistency.h2
-rw-r--r--chromium/components/signin/core/browser/signin_client.h14
-rw-r--r--chromium/components/signin/core/browser/signin_cookie_change_subscription.cc104
-rw-r--r--chromium/components/signin/core/browser/signin_cookie_change_subscription.h (renamed from chromium/components/signin/core/browser/signin_cookie_changed_subscription.h)58
-rw-r--r--chromium/components/signin/core/browser/signin_cookie_changed_subscription.cc104
-rw-r--r--chromium/components/signin/core/browser/signin_header_helper.cc23
-rw-r--r--chromium/components/signin/core/browser/signin_header_helper.h6
-rw-r--r--chromium/components/signin/core/browser/signin_header_helper_unittest.cc80
-rw-r--r--chromium/components/signin/core/browser/signin_manager.cc45
-rw-r--r--chromium/components/signin/core/browser/signin_manager.h40
-rw-r--r--chromium/components/signin/core/browser/signin_manager_unittest.cc8
-rw-r--r--chromium/components/signin/core/browser/signin_pref_names.cc3
-rw-r--r--chromium/components/signin/core/browser/signin_pref_names.h1
-rw-r--r--chromium/components/signin/core/browser/test_signin_client.cc14
-rw-r--r--chromium/components/signin/core/browser/test_signin_client.h10
-rw-r--r--chromium/components/signin/ios/browser/account_consistency_service.mm6
-rw-r--r--chromium/components/signin/ios/browser/account_consistency_service_unittest.mm8
-rw-r--r--chromium/components/spellcheck/browser/BUILD.gn5
-rw-r--r--chromium/components/spellcheck/browser/DEPS1
-rw-r--r--chromium/components/spellcheck/browser/spell_check_host_impl.cc92
-rw-r--r--chromium/components/spellcheck/browser/spell_check_host_impl.h65
-rw-r--r--chromium/components/spellcheck/browser/spellcheck_message_filter_platform.h78
-rw-r--r--chromium/components/spellcheck/browser/spellcheck_message_filter_platform_android.cc66
-rw-r--r--chromium/components/spellcheck/browser/spellcheck_platform.h2
-rw-r--r--chromium/components/spellcheck/browser/spellcheck_platform_mac.mm2
-rw-r--r--chromium/components/spellcheck/browser/spellchecker_session_bridge_android.cc39
-rw-r--r--chromium/components/spellcheck/browser/spellchecker_session_bridge_android.h36
-rw-r--r--chromium/components/spellcheck/browser/spelling_service_client.cc5
-rw-r--r--chromium/components/spellcheck/browser/spelling_service_client.h6
-rw-r--r--chromium/components/spellcheck/common/BUILD.gn10
-rw-r--r--chromium/components/spellcheck/common/DEPS1
-rw-r--r--chromium/components/spellcheck/common/spellcheck.mojom38
-rw-r--r--chromium/components/spellcheck/common/spellcheck_common.cc14
-rw-r--r--chromium/components/spellcheck/common/spellcheck_common.h12
-rw-r--r--chromium/components/spellcheck/common/spellcheck_message_generator.cc33
-rw-r--r--chromium/components/spellcheck/common/spellcheck_message_generator.h11
-rw-r--r--chromium/components/spellcheck/common/spellcheck_messages.h61
-rw-r--r--chromium/components/spellcheck/common/spellcheck_panel.mojom4
-rw-r--r--chromium/components/spellcheck/common/spellcheck_result.h1
-rw-r--r--chromium/components/spellcheck/common/spellcheck_struct_traits.cc2
-rw-r--r--chromium/components/spellcheck/renderer/BUILD.gn3
-rw-r--r--chromium/components/spellcheck/renderer/empty_local_interface_provider.cc13
-rw-r--r--chromium/components/spellcheck/renderer/empty_local_interface_provider.h24
-rw-r--r--chromium/components/spellcheck/renderer/hunspell_engine.cc10
-rw-r--r--chromium/components/spellcheck/renderer/platform_spelling_engine.cc27
-rw-r--r--chromium/components/spellcheck/renderer/platform_spelling_engine.h13
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck.cc23
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck.h11
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc10
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_panel.cc3
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_provider.cc42
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_provider.h4
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_provider_mac_unittest.cc63
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_provider_test.cc66
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_provider_test.h49
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_unittest.cc8
-rw-r--r--chromium/components/ssl_config/ssl_config_prefs.cc4
-rw-r--r--chromium/components/ssl_config/ssl_config_prefs.h2
-rw-r--r--chromium/components/ssl_config/ssl_config_service_manager_pref.cc31
-rw-r--r--chromium/components/ssl_config/ssl_config_service_manager_pref_unittest.cc140
-rw-r--r--chromium/components/ssl_config/ssl_config_switches.cc2
-rw-r--r--chromium/components/ssl_config/ssl_config_switches.h2
-rw-r--r--chromium/components/ssl_errors/error_classification_unittest.cc7
-rw-r--r--chromium/components/ssl_errors/error_info.cc5
-rw-r--r--chromium/components/ssl_errors/error_info.h1
-rw-r--r--chromium/components/startup_metric_utils/browser/startup_metric_host_impl.cc5
-rw-r--r--chromium/components/startup_metric_utils/browser/startup_metric_utils.cc4
-rw-r--r--chromium/components/storage_monitor/BUILD.gn2
-rw-r--r--chromium/components/storage_monitor/media_storage_util_unittest.cc7
-rw-r--r--chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.cc145
-rw-r--r--chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.h22
-rw-r--r--chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos_unittest.cc38
-rw-r--r--chromium/components/storage_monitor/storage_info_utils.cc98
-rw-r--r--chromium/components/storage_monitor/storage_info_utils.h31
-rw-r--r--chromium/components/storage_monitor/storage_monitor_chromeos.cc2
-rw-r--r--chromium/components/storage_monitor/storage_monitor_linux.cc6
-rw-r--r--chromium/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc13
-rw-r--r--chromium/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h8
-rw-r--r--chromium/components/strings/BUILD.gn6
-rw-r--r--chromium/components/strings/components_chromium_strings_sr.xtb2
-rw-r--r--chromium/components/strings/components_google_chrome_strings_sr.xtb2
-rw-r--r--chromium/components/strings/components_strings_am.xtb82
-rw-r--r--chromium/components/strings/components_strings_ar.xtb138
-rw-r--r--chromium/components/strings/components_strings_bg.xtb82
-rw-r--r--chromium/components/strings/components_strings_bn.xtb100
-rw-r--r--chromium/components/strings/components_strings_ca.xtb94
-rw-r--r--chromium/components/strings/components_strings_cs.xtb92
-rw-r--r--chromium/components/strings/components_strings_da.xtb88
-rw-r--r--chromium/components/strings/components_strings_de.xtb90
-rw-r--r--chromium/components/strings/components_strings_el.xtb82
-rw-r--r--chromium/components/strings/components_strings_en-GB.xtb88
-rw-r--r--chromium/components/strings/components_strings_es-419.xtb82
-rw-r--r--chromium/components/strings/components_strings_es.xtb82
-rw-r--r--chromium/components/strings/components_strings_et.xtb82
-rw-r--r--chromium/components/strings/components_strings_fa.xtb89
-rw-r--r--chromium/components/strings/components_strings_fi.xtb82
-rw-r--r--chromium/components/strings/components_strings_fil.xtb82
-rw-r--r--chromium/components/strings/components_strings_fr.xtb88
-rw-r--r--chromium/components/strings/components_strings_gu.xtb82
-rw-r--r--chromium/components/strings/components_strings_hi.xtb89
-rw-r--r--chromium/components/strings/components_strings_hr.xtb82
-rw-r--r--chromium/components/strings/components_strings_hu.xtb82
-rw-r--r--chromium/components/strings/components_strings_id.xtb85
-rw-r--r--chromium/components/strings/components_strings_it.xtb82
-rw-r--r--chromium/components/strings/components_strings_iw.xtb85
-rw-r--r--chromium/components/strings/components_strings_ja.xtb82
-rw-r--r--chromium/components/strings/components_strings_kn.xtb82
-rw-r--r--chromium/components/strings/components_strings_ko.xtb90
-rw-r--r--chromium/components/strings/components_strings_lt.xtb82
-rw-r--r--chromium/components/strings/components_strings_lv.xtb82
-rw-r--r--chromium/components/strings/components_strings_ml.xtb82
-rw-r--r--chromium/components/strings/components_strings_mr.xtb84
-rw-r--r--chromium/components/strings/components_strings_ms.xtb82
-rw-r--r--chromium/components/strings/components_strings_nl.xtb82
-rw-r--r--chromium/components/strings/components_strings_no.xtb82
-rw-r--r--chromium/components/strings/components_strings_pl.xtb84
-rw-r--r--chromium/components/strings/components_strings_pt-BR.xtb82
-rw-r--r--chromium/components/strings/components_strings_pt-PT.xtb82
-rw-r--r--chromium/components/strings/components_strings_ro.xtb82
-rw-r--r--chromium/components/strings/components_strings_ru.xtb84
-rw-r--r--chromium/components/strings/components_strings_sk.xtb82
-rw-r--r--chromium/components/strings/components_strings_sl.xtb82
-rw-r--r--chromium/components/strings/components_strings_sr.xtb82
-rw-r--r--chromium/components/strings/components_strings_sv.xtb89
-rw-r--r--chromium/components/strings/components_strings_sw.xtb84
-rw-r--r--chromium/components/strings/components_strings_ta.xtb84
-rw-r--r--chromium/components/strings/components_strings_te.xtb82
-rw-r--r--chromium/components/strings/components_strings_th.xtb84
-rw-r--r--chromium/components/strings/components_strings_tr.xtb82
-rw-r--r--chromium/components/strings/components_strings_uk.xtb82
-rw-r--r--chromium/components/strings/components_strings_vi.xtb82
-rw-r--r--chromium/components/strings/components_strings_zh-CN.xtb82
-rw-r--r--chromium/components/strings/components_strings_zh-TW.xtb102
-rw-r--r--chromium/components/subresource_filter/content/browser/async_document_subresource_filter.cc10
-rw-r--r--chromium/components/subresource_filter/content/browser/content_ruleset_service.cc7
-rw-r--r--chromium/components/subresource_filter/content/browser/content_ruleset_service.h2
-rw-r--r--chromium/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc6
-rw-r--r--chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc62
-rw-r--r--chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h27
-rw-r--r--chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc120
-rw-r--r--chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc7
-rw-r--r--chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc20
-rw-r--r--chromium/components/subresource_filter/content/browser/verified_ruleset_dealer.cc6
-rw-r--r--chromium/components/subresource_filter/content/common/subresource_filter_messages.h5
-rw-r--r--chromium/components/subresource_filter/content/renderer/subresource_filter_agent.cc22
-rw-r--r--chromium/components/subresource_filter/content/renderer/subresource_filter_agent.h15
-rw-r--r--chromium/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc28
-rw-r--r--chromium/components/subresource_filter/core/browser/ruleset_service.cc8
-rw-r--r--chromium/components/subresource_filter/core/browser/ruleset_service.h42
-rw-r--r--chromium/components/subresource_filter/core/browser/ruleset_service_unittest.cc219
-rw-r--r--chromium/components/subresource_filter/core/browser/subresource_filter_features.cc17
-rw-r--r--chromium/components/subresource_filter/core/browser/subresource_filter_features.h4
-rw-r--r--chromium/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc189
-rw-r--r--chromium/components/subresource_filter/core/common/BUILD.gn42
-rw-r--r--chromium/components/subresource_filter/core/common/document_subresource_filter.cc14
-rw-r--r--chromium/components/subresource_filter/core/common/document_subresource_filter.h6
-rw-r--r--chromium/components/subresource_filter/core/common/document_subresource_filter_unittest.cc38
-rw-r--r--chromium/components/subresource_filter/core/common/indexed_ruleset.cc33
-rw-r--r--chromium/components/subresource_filter/core/common/indexed_ruleset.h9
-rw-r--r--chromium/components/subresource_filter/core/common/indexed_ruleset_unittest.cc63
-rw-r--r--chromium/components/subresource_filter/core/common/test_ruleset_utils.cc14
-rw-r--r--chromium/components/subresource_filter/core/common/test_ruleset_utils.h5
-rw-r--r--chromium/components/subresource_filter/core/common/tools/filter_tool.cc187
-rw-r--r--chromium/components/subresource_filter/core/common/tools/filter_tool.h82
-rw-r--r--chromium/components/subresource_filter/core/common/tools/filter_tool_main.cc168
-rw-r--r--chromium/components/subresource_filter/core/common/tools/filter_tool_unittest.cc173
-rw-r--r--chromium/components/subresource_filter/core/common/tools/indexing_tool.cc53
-rw-r--r--chromium/components/subresource_filter/core/common/tools/indexing_tool.h21
-rw-r--r--chromium/components/subresource_filter/core/common/tools/indexing_tool_main.cc41
-rw-r--r--chromium/components/subresource_filter/core/common/tools/indexing_tool_unittest.cc117
-rw-r--r--chromium/components/suggestions/image_encoder_ios.mm5
-rw-r--r--chromium/components/suggestions/image_manager.cc21
-rw-r--r--chromium/components/suggestions/image_manager.h6
-rw-r--r--chromium/components/suggestions/image_manager_unittest.cc40
-rw-r--r--chromium/components/suggestions/suggestions_service_impl_unittest.cc5
-rw-r--r--chromium/components/sync/BUILD.gn60
-rw-r--r--chromium/components/sync/engine_impl/attachments/proto/BUILD.gn17
-rw-r--r--chromium/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc4
-rw-r--r--chromium/components/sync_preferences/pref_model_associator.cc5
-rw-r--r--chromium/components/sync_preferences/pref_model_associator_unittest.cc5
-rw-r--r--chromium/components/sync_preferences/pref_service_syncable.cc34
-rw-r--r--chromium/components/sync_preferences/pref_service_syncable.h8
-rw-r--r--chromium/components/sync_preferences/pref_service_syncable_factory.cc6
-rw-r--r--chromium/components/sync_preferences/pref_service_syncable_factory.h4
-rw-r--r--chromium/components/sync_preferences/pref_service_syncable_unittest.cc22
-rw-r--r--chromium/components/sync_sessions/BUILD.gn38
-rw-r--r--chromium/components/sync_sessions/fake_sync_sessions_client.cc40
-rw-r--r--chromium/components/sync_sessions/fake_sync_sessions_client.h35
-rw-r--r--chromium/components/sync_sessions/favicon_cache_unittest.cc389
-rw-r--r--chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc1
-rw-r--r--chromium/components/sync_sessions/mock_sync_sessions_client.cc17
-rw-r--r--chromium/components/sync_sessions/mock_sync_sessions_client.h30
-rw-r--r--chromium/components/sync_sessions/open_tabs_ui_delegate_impl.cc112
-rw-r--r--chromium/components/sync_sessions/open_tabs_ui_delegate_impl.h63
-rw-r--r--chromium/components/sync_sessions/open_tabs_ui_delegate_impl_unittest.cc174
-rw-r--r--chromium/components/sync_sessions/revisit/bookmarks_by_url_provider_impl.cc23
-rw-r--r--chromium/components/sync_sessions/revisit/bookmarks_by_url_provider_impl.h39
-rw-r--r--chromium/components/sync_sessions/revisit/bookmarks_page_revisit_observer.cc52
-rw-r--r--chromium/components/sync_sessions/revisit/bookmarks_page_revisit_observer.h53
-rw-r--r--chromium/components/sync_sessions/revisit/bookmarks_page_revisit_observer_unittest.cc80
-rw-r--r--chromium/components/sync_sessions/revisit/current_tab_matcher.cc45
-rw-r--r--chromium/components/sync_sessions/revisit/current_tab_matcher.h39
-rw-r--r--chromium/components/sync_sessions/revisit/current_tab_matcher_unittest.cc115
-rw-r--r--chromium/components/sync_sessions/revisit/offset_tab_matcher.cc82
-rw-r--r--chromium/components/sync_sessions/revisit/offset_tab_matcher.h44
-rw-r--r--chromium/components/sync_sessions/revisit/offset_tab_matcher_unittest.cc188
-rw-r--r--chromium/components/sync_sessions/revisit/page_equality.h28
-rw-r--r--chromium/components/sync_sessions/revisit/page_revisit_broadcaster.cc130
-rw-r--r--chromium/components/sync_sessions/revisit/page_revisit_broadcaster.h57
-rw-r--r--chromium/components/sync_sessions/revisit/page_revisit_broadcaster_unittest.cc108
-rw-r--r--chromium/components/sync_sessions/revisit/page_visit_observer.h54
-rw-r--r--chromium/components/sync_sessions/revisit/sessions_page_revisit_observer.cc82
-rw-r--r--chromium/components/sync_sessions/revisit/sessions_page_revisit_observer.h60
-rw-r--r--chromium/components/sync_sessions/revisit/sessions_page_revisit_observer_unittest.cc195
-rw-r--r--chromium/components/sync_sessions/revisit/typed_url_page_revisit_observer.cc31
-rw-r--r--chromium/components/sync_sessions/revisit/typed_url_page_revisit_observer.h42
-rw-r--r--chromium/components/sync_sessions/revisit/typed_url_page_revisit_task.cc76
-rw-r--r--chromium/components/sync_sessions/revisit/typed_url_page_revisit_task.h63
-rw-r--r--chromium/components/sync_sessions/revisit/typed_url_page_revisit_task_unittest.cc147
-rw-r--r--chromium/components/sync_sessions/session_data_type_controller_unittest.cc30
-rw-r--r--chromium/components/sync_sessions/session_sync_test_helper.cc2
-rw-r--r--chromium/components/sync_sessions/sessions_global_id_mapper.cc122
-rw-r--r--chromium/components/sync_sessions/sessions_global_id_mapper.h40
-rw-r--r--chromium/components/sync_sessions/sessions_global_id_mapper_unittest.cc83
-rw-r--r--chromium/components/sync_sessions/sessions_sync_manager.cc514
-rw-r--r--chromium/components/sync_sessions/sessions_sync_manager.h91
-rw-r--r--chromium/components/sync_sessions/sessions_sync_manager_unittest.cc345
-rw-r--r--chromium/components/sync_sessions/sync_sessions_metrics.cc61
-rw-r--r--chromium/components/sync_sessions/sync_sessions_metrics.h42
-rw-r--r--chromium/components/sync_sessions/sync_sessions_metrics_unittest.cc209
-rw-r--r--chromium/components/sync_sessions/synced_session.cc28
-rw-r--r--chromium/components/sync_sessions/synced_session.h40
-rw-r--r--chromium/components/sync_sessions/synced_session_tracker.cc170
-rw-r--r--chromium/components/sync_sessions/synced_session_tracker.h10
-rw-r--r--chromium/components/sync_sessions/synced_session_tracker_unittest.cc13
-rw-r--r--chromium/components/sync_wifi/wifi_config_delegate_chromeos_unittest.cc3
-rw-r--r--chromium/components/sync_wifi/wifi_credential.cc6
-rw-r--r--chromium/components/sync_wifi/wifi_credential_syncable_service_factory.cc4
-rw-r--r--chromium/components/sync_wifi/wifi_credential_syncable_service_unittest.cc7
-rw-r--r--chromium/components/task_scheduler_util/browser/BUILD.gn17
-rw-r--r--chromium/components/task_scheduler_util/browser/DEPS3
-rw-r--r--chromium/components/task_scheduler_util/browser/initialization.cc40
-rw-r--r--chromium/components/task_scheduler_util/browser/initialization.h21
-rw-r--r--chromium/components/task_scheduler_util/common/BUILD.gn3
-rw-r--r--chromium/components/task_scheduler_util/common/DEPS2
-rw-r--r--chromium/components/task_scheduler_util/common/variations_util.cc105
-rw-r--r--chromium/components/task_scheduler_util/common/variations_util.h47
-rw-r--r--chromium/components/task_scheduler_util/common/variations_util_unittest.cc127
-rw-r--r--chromium/components/task_scheduler_util/renderer/BUILD.gn17
-rw-r--r--chromium/components/task_scheduler_util/renderer/initialization.cc19
-rw-r--r--chromium/components/task_scheduler_util/renderer/initialization.h22
-rw-r--r--chromium/components/timers/alarm_timer_chromeos.cc4
-rw-r--r--chromium/components/timers/alarm_timer_unittest.cc17
-rw-r--r--chromium/components/toolbar/BUILD.gn3
-rw-r--r--chromium/components/toolbar/test_toolbar_model.cc6
-rw-r--r--chromium/components/toolbar/test_toolbar_model.h3
-rw-r--r--chromium/components/toolbar/toolbar_field_trial.cc21
-rw-r--r--chromium/components/toolbar/toolbar_field_trial.h32
-rw-r--r--chromium/components/toolbar/toolbar_model.h15
-rw-r--r--chromium/components/toolbar/toolbar_model_impl.cc50
-rw-r--r--chromium/components/toolbar/toolbar_model_impl.h3
-rw-r--r--chromium/components/toolbar/vector_icons/OWNERS1
-rw-r--r--chromium/components/toolbar/vector_icons/vector_icons.cc.template6
-rw-r--r--chromium/components/tracing/common/trace_config_file.h4
-rw-r--r--chromium/components/translate/content/common/BUILD.gn2
-rw-r--r--chromium/components/translate/content/common/translate.mojom5
-rw-r--r--chromium/components/translate/core/browser/BUILD.gn1
-rw-r--r--chromium/components/translate/core/common/BUILD.gn1
-rw-r--r--chromium/components/ui_devtools/devtools_server.cc38
-rw-r--r--chromium/components/ui_devtools/views/BUILD.gn2
-rw-r--r--chromium/components/ui_devtools/views/css_agent.cc6
-rw-r--r--chromium/components/ui_devtools/views/dom_agent.cc94
-rw-r--r--chromium/components/ui_devtools/views/dom_agent.h11
-rw-r--r--chromium/components/ui_devtools/views/overlay_agent.cc4
-rw-r--r--chromium/components/ui_devtools/views/root_element.cc50
-rw-r--r--chromium/components/ui_devtools/views/root_element.h34
-rw-r--r--chromium/components/ui_devtools/views/ui_devtools_unittest.cc17
-rw-r--r--chromium/components/ui_devtools/views/ui_element.cc3
-rw-r--r--chromium/components/ui_devtools/views/ui_element.h19
-rw-r--r--chromium/components/ui_devtools/views/view_element.cc14
-rw-r--r--chromium/components/ui_devtools/views/view_element.h8
-rw-r--r--chromium/components/ui_devtools/views/widget_element.cc15
-rw-r--r--chromium/components/ui_devtools/views/widget_element.h8
-rw-r--r--chromium/components/ui_devtools/views/window_element.cc19
-rw-r--r--chromium/components/ui_devtools/views/window_element.h7
-rw-r--r--chromium/components/ukm/BUILD.gn2
-rw-r--r--chromium/components/ukm/content/BUILD.gn2
-rw-r--r--chromium/components/ukm/content/debug_page/BUILD.gn (renamed from chromium/components/ukm/debug_page/BUILD.gn)4
-rw-r--r--chromium/components/ukm/content/debug_page/debug_page.cc39
-rw-r--r--chromium/components/ukm/content/debug_page/debug_page.h (renamed from chromium/components/ukm/debug_page/debug_page.h)4
-rw-r--r--chromium/components/ukm/content/source_url_recorder.cc10
-rw-r--r--chromium/components/ukm/content/source_url_recorder.h3
-rw-r--r--chromium/components/ukm/content/source_url_recorder_browsertest.cc4
-rw-r--r--chromium/components/ukm/debug/BUILD.gn15
-rw-r--r--chromium/components/ukm/debug/ukm_debug_data_extractor.cc (renamed from chromium/components/ukm/debug_page/debug_page.cc)59
-rw-r--r--chromium/components/ukm/debug/ukm_debug_data_extractor.h34
-rw-r--r--chromium/components/ukm/debug_page/DEPS3
-rw-r--r--chromium/components/ukm/observers/sync_disable_observer.cc51
-rw-r--r--chromium/components/ukm/observers/sync_disable_observer.h28
-rw-r--r--chromium/components/ukm/test_ukm_recorder.cc2
-rw-r--r--chromium/components/ukm/test_ukm_recorder.h19
-rw-r--r--chromium/components/ukm/ukm_recorder_impl.cc165
-rw-r--r--chromium/components/ukm/ukm_recorder_impl.h60
-rw-r--r--chromium/components/ukm/ukm_reporting_service.cc4
-rw-r--r--chromium/components/ukm/ukm_service.h6
-rw-r--r--chromium/components/ukm/ukm_service_unittest.cc148
-rw-r--r--chromium/components/undo/undo_manager_test.cc5
-rw-r--r--chromium/components/unzip_service/BUILD.gn32
-rw-r--r--chromium/components/unzip_service/DEPS6
-rw-r--r--chromium/components/unzip_service/OWNERS4
-rw-r--r--chromium/components/unzip_service/manifest.json15
-rw-r--r--chromium/components/unzip_service/public/cpp/BUILD.gn18
-rw-r--r--chromium/components/unzip_service/public/cpp/unzip.cc94
-rw-r--r--chromium/components/unzip_service/public/cpp/unzip.h30
-rw-r--r--chromium/components/unzip_service/public/interfaces/BUILD.gn23
-rw-r--r--chromium/components/unzip_service/public/interfaces/OWNERS2
-rw-r--r--chromium/components/unzip_service/public/interfaces/README.md1
-rw-r--r--chromium/components/unzip_service/public/interfaces/constants.mojom7
-rw-r--r--chromium/components/unzip_service/public/interfaces/unzipper.mojom15
-rw-r--r--chromium/components/unzip_service/unzip_service.cc46
-rw-r--r--chromium/components/unzip_service/unzip_service.h39
-rw-r--r--chromium/components/unzip_service/unzipper_impl.cc107
-rw-r--r--chromium/components/unzip_service/unzipper_impl.h36
-rw-r--r--chromium/components/update_client/BUILD.gn7
-rw-r--r--chromium/components/update_client/DEPS2
-rw-r--r--chromium/components/update_client/action_runner.cc15
-rw-r--r--chromium/components/update_client/action_runner.h3
-rw-r--r--chromium/components/update_client/component.cc30
-rw-r--r--chromium/components/update_client/component.h2
-rw-r--r--chromium/components/update_client/component_patcher_operation.cc12
-rw-r--r--chromium/components/update_client/component_patcher_operation.h10
-rw-r--r--chromium/components/update_client/component_unpacker.cc25
-rw-r--r--chromium/components/update_client/component_unpacker.h11
-rw-r--r--chromium/components/update_client/component_unpacker_unittest.cc4
-rw-r--r--chromium/components/update_client/configurator.h8
-rw-r--r--chromium/components/update_client/crx_downloader.cc3
-rw-r--r--chromium/components/update_client/crx_downloader.h7
-rw-r--r--chromium/components/update_client/crx_downloader_unittest.cc112
-rw-r--r--chromium/components/update_client/ping_manager.cc93
-rw-r--r--chromium/components/update_client/ping_manager.h29
-rw-r--r--chromium/components/update_client/ping_manager_unittest.cc140
-rw-r--r--chromium/components/update_client/protocol_builder.cc68
-rw-r--r--chromium/components/update_client/protocol_builder.h14
-rw-r--r--chromium/components/update_client/protocol_builder_unittest.cc78
-rw-r--r--chromium/components/update_client/request_sender.cc21
-rw-r--r--chromium/components/update_client/request_sender.h18
-rw-r--r--chromium/components/update_client/request_sender_unittest.cc39
-rw-r--r--chromium/components/update_client/test_configurator.cc25
-rw-r--r--chromium/components/update_client/test_configurator.h9
-rw-r--r--chromium/components/update_client/update_checker.cc50
-rw-r--r--chromium/components/update_client/update_checker.h14
-rw-r--r--chromium/components/update_client/update_checker_unittest.cc261
-rw-r--r--chromium/components/update_client/update_client.cc11
-rw-r--r--chromium/components/update_client/update_client.h11
-rw-r--r--chromium/components/update_client/update_client_internal.h6
-rw-r--r--chromium/components/update_client/update_client_unittest.cc311
-rw-r--r--chromium/components/update_client/update_engine.cc25
-rw-r--r--chromium/components/update_client/update_engine.h19
-rw-r--r--chromium/components/update_client/updater_state.cc4
-rw-r--r--chromium/components/update_client/updater_state.h8
-rw-r--r--chromium/components/update_client/updater_state_unittest.cc15
-rw-r--r--chromium/components/update_client/updater_state_win.cc4
-rw-r--r--chromium/components/update_client/url_fetcher_downloader.cc5
-rw-r--r--chromium/components/update_client/url_fetcher_downloader.h7
-rw-r--r--chromium/components/update_client/url_request_post_interceptor.cc37
-rw-r--r--chromium/components/update_client/url_request_post_interceptor.h44
-rw-r--r--chromium/components/update_client/utils.cc11
-rw-r--r--chromium/components/update_client/utils.h5
-rw-r--r--chromium/components/url_formatter/OWNERS3
-rw-r--r--chromium/components/url_formatter/elide_url.cc188
-rw-r--r--chromium/components/url_formatter/elide_url.h28
-rw-r--r--chromium/components/url_formatter/elide_url_unittest.cc295
-rw-r--r--chromium/components/url_formatter/idn_spoof_checker.cc47
-rw-r--r--chromium/components/url_formatter/top_domains/test_domains.list3
-rw-r--r--chromium/components/url_formatter/top_domains/test_skeletons.gperf3
-rw-r--r--chromium/components/url_formatter/url_fixer.cc7
-rw-r--r--chromium/components/url_formatter/url_fixer_unittest.cc6
-rw-r--r--chromium/components/url_formatter/url_formatter_unittest.cc39
-rw-r--r--chromium/components/url_matcher/regex_set_matcher.cc5
-rw-r--r--chromium/components/url_matcher/url_matcher_factory.cc6
-rw-r--r--chromium/components/url_matcher/url_matcher_factory_unittest.cc13
-rw-r--r--chromium/components/url_pattern_index/BUILD.gn13
-rw-r--r--chromium/components/url_pattern_index/url_pattern.cc35
-rw-r--r--chromium/components/url_pattern_index/url_pattern_index.cc10
-rw-r--r--chromium/components/url_pattern_index/url_pattern_index.h6
-rw-r--r--chromium/components/url_pattern_index/url_pattern_index_unittest.cc18
-rw-r--r--chromium/components/url_pattern_index/url_pattern_unittest.cc12
-rw-r--r--chromium/components/url_pattern_index/url_rule_util.cc183
-rw-r--r--chromium/components/url_pattern_index/url_rule_util.h21
-rw-r--r--chromium/components/url_pattern_index/url_rule_util_unittest.cc230
-rw-r--r--chromium/components/user_manager/fake_user_manager.cc3
-rw-r--r--chromium/components/user_manager/fake_user_manager.h2
-rw-r--r--chromium/components/user_manager/known_user.cc19
-rw-r--r--chromium/components/user_manager/known_user.h20
-rw-r--r--chromium/components/user_manager/user.cc46
-rw-r--r--chromium/components/user_manager/user.h18
-rw-r--r--chromium/components/user_manager/user_manager.cc11
-rw-r--r--chromium/components/user_manager/user_manager.h2
-rw-r--r--chromium/components/user_manager/user_manager_base.cc37
-rw-r--r--chromium/components/user_manager/user_manager_base.h5
-rw-r--r--chromium/components/variations/BUILD.gn12
-rw-r--r--chromium/components/variations/DEPS1
-rw-r--r--chromium/components/variations/active_field_trials.cc6
-rw-r--r--chromium/components/variations/active_field_trials_unittest.cc14
-rw-r--r--chromium/components/variations/android/BUILD.gn1
-rw-r--r--chromium/components/variations/caching_permuted_entropy_provider.cc4
-rw-r--r--chromium/components/variations/caching_permuted_entropy_provider.h4
-rw-r--r--chromium/components/variations/caching_permuted_entropy_provider_unittest.cc4
-rw-r--r--chromium/components/variations/entropy_provider.cc13
-rw-r--r--chromium/components/variations/entropy_provider.h8
-rw-r--r--chromium/components/variations/entropy_provider_unittest.cc6
-rw-r--r--chromium/components/variations/hashing.cc (renamed from chromium/components/variations/metrics_util.cc)6
-rw-r--r--chromium/components/variations/hashing.h (renamed from chromium/components/variations/metrics_util.h)11
-rw-r--r--chromium/components/variations/hashing_unittest.cc34
-rw-r--r--chromium/components/variations/metrics.cc5
-rw-r--r--chromium/components/variations/metrics.h6
-rw-r--r--chromium/components/variations/metrics_util_unittest.cc35
-rw-r--r--chromium/components/variations/net/BUILD.gn3
-rw-r--r--chromium/components/variations/net/variations_command_line.cc51
-rw-r--r--chromium/components/variations/net/variations_command_line.h19
-rw-r--r--chromium/components/variations/net/variations_command_line_unittest.cc39
-rw-r--r--chromium/components/variations/pref_names.cc24
-rw-r--r--chromium/components/variations/pref_names.h3
-rw-r--r--chromium/components/variations/processed_study.cc33
-rw-r--r--chromium/components/variations/processed_study.h21
-rw-r--r--chromium/components/variations/proto/permuted_entropy_cache.proto2
-rw-r--r--chromium/components/variations/service/safe_seed_manager.cc97
-rw-r--r--chromium/components/variations/service/safe_seed_manager.h18
-rw-r--r--chromium/components/variations/service/safe_seed_manager_unittest.cc142
-rw-r--r--chromium/components/variations/service/variations_field_trial_creator.cc177
-rw-r--r--chromium/components/variations/service/variations_field_trial_creator.h37
-rw-r--r--chromium/components/variations/service/variations_field_trial_creator_unittest.cc285
-rw-r--r--chromium/components/variations/service/variations_service.cc34
-rw-r--r--chromium/components/variations/service/variations_service.h11
-rw-r--r--chromium/components/variations/service/variations_service_unittest.cc138
-rw-r--r--chromium/components/variations/study_filtering.cc29
-rw-r--r--chromium/components/variations/study_filtering_unittest.cc118
-rw-r--r--chromium/components/variations/synthetic_trial_registry_unittest.cc31
-rw-r--r--chromium/components/variations/variations_http_header_provider.cc76
-rw-r--r--chromium/components/variations/variations_http_header_provider.h30
-rw-r--r--chromium/components/variations/variations_http_header_provider_unittest.cc45
-rw-r--r--chromium/components/variations/variations_request_scheduler_unittest.cc2
-rw-r--r--chromium/components/variations/variations_seed_processor.cc22
-rw-r--r--chromium/components/variations/variations_seed_processor_unittest.cc20
-rw-r--r--chromium/components/variations/variations_seed_store.cc237
-rw-r--r--chromium/components/variations/variations_seed_store.h55
-rw-r--r--chromium/components/variations/variations_seed_store_unittest.cc571
-rw-r--r--chromium/components/vector_icons/README.md6
-rw-r--r--chromium/components/vector_icons/aggregate_vector_icons.py11
-rw-r--r--chromium/components/vector_icons/cc_macros.h36
-rw-r--r--chromium/components/vector_icons/vector_icons.cc.template6
-rw-r--r--chromium/components/vector_icons/vector_icons.gni4
-rw-r--r--chromium/components/version_info/BUILD.gn2
-rw-r--r--chromium/components/version_info/DEPS1
-rw-r--r--chromium/components/version_info/android/BUILD.gn73
-rw-r--r--chromium/components/version_info/android/OWNERS2
-rw-r--r--chromium/components/version_info/android/channel_getter.cc16
-rw-r--r--chromium/components/version_info/android/channel_getter.h16
-rw-r--r--chromium/components/version_info/android/java/VersionConstants.java.version17
-rw-r--r--chromium/components/version_info/channel.h12
-rw-r--r--chromium/components/version_info/channel_android.cc24
-rw-r--r--chromium/components/version_info/channel_android.h17
-rw-r--r--chromium/components/version_ui/BUILD.gn1
-rw-r--r--chromium/components/version_ui/resources/about_version.css10
-rw-r--r--chromium/components/version_ui/resources/about_version.html4
-rw-r--r--chromium/components/version_ui/resources/about_version.js11
-rw-r--r--chromium/components/version_ui/resources/about_version_mobile.css1
-rw-r--r--chromium/components/version_ui/version_handler_helper.cc6
-rw-r--r--chromium/components/version_ui/version_handler_helper.h4
-rw-r--r--chromium/components/version_ui/version_ui_constants.cc3
-rw-r--r--chromium/components/version_ui/version_ui_constants.h3
-rw-r--r--chromium/components/version_ui_strings.grdp3
-rw-r--r--chromium/components/visitedlink/browser/visitedlink_master.cc8
-rw-r--r--chromium/components/viz/DEPS2
-rw-r--r--chromium/components/viz/OWNERS1
-rw-r--r--chromium/components/viz/README.md22
-rw-r--r--chromium/components/viz/client/BUILD.gn3
-rw-r--r--chromium/components/viz/client/DEPS3
-rw-r--r--chromium/components/viz/client/client_layer_tree_frame_sink.cc38
-rw-r--r--chromium/components/viz/client/client_layer_tree_frame_sink.h8
-rw-r--r--chromium/components/viz/client/client_layer_tree_frame_sink_unittest.cc5
-rw-r--r--chromium/components/viz/client/client_shared_bitmap_manager.cc14
-rw-r--r--chromium/components/viz/client/client_shared_bitmap_manager.h3
-rw-r--r--chromium/components/viz/client/hit_test_data_provider.h4
-rw-r--r--chromium/components/viz/client/hit_test_data_provider_draw_quad.cc56
-rw-r--r--chromium/components/viz/client/hit_test_data_provider_draw_quad.h31
-rw-r--r--chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc100
-rw-r--r--chromium/components/viz/common/BUILD.gn23
-rw-r--r--chromium/components/viz/common/DEPS2
-rw-r--r--chromium/components/viz/common/constants.cc11
-rw-r--r--chromium/components/viz/common/constants.h19
-rw-r--r--chromium/components/viz/common/display/renderer_settings.h7
-rw-r--r--chromium/components/viz/common/features.cc43
-rw-r--r--chromium/components/viz/common/features.h8
-rw-r--r--chromium/components/viz/common/frame_sinks/DEPS2
-rw-r--r--chromium/components/viz/common/gl_helper_scaling.cc1
-rw-r--r--chromium/components/viz/common/gpu/DEPS2
-rw-r--r--chromium/components/viz/common/gpu/context_cache_controller_unittest.cc6
-rw-r--r--chromium/components/viz/common/gpu/raster_context_provider.h10
-rw-r--r--chromium/components/viz/common/gpu/texture_allocation.cc112
-rw-r--r--chromium/components/viz/common/gpu/texture_allocation.h65
-rw-r--r--chromium/components/viz/common/quads/DEPS2
-rw-r--r--chromium/components/viz/common/quads/compositor_frame.cc13
-rw-r--r--chromium/components/viz/common/quads/compositor_frame.h2
-rw-r--r--chromium/components/viz/common/quads/compositor_frame_metadata.h10
-rw-r--r--chromium/components/viz/common/quads/frame_deadline.h61
-rw-r--r--chromium/components/viz/common/quads/render_pass.h3
-rw-r--r--chromium/components/viz/common/resources/DEPS3
-rw-r--r--chromium/components/viz/common/resources/resource_format_utils.cc43
-rw-r--r--chromium/components/viz/common/resources/resource_format_utils.h6
-rw-r--r--chromium/components/viz/common/resources/resource_settings.h1
-rw-r--r--chromium/components/viz/common/resources/shared_bitmap_manager.h18
-rw-r--r--chromium/components/viz/common/resources/transferable_resource.h27
-rw-r--r--chromium/components/viz/common/surfaces/DEPS2
-rw-r--r--chromium/components/viz/common/surfaces/child_local_surface_id_allocator.cc45
-rw-r--r--chromium/components/viz/common/surfaces/child_local_surface_id_allocator.h51
-rw-r--r--chromium/components/viz/common/surfaces/child_local_surface_id_allocator_unittest.cc178
-rw-r--r--chromium/components/viz/common/surfaces/local_surface_id.cc7
-rw-r--r--chromium/components/viz/common/surfaces/local_surface_id.h42
-rw-r--r--chromium/components/viz/common/surfaces/local_surface_id_unittest.cc58
-rw-r--r--chromium/components/viz/common/surfaces/parent_local_surface_id_allocator.cc30
-rw-r--r--chromium/components/viz/common/surfaces/parent_local_surface_id_allocator.h24
-rw-r--r--chromium/components/viz/common/surfaces/parent_local_surface_id_allocator_unittest.cc207
-rw-r--r--chromium/components/viz/common/surfaces/sequence_surface_reference_factory.cc23
-rw-r--r--chromium/components/viz/common/surfaces/sequence_surface_reference_factory.h37
-rw-r--r--chromium/components/viz/common/surfaces/stub_surface_reference_factory.cc17
-rw-r--r--chromium/components/viz/common/surfaces/stub_surface_reference_factory.h34
-rw-r--r--chromium/components/viz/common/surfaces/surface_info.cc21
-rw-r--r--chromium/components/viz/common/surfaces/surface_info.h8
-rw-r--r--chromium/components/viz/common/surfaces/surface_reference_factory.h39
-rw-r--r--chromium/components/viz/common/surfaces/surface_reference_owner.h23
-rw-r--r--chromium/components/viz/common/surfaces/surface_sequence.h53
-rw-r--r--chromium/components/viz/common/surfaces/surface_sequence_generator.cc19
-rw-r--r--chromium/components/viz/common/surfaces/surface_sequence_generator.h41
-rw-r--r--chromium/components/viz/common/surfaces/surface_sequence_generator_unittest.cc24
-rw-r--r--chromium/components/viz/common/switches.cc41
-rw-r--r--chromium/components/viz/common/switches.h6
-rw-r--r--chromium/components/viz/host/DEPS3
-rw-r--r--chromium/components/viz/host/hit_test/DEPS2
-rw-r--r--chromium/components/viz/host/hit_test/hit_test_query.cc51
-rw-r--r--chromium/components/viz/host/hit_test/hit_test_query.h19
-rw-r--r--chromium/components/viz/host/hit_test/hit_test_query_unittest.cc237
-rw-r--r--chromium/components/viz/host/host_frame_sink_client.h2
-rw-r--r--chromium/components/viz/host/host_frame_sink_manager.cc60
-rw-r--r--chromium/components/viz/host/host_frame_sink_manager.h34
-rw-r--r--chromium/components/viz/host/host_frame_sink_manager_unittest.cc149
-rw-r--r--chromium/components/viz/host/renderer_settings_creation.cc18
-rw-r--r--chromium/components/viz/host/renderer_settings_creation.h2
-rw-r--r--chromium/components/viz/host/server_gpu_memory_buffer_manager.cc11
-rw-r--r--chromium/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc6
-rw-r--r--chromium/components/viz/presubmit_checks.py29
-rw-r--r--chromium/components/viz/service/BUILD.gn8
-rw-r--r--chromium/components/viz/service/DEPS7
-rw-r--r--chromium/components/viz/service/display/DEPS4
-rw-r--r--chromium/components/viz/service/display/bsp_tree_perftest.cc2
-rw-r--r--chromium/components/viz/service/display/direct_renderer.cc16
-rw-r--r--chromium/components/viz/service/display/direct_renderer.h4
-rw-r--r--chromium/components/viz/service/display/display.cc109
-rw-r--r--chromium/components/viz/service/display/display_perftest.cc10
-rw-r--r--chromium/components/viz/service/display/display_scheduler.cc13
-rw-r--r--chromium/components/viz/service/display/display_scheduler.h3
-rw-r--r--chromium/components/viz/service/display/display_scheduler_unittest.cc8
-rw-r--r--chromium/components/viz/service/display/display_unittest.cc278
-rw-r--r--chromium/components/viz/service/display/gl_renderer.cc200
-rw-r--r--chromium/components/viz/service/display/gl_renderer.h11
-rw-r--r--chromium/components/viz/service/display/gl_renderer_copier.cc24
-rw-r--r--chromium/components/viz/service/display/gl_renderer_copier_unittest.cc10
-rw-r--r--chromium/components/viz/service/display/gl_renderer_unittest.cc293
-rw-r--r--chromium/components/viz/service/display/overlay_unittest.cc34
-rw-r--r--chromium/components/viz/service/display/program_binding.h9
-rw-r--r--chromium/components/viz/service/display/scoped_render_pass_texture.cc22
-rw-r--r--chromium/components/viz/service/display/scoped_render_pass_texture.h4
-rw-r--r--chromium/components/viz/service/display/shader.cc12
-rw-r--r--chromium/components/viz/service/display/shader.h1
-rw-r--r--chromium/components/viz/service/display/shader_unittest.cc10
-rw-r--r--chromium/components/viz/service/display/skia_renderer.cc225
-rw-r--r--chromium/components/viz/service/display/skia_renderer.h17
-rw-r--r--chromium/components/viz/service/display/software_renderer.cc16
-rw-r--r--chromium/components/viz/service/display/software_renderer.h2
-rw-r--r--chromium/components/viz/service/display/software_renderer_unittest.cc12
-rw-r--r--chromium/components/viz/service/display/surface_aggregator.cc39
-rw-r--r--chromium/components/viz/service/display/surface_aggregator_perftest.cc13
-rw-r--r--chromium/components/viz/service/display/surface_aggregator_pixeltest.cc7
-rw-r--r--chromium/components/viz/service/display/surface_aggregator_unittest.cc532
-rw-r--r--chromium/components/viz/service/display/sync_query_collection.cc148
-rw-r--r--chromium/components/viz/service/display/sync_query_collection.h41
-rw-r--r--chromium/components/viz/service/display/texture_deleter.cc5
-rw-r--r--chromium/components/viz/service/display/texture_deleter_unittest.cc12
-rw-r--r--chromium/components/viz/service/display_embedder/DEPS23
-rw-r--r--chromium/components/viz/service/display_embedder/buffer_queue_unittest.cc32
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_mac.cc12
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_mac.h3
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_win.cc29
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_win.h35
-rw-r--r--chromium/components/viz/service/display_embedder/gpu_display_provider.cc32
-rw-r--r--chromium/components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.cc5
-rw-r--r--chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.cc68
-rw-r--r--chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.h15
-rw-r--r--chromium/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc27
-rw-r--r--chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc14
-rw-r--r--chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h5
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_device_mac.cc6
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_device_mac.h3
-rw-r--r--chromium/components/viz/service/frame_sinks/DEPS7
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc34
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.h3
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.cc176
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.h102
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc138
-rw-r--r--chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc94
-rw-r--r--chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h20
-rw-r--r--chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc149
-rw-r--r--chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.cc272
-rw-r--r--chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.h103
-rw-r--r--chromium/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc141
-rw-r--r--chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc59
-rw-r--r--chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h21
-rw-r--r--chromium/components/viz/service/frame_sinks/surface_references_unittest.cc19
-rw-r--r--chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc423
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/DEPS2
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h5
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc220
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h43
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc215
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc252
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h142
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc147
-rw-r--r--chromium/components/viz/service/frame_sinks/video_detector.h3
-rw-r--r--chromium/components/viz/service/frame_sinks/video_detector_unittest.cc14
-rw-r--r--chromium/components/viz/service/gl/DEPS2
-rw-r--r--chromium/components/viz/service/gl/gpu_service_impl.cc26
-rw-r--r--chromium/components/viz/service/hit_test/DEPS5
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator.cc14
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator.h44
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator_delegate.h4
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator_unittest.cc470
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_manager.cc17
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_manager.h11
-rw-r--r--chromium/components/viz/service/main/BUILD.gn4
-rw-r--r--chromium/components/viz/service/main/DEPS3
-rw-r--r--chromium/components/viz/service/main/viz_main_impl.cc121
-rw-r--r--chromium/components/viz/service/main/viz_main_impl.h34
-rw-r--r--chromium/components/viz/service/surfaces/DEPS7
-rw-r--r--chromium/components/viz/service/surfaces/direct_surface_reference_factory.cc31
-rw-r--r--chromium/components/viz/service/surfaces/direct_surface_reference_factory.h42
-rw-r--r--chromium/components/viz/service/surfaces/surface.cc138
-rw-r--r--chromium/components/viz/service/surfaces/surface.h48
-rw-r--r--chromium/components/viz/service/surfaces/surface_client.h3
-rw-r--r--chromium/components/viz/service/surfaces/surface_deadline_client.h2
-rw-r--r--chromium/components/viz/service/surfaces/surface_dependency_deadline.cc62
-rw-r--r--chromium/components/viz/service/surfaces/surface_dependency_deadline.h33
-rw-r--r--chromium/components/viz/service/surfaces/surface_dependency_deadline_unittest.cc132
-rw-r--r--chromium/components/viz/service/surfaces/surface_dependency_tracker.cc21
-rw-r--r--chromium/components/viz/service/surfaces/surface_dependency_tracker.h5
-rw-r--r--chromium/components/viz/service/surfaces/surface_hittest_unittest.cc18
-rw-r--r--chromium/components/viz/service/surfaces/surface_manager.cc239
-rw-r--r--chromium/components/viz/service/surfaces/surface_manager.h113
-rw-r--r--chromium/components/viz/service/surfaces/surface_observer.h11
-rw-r--r--chromium/components/viz/service/surfaces/surface_unittest.cc47
-rw-r--r--chromium/components/viz/test/BUILD.gn23
-rw-r--r--chromium/components/wallpaper/OWNERS1
-rw-r--r--chromium/components/wallpaper/wallpaper_color_calculator_unittest.cc5
-rw-r--r--chromium/components/wallpaper/wallpaper_resizer_unittest.cc3
-rw-r--r--chromium/components/web_cache/renderer/web_cache_impl.cc5
-rw-r--r--chromium/components/web_contents_delegate_android/DEPS2
-rw-r--r--chromium/components/web_contents_delegate_android/color_chooser_android.h2
-rw-r--r--chromium/components/web_contents_delegate_android/web_contents_delegate_android.cc8
-rw-r--r--chromium/components/web_contents_delegate_android/web_contents_delegate_android.h8
-rw-r--r--chromium/components/web_modal/web_contents_modal_dialog_manager.cc22
-rw-r--r--chromium/components/web_modal/web_contents_modal_dialog_manager.h11
-rw-r--r--chromium/components/web_modal/web_contents_modal_dialog_manager_unittest.cc4
-rw-r--r--chromium/components/web_resource/web_resource_service.cc4
-rw-r--r--chromium/components/web_restrictions/BUILD.gn1
-rw-r--r--chromium/components/web_restrictions/browser/web_restrictions_mojo_implementation.cc4
-rw-r--r--chromium/components/webcrypto/algorithms/aes_cbc_unittest.cc10
-rw-r--r--chromium/components/webcrypto/algorithms/aes_kw_unittest.cc5
-rw-r--r--chromium/components/webcrypto/algorithms/hmac_unittest.cc6
-rw-r--r--chromium/components/webcrypto/algorithms/sha.cc2
-rw-r--r--chromium/components/webcrypto/webcrypto_impl.cc56
-rw-r--r--chromium/components/webdata/common/web_data_request_manager.cc5
-rw-r--r--chromium/components/webdata/common/web_database_service.cc8
-rw-r--r--chromium/components/webdata_services/web_data_service_wrapper.cc28
-rw-r--r--chromium/components/webdata_services/web_data_service_wrapper.h7
-rw-r--r--chromium/components/webrtc_logging/OWNERS4
-rw-r--r--chromium/components/webrtc_logging/README.md4
-rw-r--r--chromium/components/webrtc_logging/browser/BUILD.gn35
-rw-r--r--chromium/components/webrtc_logging/browser/DEPS10
-rw-r--r--chromium/components/webrtc_logging/browser/log_cleanup.cc104
-rw-r--r--chromium/components/webrtc_logging/browser/log_cleanup.h28
-rw-r--r--chromium/components/webrtc_logging/browser/log_cleanup_unittest.cc76
-rw-r--r--chromium/components/webrtc_logging/browser/log_list.cc44
-rw-r--r--chromium/components/webrtc_logging/browser/log_list.h39
-rw-r--r--chromium/components/webrtc_logging/common/BUILD.gn30
-rw-r--r--chromium/components/webrtc_logging/common/partial_circular_buffer.cc190
-rw-r--r--chromium/components/webrtc_logging/common/partial_circular_buffer.h70
-rw-r--r--chromium/components/webrtc_logging/common/partial_circular_buffer_unittest.cc223
-rw-r--r--chromium/components/zoom/zoom_event_manager.cc5
2151 files changed, 53698 insertions, 34300 deletions
diff --git a/chromium/components/BUILD.gn b/chromium/components/BUILD.gn
index edcca1e381d..e64d5e4b1cc 100644
--- a/chromium/components/BUILD.gn
+++ b/chromium/components/BUILD.gn
@@ -6,6 +6,7 @@ import("//build/config/chrome_build.gni")
import("//build/config/features.gni")
import("//build/config/ui.gni")
import("//components/nacl/features.gni")
+import("//media/media_options.gni")
import("//printing/features/features.gni")
import("//rlz/features/features.gni")
import("//testing/test.gni")
@@ -86,6 +87,7 @@ test("components_unittests") {
"//components/favicon/core:unit_tests",
"//components/favicon_base:unit_tests",
"//components/feature_engagement:unit_tests",
+ "//components/filename_generation:unit_tests",
"//components/flags_ui:unit_tests",
"//components/gcm_driver:unit_tests",
"//components/gcm_driver/crypto:unit_tests",
@@ -97,6 +99,7 @@ test("components_unittests") {
"//components/json_schema:unit_tests",
"//components/keyed_service/core:unit_tests",
"//components/language/core/browser:unit_tests",
+ "//components/language/core/common:unit_tests",
"//components/language_usage_metrics:unit_tests",
"//components/leveldb_proto:unit_tests",
"//components/login:unit_tests",
@@ -152,6 +155,7 @@ test("components_unittests") {
"//components/url_matcher:unit_tests",
"//components/url_pattern_index:unit_tests",
"//components/variations:unit_tests",
+ "//components/variations/field_trial_config:unit_tests",
"//components/variations/service:unit_tests",
"//components/web_resource:unit_tests",
"//components/webdata/common:unit_tests",
@@ -316,6 +320,9 @@ test("components_unittests") {
if (enable_basic_printing || enable_print_preview) {
deps += [ "//components/printing/service:unit_tests" ]
}
+ if (enable_print_preview) {
+ deps += [ "//components/pwg_encoder:unit_tests" ]
+ }
if (safe_browsing_mode == 1) {
deps += [ "//components/safe_browsing/db:unit_tests_desktop" ]
@@ -323,6 +330,13 @@ test("components_unittests") {
deps += [ "//components/safe_browsing/android:unit_tests_mobile" ]
}
+ if (enable_webrtc && !is_ios) {
+ deps += [
+ "//components/webrtc_logging/browser:unit_tests",
+ "//components/webrtc_logging/common:unit_tests",
+ ]
+ }
+
# No components should depend on Chrome.
assert_no_deps = [ "//chrome/*" ]
@@ -447,13 +461,13 @@ if (!is_ios) {
"//content/test:test_support",
"//device/bluetooth",
"//device/geolocation/public/cpp:test_support",
- "//device/geolocation/public/interfaces",
+ "//google_apis",
"//ipc:test_support",
"//net:test_support",
"//printing/features",
- "//services/device/public/interfaces",
+ "//services/device/public/mojom",
"//services/service_manager/public/cpp",
- "//services/service_manager/public/interfaces",
+ "//services/service_manager/public/mojom",
"//testing/gmock",
"//testing/gtest",
"//ui/base",
@@ -476,6 +490,7 @@ if (!is_ios) {
}
if (is_android) {
+ enable_multidex = true
sources += [
"test/android/browsertests_apk/components_browser_tests_jni_onload.cc",
]
diff --git a/chromium/components/OWNERS b/chromium/components/OWNERS
index 39cf7095dfc..7a8738d601a 100644
--- a/chromium/components/OWNERS
+++ b/chromium/components/OWNERS
@@ -23,6 +23,7 @@ per-file payments_strings.grdp=file://components/payments/OWNERS
per-file pdf_strings.grdp=raymes@chromium.org
per-file physical_web_ui_strings.grdp=file://components/physical_web/OWNERS
per-file policy_strings.grdp=file://components/policy/OWNERS
+per-file printing_strings.grdp=file://components/printing/OWNERS
per-file security_interstitials_strings.grdp=file://components/security_interstitials/OWNERS
per-file security_state_strings.grdp=file://components/security_state/OWNERS
per-file ssl_errors_strings.grdp=file://components/ssl_errors/OWNERS
diff --git a/chromium/components/app_modal/javascript_dialog_manager.cc b/chromium/components/app_modal/javascript_dialog_manager.cc
index bfe42fe47e6..6e7dc9fdfbc 100644
--- a/chromium/components/app_modal/javascript_dialog_manager.cc
+++ b/chromium/components/app_modal/javascript_dialog_manager.cc
@@ -162,7 +162,7 @@ base::string16 JavaScriptDialogManager::GetTitleImpl(
void JavaScriptDialogManager::RunJavaScriptDialog(
content::WebContents* web_contents,
- const GURL& alerting_frame_url,
+ content::RenderFrameHost* render_frame_host,
content::JavaScriptDialogType dialog_type,
const base::string16& message_text,
const base::string16& default_prompt_text,
@@ -212,7 +212,8 @@ void JavaScriptDialogManager::RunJavaScriptDialog(
last_close_time_ = base::TimeTicks();
}
- base::string16 dialog_title = GetTitle(web_contents, alerting_frame_url);
+ base::string16 dialog_title =
+ GetTitle(web_contents, render_frame_host->GetLastCommittedURL());
extensions_client_->OnDialogOpened(web_contents);
diff --git a/chromium/components/app_modal/javascript_dialog_manager.h b/chromium/components/app_modal/javascript_dialog_manager.h
index e7975b27c3e..57c1cac9d4d 100644
--- a/chromium/components/app_modal/javascript_dialog_manager.h
+++ b/chromium/components/app_modal/javascript_dialog_manager.h
@@ -44,7 +44,7 @@ class JavaScriptDialogManager : public content::JavaScriptDialogManager {
// JavaScriptDialogManager:
void RunJavaScriptDialog(content::WebContents* web_contents,
- const GURL& alerting_frame_url,
+ content::RenderFrameHost* render_frame_host,
content::JavaScriptDialogType dialog_type,
const base::string16& message_text,
const base::string16& default_prompt_text,
diff --git a/chromium/components/app_modal/javascript_dialog_manager_unittest.cc b/chromium/components/app_modal/javascript_dialog_manager_unittest.cc
index eb7742466d9..4b455ce3168 100644
--- a/chromium/components/app_modal/javascript_dialog_manager_unittest.cc
+++ b/chromium/components/app_modal/javascript_dialog_manager_unittest.cc
@@ -16,99 +16,84 @@ TEST(JavaScriptDialogManagerTest, GetTitle) {
struct Case {
const char* parent_url;
const char* alerting_url;
- const char* expected_titlecase;
- const char* expected_no_titlecase;
+ const char* expected;
const char* expected_android;
} cases[] = {
// Standard main frame alert.
- {"http://foo.com/", "http://foo.com/", "From foo.com", "From foo.com",
- "From foo.com"},
+ {"http://foo.com/", "http://foo.com/", "foo.com says", "foo.com says"},
// Subframe alert from the same origin.
- {"http://foo.com/1", "http://foo.com/2", "From foo.com", "From foo.com",
- "From foo.com"},
+ {"http://foo.com/1", "http://foo.com/2", "foo.com says", "foo.com says"},
// Subframe alert from a different origin.
- {"http://foo.com/", "http://bar.com/", "From an Embedded Page at bar.com",
- "From an embedded page at bar.com", "From an embedded page at bar.com"},
+ {"http://foo.com/", "http://bar.com/", "An embedded page at bar.com says",
+ "An embedded page at bar.com says"},
// file:
// - main frame:
{"file:///path/to/page.html", "file:///path/to/page.html",
- "From This Page", "From this page", "From this page"},
+ "This page says", "This page says"},
// - subframe:
{"http://foo.com/", "file:///path/to/page.html",
- "From an Embedded Page on This Page",
- "From an embedded page on this page",
- "From an embedded page on this page"},
+ "An embedded page on this page says",
+ "An embedded page on this page says"},
// ftp:
// - main frame:
{"ftp://foo.com/path/to/page.html", "ftp://foo.com/path/to/page.html",
- "From foo.com", "From foo.com", "From ftp://foo.com"},
+ "foo.com says", "ftp://foo.com says"},
// - subframe:
{"http://foo.com/", "ftp://foo.com/path/to/page.html",
- "From an Embedded Page at foo.com", "From an embedded page at foo.com",
- "From an embedded page at ftp://foo.com"},
+ "An embedded page at foo.com says",
+ "An embedded page at ftp://foo.com says"},
// data:
// - main frame:
- {"data:blahblah", "data:blahblah", "From This Page", "From this page",
- "From this page"},
+ {"data:blahblah", "data:blahblah", "This page says", "This page says"},
// - subframe:
- {"http://foo.com/", "data:blahblah", "From an Embedded Page on This Page",
- "From an embedded page on this page",
- "From an embedded page on this page"},
+ {"http://foo.com/", "data:blahblah", "An embedded page on this page says",
+ "An embedded page on this page says"},
// javascript:
// - main frame:
- {"javascript:abc", "javascript:abc", "From This Page", "From this page",
- "From this page"},
+ {"javascript:abc", "javascript:abc", "This page says", "This page says"},
// - subframe:
{"http://foo.com/", "javascript:abc",
- "From an Embedded Page on This Page",
- "From an embedded page on this page",
- "From an embedded page on this page"},
+ "An embedded page on this page says",
+ "An embedded page on this page says"},
// about:
// - main frame:
- {"about:blank", "about:blank", "From This Page", "From this page",
- "From this page"},
+ {"about:blank", "about:blank", "This page says", "This page says"},
// - subframe:
- {"http://foo.com/", "about:blank", "From an Embedded Page on This Page",
- "From an embedded page on this page",
- "From an embedded page on this page"},
+ {"http://foo.com/", "about:blank", "An embedded page on this page says",
+ "An embedded page on this page says"},
// blob:
// - main frame:
{"blob:http://foo.com/66666666-6666-6666-6666-666666666666",
"blob:http://foo.com/66666666-6666-6666-6666-666666666666",
- "From foo.com", "From foo.com", "From foo.com"},
+ "foo.com says", "foo.com says"},
// - subframe:
{"http://bar.com/",
"blob:http://foo.com/66666666-6666-6666-6666-666666666666",
- "From an Embedded Page at foo.com", "From an embedded page at foo.com",
- "From an embedded page at foo.com"},
+ "An embedded page at foo.com says", "An embedded page at foo.com says"},
// filesystem:
// - main frame:
{"filesystem:http://foo.com/bar.html",
- "filesystem:http://foo.com/bar.html", "From foo.com", "From foo.com",
- "From foo.com"},
+ "filesystem:http://foo.com/bar.html", "foo.com says", "foo.com says"},
// - subframe:
{"http://bar.com/", "filesystem:http://foo.com/bar.html",
- "From an Embedded Page at foo.com", "From an embedded page at foo.com",
- "From an embedded page at foo.com"},
+ "An embedded page at foo.com says", "An embedded page at foo.com says"},
};
for (const auto& test_case : cases) {
base::string16 result = JavaScriptDialogManager::GetTitleImpl(
GURL(test_case.parent_url), GURL(test_case.alerting_url));
-#if defined(OS_MACOSX)
- EXPECT_EQ(test_case.expected_titlecase, base::UTF16ToUTF8(result));
-#elif defined(OS_ANDROID)
+#if defined(OS_ANDROID)
EXPECT_EQ(test_case.expected_android, base::UTF16ToUTF8(result));
#else
- EXPECT_EQ(test_case.expected_no_titlecase, base::UTF16ToUTF8(result));
+ EXPECT_EQ(test_case.expected, base::UTF16ToUTF8(result));
#endif
}
}
diff --git a/chromium/components/app_modal_strings.grdp b/chromium/components/app_modal_strings.grdp
index 1e6b4fdd689..7ffaaeb2141 100644
--- a/chromium/components/app_modal_strings.grdp
+++ b/chromium/components/app_modal_strings.grdp
@@ -2,67 +2,38 @@
<grit-part>
<!-- JavaScript Dialog Box strings -->
- <if expr="not use_titlecase">
- <message name="IDS_JAVASCRIPT_MESSAGEBOX_TITLE" desc="Title for JavaScript prompt and confirm originating from a webpage">
- From <ph name="SITE">$1<ex>http://www.google.com</ex></ph>
- </message>
- <message name="IDS_JAVASCRIPT_MESSAGEBOX_TITLE_IFRAME" desc="Title for JavaScript prompt and confirm originating from an iframe inside the webpage">
- From an embedded page at <ph name="SITE">$1<ex>http://www.google.com</ex></ph>
- </message>
- <message name="IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL" desc="Title for JavaScript prompt and confirm originating from a webpage with a non-standard URL such as |data:|">
- From this page
- </message>
- <message name="IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL_IFRAME" desc="Title for JavaScript prompt and confirm originating from an iframe inside the webpage with a non-standard URL such as |data:|">
- From an embedded page on this page
- </message>
- </if>
- <if expr="use_titlecase">
- <message name="IDS_JAVASCRIPT_MESSAGEBOX_TITLE" desc="Title for JavaScript prompt and confirm originating from a webpage">
- From <ph name="SITE">$1<ex>http://www.google.com</ex></ph>
- </message>
- <message name="IDS_JAVASCRIPT_MESSAGEBOX_TITLE_IFRAME" desc="Title for JavaScript prompt and confirm originating from an iframe inside the webpage">
- From an Embedded Page at <ph name="SITE">$1<ex>http://www.google.com</ex></ph>
- </message>
- <message name="IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL" desc="Title for JavaScript prompt and confirm originating from a webpage with a non-standard URL such as |data:|">
- From This Page
- </message>
- <message name="IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL_IFRAME" desc="Title for JavaScript prompt and confirm originating from an iframe inside the webpage with a non-standard URL such as |data:|">
- From an Embedded Page on This Page
- </message>
- </if>
+ <message name="IDS_JAVASCRIPT_MESSAGEBOX_TITLE" desc="Title for JavaScript prompt and confirm originating from a webpage">
+ <ph name="SITE">$1<ex>http://www.google.com</ex></ph> says
+ </message>
+ <message name="IDS_JAVASCRIPT_MESSAGEBOX_TITLE_IFRAME" desc="Title for JavaScript prompt and confirm originating from an iframe inside the webpage">
+ An embedded page at <ph name="SITE">$1<ex>http://www.google.com</ex></ph> says
+ </message>
+ <message name="IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL" desc="Title for JavaScript prompt and confirm originating from a webpage with a non-standard URL such as |data:|">
+ This page says
+ </message>
+ <message name="IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL_IFRAME" desc="Title for JavaScript prompt and confirm originating from an iframe inside the webpage with a non-standard URL such as |data:|">
+ An embedded page on this page says
+ </message>
+
<message name="IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION" desc="Optional UI shown on the message box, in the form of a checkbox, allowing the user to suppress additional message boxes from the page.">
Prevent this page from creating additional dialogs
</message>
<!-- "Before Unload" Dialog Box strings -->
- <if expr="not use_titlecase">
- <message name="IDS_BEFOREUNLOAD_MESSAGEBOX_TITLE" desc="Title for the 'before unload' dialog.">
- Do you want to leave this site?
- </message>
- </if>
- <if expr="use_titlecase">
- <message name="IDS_BEFOREUNLOAD_MESSAGEBOX_TITLE" desc="Title for the 'before unload' dialog.">
- Do You Want to Leave This Site?
- </message>
- </if>
- <message name="IDS_BEFOREUNLOAD_MESSAGEBOX_MESSAGE" desc="Text shown as the message of the 'before unload' dialog.">
- Changes you made may not be saved.
+ <message name="IDS_BEFOREUNLOAD_MESSAGEBOX_TITLE" desc="Title for the 'before unload' dialog.">
+ Leave site?
</message>
<message name="IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL" desc="The text on the button which navigates the user away from the page.">
Leave
</message>
+ <message name="IDS_BEFOREUNLOAD_MESSAGEBOX_MESSAGE" desc="Body text in a dialog asking the user to confirm that they want to leave or reload a website.">
+ Changes you made may not be saved.
+ </message>
<!-- "Before Reload" Dialog Box strings (same as "Before Unload" but when reloading rather than unloading the page -->
- <if expr="not use_titlecase">
- <message name="IDS_BEFORERELOAD_MESSAGEBOX_TITLE" desc="Title for the 'before unload' dialog for reloads.">
- Do you want to reload this site?
- </message>
- </if>
- <if expr="use_titlecase">
- <message name="IDS_BEFORERELOAD_MESSAGEBOX_TITLE" desc="Title for the 'before unload' dialog for reloads.">
- Do You Want to Reload This Site?
- </message>
- </if>
+ <message name="IDS_BEFORERELOAD_MESSAGEBOX_TITLE" desc="Title for the 'before unload' dialog for reloads.">
+ Reload site?
+ </message>
<message name="IDS_BEFORERELOAD_MESSAGEBOX_OK_BUTTON_LABEL" desc="The text on the button which reloads the page.">
Reload
</message>
diff --git a/chromium/components/arc/BUILD.gn b/chromium/components/arc/BUILD.gn
index bf2db2d9b44..87e09f06365 100644
--- a/chromium/components/arc/BUILD.gn
+++ b/chromium/components/arc/BUILD.gn
@@ -50,8 +50,15 @@ static_library("arc") {
"rotation_lock/arc_rotation_lock_bridge.h",
"storage_manager/arc_storage_manager.cc",
"storage_manager/arc_storage_manager.h",
+ "timer/arc_timer.cc",
+ "timer/arc_timer.h",
+ "timer/arc_timer_bridge.cc",
+ "timer/arc_timer_bridge.h",
+ "timer/create_timer_request.cc",
+ "timer/create_timer_request.h",
"usb/usb_host_bridge.cc",
"usb/usb_host_bridge.h",
+ "usb/usb_host_ui_delegate.h",
"volume_mounter/arc_volume_mounter_bridge.cc",
"volume_mounter/arc_volume_mounter_bridge.h",
]
@@ -74,6 +81,7 @@ static_library("arc") {
"//components/prefs",
"//components/session_manager/core",
"//components/signin/core/account_id",
+ "//components/timers",
"//components/url_formatter",
"//components/user_manager",
"//content/public/common",
@@ -81,10 +89,10 @@ static_library("arc") {
"//device/bluetooth",
"//device/usb",
"//device/usb/mojo",
- "//device/usb/public/interfaces",
+ "//device/usb/public/mojom",
"//google_apis",
"//mojo/edk/system",
- "//services/device/public/interfaces",
+ "//services/device/public/mojom",
"//skia",
"//third_party/re2:re2",
"//ui/aura",
@@ -190,6 +198,8 @@ static_library("arc_test_support") {
"test/fake_policy_instance.h",
"test/fake_power_instance.cc",
"test/fake_power_instance.h",
+ "test/fake_timer_instance.cc",
+ "test/fake_timer_instance.h",
"test/fake_voice_interaction_framework_instance.cc",
"test/fake_voice_interaction_framework_instance.h",
"test/fake_wallpaper_instance.cc",
@@ -231,6 +241,7 @@ source_set("unit_tests") {
"intent_helper/page_transition_util_unittest.cc",
"metrics/arc_metrics_service_unittest.cc",
"power/arc_power_bridge_unittest.cc",
+ "timer/arc_timer_bridge_unittest.cc",
]
deps = [
@@ -251,7 +262,7 @@ source_set("unit_tests") {
"//device/bluetooth",
"//mojo/public/cpp/system:system",
"//services/device/public/cpp/test:test_support",
- "//services/device/public/interfaces:interfaces",
+ "//services/device/public/mojom",
"//services/service_manager/public/cpp/test:test_support",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/components/arc/DEPS b/chromium/components/arc/DEPS
index 598dba8904a..320c49e4fe5 100644
--- a/chromium/components/arc/DEPS
+++ b/chromium/components/arc/DEPS
@@ -9,6 +9,7 @@ include_rules = [
"+components/prefs",
"+components/session_manager/core",
"+components/signin/core/account_id",
+ "+components/timers",
"+components/user_manager",
"+media/base/video_codecs.h",
"+media/video/video_encode_accelerator.h",
diff --git a/chromium/components/arc/PRESUBMIT.py b/chromium/components/arc/PRESUBMIT.py
index f85e850e212..b75e0c49205 100644
--- a/chromium/components/arc/PRESUBMIT.py
+++ b/chromium/components/arc/PRESUBMIT.py
@@ -20,21 +20,9 @@ def CheckMakeUnique(input_api, output_api):
return errors
-def CheckUniquePtr(input_api, output_api):
- # Runs CheckUniquePtr in cc/PRESUBMIT.py.
- # Probably, we'd like to promote the check to somewhere to be shared.
- presubmit_path = (
- input_api.change.RepositoryRoot() + '/cc/PRESUBMIT.py')
- presubmit_content = input_api.ReadFile(presubmit_path)
- global_vars = {}
- exec(presubmit_content, global_vars)
- return global_vars['CheckUniquePtr'](input_api, output_api)
-
-
def CheckChangeOnUpload(input_api, output_api):
results = []
results += input_api.canned_checks.CheckChangeLintsClean(
input_api, output_api)
- results += CheckUniquePtr(input_api, output_api)
results += CheckMakeUnique(input_api, output_api)
return results
diff --git a/chromium/components/arc/arc_bridge_host_impl.cc b/chromium/components/arc/arc_bridge_host_impl.cc
index eb7aaaef12f..6e2dfc09eac 100644
--- a/chromium/components/arc/arc_bridge_host_impl.cc
+++ b/chromium/components/arc/arc_bridge_host_impl.cc
@@ -233,12 +233,23 @@ void ArcBridgeHostImpl::OnRotationLockInstanceReady(
std::move(rotation_lock_ptr));
}
+void ArcBridgeHostImpl::OnScreenCaptureInstanceReady(
+ mojom::ScreenCaptureInstancePtr screen_capture_ptr) {
+ OnInstanceReady(arc_bridge_service_->screen_capture(),
+ std::move(screen_capture_ptr));
+}
+
void ArcBridgeHostImpl::OnStorageManagerInstanceReady(
mojom::StorageManagerInstancePtr storage_manager_ptr) {
OnInstanceReady(arc_bridge_service_->storage_manager(),
std::move(storage_manager_ptr));
}
+void ArcBridgeHostImpl::OnTimerInstanceReady(
+ mojom::TimerInstancePtr timer_ptr) {
+ OnInstanceReady(arc_bridge_service_->timer(), std::move(timer_ptr));
+}
+
void ArcBridgeHostImpl::OnTracingInstanceReady(
mojom::TracingInstancePtr tracing_ptr) {
OnInstanceReady(arc_bridge_service_->tracing(), std::move(tracing_ptr));
diff --git a/chromium/components/arc/arc_bridge_host_impl.h b/chromium/components/arc/arc_bridge_host_impl.h
index 0a7374a8e30..ccb7a559b90 100644
--- a/chromium/components/arc/arc_bridge_host_impl.h
+++ b/chromium/components/arc/arc_bridge_host_impl.h
@@ -82,8 +82,11 @@ class ArcBridgeHostImpl : public mojom::ArcBridgeHost {
void OnProcessInstanceReady(mojom::ProcessInstancePtr process_ptr) override;
void OnRotationLockInstanceReady(
mojom::RotationLockInstancePtr rotation_lock_ptr) override;
+ void OnScreenCaptureInstanceReady(
+ mojom::ScreenCaptureInstancePtr screen_capture_ptr) override;
void OnStorageManagerInstanceReady(
mojom::StorageManagerInstancePtr storage_manager_ptr) override;
+ void OnTimerInstanceReady(mojom::TimerInstancePtr timer_ptr) override;
void OnTracingInstanceReady(mojom::TracingInstancePtr trace_ptr) override;
void OnTtsInstanceReady(mojom::TtsInstancePtr tts_ptr) override;
void OnUsbHostInstanceReady(mojom::UsbHostInstancePtr usb_host_ptr) override;
diff --git a/chromium/components/arc/arc_bridge_service.h b/chromium/components/arc/arc_bridge_service.h
index 6cfd090c5d1..5f4232995b7 100644
--- a/chromium/components/arc/arc_bridge_service.h
+++ b/chromium/components/arc/arc_bridge_service.h
@@ -65,7 +65,11 @@ class PrintHost;
class PrintInstance;
class ProcessInstance;
class RotationLockInstance;
+class ScreenCaptureHost;
+class ScreenCaptureInstance;
class StorageManagerInstance;
+class TimerInstance;
+class TimerHost;
class TracingInstance;
class TtsHost;
class TtsInstance;
@@ -77,6 +81,7 @@ class VoiceInteractionArcHomeHost;
class VoiceInteractionArcHomeInstance;
class VoiceInteractionFrameworkHost;
class VoiceInteractionFrameworkInstance;
+class VolumeMounterHost;
class VolumeMounterInstance;
class WallpaperHost;
class WallpaperInstance;
@@ -181,9 +186,16 @@ class ArcBridgeService {
ConnectionHolder<mojom::RotationLockInstance>* rotation_lock() {
return &rotation_lock_;
}
+ ConnectionHolder<mojom::ScreenCaptureInstance, mojom::ScreenCaptureHost>*
+ screen_capture() {
+ return &screen_capture_;
+ }
ConnectionHolder<mojom::StorageManagerInstance>* storage_manager() {
return &storage_manager_;
}
+ ConnectionHolder<mojom::TimerInstance, mojom::TimerHost>* timer() {
+ return &timer_;
+ }
ConnectionHolder<mojom::TracingInstance>* tracing() { return &tracing_; }
ConnectionHolder<mojom::TtsInstance, mojom::TtsHost>* tts() { return &tts_; }
ConnectionHolder<mojom::UsbHostInstance, mojom::UsbHostHost>* usb_host() {
@@ -202,7 +214,8 @@ class ArcBridgeService {
voice_interaction_framework() {
return &voice_interaction_framework_;
}
- ConnectionHolder<mojom::VolumeMounterInstance>* volume_mounter() {
+ ConnectionHolder<mojom::VolumeMounterInstance, mojom::VolumeMounterHost>*
+ volume_mounter() {
return &volume_mounter_;
}
ConnectionHolder<mojom::WallpaperInstance, mojom::WallpaperHost>*
@@ -249,7 +262,10 @@ class ArcBridgeService {
ConnectionHolder<mojom::PrintInstance, mojom::PrintHost> print_;
ConnectionHolder<mojom::ProcessInstance> process_;
ConnectionHolder<mojom::RotationLockInstance> rotation_lock_;
+ ConnectionHolder<mojom::ScreenCaptureInstance, mojom::ScreenCaptureHost>
+ screen_capture_;
ConnectionHolder<mojom::StorageManagerInstance> storage_manager_;
+ ConnectionHolder<mojom::TimerInstance, mojom::TimerHost> timer_;
ConnectionHolder<mojom::TracingInstance> tracing_;
ConnectionHolder<mojom::TtsInstance, mojom::TtsHost> tts_;
ConnectionHolder<mojom::UsbHostInstance, mojom::UsbHostHost> usb_host_;
@@ -260,7 +276,8 @@ class ArcBridgeService {
ConnectionHolder<mojom::VoiceInteractionFrameworkInstance,
mojom::VoiceInteractionFrameworkHost>
voice_interaction_framework_;
- ConnectionHolder<mojom::VolumeMounterInstance> volume_mounter_;
+ ConnectionHolder<mojom::VolumeMounterInstance, mojom::VolumeMounterHost>
+ volume_mounter_;
ConnectionHolder<mojom::WallpaperInstance, mojom::WallpaperHost> wallpaper_;
DISALLOW_COPY_AND_ASSIGN(ArcBridgeService);
diff --git a/chromium/components/arc/arc_prefs.cc b/chromium/components/arc/arc_prefs.cc
index 5f4fc858c54..47cbeb8c060 100644
--- a/chromium/components/arc/arc_prefs.cc
+++ b/chromium/components/arc/arc_prefs.cc
@@ -34,12 +34,20 @@ const char kArcEnabled[] = "arc.enabled";
const char kArcPolicyComplianceReported[] = "arc.policy_compliance_reported";
// A preference that indicates that user accepted PlayStore terms.
const char kArcTermsAccepted[] = "arc.terms.accepted";
+// A preference that indicates that ToS was shown in OOBE flow.
+const char kArcTermsShownInOobe[] = "arc.terms.shown_in_oobe";
// A preference to keep user's consent to use location service.
const char kArcLocationServiceEnabled[] = "arc.location_service.enabled";
// A preference to keep list of Android packages and their infomation.
const char kArcPackages[] = "arc.packages";
// A preference that indicates that Play Auto Install flow was already started.
const char kArcPaiStarted[] = "arc.pai.started";
+// A preference that holds the list of apps that the admin requested to be
+// push-installed.
+const char kArcPushInstallAppsRequested[] = "arc.push_install.requested";
+// A preference that holds the list of apps that the admin requested to be
+// push-installed, but which have not been successfully installed yet.
+const char kArcPushInstallAppsPending[] = "arc.push_install.pending";
// A preference to keep deferred requests of setting notifications enabled flag.
const char kArcSetNotificationsEnabledDeferred[] =
"arc.set_notifications_enabled_deferred";
@@ -90,6 +98,7 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(kArcPolicyComplianceReported, false);
registry->RegisterBooleanPref(kArcSignedIn, false);
registry->RegisterBooleanPref(kArcTermsAccepted, false);
+ registry->RegisterBooleanPref(kArcTermsShownInOobe, false);
registry->RegisterBooleanPref(kArcVoiceInteractionValuePropAccepted, false);
registry->RegisterBooleanPref(kSmsConnectEnabled, true);
registry->RegisterBooleanPref(kVoiceInteractionContextEnabled, false);
diff --git a/chromium/components/arc/arc_prefs.h b/chromium/components/arc/arc_prefs.h
index 16c37e3aa6d..46b3bfdacd9 100644
--- a/chromium/components/arc/arc_prefs.h
+++ b/chromium/components/arc/arc_prefs.h
@@ -20,9 +20,12 @@ ARC_EXPORT extern const char kArcDataRemoveRequested[];
ARC_EXPORT extern const char kArcEnabled[];
ARC_EXPORT extern const char kArcPolicyComplianceReported[];
ARC_EXPORT extern const char kArcTermsAccepted[];
+ARC_EXPORT extern const char kArcTermsShownInOobe[];
ARC_EXPORT extern const char kArcLocationServiceEnabled[];
ARC_EXPORT extern const char kArcPackages[];
ARC_EXPORT extern const char kArcPaiStarted[];
+ARC_EXPORT extern const char kArcPushInstallAppsRequested[];
+ARC_EXPORT extern const char kArcPushInstallAppsPending[];
ARC_EXPORT extern const char kArcSetNotificationsEnabledDeferred[];
ARC_EXPORT extern const char kArcSignedIn[];
ARC_EXPORT extern const char kArcCompatibleFilesystemChosen[];
diff --git a/chromium/components/arc/arc_session.h b/chromium/components/arc/arc_session.h
index 6e303c93e75..d0d680e0cf0 100644
--- a/chromium/components/arc/arc_session.h
+++ b/chromium/components/arc/arc_session.h
@@ -9,8 +9,6 @@
#include "base/macros.h"
#include "base/observer_list.h"
-#include "base/optional.h"
-#include "components/arc/arc_instance_mode.h"
#include "components/arc/arc_stop_reason.h"
namespace arc {
@@ -20,20 +18,21 @@ class ArcBridgeService;
// Starts the ARC instance and bootstraps the bridge connection.
// Clients should implement the Delegate to be notified upon communications
// being available.
-// The instance can be safely removed 1) before Start() is called, or 2) after
-// OnSessionStopped() is called.
-// The number of instances must be at most one. Otherwise, ARC instances will
-// conflict.
+// The instance can be safely removed before StartMiniInstance() is called, or
+// after OnSessionStopped() is called. The number of instances must be at most
+// one. Otherwise, ARC instances will conflict.
class ArcSession {
public:
// Observer to notify events corresponding to one ARC session run.
class Observer {
public:
- // Called when ARC instance is stopped. This is called exactly once
- // per instance which is Start()ed.
- // |was_running| is true, if the stopped instance was fully set up
- // and running.
- virtual void OnSessionStopped(ArcStopReason reason, bool was_running) = 0;
+ // Called when ARC instance is stopped. This is called exactly once per
+ // instance. |was_running| is true if the stopped instance was fully set up
+ // and running. |full_requested| is true if the full container was
+ // requested.
+ virtual void OnSessionStopped(ArcStopReason reason,
+ bool was_running,
+ bool full_requested) = 0;
protected:
virtual ~Observer() = default;
@@ -44,21 +43,18 @@ class ArcSession {
ArcBridgeService* arc_bridge_service);
virtual ~ArcSession();
- // Starts an instance in the |request_mode|. Start(FULL_INSTANCE) should
- // not be called twice or more. When Start(MINI_INSTANCE) was called then
- // Start(FULL_INSTANCE) is called, it upgrades the mini instance to a full
- // instance.
- virtual void Start(ArcInstanceMode request_mode) = 0;
+ // Sends D-Bus message to start a mini-container.
+ virtual void StartMiniInstance() = 0;
+
+ // Sends a D-Bus message to upgrade to a full instance if
+ // possible. This might be done asynchronously; the message might only be sent
+ // after other operations have completed.
+ virtual void RequestUpgrade() = 0;
// Requests to stop the currently-running instance regardless of its mode.
// The completion is notified via OnSessionStopped() of the Observer.
virtual void Stop() = 0;
- // Returns the current target mode, in which eventually this instance is
- // running.
- // If the instance is not yet started, this returns nullopt.
- virtual base::Optional<ArcInstanceMode> GetTargetMode() = 0;
-
// Returns true if Stop() has been called already.
virtual bool IsStopRequested() = 0;
diff --git a/chromium/components/arc/arc_session_impl.cc b/chromium/components/arc/arc_session_impl.cc
index d26d61b51c6..a2d4370ae44 100644
--- a/chromium/components/arc/arc_session_impl.cc
+++ b/chromium/components/arc/arc_session_impl.cc
@@ -267,109 +267,56 @@ ArcSessionImpl::~ArcSessionImpl() {
client->RemoveObserver(this);
}
-void ArcSessionImpl::Start(ArcInstanceMode request_mode) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
- target_mode_ = request_mode;
- switch (request_mode) {
- case ArcInstanceMode::MINI_INSTANCE:
- StartMiniInstance();
- return;
- case ArcInstanceMode::FULL_INSTANCE:
- StartFullInstance();
- return;
- }
-
- NOTREACHED();
-}
-
void ArcSessionImpl::StartMiniInstance() {
- DCHECK_EQ(State::NOT_STARTED, state_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK_EQ(state_, State::NOT_STARTED);
- VLOG(2) << "Starting ARC mini instance";
state_ = State::STARTING_MINI_INSTANCE;
- SendStartArcInstanceDBusMessage(
- target_mode_.value(),
- base::BindOnce(&ArcSessionImpl::OnMiniInstanceStarted,
- weak_factory_.GetWeakPtr()));
+ VLOG(2) << "Starting ARC mini instance";
+ login_manager::StartArcInstanceRequest request;
+ request.set_native_bridge_experiment(
+ base::FeatureList::IsEnabled(arc::kNativeBridgeExperimentFeature));
+ request.set_for_login_screen(true);
+
+ chromeos::SessionManagerClient* client = GetSessionManagerClient();
+ client->StartArcInstance(
+ request, base::BindOnce(&ArcSessionImpl::OnMiniInstanceStarted,
+ weak_factory_.GetWeakPtr()));
}
-void ArcSessionImpl::OnMiniInstanceStarted(
- chromeos::SessionManagerClient::StartArcInstanceResult result,
- const std::string& container_instance_id,
- base::ScopedFD socket_fd) {
+void ArcSessionImpl::RequestUpgrade() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK_EQ(state_, State::STARTING_MINI_INSTANCE);
-
- if (result != StartArcInstanceResult::SUCCESS) {
- LOG(ERROR) << "Failed to start ARC instance";
- OnStopped(GetArcStopReason(result, stop_requested_));
- return;
- }
-
- DCHECK(!container_instance_id.empty());
- container_instance_id_ = container_instance_id;
- VLOG(2) << "ARC mini instance is successfully started: "
- << container_instance_id_;
-
- if (stop_requested_) {
- // The ARC instance has started to run. Request to stop.
- StopArcInstance();
- return;
- }
- state_ = State::RUNNING_MINI_INSTANCE;
+ upgrade_requested_ = true;
- if (target_mode_ == ArcInstanceMode::FULL_INSTANCE) {
- // Start(FULL_INSTANCE) has been called during the D-Bus call.
- StartFullInstance();
- }
-}
-
-void ArcSessionImpl::StartFullInstance() {
- // StartFullInstance() can be called either for starting ARC from scratch or
- // for upgrading to an existing one. StartFullInstance() must be able to
- // start a fully functional instance from all of |state_| up to and including
- // RUNNING_MINI_INSTANCE.
switch (state_) {
case State::NOT_STARTED:
- // A mini instance does not exist. Start a new one from scratch.
- VLOG(2) << "Starting ARC session";
- state_ = State::STARTING_FULL_INSTANCE;
- SendStartArcInstanceDBusMessage(
- target_mode_.value(),
- base::BindOnce(&ArcSessionImpl::OnFullInstanceStarted,
- weak_factory_.GetWeakPtr()));
+ NOTREACHED();
break;
case State::STARTING_MINI_INSTANCE:
VLOG(2) << "Requested to upgrade a starting ARC mini instance";
// OnMiniInstanceStarted() will restart a full instance.
break;
case State::RUNNING_MINI_INSTANCE:
- VLOG(2) << "Upgrading an existing ARC mini instance";
- state_ = State::STARTING_FULL_INSTANCE;
- SendStartArcInstanceDBusMessage(
- target_mode_.value(),
- base::BindOnce(&ArcSessionImpl::OnFullInstanceStarted,
- weak_factory_.GetWeakPtr()));
+ DoUpgrade();
break;
case State::STARTING_FULL_INSTANCE:
case State::CONNECTING_MOJO:
case State::RUNNING_FULL_INSTANCE:
case State::STOPPED:
- // These mean Start(FULL_INSTANCE) is called twice or called after
+ // These mean RequestUpgrade() is called twice or called after
// stopped, which are invalid operations.
NOTREACHED();
break;
}
}
-void ArcSessionImpl::OnFullInstanceStarted(
+void ArcSessionImpl::OnMiniInstanceStarted(
chromeos::SessionManagerClient::StartArcInstanceResult result,
const std::string& container_instance_id,
base::ScopedFD socket_fd) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK_EQ(state_, State::STARTING_FULL_INSTANCE);
+ DCHECK_EQ(state_, State::STARTING_MINI_INSTANCE);
if (result != StartArcInstanceResult::SUCCESS) {
LOG(ERROR) << "Failed to start ARC instance";
@@ -377,16 +324,10 @@ void ArcSessionImpl::OnFullInstanceStarted(
return;
}
- if (container_instance_id.empty()) {
- // This was upgrade request.
- VLOG(2) << "ARC instance is successfully upgraded.";
- DCHECK(!container_instance_id_.empty());
- } else {
- // This was a request to start a full instance from scratch.
- container_instance_id_ = container_instance_id;
- VLOG(2) << "ARC instance is successfully started: "
- << container_instance_id_;
- }
+ DCHECK(!container_instance_id.empty());
+ container_instance_id_ = container_instance_id;
+ VLOG(2) << "ARC mini instance is successfully started: "
+ << container_instance_id_;
if (stop_requested_) {
// The ARC instance has started to run. Request to stop.
@@ -394,46 +335,34 @@ void ArcSessionImpl::OnFullInstanceStarted(
return;
}
- VLOG(2) << "Connecting mojo...";
- state_ = State::CONNECTING_MOJO;
- accept_cancel_pipe_ = delegate_->ConnectMojo(
- std::move(socket_fd), base::BindOnce(&ArcSessionImpl::OnMojoConnected,
- weak_factory_.GetWeakPtr()));
- if (!accept_cancel_pipe_.is_valid()) {
- // Failed to post a task to accept() the request.
- StopArcInstance();
- return;
- }
+ state_ = State::RUNNING_MINI_INSTANCE;
+
+ if (upgrade_requested_)
+ // RequestUpgrade() has been called during the D-Bus call.
+ DoUpgrade();
}
-// static
-void ArcSessionImpl::SendStartArcInstanceDBusMessage(
- ArcInstanceMode target_mode,
- chromeos::SessionManagerClient::StartArcInstanceCallback callback) {
- chromeos::SessionManagerClient* session_manager_client =
- chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
+void ArcSessionImpl::DoUpgrade() {
+ DCHECK_EQ(state_, State::RUNNING_MINI_INSTANCE);
+
+ VLOG(2) << "Upgrading an existing ARC mini instance";
+ state_ = State::STARTING_FULL_INSTANCE;
login_manager::StartArcInstanceRequest request;
request.set_native_bridge_experiment(
base::FeatureList::IsEnabled(arc::kNativeBridgeExperimentFeature));
-
- if (target_mode == ArcInstanceMode::MINI_INSTANCE) {
- request.set_for_login_screen(true);
- session_manager_client->StartArcInstance(request, std::move(callback));
- return;
- }
- DCHECK_EQ(ArcInstanceMode::FULL_INSTANCE, target_mode);
-
user_manager::UserManager* user_manager = user_manager::UserManager::Get();
DCHECK(user_manager->GetPrimaryUser());
+
request.set_account_id(
cryptohome::Identification(user_manager->GetPrimaryUser()->GetAccountId())
.id());
request.set_skip_boot_completed_broadcast(
!base::FeatureList::IsEnabled(arc::kBootCompletedBroadcastFeature));
- // We only enable /vendor/priv-app when voice interaction is enabled because
- // voice interaction service apk would be bundled in this location.
+ // We only enable /vendor/priv-app when voice interaction is enabled
+ // because voice interaction service apk would be bundled in this
+ // location.
request.set_scan_vendor_priv_app(
chromeos::switches::IsVoiceInteractionEnabled());
@@ -453,7 +382,42 @@ void ArcSessionImpl::SendStartArcInstanceDBusMessage(
<< packages_cache_mode_string << ".";
}
- session_manager_client->StartArcInstance(request, std::move(callback));
+ chromeos::SessionManagerClient* client = GetSessionManagerClient();
+ client->StartArcInstance(request, base::BindOnce(&ArcSessionImpl::OnUpgraded,
+ weak_factory_.GetWeakPtr()));
+}
+
+void ArcSessionImpl::OnUpgraded(
+ chromeos::SessionManagerClient::StartArcInstanceResult result,
+ const std::string& container_instance_id, // unused
+ base::ScopedFD socket_fd) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK_EQ(state_, State::STARTING_FULL_INSTANCE);
+
+ if (result != StartArcInstanceResult::SUCCESS) {
+ LOG(ERROR) << "Failed to start ARC instance";
+ OnStopped(GetArcStopReason(result, stop_requested_));
+ return;
+ }
+
+ VLOG(2) << "ARC instance is successfully upgraded.";
+
+ if (stop_requested_) {
+ // The ARC instance has started to run. Request to stop.
+ StopArcInstance();
+ return;
+ }
+
+ VLOG(2) << "Connecting mojo...";
+ state_ = State::CONNECTING_MOJO;
+ accept_cancel_pipe_ = delegate_->ConnectMojo(
+ std::move(socket_fd), base::BindOnce(&ArcSessionImpl::OnMojoConnected,
+ weak_factory_.GetWeakPtr()));
+ if (!accept_cancel_pipe_.is_valid()) {
+ // Failed to post a task to accept() the request.
+ StopArcInstance();
+ return;
+ }
}
void ArcSessionImpl::OnMojoConnected(
@@ -493,7 +457,6 @@ void ArcSessionImpl::Stop() {
case State::NOT_STARTED:
OnStopped(ArcStopReason::SHUTDOWN);
return;
-
case State::STARTING_MINI_INSTANCE:
case State::STARTING_FULL_INSTANCE:
// Before starting the ARC instance, we do nothing here.
@@ -537,12 +500,10 @@ void ArcSessionImpl::StopArcInstance() {
// When the instance is full instance, change the |state_| in
// ArcInstanceStopped().
- chromeos::SessionManagerClient* session_manager_client =
- chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
+ chromeos::SessionManagerClient* client = GetSessionManagerClient();
// Since we have the ArcInstanceStopped() callback, we don't need to do
// anything when StopArcInstance completes.
- session_manager_client->StopArcInstance(
- chromeos::EmptyVoidDBusMethodCallback());
+ client->StopArcInstance(chromeos::EmptyVoidDBusMethodCallback());
}
void ArcSessionImpl::ArcInstanceStopped(
@@ -582,10 +543,6 @@ void ArcSessionImpl::ArcInstanceStopped(
OnStopped(reason);
}
-base::Optional<ArcInstanceMode> ArcSessionImpl::GetTargetMode() {
- return target_mode_;
-}
-
bool ArcSessionImpl::IsStopRequested() {
return stop_requested_;
}
@@ -599,7 +556,7 @@ void ArcSessionImpl::OnStopped(ArcStopReason reason) {
arc_bridge_host_.reset();
state_ = State::STOPPED;
for (auto& observer : observer_list_)
- observer.OnSessionStopped(reason, was_running);
+ observer.OnSessionStopped(reason, was_running, upgrade_requested_);
}
void ArcSessionImpl::OnShutdown() {
diff --git a/chromium/components/arc/arc_session_impl.h b/chromium/components/arc/arc_session_impl.h
index 1a17a1de2cf..2099a880708 100644
--- a/chromium/components/arc/arc_session_impl.h
+++ b/chromium/components/arc/arc_session_impl.h
@@ -13,10 +13,8 @@
#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/dbus/session_manager_client.h"
-#include "components/arc/arc_instance_mode.h"
#include "components/arc/arc_session.h"
namespace arc {
@@ -30,29 +28,19 @@ class ArcSessionImpl : public ArcSession,
public:
// The possible states of the session. Expected state changes are as follows.
//
- // 1) Starting MINI_INSTANCE.
// NOT_STARTED
- // -> StartMiniInstance() ->
+ // -> StartMiniInstance() ->
// STARTING_MINI_INSTANCE
// -> OnMiniInstanceStarted() ->
// RUNNING_MINI_INSTANCE.
- //
- // 2) Starting FULL_INSTANCE.
- // NOT_STARTED
- // -> StartFullInstance() ->
+ // -> RequestUpgrade() ->
// STARTING_FULL_INSTANCE
- // -> OnFullInstanceStarted() ->
+ // -> OnUpgraded() ->
// CONNECTING_MOJO
// -> OnMojoConnected() ->
// RUNNING_FULL_INSTANCE
//
- // 3) Upgrading from a MINI_INSTANCE to FULL_INSTANCE.
- // RUNNING_MINI_INSTANCE
- // -> StartFullInstance() ->
- // STARTING_FULL_INSTANCE
- // -> ... (remaining is as same as (2)).
- //
- // Note that, if Start(FULL_INSTANCE) is called during STARTING_MINI_INSTANCE
+ // Note that, if RequestUpgrade() is called during STARTING_MINI_INSTANCE
// state, the state change to STARTING_FULL_INSTANCE is suspended until
// the state becomes RUNNING_MINI_INSTANCE.
//
@@ -108,7 +96,7 @@ class ArcSessionImpl : public ArcSession,
// arcbridgeservice (i.e. mojo endpoint) are running.
RUNNING_MINI_INSTANCE,
- // The request to start or upgrade to a full instance has been sent.
+ // The request to upgrade to a full instance has been sent.
STARTING_FULL_INSTANCE,
// The instance has started. Waiting for it to connect to the IPC bridge.
@@ -150,16 +138,13 @@ class ArcSessionImpl : public ArcSession,
State GetStateForTesting() { return state_; }
// ArcSession overrides:
- void Start(ArcInstanceMode request_mode) override;
+ void StartMiniInstance() override;
+ void RequestUpgrade() override;
void Stop() override;
- base::Optional<ArcInstanceMode> GetTargetMode() override;
bool IsStopRequested() override;
void OnShutdown() override;
private:
- // Sends a D-Bus message to start a mini instance.
- void StartMiniInstance();
-
// D-Bus callback for StartArcInstance() for a mini instance.
// In case of success, |container_instance_id| must not be empty, and
// |socket_fd| is /dev/null.
@@ -169,19 +154,15 @@ class ArcSessionImpl : public ArcSession,
const std::string& container_instance_id,
base::ScopedFD socket_fd);
- // Sends a D-Bus message to start or to upgrade to a full instance.
- void StartFullInstance();
+ // Sends a D-Bus message to upgrade to a full instance.
+ void DoUpgrade();
- // D-Bus callback for StartArcInstance() for a full instance.
- // In case of success, |container_instance_id| must not be empty, if this is
- // actually starting an instance, or empty if this is upgrade from a mini
- // instance to a full instance.
- // In either start or upgrade case, |socket_fd| should be a socket which
- // shold be accept(2)ed to connect ArcBridgeService Mojo channel.
- void OnFullInstanceStarted(
- chromeos::SessionManagerClient::StartArcInstanceResult result,
- const std::string& container_instance_id,
- base::ScopedFD socket_fd);
+ // D-Bus callback for StartArcInstance() for an upgrade. |socket_fd| should be
+ // a socket which should be accept(2)ed to connect ArcBridgeService Mojo
+ // channel.
+ void OnUpgraded(chromeos::SessionManagerClient::StartArcInstanceResult result,
+ const std::string& container_instance_id, // unused
+ base::ScopedFD socket_fd);
// Called when Mojo connection is established (or canceled during the
// connect.)
@@ -198,11 +179,6 @@ class ArcSessionImpl : public ArcSession,
// deleting |this| because the function calls observers' OnSessionStopped().
void OnStopped(ArcStopReason reason);
- // Sends a StartArcInstance D-Bus request to session_manager.
- static void SendStartArcInstanceDBusMessage(
- ArcInstanceMode target_mode,
- chromeos::SessionManagerClient::StartArcInstanceCallback callback);
-
// Checks whether a function runs on the thread where the instance is
// created.
THREAD_CHECKER(thread_checker_);
@@ -216,9 +192,8 @@ class ArcSessionImpl : public ArcSession,
// When Stop() is called, this flag is set.
bool stop_requested_ = false;
- // In which mode this instance should be running eventually.
- // Initialized in nullopt.
- base::Optional<ArcInstanceMode> target_mode_;
+ // Whether the full container has been requested
+ bool upgrade_requested_ = false;
// Container instance id passed from session_manager.
// Should be available only after On{Mini,Full}InstanceStarted().
diff --git a/chromium/components/arc/arc_session_impl_unittest.cc b/chromium/components/arc/arc_session_impl_unittest.cc
index 4291d7f0076..0347834782b 100644
--- a/chromium/components/arc/arc_session_impl_unittest.cc
+++ b/chromium/components/arc/arc_session_impl_unittest.cc
@@ -87,6 +87,7 @@ class TestArcSessionObserver : public ArcSession::Observer {
struct OnSessionStoppedArgs {
ArcStopReason reason;
bool was_running;
+ bool full_requested;
};
explicit TestArcSessionObserver(ArcSession* arc_session)
@@ -101,8 +102,11 @@ class TestArcSessionObserver : public ArcSession::Observer {
}
// ArcSession::Observer overrides:
- void OnSessionStopped(ArcStopReason reason, bool was_running) override {
- on_session_stopped_args_.emplace(OnSessionStoppedArgs{reason, was_running});
+ void OnSessionStopped(ArcStopReason reason,
+ bool was_running,
+ bool full_requested) override {
+ on_session_stopped_args_.emplace(
+ OnSessionStoppedArgs{reason, was_running, full_requested});
}
private:
@@ -168,7 +172,7 @@ class ArcSessionImplTest : public testing::Test {
void SetupMiniContainer(ArcSessionImpl* arc_session,
TestArcSessionObserver* observer) {
- arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ arc_session->StartMiniInstance();
base::RunLoop().RunUntilIdle();
ASSERT_EQ(ArcSessionImpl::State::RUNNING_MINI_INSTANCE,
arc_session->GetStateForTesting());
@@ -183,74 +187,11 @@ class ArcSessionImplTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(ArcSessionImplTest);
};
-// Simple case. Starting FULL_INSTANCE will eventually start the container.
-TEST_F(ArcSessionImplTest, FullInstance_Success) {
- auto arc_session = CreateArcSession();
- TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
- base::RunLoop().RunUntilIdle();
-
- EXPECT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
- arc_session->GetStateForTesting());
- EXPECT_FALSE(observer.on_session_stopped_args().has_value());
-}
-
-// SessionManagerClient::StartArcInstance() reports an error, so that
-// the container fails to start.
-TEST_F(ArcSessionImplTest, FullInstance_DBusFail) {
- EmulateDBusFailure();
-
- auto arc_session = CreateArcSession();
- TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
- base::RunLoop().RunUntilIdle();
-
- EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
- ASSERT_TRUE(observer.on_session_stopped_args().has_value());
- EXPECT_EQ(ArcStopReason::GENERIC_BOOT_FAILURE,
- observer.on_session_stopped_args()->reason);
- EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
-}
-
-// SessionManagerClient::StartArcInstance() fails due to low disk, so that
-// the container fails to start with reporting LOW_DISK_SPACE.
-TEST_F(ArcSessionImplTest, FullInstance_LowDisk) {
- GetSessionManagerClient()->set_low_disk(true);
-
- auto arc_session = CreateArcSession();
- TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
- base::RunLoop().RunUntilIdle();
-
- EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
- ASSERT_TRUE(observer.on_session_stopped_args().has_value());
- EXPECT_EQ(ArcStopReason::LOW_DISK_SPACE,
- observer.on_session_stopped_args()->reason);
- EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
-}
-
-// Mojo connection fails, so that the container fails to start.
-TEST_F(ArcSessionImplTest, FullInstance_MojoConnectionFail) {
- auto delegate = std::make_unique<FakeDelegate>();
- delegate->EmulateMojoConnectionFailure();
-
- auto arc_session = CreateArcSession(std::move(delegate));
- TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
- base::RunLoop().RunUntilIdle();
-
- EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
- ASSERT_TRUE(observer.on_session_stopped_args().has_value());
- EXPECT_EQ(ArcStopReason::GENERIC_BOOT_FAILURE,
- observer.on_session_stopped_args()->reason);
- EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
-}
-
// Starting mini container success case.
TEST_F(ArcSessionImplTest, MiniInstance_Success) {
auto arc_session = CreateArcSession();
TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ arc_session->StartMiniInstance();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(ArcSessionImpl::State::RUNNING_MINI_INSTANCE,
@@ -265,7 +206,7 @@ TEST_F(ArcSessionImplTest, MiniInstance_DBusFail) {
auto arc_session = CreateArcSession();
TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ arc_session->StartMiniInstance();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
@@ -273,6 +214,7 @@ TEST_F(ArcSessionImplTest, MiniInstance_DBusFail) {
EXPECT_EQ(ArcStopReason::GENERIC_BOOT_FAILURE,
observer.on_session_stopped_args()->reason);
EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+ EXPECT_FALSE(observer.on_session_stopped_args()->full_requested);
}
// SessionManagerClient::StartArcInstance() reports an error due to low disk,
@@ -283,7 +225,7 @@ TEST_F(ArcSessionImplTest, MiniInstance_LowDisk) {
auto arc_session = CreateArcSession();
TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ arc_session->StartMiniInstance();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
@@ -291,6 +233,7 @@ TEST_F(ArcSessionImplTest, MiniInstance_LowDisk) {
EXPECT_EQ(ArcStopReason::LOW_DISK_SPACE,
observer.on_session_stopped_args()->reason);
EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+ EXPECT_FALSE(observer.on_session_stopped_args()->full_requested);
}
// Upgrading a mini container to a full container. Success case.
@@ -301,7 +244,7 @@ TEST_F(ArcSessionImplTest, Upgrade_Success) {
ASSERT_NO_FATAL_FAILURE(SetupMiniContainer(arc_session.get(), &observer));
// Then, upgrade to a full instance.
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ arc_session->RequestUpgrade();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
@@ -321,7 +264,7 @@ TEST_F(ArcSessionImplTest, Upgrade_DBusFail) {
EmulateDBusFailure();
// Then upgrade, which should fail.
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ arc_session->RequestUpgrade();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
@@ -329,6 +272,7 @@ TEST_F(ArcSessionImplTest, Upgrade_DBusFail) {
EXPECT_EQ(ArcStopReason::GENERIC_BOOT_FAILURE,
observer.on_session_stopped_args()->reason);
EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+ EXPECT_TRUE(observer.on_session_stopped_args()->full_requested);
}
// Mojo connection fails on upgrading. Then, the upgrade fails.
@@ -345,7 +289,7 @@ TEST_F(ArcSessionImplTest, Upgrade_MojoConnectionFail) {
ASSERT_NO_FATAL_FAILURE(SetupMiniContainer(arc_session.get(), &observer));
// Upgrade should fail, due to Mojo connection fail set above.
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ arc_session->RequestUpgrade();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
@@ -353,6 +297,7 @@ TEST_F(ArcSessionImplTest, Upgrade_MojoConnectionFail) {
EXPECT_EQ(ArcStopReason::GENERIC_BOOT_FAILURE,
observer.on_session_stopped_args()->reason);
EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+ EXPECT_TRUE(observer.on_session_stopped_args()->full_requested);
}
// Calling StartArcInstance() during STARTING_MINI_INSTANCE should eventually
@@ -360,12 +305,12 @@ TEST_F(ArcSessionImplTest, Upgrade_MojoConnectionFail) {
TEST_F(ArcSessionImplTest, Upgrade_StartingMiniInstance) {
auto arc_session = CreateArcSession();
TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ arc_session->StartMiniInstance();
ASSERT_EQ(ArcSessionImpl::State::STARTING_MINI_INSTANCE,
arc_session->GetStateForTesting());
// Before moving forward to RUNNING_MINI_INSTANCE, start upgrading it.
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ arc_session->RequestUpgrade();
// The state should not immediately switch to STARTING_FULL_INSTANCE, yet.
EXPECT_EQ(ArcSessionImpl::State::STARTING_MINI_INSTANCE,
@@ -383,7 +328,7 @@ TEST_F(ArcSessionImplTest, Upgrade_StartingMiniInstance) {
TEST_F(ArcSessionImplTest, Stop_StartingMiniInstance) {
auto arc_session = CreateArcSession();
TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ arc_session->StartMiniInstance();
ASSERT_EQ(ArcSessionImpl::State::STARTING_MINI_INSTANCE,
arc_session->GetStateForTesting());
@@ -395,13 +340,14 @@ TEST_F(ArcSessionImplTest, Stop_StartingMiniInstance) {
EXPECT_EQ(ArcStopReason::SHUTDOWN,
observer.on_session_stopped_args()->reason);
EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+ EXPECT_FALSE(observer.on_session_stopped_args()->full_requested);
}
// Testing stop during RUNNING_MINI_INSTANCE.
TEST_F(ArcSessionImplTest, Stop_RunningMiniInstance) {
auto arc_session = CreateArcSession();
TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ arc_session->StartMiniInstance();
base::RunLoop().RunUntilIdle();
ASSERT_EQ(ArcSessionImpl::State::RUNNING_MINI_INSTANCE,
arc_session->GetStateForTesting());
@@ -414,67 +360,7 @@ TEST_F(ArcSessionImplTest, Stop_RunningMiniInstance) {
EXPECT_EQ(ArcStopReason::SHUTDOWN,
observer.on_session_stopped_args()->reason);
EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
-}
-
-// Testing stop during STARTING_FULL_INSTANCE.
-TEST_F(ArcSessionImplTest, Stop_StartingFullInstance) {
- auto arc_session = CreateArcSession();
- TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
- ASSERT_EQ(ArcSessionImpl::State::STARTING_FULL_INSTANCE,
- arc_session->GetStateForTesting());
-
- arc_session->Stop();
- base::RunLoop().RunUntilIdle();
-
- 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_FALSE(observer.on_session_stopped_args()->was_running);
-}
-
-// Testing stop during CONNECTING_MOJO.
-TEST_F(ArcSessionImplTest, Stop_ConnectingMojo) {
- // Let Mojo connection suspend.
- auto delegate = std::make_unique<FakeDelegate>();
- delegate->SuspendMojoConnection();
- auto* delegate_ptr = delegate.get();
- auto arc_session = CreateArcSession(std::move(delegate));
- TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(ArcSessionImpl::State::CONNECTING_MOJO,
- arc_session->GetStateForTesting());
-
- arc_session->Stop();
- delegate_ptr->ResumeMojoConnection();
- base::RunLoop().RunUntilIdle();
-
- 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_FALSE(observer.on_session_stopped_args()->was_running);
-}
-
-// Testing stop during RUNNING_FULL_INSTANCE.
-TEST_F(ArcSessionImplTest, Stop_RunningFullInstance) {
- auto arc_session = CreateArcSession();
- TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
- arc_session->GetStateForTesting());
-
- arc_session->Stop();
- base::RunLoop().RunUntilIdle();
-
- 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_FALSE(observer.on_session_stopped_args()->full_requested);
}
// Testing stop during STARTING_FULL_INSTANCE for upgrade.
@@ -485,7 +371,7 @@ TEST_F(ArcSessionImplTest, Stop_StartingFullInstanceForUpgrade) {
ASSERT_NO_FATAL_FAILURE(SetupMiniContainer(arc_session.get(), &observer));
// Then upgrade.
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ arc_session->RequestUpgrade();
ASSERT_EQ(ArcSessionImpl::State::STARTING_FULL_INSTANCE,
arc_session->GetStateForTesting());
@@ -498,6 +384,7 @@ TEST_F(ArcSessionImplTest, Stop_StartingFullInstanceForUpgrade) {
EXPECT_EQ(ArcStopReason::SHUTDOWN,
observer.on_session_stopped_args()->reason);
EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+ EXPECT_TRUE(observer.on_session_stopped_args()->full_requested);
}
// Testing stop during CONNECTING_MOJO for upgrade.
@@ -512,7 +399,7 @@ TEST_F(ArcSessionImplTest, Stop_ConnectingMojoForUpgrade) {
ASSERT_NO_FATAL_FAILURE(SetupMiniContainer(arc_session.get(), &observer));
// Then upgrade. This should suspend at Mojo connection.
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ arc_session->RequestUpgrade();
base::RunLoop().RunUntilIdle();
ASSERT_EQ(ArcSessionImpl::State::CONNECTING_MOJO,
arc_session->GetStateForTesting());
@@ -527,6 +414,7 @@ TEST_F(ArcSessionImplTest, Stop_ConnectingMojoForUpgrade) {
EXPECT_EQ(ArcStopReason::SHUTDOWN,
observer.on_session_stopped_args()->reason);
EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+ EXPECT_TRUE(observer.on_session_stopped_args()->full_requested);
}
// Testing stop during RUNNING_FULL_INSTANCE after upgrade.
@@ -537,7 +425,7 @@ TEST_F(ArcSessionImplTest, Stop_RunningFullInstanceForUpgrade) {
ASSERT_NO_FATAL_FAILURE(SetupMiniContainer(arc_session.get(), &observer));
// And upgrade successfully.
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ arc_session->RequestUpgrade();
base::RunLoop().RunUntilIdle();
ASSERT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
arc_session->GetStateForTesting());
@@ -551,6 +439,7 @@ TEST_F(ArcSessionImplTest, Stop_RunningFullInstanceForUpgrade) {
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()->full_requested);
}
// Testing stop during STARTING_MINI_INSTANCE with upgrade request.
@@ -558,12 +447,12 @@ TEST_F(ArcSessionImplTest,
Stop_StartingFullInstanceForUpgradeDuringMiniInstanceStart) {
auto arc_session = CreateArcSession();
TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ arc_session->StartMiniInstance();
ASSERT_EQ(ArcSessionImpl::State::STARTING_MINI_INSTANCE,
arc_session->GetStateForTesting());
// Request to upgrade during starting mini container.
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ arc_session->RequestUpgrade();
// Then, the state should stay at STARTING_MINI_INSTANCE.
ASSERT_EQ(ArcSessionImpl::State::STARTING_MINI_INSTANCE,
arc_session->GetStateForTesting());
@@ -577,6 +466,7 @@ TEST_F(ArcSessionImplTest,
EXPECT_EQ(ArcStopReason::SHUTDOWN,
observer.on_session_stopped_args()->reason);
EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+ EXPECT_TRUE(observer.on_session_stopped_args()->full_requested);
}
// Stop is requested, but at the same time
@@ -589,8 +479,8 @@ TEST_F(ArcSessionImplTest, Stop_ConflictWithFailure) {
auto arc_session = CreateArcSession();
TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
- ASSERT_EQ(ArcSessionImpl::State::STARTING_FULL_INSTANCE,
+ arc_session->StartMiniInstance();
+ ASSERT_EQ(ArcSessionImpl::State::STARTING_MINI_INSTANCE,
arc_session->GetStateForTesting());
arc_session->Stop();
@@ -603,13 +493,15 @@ TEST_F(ArcSessionImplTest, Stop_ConflictWithFailure) {
EXPECT_EQ(ArcStopReason::SHUTDOWN,
observer.on_session_stopped_args()->reason);
EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+ EXPECT_FALSE(observer.on_session_stopped_args()->full_requested);
}
// Emulating crash.
TEST_F(ArcSessionImplTest, ArcStopInstance) {
auto arc_session = CreateArcSession();
TestArcSessionObserver observer(arc_session.get());
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ arc_session->StartMiniInstance();
+ arc_session->RequestUpgrade();
base::RunLoop().RunUntilIdle();
ASSERT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
arc_session->GetStateForTesting());
@@ -624,6 +516,7 @@ TEST_F(ArcSessionImplTest, ArcStopInstance) {
ASSERT_TRUE(observer.on_session_stopped_args().has_value());
EXPECT_EQ(ArcStopReason::CRASH, observer.on_session_stopped_args()->reason);
EXPECT_TRUE(observer.on_session_stopped_args()->was_running);
+ EXPECT_TRUE(observer.on_session_stopped_args()->full_requested);
}
// ArcStopInstance for the *previous* ARC container may be reported
@@ -631,7 +524,8 @@ TEST_F(ArcSessionImplTest, ArcStopInstance) {
// Unrelated ArcStopInstance signal should be ignored.
TEST_F(ArcSessionImplTest, ArcStopInstance_WrongContainerInstanceId) {
auto arc_session = CreateArcSession();
- arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ arc_session->StartMiniInstance();
+ arc_session->RequestUpgrade();
base::RunLoop().RunUntilIdle();
ASSERT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
arc_session->GetStateForTesting());
@@ -649,24 +543,24 @@ TEST_F(ArcSessionImplTest, ArcStopInstance_WrongContainerInstanceId) {
struct PackagesCacheModeState {
// Possible values for chromeos::switches::kArcPackagesCacheMode
const char* chrome_switch;
- ArcInstanceMode start_mode;
+ bool full_container;
login_manager::StartArcInstanceRequest_PackageCacheMode
expected_packages_cache_mode;
};
constexpr PackagesCacheModeState kPackagesCacheModeStates[] = {
- {nullptr, ArcInstanceMode::FULL_INSTANCE,
+ {nullptr, true,
login_manager::StartArcInstanceRequest_PackageCacheMode_DEFAULT},
- {nullptr, ArcInstanceMode::MINI_INSTANCE,
+ {nullptr, false,
login_manager::StartArcInstanceRequest_PackageCacheMode_DEFAULT},
- {ArcSessionImpl::kPackagesCacheModeCopy, ArcInstanceMode::FULL_INSTANCE,
+ {ArcSessionImpl::kPackagesCacheModeCopy, true,
login_manager::StartArcInstanceRequest_PackageCacheMode_COPY_ON_INIT},
- {ArcSessionImpl::kPackagesCacheModeCopy, ArcInstanceMode::MINI_INSTANCE,
+ {ArcSessionImpl::kPackagesCacheModeCopy, false,
login_manager::StartArcInstanceRequest_PackageCacheMode_DEFAULT},
- {ArcSessionImpl::kPackagesCacheModeSkipCopy, ArcInstanceMode::FULL_INSTANCE,
+ {ArcSessionImpl::kPackagesCacheModeSkipCopy, true,
login_manager::
StartArcInstanceRequest_PackageCacheMode_SKIP_SETUP_COPY_ON_INIT},
- {ArcSessionImpl::kPackagesCacheModeCopy, ArcInstanceMode::MINI_INSTANCE,
+ {ArcSessionImpl::kPackagesCacheModeCopy, false,
login_manager::StartArcInstanceRequest_PackageCacheMode_DEFAULT},
};
@@ -685,7 +579,9 @@ TEST_P(ArcSessionImplPackagesCacheModeTest, PackagesCacheModes) {
state.chrome_switch);
}
- arc_session->Start(state.start_mode);
+ arc_session->StartMiniInstance();
+ if (state.full_container)
+ arc_session->RequestUpgrade();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(state.expected_packages_cache_mode, GetSessionManagerClient()
->last_start_arc_request()
diff --git a/chromium/components/arc/arc_session_runner.cc b/chromium/components/arc/arc_session_runner.cc
index 5a453002ad2..ca10d68d93d 100644
--- a/chromium/components/arc/arc_session_runner.cc
+++ b/chromium/components/arc/arc_session_runner.cc
@@ -112,23 +112,6 @@ bool IsRequestAllowed(const base::Optional<ArcInstanceMode>& current_mode,
return false;
}
-// Returns true if OnSessionStopped() should be called to notify observers.
-bool ShouldNotifyOnSessionStopped(
- const base::Optional<ArcInstanceMode>& target_mode) {
- DCHECK(target_mode.has_value());
-
- switch (target_mode.value()) {
- case ArcInstanceMode::MINI_INSTANCE:
- return false;
- case ArcInstanceMode::FULL_INSTANCE:
- return true;
- }
-
- NOTREACHED() << "Unexpeceted |target_mode|: "
- << static_cast<int>(target_mode.value());
- return false;
-}
-
} // namespace
ArcSessionRunner::ArcSessionRunner(const ArcSessionFactory& factory)
@@ -242,15 +225,15 @@ void ArcSessionRunner::StartArcSession() {
if (!arc_session_) {
arc_session_ = factory_.Run();
arc_session_->AddObserver(this);
+ arc_session_->StartMiniInstance();
// Record the UMA only when |restart_after_crash_count_| is zero to avoid
// recording an auto-restart-then-crash loop. Such a crash loop is recorded
// separately with RecordInstanceRestartAfterCrashUma().
if (!restart_after_crash_count_)
RecordInstanceCrashUma(ArcContainerLifetimeEvent::CONTAINER_STARTING);
- } else {
- DCHECK_EQ(ArcInstanceMode::MINI_INSTANCE, arc_session_->GetTargetMode());
}
- arc_session_->Start(target_mode_.value());
+ if (target_mode_ == ArcInstanceMode::FULL_INSTANCE)
+ arc_session_->RequestUpgrade();
}
void ArcSessionRunner::RestartArcSession() {
@@ -262,18 +245,14 @@ void ArcSessionRunner::RestartArcSession() {
}
void ArcSessionRunner::OnSessionStopped(ArcStopReason stop_reason,
- bool was_running) {
+ bool was_running,
+ bool full_requested) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(arc_session_);
DCHECK(!restart_timer_.IsRunning());
VLOG(0) << "ARC stopped: " << stop_reason;
- // The observers should be agnostic to the existence of the limited-purpose
- // instance.
- const bool notify_observers =
- ShouldNotifyOnSessionStopped(arc_session_->GetTargetMode());
-
arc_session_->RemoveObserver(this);
arc_session_.reset();
@@ -305,7 +284,9 @@ void ArcSessionRunner::OnSessionStopped(ArcStopReason stop_reason,
weak_ptr_factory_.GetWeakPtr()));
}
- if (notify_observers) {
+ // The observers should be agnostic to the existence of the limited-purpose
+ // instance.
+ if (full_requested) {
for (auto& observer : observer_list_)
observer.OnSessionStopped(stop_reason, restarting);
}
diff --git a/chromium/components/arc/arc_session_runner.h b/chromium/components/arc/arc_session_runner.h
index 4b7f546bc25..ab9bbff8ce5 100644
--- a/chromium/components/arc/arc_session_runner.h
+++ b/chromium/components/arc/arc_session_runner.h
@@ -102,7 +102,9 @@ class ArcSessionRunner : public ArcSession::Observer {
void RestartArcSession();
// ArcSession::Observer:
- void OnSessionStopped(ArcStopReason reason, bool was_running) override;
+ void OnSessionStopped(ArcStopReason reason,
+ bool was_running,
+ bool full_requested) override;
THREAD_CHECKER(thread_checker_);
diff --git a/chromium/components/arc/arc_session_runner_unittest.cc b/chromium/components/arc/arc_session_runner_unittest.cc
index 7cf99558eeb..808e5ab4e1f 100644
--- a/chromium/components/arc/arc_session_runner_unittest.cc
+++ b/chromium/components/arc/arc_session_runner_unittest.cc
@@ -233,6 +233,7 @@ TEST_F(ArcSessionRunnerTest, BootFailure_MiniInstance) {
// If starting the mini instance fails, arc_session_runner()'s state goes back
// to STOPPED, but its observers won't be notified.
arc_session_runner()->RequestStart(ArcInstanceMode::MINI_INSTANCE);
+ arc_session()->EmulateMiniContainerStart();
EXPECT_FALSE(arc_session());
EXPECT_FALSE(stopped_called());
@@ -255,6 +256,7 @@ TEST_F(ArcSessionRunnerTest, Crash_MiniInstance) {
// If starting the mini instance fails, arc_session_runner()'s state goes back
// to STOPPED, but its observers won't be notified.
arc_session_runner()->RequestStart(ArcInstanceMode::MINI_INSTANCE);
+ arc_session()->EmulateMiniContainerStart();
EXPECT_FALSE(arc_session());
EXPECT_FALSE(stopped_called());
}
diff --git a/chromium/components/arc/common/BUILD.gn b/chromium/components/arc/common/BUILD.gn
index 0ea2baf1e34..267d0fa40e9 100644
--- a/chromium/components/arc/common/BUILD.gn
+++ b/chromium/components/arc/common/BUILD.gn
@@ -43,7 +43,9 @@ if (is_chromeos) {
"process.mojom",
"rotation_lock.mojom",
"scale_factor.mojom",
+ "screen_capture.mojom",
"storage_manager.mojom",
+ "timer.mojom",
"tracing.mojom",
"tts.mojom",
"usb_host.mojom",
diff --git a/chromium/components/arc/common/accessibility_helper.mojom b/chromium/components/arc/common/accessibility_helper.mojom
index 9e6eebabe90..4df7fa3d04c 100644
--- a/chromium/components/arc/common/accessibility_helper.mojom
+++ b/chromium/components/arc/common/accessibility_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: 10
+// Next MinVersion: 11
module arc.mojom;
@@ -244,6 +244,17 @@ enum AccessibilityFilterType {
[MinVersion=2] WHITELISTED_PACKAGE_NAME
};
+[Extensible]
+enum AccessibilityNotificationStateType {
+ // Surface for a notification is created. OnNotificationStateChanged of
+ // SURFACE_CREATED for a notification must be called before
+ // OnAccessibilityEvent of WINDOW_STATE_CHANGED for it is called.
+ SURFACE_CREATED,
+
+ // Surface for a notification is removed.
+ SURFACE_REMOVED,
+};
+
// AccessibilityEventData is a struct to contain info of
// AccessibilityEvent in Android.
// https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent.html
@@ -280,7 +291,7 @@ struct AccessibilityActionData {
[MinVersion=6] int32 window_id;
};
-// Next method ID: 2
+// Next method ID: 3
interface AccessibilityHelperHost {
OnAccessibilityEventDeprecated@0(AccessibilityEventType event_type,
AccessibilityNodeInfoData? event_source);
@@ -288,6 +299,11 @@ interface AccessibilityHelperHost {
// OnAccessibilityEvent is called when a converted Android accessibility event
// is sent from Android.
OnAccessibilityEvent@1(AccessibilityEventData event_data);
+
+ // OnNotificationStateChanged is called when state of a notification is
+ // changed, e.g. surface for a notification is created.
+ [MinVersion=10] OnNotificationStateChanged@2(
+ string notification_key, AccessibilityNotificationStateType state);
};
// Next method ID: 8
diff --git a/chromium/components/arc/common/arc_bridge.mojom b/chromium/components/arc/common/arc_bridge.mojom
index c779b381aba..63783e55653 100644
--- a/chromium/components/arc/common/arc_bridge.mojom
+++ b/chromium/components/arc/common/arc_bridge.mojom
@@ -32,7 +32,9 @@ import "power.mojom";
import "print.mojom";
import "process.mojom";
import "rotation_lock.mojom";
+import "screen_capture.mojom";
import "storage_manager.mojom";
+import "timer.mojom";
import "tracing.mojom";
import "tts.mojom";
import "usb_host.mojom";
@@ -42,9 +44,9 @@ import "voice_interaction_framework.mojom";
import "volume_mounter.mojom";
import "wallpaper.mojom";
-// Next MinVersion: 35
+// Next MinVersion: 37
// Deprecated method IDs: 101, 105
-// Next method ID: 140
+// Next method ID: 142
interface ArcBridgeHost {
// Keep the entries alphabetical. In order to do so without breaking
// compatibility with the ARC instance, explicitly assign each interface a
@@ -142,9 +144,15 @@ interface ArcBridgeHost {
// Notifies Chrome that the RotationLockInstance interface is ready.
[MinVersion=32] OnRotationLockInstanceReady@137(RotationLockInstance instance_ptr);
+ // Notifies Chrome that the ScreenCaptureInstance interface is ready.
+ [MinVersion=35] OnScreenCaptureInstanceReady@140(ScreenCaptureInstance instance_ptr);
+
// Notifies Chrome that the StorageManagerInstance interface is ready.
[MinVersion=12] OnStorageManagerInstanceReady@118(StorageManagerInstance instance_ptr);
+ // Notifies Chrome that the TimerInstance interface is ready.
+ [MinVersion=36] OnTimerInstanceReady@141(TimerInstance instance_ptr);
+
// Notifies Chrome that the TracingInstance interface is ready.
[MinVersion=22] OnTracingInstanceReady@128(TracingInstance instance_ptr);
diff --git a/chromium/components/arc/common/ime.mojom b/chromium/components/arc/common/ime.mojom
index db7517c0d22..b1f2fc09cc3 100644
--- a/chromium/components/arc/common/ime.mojom
+++ b/chromium/components/arc/common/ime.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Next MinVersion: 8
+// Next MinVersion: 9
module arc.mojom;
@@ -40,7 +40,13 @@ interface ImeHost {
OnTextInputTypeChanged@0(TextInputType type);
// Notifies Chrome that the cursor poisition has changed.
- OnCursorRectChanged@1(Rect rect);
+ //
+ // |rect| describes the coordinates in physical pixels.
+ // If |is_screen_coordinates| is set to true, its origin (0,0) is the top-left
+ // of the primary display. Otherwise it is the top-left of the window that has
+ // the IME focus.
+ OnCursorRectChanged@1(Rect rect,
+ [MinVersion=8] bool is_screen_coordinates);
// Notifies Chrome that the current composition is canceled.
[MinVersion=1] OnCancelComposition@2();
@@ -51,16 +57,23 @@ interface ImeHost {
// Notifies Chrome that the cursor position has changed and
// also sends surrounding text.
//
+ // |rect| describes the coordinates in physical pixels.
+ // If |is_screen_coordinates| is set to true, its origin (0,0) is the top-left
+ // of the primary display. Otherwise it is the top-left of the window that has
+ // the IME focus.
+ //
// |text_range|, |text_in_range| and |selection_range| are piggy-backed
// into this method because Chrome OS IME tries to retrieve these information
// synchronously, so we need to update them all at once to keep consistency.
[MinVersion=5] OnCursorRectChangedWithSurroundingText@4(
- Rect rect, // The cursor position.
- Range text_range, // The range of |text_in_range| in the current
- // text in the editor.
- string text_in_range, // The text around the cursor.
- Range selection_range // The range of the selected text
- // in the current text in the editor.
+ Rect rect, // The cursor position.
+ Range text_range, // The range of |text_in_range| in the current
+ // text in the editor.
+ string text_in_range, // The text around the cursor.
+ Range selection_range, // The range of the selected text
+ // in the current text in the editor.
+ [MinVersion=8] bool is_screen_coordinates // Whether or not the |rect|
+ // are in screen coordinates.
);
};
diff --git a/chromium/components/arc/common/notifications.mojom b/chromium/components/arc/common/notifications.mojom
index ee6475d5353..165b6069f13 100644
--- a/chromium/components/arc/common/notifications.mojom
+++ b/chromium/components/arc/common/notifications.mojom
@@ -25,13 +25,12 @@ enum ArcNotificationEvent {
[MinVersion=10] TOGGLE_EXPANSION = 7,
};
-// These values must be matched with the NOTIFICATION_TYPE_* constants in
-// com.android.server.ArcNotificationListenerService.
+[Extensible]
enum ArcNotificationType {
- BASIC = 0,
- IMAGE = 1,
- PROGRESS = 2,
- LIST = 3,
+ SIMPLE = 0,
+ DEPRECATED_IMAGE = 1,
+ DEPRECATED_PROGRESS = 2,
+ DEPRECATED_LIST = 3,
};
// These values are corresponding to the priorities of Android notification.
@@ -44,7 +43,8 @@ enum ArcNotificationPriority {
MAX = 2, // same value as Notification.PRIORITY_MAX
};
-struct ArcNotificationButton {
+// DEPRECATED
+struct DeprecatedArcNotificationButton {
// Title
string label;
};
@@ -80,37 +80,36 @@ struct ArcNotificationData {
string message;
// Title of notification
string title;
- // Mimetype of |icon_data|
- string icon_mimetype;
- // Binary data of the icon
- array<uint8> icon_data;
+ // DEPRECATED: Mimetype of |icon_data|
+ string? deprecated_icon_mimetype;
+ // DEPRECATED: Binary data of the icon
+ array<uint8>? deprecated_icon_data;
// Priority of notification
ArcNotificationPriority priority;
// Timestamp related to the notification
int64 time;
- // The current value of progress, must be [0, progress_max].
- int32 progress_current;
- // The maximum value of progress.
- int32 progress_max;
- // Action buttons
- array<ArcNotificationButton> buttons;
+ // DEPRECATED: The current value of progress, must be [0, progress_max].
+ int32 deprecated_progress_current;
+ // DEPRECATED: The maximum value of progress.
+ int32 deprecated_progress_max;
+ // DEPRECATED: Action buttons
+ array<DeprecatedArcNotificationButton>? deprecated_buttons;
// Flag if the notification has FLAG_NO_CLEAR.
[MinVersion=1]
bool no_clear;
// Flag if the notification has FLAG_ONGOING_EVENT.
[MinVersion=1]
bool ongoing_event;
- // Subtexts for list notifications.
+ // DEPRECATED: Subtexts for list notifications.
[MinVersion=3]
- array<string>? texts;
- // Image for image notifications.
+ array<string>? deprecated_texts;
+ // DEPRECATED: Image for image notifications.
[MinVersion=3]
- ArcBitmap? big_picture;
- // Flag if a notification is a custom notification backed by a notification
- // surface. Note the flag is only used on creation. Change of the flag
- // on notification update is ignored.
+ ArcBitmap? deprecated_big_picture;
+ // DEPRECATED: Flag if a notification is a custom notification backed by a
+ // notification surface.
[MinVersion=5]
- bool use_custom_notification;
+ bool deprecated_use_custom_notification;
[MinVersion=6]
ArcBitmap? small_icon;
// A snapshot image to show before the notification window is created.
diff --git a/chromium/components/arc/common/policy.mojom b/chromium/components/arc/common/policy.mojom
index 08294b4cabd..59aa7f0a2df 100644
--- a/chromium/components/arc/common/policy.mojom
+++ b/chromium/components/arc/common/policy.mojom
@@ -2,10 +2,54 @@
// 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;
+import "mojo/common/time.mojom";
+
+[Extensible]
+//See depot/google3/wireless/android/enterprise/clouddps/proto/clouddps.proto
+enum InstallErrorReason {
+ // If the reason is unspecified, this error should be treated as a
+ // non-transient error.
+ REASON_UNSPECIFIED = 0,
+
+ // The server didn't get a response from Play in time. The install may
+ // still succeed or may fail with any error.
+ TIMEOUT = 1,
+
+ // A potentially transient error, for example, the device is not found (due
+ // to replication delay), or Play was unavailable. A retry in a short amount
+ // of time is likely to succeed.
+ TRANSIENT_ERROR = 2,
+
+ // The app was not found in Play.
+ NOT_FOUND = 3,
+
+ // The app is incompatible with the device.
+ NOT_COMPATIBLE_WITH_DEVICE = 4,
+
+ // The app has not been approved by the admin.
+ NOT_APPROVED = 5,
+
+ // The app has new permissions that have not been accepted by the admin.
+ PERMISSIONS_NOT_ACCEPTED = 6,
+
+ // The app is not available in the user's country.
+ NOT_AVAILABLE_IN_COUNTRY = 7,
+
+ // There are no more licenses to assign to the user.
+ NO_LICENSES_REMAINING = 8,
+
+ // The enterprise is no longer enrolled with Play for Work or CloudDPC is
+ // not enabled for the enterprise.
+ NOT_ENROLLED = 9,
+
+ // The user is no longer valid. The user may have been deleted or disabled.
+ USER_INVALID = 10,
+};
+
// Next Method ID: 2
interface PolicyHost {
// Get policies from Chrome OS, as JSON-encoded dictionary with the policies'
@@ -18,6 +62,18 @@ interface PolicyHost {
// in JSON format as in CloudDps PolicyComplianceReportResponse.
// ChromeOS always returns that it's compliant with the report.
[MinVersion=1] ReportCompliance@1(string request) => (string response);
+
+ // Reports that request was sent to CloudDPS for set of packages.
+ [MinVersion=3] ReportCloudDpsRequested(mojo.common.mojom.Time time,
+ array<string> package_names);
+ // Reports that successful response was received from CloudDPS for set of
+ // packages.
+ [MinVersion=3] ReportCloudDpsSucceeded(mojo.common.mojom.Time time,
+ array<string> package_names);
+ // Reports that CloudDPS reports an error for packages.
+ [MinVersion=3] ReportCloudDpsFailed(mojo.common.mojom.Time time,
+ string package_name,
+ InstallErrorReason reason);
};
// Next Method ID: 3
diff --git a/chromium/components/arc/common/print.mojom b/chromium/components/arc/common/print.mojom
index 3f03b7ff82c..f74d468ca4c 100644
--- a/chromium/components/arc/common/print.mojom
+++ b/chromium/components/arc/common/print.mojom
@@ -6,12 +6,193 @@
module arc.mojom;
+// android.print.PageRange
+struct PrintPageRange {
+ // First page inclusive.
+ int32 start;
+ // Last page inclusive.
+ int32 end;
+};
+
+// android.print.PrintAttributes.MediaSize
+struct PrintMediaSize {
+ // Id unique among media sizes.
+ string id;
+ // Localized label.
+ string label;
+ int32 width_mils;
+ int32 height_mils;
+};
+
+// android.print.PrintAttributes.Resolution
+struct PrintResolution {
+ // Id unique among resolutions.
+ string id;
+ // Localized label.
+ string label;
+ int32 horizontal_dpi;
+ int32 vertical_dpi;
+};
+
+// android.print.PrintAttributes.Margins
+struct PrintMargins {
+ int32 left_mils;
+ int32 top_mils;
+ int32 right_mils;
+ int32 bottom_mils;
+};
+
+// android.print.PrintAttributes.COLOR_MODE_*
+[Extensible]
+enum PrintColorMode {
+ MONOCHROME = 1,
+ COLOR = 2,
+};
+
+// android.print.PrintAttributes.DUPLEX_MODE_*
+[Extensible]
+enum PrintDuplexMode {
+ NONE = 1,
+ LONG_EDGE = 2,
+ SHORT_EDGE = 4,
+};
+
+// android.print.PrintDocumentInfo.CONTENT_TYPE_*
+[Extensible]
+enum PrintContentType {
+ UNKNOWN = -1,
+ DOCUMENT = 0,
+ PHOTO = 1,
+};
+
+// android.print.PrintAttributes
+struct PrintAttributes {
+ PrintMediaSize? media_size;
+ PrintResolution? resolution;
+ PrintMargins? min_margins;
+ PrintColorMode color_mode;
+ PrintDuplexMode duplex_mode;
+};
+
+struct PrintJobRequest {
+ // android.printservice.PrintJob fields:
+ array<int8> id;
+ string label;
+ string? printer_id;
+ int64 creation_time;
+ int32 copies;
+ array<PrintPageRange> pages;
+ PrintAttributes attributes;
+ // android.print.PrintDocumentInfo fields:
+ string document_name;
+ int32 document_page_count;
+ PrintContentType content_type;
+ int64 data_size;
+ // android.printservice.PrintDocument fields:
+ handle? data;
+};
+
+// android.print.PrinterInfo.STATUS_*
+[Extensible]
+enum PrinterStatus {
+ IDLE = 1,
+ BUSY = 2,
+ UNAVAILABLE = 3,
+};
+
+// android.print.PrinterCapabilitiesInfo
+struct PrinterCapabilities {
+ array<PrintMediaSize> media_sizes;
+ array<PrintResolution> resolutions;
+ PrintMargins min_margins;
+ PrintColorMode color_modes;
+ PrintDuplexMode duplex_modes;
+ PrintAttributes defaults;
+};
+
+// android.print.PrinterInfo
+struct PrinterInfo {
+ // Id unique among printers.
+ string id;
+ // Localized name.
+ string name;
+ PrinterStatus status;
+ // Localized description.
+ string? description;
+ // Intent for provider-specific settings.
+ string? info_intent;
+ PrinterCapabilities? capabilities;
+};
+
+// android.printservice.PrinterDiscoverySession implementation.
+// This is called by container when printing is requested and printer discovery
+// has to start. Implemented in embedder.
+// The normal order this is called is:
+// StartPrinterDiscovery
+// StartPrinterStateTracking
+// StopPrinterStateTracking
+// StopPrinterDiscovery
+// DestroyDiscoverySession
+// (ValidatePrinters is not used in practice)
+//
+// Next method ID: 6
+interface PrinterDiscoverySessionHost {
+ StartPrinterDiscovery@0(array<string> printer_ids);
+ StopPrinterDiscovery@1();
+ ValidatePrinters@2(array<string> printer_ids);
+ StartPrinterStateTracking@3(string printer_id);
+ StopPrinterStateTracking@4(string printer_id);
+ DestroyDiscoverySession@5();
+};
+
+// android.printservice.PrinterDiscoverySession final methods proxy.
+// This is called by embedder when printer discovery is active.
+// Implemented in container.
+// Next method ID: 2
+interface PrinterDiscoverySessionInstance {
+ AddPrinters@0(array<PrinterInfo> printers);
+ RemovePrinters@1(array<string> printers);
+};
+
+// android.printservice.PrintService.onRequestCancelPrintJob implementation.
+// This is called by container when job cancellation was requested.
+// Implemented in embedder.
// Next method ID: 1
+interface PrintJobHost {
+ Cancel@0();
+};
+
+// android.printservice.PrintJob proxy.
+// This is called by embedder when print job status changes.
+// Implemented in container.
+// See https://developer.android.com/reference/android/printservice/PrintJob.html
+// Next method ID: 7
+interface PrintJobInstance {
+ Start@0();
+ Block@1(string? reason);
+ Complete@2();
+ Fail@3(string? reason);
+ Cancel@4();
+ SetProgress@5(float progress);
+ SetStatus@6(string? status);
+};
+
+// android.printservice.PrintService implementation.
+// This is called by container to create new discovery sessions and print jobs.
+// Implemented in embedder.
+// Next method ID: 2
+// Deprecated method ID: 0
interface PrintHost {
- Print@0(handle file);
+ PrintDeprecated@0(handle file);
+ [MinVersion=1] Print@1(PrintJobInstance instance, PrintJobRequest request) => (PrintJobHost host);
+ [MinVersion=1] CreateDiscoverySession@2(PrinterDiscoverySessionInstance instance) =>
+ (PrinterDiscoverySessionHost host);
};
+// This is called by embedder to indicate that it's ready to accept print jobs.
+// Implemented in container.
// Next method ID: 2
+// Deprecated method ID: 0
interface PrintInstance {
// DEPRECATED: Please use Init@1 instead.
InitDeprecated@0(PrintHost host_ptr);
diff --git a/chromium/components/arc/common/print.typemap b/chromium/components/arc/common/print.typemap
new file mode 100644
index 00000000000..c8bb9251091
--- /dev/null
+++ b/chromium/components/arc/common/print.typemap
@@ -0,0 +1,19 @@
+mojom = "//components/arc/common/print.mojom"
+public_headers = [
+ "//printing/backend/print_backend.h",
+ "//printing/page_range.h",
+ "//ui/gfx/geometry/size.h",
+]
+traits_headers = [ "//chrome/browser/chromeos/arc/print/print_struct_traits.h" ]
+sources = [
+ "//chrome/browser/chromeos/arc/print/print_struct_traits.cc",
+]
+deps = []
+public_deps = [
+ "//printing:printing",
+]
+type_mappings = [
+ "arc.mojom.PrintPageRange=printing::PageRange",
+ "arc.mojom.PrintResolution=gfx::Size",
+ "arc.mojom.PrinterCapabilities=printing::PrinterSemanticCapsAndDefaults",
+]
diff --git a/chromium/components/arc/common/scale_factor.mojom b/chromium/components/arc/common/scale_factor.mojom
index 65e6cbd71ab..df38c5c035b 100644
--- a/chromium/components/arc/common/scale_factor.mojom
+++ b/chromium/components/arc/common/scale_factor.mojom
@@ -5,6 +5,7 @@
module arc.mojom;
// Duplicates ui::ScaleFactor enum in order to be accessible on Android side.
+[Extensible]
enum ScaleFactor {
SCALE_FACTOR_NONE = 0,
SCALE_FACTOR_100P,
diff --git a/chromium/components/arc/common/screen_capture.mojom b/chromium/components/arc/common/screen_capture.mojom
new file mode 100644
index 00000000000..0d205e60870
--- /dev/null
+++ b/chromium/components/arc/common/screen_capture.mojom
@@ -0,0 +1,74 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Mojo interface for performing screen capture in ChromeOS at the request of
+// Android. Android does not have access to the full desktop for capture (it has
+// access only to its Windows), so via this IPC mechanism it can request
+// permissions to capture the entire desktop and then also perform that capture.
+
+// The original version of this file lives in the Chromium repository at:
+// src/components/arc/common/screen_capture.mojom
+
+// Next MinVersion: 2
+
+module arc.mojom;
+
+// For gfx::Size.
+import "video_common.mojom";
+
+// Implemented by Chrome in order to allow requesting of permissions to perform
+// desktop capture as well as creating a session for it.
+interface ScreenCaptureHost {
+ // This will also show the desktop picker in case of multiple displays and
+ // will then link that desktop window to the granted permission.
+ // display_name is the string that should be used in the UI
+ // package_name is what should be used as the permission token
+ // returns true if the user accepts, false otherwise
+ RequestPermission@0(string display_name, string package_name) => (bool granted);
+
+ // Requests that a corresponding active permission dialog from a prior call to
+ // RequestPermission be accepted. This will only be allowed under test
+ // conditions.
+ // package_name should match what was passed into RequestPermission
+ [MinVersion=1] TestModeAcceptPermission@2(string package_name);
+
+ // Starts a new capture session, binding the session interface to the passed
+ // in session request.
+ // notifier interface passed in will be used to send messages back to Android
+ // for when updates are needed by the Chrome rendering engine
+ // package_name should correspond to what was passed into the
+ // RequestPermission call
+ // size should have the width/height of the buffers used
+ // returns null interface in the case the permission was not granted, a valid
+ // interface pointer otherwise
+ OpenSession@1(ScreenCaptureSessionNotifier notifier,
+ string package_name, Size size) =>
+ (ScreenCaptureSession? session);
+};
+
+// Implemented by Chrome for handling a screen capture session.
+interface ScreenCaptureSession {
+ // Called to set the graphics buffer that the screen capture should be
+ // rendered to. This call does not return until the rendering is complete to
+ // the passed in buffer.
+ // graphics_buffer should be a handle to the buffer which corresponds to the
+ // surface being rendered to
+ // stride is the stride in pixels for each row of the buffer
+ SetOutputBuffer@0(handle graphics_buffer, uint32 stride) => ();
+};
+
+// Implemented by Android.
+interface ScreenCaptureInstance {
+ // Establishes full-duplex communication with the host.
+ Init@0(ScreenCaptureHost host_ptr) => ();
+};
+
+// Implemented by Android as a callback mechanism.
+interface ScreenCaptureSessionNotifier {
+ // This is called when Chrome detects a compositor update but Android is not
+ // actively rendering. This will occur if the Android windows are minimized or
+ // not animating but Chrome windows are since Android’s rendering stack does
+ // not update if nothing in Android itself is changing.
+ ForceUpdate@0();
+};
diff --git a/chromium/components/arc/common/timer.mojom b/chromium/components/arc/common/timer.mojom
new file mode 100644
index 00000000000..f42fb94bc3c
--- /dev/null
+++ b/chromium/components/arc/common/timer.mojom
@@ -0,0 +1,66 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Next min version: 1
+
+module arc.mojom;
+
+import "mojo/common/time.mojom";
+
+[Extensible]
+enum ArcTimerResult {
+ SUCCESS = 0,
+ FAILURE = 1,
+};
+
+[Extensible]
+enum ClockId {
+ REALTIME_ALARM = 0,
+ BOOTTIME_ALARM = 1,
+};
+
+struct CreateTimerRequest {
+ // Type of the clock for which a timer needs to be created. This value
+ // corresponds to the clock ids used by timerfd_create.
+ ClockId clock_id;
+
+ // File descriptor to write to when the timer is expired. This indicates to
+ // the instance that the timer is expired. This fd is owned by the host.
+ handle expiration_fd;
+};
+
+// Next method ID: 1
+interface Timer {
+ // Starts the timer to run at |absolute_expiration_time| in the future. If
+ // the timer is already running, it will be replaced. Notification will be
+ // performed as an 8-byte write to the associated expiration fd. Returns
+ // |ArcTimerResult::SUCCESS| if the timer can be started and
+ // |ArcTimerResult::FAILURE| otherwise.
+ Start@0(mojo.common.mojom.TimeTicks absolute_expiration_time)
+ => (ArcTimerResult result);
+};
+
+struct CreateTimerResponse {
+ // Type of the clock associated with the timer.
+ ClockId clock_id;
+
+ // Timer object that will set timers of type |clock_id|.
+ Timer timer;
+};
+
+// Next method ID: 1
+interface TimerHost {
+ // Creates timers with the given arguments. Returns a null array on failure
+ // and an array of |Timer| objects of the same size as |arc_timer_requests|
+ // on success. Only one |Timer| per clock id is created and
+ // |arc_timer_requests| need to have unique clock ids for success.
+ CreateTimers@0(array<CreateTimerRequest> timer_requests)
+ => (array<CreateTimerResponse>? response);
+};
+
+// Next method ID: 1
+interface TimerInstance {
+ // Establishes full-duplex communication with the host.
+ Init@0(TimerHost host_ptr) => ();
+};
diff --git a/chromium/components/arc/common/timer.typemap b/chromium/components/arc/common/timer.typemap
new file mode 100644
index 00000000000..6f46f6c8cea
--- /dev/null
+++ b/chromium/components/arc/common/timer.typemap
@@ -0,0 +1,12 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom = "//components/arc/common/timer.mojom"
+public_headers = [ "//components/arc/timer/create_timer_request.h" ]
+traits_headers = [ "//components/arc/timer/arc_timer_traits.h" ]
+sources = [
+ "//components/arc/timer/arc_timer_traits.cc",
+]
+type_mappings =
+ [ "arc.mojom.CreateTimerRequest=arc::CreateTimerRequest[move_only]" ]
diff --git a/chromium/components/arc/common/typemaps.gni b/chromium/components/arc/common/typemaps.gni
index 622d8214544..5dd1b81f850 100644
--- a/chromium/components/arc/common/typemaps.gni
+++ b/chromium/components/arc/common/typemaps.gni
@@ -9,6 +9,8 @@ typemaps = [
"//components/arc/common/file_system.typemap",
"//components/arc/common/gfx.typemap",
"//components/arc/common/intent_helper.typemap",
+ "//components/arc/common/print.typemap",
+ "//components/arc/common/timer.typemap",
"//components/arc/common/video_common.typemap",
"//components/arc/common/video_encode_accelerator.typemap",
"//components/arc/common/volume_mounter.typemap",
diff --git a/chromium/components/arc/common/usb_host.mojom b/chromium/components/arc/common/usb_host.mojom
index abdeac80f4d..d47e6df7888 100644
--- a/chromium/components/arc/common/usb_host.mojom
+++ b/chromium/components/arc/common/usb_host.mojom
@@ -6,7 +6,7 @@
module arc.mojom;
// re-use device.mojom.UsbDeviceInfo
-import "device/usb/public/interfaces/device.mojom";
+import "device/usb/public/mojom/device.mojom";
// Next method ID: 3
interface UsbHostHost {
diff --git a/chromium/components/arc/common/voice_interaction_arc_home.mojom b/chromium/components/arc/common/voice_interaction_arc_home.mojom
index ebe7be2e898..c1d96950c4a 100644
--- a/chromium/components/arc/common/voice_interaction_arc_home.mojom
+++ b/chromium/components/arc/common/voice_interaction_arc_home.mojom
@@ -7,7 +7,7 @@
module arc.mojom;
import "gfx.mojom";
-import "mojo/common/string16.mojom";
+import "mojo/public/mojom/base/string16.mojom";
// Represents view structure to be passed to ARC. The view
// structure is synthesized from the AXStructure, which
@@ -20,7 +20,7 @@ struct VoiceInteractionStructure {
Rect rect;
// Text of the view.
- mojo.common.mojom.String16 text;
+ mojo_base.mojom.String16 text;
// Text properties
float text_size;
diff --git a/chromium/components/arc/common/volume_mounter.mojom b/chromium/components/arc/common/volume_mounter.mojom
index 64718211725..27401b9a59b 100644
--- a/chromium/components/arc/common/volume_mounter.mojom
+++ b/chromium/components/arc/common/volume_mounter.mojom
@@ -33,13 +33,24 @@ struct MountPointInfo {
string fs_uuid;
// The file system label.
string label;
- // The device type that contains this mount point. If unknown, the event should be ignored.
+ // The device type that contains this mount point. If unknown, the event
+ // should be ignored.
DeviceType device_type;
};
+// Next Method ID: 1
+interface VolumeMounterHost {
+ // Requests all recorded MountPointInfos to be sent through a series of
+ // VolumeMounterInstance::OnMountEvent call.
+ [MinVersion=0] RequestAllMountPoints@1();
+};
+
// Notifies Android about Mounting events.
+// Next Method ID: 2
interface VolumeMounterInstance {
- // @0 is reserved for Init().
+ // Establishes full-duplex communication with the host.
+ [MinVersion=1] Init@0(VolumeMounterHost host_ptr) => ();
+
// Triggers a mount event in Android.
OnMountEvent@1(MountPointInfo mount_point_info);
};
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 a84bb8261cc..e75aadaa3db 100644
--- a/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc
+++ b/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc
@@ -97,7 +97,7 @@ void ArcCrashCollectorBridge::DumpCrash(const std::string& type,
base::PostTaskWithTraits(
FROM_HERE, {base::WithBaseSyncPrimitives()},
base::BindOnce(&RunCrashReporter, type, device_, board_, cpu_abi_,
- base::Passed(std::move(pipe_handle))));
+ std::move(pipe_handle)));
}
void ArcCrashCollectorBridge::SetBuildProperties(const std::string& device,
diff --git a/chromium/components/arc/ime/arc_ime_bridge.h b/chromium/components/arc/ime/arc_ime_bridge.h
index 1ed10087fff..09cfce68d8c 100644
--- a/chromium/components/arc/ime/arc_ime_bridge.h
+++ b/chromium/components/arc/ime/arc_ime_bridge.h
@@ -30,14 +30,16 @@ class ArcImeBridge {
class Delegate {
public:
virtual void OnTextInputTypeChanged(ui::TextInputType type) = 0;
- virtual void OnCursorRectChanged(const gfx::Rect& rect) = 0;
+ virtual void OnCursorRectChanged(const gfx::Rect& rect,
+ bool is_screen_cooridnates) = 0;
virtual void OnCancelComposition() = 0;
virtual void ShowImeIfNeeded() = 0;
virtual void OnCursorRectChangedWithSurroundingText(
const gfx::Rect& rect,
const gfx::Range& text_range,
const base::string16& text_in_range,
- const gfx::Range& selection_range) = 0;
+ const gfx::Range& selection_range,
+ bool is_screen_coordinates) = 0;
};
// Serializes and sends IME related requests through IPCs.
diff --git a/chromium/components/arc/ime/arc_ime_bridge_impl.cc b/chromium/components/arc/ime/arc_ime_bridge_impl.cc
index ee10026ba2c..5dad77673c9 100644
--- a/chromium/components/arc/ime/arc_ime_bridge_impl.cc
+++ b/chromium/components/arc/ime/arc_ime_bridge_impl.cc
@@ -138,8 +138,9 @@ void ArcImeBridgeImpl::OnTextInputTypeChanged(mojom::TextInputType type) {
delegate_->OnTextInputTypeChanged(ConvertTextInputType(type));
}
-void ArcImeBridgeImpl::OnCursorRectChanged(const gfx::Rect& rect) {
- delegate_->OnCursorRectChanged(rect);
+void ArcImeBridgeImpl::OnCursorRectChanged(const gfx::Rect& rect,
+ bool is_screen_coordinates) {
+ delegate_->OnCursorRectChanged(rect, is_screen_coordinates);
}
void ArcImeBridgeImpl::OnCancelComposition() {
@@ -154,9 +155,11 @@ void ArcImeBridgeImpl::OnCursorRectChangedWithSurroundingText(
const gfx::Rect& rect,
const gfx::Range& text_range,
const std::string& text_in_range,
- const gfx::Range& selection_range) {
+ const gfx::Range& selection_range,
+ bool is_screen_coordinates) {
delegate_->OnCursorRectChangedWithSurroundingText(
- rect, text_range, base::UTF8ToUTF16(text_in_range), selection_range);
+ rect, text_range, base::UTF8ToUTF16(text_in_range), selection_range,
+ is_screen_coordinates);
}
} // namespace arc
diff --git a/chromium/components/arc/ime/arc_ime_bridge_impl.h b/chromium/components/arc/ime/arc_ime_bridge_impl.h
index 669c130dca2..a71fdba2483 100644
--- a/chromium/components/arc/ime/arc_ime_bridge_impl.h
+++ b/chromium/components/arc/ime/arc_ime_bridge_impl.h
@@ -39,14 +39,15 @@ class ArcImeBridgeImpl : public ArcImeBridge, public mojom::ImeHost {
// mojom::ImeHost overrides:
void OnTextInputTypeChanged(mojom::TextInputType type) override;
- void OnCursorRectChanged(const gfx::Rect& rect) override;
+ void OnCursorRectChanged(const gfx::Rect& rect,
+ bool screen_coordinates) override;
void OnCancelComposition() override;
void ShowImeIfNeeded() override;
- void OnCursorRectChangedWithSurroundingText(
- const gfx::Rect& rect,
- const gfx::Range& text_range,
- const std::string& text_in_range,
- const gfx::Range& selection_range) override;
+ void OnCursorRectChangedWithSurroundingText(const gfx::Rect& rect,
+ const gfx::Range& text_range,
+ const std::string& text_in_range,
+ const gfx::Range& selection_range,
+ bool screen_coordinates) override;
private:
Delegate* const delegate_;
diff --git a/chromium/components/arc/ime/arc_ime_service.cc b/chromium/components/arc/ime/arc_ime_service.cc
index 603b66f170b..0f68a67ae53 100644
--- a/chromium/components/arc/ime/arc_ime_service.cc
+++ b/chromium/components/arc/ime/arc_ime_service.cc
@@ -28,6 +28,16 @@ namespace arc {
namespace {
+base::Optional<double> g_override_default_device_scale_factor;
+
+double GetDefaultDeviceScaleFactor() {
+ if (g_override_default_device_scale_factor.has_value())
+ return g_override_default_device_scale_factor.value();
+ if (!exo::WMHelper::HasInstance())
+ return 1.0;
+ return exo::WMHelper::GetInstance()->GetDefaultDeviceScaleFactor();
+}
+
class ArcWindowDelegateImpl : public ArcImeService::ArcWindowDelegate {
public:
explicit ArcWindowDelegateImpl(ArcImeService* ime_service)
@@ -234,11 +244,11 @@ void ArcImeService::OnTextInputTypeChanged(ui::TextInputType type) {
input_method->OnTextInputTypeChanged(this);
}
-void ArcImeService::OnCursorRectChanged(const gfx::Rect& rect) {
+void ArcImeService::OnCursorRectChanged(const gfx::Rect& rect,
+ bool is_screen_coordinates) {
InvalidateSurroundingTextAndSelectionRange();
- if (cursor_rect_ == rect)
+ if (!UpdateCursorRect(rect, is_screen_coordinates))
return;
- cursor_rect_ = rect;
ui::InputMethod* const input_method = GetInputMethod();
if (input_method)
@@ -263,14 +273,14 @@ void ArcImeService::OnCursorRectChangedWithSurroundingText(
const gfx::Rect& rect,
const gfx::Range& text_range,
const base::string16& text_in_range,
- const gfx::Range& selection_range) {
+ const gfx::Range& selection_range,
+ bool is_screen_coordinates) {
text_range_ = text_range;
text_in_range_ = text_in_range;
selection_range_ = selection_range;
- if (cursor_rect_ == rect)
+ if (!UpdateCursorRect(rect, is_screen_coordinates))
return;
- cursor_rect_ = rect;
ui::InputMethod* const input_method = GetInputMethod();
if (input_method)
@@ -279,15 +289,20 @@ void ArcImeService::OnCursorRectChangedWithSurroundingText(
////////////////////////////////////////////////////////////////////////////////
// Overridden from keyboard::KeyboardControllerObserver
-void ArcImeService::OnKeyboardAppearanceChanging(
+void ArcImeService::OnKeyboardAppearanceChanged(
const keyboard::KeyboardStateDescriptor& state) {
if (!focused_arc_window_)
return;
- aura::Window* window = focused_arc_window_;
gfx::Rect new_bounds = state.occluded_bounds;
- // Multiply by the scale factor. To convert from DPI to physical pixels.
- gfx::Rect bounds_in_px = gfx::ScaleToEnclosingRect(
- new_bounds, window->layer()->device_scale_factor());
+ // Multiply by the scale factor. To convert from DIP to physical pixels.
+ // The default scale factor is always used in Android side regardless of
+ // dynamic scale factor in Chrome side because Chrome sends only the default
+ // scale factor. You can find that in WaylandRemoteShell in
+ // components/exo/wayland/server.cc. We can't send dynamic scale factor due to
+ // difference between definition of DIP in Chrome OS and definition of DIP in
+ // Android.
+ gfx::Rect bounds_in_px =
+ gfx::ScaleToEnclosingRect(new_bounds, GetDefaultDeviceScaleFactor());
ime_bridge_->SendOnKeyboardAppearanceChanging(bounds_in_px,
state.is_available);
@@ -369,26 +384,7 @@ ui::TextInputType ArcImeService::GetTextInputType() const {
}
gfx::Rect ArcImeService::GetCaretBounds() const {
- if (!focused_arc_window_)
- return gfx::Rect();
- aura::Window* window = focused_arc_window_;
-
- // |cursor_rect_| holds the rectangle reported from ARC apps, in the "screen
- // coordinates" in ARC, counted by physical pixels.
- // Chrome OS input methods expect the coordinates in Chrome OS screen, within
- // device independent pixels. Two factors are involved for the conversion.
-
- // Divide by the scale factor. To convert from physical pixels to DIP.
- gfx::Rect converted = gfx::ScaleToEnclosingRect(
- cursor_rect_, 1 / window->layer()->device_scale_factor());
-
- // Add the offset of the window showing the ARC app.
- // TODO(yoshiki): Support for non-arc toplevel window. The following code do
- // not work correctly with arc windows inside non-arc toplevel window (eg.
- // notification).
- converted.Offset(
- window->GetToplevelWindow()->GetBoundsInScreen().OffsetFromOrigin());
- return converted;
+ return cursor_rect_;
}
bool ArcImeService::GetTextRange(gfx::Range* range) const {
@@ -475,10 +471,41 @@ const std::string& ArcImeService::GetClientSourceInfo() const {
return base::EmptyString();
}
+// static
+void ArcImeService::SetOverrideDefaultDeviceScaleFactorForTesting(
+ base::Optional<double> scale_factor) {
+ g_override_default_device_scale_factor = scale_factor;
+}
+
void ArcImeService::InvalidateSurroundingTextAndSelectionRange() {
text_range_ = gfx::Range::InvalidRange();
text_in_range_ = base::string16();
selection_range_ = gfx::Range::InvalidRange();
}
+bool ArcImeService::UpdateCursorRect(const gfx::Rect& rect,
+ bool is_screen_coordinates) {
+ // Divide by the scale factor. To convert from physical pixels to DIP.
+ // The default scale factor is always used because Android side is always
+ // using the default scale factor regardless of dynamic scale factor in Chrome
+ // side.
+ gfx::Rect converted(
+ gfx::ScaleToEnclosingRect(rect, 1 / GetDefaultDeviceScaleFactor()));
+
+ // If the supplied coordinates are relative to the window, add the offset of
+ // the window showing the ARC app.
+ if (!is_screen_coordinates) {
+ if (!focused_arc_window_)
+ return false;
+ converted.Offset(focused_arc_window_->GetToplevelWindow()
+ ->GetBoundsInScreen()
+ .OffsetFromOrigin());
+ }
+
+ if (cursor_rect_ == converted)
+ return false;
+ cursor_rect_ = converted;
+ return true;
+}
+
} // namespace arc
diff --git a/chromium/components/arc/ime/arc_ime_service.h b/chromium/components/arc/ime/arc_ime_service.h
index d1d8bcea12a..fa758e88b4c 100644
--- a/chromium/components/arc/ime/arc_ime_service.h
+++ b/chromium/components/arc/ime/arc_ime_service.h
@@ -85,17 +85,19 @@ class ArcImeService : public KeyedService,
// Overridden from ArcImeBridge::Delegate:
void OnTextInputTypeChanged(ui::TextInputType type) override;
- void OnCursorRectChanged(const gfx::Rect& rect) override;
+ void OnCursorRectChanged(const gfx::Rect& rect,
+ bool is_screen_coordinates) override;
void OnCancelComposition() override;
void ShowImeIfNeeded() override;
void OnCursorRectChangedWithSurroundingText(
const gfx::Rect& rect,
const gfx::Range& text_range,
const base::string16& text_in_range,
- const gfx::Range& selection_range) override;
+ const gfx::Range& selection_range,
+ bool is_screen_coordinates) override;
// Overridden from keyboard::KeyboardControllerObserver.
- void OnKeyboardAppearanceChanging(
+ void OnKeyboardAppearanceChanged(
const keyboard::KeyboardStateDescriptor& state) override;
// Overridden from ui::TextInputClient:
@@ -134,6 +136,11 @@ class ArcImeService : public KeyedService,
}
const std::string& GetClientSourceInfo() const 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);
+
private:
ui::InputMethod* GetInputMethod();
@@ -145,6 +152,10 @@ class ArcImeService : public KeyedService,
void InvalidateSurroundingTextAndSelectionRange();
+ // Converts |rect| passed from the client to the host's cooridnates and
+ // updates |cursor_rect_|. Returns whether or not the stored value changed.
+ bool UpdateCursorRect(const gfx::Rect& rect, bool is_screen_coordinates);
+
std::unique_ptr<ArcImeBridge> ime_bridge_;
std::unique_ptr<ArcWindowDelegate> arc_window_delegate_;
ui::TextInputType ime_type_;
diff --git a/chromium/components/arc/ime/arc_ime_service_unittest.cc b/chromium/components/arc/ime/arc_ime_service_unittest.cc
index 34e759f5be2..f60d6336883 100644
--- a/chromium/components/arc/ime/arc_ime_service_unittest.cc
+++ b/chromium/components/arc/ime/arc_ime_service_unittest.cc
@@ -26,7 +26,8 @@ namespace {
class FakeArcImeBridge : public ArcImeBridge {
public:
- FakeArcImeBridge() : count_send_insert_text_(0) {}
+ FakeArcImeBridge()
+ : count_send_insert_text_(0), last_keyboard_availability_(false) {}
void SendSetCompositionText(const ui::CompositionText& composition) override {
}
@@ -39,12 +40,22 @@ class FakeArcImeBridge : public ArcImeBridge {
}
void SendOnKeyboardAppearanceChanging(const gfx::Rect& new_bounds,
bool is_available) override {
+ last_keyboard_bounds_ = new_bounds;
+ last_keyboard_availability_ = is_available;
}
int count_send_insert_text() const { return count_send_insert_text_; }
+ const gfx::Rect& last_keyboard_bounds() const {
+ return last_keyboard_bounds_;
+ }
+ bool last_keyboard_availability() const {
+ return last_keyboard_availability_;
+ }
private:
int count_send_insert_text_;
+ gfx::Rect last_keyboard_bounds_;
+ bool last_keyboard_availability_;
};
class FakeInputMethod : public ui::DummyInputMethod {
@@ -167,6 +178,7 @@ class ArcImeServiceTest : public testing::Test {
}
void TearDown() override {
+ ArcImeService::SetOverrideDefaultDeviceScaleFactorForTesting(base::nullopt);
arc_win_.reset();
fake_window_delegate_ = nullptr;
fake_arc_ime_bridge_ = nullptr;
@@ -303,7 +315,8 @@ TEST_F(ArcImeServiceTest, GetTextFromRange) {
const gfx::Range selection_range(cursor_pos, cursor_pos);
instance_->OnCursorRectChangedWithSurroundingText(
- gfx::Rect(0, 0, 1, 1), text_range, text_in_range, selection_range);
+ gfx::Rect(0, 0, 1, 1), text_range, text_in_range, selection_range,
+ true /* is_screen_coordinates */);
gfx::Range temp;
instance_->GetTextRange(&temp);
@@ -317,4 +330,56 @@ TEST_F(ArcImeServiceTest, GetTextFromRange) {
EXPECT_EQ(selection_range, temp);
}
+TEST_F(ArcImeServiceTest, OnKeyboardAppearanceChanged) {
+ instance_->OnWindowFocused(arc_win_.get(), nullptr);
+ EXPECT_EQ(gfx::Rect(), fake_arc_ime_bridge_->last_keyboard_bounds());
+ EXPECT_FALSE(fake_arc_ime_bridge_->last_keyboard_availability());
+
+ const gfx::Rect keyboard_bounds(0, 480, 1200, 320);
+ keyboard::KeyboardStateDescriptor desc1{true, false, keyboard_bounds,
+ keyboard_bounds, keyboard_bounds};
+ instance_->OnKeyboardAppearanceChanged(desc1);
+ EXPECT_EQ(keyboard_bounds, fake_arc_ime_bridge_->last_keyboard_bounds());
+ EXPECT_TRUE(fake_arc_ime_bridge_->last_keyboard_availability());
+
+ // Change the default scale factor of the internal display.
+ const double new_scale_factor = 10.0;
+ const gfx::Rect new_keyboard_bounds(
+ 0 * new_scale_factor, 480 * new_scale_factor, 1200 * new_scale_factor,
+ 320 * new_scale_factor);
+ instance_->SetOverrideDefaultDeviceScaleFactorForTesting(new_scale_factor);
+
+ // Keyboard bounds passed to Android should be changed.
+ instance_->OnKeyboardAppearanceChanged(desc1);
+ EXPECT_EQ(new_keyboard_bounds, fake_arc_ime_bridge_->last_keyboard_bounds());
+ EXPECT_TRUE(fake_arc_ime_bridge_->last_keyboard_availability());
+}
+
+TEST_F(ArcImeServiceTest, GetCaretBounds) {
+ EXPECT_EQ(gfx::Rect(), instance_->GetCaretBounds());
+
+ const gfx::Rect window_rect(123, 321, 100, 100);
+ arc_win_->SetBounds(window_rect);
+ instance_->OnWindowFocused(arc_win_.get(), nullptr);
+
+ const gfx::Rect cursor_rect(10, 12, 2, 8);
+ instance_->OnCursorRectChanged(cursor_rect, true); // screen coordinates
+ EXPECT_EQ(cursor_rect, instance_->GetCaretBounds());
+
+ instance_->OnCursorRectChanged(cursor_rect, false); // window coordinates
+ EXPECT_EQ(cursor_rect + window_rect.OffsetFromOrigin(),
+ instance_->GetCaretBounds());
+
+ const double new_scale_factor = 10.0;
+ const gfx::Rect new_cursor_rect(10 * new_scale_factor, 12 * new_scale_factor,
+ 2 * new_scale_factor, 8 * new_scale_factor);
+ instance_->SetOverrideDefaultDeviceScaleFactorForTesting(new_scale_factor);
+ instance_->OnCursorRectChanged(new_cursor_rect, true); // screen coordinates
+ EXPECT_EQ(cursor_rect, instance_->GetCaretBounds());
+
+ instance_->OnCursorRectChanged(new_cursor_rect, false); // window coordinates
+ EXPECT_EQ(cursor_rect + window_rect.OffsetFromOrigin(),
+ instance_->GetCaretBounds());
+}
+
} // namespace arc
diff --git a/chromium/components/arc/intent_helper/DEPS b/chromium/components/arc/intent_helper/DEPS
index 71b171809a0..18765ba069a 100644
--- a/chromium/components/arc/intent_helper/DEPS
+++ b/chromium/components/arc/intent_helper/DEPS
@@ -2,11 +2,13 @@ include_rules = [
"+ash/link_handler_model.h",
"+ash/link_handler_model_factory.h",
"+ash/new_window_controller.h",
+ "+ash/public",
"+ash/shell.h",
"+ash/shell_delegate.h",
- "+ash/wallpaper/wallpaper_controller.h",
"+components/google/core/browser",
"+components/url_formatter",
+ "+content/public/common/service_manager_connection.h",
+ "+services/service_manager/public/cpp/connector.h",
"+ui/base",
"+ui/gfx",
]
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 a80e61b4e0c..653614ba259 100644
--- a/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc
+++ b/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc
@@ -8,9 +8,10 @@
#include <utility>
#include "ash/new_window_controller.h"
+#include "ash/public/interfaces/constants.mojom.h"
+#include "ash/public/interfaces/wallpaper.mojom.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
-#include "ash/wallpaper/wallpaper_controller.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
@@ -20,6 +21,8 @@
#include "components/arc/arc_service_manager.h"
#include "components/arc/audio/arc_audio_bridge.h"
#include "components/url_formatter/url_fixer.h"
+#include "content/public/common/service_manager_connection.h"
+#include "services/service_manager/public/cpp/connector.h"
#include "ui/base/layout.h"
#include "url/url_constants.h"
@@ -189,9 +192,11 @@ void ArcIntentHelperBridge::OnOpenChromePage(mojom::ChromePage page) {
void ArcIntentHelperBridge::OpenWallpaperPicker() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- // TODO(mash): Support this functionality without ash::Shell access in Chrome.
- if (ash::Shell::HasInstance())
- ash::Shell::Get()->wallpaper_controller()->OpenSetWallpaperPage();
+ ash::mojom::WallpaperControllerPtr wallpaper_controller_ptr;
+ content::ServiceManagerConnection::GetForProcess()
+ ->GetConnector()
+ ->BindInterface(ash::mojom::kServiceName, &wallpaper_controller_ptr);
+ wallpaper_controller_ptr->OpenWallpaperPickerIfAllowed();
}
void ArcIntentHelperBridge::SetWallpaperDeprecated(
diff --git a/chromium/components/arc/midis/arc_midis_bridge.cc b/chromium/components/arc/midis/arc_midis_bridge.cc
index 657fcc4e32b..2ba7218fb3a 100644
--- a/chromium/components/arc/midis/arc_midis_bridge.cc
+++ b/chromium/components/arc/midis/arc_midis_bridge.cc
@@ -100,9 +100,9 @@ void ArcMidisBridge::Connect(mojom::MidisServerRequest request,
->GetArcMidisClient()
->BootstrapMojoConnection(
std::move(fd),
- base::Bind(&ArcMidisBridge::OnBootstrapMojoConnection,
- weak_factory_.GetWeakPtr(), base::Passed(&request),
- base::Passed(&client_ptr)));
+ base::BindOnce(&ArcMidisBridge::OnBootstrapMojoConnection,
+ weak_factory_.GetWeakPtr(), std::move(request),
+ std::move(client_ptr)));
}
} // namespace arc
diff --git a/chromium/components/arc/power/arc_power_bridge.cc b/chromium/components/arc/power/arc_power_bridge.cc
index b584cd6135c..d110d313038 100644
--- a/chromium/components/arc/power/arc_power_bridge.cc
+++ b/chromium/components/arc/power/arc_power_bridge.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "ash/shell.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "chromeos/dbus/dbus_thread_manager.h"
@@ -16,9 +17,9 @@
#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
#include "components/arc/arc_service_manager.h"
#include "content/public/common/service_manager_connection.h"
-#include "services/device/public/interfaces/constants.mojom.h"
-#include "services/device/public/interfaces/wake_lock.mojom.h"
-#include "services/device/public/interfaces/wake_lock_provider.mojom.h"
+#include "services/device/public/mojom/constants.mojom.h"
+#include "services/device/public/mojom/wake_lock.mojom.h"
+#include "services/device/public/mojom/wake_lock_provider.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace arc {
@@ -175,9 +176,9 @@ void ArcPowerBridge::SuspendImminent(
if (!power_instance)
return;
- power_instance->Suspend(
- chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
- GetSuspendReadinessCallback());
+ power_instance->Suspend(chromeos::DBusThreadManager::Get()
+ ->GetPowerManagerClient()
+ ->GetSuspendReadinessCallback(FROM_HERE));
}
void ArcPowerBridge::SuspendDone(const base::TimeDelta& sleep_duration) {
diff --git a/chromium/components/arc/power/arc_power_bridge.h b/chromium/components/arc/power/arc_power_bridge.h
index 31894c4b53b..e21306fdeef 100644
--- a/chromium/components/arc/power/arc_power_bridge.h
+++ b/chromium/components/arc/power/arc_power_bridge.h
@@ -14,7 +14,7 @@
#include "components/arc/common/power.mojom.h"
#include "components/arc/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "services/device/public/interfaces/wake_lock.mojom.h"
+#include "services/device/public/mojom/wake_lock.mojom.h"
#include "ui/display/manager/chromeos/display_configurator.h"
namespace content {
diff --git a/chromium/components/arc/timer/arc_timer.cc b/chromium/components/arc/timer/arc_timer.cc
new file mode 100644
index 00000000000..8f51afb6e25
--- /dev/null
+++ b/chromium/components/arc/timer/arc_timer.cc
@@ -0,0 +1,76 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/timer/arc_timer.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/posix/unix_domain_socket.h"
+#include "base/threading/thread_restrictions.h"
+
+namespace arc {
+
+ArcTimer::ArcTimer(base::ScopedFD expiration_fd,
+ mojo::InterfaceRequest<mojom::Timer> request,
+ ConnectionErrorCallback connection_error_callback)
+ : binding_(this, std::move(request)),
+ expiration_fd_(std::move(expiration_fd)),
+ connection_error_callback_(std::move(connection_error_callback)) {
+ // It's safe to pass |this| because the error handler will be reset when
+ // the |binding_| is unbound or closed.
+ binding_.set_connection_error_handler(
+ base::BindOnce(&ArcTimer::HandleConnectionError, base::Unretained(this)));
+}
+
+ArcTimer::~ArcTimer() = default;
+
+void ArcTimer::Start(base::TimeTicks absolute_expiration_time,
+ StartCallback callback) {
+ // Start the timer to expire at |absolute_expiration_time|. This call
+ // automatically overrides the previous timer set.
+ //
+ // If the firing time has expired then set the timer to expire
+ // immediately.
+ base::TimeTicks current_time_ticks = base::TimeTicks::Now();
+ base::TimeDelta delay;
+ if (absolute_expiration_time > current_time_ticks)
+ delay = absolute_expiration_time - current_time_ticks;
+ base::Time current_time = base::Time::Now();
+ DVLOG(1) << "CurrentTime: " << current_time
+ << " NextAlarmAt: " << current_time + delay;
+ // It's safe to pass |this| because on destruction of this object the
+ // timer is stopped and the callback can't be invoked.
+ timer_.Start(
+ FROM_HERE, delay,
+ base::BindRepeating(&ArcTimer::OnExpiration, base::Unretained(this)));
+ std::move(callback).Run(arc::mojom::ArcTimerResult::SUCCESS);
+}
+
+void ArcTimer::HandleConnectionError() {
+ // Stop any pending timers when connection with the instance is dropped.
+ timer_.Stop();
+ std::move(connection_error_callback_).Run(this);
+}
+
+void ArcTimer::OnExpiration() {
+ DVLOG(1) << "Expiration callback";
+ base::AssertBlockingAllowed();
+ // The instance expects 8 bytes on the read end similar to what happens on
+ // a timerfd expiration. The timerfd API expects this to be the number of
+ // expirations, however, more than one expiration isn't tracked currently.
+ const uint64_t timer_data = 1;
+ if (!base::UnixDomainSocket::SendMsg(expiration_fd_.get(), &timer_data,
+ sizeof(timer_data),
+ std::vector<int>())) {
+ LOG(ERROR) << "Failed to indicate timer expiration to the instance";
+ }
+}
+
+} // namespace arc
diff --git a/chromium/components/arc/timer/arc_timer.h b/chromium/components/arc/timer/arc_timer.h
new file mode 100644
index 00000000000..ad16408c64b
--- /dev/null
+++ b/chromium/components/arc/timer/arc_timer.h
@@ -0,0 +1,79 @@
+// Copyright 2018 The Chromium Authors. All 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_TIMER_ARC_TIMER_H_
+#define COMPONENTS_ARC_TIMER_ARC_TIMER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <set>
+
+#include "base/callback.h"
+#include "base/files/file.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/time/time.h"
+#include "components/arc/common/timer.mojom.h"
+#include "components/arc/timer/create_timer_request.h"
+#include "components/timers/alarm_timer_chromeos.h"
+#include "mojo/public/cpp/bindings/binding.h"
+
+namespace arc {
+
+// Implements the timer interface exported to the instance. All accesses to an
+// instance of this class must happen on a single sequence that supports
+// blocking operations and the |base::FileDescriptorWatcher| API.
+//
+// In the current implementation, |ArcTimer| objects are bound to a mojo proxy
+// on a separate sequence in |arc_timer_bridge.cc|. Mojo guarantees to call
+// all callbacks on the sequence that the mojo::Binding was created on.
+// Consequently, even the timer expiration i.e. |OnExpiration| happens on the
+// sequence and is allowed to do I/O.
+class ArcTimer : public mojom::Timer {
+ // Called when there is connection error on the mojo |binding_|. Called on the
+ // the sequence this object was created on.
+ using ConnectionErrorCallback = base::OnceCallback<void(ArcTimer* timer)>;
+
+ public:
+ ArcTimer(base::ScopedFD expiration_fd,
+ mojo::InterfaceRequest<mojom::Timer> request,
+ ConnectionErrorCallback connection_error_callback);
+ ~ArcTimer() override;
+
+ // mojom::Timer overrides. Runs on the sequence this object was created
+ // on since this class is bound to a mojo proxy on a separate sequence.
+ void Start(base::TimeTicks absolute_expiration_time,
+ StartCallback callback) override;
+
+ private:
+ // Handles connection errors with the instance. Runs on the sequence this
+ // object was created on.
+ void HandleConnectionError();
+
+ // Callback fired when the timer in |ArcTimer| expires. Runs on the sequence
+ // this object was created on.
+ void OnExpiration();
+
+ mojo::Binding<mojom::Timer> binding_;
+
+ // The timer that will be scheduled. Only accessed from the sequence on which
+ // this object is created.
+ timers::SimpleAlarmTimer timer_;
+
+ // The file descriptor which will be written to when |timer| expires. Only
+ // accessed from the sequence on which this object is created.
+ base::ScopedFD expiration_fd_;
+
+ ConnectionErrorCallback connection_error_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(ArcTimer);
+};
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_TIMER_ARC_TIMER_H_
diff --git a/chromium/components/arc/timer/arc_timer_bridge.cc b/chromium/components/arc/timer/arc_timer_bridge.cc
new file mode 100644
index 00000000000..9206c22e0cf
--- /dev/null
+++ b/chromium/components/arc/timer/arc_timer_bridge.cc
@@ -0,0 +1,248 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utility>
+
+#include "base/containers/flat_set.h"
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/stl_util.h"
+#include "base/task_runner_util.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/arc/arc_bridge_service.h"
+#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/timer/arc_timer.h"
+#include "components/arc/timer/arc_timer_bridge.h"
+#include "components/arc/timer/arc_timer_traits.h"
+
+namespace arc {
+
+namespace {
+
+// Singleton factory for ArcTimerBridge.
+class ArcTimerBridgeFactory
+ : public internal::ArcBrowserContextKeyedServiceFactoryBase<
+ ArcTimerBridge,
+ ArcTimerBridgeFactory> {
+ public:
+ // Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
+ static constexpr const char* kName = "ArcTimerBridgeFactory";
+
+ static ArcTimerBridgeFactory* GetInstance() {
+ return base::Singleton<ArcTimerBridgeFactory>::get();
+ }
+
+ private:
+ friend base::DefaultSingletonTraits<ArcTimerBridgeFactory>;
+ ArcTimerBridgeFactory() = default;
+ ~ArcTimerBridgeFactory() override = default;
+};
+
+bool IsSupportedClock(int32_t clock_id) {
+ return clock_id == CLOCK_BOOTTIME_ALARM || clock_id == CLOCK_REALTIME_ALARM;
+}
+
+} // namespace
+
+// static
+BrowserContextKeyedServiceFactory* ArcTimerBridge::GetFactory() {
+ return ArcTimerBridgeFactory::GetInstance();
+}
+
+// static
+ArcTimerBridge* ArcTimerBridge::GetForBrowserContext(
+ content::BrowserContext* context) {
+ return ArcTimerBridgeFactory::GetForBrowserContext(context);
+}
+
+// static
+ArcTimerBridge* ArcTimerBridge::GetForBrowserContextForTesting(
+ content::BrowserContext* context) {
+ return ArcTimerBridgeFactory::GetForBrowserContextForTesting(context);
+}
+
+ArcTimerBridge::ArcTimerBridge(content::BrowserContext* context,
+ ArcBridgeService* bridge_service)
+ : timer_task_runner_(
+ base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})),
+ arc_bridge_service_(bridge_service),
+ binding_(this),
+ weak_ptr_factory_(this) {
+ arc_bridge_service_->timer()->SetHost(this);
+ arc_bridge_service_->timer()->AddObserver(this);
+}
+
+ArcTimerBridge::~ArcTimerBridge() {
+ arc_bridge_service_->timer()->RemoveObserver(this);
+ arc_bridge_service_->timer()->SetHost(nullptr);
+}
+
+void ArcTimerBridge::CreateTimers(
+ std::vector<CreateTimerRequest> arc_timer_requests,
+ CreateTimersCallback callback) {
+ DVLOG(1) << "Received CreateTimers";
+ // Alarm timers can't be created on the UI thread because they make syscalls
+ // in the constructor. Post a task to create |ArcTimer| objects containing
+ // alarm timer objects.
+ base::PostTaskAndReplyWithResult(
+ timer_task_runner_.get(), FROM_HERE,
+ base::BindOnce(&CreateArcTimers, !arc_timers_.empty(),
+ base::SequencedTaskRunnerHandle::Get(), timer_task_runner_,
+ std::move(arc_timer_requests),
+ weak_ptr_factory_.GetWeakPtr()),
+ base::BindOnce(&ArcTimerBridge::OnArcTimersCreated,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void ArcTimerBridge::OnConnectionClosed() {
+ DVLOG(1) << "OnConnectionClosed";
+ DeleteArcTimers();
+}
+
+// Deleter for |ArcTimer|s. Deletes the timer object on |task_runner|.
+class ArcTimerBridge::DeleteOnSequence {
+ public:
+ explicit DeleteOnSequence(
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : task_runner_(std::move(task_runner)) {}
+ ~DeleteOnSequence() = default;
+ DeleteOnSequence(DeleteOnSequence&&) = default;
+ DeleteOnSequence& operator=(DeleteOnSequence&&) = default;
+
+ void operator()(ArcTimer* timer) const {
+ task_runner_->DeleteSoon(FROM_HERE, timer);
+ }
+
+ private:
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeleteOnSequence);
+};
+
+void ArcTimerBridge::OnConnectionError(ArcTimer* timer) {
+ DVLOG(1) << "OnConnectionError";
+ // At this point the mojo binding for |timer| has an error. Find and delete
+ // the timer. Since the lifetime of |ArcTimer| objects is managed by this
+ // class it is safe to compare |timer|.
+ base::EraseIf(
+ arc_timers_,
+ [timer](const std::unique_ptr<ArcTimer, DeleteOnSequence>& element) {
+ return element.get() == timer;
+ });
+}
+
+// static.
+void ArcTimerBridge::OnConnectionErrorOnTimerThread(
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ base::WeakPtr<ArcTimerBridge> weak_self,
+ ArcTimer* timer) {
+ // Post task on the main thread since the task will access class members.
+ task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ArcTimerBridge::OnConnectionError, weak_self, timer));
+}
+
+struct ArcTimerBridge::TimersAndProxies {
+ TimersAndProxies() = default;
+ ~TimersAndProxies() = default;
+ TimersAndProxies(TimersAndProxies&&) = default;
+ TimersAndProxies& operator=(TimersAndProxies&&) = default;
+ std::vector<int32_t> clocks;
+ std::vector<std::unique_ptr<ArcTimer, DeleteOnSequence>> timers;
+ std::vector<mojom::TimerPtrInfo> proxies;
+};
+
+// static.
+base::Optional<ArcTimerBridge::TimersAndProxies>
+ArcTimerBridge::CreateArcTimers(
+ bool timers_already_created,
+ scoped_refptr<base::SequencedTaskRunner> original_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> timer_task_runner,
+ std::vector<arc::CreateTimerRequest> arc_timer_requests,
+ base::WeakPtr<ArcTimerBridge> weak_self) {
+ if (timers_already_created) {
+ LOG(ERROR) << "Double creation not supported";
+ return base::nullopt;
+ }
+
+ // Iterate over the list of {clock_id, expiration_fd} and create an |ArcTimer|
+ // and |mojom::TimerPtrInfo| entry for each clock.
+ base::flat_set<int32_t> seen_clocks;
+ ArcTimerBridge::TimersAndProxies result;
+ for (auto& request : arc_timer_requests) {
+ // Read each entry one by one. Each entry will have an |ArcTimer| entry
+ // associated with it.
+ int32_t clock_id = request.clock_id;
+
+ if (!IsSupportedClock(clock_id)) {
+ LOG(ERROR) << "Unsupported clock=" << clock_id;
+ return base::nullopt;
+ }
+
+ if (!seen_clocks.insert(clock_id).second) {
+ LOG(ERROR) << "Duplicate clocks not supported";
+ return base::nullopt;
+ }
+
+ base::ScopedFD expiration_fd = std::move(request.expiration_fd);
+ if (!expiration_fd.is_valid()) {
+ LOG(ERROR) << "Bad file descriptor for clock=" << clock_id;
+ return base::nullopt;
+ }
+
+ mojom::TimerPtrInfo timer_proxy_info;
+ // TODO(b/69759087): Make |ArcTimer| take |clock_id| to create timers of
+ // different clock types.
+ // The instance opens clocks of type CLOCK_BOOTTIME_ALARM and
+ // CLOCK_REALTIME_ALARM. However, it uses only CLOCK_BOOTTIME_ALARM to set
+ // wake up alarms. At this point, it's okay to pretend the host supports
+ // CLOCK_REALTIME_ALARM instead of returning an error.
+ //
+ // Mojo guarantees to call all callbacks on the task runner that the
+ // mojo::Binding i.e. |ArcTimer| was created on.
+ result.clocks.push_back(clock_id);
+ result.timers.push_back(std::unique_ptr<ArcTimer, DeleteOnSequence>(
+ new ArcTimer(
+ std::move(expiration_fd), mojo::MakeRequest(&timer_proxy_info),
+ base::BindOnce(&ArcTimerBridge::OnConnectionErrorOnTimerThread,
+ original_task_runner, weak_self)),
+ DeleteOnSequence(timer_task_runner)));
+ result.proxies.push_back(std::move(timer_proxy_info));
+ }
+ return result;
+}
+
+void ArcTimerBridge::OnArcTimersCreated(
+ CreateTimersCallback callback,
+ base::Optional<TimersAndProxies> timers_and_proxies) {
+ if (timers_and_proxies == base::nullopt) {
+ std::move(callback).Run(base::nullopt);
+ return;
+ }
+ DCHECK_EQ(timers_and_proxies->clocks.size(),
+ timers_and_proxies->timers.size());
+ DCHECK_EQ(timers_and_proxies->clocks.size(),
+ timers_and_proxies->proxies.size());
+ arc_timers_ = std::move(timers_and_proxies->timers);
+
+ // Respond to instance with timer proxies.
+ std::vector<mojom::CreateTimerResponsePtr> result;
+ for (size_t i = 0; i < timers_and_proxies->clocks.size(); i++) {
+ mojom::CreateTimerResponsePtr response = mojom::CreateTimerResponse::New();
+ response->clock_id =
+ mojo::EnumTraits<arc::mojom::ClockId, int32_t>::ToMojom(
+ timers_and_proxies->clocks[i]);
+ response->timer = std::move(timers_and_proxies->proxies[i]);
+ result.push_back(std::move(response));
+ }
+ std::move(callback).Run(std::move(result));
+}
+
+void ArcTimerBridge::DeleteArcTimers() {
+ // The timer objects are deleted on |timer_task_runner_|.
+ arc_timers_.clear();
+}
+
+} // namespace arc
diff --git a/chromium/components/arc/timer/arc_timer_bridge.h b/chromium/components/arc/timer/arc_timer_bridge.h
new file mode 100644
index 00000000000..57603a09f56
--- /dev/null
+++ b/chromium/components/arc/timer/arc_timer_bridge.h
@@ -0,0 +1,111 @@
+// Copyright 2018 The Chromium Authors. All 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_TIMER_ARC_TIMER_BRIDGE_H_
+#define COMPONENTS_ARC_TIMER_ARC_TIMER_BRIDGE_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/sequenced_task_runner.h"
+#include "components/arc/common/timer.mojom.h"
+#include "components/arc/connection_observer.h"
+#include "components/arc/timer/arc_timer.h"
+#include "components/arc/timer/create_timer_request.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "mojo/public/cpp/bindings/binding.h"
+
+class BrowserContextKeyedServiceFactory;
+
+namespace content {
+class BrowserContext;
+} // namespace content
+
+namespace arc {
+
+class ArcBridgeService;
+
+// Sets wake up timers / alarms based on calls from the instance.
+class ArcTimerBridge : public KeyedService,
+ public ConnectionObserver<mojom::TimerInstance>,
+ public mojom::TimerHost {
+ public:
+ // Returns the factory instance for this class.
+ static BrowserContextKeyedServiceFactory* GetFactory();
+
+ // Returns singleton instance for the given BrowserContext,
+ // or nullptr if the browser |context| is not allowed to use ARC.
+ static ArcTimerBridge* GetForBrowserContext(content::BrowserContext* context);
+
+ static ArcTimerBridge* GetForBrowserContextForTesting(
+ content::BrowserContext* context);
+
+ ArcTimerBridge(content::BrowserContext* context,
+ ArcBridgeService* bridge_service);
+ ~ArcTimerBridge() override;
+
+ // ConnectionObserver<mojom::TimerInstance>::Observer overrides.
+ void OnConnectionClosed() override;
+
+ // mojom::TimerHost overrides.
+ void CreateTimers(std::vector<CreateTimerRequest> arc_timer_requests,
+ CreateTimersCallback callback) override;
+
+ private:
+ class DeleteOnSequence;
+ struct TimersAndProxies;
+
+ // Deletes |timer| from |arc_timers_|.
+ void OnConnectionError(ArcTimer* timer);
+
+ // Callback invoked when an |ArcTimer| object has a connection error on it's
+ // mojo binding. It schedules |OnConnectionErrror| on |task_runner| which
+ // finally deletes |timer|. Since, |ArcTimerBridge| lives on the main thread
+ // and this function runs on |timer_task_runner_| this function needs to be
+ // static to be thread safe.
+ static void OnConnectionErrorOnTimerThread(
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ base::WeakPtr<ArcTimerBridge> weak_self,
+ ArcTimer* timer);
+
+ // Creates timers with the given arguments. Returns base::nullopt on failure.
+ // On success, returns a non-empty vector of |TimersAndProxies| objects. Runs
+ // on |timer_task_runner| and should only access thread-safe members of the
+ // parent class. For this reason it is also a static member.
+ static base::Optional<TimersAndProxies> CreateArcTimers(
+ bool timers_already_created,
+ scoped_refptr<base::SequencedTaskRunner> original_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> timer_task_runner,
+ std::vector<arc::CreateTimerRequest> arc_timer_requests,
+ base::WeakPtr<ArcTimerBridge> weak_self);
+
+ // Callback for |CreateArcTimers|. Runs |callback| before exiting. Runs on the
+ // main thread.
+ void OnArcTimersCreated(CreateTimersCallback callback,
+ base::Optional<TimersAndProxies> timers_and_proxies);
+
+ // Deletes all timers.
+ void DeleteArcTimers();
+
+ // Task runner on which all |ArcTimer| related operations are scheduled.
+ scoped_refptr<base::SequencedTaskRunner> timer_task_runner_;
+
+ ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
+
+ // Store of |ArcTimer| objects.
+ std::vector<std::unique_ptr<ArcTimer, DeleteOnSequence>> arc_timers_;
+
+ mojo::Binding<mojom::TimerHost> binding_;
+
+ base::WeakPtrFactory<ArcTimerBridge> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ArcTimerBridge);
+};
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_TIMER_ARC_TIMER_BRIDGE_H_
diff --git a/chromium/components/arc/timer/arc_timer_bridge_unittest.cc b/chromium/components/arc/timer/arc_timer_bridge_unittest.cc
new file mode 100644
index 00000000000..56b51b7d6c2
--- /dev/null
+++ b/chromium/components/arc/timer/arc_timer_bridge_unittest.cc
@@ -0,0 +1,278 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <map>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#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/test/scoped_task_environment.h"
+#include "base/time/time.h"
+#include "components/arc/arc_bridge_service.h"
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/common/timer.mojom.h"
+#include "components/arc/connection_holder.h"
+#include "components/arc/test/connection_holder_util.h"
+#include "components/arc/test/fake_timer_instance.h"
+#include "components/arc/test/test_browser_context.h"
+#include "components/arc/timer/arc_timer_bridge.h"
+#include "components/arc/timer/arc_timer_traits.h"
+#include "components/arc/timer/create_timer_request.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+
+namespace {
+
+class ArcTimerTest : public testing::Test {
+ public:
+ ArcTimerTest()
+ : scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::IO),
+ timer_bridge_(
+ ArcTimerBridge::GetForBrowserContextForTesting(&context_)) {
+ // This results in ArcTimerBridge::OnInstanceReady being called.
+ ArcServiceManager::Get()->arc_bridge_service()->timer()->SetInstance(
+ &timer_instance_);
+ WaitForInstanceReady(
+ ArcServiceManager::Get()->arc_bridge_service()->timer());
+ }
+
+ ~ArcTimerTest() override {
+ // Destroys the FakeTimerInstance. This results in
+ // ArcTimerBridge::OnInstanceClosed being called.
+ ArcServiceManager::Get()->arc_bridge_service()->timer()->CloseInstance(
+ &timer_instance_);
+ timer_bridge_->Shutdown();
+ }
+
+ protected:
+ FakeTimerInstance* GetFakeTimerInstance() { return &timer_instance_; }
+
+ private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ ArcServiceManager arc_service_manager_;
+ TestBrowserContext context_;
+ FakeTimerInstance timer_instance_;
+
+ ArcTimerBridge* const timer_bridge_;
+
+ DISALLOW_COPY_AND_ASSIGN(ArcTimerTest);
+};
+
+// Stores timer proxies associated with each clock's timer.
+class ArcTimerStore {
+ public:
+ ArcTimerStore() = default;
+
+ bool AddTimer(clockid_t clock_id, base::ScopedFD read_fd) {
+ ArcTimerStore::ArcTimerInfo arc_timer_info;
+ arc_timer_info.read_fd = std::move(read_fd);
+ auto emplace_result =
+ arc_timers_.emplace(clock_id, std::move(arc_timer_info));
+ if (!emplace_result.second)
+ ADD_FAILURE() << "Failed to create timer entry";
+ return emplace_result.second;
+ }
+
+ void ClearTimers() { return arc_timers_.clear(); }
+
+ base::Optional<int> GetTimerReadFd(clockid_t clock_id) {
+ if (!HasTimer(clock_id))
+ return base::nullopt;
+ return base::Optional<int>(arc_timers_[clock_id].read_fd.get());
+ }
+
+ mojom::TimerPtr* GetTimerProxy(clockid_t clock_id) {
+ if (!HasTimer(clock_id))
+ return nullptr;
+ return &arc_timers_[clock_id].timer;
+ }
+
+ bool HasTimer(clockid_t clock_id) {
+ auto it = arc_timers_.find(clock_id);
+ return (it != arc_timers_.end() && it->second.timer);
+ }
+
+ bool SetTimerProxy(clockid_t clock_id, mojom::TimerPtrInfo timer) {
+ // An entry for storing the timer proxy should already be present.
+ auto it = arc_timers_.find(clock_id);
+ if (it == arc_timers_.end())
+ return false;
+ it->second.timer = mojom::TimerPtr(std::move(timer));
+ return true;
+ }
+
+ size_t size() const { return arc_timers_.size(); }
+
+ private:
+ struct ArcTimerInfo {
+ // The mojom::Timer associated with an arc timer.
+ mojom::TimerPtr timer;
+
+ // The fd that will be signalled by the host when the timer expires.
+ base::ScopedFD read_fd;
+ };
+
+ std::map<clockid_t, ArcTimerInfo> arc_timers_;
+
+ DISALLOW_COPY_AND_ASSIGN(ArcTimerStore);
+};
+
+// Stores timer proxies returned by |mojom::TimerHost::CreateTimers|. Iff timers
+// for all clocks are created successfully, then |arc_timer_store| will have
+// proxies corresponding to each clock.
+void CreateTimersCallback(
+ ArcTimerStore* arc_timer_store,
+ base::OnceClosure quit_callback,
+ base::Optional<std::vector<mojom::CreateTimerResponsePtr>> result) {
+ base::ScopedClosureRunner quit_runner(std::move(quit_callback));
+
+ if (result == base::nullopt) {
+ ADD_FAILURE() << "Null timer objects array returned";
+ arc_timer_store->ClearTimers();
+ return;
+ }
+
+ const size_t responses_size = result.value().size();
+ if (responses_size != arc_timer_store->size()) {
+ ADD_FAILURE() << "Incorrect number of timer objects returned: "
+ << responses_size;
+ arc_timer_store->ClearTimers();
+ return;
+ }
+
+ // Store the timer objects. These will be retrieved to set timers.
+ for (auto& response : result.value()) {
+ int32_t clock_id;
+ if (!mojo::EnumTraits<arc::mojom::ClockId, int32_t>::FromMojom(
+ response->clock_id, &clock_id)) {
+ ADD_FAILURE() << "Failed to convert mojo clock id: "
+ << response->clock_id;
+ arc_timer_store->ClearTimers();
+ return;
+ }
+ EXPECT_TRUE(
+ arc_timer_store->SetTimerProxy(clock_id, std::move(response->timer)));
+ }
+}
+
+// Returns true iff timer creation of each clock type succeeded.
+bool CreateTimers(const std::vector<clockid_t>& clocks,
+ ArcTimerStore* arc_timer_store,
+ FakeTimerInstance* timer_instance) {
+ // Create requests to create a timer for each clock.
+ std::vector<CreateTimerRequest> arc_timer_requests;
+ for (const clockid_t& clock : clocks) {
+ CreateTimerRequest request;
+ request.clock_id = clock;
+ // Create a socket pair for each clock. One socket will be part of the mojo
+ // argument and will be used by the host to indicate when the timer expires.
+ // The other socket will be used to detect the expiration of the timer by
+ // epolling and reading.
+ base::ScopedFD read_fd;
+ base::ScopedFD write_fd;
+ if (!base::CreateSocketPair(&read_fd, &write_fd)) {
+ ADD_FAILURE() << "Failed to create socket pair for ARC timers";
+ return false;
+ }
+ request.expiration_fd = std::move(write_fd);
+ // Create an entry for each clock in the store. The timer object will be
+ // populated in the callback to the call to create timers.
+ if (!arc_timer_store->AddTimer(clock, std::move(read_fd))) {
+ ADD_FAILURE() << "Failed to create timer entry";
+ arc_timer_store->ClearTimers();
+ return false;
+ }
+ arc_timer_requests.emplace_back(std::move(request));
+ }
+ // Call the host to create timers.
+ base::RunLoop loop;
+ timer_instance->CallCreateTimers(
+ std::move(arc_timer_requests),
+ base::BindOnce(&CreateTimersCallback, arc_timer_store,
+ loop.QuitClosure()));
+ loop.Run();
+ // Check if each clock's timer is created successfully.
+ for (const clockid_t clock : clocks) {
+ if (!arc_timer_store->HasTimer(clock)) {
+ ADD_FAILURE() << "Failed to create timer for clock:" << clock;
+ return false;
+ }
+ }
+ return true;
+}
+
+// Returns true iff the read descriptor of a timer is signalled. If the
+// signalling is incorrect returns false. Blocks otherwise.
+bool WaitForExpiration(clockid_t clock_id, ArcTimerStore* arc_timer_store) {
+ if (!arc_timer_store->HasTimer(clock_id)) {
+ ADD_FAILURE() << "Timer of type: " << clock_id << " not present";
+ return false;
+ }
+
+ // Wait for the host to indicate expiration by watching the read end of the
+ // socket pair.
+ base::Optional<int> timer_read_fd_opt =
+ arc_timer_store->GetTimerReadFd(clock_id);
+ EXPECT_NE(timer_read_fd_opt, base::nullopt);
+ int timer_read_fd = timer_read_fd_opt.value();
+ // Required before watching a file descriptor.
+ base::FileDescriptorWatcher file_descriptor_watcher(
+ base::MessageLoopForIO::current());
+ base::RunLoop loop;
+ std::unique_ptr<base::FileDescriptorWatcher::Controller>
+ watch_readable_controller = base::FileDescriptorWatcher::WatchReadable(
+ timer_read_fd, loop.QuitClosure());
+ loop.Run();
+
+ // The timer expects 8 bytes to be written from the host upon expiration.
+ uint64_t timer_data;
+ std::vector<base::ScopedFD> fds;
+ ssize_t bytes_read = base::UnixDomainSocket::RecvMsg(
+ timer_read_fd, &timer_data, sizeof(timer_data), &fds);
+ if (bytes_read < static_cast<ssize_t>(sizeof(timer_data))) {
+ ADD_FAILURE() << "Incorrect timer wake up bytes_read: " << bytes_read;
+ return false;
+ }
+ LOG(INFO) << "Actual expiration time: " << base::Time::Now();
+ return true;
+}
+
+TEST_F(ArcTimerTest, StartTimer) {
+ std::vector<clockid_t> clocks = {CLOCK_REALTIME_ALARM, CLOCK_BOOTTIME_ALARM};
+ ArcTimerStore arc_timer_store;
+ // Create timers before starting it.
+ EXPECT_TRUE(CreateTimers(clocks, &arc_timer_store, GetFakeTimerInstance()));
+ mojom::TimerPtr* timer = arc_timer_store.GetTimerProxy(CLOCK_BOOTTIME_ALARM);
+ ASSERT_TRUE(timer);
+ ASSERT_TRUE(*timer);
+ // Start timer and check if timer expired.
+ base::TimeDelta delay = base::TimeDelta::FromMilliseconds(20);
+ base::RunLoop loop;
+ LOG(INFO) << "Start time: " << base::Time::Now()
+ << " Expiration time: " << base::Time::Now() + delay;
+ (*timer)->Start(base::TimeTicks::Now() + delay,
+ base::BindOnce(
+ [](base::RunLoop* loop, mojom::ArcTimerResult result) {
+ if (result != mojom::ArcTimerResult::SUCCESS)
+ ADD_FAILURE() << "Start timer failed";
+ loop->Quit();
+ },
+ &loop));
+ loop.Run();
+ EXPECT_TRUE(WaitForExpiration(CLOCK_BOOTTIME_ALARM, &arc_timer_store));
+}
+
+} // namespace
+
+} // namespace arc
diff --git a/chromium/components/arc/timer/arc_timer_traits.cc b/chromium/components/arc/timer/arc_timer_traits.cc
new file mode 100644
index 00000000000..d2feb07cd89
--- /dev/null
+++ b/chromium/components/arc/timer/arc_timer_traits.cc
@@ -0,0 +1,97 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utility>
+
+#include "base/posix/unix_domain_socket.h"
+#include "components/arc/timer/arc_timer_traits.h"
+#include "mojo/public/cpp/system/handle.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+
+namespace {
+
+// Unwraps a mojo handle to a file descriptor on the system.
+base::ScopedFD UnwrapPlatformHandle(mojo::ScopedHandle handle) {
+ base::PlatformFile platform_file;
+ if (mojo::UnwrapPlatformFile(std::move(handle), &platform_file) !=
+ MOJO_RESULT_OK) {
+ LOG(ERROR) << "Failed to unwrap mojo handle";
+ return base::ScopedFD();
+ }
+ return base::ScopedFD(platform_file);
+}
+
+// Converts a system file descriptor to a mojo handle that can be sent to the
+// host.
+mojo::ScopedHandle WrapPlatformFd(base::ScopedFD scoped_fd) {
+ mojo::ScopedHandle handle = mojo::WrapPlatformFile(scoped_fd.release());
+ if (!handle.is_valid()) {
+ LOG(ERROR) << "Failed to wrap platform handle";
+ return mojo::ScopedHandle();
+ }
+ return handle;
+}
+
+} // namespace
+
+namespace mojo {
+
+// static
+arc::mojom::ClockId EnumTraits<arc::mojom::ClockId, int32_t>::ToMojom(
+ int32_t clock_id) {
+ switch (clock_id) {
+ case CLOCK_REALTIME_ALARM:
+ return arc::mojom::ClockId::REALTIME_ALARM;
+ case CLOCK_BOOTTIME_ALARM:
+ return arc::mojom::ClockId::BOOTTIME_ALARM;
+ }
+ NOTREACHED();
+ return arc::mojom::ClockId::BOOTTIME_ALARM;
+}
+
+// static
+bool EnumTraits<arc::mojom::ClockId, int32_t>::FromMojom(
+ arc::mojom::ClockId input,
+ int32_t* output) {
+ switch (input) {
+ case arc::mojom::ClockId::REALTIME_ALARM:
+ *output = CLOCK_REALTIME_ALARM;
+ return true;
+ case arc::mojom::ClockId::BOOTTIME_ALARM:
+ *output = CLOCK_BOOTTIME_ALARM;
+ return true;
+ }
+ NOTREACHED();
+ return false;
+}
+
+// static
+arc::mojom::ClockId
+StructTraits<arc::mojom::CreateTimerRequestDataView, arc::CreateTimerRequest>::
+ clock_id(const arc::CreateTimerRequest& arc_timer_request) {
+ return EnumTraits<arc::mojom::ClockId, int32_t>::ToMojom(
+ arc_timer_request.clock_id);
+}
+
+// static
+mojo::ScopedHandle
+StructTraits<arc::mojom::CreateTimerRequestDataView, arc::CreateTimerRequest>::
+ expiration_fd(arc::CreateTimerRequest& arc_timer_request) {
+ return WrapPlatformFd(std::move(arc_timer_request.expiration_fd));
+}
+
+// static
+bool StructTraits<
+ arc::mojom::CreateTimerRequestDataView,
+ arc::CreateTimerRequest>::Read(arc::mojom::CreateTimerRequestDataView input,
+ arc::CreateTimerRequest* output) {
+ if (!EnumTraits<arc::mojom::ClockId, int32_t>::FromMojom(input.clock_id(),
+ &output->clock_id)) {
+ return false;
+ }
+ output->expiration_fd = UnwrapPlatformHandle(input.TakeExpirationFd());
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/components/arc/timer/arc_timer_traits.h b/chromium/components/arc/timer/arc_timer_traits.h
new file mode 100644
index 00000000000..252791ecdaa
--- /dev/null
+++ b/chromium/components/arc/timer/arc_timer_traits.h
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All 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_TIMER_ARC_TIMER_TRAITS_H_
+#define COMPONENTS_ARC_TIMER_ARC_TIMER_TRAITS_H_
+
+#include "components/arc/common/timer.mojom.h"
+#include "components/arc/timer/create_timer_request.h"
+
+namespace mojo {
+
+template <>
+struct EnumTraits<arc::mojom::ClockId, int32_t> {
+ static arc::mojom::ClockId ToMojom(int32_t clock_id);
+ static bool FromMojom(arc::mojom::ClockId input, int32_t* output);
+};
+
+template <>
+struct StructTraits<arc::mojom::CreateTimerRequestDataView,
+ arc::CreateTimerRequest> {
+ // Due to already defined EnumTraits for |ClockId| the return type is int32_t
+ // and not |arc::mojom::ClockId|.
+ static arc::mojom::ClockId clock_id(
+ const arc::CreateTimerRequest& arc_timer_request);
+
+ static mojo::ScopedHandle expiration_fd(
+ arc::CreateTimerRequest& arc_timer_request);
+
+ static bool Read(arc::mojom::CreateTimerRequestDataView input,
+ arc::CreateTimerRequest* output);
+};
+
+} // namespace mojo
+
+#endif // COMPONENTS_ARC_TIMER_ARC_TIMER_TRAITS_H_
diff --git a/chromium/components/arc/timer/create_timer_request.cc b/chromium/components/arc/timer/create_timer_request.cc
new file mode 100644
index 00000000000..95ca1fd8449
--- /dev/null
+++ b/chromium/components/arc/timer/create_timer_request.cc
@@ -0,0 +1,13 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/timer/create_timer_request.h"
+
+namespace arc {
+
+CreateTimerRequest::CreateTimerRequest() = default;
+CreateTimerRequest::CreateTimerRequest(CreateTimerRequest&&) = default;
+CreateTimerRequest::~CreateTimerRequest() = default;
+
+} // namespace arc
diff --git a/chromium/components/arc/timer/create_timer_request.h b/chromium/components/arc/timer/create_timer_request.h
new file mode 100644
index 00000000000..252e5cca506
--- /dev/null
+++ b/chromium/components/arc/timer/create_timer_request.h
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ARC_TIMER_CREATE_TIMER_REQUEST_H_
+#define COMPONENTS_ARC_TIMER_CREATE_TIMER_REQUEST_H_
+
+#include <stdint.h>
+
+#include "base/files/scoped_file.h"
+
+// Typemapping for |CreateTimerRequest| in timer.mojom
+namespace arc {
+
+struct CreateTimerRequest {
+ CreateTimerRequest();
+ CreateTimerRequest(CreateTimerRequest&&);
+ ~CreateTimerRequest();
+
+ int32_t clock_id;
+ base::ScopedFD expiration_fd;
+
+ DISALLOW_COPY_AND_ASSIGN(CreateTimerRequest);
+};
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_TIMER_CREATE_TIMER_REQUEST_H_
diff --git a/chromium/components/arc/usb/usb_host_bridge.cc b/chromium/components/arc/usb/usb_host_bridge.cc
index 52d3b557342..1a00796349e 100644
--- a/chromium/components/arc/usb/usb_host_bridge.cc
+++ b/chromium/components/arc/usb/usb_host_bridge.cc
@@ -4,6 +4,8 @@
#include "components/arc/usb/usb_host_bridge.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
@@ -12,6 +14,7 @@
#include "components/arc/arc_bridge_service.h"
#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
#include "components/arc/arc_features.h"
+#include "components/arc/usb/usb_host_ui_delegate.h"
#include "device/base/device_client.h"
#include "device/usb/mojo/type_converters.h"
#include "device/usb/usb_device_handle.h"
@@ -107,6 +110,10 @@ ArcUsbHostBridge::~ArcUsbHostBridge() {
arc_bridge_service_->usb_host()->SetHost(nullptr);
}
+BrowserContextKeyedServiceFactory* ArcUsbHostBridge::GetFactory() {
+ return ArcUsbHostBridgeFactory::GetInstance();
+}
+
void ArcUsbHostBridge::RequestPermission(const std::string& guid,
const std::string& package,
bool interactive,
@@ -202,6 +209,9 @@ void ArcUsbHostBridge::OnDeviceAdded(scoped_refptr<device::UsbDevice> device) {
void ArcUsbHostBridge::OnDeviceRemoved(
scoped_refptr<device::UsbDevice> device) {
+ if (ui_delegate_)
+ ui_delegate_->DeviceRemoved(device.get()->guid());
+
mojom::UsbHostInstance* usb_host_instance = ARC_GET_INSTANCE_FOR_METHOD(
arc_bridge_service_->usb_host(), OnDeviceAdded);
@@ -229,6 +239,19 @@ void ArcUsbHostBridge::OnConnectionReady() {
weak_factory_.GetWeakPtr())));
}
+void ArcUsbHostBridge::OnConnectionClosed() {
+ if (ui_delegate_)
+ ui_delegate_->ClearPermissionRequests();
+}
+
+void ArcUsbHostBridge::Shutdown() {
+ ui_delegate_ = nullptr;
+}
+
+void ArcUsbHostBridge::SetUiDelegate(ArcUsbHostUiDelegate* ui_delegate) {
+ ui_delegate_ = ui_delegate;
+}
+
void ArcUsbHostBridge::OnDeviceChecked(const std::string& guid, bool allowed) {
if (!base::FeatureList::IsEnabled(arc::kUsbHostFeature)) {
VLOG(1) << "AndroidUSBHost: feature is disabled; ignoring";
@@ -251,13 +274,31 @@ void ArcUsbHostBridge::DoRequestUserAuthorization(
const std::string& guid,
const std::string& package,
RequestPermissionCallback callback) {
- // TODO: implement the UI dialog
- // fail close for now
- std::move(callback).Run(false);
+ if (!ui_delegate_) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ if (!usb_service_) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ scoped_refptr<device::UsbDevice> device = usb_service_->GetDevice(guid);
+ if (!device.get()) {
+ LOG(WARNING) << "Unknown USB device " << guid;
+ std::move(callback).Run(false);
+ return;
+ }
+
+ ui_delegate_->RequestUsbAccessPermission(
+ package, guid, device->serial_number(), device->manufacturer_string(),
+ device->product_string(), device->vendor_id(), device->product_id(),
+ std::move(callback));
}
bool ArcUsbHostBridge::HasPermissionForDevice(const std::string& guid) {
- // TODO: implement permission settings
+ // TODO(lgcheng): implement permission settings
// fail close for now
return false;
}
diff --git a/chromium/components/arc/usb/usb_host_bridge.h b/chromium/components/arc/usb/usb_host_bridge.h
index 8d9f8fd267d..f549034952a 100644
--- a/chromium/components/arc/usb/usb_host_bridge.h
+++ b/chromium/components/arc/usb/usb_host_bridge.h
@@ -9,13 +9,12 @@
#include <vector>
#include "base/callback_forward.h"
-#include "base/files/scoped_file.h"
#include "base/macros.h"
#include "base/scoped_observer.h"
#include "components/arc/common/usb_host.mojom.h"
#include "components/arc/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "device/usb/public/interfaces/device_manager.mojom.h"
+#include "device/usb/public/mojom/device_manager.mojom.h"
#include "device/usb/usb_device.h"
#include "device/usb/usb_service.h"
@@ -23,9 +22,12 @@ namespace content {
class BrowserContext;
} // namespace content
+class BrowserContextKeyedServiceFactory;
+
namespace arc {
class ArcBridgeService;
+class ArcUsbHostUiDelegate;
// Private implementation of UsbHostHost.
class ArcUsbHostBridge : public KeyedService,
@@ -43,6 +45,9 @@ class ArcUsbHostBridge : public KeyedService,
ArcBridgeService* bridge_service);
~ArcUsbHostBridge() override;
+ // Returns the factory instance for this class.
+ static BrowserContextKeyedServiceFactory* GetFactory();
+
// mojom::UsbHostHost overrides:
void RequestPermission(const std::string& guid,
const std::string& package,
@@ -60,6 +65,12 @@ class ArcUsbHostBridge : public KeyedService,
// ConnectionObserver<mojom::UsbHostInstance> overrides:
void OnConnectionReady() override;
+ void OnConnectionClosed() override;
+
+ // KeyedService overrides:
+ void Shutdown() override;
+
+ void SetUiDelegate(ArcUsbHostUiDelegate* ui_delegate);
private:
void OnDeviceChecked(const std::string& guid, bool allowed);
@@ -73,6 +84,7 @@ class ArcUsbHostBridge : public KeyedService,
ScopedObserver<device::UsbService, device::UsbService::Observer>
usb_observer_;
device::UsbService* usb_service_;
+ ArcUsbHostUiDelegate* ui_delegate_ = nullptr;
// WeakPtrFactory to use for callbacks.
base::WeakPtrFactory<ArcUsbHostBridge> weak_factory_;
diff --git a/chromium/components/arc/usb/usb_host_ui_delegate.h b/chromium/components/arc/usb/usb_host_ui_delegate.h
new file mode 100644
index 00000000000..3e9b58f00a0
--- /dev/null
+++ b/chromium/components/arc/usb/usb_host_ui_delegate.h
@@ -0,0 +1,58 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ARC_USB_USB_HOST_UI_DELEGATE_H_
+#define COMPONENTS_ARC_USB_USB_HOST_UI_DELEGATE_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/strings/string16.h"
+
+namespace arc {
+
+class ArcUsbHostUiDelegate {
+ public:
+ using RequestPermissionCallback = base::OnceCallback<void(bool)>;
+ // Requests scan device list permission when app tries to get USB device list.
+ // Since the calling application will block on the callback being resolved, it
+ // should be done as soon as possible to prevent the caller from becoming
+ // non-responsive.
+ virtual void RequestUsbScanDeviceListPermission(
+ const std::string& package_name,
+ RequestPermissionCallback callback) = 0;
+
+ // Requests USB device access permission.
+ virtual void RequestUsbAccessPermission(
+ const std::string& package_name,
+ const std::string& guid,
+ const base::string16& serial_number,
+ const base::string16& manufacturer_string,
+ const base::string16& product_string,
+ uint16_t vendor_id,
+ uint16_t product_id,
+ RequestPermissionCallback callback) = 0;
+
+ // Checks if package have access to USB device.
+ virtual bool HasUsbAccessPermission(const std::string& package_name,
+ const std::string& guid,
+ const base::string16& serial_number,
+ uint16_t vendor_id,
+ uint16_t product_id) = 0;
+
+ // Device is detached. Remove pending permission request to the device and
+ // ephemeral device permission if the device is not persistent.
+ virtual void DeviceRemoved(const std::string& guid) = 0;
+
+ // Clears all pending permission requests. Called when USB host instance
+ // connection is closed.
+ virtual void ClearPermissionRequests() = 0;
+
+ protected:
+ ~ArcUsbHostUiDelegate() = default;
+};
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_USB_USB_HOST_UI_DELEGATE_H_
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 2d5e7fb1ad2..3b4b47f93b5 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
@@ -176,8 +176,8 @@ void GpuArcVideoEncodeAccelerator::Encode(
// the shared memory as well as notifies |client_| about the end of processing
// the |frame|.
frame->AddDestructionObserver(
- base::Bind(&DropShareMemoryAndVideoFrameDoneNotifier, base::Passed(&shm),
- base::Passed(&notifier)));
+ base::BindOnce(&DropShareMemoryAndVideoFrameDoneNotifier, std::move(shm),
+ std::move(notifier)));
accelerator_->Encode(frame, force_keyframe);
}
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 7cf9eb014db..fbaebba0482 100644
--- a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
+++ b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
@@ -18,15 +18,6 @@ namespace arc {
namespace {
-// Sends MountEvents of all existing MountPoints in cros-disks.
-void SendAllMountEvents(ArcVolumeMounterBridge* bridge) {
- for (const auto& keyValue : DiskMountManager::GetInstance()->mount_points()) {
- bridge->OnMountEvent(DiskMountManager::MountEvent::MOUNTING,
- chromeos::MountError::MOUNT_ERROR_NONE,
- keyValue.second);
- }
-}
-
// Singleton factory for ArcVolumeMounterBridge.
class ArcVolumeMounterBridgeFactory
: public internal::ArcBrowserContextKeyedServiceFactoryBase<
@@ -56,22 +47,34 @@ ArcVolumeMounterBridge* ArcVolumeMounterBridge::GetForBrowserContext(
ArcVolumeMounterBridge::ArcVolumeMounterBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
- : arc_bridge_service_(bridge_service) {
+ : arc_bridge_service_(bridge_service), weak_ptr_factory_(this) {
arc_bridge_service_->volume_mounter()->AddObserver(this);
+ arc_bridge_service_->volume_mounter()->SetHost(this);
DCHECK(DiskMountManager::GetInstance());
DiskMountManager::GetInstance()->AddObserver(this);
}
ArcVolumeMounterBridge::~ArcVolumeMounterBridge() {
DiskMountManager::GetInstance()->RemoveObserver(this);
+ arc_bridge_service_->volume_mounter()->SetHost(nullptr);
arc_bridge_service_->volume_mounter()->RemoveObserver(this);
}
+// Sends MountEvents of all existing MountPoints in cros-disks.
+void ArcVolumeMounterBridge::SendAllMountEvents() {
+ for (const auto& keyValue : DiskMountManager::GetInstance()->mount_points()) {
+ OnMountEvent(DiskMountManager::MountEvent::MOUNTING,
+ chromeos::MountError::MOUNT_ERROR_NONE, keyValue.second);
+ }
+}
+
void ArcVolumeMounterBridge::OnConnectionReady() {
- base::PostTaskWithTraits(FROM_HERE,
- {base::TaskPriority::USER_BLOCKING,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
- base::BindOnce(&SendAllMountEvents, this));
+ // Deferring the SendAllMountEvents as a task to current thread to not
+ // block the mojo request since SendAllMountEvents might takes non trivial
+ // amount of time.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&ArcVolumeMounterBridge::SendAllMountEvents,
+ weak_ptr_factory_.GetWeakPtr()));
}
void ArcVolumeMounterBridge::OnAutoMountableDiskEvent(
@@ -146,4 +149,13 @@ void ArcVolumeMounterBridge::OnMountEvent(
device_label, device_type));
}
+void ArcVolumeMounterBridge::RequestAllMountPoints() {
+ // Deferring the SendAllMountEvents as a task to current thread to not
+ // block the mojo request since SendAllMountEvents might takes non trivial
+ // amount of time.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&ArcVolumeMounterBridge::SendAllMountEvents,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
} // namespace arc
diff --git a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h
index 5c47f2cfbf8..654cefa9e4d 100644
--- a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h
+++ b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "chromeos/disks/disk_mount_manager.h"
#include "components/arc/common/volume_mounter.mojom.h"
#include "components/arc/connection_observer.h"
@@ -27,7 +28,8 @@ class ArcBridgeService;
class ArcVolumeMounterBridge
: public KeyedService,
public chromeos::disks::DiskMountManager::Observer,
- public ConnectionObserver<mojom::VolumeMounterInstance> {
+ public ConnectionObserver<mojom::VolumeMounterInstance>,
+ public mojom::VolumeMounterHost {
public:
// Returns singleton instance for the given BrowserContext,
// or nullptr if the browser |context| is not allowed to use ARC.
@@ -61,9 +63,16 @@ class ArcVolumeMounterBridge
chromeos::RenameError error_code,
const std::string& device_path) override;
+ // mojom::VolumeMounterHost overrides:
+ void RequestAllMountPoints() override;
+
private:
+ void SendAllMountEvents();
+
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
+ base::WeakPtrFactory<ArcVolumeMounterBridge> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ArcVolumeMounterBridge);
};
diff --git a/chromium/components/assist_ranker/BUILD.gn b/chromium/components/assist_ranker/BUILD.gn
index 1c07991b5dd..130553d6959 100644
--- a/chromium/components/assist_ranker/BUILD.gn
+++ b/chromium/components/assist_ranker/BUILD.gn
@@ -11,6 +11,8 @@ static_library("assist_ranker") {
"base_predictor.h",
"binary_classifier_predictor.cc",
"binary_classifier_predictor.h",
+ "example_preprocessing.cc",
+ "example_preprocessing.h",
"fake_ranker_model_loader.cc",
"fake_ranker_model_loader.h",
"generic_logistic_regression_inference.cc",
@@ -47,6 +49,7 @@ source_set("unit_tests") {
sources = [
"base_predictor_unittest.cc",
"binary_classifier_predictor_unittest.cc",
+ "example_preprocessing_unittest.cc",
"generic_logistic_regression_inference_unittest.cc",
"ranker_example_util_unittest.cc",
"ranker_model_loader_impl_unittest.cc",
diff --git a/chromium/components/assist_ranker/DEPS b/chromium/components/assist_ranker/DEPS
index d8355c686f2..22c088fe59f 100644
--- a/chromium/components/assist_ranker/DEPS
+++ b/chromium/components/assist_ranker/DEPS
@@ -5,4 +5,5 @@ include_rules = [
"+components/ukm",
"+net",
"+services/metrics/public",
-] \ No newline at end of file
+ "+third_party/protobuf",
+]
diff --git a/chromium/components/assist_ranker/OWNERS b/chromium/components/assist_ranker/OWNERS
index 5f847a5bbc9..36ad72d71e6 100644
--- a/chromium/components/assist_ranker/OWNERS
+++ b/chromium/components/assist_ranker/OWNERS
@@ -1,2 +1,3 @@
+charleszhao@chromium.org
hamelphi@chromium.org
-rogerm@chromium.org \ No newline at end of file
+rogerm@chromium.org
diff --git a/chromium/components/assist_ranker/base_predictor_unittest.cc b/chromium/components/assist_ranker/base_predictor_unittest.cc
index 263f27cdb75..3ec770e99a4 100644
--- a/chromium/components/assist_ranker/base_predictor_unittest.cc
+++ b/chromium/components/assist_ranker/base_predictor_unittest.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/memory/ptr_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "components/assist_ranker/fake_ranker_model_loader.h"
@@ -83,8 +82,8 @@ RankerModelStatus FakePredictor::ValidateModel(const RankerModel& model) {
std::unique_ptr<FakePredictor> FakePredictor::Create() {
std::unique_ptr<FakePredictor> predictor(
new FakePredictor(kTestPredictorConfig));
- auto ranker_model = base::MakeUnique<RankerModel>();
- auto fake_model_loader = base::MakeUnique<FakeRankerModelLoader>(
+ auto ranker_model = std::make_unique<RankerModel>();
+ auto fake_model_loader = std::make_unique<FakeRankerModelLoader>(
base::BindRepeating(&FakePredictor::ValidateModel),
base::BindRepeating(&FakePredictor::OnModelAvailable,
base::Unretained(predictor.get())),
diff --git a/chromium/components/assist_ranker/binary_classifier_predictor.cc b/chromium/components/assist_ranker/binary_classifier_predictor.cc
index cc595bf0a62..1200cfec46d 100644
--- a/chromium/components/assist_ranker/binary_classifier_predictor.cc
+++ b/chromium/components/assist_ranker/binary_classifier_predictor.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
#include "components/assist_ranker/generic_logistic_regression_inference.h"
#include "components/assist_ranker/proto/ranker_model.pb.h"
#include "components/assist_ranker/ranker_model.h"
@@ -37,7 +36,7 @@ std::unique_ptr<BinaryClassifierPredictor> BinaryClassifierPredictor::Create(
const GURL& model_url = predictor->GetModelUrl();
DVLOG(1) << "Creating predictor instance for " << predictor->GetModelName();
DVLOG(1) << "Model URL: " << model_url;
- auto model_loader = base::MakeUnique<RankerModelLoaderImpl>(
+ auto model_loader = std::make_unique<RankerModelLoaderImpl>(
base::BindRepeating(&BinaryClassifierPredictor::ValidateModel),
base::BindRepeating(&BinaryClassifierPredictor::OnModelAvailable,
base::Unretained(predictor.get())),
@@ -76,6 +75,25 @@ RankerModelStatus BinaryClassifierPredictor::ValidateModel(
DVLOG(0) << "Model is incompatible.";
return RankerModelStatus::INCOMPATIBLE;
}
+ const GenericLogisticRegressionModel& glr =
+ model.proto().logistic_regression();
+ if (glr.is_preprocessed_model()) {
+ if (glr.fullname_weights().empty() || !glr.weights().empty()) {
+ DVLOG(0) << "Model is incompatible. Preprocessed model should use "
+ "fullname_weights.";
+ return RankerModelStatus::INCOMPATIBLE;
+ }
+ if (!glr.preprocessor_config().feature_indices().empty()) {
+ DVLOG(0) << "Preprocessed model doesn't need feature indices.";
+ return RankerModelStatus::INCOMPATIBLE;
+ }
+ } else {
+ if (!glr.fullname_weights().empty() || glr.weights().empty()) {
+ DVLOG(0) << "Model is incompatible. Non-preprocessed model should use "
+ "weights.";
+ return RankerModelStatus::INCOMPATIBLE;
+ }
+ }
return RankerModelStatus::OK;
}
diff --git a/chromium/components/assist_ranker/binary_classifier_predictor_unittest.cc b/chromium/components/assist_ranker/binary_classifier_predictor_unittest.cc
index 9249301d472..dcde981bf87 100644
--- a/chromium/components/assist_ranker/binary_classifier_predictor_unittest.cc
+++ b/chromium/components/assist_ranker/binary_classifier_predictor_unittest.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/feature_list.h"
-#include "base/memory/ptr_util.h"
#include "components/assist_ranker/fake_ranker_model_loader.h"
#include "components/assist_ranker/proto/ranker_model.pb.h"
#include "components/assist_ranker/ranker_model.h"
@@ -32,6 +31,7 @@ class BinaryClassifierPredictorTest : public ::testing::Test {
protected:
const std::string feature_ = "feature";
+ const float weight_ = 1.0;
const float threshold_ = 0.5;
};
@@ -69,14 +69,14 @@ BinaryClassifierPredictorTest::GetSimpleLogisticRegressionModel() {
GenericLogisticRegressionModel lr_model;
lr_model.set_bias(-0.5);
lr_model.set_threshold(threshold_);
- (*lr_model.mutable_weights())[feature_].set_scalar(1.0);
+ (*lr_model.mutable_weights())[feature_].set_scalar(weight_);
return lr_model;
}
// TODO(hamelphi): Test BinaryClassifierPredictor::Create.
TEST_F(BinaryClassifierPredictorTest, EmptyRankerModel) {
- auto ranker_model = base::MakeUnique<RankerModel>();
+ auto ranker_model = std::make_unique<RankerModel>();
auto predictor = InitPredictor(std::move(ranker_model), GetConfig());
EXPECT_FALSE(predictor->IsReady());
@@ -90,7 +90,7 @@ TEST_F(BinaryClassifierPredictorTest, EmptyRankerModel) {
}
TEST_F(BinaryClassifierPredictorTest, NoInferenceModuleForModel) {
- auto ranker_model = base::MakeUnique<RankerModel>();
+ auto ranker_model = std::make_unique<RankerModel>();
// TranslateRankerModel does not have an inference module. Validation will
// fail.
ranker_model->mutable_proto()
@@ -110,7 +110,7 @@ TEST_F(BinaryClassifierPredictorTest, NoInferenceModuleForModel) {
}
TEST_F(BinaryClassifierPredictorTest, GenericLogisticRegressionModel) {
- auto ranker_model = base::MakeUnique<RankerModel>();
+ auto ranker_model = std::make_unique<RankerModel>();
*ranker_model->mutable_proto()->mutable_logistic_regression() =
GetSimpleLogisticRegressionModel();
auto predictor = InitPredictor(std::move(ranker_model), GetConfig());
@@ -133,4 +133,33 @@ TEST_F(BinaryClassifierPredictorTest, GenericLogisticRegressionModel) {
EXPECT_LT(float_response, threshold_);
}
+TEST_F(BinaryClassifierPredictorTest,
+ GenericLogisticRegressionPreprocessedModel) {
+ auto ranker_model = std::make_unique<RankerModel>();
+ auto& glr = *ranker_model->mutable_proto()->mutable_logistic_regression();
+ glr = GetSimpleLogisticRegressionModel();
+ glr.clear_weights();
+ glr.set_is_preprocessed_model(true);
+ (*glr.mutable_fullname_weights())[feature_] = weight_;
+
+ auto predictor = InitPredictor(std::move(ranker_model), GetConfig());
+ EXPECT_TRUE(predictor->IsReady());
+
+ RankerExample ranker_example;
+ auto& features = *ranker_example.mutable_features();
+ features[feature_].set_bool_value(true);
+ bool bool_response;
+ EXPECT_TRUE(predictor->Predict(ranker_example, &bool_response));
+ EXPECT_TRUE(bool_response);
+ float float_response;
+ EXPECT_TRUE(predictor->PredictScore(ranker_example, &float_response));
+ EXPECT_GT(float_response, threshold_);
+
+ features[feature_].set_bool_value(false);
+ EXPECT_TRUE(predictor->Predict(ranker_example, &bool_response));
+ EXPECT_FALSE(bool_response);
+ EXPECT_TRUE(predictor->PredictScore(ranker_example, &float_response));
+ EXPECT_LT(float_response, threshold_);
+}
+
} // namespace assist_ranker
diff --git a/chromium/components/assist_ranker/example_preprocessing.cc b/chromium/components/assist_ranker/example_preprocessing.cc
new file mode 100644
index 00000000000..0ea3e4e0e08
--- /dev/null
+++ b/chromium/components/assist_ranker/example_preprocessing.cc
@@ -0,0 +1,197 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/assist_ranker/example_preprocessing.h"
+
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "components/assist_ranker/ranker_example_util.h"
+#include "third_party/protobuf/src/google/protobuf/map.h"
+#include "third_party/protobuf/src/google/protobuf/repeated_field.h"
+
+namespace assist_ranker {
+
+using google::protobuf::Map;
+using google::protobuf::MapPair;
+using google::protobuf::RepeatedField;
+
+// Initialize.
+const char ExamplePreprocessor::kMissingFeatureDefaultName[] =
+ "_MissingFeature";
+const char ExamplePreprocessor::kVectorizedFeatureDefaultName[] =
+ "_VectorizedFeature";
+
+std::string ExamplePreprocessor::FeatureFullname(
+ const std::string& feature_name,
+ const std::string& feature_value) {
+ return feature_value.empty()
+ ? feature_name
+ : base::StrCat({feature_name, "_", feature_value});
+}
+
+int ExamplePreprocessor::Process(RankerExample* const example,
+ const bool clear_other_features) const {
+ return AddMissingFeatures(example) | AddBucketizedFeatures(example) |
+ Vectorization(example, clear_other_features);
+}
+
+int ExamplePreprocessor::AddMissingFeatures(
+ RankerExample* const example) const {
+ Map<std::string, Feature>& feature_map = *example->mutable_features();
+ for (const std::string& feature_name : config_.missing_features()) {
+ // If a feature is missing in the example, set the place.
+ if (feature_map.find(feature_name) == feature_map.end()) {
+ feature_map[kMissingFeatureDefaultName]
+ .mutable_string_list()
+ ->add_string_value(feature_name);
+ }
+ }
+ return kSuccess;
+}
+
+int ExamplePreprocessor::AddBucketizedFeatures(
+ RankerExample* const example) const {
+ int error_code = kSuccess;
+ Map<std::string, Feature>& feature_map = *example->mutable_features();
+ for (const MapPair<std::string, ExamplePreprocessorConfig::Boundaries>&
+ bucketizer : config_.bucketizers()) {
+ const std::string& feature_name = bucketizer.first;
+ // Simply continue if the feature is missing. The missing feature will later
+ // on be handled as missing one_hot feature, and it's up to the user how to
+ // handle this missing feature.
+ Feature feature;
+ if (!SafeGetFeature(feature_name, *example, &feature)) {
+ continue;
+ }
+ // Get feature value as float. Only int32 or float value is supported for
+ // Bucketization. Continue if the type_case is not int32 or float.
+ float value = 0;
+ switch (feature.feature_type_case()) {
+ case Feature::kInt32Value:
+ value = static_cast<float>(feature.int32_value());
+ break;
+ case Feature::kFloatValue:
+ value = feature.float_value();
+ break;
+ default:
+ DVLOG(2) << "Can't bucketize feature type: "
+ << feature.feature_type_case();
+ error_code |= kUnbucketizableFeatureType;
+ continue;
+ }
+ // Get the bucket from the boundaries; the first index that value<boundary.
+ const RepeatedField<float>& boundaries = bucketizer.second.boundaries();
+ int index = 0;
+ for (; index < boundaries.size(); ++index) {
+ if (value < boundaries[index])
+ break;
+ }
+ // Set one hot feature as features[feature_name] = "index";
+ feature_map[feature_name].set_string_value(base::IntToString(index));
+ }
+ return error_code;
+}
+
+int ExamplePreprocessor::Vectorization(RankerExample* example,
+ const bool clear_other_features) const {
+ if (config_.feature_indices().empty()) {
+ DVLOG(2) << "Feature indices are empty, can't vectorize.";
+ return kSuccess;
+ }
+ Feature vectorized_features;
+ vectorized_features.mutable_float_list()->mutable_float_value()->Resize(
+ config_.feature_indices().size(), 0.0);
+
+ int error_code = kSuccess;
+
+ for (const auto& field : ExampleFloatIterator(*example)) {
+ error_code |= field.error;
+ if (field.error != kSuccess) {
+ continue;
+ }
+ const auto find_index = config_.feature_indices().find(field.fullname);
+ // If the feature_fullname is inside the indices map, then set the place.
+ if (find_index != config_.feature_indices().end()) {
+ vectorized_features.mutable_float_list()->set_float_value(
+ find_index->second, field.value);
+ } else {
+ DVLOG(2) << "Feature has no index: " << field.fullname;
+ error_code |= kNoFeatureIndexFound;
+ }
+ }
+ if (clear_other_features) {
+ example->clear_features();
+ }
+ (*example->mutable_features())[kVectorizedFeatureDefaultName] =
+ vectorized_features;
+ return error_code;
+}
+
+ExampleFloatIterator::Field ExampleFloatIterator::operator*() const {
+ const std::string& feature_name = feature_iterator_->first;
+ const Feature& feature = feature_iterator_->second;
+ Field field = {feature_name, 1.0f, ExamplePreprocessor::kSuccess};
+
+ switch (feature.feature_type_case()) {
+ case Feature::kBoolValue:
+ field.value = static_cast<float>(feature.bool_value());
+ break;
+ case Feature::kInt32Value:
+ field.value = static_cast<float>(feature.int32_value());
+ break;
+ case Feature::kFloatValue:
+ field.value = feature.float_value();
+ break;
+ case Feature::kStringValue:
+ field.fullname = ExamplePreprocessor::FeatureFullname(
+ feature_name, feature.string_value());
+ break;
+ case Feature::kStringList:
+ if (string_list_index_ < feature.string_list().string_value_size()) {
+ const std::string& string_value =
+ feature.string_list().string_value(string_list_index_);
+ field.fullname =
+ ExamplePreprocessor::FeatureFullname(feature_name, string_value);
+ } else {
+ // This happens when a string list field is added without any value.
+ field.error = ExamplePreprocessor::kInvalidFeatureListIndex;
+ }
+ break;
+ default:
+ field.error = ExamplePreprocessor::kInvalidFeatureType;
+ DVLOG(2) << "Feature type not supported: "
+ << feature.feature_type_case();
+ break;
+ }
+ return field;
+}
+
+ExampleFloatIterator& ExampleFloatIterator::operator++() {
+ const Feature& feature = feature_iterator_->second;
+ switch (feature.feature_type_case()) {
+ case Feature::kBoolValue:
+ case Feature::kInt32Value:
+ case Feature::kFloatValue:
+ case Feature::kStringValue:
+ ++feature_iterator_;
+ break;
+ case Feature::kStringList:
+ if (string_list_index_ < feature.string_list().string_value_size() - 1) {
+ // If not at the last element, advance the index.
+ ++string_list_index_;
+ } else {
+ // If at the last element, advance the feature_iterator.
+ string_list_index_ = 0;
+ ++feature_iterator_;
+ }
+ break;
+ default:
+ ++feature_iterator_;
+ DVLOG(2) << "Feature type not supported: "
+ << feature.feature_type_case();
+ }
+ return *this;
+}
+
+} // namespace assist_ranker
diff --git a/chromium/components/assist_ranker/example_preprocessing.h b/chromium/components/assist_ranker/example_preprocessing.h
new file mode 100644
index 00000000000..f794ee73484
--- /dev/null
+++ b/chromium/components/assist_ranker/example_preprocessing.h
@@ -0,0 +1,143 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ASSIST_RANKER_EXAMPLE_PREPROCESSING_H_
+#define COMPONENTS_ASSIST_RANKER_EXAMPLE_PREPROCESSING_H_
+
+#include "components/assist_ranker/proto/example_preprocessor.pb.h"
+#include "components/assist_ranker/proto/ranker_example.pb.h"
+#include "third_party/protobuf/src/google/protobuf/map.h"
+
+namespace assist_ranker {
+
+// Preprocessor for preprocessing RankerExample into formats that is needed by
+// Ranker Predictors.
+class ExamplePreprocessor {
+ public:
+ // Error code (bitwise) for preprocessing.
+ enum PreprocessErrorCode {
+ kSuccess = 0,
+ kNoFeatureIndexFound = 1,
+ kUnbucketizableFeatureType = 2,
+ kInvalidFeatureType = 4,
+ kInvalidFeatureListIndex = 8,
+ };
+
+ explicit ExamplePreprocessor(const ExamplePreprocessorConfig& config)
+ : config_(config) {}
+
+ // Processes a RankerExample with config_.
+ // Clear up all features except kVectorizedFeatureDefaultName if
+ // clear_other_features is set to true.
+ // Returns the error code of preprocessing, can be any sum of the error code
+ // in PreprocessErrorCode.
+ int Process(RankerExample* example, bool clear_other_features = false) const;
+
+ // Default feature name for missing features.
+ static const char kMissingFeatureDefaultName[];
+
+ // Default feature name for vectorized features.
+ static const char kVectorizedFeatureDefaultName[];
+
+ // Generates a feature's fullname based on feature_name and feature_value.
+ // A feature fullname is defined as:
+ // (1) feature_name if it's bool_value, int64_value or float_value.
+ // (2) a combination of feature_name and feature_value if it's string_value
+ // or i-th element of a string_list.
+ static std::string FeatureFullname(const std::string& feature_name,
+ const std::string& feature_value = "");
+
+ private:
+ // If a feature is specified in config_.missing_features() and missing in
+ // the example, then the feature name is added as a sparse feature value to
+ // the special sparse feature "_MissingFeature" in the example.
+ // Always returns kSuccess.
+ int AddMissingFeatures(RankerExample* example) const;
+ // If a numeric feature is specified in config_.bucketizers(), then it is
+ // bucketized based on the boundaries and reset as a one-hot feature with
+ // bucket index as it's string value.
+ int AddBucketizedFeatures(RankerExample* example) const;
+ // Add a new_float_list feature as kVectorizedFeatureDefaultName, and iterate
+ // for all existing features in example.features(), set corresponding
+ // new_float_list.float_value(config_.feature_indices(feature_value_key)) to
+ // be either numeric value (for scalars) or 1.0 (for string values).
+ int Vectorization(RankerExample* example, bool clear_other_features) const;
+
+ // Configuration proto for the preprocessor.
+ const ExamplePreprocessorConfig config_;
+};
+
+// An iterator that goes through all features of a RankerExample and converts
+// each field as a struct Field{full_name, value, error}.
+// (1) A numeric feature (bool_value, int32_value, float_value) is converted
+// to {feature_name, float(original_value), kSuccess}.
+// (2) A string feature is converted to
+// {feature_name_string_value, 1.0, kSuccess}.
+// (3) A string_value from a string list feature is converted to
+// {feature_name_string_value, 1.0, error_code} where non-empty list
+// gets error_code kSuccess, empty list gets kInvalidFeatureListIndex.
+// Example:
+// std::vector<float> ExampleToStdFloat(const RankerExample& example,
+// const Map& feature_indices) {
+// std::vector<float> vectorized(feature_indices.size());
+// for (const auto& field : ExampleFloatIterator(example)) {
+// if (field.error == ExamplePreprocessor::kSuccess) {
+// const int index = feature_indices[field.fullname];
+// vectorized[index] = field.value;
+// }
+// }
+// return vectorized;
+// }
+class ExampleFloatIterator {
+ public:
+ // A struct as float value of one field from a RankerExample.
+ struct Field {
+ std::string fullname;
+ float value;
+ int error;
+ };
+
+ explicit ExampleFloatIterator(const RankerExample& example)
+ : feature_iterator_(example.features().begin()),
+ feature_end_iterator_(example.features().end()),
+ string_list_index_(0) {}
+
+ ExampleFloatIterator begin() const { return *this; }
+ ExampleFloatIterator end() const {
+ return ExampleFloatIterator(feature_end_iterator_);
+ }
+
+ Field operator*() const;
+
+ ExampleFloatIterator& operator++();
+
+ // Two iterators are equal if they point to the same field, with the same
+ // indices if it's a string_list.
+ bool operator==(const ExampleFloatIterator& other) const {
+ return feature_iterator_ == other.feature_iterator_ &&
+ string_list_index_ == other.string_list_index_;
+ }
+
+ bool operator!=(const ExampleFloatIterator& other) const {
+ return !(*this == other);
+ }
+
+ private:
+ // Returns the end iterator.
+ explicit ExampleFloatIterator(
+ const google::protobuf::Map<std::string, Feature>::const_iterator&
+ feature_end_iterator)
+ : feature_iterator_(feature_end_iterator),
+ feature_end_iterator_(feature_end_iterator),
+ string_list_index_(0) {}
+
+ google::protobuf::Map<std::string, Feature>::const_iterator feature_iterator_;
+ google::protobuf::Map<std::string, Feature>::const_iterator
+ feature_end_iterator_;
+ int string_list_index_;
+};
+
+} // namespace assist_ranker
+
+#endif // COMPONENTS_ASSIST_RANKER_EXAMPLE_PREPROCESSING_H_
diff --git a/chromium/components/assist_ranker/example_preprocessing_unittest.cc b/chromium/components/assist_ranker/example_preprocessing_unittest.cc
new file mode 100644
index 00000000000..d6b2d064589
--- /dev/null
+++ b/chromium/components/assist_ranker/example_preprocessing_unittest.cc
@@ -0,0 +1,298 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/assist_ranker/example_preprocessing.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/protobuf/src/google/protobuf/map.h"
+#include "third_party/protobuf/src/google/protobuf/repeated_field.h"
+
+namespace assist_ranker {
+namespace {
+
+using ::google::protobuf::Map;
+using ::google::protobuf::RepeatedField;
+
+void EXPECT_EQUALS_EXAMPLE(const RankerExample& example1,
+ const RankerExample& example2) {
+ EXPECT_EQ(example1.features_size(), example2.features_size());
+ for (const auto& pair : example1.features()) {
+ const Feature& feature1 = pair.second;
+ const Feature& feature2 = example2.features().at(pair.first);
+ EXPECT_EQ(feature1.feature_type_case(), feature2.feature_type_case());
+ EXPECT_EQ(feature1.bool_value(), feature2.bool_value());
+ EXPECT_EQ(feature1.int32_value(), feature2.int32_value());
+ EXPECT_EQ(feature1.float_value(), feature2.float_value());
+ EXPECT_EQ(feature1.string_value(), feature2.string_value());
+ EXPECT_EQ(feature1.string_list().string_value_size(),
+ feature2.string_list().string_value_size());
+ for (int i = 0; i < feature1.string_list().string_value_size(); ++i) {
+ EXPECT_EQ(feature1.string_list().string_value(i),
+ feature2.string_list().string_value(i));
+ }
+ }
+}
+
+} // namespace
+
+class ExamplePreprocessorTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ auto& features = *example_.mutable_features();
+ features[bool_name_].set_bool_value(bool_value_);
+ features[int32_name_].set_int32_value(int32_value_);
+ features[float_name_].set_float_value(float_value_);
+ features[one_hot_name_].set_string_value(one_hot_value_);
+ *features[sparse_name_].mutable_string_list()->mutable_string_value() = {
+ sparse_values_.begin(), sparse_values_.end()};
+ }
+
+ RankerExample example_;
+ const std::string bool_name_ = "bool_feature";
+ const bool bool_value_ = true;
+ const std::string int32_name_ = "int32_feature";
+ const int int32_value_ = 2;
+ const std::string float_name_ = "float_feature";
+ const float float_value_ = 3.0;
+ const std::string one_hot_name_ = "one_hot_feature";
+ const std::string elem1_ = "elem1";
+ const std::string elem2_ = "elem2";
+ const std::string one_hot_value_ = elem1_;
+ const std::string sparse_name_ = "sparse_feature";
+ const std::vector<std::string> sparse_values_ = {elem1_, elem2_};
+};
+
+TEST_F(ExamplePreprocessorTest, AddMissingFeatures) {
+ RankerExample example = example_;
+ ExamplePreprocessorConfig config;
+
+ // Adding missing feature label to an existing feature has no effect.
+ config.add_missing_features(bool_name_);
+ EXPECT_EQ(ExamplePreprocessor(config).Process(&example_),
+ ExamplePreprocessor::kSuccess);
+ EXPECT_EQUALS_EXAMPLE(example, example_);
+ config.Clear();
+
+ // Adding missing feature label to non-existing feature returns a
+ // "_MissingFeature" feature with a list of feature names.
+ const std::string foo = "foo";
+ config.add_missing_features(foo);
+ EXPECT_EQ(ExamplePreprocessor(config).Process(&example_),
+ ExamplePreprocessor::kSuccess);
+ (*example.mutable_features())[ExamplePreprocessor::kMissingFeatureDefaultName]
+ .mutable_string_list()
+ ->add_string_value(foo);
+ EXPECT_EQUALS_EXAMPLE(example, example_);
+ config.Clear();
+}
+
+TEST_F(ExamplePreprocessorTest, AddBucketizeFeatures) {
+ RankerExample example = example_;
+ ExamplePreprocessorConfig config;
+ Map<std::string, ExamplePreprocessorConfig::Boundaries>& bucketizers =
+ *config.mutable_bucketizers();
+
+ // Adding bucketized feature to non-existing feature returns the same example.
+ const std::string foo = "foo";
+ bucketizers[foo].add_boundaries(0.5);
+ EXPECT_EQ(ExamplePreprocessor(config).Process(&example_),
+ ExamplePreprocessor::kSuccess);
+ EXPECT_EQUALS_EXAMPLE(example, example_);
+ config.Clear();
+
+ // Bucketizing a bool feature returns same proto.
+ bucketizers[bool_name_].add_boundaries(0.5);
+ EXPECT_EQ(ExamplePreprocessor(config).Process(&example_),
+ ExamplePreprocessor::kUnbucketizableFeatureType);
+ EXPECT_EQUALS_EXAMPLE(example, example_);
+ config.Clear();
+
+ // Bucketizing a string feature returns same proto.
+ bucketizers[one_hot_name_].add_boundaries(0.5);
+ EXPECT_EQ(ExamplePreprocessor(config).Process(&example_),
+ ExamplePreprocessor::kUnbucketizableFeatureType);
+ EXPECT_EQUALS_EXAMPLE(example, example_);
+ config.Clear();
+
+ // Bucketizing an int32 feature with 3 boundary.
+ bucketizers[int32_name_].add_boundaries(int32_value_ - 2);
+ bucketizers[int32_name_].add_boundaries(int32_value_ - 1);
+ bucketizers[int32_name_].add_boundaries(int32_value_ + 1);
+ EXPECT_EQ(ExamplePreprocessor(config).Process(&example_),
+ ExamplePreprocessor::kSuccess);
+ (*example.mutable_features())[int32_name_].set_string_value("2");
+ EXPECT_EQUALS_EXAMPLE(example, example_);
+ config.Clear();
+
+ // Bucketizing a float feature with 3 boundary.
+ bucketizers[float_name_].add_boundaries(float_value_ - 0.2);
+ bucketizers[float_name_].add_boundaries(float_value_ - 0.1);
+ bucketizers[float_name_].add_boundaries(float_value_ + 0.1);
+ EXPECT_EQ(ExamplePreprocessor(config).Process(&example_),
+ ExamplePreprocessor::kSuccess);
+ (*example.mutable_features())[float_name_].set_string_value("2");
+ EXPECT_EQUALS_EXAMPLE(example, example_);
+ config.Clear();
+
+ // Bucketizing a float feature with value equal to a boundary.
+ (*example_.mutable_features())[float_name_].set_float_value(float_value_);
+ bucketizers[float_name_].add_boundaries(float_value_ - 0.2);
+ bucketizers[float_name_].add_boundaries(float_value_ - 0.1);
+ bucketizers[float_name_].add_boundaries(float_value_);
+ bucketizers[float_name_].add_boundaries(float_value_ + 0.1);
+ EXPECT_EQ(ExamplePreprocessor(config).Process(&example_),
+ ExamplePreprocessor::kSuccess);
+ (*example.mutable_features())[float_name_].set_string_value("3");
+ EXPECT_EQUALS_EXAMPLE(example, example_);
+ config.Clear();
+}
+
+TEST_F(ExamplePreprocessorTest, Vectorization) {
+ ExamplePreprocessorConfig config;
+ Map<std::string, int32_t>& feature_indices =
+ *config.mutable_feature_indices();
+
+ RankerExample example_vec_expected = example_;
+ RepeatedField<float>& feature_vector =
+ *(*example_vec_expected.mutable_features())
+ [ExamplePreprocessor::kVectorizedFeatureDefaultName]
+ .mutable_float_list()
+ ->mutable_float_value();
+
+ // bool feature puts the value to the corresponding place.
+ feature_indices[bool_name_] = 0;
+ feature_vector.Add(1.0);
+
+ // int32 feature puts the value to the corresponding place.
+ feature_indices[int32_name_] = 1;
+ feature_vector.Add(int32_value_);
+
+ // float feature puts the value to the corresponding place.
+ feature_indices[float_name_] = 2;
+ feature_vector.Add(float_value_);
+
+ // string value is vectorized as 1.0.
+ feature_indices[ExamplePreprocessor::FeatureFullname(one_hot_name_,
+ one_hot_value_)] = 3;
+ feature_vector.Add(1.0);
+
+ // string list value is vectorized as 1.0.
+ feature_indices[ExamplePreprocessor::FeatureFullname(sparse_name_, elem1_)] =
+ 4;
+ feature_indices[ExamplePreprocessor::FeatureFullname(sparse_name_, elem2_)] =
+ 5;
+ feature_vector.Add(1.0);
+ feature_vector.Add(1.0);
+
+ // string list value with element not in the example sets the corresponding
+ // place as 0.0;
+ feature_indices[ExamplePreprocessor::FeatureFullname(sparse_name_, "foo")] =
+ 5;
+ feature_vector.Add(0.0);
+
+ // Non-existing feature puts 0 to the corresponding place.
+ feature_indices["bar"] = 6;
+ feature_vector.Add(0.0);
+
+ // Verify the propressing result.
+ RankerExample example = example_;
+ EXPECT_EQ(ExamplePreprocessor(config).Process(&example),
+ ExamplePreprocessor::kSuccess);
+ EXPECT_EQUALS_EXAMPLE(example, example_vec_expected);
+
+ // Example with extra numeric feature gets kNoFeatureIndexFound error;
+ RankerExample example_with_extra_numeric = example_;
+ (*example_with_extra_numeric.mutable_features())["foo"].set_float_value(1.0);
+ EXPECT_EQ(ExamplePreprocessor(config).Process(&example_with_extra_numeric),
+ ExamplePreprocessor::ExamplePreprocessor::kNoFeatureIndexFound);
+
+ // Example with extra one-hot feature gets kNoFeatureIndexFound error;
+ RankerExample example_with_extra_one_hot = example_;
+ (*example_with_extra_one_hot.mutable_features())["foo"].set_string_value(
+ "bar");
+ EXPECT_EQ(ExamplePreprocessor(config).Process(&example_with_extra_one_hot),
+ ExamplePreprocessor::ExamplePreprocessor::kNoFeatureIndexFound);
+
+ // Example with extra sparse feature value gets kNoFeatureIndexFound error;
+ RankerExample example_with_extra_sparse = example_;
+ (*example_with_extra_sparse.mutable_features())[sparse_name_]
+ .mutable_string_list()
+ ->add_string_value("bar");
+ EXPECT_EQ(ExamplePreprocessor(config).Process(&example_with_extra_sparse),
+ ExamplePreprocessor::ExamplePreprocessor::kNoFeatureIndexFound);
+}
+
+TEST_F(ExamplePreprocessorTest, MultipleErrorCode) {
+ ExamplePreprocessorConfig config;
+
+ (*config.mutable_feature_indices())[int32_name_] = 0;
+ (*config.mutable_feature_indices())[float_name_] = 1;
+ (*config.mutable_bucketizers())[one_hot_name_].add_boundaries(0.5);
+ RankerExample example_vec_expected = example_;
+ RepeatedField<float>& feature_vector =
+ *(*example_vec_expected.mutable_features())
+ [ExamplePreprocessor::kVectorizedFeatureDefaultName]
+ .mutable_float_list()
+ ->mutable_float_value();
+
+ feature_vector.Add(int32_value_);
+ feature_vector.Add(float_value_);
+
+ const int error_code = ExamplePreprocessor(config).Process(&example_);
+ // Error code contains features in example_ but not in feature_indices.
+ EXPECT_TRUE(error_code & ExamplePreprocessor::kNoFeatureIndexFound);
+ // Error code contains features that are not bucketizable.
+ EXPECT_TRUE(error_code & ExamplePreprocessor::kUnbucketizableFeatureType);
+ // No kInvalidFeatureType error.
+ EXPECT_FALSE(error_code & ExamplePreprocessor::kInvalidFeatureType);
+ // Only two elements is correctly vectorized.
+ EXPECT_EQUALS_EXAMPLE(example_, example_vec_expected);
+}
+
+TEST_F(ExamplePreprocessorTest, ExampleFloatIterator) {
+ RankerExample float_example;
+ for (const auto& field : ExampleFloatIterator(example_)) {
+ EXPECT_EQ(field.error, ExamplePreprocessor::kSuccess);
+ (*float_example.mutable_features())[field.fullname].set_float_value(
+ field.value);
+ }
+
+ RankerExample float_example_expected;
+ auto& feature_map = *float_example_expected.mutable_features();
+
+ feature_map[bool_name_].set_float_value(bool_value_);
+ feature_map[int32_name_].set_float_value(int32_value_);
+ feature_map[float_name_].set_float_value(float_value_);
+ feature_map[ExamplePreprocessor::FeatureFullname(one_hot_name_,
+ one_hot_value_)]
+ .set_float_value(1.0);
+ feature_map[ExamplePreprocessor::FeatureFullname(sparse_name_, elem1_)]
+ .set_float_value(1.0);
+ feature_map[ExamplePreprocessor::FeatureFullname(sparse_name_, elem2_)]
+ .set_float_value(1.0);
+
+ EXPECT_EQUALS_EXAMPLE(float_example, float_example_expected);
+}
+
+TEST_F(ExamplePreprocessorTest, ExampleFloatIteratorError) {
+ RankerExample example;
+ example.mutable_features()->insert({"foo", Feature::default_instance()});
+ (*example.mutable_features())["bar"]
+ .mutable_string_list()
+ ->mutable_string_value();
+ int num_of_fields = 0;
+ for (const auto& field : ExampleFloatIterator(example)) {
+ if (field.fullname == "foo") {
+ EXPECT_EQ(field.error, ExamplePreprocessor::kInvalidFeatureType);
+ }
+ if (field.fullname == "bar") {
+ EXPECT_EQ(field.error, ExamplePreprocessor::kInvalidFeatureListIndex);
+ }
+ ++num_of_fields;
+ }
+ // Check the iterator indeed found the two fields.
+ EXPECT_EQ(num_of_fields, 2);
+}
+
+} // namespace assist_ranker
diff --git a/chromium/components/assist_ranker/generic_logistic_regression_inference.cc b/chromium/components/assist_ranker/generic_logistic_regression_inference.cc
index 1248b69772c..96ab5484ac2 100644
--- a/chromium/components/assist_ranker/generic_logistic_regression_inference.cc
+++ b/chromium/components/assist_ranker/generic_logistic_regression_inference.cc
@@ -7,6 +7,7 @@
#include <cmath>
#include "base/logging.h"
+#include "components/assist_ranker/example_preprocessing.h"
#include "components/assist_ranker/ranker_example_util.h"
namespace assist_ranker {
@@ -24,54 +25,69 @@ GenericLogisticRegressionInference::GenericLogisticRegressionInference(
float GenericLogisticRegressionInference::PredictScore(
const RankerExample& example) {
float activation = 0.0f;
- for (const auto& weight_it : proto_.weights()) {
- const std::string& feature_name = weight_it.first;
- const FeatureWeight& feature_weight = weight_it.second;
- switch (feature_weight.feature_type_case()) {
- case FeatureWeight::FEATURE_TYPE_NOT_SET: {
- DVLOG(0) << "Feature type not set for " << feature_name;
- break;
- }
- case FeatureWeight::kScalar: {
- float value;
- if (GetFeatureValueAsFloat(feature_name, example, &value)) {
- const float weight = feature_weight.scalar();
- activation += value * weight;
- } else {
- DVLOG(1) << "Feature not in example: " << feature_name;
+ if (!proto_.is_preprocessed_model()) {
+ for (const auto& weight_it : proto_.weights()) {
+ const std::string& feature_name = weight_it.first;
+ const FeatureWeight& feature_weight = weight_it.second;
+ switch (feature_weight.feature_type_case()) {
+ case FeatureWeight::FEATURE_TYPE_NOT_SET: {
+ DVLOG(0) << "Feature type not set for " << feature_name;
+ break;
}
- break;
- }
- case FeatureWeight::kOneHot: {
- std::string value;
- if (GetOneHotValue(feature_name, example, &value)) {
- const auto& category_weights = feature_weight.one_hot().weights();
- auto category_it = category_weights.find(value);
- if (category_it != category_weights.end()) {
- activation += category_it->second;
+ case FeatureWeight::kScalar: {
+ float value;
+ if (GetFeatureValueAsFloat(feature_name, example, &value)) {
+ const float weight = feature_weight.scalar();
+ activation += value * weight;
+ } else {
+ DVLOG(1) << "Feature not in example: " << feature_name;
+ }
+ break;
+ }
+ case FeatureWeight::kOneHot: {
+ std::string value;
+ if (GetOneHotValue(feature_name, example, &value)) {
+ const auto& category_weights = feature_weight.one_hot().weights();
+ auto category_it = category_weights.find(value);
+ if (category_it != category_weights.end()) {
+ activation += category_it->second;
+ } else {
+ // If the category is not found, use the default weight.
+ activation += feature_weight.one_hot().default_weight();
+ DVLOG(1) << "Unknown feature value for " << feature_name << ": "
+ << value;
+ }
} else {
- // If the category is not found, use the default weight.
+ // If the feature is missing, use the default weight.
activation += feature_weight.one_hot().default_weight();
- DVLOG(1) << "Unknown feature value for " << feature_name << ": "
- << value;
+ DVLOG(1) << "Feature not in example: " << feature_name;
}
- } else {
- // If the feature is missing, use the default weight.
- activation += feature_weight.one_hot().default_weight();
- DVLOG(1) << "Feature not in example: " << feature_name;
+ break;
+ }
+ case FeatureWeight::kSparse: {
+ DVLOG(0) << "Sparse features not implemented yet.";
+ break;
+ }
+ case FeatureWeight::kBucketized: {
+ DVLOG(0) << "Bucketized features not implemented yet.";
+ break;
}
- break;
- }
- case FeatureWeight::kSparse: {
- DVLOG(0) << "Sparse features not implemented yet.";
- break;
}
- case FeatureWeight::kBucketized: {
- DVLOG(0) << "Bucketized features not implemented yet.";
- break;
+ }
+ } else {
+ RankerExample processed_example = example;
+ ExamplePreprocessor(proto_.preprocessor_config())
+ .Process(&processed_example);
+ for (const auto& field : ExampleFloatIterator(processed_example)) {
+ if (field.error != ExamplePreprocessor::kSuccess)
+ continue;
+ const auto& find_weight = proto_.fullname_weights().find(field.fullname);
+ if (find_weight != proto_.fullname_weights().end()) {
+ activation += find_weight->second * field.value;
}
}
}
+
return Sigmoid(proto_.bias() + activation);
}
diff --git a/chromium/components/assist_ranker/generic_logistic_regression_inference_unittest.cc b/chromium/components/assist_ranker/generic_logistic_regression_inference_unittest.cc
index 6cd65ff966c..a1cba82401a 100644
--- a/chromium/components/assist_ranker/generic_logistic_regression_inference_unittest.cc
+++ b/chromium/components/assist_ranker/generic_logistic_regression_inference_unittest.cc
@@ -3,10 +3,13 @@
// found in the LICENSE file.
#include "components/assist_ranker/generic_logistic_regression_inference.h"
+#include "components/assist_ranker/example_preprocessing.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/protobuf/src/google/protobuf/map.h"
namespace assist_ranker {
+using ::google::protobuf::Map;
class GenericLogisticRegressionInferenceTest : public testing::Test {
protected:
@@ -19,11 +22,33 @@ class GenericLogisticRegressionInferenceTest : public testing::Test {
weights[scalar1_name_].set_scalar(scalar1_weight_);
weights[scalar2_name_].set_scalar(scalar2_weight_);
weights[scalar3_name_].set_scalar(scalar3_weight_);
+
auto* one_hot_feat = weights[one_hot_name_].mutable_one_hot();
one_hot_feat->set_default_weight(one_hot_default_weight_);
- (*one_hot_feat->mutable_weights())[one_hot_elem1_name_] = elem1_weight_;
- (*one_hot_feat->mutable_weights())[one_hot_elem2_name_] = elem2_weight_;
- (*one_hot_feat->mutable_weights())[one_hot_elem3_name_] = elem3_weight_;
+ (*one_hot_feat->mutable_weights())[one_hot_elem1_name_] =
+ one_hot_elem1_weight_;
+ (*one_hot_feat->mutable_weights())[one_hot_elem2_name_] =
+ one_hot_elem2_weight_;
+ (*one_hot_feat->mutable_weights())[one_hot_elem3_name_] =
+ one_hot_elem3_weight_;
+
+ SparseWeights* sparse_feat = weights[sparse_name_].mutable_sparse();
+ sparse_feat->set_default_weight(sparse_default_weight_);
+ (*sparse_feat->mutable_weights())[sparse_elem1_name_] =
+ sparse_elem1_weight_;
+ (*sparse_feat->mutable_weights())[sparse_elem2_name_] =
+ sparse_elem2_weight_;
+
+ BucketizedWeights* bucketized_feat =
+ weights[bucketized_name_].mutable_bucketized();
+ bucketized_feat->set_default_weight(bucketization_default_weight_);
+ for (const float boundary : bucketization_boundaries_) {
+ bucketized_feat->add_boundaries(boundary);
+ }
+ for (const float weight : bucketization_weights_) {
+ bucketized_feat->add_weights(weight);
+ }
+
return proto;
}
@@ -31,19 +56,31 @@ class GenericLogisticRegressionInferenceTest : public testing::Test {
const std::string scalar2_name_ = "scalar_feature2";
const std::string scalar3_name_ = "scalar_feature3";
const std::string one_hot_name_ = "one_hot_feature";
- const std::string one_hot_elem1_name_ = "elem1";
- const std::string one_hot_elem2_name_ = "elem2";
- const std::string one_hot_elem3_name_ = "elem3";
+ const std::string one_hot_elem1_name_ = "one_hot_elem1";
+ const std::string one_hot_elem2_name_ = "one_hot_elem2";
+ const std::string one_hot_elem3_name_ = "one_hot_elem3";
const float bias_ = 1.5f;
const float threshold_ = 0.6f;
const float scalar1_weight_ = 0.8f;
const float scalar2_weight_ = -2.4f;
const float scalar3_weight_ = 0.01f;
- const float elem1_weight_ = -1.0f;
- const float elem2_weight_ = 5.0f;
- const float elem3_weight_ = -1.5f;
+ const float one_hot_elem1_weight_ = -1.0f;
+ const float one_hot_elem2_weight_ = 5.0f;
+ const float one_hot_elem3_weight_ = -1.5f;
const float one_hot_default_weight_ = 10.0f;
const float epsilon_ = 0.001f;
+
+ const std::string sparse_name_ = "sparse_feature";
+ const std::string sparse_elem1_name_ = "sparse_elem1";
+ const std::string sparse_elem2_name_ = "sparse_elem2";
+ const float sparse_elem1_weight_ = -2.2f;
+ const float sparse_elem2_weight_ = 3.1f;
+ const float sparse_default_weight_ = 4.4f;
+
+ const std::string bucketized_name_ = "bucketized_feature";
+ const float bucketization_boundaries_[2] = {0.3f, 0.7f};
+ const float bucketization_weights_[3] = {-1.0f, 1.0f, 3.0f};
+ const float bucketization_default_weight_ = -3.3f;
};
TEST_F(GenericLogisticRegressionInferenceTest, BaseTest) {
@@ -59,7 +96,7 @@ TEST_F(GenericLogisticRegressionInferenceTest, BaseTest) {
float score = predictor.PredictScore(example);
float expected_score =
Sigmoid(bias_ + 1.0f * scalar1_weight_ + 42.0f * scalar2_weight_ +
- 0.666f * scalar3_weight_ + elem1_weight_);
+ 0.666f * scalar3_weight_ + one_hot_elem1_weight_);
EXPECT_NEAR(expected_score, score, epsilon_);
EXPECT_EQ(expected_score >= threshold_, predictor.Predict(example));
}
@@ -99,7 +136,7 @@ TEST_F(GenericLogisticRegressionInferenceTest, UnknownFeatures) {
auto predictor = GenericLogisticRegressionInference(GetProto());
float score = predictor.PredictScore(example);
// Unknown features will be ignored.
- float expected_score = Sigmoid(bias_ + elem2_weight_);
+ float expected_score = Sigmoid(bias_ + one_hot_elem2_weight_);
EXPECT_NEAR(expected_score, score, epsilon_);
}
@@ -177,4 +214,77 @@ TEST_F(GenericLogisticRegressionInferenceTest, NoThreshold) {
EXPECT_FALSE(predictor.Predict(example));
}
+TEST_F(GenericLogisticRegressionInferenceTest, PreprossessedModel) {
+ GenericLogisticRegressionModel proto = GetProto();
+ proto.set_is_preprocessed_model(true);
+ // Clear the weights to make sure the inference is done by fullname_weights.
+ proto.clear_weights();
+
+ // Build fullname weights.
+ Map<std::string, float>& weights = *proto.mutable_fullname_weights();
+ weights[scalar1_name_] = scalar1_weight_;
+ weights[scalar2_name_] = scalar2_weight_;
+ weights[scalar3_name_] = scalar3_weight_;
+ weights[ExamplePreprocessor::FeatureFullname(
+ one_hot_name_, one_hot_elem1_name_)] = one_hot_elem1_weight_;
+ weights[ExamplePreprocessor::FeatureFullname(
+ one_hot_name_, one_hot_elem2_name_)] = one_hot_elem2_weight_;
+ weights[ExamplePreprocessor::FeatureFullname(
+ one_hot_name_, one_hot_elem3_name_)] = one_hot_elem3_weight_;
+ weights[ExamplePreprocessor::FeatureFullname(
+ sparse_name_, sparse_elem1_name_)] = sparse_elem1_weight_;
+ weights[ExamplePreprocessor::FeatureFullname(
+ sparse_name_, sparse_elem2_name_)] = sparse_elem2_weight_;
+ weights[ExamplePreprocessor::FeatureFullname(bucketized_name_, "0")] =
+ bucketization_weights_[0];
+ weights[ExamplePreprocessor::FeatureFullname(bucketized_name_, "1")] =
+ bucketization_weights_[1];
+ weights[ExamplePreprocessor::FeatureFullname(bucketized_name_, "2")] =
+ bucketization_weights_[2];
+ weights[ExamplePreprocessor::FeatureFullname(
+ ExamplePreprocessor::kMissingFeatureDefaultName, one_hot_name_)] =
+ one_hot_default_weight_;
+ weights[ExamplePreprocessor::FeatureFullname(
+ ExamplePreprocessor::kMissingFeatureDefaultName, sparse_name_)] =
+ sparse_default_weight_;
+ weights[ExamplePreprocessor::FeatureFullname(
+ ExamplePreprocessor::kMissingFeatureDefaultName, bucketized_name_)] =
+ bucketization_default_weight_;
+
+ // Build preprocessor_config.
+ ExamplePreprocessorConfig& config = *proto.mutable_preprocessor_config();
+ config.add_missing_features(one_hot_name_);
+ config.add_missing_features(sparse_name_);
+ config.add_missing_features(bucketized_name_);
+ (*config.mutable_bucketizers())[bucketized_name_].add_boundaries(
+ bucketization_boundaries_[0]);
+ (*config.mutable_bucketizers())[bucketized_name_].add_boundaries(
+ bucketization_boundaries_[1]);
+
+ auto predictor = GenericLogisticRegressionInference(proto);
+
+ // Build example.
+ RankerExample example;
+ Map<std::string, Feature>& features = *example.mutable_features();
+ features[scalar1_name_].set_bool_value(true);
+ features[scalar2_name_].set_int32_value(42);
+ features[scalar3_name_].set_float_value(0.666f);
+ features[one_hot_name_].set_string_value(one_hot_elem1_name_);
+ features[sparse_name_].mutable_string_list()->add_string_value(
+ sparse_elem1_name_);
+ features[sparse_name_].mutable_string_list()->add_string_value(
+ sparse_elem2_name_);
+ features[bucketized_name_].set_float_value(0.98f);
+
+ // Inference.
+ float score = predictor.PredictScore(example);
+ float expected_score = Sigmoid(
+ bias_ + 1.0f * scalar1_weight_ + 42.0f * scalar2_weight_ +
+ 0.666f * scalar3_weight_ + one_hot_elem1_weight_ + sparse_elem1_weight_ +
+ sparse_elem2_weight_ + bucketization_weights_[2]);
+
+ EXPECT_NEAR(expected_score, score, epsilon_);
+ EXPECT_EQ(expected_score >= threshold_, predictor.Predict(example));
+}
+
} // namespace assist_ranker
diff --git a/chromium/components/assist_ranker/proto/BUILD.gn b/chromium/components/assist_ranker/proto/BUILD.gn
index 9c1d6a0d526..7955a349561 100644
--- a/chromium/components/assist_ranker/proto/BUILD.gn
+++ b/chromium/components/assist_ranker/proto/BUILD.gn
@@ -6,6 +6,7 @@ import("//third_party/protobuf/proto_library.gni")
proto_library("proto") {
sources = [
+ "example_preprocessor.proto",
"generic_logistic_regression_model.proto",
"ranker_example.proto",
"ranker_model.proto",
diff --git a/chromium/components/assist_ranker/proto/example_preprocessor.proto b/chromium/components/assist_ranker/proto/example_preprocessor.proto
new file mode 100644
index 00000000000..84662c5ff74
--- /dev/null
+++ b/chromium/components/assist_ranker/proto/example_preprocessor.proto
@@ -0,0 +1,26 @@
+// Contains features required for Ranker model inference and training.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package assist_ranker;
+
+message ExamplePreprocessorConfig {
+ // A list of features names for which you want to do special handling if
+ // the feature is missing in the RankerExample.
+ repeated string missing_features = 1;
+
+ // Boundaries to bucketize a feature.
+ message Boundaries { repeated float boundaries = 1; }
+
+ // A map of feature_name to boundaries for bucketizing this feature.
+ map<string, Boundaries> bucketizers = 2;
+
+ // A map from feature_fullnames to indices for vectorizing a RankerExample.
+ // A feature fullname is defined as:
+ // (1) feature_name if it's bool_value, int64_value or float_value.
+ // (2) a combination of feature_name and feature_value if it's string_value
+ // or i-th element of a string_list.
+ map<string, int32> feature_indices = 3;
+}
diff --git a/chromium/components/assist_ranker/proto/generic_logistic_regression_model.proto b/chromium/components/assist_ranker/proto/generic_logistic_regression_model.proto
index 19c604accbc..cd1c4bf71db 100644
--- a/chromium/components/assist_ranker/proto/generic_logistic_regression_model.proto
+++ b/chromium/components/assist_ranker/proto/generic_logistic_regression_model.proto
@@ -8,6 +8,8 @@ syntax = "proto2";
option optimize_for = LITE_RUNTIME;
+import "example_preprocessor.proto";
+
package assist_ranker;
message SparseWeights {
@@ -69,4 +71,15 @@ message GenericLogisticRegressionModel {
// Map of weights keyed by feature name. Features can be scalar, one-hot,
// sparse or bucketized.
map<string, FeatureWeight> weights = 3;
-} \ No newline at end of file
+
+ // If it's a preprocessed_model, then use preprocessor_config to preprocess
+ // the input and fullname_weights to calculate the score.
+ optional bool is_preprocessed_model = 4;
+
+ // Map from feature fullname to it's weights.
+ map<string, float> fullname_weights = 5;
+
+ // Config for preprocessor (without feature_indices; there is no need for
+ // vectorization, since the inference model use ExampleFloatIterator instead).
+ optional ExamplePreprocessorConfig preprocessor_config = 6;
+}
diff --git a/chromium/components/assist_ranker/proto/ranker_example.proto b/chromium/components/assist_ranker/proto/ranker_example.proto
index 36d1a2c6e38..53b1c662aa8 100644
--- a/chromium/components/assist_ranker/proto/ranker_example.proto
+++ b/chromium/components/assist_ranker/proto/ranker_example.proto
@@ -14,6 +14,11 @@ message StringList {
repeated bytes string_value = 1;
}
+// A repeated list of float values.
+message FloatList {
+ repeated float float_value = 1;
+}
+
// Generic message that can contain a variety of data types.
message Feature {
oneof feature_type {
@@ -26,6 +31,8 @@ message Feature {
bytes string_value = 4;
// String list are used for sparse features.
StringList string_list = 5;
+ // Float lists represent vectorial features.
+ FloatList float_list = 6;
}
}
diff --git a/chromium/components/assist_ranker/ranker_example_util.cc b/chromium/components/assist_ranker/ranker_example_util.cc
index 54d4dbd58f7..ceedd8f9b18 100644
--- a/chromium/components/assist_ranker/ranker_example_util.cc
+++ b/chromium/components/assist_ranker/ranker_example_util.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <math.h>
+
#include "components/assist_ranker/ranker_example_util.h"
#include "base/bit_cast.h"
#include "base/format_macros.h"
diff --git a/chromium/components/assist_ranker/ranker_model.cc b/chromium/components/assist_ranker/ranker_model.cc
index 8278a0c24be..0495bcc65ef 100644
--- a/chromium/components/assist_ranker/ranker_model.cc
+++ b/chromium/components/assist_ranker/ranker_model.cc
@@ -4,19 +4,20 @@
#include "components/assist_ranker/ranker_model.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "base/time/time.h"
#include "components/assist_ranker/proto/ranker_model.pb.h"
namespace assist_ranker {
-RankerModel::RankerModel() : proto_(base::MakeUnique<RankerModelProto>()) {}
+RankerModel::RankerModel() : proto_(std::make_unique<RankerModelProto>()) {}
RankerModel::~RankerModel() {}
// static
std::unique_ptr<RankerModel> RankerModel::FromString(const std::string& data) {
- auto model = base::MakeUnique<RankerModel>();
+ auto model = std::make_unique<RankerModel>();
if (!model->mutable_proto()->ParseFromString(data))
return nullptr;
return model;
diff --git a/chromium/components/assist_ranker/ranker_model_loader_impl.cc b/chromium/components/assist_ranker/ranker_model_loader_impl.cc
index c2415645a73..e03529f3038 100644
--- a/chromium/components/assist_ranker/ranker_model_loader_impl.cc
+++ b/chromium/components/assist_ranker/ranker_model_loader_impl.cc
@@ -6,13 +6,14 @@
#include <utility>
+#include <memory>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/files/important_file_writer.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
@@ -102,7 +103,7 @@ RankerModelLoaderImpl::RankerModelLoaderImpl(
model_path_(std::move(model_path)),
model_url_(std::move(model_url)),
uma_prefix_(std::move(uma_prefix)),
- url_fetcher_(base::MakeUnique<RankerURLFetcher>()),
+ url_fetcher_(std::make_unique<RankerURLFetcher>()),
weak_ptr_factory_(this) {}
RankerModelLoaderImpl::~RankerModelLoaderImpl() {
@@ -120,6 +121,7 @@ void RankerModelLoaderImpl::NotifyOfRankerActivity() {
// There was no configured model path. Switch the state to IDLE and
// fall through to consider the URL.
state_ = LoaderState::IDLE;
+ FALLTHROUGH;
case LoaderState::IDLE:
if (model_url_.is_valid()) {
StartLoadFromURL();
@@ -128,6 +130,7 @@ void RankerModelLoaderImpl::NotifyOfRankerActivity() {
// There was no configured model URL. Switch the state to FINISHED and
// fall through.
state_ = LoaderState::FINISHED;
+ FALLTHROUGH;
case LoaderState::FINISHED:
case LoaderState::LOADING_FROM_FILE:
case LoaderState::LOADING_FROM_URL:
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 097e15c7c38..9799c9ceb5c 100644
--- a/chromium/components/assist_ranker/ranker_model_loader_impl_unittest.cc
+++ b/chromium/components/assist_ranker/ranker_model_loader_impl_unittest.cc
@@ -11,7 +11,6 @@
#include "base/containers/circular_deque.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/strings/stringprintf.h"
#include "base/task_scheduler/post_task.h"
@@ -143,7 +142,7 @@ void RankerModelLoaderImplTest::SetUp() {
// static
std::unique_ptr<RankerModel> RankerModelLoaderImplTest::Clone(
const RankerModel& model) {
- auto copy = base::MakeUnique<RankerModel>();
+ auto copy = std::make_unique<RankerModel>();
*copy->mutable_proto() = model.proto();
return copy;
}
@@ -168,7 +167,7 @@ bool RankerModelLoaderImplTest::IsEquivalent(const RankerModel& m1,
bool RankerModelLoaderImplTest::DoLoaderTest(const base::FilePath& model_path,
const GURL& model_url) {
- auto loader = base::MakeUnique<RankerModelLoaderImpl>(
+ auto loader = std::make_unique<RankerModelLoaderImpl>(
base::Bind(&RankerModelLoaderImplTest::ValidateModel,
base::Unretained(this)),
base::Bind(&RankerModelLoaderImplTest::OnModelAvailable,
diff --git a/chromium/components/assist_ranker/ranker_model_unittest.cc b/chromium/components/assist_ranker/ranker_model_unittest.cc
index cd53970794f..3ac195f0b9e 100644
--- a/chromium/components/assist_ranker/ranker_model_unittest.cc
+++ b/chromium/components/assist_ranker/ranker_model_unittest.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "components/assist_ranker/proto/ranker_model.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -24,7 +23,7 @@ int64_t InSeconds(const base::Time t) {
std::unique_ptr<RankerModel> NewModel(const std::string& model_url,
base::Time last_modified,
base::TimeDelta cache_duration) {
- std::unique_ptr<RankerModel> model = base::MakeUnique<RankerModel>();
+ std::unique_ptr<RankerModel> model = std::make_unique<RankerModel>();
auto* metadata = model->mutable_proto()->mutable_metadata();
if (!model_url.empty())
metadata->set_source(model_url);
diff --git a/chromium/components/autofill/android/java/strings/translations/autofill_strings_ko.xtb b/chromium/components/autofill/android/java/strings/translations/autofill_strings_ko.xtb
index cdc1519f95e..384f7c2fa0c 100644
--- a/chromium/components/autofill/android/java/strings/translations/autofill_strings_ko.xtb
+++ b/chromium/components/autofill/android/java/strings/translations/autofill_strings_ko.xtb
@@ -1,5 +1,5 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="ko">
-<translation id="1112374155460533568">자동완성 팝업 표시</translation>
+<translation id="1112374155460533568">자동 완성 팝업 표시</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/components/autofill/content/browser/BUILD.gn b/chromium/components/autofill/content/browser/BUILD.gn
index 94c98d4739a..3e13b847251 100644
--- a/chromium/components/autofill/content/browser/BUILD.gn
+++ b/chromium/components/autofill/content/browser/BUILD.gn
@@ -34,13 +34,12 @@ static_library("browser") {
"//content/public/browser",
"//content/public/common",
"//device/geolocation/public/cpp",
- "//device/geolocation/public/interfaces",
"//gpu/config",
"//mojo/common:common_base",
"//mojo/public/cpp/bindings",
"//net",
"//ppapi/features",
- "//services/device/public/interfaces",
+ "//services/device/public/mojom",
"//services/service_manager/public/cpp",
"//sql",
"//ui/base",
diff --git a/chromium/components/autofill/content/browser/DEPS b/chromium/components/autofill/content/browser/DEPS
index e6b2b02eb74..234f67bc55b 100644
--- a/chromium/components/autofill/content/browser/DEPS
+++ b/chromium/components/autofill/content/browser/DEPS
@@ -4,7 +4,7 @@ include_rules = [
"+device/geolocation/public",
"+gpu/config/gpu_info.h",
"+services/device/public",
- "+services/service_manager/public/interfaces",
+ "+services/service_manager/public/mojom",
"+third_party/WebKit/public/platform/WebRect.h",
]
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.cc b/chromium/components/autofill/content/browser/content_autofill_driver.cc
index 71f4284a9f8..42209e8e38a 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.cc
@@ -42,11 +42,7 @@ ContentAutofillDriver::ContentAutofillDriver(
// AutofillManager isn't used if provider is valid, Autofill provider is
// currently used by Android WebView only.
if (provider) {
- autofill_handler_ = std::make_unique<AutofillHandlerProxy>(this, provider);
- GetAutofillAgent()->SetUserGestureRequired(false);
- GetAutofillAgent()->SetSecureContextRequired(true);
- GetAutofillAgent()->SetFocusRequiresScroll(false);
- GetAutofillAgent()->SetQueryPasswordSuggestion(true);
+ SetAutofillProvider(provider);
} else {
autofill_handler_ = std::make_unique<AutofillManager>(
this, client, app_locale, enable_download_manager);
@@ -167,9 +163,9 @@ gfx::RectF ContentAutofillDriver::TransformBoundingBoxToViewportCoordinates(
if (!view)
return bounding_box;
- gfx::Point orig_point(bounding_box.x(), bounding_box.y());
- gfx::Point transformed_point =
- view->TransformPointToRootCoordSpace(orig_point);
+ gfx::PointF orig_point(bounding_box.x(), bounding_box.y());
+ gfx::PointF transformed_point =
+ view->TransformPointToRootCoordSpaceF(orig_point);
return gfx::RectF(transformed_point.x(), transformed_point.y(),
bounding_box.width(), bounding_box.height());
}
@@ -304,4 +300,17 @@ void ContentAutofillDriver::RemoveHandler(
view->GetRenderWidgetHost()->RemoveKeyPressEventCallback(handler);
}
+void ContentAutofillDriver::SetAutofillProvider(AutofillProvider* provider) {
+ autofill_handler_ = std::make_unique<AutofillHandlerProxy>(this, provider);
+ GetAutofillAgent()->SetUserGestureRequired(false);
+ GetAutofillAgent()->SetSecureContextRequired(true);
+ GetAutofillAgent()->SetFocusRequiresScroll(false);
+ GetAutofillAgent()->SetQueryPasswordSuggestion(true);
+}
+
+void ContentAutofillDriver::SetAutofillProviderForTesting(
+ AutofillProvider* provider) {
+ SetAutofillProvider(provider);
+}
+
} // 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 17758e4472a..285f2f92535 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.h
@@ -119,6 +119,8 @@ class ContentAutofillDriver : public AutofillDriver,
const content::RenderWidgetHost::KeyPressEventCallback& handler);
void RemoveKeyPressHandler();
+ void SetAutofillProviderForTesting(AutofillProvider* provider);
+
protected:
// Sets the manager to |manager| and sets |manager|'s external delegate
// to |autofill_external_delegate_|. Takes ownership of |manager|.
@@ -131,6 +133,8 @@ class ContentAutofillDriver : public AutofillDriver,
void RemoveHandler(
const content::RenderWidgetHost::KeyPressEventCallback& handler) override;
+ void SetAutofillProvider(AutofillProvider* provider);
+
// Weak ref to the RenderFrameHost the driver is associated with. Should
// always be non-NULL and valid for lifetime of |this|.
content::RenderFrameHost* const render_frame_host_;
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 f336ddd579d..f67d15c2a7f 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc
@@ -149,8 +149,10 @@ void ContentAutofillDriverFactory::DidFinishNavigation(
->DidNavigateMainFrame(navigation_handle);
}
-void ContentAutofillDriverFactory::WasHidden() {
- TabHidden();
+void ContentAutofillDriverFactory::OnVisibilityChanged(
+ content::Visibility visibility) {
+ if (visibility == content::Visibility::HIDDEN)
+ TabHidden();
}
} // namespace autofill
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 adc12b53ffc..1bcb2f909f3 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -59,7 +59,7 @@ class ContentAutofillDriverFactory : public AutofillDriverFactory,
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
- void WasHidden() override;
+ void OnVisibilityChanged(content::Visibility visibility) override;
static const char kContentAutofillDriverFactoryWebContentsUserDataKey[];
diff --git a/chromium/components/autofill/content/browser/risk/fingerprint.cc b/chromium/components/autofill/content/browser/risk/fingerprint.cc
index b194e1c91b0..8a9125ba166 100644
--- a/chromium/components/autofill/content/browser/risk/fingerprint.cc
+++ b/chromium/components/autofill/content/browser/risk/fingerprint.cc
@@ -39,13 +39,13 @@
#include "content/public/common/screen_info.h"
#include "content/public/common/webplugininfo.h"
#include "device/geolocation/public/cpp/geoposition.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
#include "gpu/config/gpu_info.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "ppapi/features/features.h"
-#include "services/device/public/interfaces/constants.mojom.h"
-#include "services/device/public/interfaces/geolocation_context.mojom.h"
+#include "services/device/public/mojom/constants.mojom.h"
+#include "services/device/public/mojom/geolocation.mojom.h"
+#include "services/device/public/mojom/geolocation_context.mojom.h"
+#include "services/device/public/mojom/geoposition.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "ui/display/display.h"
diff --git a/chromium/components/autofill/content/browser/risk/fingerprint_browsertest.cc b/chromium/components/autofill/content/browser/risk/fingerprint_browsertest.cc
index 12245ec0dcb..367fb77e1f8 100644
--- a/chromium/components/autofill/content/browser/risk/fingerprint_browsertest.cc
+++ b/chromium/components/autofill/content/browser/risk/fingerprint_browsertest.cc
@@ -19,7 +19,7 @@
#include "content/public/test/content_browser_test.h"
#include "content/public/test/test_utils.h"
#include "device/geolocation/public/cpp/scoped_geolocation_overrider.h"
-#include "device/geolocation/public/interfaces/geoposition.mojom.h"
+#include "services/device/public/mojom/geoposition.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/autofill/content/common/BUILD.gn b/chromium/components/autofill/content/common/BUILD.gn
index 1aa868d6f15..0b9280774c0 100644
--- a/chromium/components/autofill/content/common/BUILD.gn
+++ b/chromium/components/autofill/content/common/BUILD.gn
@@ -14,7 +14,7 @@ mojom("mojo_interfaces") {
":mojo_types",
"//mojo/common:common_custom_types",
"//ui/gfx/geometry/mojo",
- "//url/mojo:url_mojom_gurl",
+ "//url/mojom:url_mojom_gurl",
]
}
@@ -25,8 +25,9 @@ mojom("mojo_types") {
public_deps = [
"//mojo/common:common_custom_types",
- "//url/mojo:url_mojom_gurl",
- "//url/mojo:url_mojom_origin",
+ "//mojo/public/mojom/base",
+ "//url/mojom:url_mojom_gurl",
+ "//url/mojom:url_mojom_origin",
]
}
diff --git a/chromium/components/autofill/content/common/autofill_agent.mojom b/chromium/components/autofill/content/common/autofill_agent.mojom
index 687804e63b7..bec0acd1f70 100644
--- a/chromium/components/autofill/content/common/autofill_agent.mojom
+++ b/chromium/components/autofill/content/common/autofill_agent.mojom
@@ -5,7 +5,7 @@
module autofill.mojom;
import "components/autofill/content/common/autofill_types.mojom";
-import "mojo/common/string16.mojom";
+import "mojo/public/mojom/base/string16.mojom";
// There is one instance of this interface per render frame in the render
// process. All methods are called by browser on renderer.
@@ -28,23 +28,23 @@ interface AutofillAgent {
ClearPreviewedForm();
// Sets the currently selected node's value.
- FillFieldWithValue(mojo.common.mojom.String16 value);
+ FillFieldWithValue(mojo_base.mojom.String16 value);
// Sets the suggested value for the currently previewed node.
- PreviewFieldWithValue(mojo.common.mojom.String16 value);
+ PreviewFieldWithValue(mojo_base.mojom.String16 value);
// Sets the currently selected node's value to be the given data list value.
- AcceptDataListSuggestion(mojo.common.mojom.String16 value);
+ AcceptDataListSuggestion(mojo_base.mojom.String16 value);
// Tells the renderer to fill the username and password with with given
// values.
- FillPasswordSuggestion(mojo.common.mojom.String16 username,
- mojo.common.mojom.String16 password);
+ FillPasswordSuggestion(mojo_base.mojom.String16 username,
+ mojo_base.mojom.String16 password);
// Tells the renderer to preview the username and password with the given
// values.
- PreviewPasswordSuggestion(mojo.common.mojom.String16 username,
- mojo.common.mojom.String16 password);
+ PreviewPasswordSuggestion(mojo_base.mojom.String16 username,
+ mojo_base.mojom.String16 password);
// Sent when a password form is initially detected and suggestions should be
// shown. Used by the fill-on-select experiment.
@@ -106,7 +106,7 @@ interface PasswordAutofillAgent {
interface PasswordGenerationAgent {
// Tells the renderer to populate the correct password fields with this
// generated password.
- GeneratedPasswordAccepted(mojo.common.mojom.String16 generated_password);
+ GeneratedPasswordAccepted(mojo_base.mojom.String16 generated_password);
// Tells the renderer to find a focused element, and if it is a password field
// eligible for generation then to trigger generation by responding to the
diff --git a/chromium/components/autofill/content/common/autofill_driver.mojom b/chromium/components/autofill/content/common/autofill_driver.mojom
index 1e6f10810d3..70527dab04b 100644
--- a/chromium/components/autofill/content/common/autofill_driver.mojom
+++ b/chromium/components/autofill/content/common/autofill_driver.mojom
@@ -5,11 +5,11 @@
module autofill.mojom;
import "components/autofill/content/common/autofill_types.mojom";
-import "mojo/common/string16.mojom";
+import "mojo/public/mojom/base/string16.mojom";
import "mojo/common/text_direction.mojom";
import "mojo/common/time.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
-import "url/mojo/url.mojom";
+import "url/mojom/url.mojom";
// There is one instance of this interface per render frame host in the browser
// process. All methods are called by renderer on browser.
@@ -65,8 +65,8 @@ interface AutofillDriver {
DidEndTextFieldEditing();
// Informs browser of data list values for the current field.
- SetDataList(array<mojo.common.mojom.String16> values,
- array<mojo.common.mojom.String16> labels);
+ SetDataList(array<mojo_base.mojom.String16> values,
+ array<mojo_base.mojom.String16> labels);
};
// There is one instance of this interface per render frame host in the browser
@@ -93,9 +93,9 @@ interface PasswordManagerDriver {
// save/update prompt anchored to the omnibox icon should be removed.
HideManualFallbackForSaving();
- // Notification that in-page navigation happened and at this moment we have
- // filled password form. We use this as a signal for successful login.
- InPageNavigation(PasswordForm password_form);
+ // Notification that same-document navigation happened and at this moment we
+ // have filled password form. We use this as a signal for successful login.
+ SameDocumentNavigation(PasswordForm password_form);
// Sends |log| to browser for displaying to the user. Only strings passed as
// an argument to methods overriding SavePasswordProgressLogger::SendLog may
@@ -112,7 +112,7 @@ interface PasswordManagerDriver {
// text.
ShowPasswordSuggestions(int32 key,
mojo.common.mojom.TextDirection text_direction,
- mojo.common.mojom.String16 typed_username,
+ mojo_base.mojom.String16 typed_username,
int32 options, gfx.mojom.RectF bounds);
// Instructs the browser to show a popup with a warning that the form
@@ -139,7 +139,7 @@ interface PasswordManagerDriver {
// Sends the outcome of HTML parsing based form classifier that detects the
// forms where password generation should be available.
SaveGenerationFieldDetectedByClassifier(
- PasswordForm password_form, mojo.common.mojom.String16 generation_field);
+ PasswordForm password_form, mojo_base.mojom.String16 generation_field);
// Checks the safe browsing reputation of the website where the focused
// username/password field is on.
@@ -164,7 +164,7 @@ interface PasswordManagerClient {
// triggered generation.
ShowPasswordGenerationPopup(
gfx.mojom.RectF bounds, int32 max_length,
- mojo.common.mojom.String16 generation_element, bool is_manually_triggered,
+ mojo_base.mojom.String16 generation_element, bool is_manually_triggered,
PasswordForm password_form);
// Instructs the browser to show the popup for editing a generated password.
diff --git a/chromium/components/autofill/content/common/autofill_types.mojom b/chromium/components/autofill/content/common/autofill_types.mojom
index 3a6fa9ecc63..a595a192dad 100644
--- a/chromium/components/autofill/content/common/autofill_types.mojom
+++ b/chromium/components/autofill/content/common/autofill_types.mojom
@@ -6,8 +6,9 @@ module autofill.mojom;
import "mojo/common/text_direction.mojom";
import "mojo/common/time.mojom";
-import "url/mojo/origin.mojom";
-import "url/mojo/url.mojom";
+import "mojo/public/mojom/base/string16.mojom";
+import "url/mojom/origin.mojom";
+import "url/mojom/url.mojom";
// autofill::FormFieldData::CheckStatus
enum CheckStatus {
@@ -85,16 +86,30 @@ enum SubmissionSource {
FORM_SUBMISSION,
};
+// autofill::FormFieldData::LabelSource
+enum LabelSource {
+ UNKNOWN,
+ LABEL_TAG,
+ P_TAG,
+ DIV_TABLE,
+ TD_TAG,
+ DD_TAG,
+ LI_TAG,
+ PLACE_HOLDER,
+ COMBINED,
+ VALUE,
+};
+
// autofill::FormFieldData
struct FormFieldData {
- string label;
- string name;
- string id;
- string value;
+ mojo_base.mojom.String16 label;
+ mojo_base.mojom.String16 name;
+ mojo_base.mojom.String16 id;
+ mojo_base.mojom.String16 value;
string form_control_type;
string autocomplete_attribute;
- string placeholder;
- string css_classes;
+ mojo_base.mojom.String16 placeholder;
+ mojo_base.mojom.String16 css_classes;
uint32 properties_mask;
uint64 max_length;
@@ -105,13 +120,15 @@ struct FormFieldData {
RoleAttribute role;
mojo.common.mojom.TextDirection text_direction;
- array<string> option_values;
- array<string> option_contents;
+ array<mojo_base.mojom.String16> option_values;
+ array<mojo_base.mojom.String16> option_contents;
+
+ LabelSource label_source;
};
// autofill::FormData
struct FormData {
- string name;
+ mojo_base.mojom.String16 name;
// TODO(crbug.com/788181): Either change type to Origin or rename to URL.
url.mojom.Url origin;
url.mojom.Url action;
@@ -140,20 +157,19 @@ struct FormDataPredictions {
// autofill::PasswordAndRealm
struct PasswordAndRealm {
- string password;
+ mojo_base.mojom.String16 password;
string realm;
};
-
// autofill::PasswordFormFillData
struct PasswordFormFillData {
- string name;
+ mojo_base.mojom.String16 name;
url.mojom.Url origin;
url.mojom.Url action;
FormFieldData username_field;
FormFieldData password_field;
string preferred_realm;
- map<string, PasswordAndRealm> additional_logins;
+ map<mojo_base.mojom.String16, PasswordAndRealm> additional_logins;
bool wait_for_username;
bool is_possible_change_password_form;
};
@@ -168,8 +184,8 @@ struct PasswordFormGenerationData {
// autofill::PossibleUsernamePair
struct PossibleUsernamePair {
- string value;
- string field_name;
+ mojo_base.mojom.String16 value;
+ mojo_base.mojom.String16 field_name;
};
// autofill::PasswordForm
@@ -179,21 +195,21 @@ struct PasswordForm {
url.mojom.Url origin_with_path;
url.mojom.Url action;
string affiliated_web_realm;
- string submit_element;
- string username_element;
+ mojo_base.mojom.String16 submit_element;
+ mojo_base.mojom.String16 username_element;
bool username_marked_by_site;
- string username_value;
+ mojo_base.mojom.String16 username_value;
array<PossibleUsernamePair> other_possible_usernames;
- array<string> all_possible_passwords;
+ array<mojo_base.mojom.String16> all_possible_passwords;
bool form_has_autofilled_value;
- string password_element;
- string password_value;
+ mojo_base.mojom.String16 password_element;
+ mojo_base.mojom.String16 password_value;
bool password_value_is_default;
- string new_password_element;
- string new_password_value;
+ mojo_base.mojom.String16 new_password_element;
+ mojo_base.mojom.String16 new_password_value;
bool new_password_value_is_default;
bool new_password_marked_by_site;
- string confirmation_password_element;
+ mojo_base.mojom.String16 confirmation_password_element;
bool preferred;
mojo.common.mojom.Time date_created;
mojo.common.mojom.Time date_synced;
@@ -202,7 +218,7 @@ struct PasswordForm {
int32 times_used;
FormData form_data;
GenerationUploadStatus generation_upload_status;
- string display_name;
+ mojo_base.mojom.String16 display_name;
url.mojom.Url icon_url;
url.mojom.Origin federation_origin;
bool skip_zero_click;
diff --git a/chromium/components/autofill/content/common/autofill_types_struct_traits.cc b/chromium/components/autofill/content/common/autofill_types_struct_traits.cc
index 953a9835f31..aaa587f914d 100644
--- a/chromium/components/autofill/content/common/autofill_types_struct_traits.cc
+++ b/chromium/components/autofill/content/common/autofill_types_struct_traits.cc
@@ -7,8 +7,9 @@
#include "base/i18n/rtl.h"
#include "mojo/common/common_custom_types_struct_traits.h"
#include "mojo/common/time_struct_traits.h"
-#include "url/mojo/origin_struct_traits.h"
-#include "url/mojo/url_gurl_struct_traits.h"
+#include "mojo/public/cpp/base/string16_mojom_traits.h"
+#include "url/mojom/origin_mojom_traits.h"
+#include "url/mojom/url_gurl_mojom_traits.h"
namespace mojo {
@@ -467,6 +468,79 @@ bool EnumTraits<autofill::mojom::SubmissionSource, autofill::SubmissionSource>::
}
// static
+autofill::mojom::LabelSource
+EnumTraits<autofill::mojom::LabelSource, autofill::FormFieldData::LabelSource>::
+ ToMojom(autofill::FormFieldData::LabelSource input) {
+ switch (input) {
+ case autofill::FormFieldData::LabelSource::UNKNOWN:
+ return autofill::mojom::LabelSource::UNKNOWN;
+ case autofill::FormFieldData::LabelSource::LABEL_TAG:
+ return autofill::mojom::LabelSource::LABEL_TAG;
+ case autofill::FormFieldData::LabelSource::P_TAG:
+ return autofill::mojom::LabelSource::P_TAG;
+ case autofill::FormFieldData::LabelSource::DIV_TABLE:
+ return autofill::mojom::LabelSource::DIV_TABLE;
+ case autofill::FormFieldData::LabelSource::TD_TAG:
+ return autofill::mojom::LabelSource::TD_TAG;
+ case autofill::FormFieldData::LabelSource::DD_TAG:
+ return autofill::mojom::LabelSource::DD_TAG;
+ case autofill::FormFieldData::LabelSource::LI_TAG:
+ return autofill::mojom::LabelSource::LI_TAG;
+ case autofill::FormFieldData::LabelSource::PLACE_HOLDER:
+ return autofill::mojom::LabelSource::PLACE_HOLDER;
+ case autofill::FormFieldData::LabelSource::COMBINED:
+ return autofill::mojom::LabelSource::COMBINED;
+ case autofill::FormFieldData::LabelSource::VALUE:
+ return autofill::mojom::LabelSource::VALUE;
+ }
+
+ NOTREACHED();
+ return autofill::mojom::LabelSource::UNKNOWN;
+}
+
+// static
+bool EnumTraits<autofill::mojom::LabelSource,
+ autofill::FormFieldData::LabelSource>::
+ FromMojom(autofill::mojom::LabelSource input,
+ autofill::FormFieldData::LabelSource* output) {
+ switch (input) {
+ case autofill::mojom::LabelSource::UNKNOWN:
+ *output = autofill::FormFieldData::LabelSource::UNKNOWN;
+ return true;
+ case autofill::mojom::LabelSource::LABEL_TAG:
+ *output = autofill::FormFieldData::LabelSource::LABEL_TAG;
+ return true;
+ case autofill::mojom::LabelSource::P_TAG:
+ *output = autofill::FormFieldData::LabelSource::P_TAG;
+ return true;
+ case autofill::mojom::LabelSource::DIV_TABLE:
+ *output = autofill::FormFieldData::LabelSource::DIV_TABLE;
+ return true;
+ case autofill::mojom::LabelSource::TD_TAG:
+ *output = autofill::FormFieldData::LabelSource::TD_TAG;
+ return true;
+ case autofill::mojom::LabelSource::DD_TAG:
+ *output = autofill::FormFieldData::LabelSource::DD_TAG;
+ return true;
+ case autofill::mojom::LabelSource::LI_TAG:
+ *output = autofill::FormFieldData::LabelSource::LI_TAG;
+ return true;
+ case autofill::mojom::LabelSource::PLACE_HOLDER:
+ *output = autofill::FormFieldData::LabelSource::PLACE_HOLDER;
+ return true;
+ case autofill::mojom::LabelSource::COMBINED:
+ *output = autofill::FormFieldData::LabelSource::COMBINED;
+ return true;
+ case autofill::mojom::LabelSource::VALUE:
+ *output = autofill::FormFieldData::LabelSource::VALUE;
+ return true;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+// static
bool StructTraits<
autofill::mojom::FormFieldDataDataView,
autofill::FormFieldData>::Read(autofill::mojom::FormFieldDataDataView data,
@@ -513,6 +587,9 @@ bool StructTraits<
if (!data.ReadOptionContents(&out->option_contents))
return false;
+ if (!data.ReadLabelSource(&out->label_source))
+ return false;
+
return true;
}
diff --git a/chromium/components/autofill/content/common/autofill_types_struct_traits.h b/chromium/components/autofill/content/common/autofill_types_struct_traits.h
index bcdd9bf53ad..88de915f3ca 100644
--- a/chromium/components/autofill/content/common/autofill_types_struct_traits.h
+++ b/chromium/components/autofill/content/common/autofill_types_struct_traits.h
@@ -107,6 +107,15 @@ struct EnumTraits<autofill::mojom::SubmissionSource,
};
template <>
+struct EnumTraits<autofill::mojom::LabelSource,
+ autofill::FormFieldData::LabelSource> {
+ static autofill::mojom::LabelSource ToMojom(
+ autofill::FormFieldData::LabelSource input);
+ static bool FromMojom(autofill::mojom::LabelSource input,
+ autofill::FormFieldData::LabelSource* output);
+};
+
+template <>
struct StructTraits<autofill::mojom::FormFieldDataDataView,
autofill::FormFieldData> {
static const base::string16& label(const autofill::FormFieldData& r) {
@@ -188,6 +197,11 @@ struct StructTraits<autofill::mojom::FormFieldDataDataView,
return r.option_contents;
}
+ static autofill::FormFieldData::LabelSource label_source(
+ const autofill::FormFieldData& r) {
+ return r.label_source;
+ }
+
static bool Read(autofill::mojom::FormFieldDataDataView data,
autofill::FormFieldData* out);
};
diff --git a/chromium/components/autofill/content/renderer/DEPS b/chromium/components/autofill/content/renderer/DEPS
index ab8522257a9..628834d5642 100644
--- a/chromium/components/autofill/content/renderer/DEPS
+++ b/chromium/components/autofill/content/renderer/DEPS
@@ -3,7 +3,7 @@ include_rules = [
"+content/public/renderer",
"+third_party/re2",
# Allow inclusion of WebKit API files.
- "+third_party/WebKit/common",
+ "+third_party/WebKit/public/common",
"+third_party/WebKit/public/platform",
"+third_party/WebKit/public/web",
]
diff --git a/chromium/components/autofill/content/renderer/autofill_agent.cc b/chromium/components/autofill/content/renderer/autofill_agent.cc
index 2fd093bcad2..854cb1ac0f0 100644
--- a/chromium/components/autofill/content/renderer/autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/autofill_agent.cc
@@ -544,6 +544,9 @@ void AutofillAgent::ShowNotSecureWarning(
}
bool AutofillAgent::CollectFormlessElements(FormData* output) {
+ if (render_frame() == nullptr || render_frame()->GetWebFrame() == nullptr)
+ return false;
+
WebDocument document = render_frame()->GetWebFrame()->GetDocument();
// Build up the FormData from the unowned elements. This logic mostly
@@ -686,8 +689,7 @@ void AutofillAgent::QueryAutofillSuggestions(
void AutofillAgent::DoFillFieldWithValue(const base::string16& value,
WebInputElement* node) {
form_tracker_.set_ignore_text_changes(true);
- node->SetAutofillValue(
- blink::WebString::FromUTF16(value.substr(0, node->MaxLength())));
+ node->SetAutofillValue(blink::WebString::FromUTF16(value));
password_autofill_agent_->UpdateStateForTextChange(*node);
form_tracker_.set_ignore_text_changes(false);
}
@@ -695,8 +697,7 @@ void AutofillAgent::DoFillFieldWithValue(const base::string16& value,
void AutofillAgent::DoPreviewFieldWithValue(const base::string16& value,
WebInputElement* node) {
was_query_node_autofilled_ = element_.IsAutofilled();
- node->SetSuggestedValue(
- blink::WebString::FromUTF16(value.substr(0, node->MaxLength())));
+ node->SetSuggestedValue(blink::WebString::FromUTF16(value));
node->SetAutofilled(true);
form_util::PreviewSuggestion(node->SuggestedValue().Utf16(),
node->Value().Utf16(), node);
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util.cc b/chromium/components/autofill/content/renderer/form_autofill_util.cc
index ba6d04d09a6..7b035ecd689 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util.cc
+++ b/chromium/components/autofill/content/renderer/form_autofill_util.cc
@@ -12,6 +12,7 @@
#include <vector>
#include "base/command_line.h"
+#include "base/i18n/case_conversion.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
@@ -41,6 +42,7 @@
#include "third_party/WebKit/public/web/WebOptionElement.h"
#include "third_party/WebKit/public/web/WebSelectElement.h"
+using autofill::FormFieldData;
using blink::WebDocument;
using blink::WebElement;
using blink::WebElementCollection;
@@ -261,10 +263,26 @@ base::string16 FindChildTextWithIgnoreList(
return node_text;
}
+bool IsLabelValid(base::StringPiece16 inferred_label,
+ const std::vector<base::char16>& 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](base::char16 c) {
+ return !base::ContainsValue(stop_words, c);
+ });
+ return first_non_stop_word != inferred_label.end();
+}
+
// Shared function for InferLabelFromPrevious() and InferLabelFromNext().
-base::string16 InferLabelFromSibling(const WebFormControlElement& element,
- bool forward) {
+bool InferLabelFromSibling(const WebFormControlElement& element,
+ const std::vector<base::char16>& stop_words,
+ bool forward,
+ base::string16* label,
+ FormFieldData::LabelSource* label_source) {
base::string16 inferred_label;
+ FormFieldData::LabelSource inferred_label_source =
+ FormFieldData::LabelSource::UNKNOWN;
WebNode sibling = element;
while (true) {
sibling = forward ? sibling.NextSibling() : sibling.PreviousSibling();
@@ -293,6 +311,7 @@ base::string16 InferLabelFromSibling(const WebFormControlElement& element,
base::string16 value = FindChildText(sibling);
// A text node's value will be empty if it is for a line break.
bool add_space = sibling.IsTextNode() && value.empty();
+ inferred_label_source = FormFieldData::LabelSource::COMBINED;
inferred_label =
CombineAndCollapseWhitespace(value, inferred_label, add_space);
continue;
@@ -302,8 +321,10 @@ base::string16 InferLabelFromSibling(const WebFormControlElement& element,
// element, consider the label to be complete.
base::string16 trimmed_label;
base::TrimWhitespace(inferred_label, base::TRIM_ALL, &trimmed_label);
- if (!trimmed_label.empty())
+ if (!trimmed_label.empty()) {
+ inferred_label_source = FormFieldData::LabelSource::COMBINED;
break;
+ }
// <img> and <br> tags often appear between the input element and its
// label text, so skip over them.
@@ -315,14 +336,24 @@ base::string16 InferLabelFromSibling(const WebFormControlElement& element,
// We only expect <p> and <label> tags to contain the full label text.
CR_DEFINE_STATIC_LOCAL(WebString, kPage, ("p"));
CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label"));
- if (HasTagName(sibling, kPage) || HasTagName(sibling, kLabel))
+ bool has_label_tag = HasTagName(sibling, kLabel);
+ if (HasTagName(sibling, kPage) || has_label_tag) {
inferred_label = FindChildText(sibling);
+ inferred_label_source = has_label_tag
+ ? FormFieldData::LabelSource::LABEL_TAG
+ : FormFieldData::LabelSource::P_TAG;
+ }
break;
}
base::TrimWhitespace(inferred_label, base::TRIM_ALL, &inferred_label);
- return inferred_label;
+ if (IsLabelValid(inferred_label, stop_words)) {
+ *label = std::move(inferred_label);
+ *label_source = inferred_label_source;
+ return true;
+ }
+ return false;
}
// Helper for |InferLabelForElement()| that infers a label, if possible, from
@@ -333,14 +364,22 @@ base::string16 InferLabelFromSibling(const WebFormControlElement& element,
// or <label>Some Text</label> <input ...>
// or Some Text <img><input ...>
// or <b>Some Text</b><br/> <input ...>.
-base::string16 InferLabelFromPrevious(const WebFormControlElement& element) {
- return InferLabelFromSibling(element, false /* forward? */);
+bool InferLabelFromPrevious(const WebFormControlElement& element,
+ const std::vector<base::char16>& stop_words,
+ base::string16* label,
+ FormFieldData::LabelSource* label_source) {
+ return InferLabelFromSibling(element, stop_words, false /* forward? */, label,
+ label_source);
}
// Same as InferLabelFromPrevious(), but in the other direction.
// Useful for cases like: <span><input type="checkbox">Label For Checkbox</span>
-base::string16 InferLabelFromNext(const WebFormControlElement& element) {
- return InferLabelFromSibling(element, true /* forward? */);
+bool InferLabelFromNext(const WebFormControlElement& element,
+ const std::vector<base::char16>& stop_words,
+ base::string16* label,
+ FormFieldData::LabelSource* label_source) {
+ return InferLabelFromSibling(element, stop_words, true /* forward? */, label,
+ label_source);
}
// Helper for |InferLabelForElement()| that infers a label, if possible, from
@@ -650,72 +689,75 @@ std::vector<std::string> AncestorTagNames(
return tag_names;
}
-bool IsLabelValid(base::StringPiece16 inferred_label,
- const std::vector<base::char16>& 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](base::char16 c) {
- return !base::ContainsValue(stop_words, c);
- });
- return first_non_stop_word != inferred_label.end();
-}
-
// Infers corresponding label for |element| from surrounding context in the DOM,
// e.g. the contents of the preceding <p> tag or text element.
-base::string16 InferLabelForElement(const WebFormControlElement& element,
- const std::vector<base::char16>& stop_words) {
- base::string16 inferred_label;
-
+bool InferLabelForElement(const WebFormControlElement& element,
+ const std::vector<base::char16>& stop_words,
+ base::string16* label,
+ FormFieldData::LabelSource* label_source) {
if (IsCheckableElement(ToWebInputElement(&element))) {
- inferred_label = InferLabelFromNext(element);
- if (IsLabelValid(inferred_label, stop_words))
- return inferred_label;
+ if (InferLabelFromNext(element, stop_words, label, label_source))
+ return true;
}
- inferred_label = InferLabelFromPrevious(element);
- if (IsLabelValid(inferred_label, stop_words))
- return inferred_label;
+ if (InferLabelFromPrevious(element, stop_words, label, label_source))
+ return true;
// If we didn't find a label, check for placeholder text.
- inferred_label = InferLabelFromPlaceholder(element);
- if (IsLabelValid(inferred_label, stop_words))
- return inferred_label;
+ base::string16 inferred_label = InferLabelFromPlaceholder(element);
+ if (IsLabelValid(inferred_label, stop_words)) {
+ *label_source = FormFieldData::LabelSource::PLACE_HOLDER;
+ *label = std::move(inferred_label);
+ return true;
+ }
// For all other searches that involve traversing up the tree, the search
// order is based on which tag is the closest ancestor to |element|.
std::vector<std::string> tag_names = AncestorTagNames(element);
std::set<std::string> seen_tag_names;
+ FormFieldData::LabelSource ancestor_label_source =
+ FormFieldData::LabelSource::UNKNOWN;
for (const std::string& tag_name : tag_names) {
if (base::ContainsKey(seen_tag_names, tag_name))
continue;
seen_tag_names.insert(tag_name);
if (tag_name == "LABEL") {
+ ancestor_label_source = FormFieldData::LabelSource::LABEL_TAG;
inferred_label = InferLabelFromEnclosingLabel(element);
} else if (tag_name == "DIV") {
+ ancestor_label_source = FormFieldData::LabelSource::DIV_TABLE;
inferred_label = InferLabelFromDivTable(element);
} else if (tag_name == "TD") {
+ ancestor_label_source = FormFieldData::LabelSource::TD_TAG;
inferred_label = InferLabelFromTableColumn(element);
if (!IsLabelValid(inferred_label, stop_words))
inferred_label = InferLabelFromTableRow(element);
} else if (tag_name == "DD") {
+ ancestor_label_source = FormFieldData::LabelSource::DD_TAG;
inferred_label = InferLabelFromDefinitionList(element);
} else if (tag_name == "LI") {
+ ancestor_label_source = FormFieldData::LabelSource::LI_TAG;
inferred_label = InferLabelFromListItem(element);
} else if (tag_name == "FIELDSET") {
break;
}
- if (IsLabelValid(inferred_label, stop_words))
- return inferred_label;
+ if (IsLabelValid(inferred_label, stop_words)) {
+ *label_source = ancestor_label_source;
+ *label = std::move(inferred_label);
+ return true;
+ }
}
// 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))
- return inferred_label;
- return base::string16();
+ if (IsLabelValid(inferred_label, stop_words)) {
+ *label_source = FormFieldData::LabelSource::VALUE;
+ *label = std::move(inferred_label);
+ return true;
+ }
+ return false;
}
// Fills |option_strings| with the values of the <option> elements present in
@@ -807,7 +849,8 @@ void ForEachMatchingFormFieldCommon(
(!element->HasAttribute(kValue) ||
element->GetAttribute(kValue) != element->Value()) &&
(!element->HasAttribute(kPlaceholder) ||
- element->GetAttribute(kPlaceholder) != element->Value()))
+ base::i18n::ToLower(element->GetAttribute(kPlaceholder).Utf16()) !=
+ base::i18n::ToLower(element->Value().Utf16())))
continue;
DCHECK(!g_prevent_layout || !(filters & FILTER_NON_FOCUSABLE_ELEMENTS))
@@ -1122,8 +1165,9 @@ bool FormOrFieldsetsToFormData(
const WebFormControlElement& control_element = control_elements[i];
if (form_fields[field_idx]->label.empty()) {
- form_fields[field_idx]->label = InferLabelForElement(control_element,
- stop_words);
+ InferLabelForElement(control_element, stop_words,
+ &(form_fields[field_idx]->label),
+ &(form_fields[field_idx]->label_source));
}
TruncateString(&form_fields[field_idx]->label, kMaxDataLength);
@@ -1149,7 +1193,7 @@ bool UnownedFormElementsAndFieldSetsToFormData(
FormData* form,
FormFieldData* field) {
form->origin = GetCanonicalOriginForDocument(document);
- if (document.GetFrame()) {
+ if (document.GetFrame() && document.GetFrame()->Top()) {
form->main_frame_origin = document.GetFrame()->Top()->GetSecurityOrigin();
} else {
form->main_frame_origin = url::Origin();
@@ -1836,10 +1880,11 @@ base::string16 FindChildTextWithIgnoreListForTesting(
return FindChildTextWithIgnoreList(node, divs_to_skip);
}
-base::string16 InferLabelForElementForTesting(
- const WebFormControlElement& element,
- const std::vector<base::char16>& stop_words) {
- return InferLabelForElement(element, stop_words);
+bool InferLabelForElementForTesting(const WebFormControlElement& element,
+ const std::vector<base::char16>& stop_words,
+ base::string16* label,
+ FormFieldData::LabelSource* label_source) {
+ return InferLabelForElement(element, stop_words, label, label_source);
}
} // namespace form_util
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util.h b/chromium/components/autofill/content/renderer/form_autofill_util.h
index ed772f55195..3699b267eae 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util.h
+++ b/chromium/components/autofill/content/renderer/form_autofill_util.h
@@ -283,9 +283,10 @@ base::string16 FindChildText(const blink::WebNode& node);
base::string16 FindChildTextWithIgnoreListForTesting(
const blink::WebNode& node,
const std::set<blink::WebNode>& divs_to_skip);
-base::string16 InferLabelForElementForTesting(
- const blink::WebFormControlElement& element,
- const std::vector<base::char16>& stop_words);
+bool InferLabelForElementForTesting(const blink::WebFormControlElement& element,
+ const std::vector<base::char16>& stop_words,
+ base::string16* label,
+ FormFieldData::LabelSource* label_source);
} // namespace form_util
} // namespace autofill
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 44dffc4bd13..e75eb6899b6 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc
+++ b/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -17,6 +17,7 @@
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebSelectElement.h"
+using autofill::FormFieldData;
using blink::WebDocument;
using blink::WebElement;
using blink::WebFormControlElement;
@@ -27,6 +28,12 @@ using blink::WebSelectElement;
using blink::WebString;
using blink::WebVector;
+struct AutofillFieldLabelSourceCase {
+ const char* description;
+ const char* html;
+ const FormFieldData::LabelSource label_source;
+};
+
struct AutofillFieldUtilCase {
const char* description;
const char* html;
@@ -199,8 +206,59 @@ TEST_F(FormAutofillUtilsTest, InferLabelForElementTest) {
target.ToConst<WebFormControlElement>();
ASSERT_FALSE(form_target.IsNull());
- EXPECT_EQ(base::UTF8ToUTF16(test_case.expected_label),
- autofill::form_util::InferLabelForElementForTesting(form_target,
- stop_words));
+ FormFieldData::LabelSource label_source =
+ FormFieldData::LabelSource::UNKNOWN;
+ base::string16 label;
+ autofill::form_util::InferLabelForElementForTesting(form_target, stop_words,
+ &label, &label_source);
+ EXPECT_EQ(base::UTF8ToUTF16(test_case.expected_label), label);
+ }
+}
+
+TEST_F(FormAutofillUtilsTest, InferLabelSourceTest) {
+ const char kLabelSourceExpectedLabel[] = "label";
+ static const AutofillFieldLabelSourceCase test_cases[] = {
+ {"DIV_TABLE",
+ "<div><div>label</div><div><input id='target'/></div></div>",
+ FormFieldData::LabelSource::DIV_TABLE},
+ {"LABEL_TAG", "<label>label</label><input id='target'/>",
+ FormFieldData::LabelSource::LABEL_TAG},
+ {"COMBINED", "<b>l</b><strong>a</strong>bel<input id='target'/>",
+ FormFieldData::LabelSource::COMBINED},
+ {"P_TAG", "<p><b>l</b><strong>a</strong>bel</p><input id='target'/>",
+ FormFieldData::LabelSource::P_TAG},
+ {"PLACE_HOLDER", "<input id='target' placeholder='label'/>",
+ FormFieldData::LabelSource::PLACE_HOLDER},
+ {"VALUE", "<input id='target' value='label'/>",
+ FormFieldData::LabelSource::VALUE},
+ {"LI_TAG", "<li>label<div><input id='target'/></div></li>",
+ FormFieldData::LabelSource::LI_TAG},
+ {"TD_TAG",
+ "<table><tr><td>label</td><td><input id='target'/></td></tr></table>",
+ FormFieldData::LabelSource::TD_TAG},
+ {"DD_TAG", "<dl><dt>label</dt><dd><input id='target'></dd></dl>",
+ FormFieldData::LabelSource::DD_TAG},
+ };
+ std::vector<base::char16> stop_words;
+ stop_words.push_back(static_cast<base::char16>('-'));
+
+ for (auto test_case : test_cases) {
+ SCOPED_TRACE(test_case.description);
+ LoadHTML(test_case.html);
+ WebLocalFrame* web_frame = GetMainFrame();
+ ASSERT_NE(nullptr, web_frame);
+ WebElement target = web_frame->GetDocument().GetElementById("target");
+ ASSERT_FALSE(target.IsNull());
+ const WebFormControlElement form_target =
+ target.ToConst<WebFormControlElement>();
+ ASSERT_FALSE(form_target.IsNull());
+
+ FormFieldData::LabelSource label_source =
+ FormFieldData::LabelSource::UNKNOWN;
+ base::string16 label;
+ EXPECT_TRUE(autofill::form_util::InferLabelForElementForTesting(
+ form_target, stop_words, &label, &label_source));
+ EXPECT_EQ(base::UTF8ToUTF16(kLabelSourceExpectedLabel), label);
+ EXPECT_EQ(test_case.label_source, label_source);
}
}
diff --git a/chromium/components/autofill/content/renderer/form_classifier.h b/chromium/components/autofill/content/renderer/form_classifier.h
index 2ce96c3c3f2..919360284e0 100644
--- a/chromium/components/autofill/content/renderer/form_classifier.h
+++ b/chromium/components/autofill/content/renderer/form_classifier.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_CLASSIFIER_H_
+#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_CLASSIFIER_H_
+
#include "third_party/WebKit/public/web/WebFormElement.h"
namespace autofill {
@@ -12,3 +15,5 @@ namespace autofill {
bool ClassifyFormAndFindGenerationField(const blink::WebFormElement& form,
base::string16* generation_field);
}
+
+#endif // COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_CLASSIFIER_H_
diff --git a/chromium/components/autofill/content/renderer/form_tracker.cc b/chromium/components/autofill/content/renderer/form_tracker.cc
index 97d2e2ae46d..aa4214305a3 100644
--- a/chromium/components/autofill/content/renderer/form_tracker.cc
+++ b/chromium/components/autofill/content/renderer/form_tracker.cc
@@ -11,8 +11,8 @@
#include "third_party/WebKit/public/web/WebInputElement.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
-#include "third_party/WebKit/public/web/modules/password_manager/WebFormElementObserver.h"
-#include "third_party/WebKit/public/web/modules/password_manager/WebFormElementObserverCallback.h"
+#include "third_party/WebKit/public/web/modules/autofill/WebFormElementObserver.h"
+#include "third_party/WebKit/public/web/modules/autofill/WebFormElementObserverCallback.h"
#include "ui/base/page_transition_types.h"
using blink::WebDocumentLoader;
@@ -78,7 +78,8 @@ void FormTracker::TextFieldDidChange(const WebFormControlElement& element) {
// that pastes aren't necessarily user gestures because Blink's conception of
// user gestures is centered around creating new windows/tabs.
if (user_gesture_required_ &&
- !blink::WebUserGestureIndicator::IsProcessingUserGesture() &&
+ !blink::WebUserGestureIndicator::IsProcessingUserGesture(
+ render_frame()->GetWebFrame()) &&
!render_frame()->IsPasting())
return;
@@ -151,11 +152,16 @@ void FormTracker::DidStartProvisionalLoad(WebDocumentLoader* document_loader) {
if (!navigation_state)
return;
- ui::PageTransition type = navigation_state->GetTransitionType();
- if (ui::PageTransitionIsWebTriggerable(type) &&
- ui::PageTransitionIsNewNavigation(type) &&
- !blink::WebUserGestureIndicator::IsProcessingUserGesture(
- navigated_frame)) {
+ // We are interested only in content initiated navigations. Explicit browser
+ // initiated navigations (e.g. via omnibox) are discarded here. Similarly
+ // PlzNavigate navigations originating from the browser are discarded because
+ // they were already processed as a content initiated one
+ // (i.e. DidStartProvisionalLoad is called twice in this case). The check for
+ // kWebNavigationTypeLinkClicked is reliable only for content initiated
+ // navigations.
+ if (navigation_state->IsContentInitiated() &&
+ document_loader->GetNavigationType() !=
+ blink::kWebNavigationTypeLinkClicked) {
FireProbablyFormSubmitted();
}
}
diff --git a/chromium/components/autofill/content/renderer/html_based_username_detector.h b/chromium/components/autofill/content/renderer/html_based_username_detector.h
index 4f589ffe2af..cb9e4cd843b 100644
--- a/chromium/components/autofill/content/renderer/html_based_username_detector.h
+++ b/chromium/components/autofill/content/renderer/html_based_username_detector.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_H_
+#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_H_
+
#include <map>
#include "components/autofill/core/common/password_form.h"
@@ -34,3 +37,5 @@ bool GetUsernameFieldBasedOnHtmlAttributes(
UsernameDetectorCache* username_detector_cache);
} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_H_
diff --git a/chromium/components/autofill/content/renderer/html_based_username_detector_vocabulary.h b/chromium/components/autofill/content/renderer/html_based_username_detector_vocabulary.h
index 8164fa201fe..6013e3f217e 100644
--- a/chromium/components/autofill/content/renderer/html_based_username_detector_vocabulary.h
+++ b/chromium/components/autofill/content/renderer/html_based_username_detector_vocabulary.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_VOCABULARY_H_
+#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_VOCABULARY_H_
+
namespace autofill {
// Words that certainly point to a non-username field.
@@ -37,3 +40,5 @@ extern const char* const kWeakWords[];
extern const int kWeakWordsSize;
} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_VOCABULARY_H_
diff --git a/chromium/components/autofill/content/renderer/page_passwords_analyser.cc b/chromium/components/autofill/content/renderer/page_passwords_analyser.cc
index f45a6caa4ad..0f32b132b7d 100644
--- a/chromium/components/autofill/content/renderer/page_passwords_analyser.cc
+++ b/chromium/components/autofill/content/renderer/page_passwords_analyser.cc
@@ -320,7 +320,7 @@ void GuessAutocompleteAttributesForPasswordFields(
switch (password_count) {
case 3:
(*autocomplete_suggestions)[password_inputs[0]] = "current-password";
- // Fall-through here to match the last two password fields.
+ FALLTHROUGH; // To match the last two password fields.
case 2:
(*autocomplete_suggestions)[password_inputs[password_count - 2]] =
"new-password";
diff --git a/chromium/components/autofill/content/renderer/password_autofill_agent.cc b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
index daa25e605b0..7469b2cbcbd 100644
--- a/chromium/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
@@ -176,24 +176,21 @@ bool FindFormInputElement(
continue;
}
- // Check for a non-unique match.
if (found_input) {
- // For change password form keep only the first password field entry.
- if (does_password_field_has_ambigous_or_empty_name) {
+ if (ambiguous_or_empty_names) {
+ // In case of ambigous or empty names, there might be multiple
+ // appropriate inputs. Check if the current input is better than
+ // previously found one.
if (!form_util::IsWebElementVisible((*result)[field_name])) {
// If a previously chosen field was invisible then take the current
// one.
(*result)[field_name] = input_element;
}
- continue;
}
-
- found_input = false;
- break;
+ } else {
+ (*result)[field_name] = input_element;
+ found_input = true;
}
-
- (*result)[field_name] = input_element;
- found_input = true;
}
// A required element was not found. This is not the right form.
@@ -1051,7 +1048,7 @@ void PasswordAutofillAgent::FireSubmissionIfFormDisappear(
}
provisionally_saved_form_.SetSubmissionIndicatorEvent(event);
- GetPasswordManagerDriver()->InPageNavigation(password_form);
+ GetPasswordManagerDriver()->SameDocumentNavigation(password_form);
provisionally_saved_form_.Reset();
}
@@ -1105,6 +1102,11 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
// page will be ignored.
return;
}
+ if (IsGaiaWithSkipSavePasswordForm(form)) {
+ // Bail if this is a GAIA enable Chrome sync flow, so that page will be
+ // ignored.
+ return;
+ }
if (only_visible) {
bool is_form_visible = form_util::AreFormContentsVisible(form);
if (logger) {
@@ -1229,7 +1231,7 @@ void PasswordAutofillAgent::OnFrameDetached() {
DCHECK(FrameCanAccessPasswordManager());
provisionally_saved_form_.SetSubmissionIndicatorEvent(
PasswordForm::SubmissionIndicatorEvent::FRAME_DETACHED);
- GetPasswordManagerDriver()->InPageNavigation(
+ GetPasswordManagerDriver()->SameDocumentNavigation(
provisionally_saved_form_.password_form());
}
FrameClosing();
@@ -1720,7 +1722,7 @@ void PasswordAutofillAgent::ProvisionallySavePassword(
provisionally_saved_form_.Set(std::move(password_form), form, element);
if (base::FeatureList::IsEnabled(
- password_manager::features::kEnableManualSaving)) {
+ password_manager::features::kManualSaving)) {
if (has_password) {
GetPasswordManagerDriver()->ShowManualFallbackForSaving(
provisionally_saved_form_.password_form());
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 9b14427e3c7..fc3bec3769c 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -27,6 +27,7 @@
#include "components/autofill/core/common/password_form_field_prediction_map.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "google_apis/gaia/gaia_urls.h"
+#include "net/base/url_util.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebDocument.h"
@@ -660,7 +661,7 @@ bool GetPasswordForm(
// Call HTML based username detector, only if corresponding flag is enabled.
if (base::FeatureList::IsEnabled(
- password_manager::features::kEnableHtmlBasedUsernameDetector)) {
+ password_manager::features::kHtmlBasedUsernameDetector)) {
if (username_element.IsNull()) {
GetUsernameFieldBasedOnHtmlAttributes(
form.control_elements, possible_usernames, password_form->form_data,
@@ -865,6 +866,18 @@ bool IsGaiaReauthenticationForm(const blink::WebFormElement& form) {
return has_rart_field && has_continue_field;
}
+bool IsGaiaWithSkipSavePasswordForm(const blink::WebFormElement& form) {
+ GURL url(form.GetDocument().Url());
+ if (url.GetOrigin() != GaiaUrls::GetInstance()->gaia_url().GetOrigin()) {
+ return false;
+ }
+
+ std::string should_skip_password;
+ if (!net::GetValueForKeyInQuery(url, "ssp", &should_skip_password))
+ return false;
+ return should_skip_password == "1";
+}
+
std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
const WebFormElement& web_form,
const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
diff --git a/chromium/components/autofill/content/renderer/password_form_conversion_utils.h b/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
index d310b309152..61f6e89bafc 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
@@ -48,6 +48,9 @@ re2::RE2* CreateMatcher(void* instance, const char* pattern);
// Tests whether the given form is a GAIA reauthentication form.
bool IsGaiaReauthenticationForm(const blink::WebFormElement& form);
+// Tests whether the given form is a GAIA form with a skip password argument.
+bool IsGaiaWithSkipSavePasswordForm(const blink::WebFormElement& form);
+
typedef std::map<
const blink::WebFormControlElement,
std::pair<std::unique_ptr<base::string16>, FieldPropertiesMask>>
diff --git a/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc b/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
index 961cb498ffa..9565ba4ebc9 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
@@ -20,6 +20,7 @@
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "content/public/test/render_view_test.h"
+#include "google_apis/gaia/gaia_urls.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebVector.h"
@@ -350,7 +351,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
HTMLDetector_DeveloperGroupAttributes) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- password_manager::features::kEnableHtmlBasedUsernameDetector);
+ password_manager::features::kHtmlBasedUsernameDetector);
// Each test case consists of a set of parameters to be plugged into the
// PasswordFormBuilder below, plus the corresponding expectations.
@@ -472,7 +473,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
TEST_F(MAYBE_PasswordFormConversionUtilsTest, HTMLDetector_SeveralDetections) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- password_manager::features::kEnableHtmlBasedUsernameDetector);
+ password_manager::features::kHtmlBasedUsernameDetector);
// If word matches in more than 2 fields, we don't match on it.
// We search for match with another word.
@@ -506,7 +507,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
HTMLDetector_UserGroupAttributes) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- password_manager::features::kEnableHtmlBasedUsernameDetector);
+ password_manager::features::kHtmlBasedUsernameDetector);
// Each test case consists of a set of parameters to be plugged into the
// PasswordFormBuilder below, plus the corresponding expectations.
@@ -626,7 +627,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
TEST_F(MAYBE_PasswordFormConversionUtilsTest, HTMLDetectorCache) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- password_manager::features::kEnableHtmlBasedUsernameDetector);
+ password_manager::features::kHtmlBasedUsernameDetector);
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddTextField("unknown", "12345", nullptr);
@@ -2030,7 +2031,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
WebInputElement* input_element = ToWebInputElement(&control_elements[3]);
const base::string16 element_value = input_element->Value().Utf16();
user_input[control_elements[3]] =
- std::make_pair(base::MakeUnique<base::string16>(element_value),
+ std::make_pair(std::make_unique<base::string16>(element_value),
FieldPropertiesFlags::USER_TYPED);
std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
@@ -2222,6 +2223,40 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, IsGaiaReauthFormIgnored) {
}
}
+TEST_F(MAYBE_PasswordFormConversionUtilsTest, IsGaiaWithSkipSavePasswordForm) {
+ struct TestCase {
+ const char* origin;
+ bool expected_form_has_skip_save_password;
+ } cases[] = {
+ // A common password form is parsed successfully.
+ {"https://example.com", false},
+ // A common GAIA sign-in page, with no skip save password argument.
+ {"https://accounts.google.com", false},
+ // A common GAIA sign-in page, with "0" skip save password argument.
+ {"https://accounts.google.com/?ssp=0", false},
+ // A common GAIA sign-in page, with skip save password argument.
+ {"https://accounts.google.com/?ssp=1", true},
+ // The Gaia page that is used to start a Chrome sign-in flow when Desktop
+ // Identity Consistency is enable.
+ {GaiaUrls::GetInstance()->signin_chrome_sync_dice().spec().c_str(), true},
+ };
+
+ for (TestCase& test_case : cases) {
+ SCOPED_TRACE(testing::Message("origin=")
+ << test_case.origin
+ << ", expected_form_has_skip_save_password="
+ << test_case.expected_form_has_skip_save_password);
+ std::unique_ptr<PasswordFormBuilder> builder(new PasswordFormBuilder(""));
+ builder->AddTextField("username", "", nullptr);
+ builder->AddPasswordField("password", "", nullptr);
+ std::string html = builder->ProduceHTML();
+ WebFormElement form;
+ LoadWebFormFromHTML(html, &form, test_case.origin);
+ EXPECT_EQ(test_case.expected_form_has_skip_save_password,
+ IsGaiaWithSkipSavePasswordForm(form));
+ }
+}
+
TEST_F(MAYBE_PasswordFormConversionUtilsTest,
IdentifyingFieldsWithoutNameOrIdAttributes) {
const char* kEmpty = nullptr;
@@ -2414,7 +2449,7 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, ResetPasswordForm) {
// without any text fields.
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- password_manager::features::kEnableHtmlBasedUsernameDetector);
+ password_manager::features::kHtmlBasedUsernameDetector);
PasswordFormBuilder builder(kTestFormActionURL);
builder.AddPasswordField("password", "secret", nullptr);
builder.AddSubmitButton("submit");
diff --git a/chromium/components/autofill/content/renderer/password_generation_agent.cc b/chromium/components/autofill/content/renderer/password_generation_agent.cc
index 8fd4082a810..6446e2f170f 100644
--- a/chromium/components/autofill/content/renderer/password_generation_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_generation_agent.cc
@@ -24,7 +24,7 @@
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "google_apis/gaia/gaia_urls.h"
-#include "third_party/WebKit/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/WebKit/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebDocument.h"
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 887c0cf0207..c7b0b3a4324 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
@@ -55,7 +55,8 @@ class FakeContentPasswordManagerDriver : public mojom::PasswordManagerDriver {
void HideManualFallbackForSaving() override {}
- void InPageNavigation(const autofill::PasswordForm& password_form) override {}
+ void SameDocumentNavigation(
+ const autofill::PasswordForm& password_form) override {}
void PresaveGeneratedPassword(
const autofill::PasswordForm& password_form) override {}
diff --git a/chromium/components/autofill/core/browser/BUILD.gn b/chromium/components/autofill/core/browser/BUILD.gn
index 490257aef3f..cfdd2950579 100644
--- a/chromium/components/autofill/core/browser/BUILD.gn
+++ b/chromium/components/autofill/core/browser/BUILD.gn
@@ -236,7 +236,6 @@ static_library("browser") {
"//components/pref_registry",
"//components/prefs",
"//components/security_state/core",
- "//components/signin/core/browser",
"//components/strings",
"//components/sync",
"//components/variations/net",
@@ -244,6 +243,7 @@ static_library("browser") {
"//components/webdata/common",
"//google_apis",
"//net",
+ "//services/identity/public/cpp",
"//services/metrics/public/cpp:metrics_cpp",
"//services/metrics/public/cpp:ukm_builders",
"//sql",
@@ -326,10 +326,10 @@ static_library("test_support") {
"//components/os_crypt:test_support",
"//components/pref_registry",
"//components/prefs:test_support",
- "//components/signin/core/browser",
"//components/ukm",
"//components/ukm:test_support",
"//google_apis:test_support",
+ "//services/identity/public/cpp:test_support",
"//skia",
"//testing/gtest",
"//third_party/libaddressinput:util",
@@ -447,8 +447,6 @@ source_set("unit_tests") {
"//components/prefs:test_support",
"//components/resources",
"//components/security_state/core",
- "//components/signin/core/browser",
- "//components/signin/core/browser:test_support",
"//components/strings",
"//components/sync",
"//components/sync:test_support_driver",
@@ -462,6 +460,7 @@ source_set("unit_tests") {
"//google_apis",
"//google_apis:test_support",
"//net:test_support",
+ "//services/identity/public/cpp:test_support",
"//services/metrics/public/cpp:ukm_builders",
"//sql",
"//testing/gmock",
diff --git a/chromium/components/autofill/core/browser/DEPS b/chromium/components/autofill/core/browser/DEPS
index ebd3a7e60b6..e50f9ccc9b5 100644
--- a/chromium/components/autofill/core/browser/DEPS
+++ b/chromium/components/autofill/core/browser/DEPS
@@ -6,7 +6,6 @@ include_rules = [
"+components/metrics",
"+components/policy",
"+components/security_state",
- "+components/signin/core/browser",
"+components/sync",
"+components/variations",
"+components/version_info",
@@ -16,12 +15,12 @@ include_rules = [
"+google_apis/gaia",
"+google_apis/google_api_keys.h",
"+net",
+ "+services/identity/public",
"+services/metrics/public",
"+sql",
"+third_party/fips181",
"+third_party/libaddressinput", # For address i18n.
"+third_party/libphonenumber", # For phone number i18n.
- "+third_party/libxml",
"+third_party/re2",
"+ui/base",
"+ui/gfx",
diff --git a/chromium/components/autofill/core/browser/autocomplete_history_manager.cc b/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
index 8fbe4e467ec..1a4f54a622e 100644
--- a/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
+++ b/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
@@ -61,6 +61,7 @@ void AutocompleteHistoryManager::OnGetAutocompleteSuggestions(
query_id_ = query_id;
if (!autofill_client_->IsAutocompleteEnabled() ||
+ !autofill_client_->IsAutofillSupported() ||
form_control_type == "textarea" ||
IsInAutofillSuggestionsDisabledExperiment()) {
SendSuggestions(nullptr);
diff --git a/chromium/components/autofill/core/browser/autofill_client.h b/chromium/components/autofill/core/browser/autofill_client.h
index c44c5ec4fde..5dc4056f6fd 100644
--- a/chromium/components/autofill/core/browser/autofill_client.h
+++ b/chromium/components/autofill/core/browser/autofill_client.h
@@ -18,7 +18,6 @@
#include "ui/base/window_open_disposition.h"
#include "url/gurl.h"
-class IdentityProvider;
class PrefService;
namespace content {
@@ -29,6 +28,10 @@ namespace gfx {
class RectF;
}
+namespace identity {
+class IdentityManager;
+}
+
namespace syncer {
class SyncService;
}
@@ -102,8 +105,8 @@ class AutofillClient : public RiskDataLoader {
// Gets the sync service associated with the client.
virtual syncer::SyncService* GetSyncService() = 0;
- // Gets the IdentityProvider associated with the client (for OAuth2).
- virtual IdentityProvider* GetIdentityProvider() = 0;
+ // Gets the IdentityManager associated with the client.
+ virtual identity::IdentityManager* GetIdentityManager() = 0;
// Gets the UKM service associated with this client (for metrics).
virtual ukm::UkmRecorder* GetUkmRecorder() = 0;
diff --git a/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc b/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc
index 2de1eae75f4..d302321d73b 100644
--- a/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc
+++ b/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc
@@ -72,11 +72,6 @@ bool AutofillCreditCardFillingInfoBarDelegateMobile::Cancel() {
return true;
}
-infobars::InfoBarDelegate::Type
-AutofillCreditCardFillingInfoBarDelegateMobile::GetInfoBarType() const {
- return PAGE_ACTION_TYPE;
-}
-
infobars::InfoBarDelegate::InfoBarIdentifier
AutofillCreditCardFillingInfoBarDelegateMobile::GetIdentifier() const {
return AUTOFILL_CREDIT_CARD_FILLING_INFOBAR_DELEGATE_ANDROID;
diff --git a/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.h b/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.h
index 04e030694d5..e73333928d5 100644
--- a/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.h
+++ b/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.h
@@ -41,7 +41,6 @@ class AutofillCreditCardFillingInfoBarDelegateMobile
private:
// ConfirmInfoBarDelegate (continued):
- Type GetInfoBarType() const override;
infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
base::string16 GetButtonLabel(InfoBarButton button) const override;
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.cc b/chromium/components/autofill/core/browser/autofill_experiments.cc
index 07f9ab25513..15ceb84c27c 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.cc
+++ b/chromium/components/autofill/core/browser/autofill_experiments.cc
@@ -26,6 +26,8 @@ namespace autofill {
const base::Feature kAutofillAlwaysFillAddresses{
"AlwaysFillAddresses", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kAutofillAutoDismissableUpstreamBubble{
+ "AutofillAutoDismissableUpstreamBubble", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillCreateDataForTest{
"AutofillCreateDataForTest", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillCreditCardAssist{
@@ -46,9 +48,8 @@ const base::Feature kAutofillDeleteDisusedCreditCards{
"AutofillDeleteDisusedCreditCards", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillExpandedPopupViews{
"AutofillExpandedPopupViews", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillOfferLocalSaveIfServerCardManuallyEntered{
- "AutofillOfferLocalSaveIfServerCardManuallyEntered",
- base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillPreferServerNamePredictions{
+ "AutofillPreferServerNamePredictions", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillRationalizeFieldTypePredictions{
"AutofillRationalizeFieldTypePredictions",
base::FEATURE_ENABLED_BY_DEFAULT};
@@ -58,9 +59,6 @@ const base::Feature kAutofillSuppressDisusedAddresses{
"AutofillSuppressDisusedAddresses", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kAutofillSuppressDisusedCreditCards{
"AutofillSuppressDisusedCreditCards", base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kAutofillToolkitViewsCreditCardDialogsMac{
- "AutofillToolkitViewsCreditCardDialogsMac",
- base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kAutofillUpstreamAllowAllEmailDomains{
"AutofillUpstreamAllowAllEmailDomains", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillUpstreamRequestCvcIfMissing{
@@ -84,7 +82,7 @@ const char kAutofillCreditCardLastUsedDateShowExpirationDateKey[] =
#if defined(OS_MACOSX)
const base::Feature kCreditCardAutofillTouchBar{
- "CreditCardAutofillTouchBar", base::FEATURE_DISABLED_BY_DEFAULT};
+ "CreditCardAutofillTouchBar", base::FEATURE_ENABLED_BY_DEFAULT};
#endif // defined(OS_MACOSX)
namespace {
@@ -125,6 +123,10 @@ bool IsAutofillCreditCardPopupLayoutExperimentEnabled() {
return base::FeatureList::IsEnabled(kAutofillCreditCardPopupLayout);
}
+bool IsAutofillAutoDismissableUpstreamBubbleExperimentEnabled() {
+ return base::FeatureList::IsEnabled(kAutofillAutoDismissableUpstreamBubble);
+}
+
bool IsAutofillCreditCardLastUsedDateDisplayExperimentEnabled() {
return base::FeatureList::IsEnabled(kAutofillCreditCardLastUsedDateDisplay);
}
@@ -273,11 +275,6 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
return !group_name.empty() && group_name != "Disabled";
}
-bool IsAutofillOfferLocalSaveIfServerCardManuallyEnteredExperimentEnabled() {
- return base::FeatureList::IsEnabled(
- kAutofillOfferLocalSaveIfServerCardManuallyEntered);
-}
-
bool IsAutofillSendBillingCustomerNumberExperimentEnabled() {
return base::FeatureList::IsEnabled(kAutofillSendBillingCustomerNumber);
}
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.h b/chromium/components/autofill/core/browser/autofill_experiments.h
index 4589881391d..b0f8c9892cf 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.h
+++ b/chromium/components/autofill/core/browser/autofill_experiments.h
@@ -26,6 +26,7 @@ namespace autofill {
struct Suggestion;
extern const base::Feature kAutofillAlwaysFillAddresses;
+extern const base::Feature kAutofillAutoDismissableUpstreamBubble;
extern const base::Feature kAutofillCreateDataForTest;
extern const base::Feature kAutofillCreditCardAssist;
extern const base::Feature kAutofillScanCardholderName;
@@ -36,12 +37,11 @@ extern const base::Feature kAutofillCreditCardLastUsedDateDisplay;
extern const base::Feature kAutofillDeleteDisusedAddresses;
extern const base::Feature kAutofillDeleteDisusedCreditCards;
extern const base::Feature kAutofillExpandedPopupViews;
-extern const base::Feature kAutofillOfferLocalSaveIfServerCardManuallyEntered;
+extern const base::Feature kAutofillPreferServerNamePredictions;
extern const base::Feature kAutofillRationalizeFieldTypePredictions;
extern const base::Feature kAutofillSendBillingCustomerNumber;
extern const base::Feature kAutofillSuppressDisusedAddresses;
extern const base::Feature kAutofillSuppressDisusedCreditCards;
-extern const base::Feature kAutofillToolkitViewsCreditCardDialogsMac;
extern const base::Feature kAutofillUpstreamAllowAllEmailDomains;
extern const base::Feature kAutofillUpstreamRequestCvcIfMissing;
extern const base::Feature kAutofillUpstreamSendDetectedValues;
@@ -83,6 +83,10 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
// enabled.
bool IsAutofillCreditCardPopupLayoutExperimentEnabled();
+// Returns whether the experiment to make the credit card Upstream bubble non
+// sticky is enabled.
+bool IsAutofillAutoDismissableUpstreamBubbleExperimentEnabled();
+
// Returns whether Autofill credit card last used date display experiment is
// enabled.
bool IsAutofillCreditCardLastUsedDateDisplayExperimentEnabled();
@@ -125,12 +129,6 @@ void ModifyAutofillCreditCardSuggestion(struct Suggestion* suggestion);
// layout.
unsigned int GetPopupMargin();
-// Returns whether the experiment is enabled where if Chrome Autofill has a
-// server card synced down from Payments but the user manually enters its card
-// number into a checkout form anyway, the option to locally save the card is
-// offered.
-bool IsAutofillOfferLocalSaveIfServerCardManuallyEnteredExperimentEnabled();
-
// Returns whether the experiment is enabled where Chrome reads billing customer
// number from priority preference and sends it along with UploadCardRequest and
// FullCardRequest.
diff --git a/chromium/components/autofill/core/browser/autofill_field.cc b/chromium/components/autofill/core/browser/autofill_field.cc
index 0e86da83827..40b92446559 100644
--- a/chromium/components/autofill/core/browser/autofill_field.cc
+++ b/chromium/components/autofill/core/browser/autofill_field.cc
@@ -6,7 +6,9 @@
#include <stdint.h>
+#include "base/feature_list.h"
#include "base/strings/string_number_conversions.h"
+#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/proto/server.pb.h"
@@ -108,21 +110,29 @@ AutofillType AutofillField::Type() const {
}
if (overall_server_type_ != NO_SERVER_DATA) {
- // See http://crbug.com/429236 for background on why we might not always
- // believe the server.
- // TODO(http://crbug.com/589129) investigate how well the server is doing in
- // regard to credit card predictions.
- bool believe_server =
- !(overall_server_type_ == NAME_FULL &&
- heuristic_type_ == CREDIT_CARD_NAME_FULL) &&
- !(overall_server_type_ == CREDIT_CARD_NAME_FULL &&
- heuristic_type_ == NAME_FULL) &&
- !(overall_server_type_ == NAME_FIRST &&
- heuristic_type_ == CREDIT_CARD_NAME_FIRST) &&
- !(overall_server_type_ == NAME_LAST &&
- heuristic_type_ == CREDIT_CARD_NAME_LAST) &&
- // CVC is sometimes type="password", which tricks the server.
- // See http://crbug.com/469007
+ // Sometimes the server and heuristics disagree on whether a name field
+ // should be associated with an address or a credit card. There was a
+ // decision to prefer the heuristics in these cases, but it looks like
+ // it might be better to fix this server-side.
+ // See http://crbug.com/429236 for background.
+ bool believe_server;
+ if (base::FeatureList::IsEnabled(kAutofillPreferServerNamePredictions)) {
+ believe_server = true;
+ } else {
+ believe_server = !(overall_server_type_ == NAME_FULL &&
+ heuristic_type_ == CREDIT_CARD_NAME_FULL) &&
+ !(overall_server_type_ == CREDIT_CARD_NAME_FULL &&
+ heuristic_type_ == NAME_FULL) &&
+ !(overall_server_type_ == NAME_FIRST &&
+ heuristic_type_ == CREDIT_CARD_NAME_FIRST) &&
+ !(overall_server_type_ == NAME_LAST &&
+ heuristic_type_ == CREDIT_CARD_NAME_LAST);
+ }
+
+ // Either way, retain a preference for the the CVC heuristic over the
+ // server's password predictions (http://crbug.com/469007)
+ believe_server =
+ believe_server &&
!(AutofillType(overall_server_type_).group() == PASSWORD_FIELD &&
heuristic_type_ == CREDIT_CARD_VERIFICATION_CODE);
if (believe_server)
diff --git a/chromium/components/autofill/core/browser/autofill_manager.cc b/chromium/components/autofill/core/browser/autofill_manager.cc
index 50180a1c2c9..1b129ef4724 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager.cc
@@ -69,7 +69,6 @@
#include "components/prefs/pref_service.h"
#include "components/security_state/core/security_state.h"
#include "components/strings/grit/components_strings.h"
-#include "google_apis/gaia/identity_provider.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
@@ -96,9 +95,9 @@ const size_t kMaxFormCacheSize = 100;
// Precondition: |form_structure| and |form| should correspond to the same
// logical form. Returns true if any field in the given |section| within |form|
// is auto-filled.
-bool SectionIsAutofilled(const FormStructure& form_structure,
- const FormData& form,
- const std::string& section) {
+bool SectionHasAutofilledField(const FormStructure& form_structure,
+ const FormData& form,
+ const std::string& section) {
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() == section &&
@@ -606,14 +605,14 @@ void AutofillManager::OnQueryFormFieldAutofillImpl(
POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE;
suggestions.assign(1, warning_suggestion);
} else {
- bool section_is_autofilled = SectionIsAutofilled(
+ bool section_has_autofilled_field = SectionHasAutofilledField(
*form_structure, form, autofill_field->section());
- if (section_is_autofilled) {
- // If the relevant section is auto-filled and the renderer is querying
- // for suggestions, then the user is editing the value of a field.
- // In this case, mimic autocomplete: don't display labels or icons,
- // as that information is redundant. Moreover, filter out duplicate
- // suggestions.
+ if (section_has_autofilled_field) {
+ // If the relevant section has auto-filled fields and the renderer is
+ // querying for suggestions, then for some fields, the user is editing
+ // the value of a field. In this case, mimic autocomplete: don't
+ // display labels or icons, as that information is redundant.
+ // Moreover, filter out duplicate suggestions.
std::set<base::string16> seen_values;
for (auto iter = suggestions.begin(); iter != suggestions.end();) {
if (!seen_values.insert(iter->value).second) {
@@ -631,7 +630,8 @@ void AutofillManager::OnQueryFormFieldAutofillImpl(
// suggestions available.
// TODO(mathp): Differentiate between number of suggestions available
// (current metric) and number shown to the user.
- if (!has_logged_address_suggestions_count_ && !section_is_autofilled) {
+ if (!has_logged_address_suggestions_count_ &&
+ !section_has_autofilled_field) {
AutofillMetrics::LogAddressSuggestionsCount(suggestions.size());
has_logged_address_suggestions_count_ = true;
}
@@ -690,17 +690,12 @@ bool AutofillManager::WillFillCreditCardNumber(const FormData& form,
if (autofill_field->Type().GetStorableType() == CREDIT_CARD_NUMBER)
return true;
- // If the relevant section is already autofilled, the new fill operation will
- // only fill |autofill_field|.
- if (SectionIsAutofilled(*form_structure, form, autofill_field->section()))
- return false;
-
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].value.empty() && !form.fields[i].is_autofilled) {
return true;
}
}
@@ -1178,7 +1173,7 @@ AutofillManager::AutofillManager(
payments_client_(std::make_unique<payments::PaymentsClient>(
driver->GetURLRequestContext(),
client->GetPrefs(),
- client->GetIdentityProvider(),
+ client->GetIdentityManager(),
/*unmask_delegate=*/this,
// save_delegate starts out as nullptr and is set up by the
// CreditCardSaveManager owned by form_data_importer_.
@@ -1325,25 +1320,6 @@ void AutofillManager::FillOrPreviewDataModelForm(
form_structure->RationalizePhoneNumbersInSection(autofill_field->section());
}
- // If the relevant section is auto-filled, we should fill |field| but not the
- // rest of the form.
- if (SectionIsAutofilled(*form_structure, form, autofill_field->section())) {
- for (FormFieldData& iter : result.fields) {
- if (iter.SameFieldAs(field)) {
- FillFieldWithValue(autofill_field, data_model, &iter,
- /*should_notify=*/!is_credit_card, cvc);
- break;
- }
- }
-
- // Note that this may invalidate |data_model|.
- if (action == AutofillDriver::FORM_DATA_ACTION_FILL)
- personal_data_->RecordUseOf(data_model);
-
- driver()->SendFormDataToRenderer(query_id, action, result);
- return;
- }
-
DCHECK_EQ(form_structure->field_count(), form.fields.size());
for (size_t i = 0; i < form_structure->field_count(); ++i) {
@@ -1360,6 +1336,17 @@ void AutofillManager::FillOrPreviewDataModelForm(
AutofillField* cached_field = form_structure->field(i);
FieldTypeGroup field_group_type = cached_field->Type().group();
+ // Don't fill hidden fields.
+ if (!cached_field->is_focusable ||
+ cached_field->role == FormFieldData::ROLE_ATTRIBUTE_PRESENTATION) {
+ continue;
+ }
+
+ // Don't fill previously autofilled fields.
+ if (result.fields[i].is_autofilled && !cached_field->SameFieldAs(field)) {
+ continue;
+ }
+
if (field_group_type == NO_GROUP)
continue;
@@ -1411,7 +1398,9 @@ std::unique_ptr<FormStructure> AutofillManager::ValidateSubmittedForm(
if (!FindCachedForm(form, &cached_submitted_form))
return std::unique_ptr<FormStructure>();
- submitted_form->UpdateFromCache(*cached_submitted_form, false);
+ submitted_form->RetrieveFromCache(*cached_submitted_form,
+ /* apply_is_autofilled */ false,
+ /* only_server_and_autofill_state */ false);
return submitted_form;
}
@@ -1513,9 +1502,11 @@ bool AutofillManager::UpdateCachedForm(const FormData& live_form,
if (!ParseForm(live_form, updated_form))
return false;
+ // We need to keep the server data.
if (cached_form)
- (*updated_form)->UpdateFromCache(*cached_form, true);
-
+ (*updated_form)
+ ->RetrieveFromCache(*cached_form, /* apply_is_autofilled */ true,
+ /* only_server_and_autofill_state */ true);
// Annotate the updated form with its predicted types.
driver()->SendAutofillTypePredictionsToRenderer({*updated_form});
diff --git a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
index c59970f7156..ccfdc65244e 100644
--- a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -1852,10 +1852,16 @@ TEST_F(AutofillManagerTest, WillFillCreditCardNumber) {
number_field->value.clear();
EXPECT_TRUE(WillFillCreditCardNumber(form, *name_field));
- // When part of the section is Autofilled, only fill the initiating field.
- month_field->is_autofilled = true;
+ // When the number is already autofilled, we won't fill it.
+ number_field->is_autofilled = true;
EXPECT_FALSE(WillFillCreditCardNumber(form, *name_field));
EXPECT_TRUE(WillFillCreditCardNumber(form, *number_field));
+
+ // If another field is filled, we would still fill other non-filled fields in
+ // the section.
+ number_field->is_autofilled = false;
+ name_field->is_autofilled = true;
+ EXPECT_TRUE(WillFillCreditCardNumber(form, *name_field));
}
// Test that we correctly log FIELD_WAS_AUTOFILLED event in UserHappiness.
@@ -2448,7 +2454,7 @@ TEST_F(AutofillManagerTest, FillCreditCardForm_ExpiredCard) {
}
// Test that non-focusable field is ignored while inferring boundaries between
-// sections: http://crbug.com/231160
+// sections, but not filled.
TEST_F(AutofillManagerTest, FillFormWithNonFocusableFields) {
// Create a form with both focusable and non-focusable fields.
FormData form;
@@ -2488,8 +2494,8 @@ TEST_F(AutofillManagerTest, FillFormWithNonFocusableFields) {
MakeFrontendID(std::string(), guid),
&response_page_id, &response_data);
- // The whole form should be filled as all the fields belong to the same
- // logical section.
+ // All the visible fields should be filled as all the fields belong to the
+ // same logical section.
ASSERT_EQ(6U, response_data.fields.size());
ExpectFilledField("First Name", "firstname", "Elvis", "text",
response_data.fields[0]);
@@ -2498,8 +2504,7 @@ TEST_F(AutofillManagerTest, FillFormWithNonFocusableFields) {
response_data.fields[2]);
ExpectFilledField("Phone Number", "phonenumber", "12345678901", "tel",
response_data.fields[3]);
- ExpectFilledField("", "email_", "theking@gmail.com", "text",
- response_data.fields[4]);
+ ExpectFilledField("", "email_", "", "text", response_data.fields[4]);
ExpectFilledField("Country", "country", "United States", "text",
response_data.fields[5]);
}
@@ -2761,8 +2766,12 @@ TEST_F(AutofillManagerTest, FillAutofilledForm) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
- // Mark one of the address fields as autofilled.
- form.fields[4].is_autofilled = true;
+ // Mark the address fields as autofilled.
+ for (std::vector<FormFieldData>::iterator iter = form.fields.begin();
+ iter != form.fields.end(); ++iter) {
+ iter->is_autofilled = true;
+ }
+
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
@@ -2814,10 +2823,55 @@ TEST_F(AutofillManagerTest, FillAutofilledForm) {
}
}
+// Test that we correctly fill a previously partly auto-filled form.
+TEST_F(AutofillManagerTest, FillPartlyAutofilledForm) {
+ // Set up our form data.
+ FormData form;
+ test::CreateTestAddressFormData(&form);
+ // Mark couple of the address fields as autofilled.
+ form.fields[3].is_autofilled = true;
+ form.fields[4].is_autofilled = true;
+ form.fields[5].is_autofilled = true;
+ form.fields[6].is_autofilled = true;
+ form.fields[10].is_autofilled = true;
+
+ CreateTestCreditCardFormData(&form, true, false);
+ std::vector<FormData> forms(1, form);
+ FormsSeen(forms);
+
+ // First fill the address data.
+ const char guid[] = "00000000-0000-0000-0000-000000000001";
+ int response_page_id = 0;
+ FormData response_data;
+ FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
+ MakeFrontendID(std::string(), guid),
+ &response_page_id, &response_data);
+ {
+ SCOPED_TRACE("Address");
+ ExpectFilledForm(response_page_id, response_data, kDefaultPageID, "Elvis",
+ "Aaron", "Presley", "", "", "", "", "38116",
+ "United States", "12345678901", "", "", "", "", "", true,
+ true, false);
+ }
+
+ // Now fill the credit card data.
+ const int kPageID2 = 2;
+ const char guid2[] = "00000000-0000-0000-0000-000000000004";
+ response_page_id = 0;
+ FillAutofillFormDataAndSaveResults(kPageID2, form, form.fields.back(),
+ MakeFrontendID(guid2, std::string()),
+ &response_page_id, &response_data);
+ {
+ SCOPED_TRACE("Credit card 1");
+ ExpectFilledCreditCardFormElvis(response_page_id, response_data, kPageID2,
+ true);
+ }
+}
+
// Test that we correctly fill a phone number split across multiple fields.
TEST_F(AutofillManagerTest, FillPhoneNumber) {
- // In one form, rely on the maxlength attribute to imply US phone number
- // parts. In the other form, rely on the autocompletetype attribute.
+ // 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;
form_with_us_number_max_length.name = ASCIIToUTF16("MyMaxlengthPhoneForm");
form_with_us_number_max_length.origin =
@@ -3555,7 +3609,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_HiddenFieldShouldNotCount) {
ASSERT_EQ(4U, response_data.fields.size());
EXPECT_EQ(ASCIIToUTF16("Charles Hardin Holley"),
response_data.fields[0].value);
- EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[1].value);
+ EXPECT_EQ(ASCIIToUTF16(""), response_data.fields[1].value);
EXPECT_EQ(base::string16(), response_data.fields[2].value);
EXPECT_EQ(ASCIIToUTF16("6505554567"), response_data.fields[3].value);
}
@@ -3767,6 +3821,79 @@ TEST_F(AutofillManagerTest, FormChangesAddField) {
false);
}
+// Test that we can still fill a form when the visibility of some fields
+// changes.
+TEST_F(AutofillManagerTest, FormChangesVisibilityOfFields) {
+ // Set up our form data.
+ FormData form;
+ FormFieldData field;
+
+ // Default is zero, have to set to a number autofill can process.
+ field.max_length = 10;
+ form.name = ASCIIToUTF16("multiple_groups_fields");
+ test::CreateTestFormField("First Name", "first_name", "", "text", &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("Last Name", "last_name", "", "text", &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("Address", "address", "", "text", &field);
+ form.fields.push_back(field);
+
+ test::CreateTestFormField("Postal Code", "postal_code", "", "text", &field);
+ field.is_focusable = false;
+ form.fields.push_back(field);
+
+ test::CreateTestFormField("Country", "country", "", "text", &field);
+ field.is_focusable = false;
+ form.fields.push_back(field);
+
+ std::vector<FormData> forms(1, form);
+ FormsSeen(forms);
+
+ // Fill the form with the first profile. The hidden fields will not get
+ // filled.
+ const char guid[] = "00000000-0000-0000-0000-000000000001";
+ int response_page_id = 0;
+ FormData response_data;
+ FillAutofillFormDataAndSaveResults(kDefaultPageID, form, form.fields[0],
+ MakeFrontendID(std::string(), guid),
+ &response_page_id, &response_data);
+
+ ASSERT_EQ(5U, response_data.fields.size());
+ ExpectFilledField("First Name", "first_name", "Elvis", "text",
+ response_data.fields[0]);
+ ExpectFilledField("Last Name", "last_name", "Presley", "text",
+ response_data.fields[1]);
+ ExpectFilledField("Address", "address", "3734 Elvis Presley Blvd.", "text",
+ response_data.fields[2]);
+ ExpectFilledField("Postal Code", "postal_code", "", "text",
+ response_data.fields[3]);
+ ExpectFilledField("Country", "country", "", "text", response_data.fields[4]);
+
+ // Two other fields will show up. Select the second profile. The fields that
+ // were already filled, would be left unchanged, and the rest would be filled
+ // with the second profile. (Two different profiles are selected, to make sure
+ // the right fields are getting filled.)
+ response_data.fields[3].is_focusable = true;
+ response_data.fields[4].is_focusable = true;
+ FormData later_response_data;
+ const char guid2[] = "00000000-0000-0000-0000-000000000002";
+ FillAutofillFormDataAndSaveResults(kDefaultPageID, response_data,
+ response_data.fields[4],
+ MakeFrontendID(std::string(), guid2),
+ &response_page_id, &later_response_data);
+ ASSERT_EQ(5U, later_response_data.fields.size());
+ ExpectFilledField("First Name", "first_name", "Elvis", "text",
+ later_response_data.fields[0]);
+ ExpectFilledField("Last Name", "last_name", "Presley", "text",
+ later_response_data.fields[1]);
+ ExpectFilledField("Address", "address", "3734 Elvis Presley Blvd.", "text",
+ later_response_data.fields[2]);
+ ExpectFilledField("Postal Code", "postal_code", "79401", "text",
+ later_response_data.fields[3]);
+ ExpectFilledField("Country", "country", "United States", "text",
+ later_response_data.fields[4]);
+}
+
// Test that we are able to save form data when forms are submitted.
TEST_F(AutofillManagerTest, FormSubmitted) {
// Set up our form data.
diff --git a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
index ce993ac659c..87dc8149da5 100644
--- a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -275,13 +275,10 @@ void AutofillMergeTest::MergeProfiles(const std::string& profiles,
// Import the profile.
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- form_data_importer_->ImportFormData(
- form_structure,
- true, // credit card autofill enabled
- false, // should return local card
- &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card);
+ form_data_importer_->ImportFormData(form_structure,
+ true, // credit card autofill enabled
+ false, // should return local card
+ &imported_credit_card);
EXPECT_FALSE(imported_credit_card);
// Clear the |form| to start a new profile.
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.cc b/chromium/components/autofill/core/browser/autofill_metrics.cc
index 3bf9b0264e8..4f9a0dbb69b 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics.cc
@@ -143,6 +143,7 @@ int GetFieldTypeGroupMetric(ServerFieldType field_type,
break;
case ADDRESS_HOME_STREET_ADDRESS:
group = GROUP_STREET_ADDRESS;
+ break;
case ADDRESS_HOME_CITY:
group = GROUP_ADDRESS_CITY;
break;
@@ -271,8 +272,7 @@ const char* GetQualityMetricTypeSuffix(
switch (metric_type) {
default:
NOTREACHED();
- // Fall through...
-
+ FALLTHROUGH;
case AutofillMetrics::TYPE_SUBMISSION:
return "";
case AutofillMetrics::TYPE_NO_SUBMISSION:
@@ -633,6 +633,14 @@ void AutofillMetrics::LogSubmittedServerCardExpirationStatusMetric(
}
// static
+void AutofillMetrics::LogSubmittedCardStateMetric(
+ SubmittedCardStateMetric metric) {
+ DCHECK_LT(metric, NUM_SUBMITTED_CARD_STATE_METRICS);
+ UMA_HISTOGRAM_ENUMERATION("Autofill.SubmittedCardState", metric,
+ NUM_SUBMITTED_CARD_STATE_METRICS);
+}
+
+// static
void AutofillMetrics::LogCardUploadDecisionMetrics(
int upload_decision_metrics) {
DCHECK(upload_decision_metrics);
@@ -1526,8 +1534,6 @@ void AutofillMetrics::FormEventLogger::Log(FormEvent event) const {
}
// Logging again in a different histogram for segmentation purposes.
- // TODO(waltercacau): Re-evaluate if we still need such fine grained
- // segmentation. http://crbug.com/454018
if (server_record_type_count_ == 0 && local_record_type_count_ == 0)
name += ".WithNoData";
else if (server_record_type_count_ > 0 && local_record_type_count_ == 0)
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.h b/chromium/components/autofill/core/browser/autofill_metrics.h
index 09e1d064b2b..be86575c086 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.h
+++ b/chromium/components/autofill/core/browser/autofill_metrics.h
@@ -118,6 +118,19 @@ class AutofillMetrics {
NUM_INFO_BAR_METRICS,
};
+ // Represents card submitted state.
+ enum SubmittedCardStateMetric {
+ // Submitted card has valid card number and expiration date.
+ HAS_CARD_NUMBER_AND_EXPIRATION_DATE,
+ // Submitted card has a valid card number but an invalid or missing
+ // expiration date.
+ HAS_CARD_NUMBER_ONLY,
+ // Submitted card has a valid expiration date but an invalid or missing card
+ // number.
+ HAS_EXPIRATION_DATE_ONLY,
+ NUM_SUBMITTED_CARD_STATE_METRICS,
+ };
+
// 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
@@ -694,6 +707,8 @@ class AutofillMetrics {
static void LogSubmittedServerCardExpirationStatusMetric(
SubmittedServerCardExpirationStatusMetric metric);
+ static void LogSubmittedCardStateMetric(SubmittedCardStateMetric metric);
+
// |upload_decision_metrics| is a bitmask of |CardUploadDecisionMetric|.
static void LogCardUploadDecisionMetrics(int upload_decision_metrics);
static void LogCreditCardInfoBarMetric(
diff --git a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
index 87676d05c18..2db7c2a517b 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/metrics/metrics_hashes.h"
#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/test/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
@@ -35,10 +36,6 @@
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/fake_signin_manager.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/test_signin_client.h"
#include "components/ukm/test_ukm_recorder.h"
#include "components/ukm/ukm_source.h"
#include "components/webdata/common/web_data_results.h"
@@ -207,7 +204,6 @@ class AutofillMetricsTest : public testing::Test {
void TearDown() override;
protected:
- void EnableWalletSync();
void CreateAmbiguousProfiles();
// Removes all existing profiles and creates one profile.
@@ -226,9 +222,6 @@ class AutofillMetricsTest : public testing::Test {
base::test::ScopedTaskEnvironment scoped_task_environment_;
ukm::TestAutoSetUkmRecorder test_ukm_recorder_;
MockAutofillClient autofill_client_;
- std::unique_ptr<AccountTrackerService> account_tracker_;
- std::unique_ptr<FakeSigninManagerBase> signin_manager_;
- std::unique_ptr<TestSigninClient> signin_client_;
std::unique_ptr<TestAutofillDriver> autofill_driver_;
std::unique_ptr<TestAutofillManager> autofill_manager_;
std::unique_ptr<TestPersonalDataManager> personal_data_;
@@ -248,21 +241,9 @@ AutofillMetricsTest::~AutofillMetricsTest() {
void AutofillMetricsTest::SetUp() {
autofill_client_.SetPrefs(test::PrefServiceForTesting());
- // Set up identity services.
- signin_client_ =
- std::make_unique<TestSigninClient>(autofill_client_.GetPrefs());
- account_tracker_ = std::make_unique<AccountTrackerService>();
- account_tracker_->Initialize(signin_client_.get());
-
- signin_manager_ = std::make_unique<FakeSigninManagerBase>(
- signin_client_.get(), account_tracker_.get());
- signin_manager_->Initialize(autofill_client_.GetPrefs());
-
personal_data_ = std::make_unique<TestPersonalDataManager>();
personal_data_->set_database(autofill_client_.GetDatabase());
personal_data_->SetPrefService(autofill_client_.GetPrefs());
- personal_data_->set_account_tracker(account_tracker_.get());
- personal_data_->set_signin_manager(signin_manager_.get());
autofill_driver_ = std::make_unique<TestAutofillDriver>();
autofill_manager_ = std::make_unique<TestAutofillManager>(
autofill_driver_.get(), &autofill_client_, personal_data_.get());
@@ -281,19 +262,10 @@ void AutofillMetricsTest::TearDown() {
autofill_manager_.reset();
autofill_driver_.reset();
personal_data_.reset();
- signin_manager_->Shutdown();
- signin_manager_.reset();
- account_tracker_->Shutdown();
- account_tracker_.reset();
- signin_client_.reset();
test::ReenableSystemServices();
test_ukm_recorder_.Purge();
}
-void AutofillMetricsTest::EnableWalletSync() {
- signin_manager_->SetAuthenticatedAccountInfo("12345", "syncuser@example.com");
-}
-
void AutofillMetricsTest::CreateAmbiguousProfiles() {
personal_data_->ClearProfiles();
CreateTestAutofillProfiles();
@@ -2462,8 +2434,7 @@ TEST_F(AutofillMetricsTest, AutofillIsEnabledAtStartup) {
base::HistogramTester histogram_tester;
personal_data_->SetAutofillEnabled(true);
personal_data_->Init(autofill_client_.GetDatabase(),
- autofill_client_.GetPrefs(), account_tracker_.get(),
- signin_manager_.get(), false);
+ autofill_client_.GetPrefs(), nullptr, false);
histogram_tester.ExpectUniqueSample("Autofill.IsEnabled.Startup", true, 1);
}
@@ -2472,8 +2443,7 @@ TEST_F(AutofillMetricsTest, AutofillIsDisabledAtStartup) {
base::HistogramTester histogram_tester;
personal_data_->SetAutofillEnabled(false);
personal_data_->Init(autofill_client_.GetDatabase(),
- autofill_client_.GetPrefs(), account_tracker_.get(),
- signin_manager_.get(), false);
+ autofill_client_.GetPrefs(), nullptr, false);
histogram_tester.ExpectUniqueSample("Autofill.IsEnabled.Startup", false, 1);
}
@@ -3139,7 +3109,6 @@ TEST_F(AutofillMetricsTest, CreditCardShownFormEvents) {
// Test that we log selected form event for credit cards.
TEST_F(AutofillMetricsTest, CreditCardSelectedFormEvents) {
- EnableWalletSync();
// Creating all kinds of cards.
RecreateCreditCards(true /* include_local_credit_card */,
true /* include_masked_server_credit_card */,
@@ -3381,7 +3350,6 @@ TEST_F(AutofillMetricsTest, CreditCardFilledFormEvents) {
// Test that we log submitted form events for credit cards.
TEST_F(AutofillMetricsTest, CreditCardGetRealPanDuration) {
- EnableWalletSync();
// Creating masked card
RecreateCreditCards(false /* include_local_credit_card */,
true /* include_masked_server_credit_card */,
@@ -3453,7 +3421,6 @@ TEST_F(AutofillMetricsTest, CreditCardGetRealPanDuration) {
TEST_F(AutofillMetricsTest,
CreditCardSubmittedWithoutSelectingSuggestionsNoCard) {
- EnableWalletSync();
// Create a local card for testing, card number is 4111111111111111.
RecreateCreditCards(true /* include_local_credit_card */,
false /* include_masked_server_credit_card */,
@@ -3496,7 +3463,6 @@ TEST_F(AutofillMetricsTest,
TEST_F(AutofillMetricsTest,
CreditCardSubmittedWithoutSelectingSuggestionsWrongSizeCard) {
- EnableWalletSync();
// Create a local card for testing, card number is 4111111111111111.
RecreateCreditCards(true /* include_local_credit_card */,
false /* include_masked_server_credit_card */,
@@ -3538,7 +3504,6 @@ TEST_F(AutofillMetricsTest,
TEST_F(AutofillMetricsTest,
CreditCardSubmittedWithoutSelectingSuggestionsFailLuhnCheckCard) {
- EnableWalletSync();
// Create a local card for testing, card number is 4111111111111111.
RecreateCreditCards(true /* include_local_credit_card */,
false /* include_masked_server_credit_card */,
@@ -3581,7 +3546,6 @@ TEST_F(AutofillMetricsTest,
TEST_F(AutofillMetricsTest,
CreditCardSubmittedWithoutSelectingSuggestionsUnknownCard) {
- EnableWalletSync();
// Create a local card for testing, card number is 4111111111111111.
RecreateCreditCards(true /* include_local_credit_card */,
false /* include_masked_server_credit_card */,
@@ -3626,7 +3590,6 @@ TEST_F(AutofillMetricsTest,
TEST_F(AutofillMetricsTest,
CreditCardSubmittedWithoutSelectingSuggestionsKnownCard) {
- EnableWalletSync();
// Create a local card for testing, card number is 4111111111111111.
RecreateCreditCards(true /* include_local_credit_card */,
false /* include_masked_server_credit_card */,
@@ -3671,7 +3634,6 @@ TEST_F(AutofillMetricsTest,
TEST_F(AutofillMetricsTest,
ShouldNotLogSubmitWithoutSelectingSuggestionsIfSuggestionFilled) {
- EnableWalletSync();
// Create a local card for testing, card number is 4111111111111111.
RecreateCreditCards(true /* include_local_credit_card */,
false /* include_masked_server_credit_card */,
@@ -3729,7 +3691,6 @@ TEST_F(AutofillMetricsTest,
}
TEST_F(AutofillMetricsTest, ShouldNotLogFormEventNoCardForAddressForm) {
- EnableWalletSync();
// Create a profile.
RecreateProfile();
// Set up our form data.
@@ -3769,7 +3730,6 @@ TEST_F(AutofillMetricsTest, ShouldNotLogFormEventNoCardForAddressForm) {
// Test that we log submitted form events for credit cards.
TEST_F(AutofillMetricsTest, CreditCardSubmittedFormEvents) {
- EnableWalletSync();
// Creating all kinds of cards.
RecreateCreditCards(true /* include_local_credit_card */,
true /* include_masked_server_credit_card */,
@@ -4115,7 +4075,6 @@ TEST_F(AutofillMetricsTest, CreditCardSubmittedFormEvents) {
// Test that we log "will submit" and "submitted" form events for credit
// cards.
TEST_F(AutofillMetricsTest, CreditCardWillSubmitFormEvents) {
- EnableWalletSync();
// Creating all kinds of cards.
RecreateCreditCards(true /* include_local_credit_card */,
true /* include_masked_server_credit_card */,
@@ -4392,7 +4351,6 @@ TEST_F(AutofillMetricsTest, AddressInteractedFormEvents) {
// Test that we log suggestion shown form events for address.
TEST_F(AutofillMetricsTest, AddressShownFormEvents) {
- EnableWalletSync();
// Create a profile.
RecreateProfile();
// Set up our form data.
@@ -4483,7 +4441,6 @@ TEST_F(AutofillMetricsTest, AddressShownFormEvents) {
// Test that we log filled form events for address.
TEST_F(AutofillMetricsTest, AddressFilledFormEvents) {
- EnableWalletSync();
// Create a profile.
RecreateProfile();
// Set up our form data.
@@ -4550,7 +4507,6 @@ TEST_F(AutofillMetricsTest, AddressFilledFormEvents) {
// Test that we log submitted form events for address.
TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
- EnableWalletSync();
// Create a profile.
RecreateProfile();
// Set up our form data.
@@ -4750,7 +4706,6 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
// Test that we log "will submit" and "submitted" form events for address.
TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
- EnableWalletSync();
// Create a profile.
RecreateProfile();
// Set up our form data.
@@ -4924,8 +4879,6 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
// Test that we log interacted form event for credit cards only once.
TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) {
- EnableWalletSync();
-
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("TestForm");
@@ -5029,8 +4982,6 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) {
// Test that we log interacted form event for address only once.
TEST_F(AutofillMetricsTest, AddressFormEventsAreSegmented) {
- EnableWalletSync();
-
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("TestForm");
diff --git a/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc b/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
index bc4d854bcdb..becc1289c2b 100644
--- a/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
+++ b/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
@@ -11,6 +11,7 @@
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/legal_message_line.h"
#include "components/autofill/core/common/autofill_constants.h"
+#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/grit/components_scaled_resources.h"
#include "components/infobars/core/infobar.h"
@@ -53,6 +54,10 @@ AutofillSaveCardInfoBarDelegateMobile::AutofillSaveCardInfoBarDelegateMobile(
return;
}
}
+ if (IsGooglePayBrandingEnabled()) {
+ card_label_ = card.NetworkForDisplay() + base::string16(kMidlineEllipsis) +
+ card.LastFourDigits();
+ }
AutofillMetrics::LogCreditCardInfoBarMetric(
AutofillMetrics::INFOBAR_SHOWN, upload_,
@@ -77,23 +82,40 @@ bool AutofillSaveCardInfoBarDelegateMobile::LegalMessagesParsedSuccessfully() {
return !upload_ || !legal_messages_.empty();
}
+bool AutofillSaveCardInfoBarDelegateMobile::IsGooglePayBrandingEnabled() const {
+ return upload_ &&
+ base::FeatureList::IsEnabled(
+ features::kAutofillUpstreamUseGooglePayOnAndroidBranding);
+}
+
+base::string16 AutofillSaveCardInfoBarDelegateMobile::GetTitleText() const {
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_TO_CLOUD_V3);
+}
+
+base::string16 AutofillSaveCardInfoBarDelegateMobile::GetDescriptionText()
+ const {
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_SAVE_CARD_PROMPT_UPLOAD_EXPLANATION_V2);
+}
+
int AutofillSaveCardInfoBarDelegateMobile::GetIconId() const {
- return IDR_INFOBAR_AUTOFILL_CC;
+ return IsGooglePayBrandingEnabled() ? 0 : IDR_INFOBAR_AUTOFILL_CC;
}
base::string16 AutofillSaveCardInfoBarDelegateMobile::GetMessageText() const {
+ if (IsGooglePayBrandingEnabled()) {
+ return base::string16();
+ }
return l10n_util::GetStringUTF16(
upload_ ? IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_TO_CLOUD
: IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_LOCAL);
}
base::string16 AutofillSaveCardInfoBarDelegateMobile::GetLinkText() const {
- return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
-}
-
-infobars::InfoBarDelegate::Type
-AutofillSaveCardInfoBarDelegateMobile::GetInfoBarType() const {
- return PAGE_ACTION_TYPE;
+ return IsGooglePayBrandingEnabled()
+ ? base::string16()
+ : l10n_util::GetStringUTF16(IDS_LEARN_MORE);
}
infobars::InfoBarDelegate::InfoBarIdentifier
@@ -133,7 +155,7 @@ bool AutofillSaveCardInfoBarDelegateMobile::Cancel() {
}
GURL AutofillSaveCardInfoBarDelegateMobile::GetLinkURL() const {
- return GURL(kHelpURL);
+ return IsGooglePayBrandingEnabled() ? GURL() : GURL(kHelpURL);
}
void AutofillSaveCardInfoBarDelegateMobile::LogUserAction(
diff --git a/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h b/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h
index 8b933018107..0d4d63c0039 100644
--- a/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h
+++ b/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h
@@ -49,11 +49,18 @@ class AutofillSaveCardInfoBarDelegateMobile : public ConfirmInfoBarDelegate {
// Legal messages are only specified for the upload case, not for local save.
bool LegalMessagesParsedSuccessfully();
+ // Google Pay branding is enabled with a flag and only for cards upstreamed
+ // to Google.
+ bool IsGooglePayBrandingEnabled() const;
+
+ // All following changes are with respect to Google Pay branding.
+ base::string16 GetTitleText() const;
+ base::string16 GetDescriptionText() const;
+
// ConfirmInfoBarDelegate:
int GetIconId() const override;
base::string16 GetMessageText() const override;
base::string16 GetLinkText() const override;
- Type GetInfoBarType() const override;
infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
bool ShouldExpire(const NavigationDetails& details) const override;
void InfoBarDismissed() override;
diff --git a/chromium/components/autofill/core/browser/autofill_scanner.h b/chromium/components/autofill/core/browser/autofill_scanner.h
index 88b84e6fd94..0babe38a2fd 100644
--- a/chromium/components/autofill/core/browser/autofill_scanner.h
+++ b/chromium/components/autofill/core/browser/autofill_scanner.h
@@ -45,6 +45,9 @@ class AutofillScanner {
// |RewindTo()|.
size_t SaveCursor();
+ // This is only for logging purposes.
+ size_t CursorIndex() { return static_cast<size_t>(cursor_ - begin_); };
+
private:
void Init(const std::vector<AutofillField*>& fields);
diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.cc b/chromium/components/autofill/core/browser/autofill_test_utils.cc
index 091a4fcfdf3..6ed36affa53 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.cc
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.cc
@@ -26,9 +26,6 @@
#include "components/prefs/pref_service.h"
#include "components/prefs/pref_service_factory.h"
#include "components/prefs/testing_pref_store.h"
-#include "components/signin/core/browser/account_fetcher_service.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/signin_pref_names.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rect.h"
@@ -60,26 +57,6 @@ std::unique_ptr<PrefService> PrefServiceForTesting(
user_prefs::PrefRegistrySyncable* registry) {
AutofillManager::RegisterProfilePrefs(registry);
- // PDM depends on these prefs, which are normally registered in
- // SigninManagerFactory.
- registry->RegisterStringPref(::prefs::kGoogleServicesAccountId,
- std::string());
- registry->RegisterStringPref(::prefs::kGoogleServicesLastAccountId,
- std::string());
- registry->RegisterStringPref(::prefs::kGoogleServicesLastUsername,
- std::string());
- registry->RegisterStringPref(::prefs::kGoogleServicesUserAccountId,
- std::string());
- registry->RegisterStringPref(::prefs::kGoogleServicesUsername,
- std::string());
-
- // PDM depends on these prefs, which are normally registered in
- // AccountTrackerServiceFactory.
- registry->RegisterListPref(AccountTrackerService::kAccountInfoPref);
- registry->RegisterIntegerPref(::prefs::kAccountIdMigrationState,
- AccountTrackerService::MIGRATION_NOT_STARTED);
- registry->RegisterInt64Pref(AccountFetcherService::kLastUpdatePref, 0);
-
PrefServiceFactory factory;
factory.set_user_prefs(base::MakeRefCounted<TestingPrefStore>());
return factory.Create(registry);
diff --git a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc
index 9610d5dd02b..49eddabe2f2 100644
--- a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc
@@ -94,7 +94,7 @@ class AutofillWalletDataTypeControllerTest : public testing::Test,
base::ThreadTaskRunnerHandle::Get());
autofill_wallet_dtc_ = std::make_unique<AutofillWalletDataTypeController>(
syncer::AUTOFILL_WALLET_DATA, base::ThreadTaskRunnerHandle::Get(),
- base::Bind(&base::DoNothing), this, web_data_service_);
+ base::DoNothing(), this, web_data_service_);
last_type_ = syncer::UNSPECIFIED;
last_error_ = syncer::SyncError();
diff --git a/chromium/components/autofill/core/browser/credit_card.cc b/chromium/components/autofill/core/browser/credit_card.cc
index 87d845e341f..4788afc8cfc 100644
--- a/chromium/components/autofill/core/browser/credit_card.cc
+++ b/chromium/components/autofill/core/browser/credit_card.cc
@@ -624,8 +624,15 @@ bool CreditCard::IsEmpty(const std::string& app_locale) const {
}
bool CreditCard::IsValid() const {
- return IsValidCreditCardNumber(number_) &&
- IsValidCreditCardExpirationDate(expiration_year_, expiration_month_,
+ return HasValidCardNumber() && HasValidExpirationDate();
+}
+
+bool CreditCard::HasValidCardNumber() const {
+ return IsValidCreditCardNumber(number_);
+}
+
+bool CreditCard::HasValidExpirationDate() const {
+ return IsValidCreditCardExpirationDate(expiration_year_, expiration_month_,
AutofillClock::Now());
}
diff --git a/chromium/components/autofill/core/browser/credit_card.h b/chromium/components/autofill/core/browser/credit_card.h
index 40ce0b39a3e..1894581ebd2 100644
--- a/chromium/components/autofill/core/browser/credit_card.h
+++ b/chromium/components/autofill/core/browser/credit_card.h
@@ -164,9 +164,15 @@ class CreditCard : public AutofillDataModel {
// Returns true if there are no values (field types) set.
bool IsEmpty(const std::string& app_locale) const;
- // Returns true if all field types have valid values set and the card is not
- // expired. MASKED_SERVER_CARDs will never be valid because the number is
+ // Returns true if credit card number is valid.
+ // MASKED_SERVER_CARDs will never be valid because the number is
// not complete.
+ bool HasValidCardNumber() const;
+
+ // Returns true if credit card has valid expiration date.
+ bool HasValidExpirationDate() const;
+
+ // Returns true if IsValidCardNumber && IsValidExpirationDate.
bool IsValid() const;
// Returns the card number.
diff --git a/chromium/components/autofill/core/browser/credit_card_field.cc b/chromium/components/autofill/core/browser/credit_card_field.cc
index 3343e584b9b..a0c484b8dd9 100644
--- a/chromium/components/autofill/core/browser/credit_card_field.cc
+++ b/chromium/components/autofill/core/browser/credit_card_field.cc
@@ -88,6 +88,7 @@ std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
// Using 'new' to access private constructor.
auto credit_card_field = base::WrapUnique(new CreditCardField());
size_t saved_cursor = scanner->SaveCursor();
+ int nb_unknown_fields = 0;
// Credit card fields can appear in many different orders.
// We loop until no more credit card related fields are found, see |break| at
@@ -134,6 +135,7 @@ std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
if (!credit_card_field->type_ && LikelyCardTypeSelectField(scanner)) {
credit_card_field->type_ = scanner->Cursor();
scanner->Advance();
+ nb_unknown_fields = 0;
continue;
}
@@ -176,6 +178,7 @@ std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
credit_card_field->verification_ = nullptr;
}
} else {
+ nb_unknown_fields = 0;
continue;
}
}
@@ -204,11 +207,14 @@ std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
current_number_field->set_credit_card_number_offset(start_index);
credit_card_field->numbers_.push_back(current_number_field);
+ nb_unknown_fields = 0;
continue;
}
- if (credit_card_field->ParseExpirationDate(scanner))
+ if (credit_card_field->ParseExpirationDate(scanner)) {
+ nb_unknown_fields = 0;
continue;
+ }
if (credit_card_field->expiration_month_ &&
!credit_card_field->expiration_year_ &&
@@ -218,6 +224,24 @@ std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
return nullptr;
}
+ nb_unknown_fields++;
+
+ // Since cc#/verification and expiration are inter-dependent for the final
+ // detection decision, we allow for 4 UNKONWN fields in between.
+ // We can't allow for a lot of unknown fields, because the name on address
+ // sections may sometimes be mistakenly detected as cardholder name.
+ if ((credit_card_field->verification_ ||
+ !credit_card_field->numbers_.empty() ||
+ credit_card_field->HasExpiration()) &&
+ (!credit_card_field->verification_ ||
+ credit_card_field->numbers_.empty() ||
+ !credit_card_field->HasExpiration()) &&
+ nb_unknown_fields < 4) {
+ scanner->Advance();
+ fields--; // We continue searching in the same credit card section, but
+ // no more field is identified.
+ continue;
+ }
break;
}
diff --git a/chromium/components/autofill/core/browser/credit_card_save_manager.cc b/chromium/components/autofill/core/browser/credit_card_save_manager.cc
index 0ddd6ce1106..e3935b3c4be 100644
--- a/chromium/components/autofill/core/browser/credit_card_save_manager.cc
+++ b/chromium/components/autofill/core/browser/credit_card_save_manager.cc
@@ -37,7 +37,7 @@
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/prefs/pref_service.h"
-#include "google_apis/gaia/identity_provider.h"
+#include "services/identity/public/cpp/identity_manager.h"
#include "url/gurl.h"
namespace autofill {
@@ -209,7 +209,7 @@ bool CreditCardSaveManager::IsCreditCardUploadEnabled() {
return observer_for_testing_ ||
::autofill::IsCreditCardUploadEnabled(
client_->GetPrefs(), client_->GetSyncService(),
- client_->GetIdentityProvider()->GetActiveUsername());
+ client_->GetIdentityManager()->GetPrimaryAccountInfo().email);
}
void CreditCardSaveManager::OnDidUploadCard(
diff --git a/chromium/components/autofill/core/browser/credit_card_save_manager_unittest.cc b/chromium/components/autofill/core/browser/credit_card_save_manager_unittest.cc
index dfa40607188..ac381155f07 100644
--- a/chromium/components/autofill/core/browser/credit_card_save_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/credit_card_save_manager_unittest.cc
@@ -99,7 +99,7 @@ class CreditCardSaveManagerTest : public testing::Test {
autofill_driver_->SetURLRequestContext(request_context_.get());
payments_client_ = new payments::TestPaymentsClient(
autofill_driver_->GetURLRequestContext(), autofill_client_.GetPrefs(),
- autofill_client_.GetIdentityProvider(),
+ autofill_client_.GetIdentityManager(),
/*unmask_delegate=*/nullptr,
// Will be set by CreditCardSaveManager's ctor
/*save_delegate=*/nullptr);
@@ -128,11 +128,6 @@ class CreditCardSaveManagerTest : public testing::Test {
request_context_ = nullptr;
}
- void EnableAutofillOfferLocalSaveIfServerCardManuallyEnteredExperiment() {
- scoped_feature_list_.InitAndEnableFeature(
- kAutofillOfferLocalSaveIfServerCardManuallyEntered);
- }
-
void EnableAutofillUpstreamRequestCvcIfMissingExperiment() {
scoped_feature_list_.InitAndEnableFeature(
kAutofillUpstreamRequestCvcIfMissing);
@@ -1848,48 +1843,7 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadDetailsFails) {
AutofillMetrics::UPLOAD_NOT_OFFERED_GET_UPLOAD_DETAILS_FAILED);
}
-TEST_F(CreditCardSaveManagerTest, DuplicateMaskedCreditCard) {
- EnableAutofillOfferLocalSaveIfServerCardManuallyEnteredExperiment();
-
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
- credit_card_save_manager_->SetAppLocale("en-US");
-
- // Create, fill and submit an address form in order to establish a recent
- // profile which can be selected for the upload request.
- FormData address_form;
- test::CreateTestAddressFormData(&address_form);
- FormsSeen(std::vector<FormData>(1, address_form));
- ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form);
- FormSubmitted(address_form);
-
- // Add a masked credit card whose |TypeAndLastFourDigits| matches what we will
- // enter below.
- CreditCard credit_card(CreditCard::MASKED_SERVER_CARD, "a123");
- test::SetCreditCardInfo(&credit_card, "Flo Master", "1111", "11",
- NextYear().c_str(), "1");
- credit_card.SetNetworkForMaskedCard(kVisaCard);
- personal_data_.AddServerCreditCard(credit_card);
-
- // Set up our credit card form data.
- FormData credit_card_form;
- CreateTestCreditCardFormData(&credit_card_form, true, false);
- FormsSeen(std::vector<FormData>(1, credit_card_form));
-
- // Edit the data, and submit.
- credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
- credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16("11");
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
- credit_card_form.fields[4].value = ASCIIToUTF16("123");
-
- // The local save prompt should be shown.
- EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _));
- FormSubmitted(credit_card_form);
- EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
-}
-
-TEST_F(CreditCardSaveManagerTest, DuplicateMaskedCreditCard_ExperimentOff) {
+TEST_F(CreditCardSaveManagerTest, DuplicateMaskedCreditCard_NoUpload) {
personal_data_.ClearProfiles();
credit_card_save_manager_->SetCreditCardUploadEnabled(true);
credit_card_save_manager_->SetAppLocale("en-US");
@@ -1922,7 +1876,8 @@ TEST_F(CreditCardSaveManagerTest, DuplicateMaskedCreditCard_ExperimentOff) {
credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
- // The local save prompt should not be shown because the experiment is off.
+ // Local save prompt should not be shown as there is alredy masked
+ // card with same |TypeAndLastFourDigits|.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
diff --git a/chromium/components/autofill/core/browser/credit_card_unittest.cc b/chromium/components/autofill/core/browser/credit_card_unittest.cc
index b110302b1aa..99b28bf0e34 100644
--- a/chromium/components/autofill/core/browser/credit_card_unittest.cc
+++ b/chromium/components/autofill/core/browser/credit_card_unittest.cc
@@ -631,7 +631,7 @@ TEST(CreditCardTest, UpdateFromImportedCard) {
EXPECT_EQ(original_card, a);
}
-TEST(CreditCardTest, IsValid) {
+TEST(CreditCardTest, IsValidCardNumberAndExpiryDate) {
CreditCard card;
// Invalid because expired
const base::Time now(base::Time::Now());
@@ -643,6 +643,8 @@ TEST(CreditCardTest, IsValid) {
base::IntToString16(now_exploded.year - 1));
card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
EXPECT_FALSE(card.IsValid());
+ EXPECT_FALSE(card.HasValidExpirationDate());
+ EXPECT_TRUE(card.HasValidCardNumber());
// Invalid because card number is not complete
card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("12"));
@@ -654,11 +656,15 @@ TEST(CreditCardTest, IsValid) {
SCOPED_TRACE(valid_number);
card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16(valid_number));
EXPECT_TRUE(card.IsValid());
+ EXPECT_TRUE(card.HasValidCardNumber());
+ EXPECT_TRUE(card.HasValidExpirationDate());
}
for (const char* invalid_number : kInvalidNumbers) {
SCOPED_TRACE(invalid_number);
card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16(invalid_number));
EXPECT_FALSE(card.IsValid());
+ EXPECT_TRUE(card.HasValidExpirationDate());
+ EXPECT_FALSE(card.HasValidCardNumber());
}
}
diff --git a/chromium/components/autofill/core/browser/form_data_importer.cc b/chromium/components/autofill/core/browser/form_data_importer.cc
index 4a3f19fe7dc..5195eb23352 100644
--- a/chromium/components/autofill/core/browser/form_data_importer.cc
+++ b/chromium/components/autofill/core/browser/form_data_importer.cc
@@ -109,23 +109,17 @@ FormDataImporter::~FormDataImporter() {}
void FormDataImporter::ImportFormData(const FormStructure& submitted_form,
bool credit_card_autofill_enabled) {
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
if (!ImportFormData(submitted_form, credit_card_autofill_enabled,
credit_card_save_manager_->IsCreditCardUploadEnabled(),
- &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card))
+ &imported_credit_card))
return;
// No card available to offer save or upload.
if (!imported_credit_card)
return;
- if (!credit_card_save_manager_->IsCreditCardUploadEnabled() ||
- imported_credit_card_matches_masked_server_credit_card) {
- // Offer local save. This block will only be reached if we have observed a
- // new card or a card whose |TypeAndLastFourDigits| matches a masked server
- // card. |ImportFormData| will return false if the card matches a full card
- // that we have already stored.
+ if (!credit_card_save_manager_->IsCreditCardUploadEnabled()) {
+ // Offer local save.
credit_card_save_manager_->OfferCardLocalSave(*imported_credit_card);
} else {
// Attempt to offer upload save. Because we pass IsCreditCardUploadEnabled()
@@ -170,18 +164,15 @@ bool FormDataImporter::ImportFormData(
const FormStructure& submitted_form,
bool credit_card_autofill_enabled,
bool should_return_local_card,
- std::unique_ptr<CreditCard>* imported_credit_card,
- bool* imported_credit_card_matches_masked_server_credit_card) {
+ std::unique_ptr<CreditCard>* imported_credit_card) {
// 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
- // |should_return_local_card| and
- // |imported_credit_card_matches_masked_server_credit_card|.
+ // |should_return_local_card|.
bool cc_import = false;
if (credit_card_autofill_enabled) {
- cc_import = ImportCreditCard(
- submitted_form, should_return_local_card, imported_credit_card,
- imported_credit_card_matches_masked_server_credit_card);
+ cc_import = ImportCreditCard(submitted_form, should_return_local_card,
+ imported_credit_card);
}
// - ImportAddressProfiles may eventually save or update one or more address
// profiles.
@@ -307,10 +298,8 @@ bool FormDataImporter::ImportAddressProfileForSection(
bool FormDataImporter::ImportCreditCard(
const FormStructure& form,
bool should_return_local_card,
- std::unique_ptr<CreditCard>* imported_credit_card,
- bool* imported_credit_card_matches_masked_server_credit_card) {
+ std::unique_ptr<CreditCard>* imported_credit_card) {
DCHECK(!imported_credit_card->get());
- *imported_credit_card_matches_masked_server_credit_card = false;
// The candidate for credit card import. There are many ways for the candidate
// to be rejected (see everywhere this function returns false, below).
@@ -323,10 +312,20 @@ bool FormDataImporter::ImportCreditCard(
if (has_duplicate_field_type)
return false;
- // Reject the credit card if we did not detect enough filled credit card
- // fields (such as valid number, month, year).
- if (!candidate_credit_card.IsValid())
+ if (!candidate_credit_card.IsValid()) {
+ if (candidate_credit_card.HasValidCardNumber()) {
+ AutofillMetrics::LogSubmittedCardStateMetric(
+ AutofillMetrics::HAS_CARD_NUMBER_ONLY);
+ }
+ if (candidate_credit_card.HasValidExpirationDate()) {
+ AutofillMetrics::LogSubmittedCardStateMetric(
+ AutofillMetrics::HAS_EXPIRATION_DATE_ONLY);
+ }
+
return false;
+ }
+ AutofillMetrics::LogSubmittedCardStateMetric(
+ AutofillMetrics::HAS_CARD_NUMBER_AND_EXPIRATION_DATE);
// Attempt to merge with an existing credit card. Don't present a prompt if we
// have already saved this card number, unless |should_return_local_card| is
@@ -349,7 +348,7 @@ bool FormDataImporter::ImportCreditCard(
}
}
- // Also don't offer to save if we already have this stored as a full server
+ // Also don't offer to save if we already have this stored as a server
// card. We only check the number because if the new card has the same number
// as the server card, upload is guaranteed to fail. There's no mechanism for
// entries with the same number but different names or expiration dates as
@@ -373,19 +372,7 @@ bool FormDataImporter::ImportCreditCard(
: AutofillMetrics::
MASKED_SERVER_CARD_EXPIRATION_DATE_DID_NOT_MATCH);
}
-
- // We can offer to save locally even if we already have this stored as
- // another masked server card with the same |TypeAndLastFourDigits| as
- // long as the AutofillOfferLocalSaveIfServerCardManuallyEntered flag is
- // enabled. This will allow the user to fill the full card number in the
- // future without having to unmask the card.
- if (card->record_type() == CreditCard::FULL_SERVER_CARD ||
- !IsAutofillOfferLocalSaveIfServerCardManuallyEnteredExperimentEnabled()) {
- return false;
- }
- DCHECK_EQ(card->record_type(), CreditCard::MASKED_SERVER_CARD);
- *imported_credit_card_matches_masked_server_credit_card = true;
- break;
+ return false;
}
}
diff --git a/chromium/components/autofill/core/browser/form_data_importer.h b/chromium/components/autofill/core/browser/form_data_importer.h
index d3c07d5c817..861b2fb5d43 100644
--- a/chromium/components/autofill/core/browser/form_data_importer.h
+++ b/chromium/components/autofill/core/browser/form_data_importer.h
@@ -63,17 +63,12 @@ class FormDataImporter {
// data. If the form contains credit card data already present in a local
// credit card entry *and* |should_return_local_card| is true, the data is
// stored into |imported_credit_card| so that we can prompt the user whether
- // to upload it. |imported_credit_card_matches_masked_server_credit_card| is
- // set to |true| if the |TypeAndLastFourDigits| in |imported_credit_card|
- // matches the |TypeAndLastFourDigits| in a saved masked server card. Returns
- // |true| if sufficient address or credit card data was found.
- // Exposed for testing.
- bool ImportFormData(
- const FormStructure& form,
- bool credit_card_autofill_enabled,
- bool should_return_local_card,
- std::unique_ptr<CreditCard>* imported_credit_card,
- bool* imported_credit_card_matches_masked_server_credit_card);
+ // to upload it. Returns |true| if sufficient address or credit card data
+ // was found. Exposed for testing.
+ bool ImportFormData(const FormStructure& form,
+ bool credit_card_autofill_enabled,
+ bool should_return_local_card,
+ std::unique_ptr<CreditCard>* imported_credit_card);
// Go through the |form| fields and attempt to extract and import valid
// address profiles. Returns true on extraction success of at least one
@@ -89,16 +84,11 @@ class FormDataImporter {
// Go through the |form| fields and attempt to extract a new credit card in
// |imported_credit_card|, or update an existing card.
// |should_return_local_card| will indicate whether |imported_credit_card| is
- // filled even if an existing card was updated.
- // |imported_credit_card_matches_masked_server_credit_card| will indicate
- // whether |imported_credit_card| is filled even if an existing masked server
- // card as the same |TypeAndLastFourDigits|. Success is defined as having a
- // new card to import, or having merged with an existing card.
- bool ImportCreditCard(
- const FormStructure& form,
- bool should_return_local_card,
- std::unique_ptr<CreditCard>* imported_credit_card,
- bool* imported_credit_card_matches_masked_server_credit_card);
+ // filled even if an existing card was updated. Success is defined as having
+ // a new card to import, or having merged with an existing card.
+ bool ImportCreditCard(const FormStructure& form,
+ bool should_return_local_card,
+ std::unique_ptr<CreditCard>* imported_credit_card);
// Extracts credit card from the form structure. |hasDuplicateFieldType| will
// be set as true if there are duplicated field types in the form.
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 209c12f4ad9..f648321448f 100644
--- a/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -43,9 +43,6 @@
#include "components/autofill/core/common/form_field_data.h"
#include "components/os_crypt/os_crypt_mocker.h"
#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/fake_signin_manager.h"
-#include "components/signin/core/browser/test_signin_client.h"
#include "components/webdata/common/web_data_service_base.h"
#include "components/webdata/common/web_database_service.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -120,8 +117,7 @@ class FormDataImporterTestBase {
personal_data_manager_.reset(new PersonalDataManager("en"));
personal_data_manager_->Init(
scoped_refptr<AutofillWebDataService>(autofill_database_service_),
- prefs_.get(), account_tracker_.get(), signin_manager_.get(),
- is_incognito);
+ prefs_.get(), nullptr, is_incognito);
personal_data_manager_->AddObserver(&personal_data_observer_);
personal_data_manager_->OnSyncServiceInitialized(nullptr);
@@ -132,8 +128,6 @@ class FormDataImporterTestBase {
}
void EnableWalletCardImport() {
- signin_manager_->SetAuthenticatedAccountInfo("12345",
- "syncuser@example.com");
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableOfferStoreUnmaskedWalletCards);
}
@@ -175,14 +169,11 @@ class FormDataImporterTestBase {
return form_data_importer_->ImportAddressProfiles(form);
}
- bool ImportCreditCard(
- const FormStructure& form,
- bool should_return_local_card,
- std::unique_ptr<CreditCard>* imported_credit_card,
- bool* imported_credit_card_matches_masked_server_credit_card) {
- return form_data_importer_->ImportCreditCard(
- form, should_return_local_card, imported_credit_card,
- imported_credit_card_matches_masked_server_credit_card);
+ bool ImportCreditCard(const FormStructure& form,
+ bool should_return_local_card,
+ std::unique_ptr<CreditCard>* imported_credit_card) {
+ return form_data_importer_->ImportCreditCard(form, should_return_local_card,
+ imported_credit_card);
}
void SubmitFormAndExpectImportedCardWithData(const FormData& form,
@@ -193,12 +184,8 @@ class FormDataImporterTestBase {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(ImportCreditCard(
- form_structure, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
personal_data_manager_->SaveImportedCreditCard(*imported_credit_card);
base::RunLoop run_loop;
@@ -227,9 +214,6 @@ class FormDataImporterTestBase {
base::ScopedTempDir temp_dir_;
base::MessageLoopForUI message_loop_;
std::unique_ptr<PrefService> prefs_;
- std::unique_ptr<AccountTrackerService> account_tracker_;
- std::unique_ptr<FakeSigninManagerBase> signin_manager_;
- std::unique_ptr<TestSigninClient> signin_client_;
scoped_refptr<AutofillWebDataService> autofill_database_service_;
scoped_refptr<WebDatabaseService> web_database_;
AutofillTable* autofill_table_; // weak ref
@@ -249,14 +233,6 @@ class FormDataImporterTest : public FormDataImporterTestBase,
new WebDatabaseService(path, base::ThreadTaskRunnerHandle::Get(),
base::ThreadTaskRunnerHandle::Get());
- // Set up account tracker.
- signin_client_.reset(new TestSigninClient(prefs_.get()));
- account_tracker_.reset(new AccountTrackerService());
- account_tracker_->Initialize(signin_client_.get());
- signin_manager_.reset(new FakeSigninManagerBase(signin_client_.get(),
- account_tracker_.get()));
- signin_manager_->Initialize(prefs_.get());
-
// Hacky: hold onto a pointer but pass ownership.
autofill_table_ = new AutofillTable;
web_database_->AddTable(std::unique_ptr<WebDatabaseTable>(autofill_table_));
@@ -285,13 +261,6 @@ class FormDataImporterTest : public FormDataImporterTestBase,
void TearDown() override {
// Order of destruction is important as AutofillManager relies on
// PersonalDataManager to be around when it gets destroyed.
- signin_manager_->Shutdown();
- signin_manager_.reset();
-
- account_tracker_->Shutdown();
- account_tracker_.reset();
- signin_client_.reset();
-
test::ReenableSystemServices();
OSCryptMocker::TearDown();
}
@@ -1393,12 +1362,12 @@ TEST_F(FormDataImporterTest, ImportCreditCard_Valid) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(ImportCreditCard(
- form_structure, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ base::HistogramTester histogram_tester;
+ EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.SubmittedCardState",
+ AutofillMetrics::HAS_CARD_NUMBER_AND_EXPIRATION_DATE, 1);
personal_data_manager_->SaveImportedCreditCard(*imported_credit_card);
WaitForOnPersonalDataChanged();
@@ -1412,8 +1381,8 @@ TEST_F(FormDataImporterTest, ImportCreditCard_Valid) {
EXPECT_EQ(0, expected.Compare(*results[0]));
}
-// Tests that an invalid credit card is not extracted.
-TEST_F(FormDataImporterTest, ImportCreditCard_Invalid) {
+// Tests that an invalid credit card number is not extracted.
+TEST_F(FormDataImporterTest, ImportCreditCard_InvalidCardNumber) {
FormData form;
AddFullCreditCardForm(&form, "Jim Johansen", "1000000000000000", "02",
"2999");
@@ -1421,11 +1390,34 @@ TEST_F(FormDataImporterTest, ImportCreditCard_Invalid) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_FALSE(ImportCreditCard(
- form_structure, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ base::HistogramTester histogram_tester;
+ EXPECT_FALSE(ImportCreditCard(form_structure, false, &imported_credit_card));
+ ASSERT_FALSE(imported_credit_card);
+ histogram_tester.ExpectUniqueSample("Autofill.SubmittedCardState",
+ AutofillMetrics::HAS_EXPIRATION_DATE_ONLY,
+ 1);
+
+ // Since no refresh is expected, reload the data from the database to make
+ // sure no changes were written out.
+ ResetPersonalDataManager(USER_MODE_NORMAL);
+
+ ASSERT_EQ(0U, personal_data_manager_->GetCreditCards().size());
+}
+
+// Tests that an invalid credit card expiration is not extracted.
+TEST_F(FormDataImporterTest, ImportCreditCard_InvalidExpiryDate) {
+ FormData form;
+ AddFullCreditCardForm(&form, "Smalls Biggie", "4111-1111-1111-1111", "0",
+ "2999");
+
+ FormStructure form_structure(form);
+ form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
+ std::unique_ptr<CreditCard> imported_credit_card;
+ base::HistogramTester histogram_tester;
+ EXPECT_FALSE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_FALSE(imported_credit_card);
+ histogram_tester.ExpectUniqueSample("Autofill.SubmittedCardState",
+ AutofillMetrics::HAS_CARD_NUMBER_ONLY, 1);
// Since no refresh is expected, reload the data from the database to make
// sure no changes were written out.
@@ -1457,12 +1449,12 @@ TEST_F(FormDataImporterTest, ImportCreditCard_MonthSelectInvalidText) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(ImportCreditCard(
- form_structure, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ base::HistogramTester histogram_tester;
+ EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.SubmittedCardState",
+ AutofillMetrics::HAS_CARD_NUMBER_AND_EXPIRATION_DATE, 1);
personal_data_manager_->SaveImportedCreditCard(*imported_credit_card);
WaitForOnPersonalDataChanged();
@@ -1486,12 +1478,8 @@ TEST_F(FormDataImporterTest, ImportCreditCard_TwoValidCards) {
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(ImportCreditCard(
- form_structure1, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
personal_data_manager_->SaveImportedCreditCard(*imported_credit_card);
WaitForOnPersonalDataChanged();
@@ -1511,11 +1499,8 @@ TEST_F(FormDataImporterTest, ImportCreditCard_TwoValidCards) {
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card2;
- EXPECT_TRUE(ImportCreditCard(
- form_structure2, false, &imported_credit_card2,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure2, false, &imported_credit_card2));
ASSERT_TRUE(imported_credit_card2);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
personal_data_manager_->SaveImportedCreditCard(*imported_credit_card2);
WaitForOnPersonalDataChanged();
@@ -1606,15 +1591,9 @@ TEST_F(FormDataImporterTest, ImportCreditCard_2DigitYear) {
}
// Tests that a credit card is not extracted because the
-// kAutofillOfferLocalSaveIfServerCardManuallyEntered feature flag is off even
-// though the card matches a masked server card.
+// card matches a masked server card.
TEST_F(FormDataImporterTest,
- ImportCreditCard_DuplicateServerCards_MaskedCard_ExperimentOff) {
- // Ensure feature flag is off.
- base::test::ScopedFeatureList scoped_feature_list_;
- scoped_feature_list_.InitAndDisableFeature(
- kAutofillOfferLocalSaveIfServerCardManuallyEntered);
-
+ ImportCreditCard_DuplicateServerCards_MaskedCard_DontExtract) {
// Add a masked server card.
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
@@ -1638,57 +1617,10 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_FALSE(ImportCreditCard(
- form_structure, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_FALSE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_FALSE(imported_credit_card);
}
-// Tests that a credit card is extracted because it matches a masked server card
-// and the kAutofillOfferLocalSaveIfServerCardManuallyEntered feature flag is
-// enabled.
-TEST_F(FormDataImporterTest,
- ImportCreditCard_DuplicateServerCards_MaskedCard_ExperimentOn) {
- // Enable feature flag.
- base::test::ScopedFeatureList scoped_feature_list_;
- scoped_feature_list_.InitAndEnableFeature(
- kAutofillOfferLocalSaveIfServerCardManuallyEntered);
-
- // Add a masked server card.
- std::vector<CreditCard> server_cards;
- server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
- test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
- "1111" /* Visa */, "01", "2999", "");
- server_cards.back().SetNetworkForMaskedCard(kVisaCard);
- test::SetServerCreditCards(autofill_table_, server_cards);
-
- // Make sure everything is set up correctly.
- personal_data_manager_->Refresh();
- WaitForOnPersonalDataChanged();
- EXPECT_EQ(1U, personal_data_manager_->GetCreditCards().size());
-
- // Type the same data as the masked card into a form.
- FormData form;
- AddFullCreditCardForm(&form, "John Dillinger", "4111111111111111", "01",
- "2999");
-
- // The card should be offered to be saved locally because it matches the
- // masked server card.
- FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
- std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(ImportCreditCard(
- form_structure, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
- ASSERT_TRUE(imported_credit_card);
- EXPECT_TRUE(imported_credit_card_matches_masked_server_credit_card);
- personal_data_manager_->SaveImportedCreditCard(*imported_credit_card);
-
- WaitForOnPersonalDataChanged();
-}
-
// Tests that a credit card is not extracted because it matches a full server
// card.
TEST_F(FormDataImporterTest, ImportCreditCard_DuplicateServerCards_FullCard) {
@@ -1714,10 +1646,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_DuplicateServerCards_FullCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_FALSE(ImportCreditCard(
- form_structure, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_FALSE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_FALSE(imported_credit_card);
}
@@ -1730,12 +1659,8 @@ TEST_F(FormDataImporterTest, ImportCreditCard_SameCreditCardWithConflict) {
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(ImportCreditCard(
- form_structure1, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
personal_data_manager_->SaveImportedCreditCard(*imported_credit_card);
WaitForOnPersonalDataChanged();
@@ -1757,9 +1682,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_SameCreditCardWithConflict) {
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card2;
- EXPECT_TRUE(ImportCreditCard(
- form_structure2, false, &imported_credit_card2,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure2, false, &imported_credit_card2));
EXPECT_FALSE(imported_credit_card2);
WaitForOnPersonalDataChanged();
@@ -1784,12 +1707,8 @@ TEST_F(FormDataImporterTest, ImportCreditCard_ShouldReturnLocalCard) {
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(ImportCreditCard(
- form_structure1, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
personal_data_manager_->SaveImportedCreditCard(*imported_credit_card);
WaitForOnPersonalDataChanged();
@@ -1811,13 +1730,11 @@ TEST_F(FormDataImporterTest, ImportCreditCard_ShouldReturnLocalCard) {
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card2;
- EXPECT_TRUE(ImportCreditCard(
- form_structure2,
- /* should_return_local_card= */ true, &imported_credit_card2,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure2,
+ /* should_return_local_card= */ true,
+ &imported_credit_card2));
// The local card is returned after an update.
EXPECT_TRUE(imported_credit_card2);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
WaitForOnPersonalDataChanged();
@@ -1841,12 +1758,8 @@ TEST_F(FormDataImporterTest, ImportCreditCard_EmptyCardWithConflict) {
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(ImportCreditCard(
- form_structure1, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
personal_data_manager_->SaveImportedCreditCard(*imported_credit_card);
WaitForOnPersonalDataChanged();
@@ -1867,9 +1780,8 @@ TEST_F(FormDataImporterTest, ImportCreditCard_EmptyCardWithConflict) {
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card2;
- EXPECT_FALSE(ImportCreditCard(
- form_structure2, false, &imported_credit_card2,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_FALSE(
+ ImportCreditCard(form_structure2, false, &imported_credit_card2));
EXPECT_FALSE(imported_credit_card2);
// Since no refresh is expected, reload the data from the database to make
@@ -1895,12 +1807,8 @@ TEST_F(FormDataImporterTest, ImportCreditCard_MissingInfoInNew) {
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(ImportCreditCard(
- form_structure1, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
personal_data_manager_->SaveImportedCreditCard(*imported_credit_card);
WaitForOnPersonalDataChanged();
@@ -1922,9 +1830,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_MissingInfoInNew) {
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card2;
- EXPECT_TRUE(ImportCreditCard(
- form_structure2, false, &imported_credit_card2,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure2, false, &imported_credit_card2));
EXPECT_FALSE(imported_credit_card2);
// Since no refresh is expected, reload the data from the database to make
@@ -1949,9 +1855,8 @@ TEST_F(FormDataImporterTest, ImportCreditCard_MissingInfoInNew) {
FormStructure form_structure3(form3);
form_structure3.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card3;
- EXPECT_FALSE(ImportCreditCard(
- form_structure3, false, &imported_credit_card3,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_FALSE(
+ ImportCreditCard(form_structure3, false, &imported_credit_card3));
ASSERT_FALSE(imported_credit_card3);
// Since no refresh is expected, reload the data from the database to make
@@ -1992,10 +1897,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_MissingInfoInOld) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(ImportCreditCard(
- form_structure, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
EXPECT_FALSE(imported_credit_card);
WaitForOnPersonalDataChanged();
@@ -2036,10 +1938,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_SameCardWithSeparators) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(ImportCreditCard(
- form_structure, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
EXPECT_FALSE(imported_credit_card);
// Since no refresh is expected, reload the data from the database to make
@@ -2079,10 +1978,7 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(ImportCreditCard(
- form_structure, false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_FALSE(imported_credit_card);
// Since no refresh is expected, reload the data from the database to make
@@ -2130,14 +2026,11 @@ TEST_F(FormDataImporterTest, ImportFormData_OneAddressOneCreditCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure,
/*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
personal_data_manager_->SaveImportedCreditCard(*imported_credit_card);
WaitForOnPersonalDataChanged();
@@ -2211,14 +2104,11 @@ TEST_F(FormDataImporterTest, ImportFormData_TwoAddressesOneCreditCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
// Still returns true because the credit card import was successful.
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
personal_data_manager_->SaveImportedCreditCard(*imported_credit_card);
WaitForOnPersonalDataChanged();
@@ -2266,11 +2156,9 @@ TEST_F(FormDataImporterTest, ImportFormData_OneAddressCreditCardDisabled) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*credit_card_autofill_enabled=*/false,
- /*should_return_local_card=*/false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card));
ASSERT_FALSE(imported_credit_card);
WaitForOnPersonalDataChanged();
@@ -2293,71 +2181,6 @@ TEST_F(FormDataImporterTest, ImportFormData_OneAddressCreditCardDisabled) {
ASSERT_EQ(0U, results_cards.size());
}
-TEST_F(FormDataImporterTest, AllowDuplicateMaskedServerCardIfFlagEnabled) {
- EnableWalletCardImport();
- // Turn on feature flag.
- base::test::ScopedFeatureList scoped_feature_list_;
- scoped_feature_list_.InitAndEnableFeature(
- kAutofillOfferLocalSaveIfServerCardManuallyEntered);
-
- std::vector<CreditCard> server_cards;
- server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
- test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
- "1881" /* Visa */, "01", "2999", "");
- server_cards.back().SetNetworkForMaskedCard(kVisaCard);
-
- server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
- test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
- "378282246310005" /* American Express */, "04",
- "2999", "");
-
- test::SetServerCreditCards(autofill_table_, server_cards);
-
- // Make sure everything is set up correctly.
- personal_data_manager_->Refresh();
- WaitForOnPersonalDataChanged();
- EXPECT_EQ(2U, personal_data_manager_->GetCreditCards().size());
-
- // A valid credit card form. A user re-enters one of their masked cards.
- // We should offer to save locally so that user can fill future credit card
- // forms without unmasking.
- FormData form;
- FormFieldData field;
- test::CreateTestFormField("Name on card:", "name_on_card", "John Dillinger",
- "text", &field);
- form.fields.push_back(field);
- test::CreateTestFormField("Card Number:", "card_number", "4012888888881881",
- "text", &field);
- form.fields.push_back(field);
- test::CreateTestFormField("Exp Month:", "exp_month", "01", "text", &field);
- form.fields.push_back(field);
- test::CreateTestFormField("Exp Year:", "exp_year", "2999", "text", &field);
- form.fields.push_back(field);
-
- FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
- std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
- EXPECT_TRUE(form_data_importer_->ImportFormData(
- form_structure, /*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
- ASSERT_TRUE(imported_credit_card);
- EXPECT_TRUE(imported_credit_card_matches_masked_server_credit_card);
- personal_data_manager_->SaveImportedCreditCard(*imported_credit_card);
-
- WaitForOnPersonalDataChanged();
-
- CreditCard local_card(base::GenerateGUID(), "https://www.example.com");
- test::SetCreditCardInfo(&local_card, "John Dillinger", "4012888888881881",
- "01", "2999", "");
- const std::vector<CreditCard*>& results =
- personal_data_manager_->GetLocalCreditCards();
- ASSERT_EQ(1U, results.size());
- EXPECT_EQ(0, local_card.Compare(*results[0]));
- EXPECT_EQ(3U, personal_data_manager_->GetCreditCards().size());
-}
-
TEST_F(FormDataImporterTest, DontDuplicateMaskedServerCard) {
EnableWalletCardImport();
@@ -2380,8 +2203,7 @@ TEST_F(FormDataImporterTest, DontDuplicateMaskedServerCard) {
EXPECT_EQ(2U, personal_data_manager_->GetCreditCards().size());
// A valid credit card form. A user re-enters one of their masked cards.
- // We should not offer to save locally because the
- // AutofillOfferLocalSaveIfServerCardManuallyEntered flag is not enabled.
+ // We should not offer to save locally.
FormData form;
FormFieldData field;
test::CreateTestFormField("Name on card:", "name_on_card", "John Dillinger",
@@ -2398,13 +2220,10 @@ TEST_F(FormDataImporterTest, DontDuplicateMaskedServerCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card));
ASSERT_FALSE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
}
TEST_F(FormDataImporterTest, DontDuplicateFullServerCard) {
@@ -2447,13 +2266,10 @@ TEST_F(FormDataImporterTest, DontDuplicateFullServerCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card));
EXPECT_FALSE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
}
TEST_F(FormDataImporterTest,
@@ -2491,13 +2307,10 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card));
EXPECT_FALSE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
histogram_tester.ExpectUniqueSample(
"Autofill.SubmittedServerCardExpirationStatus",
AutofillMetrics::FULL_SERVER_CARD_EXPIRATION_DATE_MATCHED, 1);
@@ -2539,13 +2352,10 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card));
EXPECT_FALSE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
histogram_tester.ExpectUniqueSample(
"Autofill.SubmittedServerCardExpirationStatus",
AutofillMetrics::FULL_SERVER_CARD_EXPIRATION_DATE_DID_NOT_MATCH, 1);
@@ -2587,13 +2397,10 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card));
EXPECT_FALSE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
histogram_tester.ExpectUniqueSample(
"Autofill.SubmittedServerCardExpirationStatus",
AutofillMetrics::MASKED_SERVER_CARD_EXPIRATION_DATE_MATCHED, 1);
@@ -2636,13 +2443,10 @@ TEST_F(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
std::unique_ptr<CreditCard> imported_credit_card;
- bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card,
- &imported_credit_card_matches_masked_server_credit_card));
+ /*should_return_local_card=*/false, &imported_credit_card));
EXPECT_FALSE(imported_credit_card);
- EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
histogram_tester.ExpectUniqueSample(
"Autofill.SubmittedServerCardExpirationStatus",
AutofillMetrics::MASKED_SERVER_CARD_EXPIRATION_DATE_DID_NOT_MATCH, 1);
diff --git a/chromium/components/autofill/core/browser/form_field.h b/chromium/components/autofill/core/browser/form_field.h
index 3ec73b4cf3a..c721f4bed83 100644
--- a/chromium/components/autofill/core/browser/form_field.h
+++ b/chromium/components/autofill/core/browser/form_field.h
@@ -74,9 +74,9 @@ class FormField {
// Parses the stream of fields in |scanner| with regular expression |pattern|
// as specified in the |match_type| bit field (see |MatchType|). If |match|
- // is non-NULL and the pattern matches, the matched field is returned.
- // A |true| result is returned in the case of a successful match, false
- // otherwise.
+ // is non-NULL and the pattern matches, |match| will be set to the matched
+ // field, and the scanner would advance by one step. A |true| result is
+ // returned in the case of a successful match, false otherwise.
static bool ParseFieldSpecifics(AutofillScanner* scanner,
const base::string16& pattern,
int match_type,
diff --git a/chromium/components/autofill/core/browser/form_structure.cc b/chromium/components/autofill/core/browser/form_structure.cc
index ab0c22def95..3ac2d1a45a7 100644
--- a/chromium/components/autofill/core/browser/form_structure.cc
+++ b/chromium/components/autofill/core/browser/form_structure.cc
@@ -680,8 +680,10 @@ bool FormStructure::ShouldBeUploaded() const {
ShouldBeParsed();
}
-void FormStructure::UpdateFromCache(const FormStructure& cached_form,
- const bool apply_is_autofilled) {
+void FormStructure::RetrieveFromCache(
+ const FormStructure& cached_form,
+ const bool apply_is_autofilled,
+ const bool only_server_and_autofill_state) {
// Map from field signatures to cached fields.
std::map<base::string16, const AutofillField*> cached_fields;
for (size_t i = 0; i < cached_form.field_count(); ++i) {
@@ -691,28 +693,29 @@ void FormStructure::UpdateFromCache(const FormStructure& cached_form,
for (auto& field : *this) {
const auto& cached_field = cached_fields.find(field->unique_name());
if (cached_field != cached_fields.end()) {
+ if (!only_server_and_autofill_state) {
+ // Transfer attributes of the cached AutofillField to the newly created
+ // AutofillField.
+ field->set_heuristic_type(cached_field->second->heuristic_type());
+ field->SetHtmlType(cached_field->second->html_type(),
+ cached_field->second->html_mode());
+ field->set_section(cached_field->second->section());
+ field->set_only_fill_when_focused(
+ cached_field->second->only_fill_when_focused());
+ }
+ if (apply_is_autofilled) {
+ field->is_autofilled = cached_field->second->is_autofilled;
+ }
if (field->form_control_type != "select-one" &&
field->value == cached_field->second->value) {
// From the perspective of learning user data, text fields containing
// default values are equivalent to empty fields.
field->value = base::string16();
}
-
- // Transfer attributes of the cached AutofillField to the newly created
- // AutofillField.
- field->set_heuristic_type(cached_field->second->heuristic_type());
field->set_overall_server_type(
cached_field->second->overall_server_type());
- field->SetHtmlType(cached_field->second->html_type(),
- cached_field->second->html_mode());
- if (apply_is_autofilled) {
- field->is_autofilled = cached_field->second->is_autofilled;
- }
field->set_previously_autofilled(
cached_field->second->previously_autofilled());
- field->set_section(cached_field->second->section());
- field->set_only_fill_when_focused(
- cached_field->second->only_fill_when_focused());
}
}
@@ -1330,6 +1333,8 @@ void FormStructure::IdentifySections(bool has_author_specified_sections) {
std::set<ServerFieldType> seen_types;
ServerFieldType previous_type = UNKNOWN_TYPE;
+ bool is_hidden_section = false;
+ base::string16 last_visible_section;
for (const auto& field : fields_) {
const ServerFieldType current_type = field->Type().GetStorableType();
// All credit card fields belong to the same section that's different
@@ -1347,13 +1352,26 @@ void FormStructure::IdentifySections(bool has_author_specified_sections) {
if (AutofillType(current_type).group() == PHONE_HOME)
already_saw_current_type = false;
- // Ignore non-focusable field and presentation role fields while inferring
- // boundaries between sections.
bool ignored_field =
!field->is_focusable ||
field->role == FormFieldData::ROLE_ATTRIBUTE_PRESENTATION;
- if (ignored_field)
+
+ // This is the first visible field after a hidden section. Consider it as
+ // the continuation of the last visible section.
+ if (!ignored_field && is_hidden_section) {
+ current_section = last_visible_section;
+ }
+
+ // Start a new section by an ignored field, only if the next field is also
+ // already seen.
+ size_t field_index = &field - &fields_[0];
+ if (ignored_field &&
+ (is_hidden_section ||
+ !((field_index + 1) < fields_.size() &&
+ seen_types.count(
+ fields_[field_index + 1]->Type().GetStorableType()) > 0))) {
already_saw_current_type = false;
+ }
// Some forms have adjacent fields of the same type. Two common examples:
// * Forms with two email fields, where the second is meant to "confirm"
@@ -1368,8 +1386,17 @@ void FormStructure::IdentifySections(bool has_author_specified_sections) {
already_saw_current_type = false;
if (current_type != UNKNOWN_TYPE && already_saw_current_type) {
- // We reached the end of a section, so start a new section.
- seen_types.clear();
+ // Keep track of seen_types if the new section is hidden. The next
+ // visible section might be the continuation of the previous visible
+ // section.
+ if (ignored_field) {
+ is_hidden_section = true;
+ last_visible_section = current_section;
+ }
+ if (!is_hidden_section)
+ seen_types.clear();
+
+ // The end of a section, so start a new section.
current_section = field->unique_name();
}
@@ -1383,6 +1410,7 @@ void FormStructure::IdentifySections(bool has_author_specified_sections) {
if (!ignored_field) {
seen_types.insert(current_type);
previous_type = current_type;
+ is_hidden_section = false;
}
field->set_section(base::UTF16ToUTF8(current_section));
diff --git a/chromium/components/autofill/core/browser/form_structure.h b/chromium/components/autofill/core/browser/form_structure.h
index eb576f3b55c..b8783c4dcce 100644
--- a/chromium/components/autofill/core/browser/form_structure.h
+++ b/chromium/components/autofill/core/browser/form_structure.h
@@ -121,8 +121,9 @@ class FormStructure {
bool ShouldBeUploaded() const;
// Sets the field types to be those set for |cached_form|.
- void UpdateFromCache(const FormStructure& cached_form,
- const bool apply_is_autofilled);
+ void RetrieveFromCache(const FormStructure& cached_form,
+ const bool apply_is_autofilled,
+ const bool only_server_and_autofill_state);
// Logs quality metrics for |this|, which should be a user-submitted form.
// This method should only be called after the possible field types have been
diff --git a/chromium/components/autofill/core/browser/form_structure_unittest.cc b/chromium/components/autofill/core/browser/form_structure_unittest.cc
index 24217d68a35..07f8b818f5f 100644
--- a/chromium/components/autofill/core/browser/form_structure_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_structure_unittest.cc
@@ -129,7 +129,7 @@ class FormStructureTest : public testing::Test {
void EnableAutofillMetadataFieldTrial() {
field_trial_list_.reset();
field_trial_list_.reset(new base::FieldTrialList(
- std::make_unique<metrics::SHA1EntropyProvider>("foo")));
+ std::make_unique<variations::SHA1EntropyProvider>("foo")));
field_trial_ = base::FieldTrialList::CreateFieldTrial(
"AutofillFieldMetadata", "Enabled");
field_trial_->group();
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 6b2269fb013..3f95ca3a104 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
@@ -76,7 +76,7 @@ class FullCardRequestTest : public testing::Test,
autofill_client_.SetPrefs(std::move(pref_service));
payments_client_ = std::make_unique<PaymentsClient>(
request_context_.get(), autofill_client_.GetPrefs(),
- autofill_client_.GetIdentityProvider(), this, nullptr);
+ autofill_client_.GetIdentityManager(), this, nullptr);
request_ = std::make_unique<FullCardRequest>(
&autofill_client_, payments_client_.get(), &personal_data_);
// Silence the warning from PaymentsClient about matching sync and Payments
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.cc b/chromium/components/autofill/core/browser/payments/payments_client.cc
index 719ad557bbd..f65c8214c22 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client.cc
@@ -24,13 +24,13 @@
#include "components/autofill/core/browser/payments/payments_request.h"
#include "components/autofill/core/browser/payments/payments_service_url.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
-#include "google_apis/gaia/identity_provider.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/http/http_status_code.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/identity/public/cpp/identity_manager.h"
namespace autofill {
namespace payments {
@@ -56,7 +56,7 @@ const char kUploadCardRequestFormatWithoutCvc[] =
"requestContentType=application/json; charset=utf-8&request=%s"
"&s7e_1_pan=%s";
-const char kTokenServiceConsumerId[] = "wallet_client";
+const char kTokenFetchId[] = "wallet_client";
const char kPaymentsOAuth2Scope[] =
"https://www.googleapis.com/auth/wallet.chrome";
@@ -456,13 +456,12 @@ PaymentsClient::UploadRequestDetails::~UploadRequestDetails() {}
PaymentsClient::PaymentsClient(net::URLRequestContextGetter* context_getter,
PrefService* pref_service,
- IdentityProvider* identity_provider,
+ identity::IdentityManager* identity_manager,
PaymentsClientUnmaskDelegate* unmask_delegate,
PaymentsClientSaveDelegate* save_delegate)
- : OAuth2TokenService::Consumer(kTokenServiceConsumerId),
- context_getter_(context_getter),
+ : context_getter_(context_getter),
pref_service_(pref_service),
- identity_provider_(identity_provider),
+ identity_manager_(identity_manager),
unmask_delegate_(unmask_delegate),
save_delegate_(save_delegate),
has_retried_authorization_(false),
@@ -581,7 +580,7 @@ void PaymentsClient::InitializeUrlFetcher() {
void PaymentsClient::CancelRequest() {
request_.reset();
url_fetcher_.reset();
- access_token_request_.reset();
+ token_fetcher_.reset();
access_token_.clear();
has_retried_authorization_ = false;
}
@@ -654,46 +653,52 @@ void PaymentsClient::OnURLFetchComplete(const net::URLFetcher* source) {
request_->RespondToDelegate(result);
}
-void PaymentsClient::OnGetTokenSuccess(
- const OAuth2TokenService::Request* request,
- const std::string& access_token,
- const base::Time& expiration_time) {
- DCHECK_EQ(request, access_token_request_.get());
+void PaymentsClient::AccessTokenFetchFinished(
+ const GoogleServiceAuthError& error,
+ const std::string& access_token) {
+ // Delete the fetcher only after we leave this method (which is called from
+ // the fetcher itself).
+ DCHECK(token_fetcher_);
+ std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher>
+ token_fetcher_deleter(std::move(token_fetcher_));
+
+ if (error.state() != GoogleServiceAuthError::NONE) {
+ AccessTokenError(error);
+ return;
+ }
+
access_token_ = access_token;
if (url_fetcher_)
SetOAuth2TokenAndStartRequest();
-
- access_token_request_.reset();
}
-void PaymentsClient::OnGetTokenFailure(
- const OAuth2TokenService::Request* request,
- const GoogleServiceAuthError& error) {
- DCHECK_EQ(request, access_token_request_.get());
+void PaymentsClient::AccessTokenError(const GoogleServiceAuthError& error) {
VLOG(1) << "Unhandled OAuth2 error: " << error.ToString();
if (url_fetcher_) {
url_fetcher_.reset();
request_->RespondToDelegate(AutofillClient::PERMANENT_FAILURE);
}
- access_token_request_.reset();
}
void PaymentsClient::StartTokenFetch(bool invalidate_old) {
// We're still waiting for the last request to come back.
- if (!invalidate_old && access_token_request_)
+ if (!invalidate_old && token_fetcher_)
return;
OAuth2TokenService::ScopeSet payments_scopes;
payments_scopes.insert(kPaymentsOAuth2Scope);
if (invalidate_old) {
DCHECK(!access_token_.empty());
- identity_provider_->GetTokenService()->InvalidateAccessToken(
- identity_provider_->GetActiveAccountId(), payments_scopes,
+ identity_manager_->RemoveAccessTokenFromCache(
+ identity_manager_->GetPrimaryAccountInfo(), payments_scopes,
access_token_);
}
access_token_.clear();
- access_token_request_ = identity_provider_->GetTokenService()->StartRequest(
- identity_provider_->GetActiveAccountId(), payments_scopes, this);
+ token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForPrimaryAccount(
+ kTokenFetchId, payments_scopes,
+ base::BindOnce(&PaymentsClient::AccessTokenFetchFinished,
+ base::Unretained(this)),
+ identity::PrimaryAccountAccessTokenFetcher::Mode::kImmediate);
}
void PaymentsClient::SetOAuth2TokenAndStartRequest() {
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.h b/chromium/components/autofill/core/browser/payments/payments_client.h
index 5b10f216341..f097be903ab 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.h
+++ b/chromium/components/autofill/core/browser/payments/payments_client.h
@@ -13,10 +13,13 @@
#include "components/autofill/core/browser/card_unmask_delegate.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/prefs/pref_service.h"
-#include "google_apis/gaia/oauth2_token_service.h"
+#include "google_apis/gaia/google_service_auth_error.h"
#include "net/url_request/url_fetcher_delegate.h"
-class IdentityProvider;
+namespace identity {
+class IdentityManager;
+class PrimaryAccountAccessTokenFetcher;
+} // namespace identity
namespace net {
class URLFetcher;
@@ -59,8 +62,7 @@ class PaymentsClientSaveDelegate {
// request will cancel a pending request.
// Tests are located in
// src/components/autofill/content/browser/payments/payments_client_unittest.cc.
-class PaymentsClient : public net::URLFetcherDelegate,
- public OAuth2TokenService::Consumer {
+class PaymentsClient : public net::URLFetcherDelegate {
public:
// The names of the fields used to send non-location elements as part of an
// address. Used in the implementation and in tests which verify that these
@@ -100,11 +102,11 @@ class PaymentsClient : public net::URLFetcherDelegate,
// |context_getter| is reference counted so it has no lifetime or ownership
// requirements. |pref_service| is used to get the registered preference
- // value, |identity_provider|, |unmask_delegate| and |save_delegate| must all
+ // value, |identity_manager|, |unmask_delegate| and |save_delegate| must all
// outlive |this|. Either delegate might be nullptr.
PaymentsClient(net::URLRequestContextGetter* context_getter,
PrefService* pref_service,
- IdentityProvider* identity_provider,
+ identity::IdentityManager* identity_manager,
PaymentsClientUnmaskDelegate* unmask_delegate,
PaymentsClientSaveDelegate* save_delegate);
@@ -162,12 +164,12 @@ class PaymentsClient : public net::URLFetcherDelegate,
// net::URLFetcherDelegate:
void OnURLFetchComplete(const net::URLFetcher* source) override;
- // OAuth2TokenService::Consumer implementation.
- void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
- const std::string& access_token,
- const base::Time& expiration_time) override;
- void OnGetTokenFailure(const OAuth2TokenService::Request* request,
- const GoogleServiceAuthError& error) override;
+ // Callback that handles a completed access token request.
+ void AccessTokenFetchFinished(const GoogleServiceAuthError& error,
+ const std::string& access_token);
+
+ // Handles a completed access token request in the case of failure.
+ void AccessTokenError(const GoogleServiceAuthError& error);
// Creates |url_fetcher_| based on the current state of |request_|.
void InitializeUrlFetcher();
@@ -184,7 +186,7 @@ class PaymentsClient : public net::URLFetcherDelegate,
// The pref service for this client.
PrefService* const pref_service_;
- IdentityProvider* const identity_provider_;
+ identity::IdentityManager* const identity_manager_;
// Delegates for the results of the various requests to Payments. Both must
// outlive |this|.
@@ -197,8 +199,8 @@ class PaymentsClient : public net::URLFetcherDelegate,
// The fetcher being used to issue the current request.
std::unique_ptr<net::URLFetcher> url_fetcher_;
- // The current OAuth2 token request object.
- std::unique_ptr<OAuth2TokenService::Request> access_token_request_;
+ // The current OAuth2 token fetcher.
+ std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher> token_fetcher_;
// The OAuth2 token, or empty if not fetched.
std::string access_token_;
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 dcb3d01cf5e..50ef8b744b2 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
@@ -20,10 +20,9 @@
#include "components/autofill/core/common/autofill_switches.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
-#include "google_apis/gaia/fake_identity_provider.h"
-#include "google_apis/gaia/fake_oauth2_token_service.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_test_util.h"
+#include "services/identity/public/cpp/identity_test_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace autofill {
@@ -62,11 +61,10 @@ class PaymentsClientTest : public testing::Test,
request_context_ = new net::TestURLRequestContextGetter(
base::ThreadTaskRunnerHandle::Get());
- token_service_.reset(new FakeOAuth2TokenService());
- identity_provider_.reset(new FakeIdentityProvider(token_service_.get()));
TestingPrefServiceSimple pref_service_;
client_.reset(new PaymentsClient(request_context_.get(), &pref_service_,
- identity_provider_.get(), this, this));
+ identity_test_env_.identity_manager(),
+ this, this));
}
void TearDown() override { client_.reset(); }
@@ -110,8 +108,9 @@ class PaymentsClientTest : public testing::Test,
base::test::ScopedFeatureList scoped_feature_list_;
void StartUnmasking() {
- token_service_->AddAccount("example@gmail.com");
- identity_provider_->LogIn("example@gmail.com");
+ if (!identity_test_env_.identity_manager()->HasPrimaryAccount())
+ identity_test_env_.MakePrimaryAccountAvailable("example@gmail.com");
+
PaymentsClient::UnmaskRequestDetails request_details;
request_details.billing_customer_number = 111222333444;
request_details.card = test::GetMaskedServerCard();
@@ -121,16 +120,18 @@ class PaymentsClientTest : public testing::Test,
}
void StartGettingUploadDetails() {
- token_service_->AddAccount("example@gmail.com");
- identity_provider_->LogIn("example@gmail.com");
+ if (!identity_test_env_.identity_manager()->HasPrimaryAccount())
+ identity_test_env_.MakePrimaryAccountAvailable("example@gmail.com");
+
client_->GetUploadDetails(BuildTestProfiles(), kAllDetectableValues,
/*pan_first_six=*/"411111",
std::vector<const char*>(), "language-LOCALE");
}
void StartUploading(bool include_cvc) {
- token_service_->AddAccount("example@gmail.com");
- identity_provider_->LogIn("example@gmail.com");
+ if (!identity_test_env_.identity_manager()->HasPrimaryAccount())
+ identity_test_env_.MakePrimaryAccountAvailable("example@gmail.com");
+
PaymentsClient::UploadRequestDetails request_details;
request_details.billing_customer_number = 111222333444;
request_details.card = test::GetCreditCard();
@@ -148,8 +149,8 @@ class PaymentsClientTest : public testing::Test,
}
void IssueOAuthToken() {
- token_service_->IssueAllTokensForAccount(
- "example@gmail.com", "totally_real_token",
+ identity_test_env_.WaitForAccessTokenRequestAndRespondWithToken(
+ "totally_real_token",
base::Time::Now() + base::TimeDelta::FromDays(10));
// Verify the auth header.
@@ -180,9 +181,8 @@ class PaymentsClientTest : public testing::Test,
base::test::ScopedTaskEnvironment scoped_task_environment_;
net::TestURLFetcherFactory factory_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_;
- std::unique_ptr<FakeOAuth2TokenService> token_service_;
- std::unique_ptr<FakeIdentityProvider> identity_provider_;
std::unique_ptr<PaymentsClient> client_;
+ identity::IdentityTestEnvironment identity_test_env_;
private:
DISALLOW_COPY_AND_ASSIGN(PaymentsClientTest);
@@ -220,8 +220,7 @@ class PaymentsClientTest : public testing::Test,
TEST_F(PaymentsClientTest, OAuthError) {
StartUnmasking();
- token_service_->IssueErrorForAllPendingRequestsForAccount(
- "example@gmail.com",
+ identity_test_env_.WaitForAccessTokenRequestAndRespondWithError(
GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
EXPECT_EQ(AutofillClient::PERMANENT_FAILURE, result_);
EXPECT_TRUE(real_pan_.empty());
@@ -494,7 +493,10 @@ TEST_F(PaymentsClientTest, ReauthNeeded) {
{
StartUnmasking();
- IssueOAuthToken();
+ // NOTE: Don't issue an access token here: the issuing of an access token
+ // first waits for the access token request to be received, but here there
+ // should be no access token request because PaymentsClient should reuse the
+ // access token from the previous request.
ReturnResponse(net::HTTP_UNAUTHORIZED, "");
// No response yet.
EXPECT_EQ(AutofillClient::NONE, result_);
diff --git a/chromium/components/autofill/core/browser/payments/test_payments_client.cc b/chromium/components/autofill/core/browser/payments/test_payments_client.cc
index c8d5be1ded6..845b84d895d 100644
--- a/chromium/components/autofill/core/browser/payments/test_payments_client.cc
+++ b/chromium/components/autofill/core/browser/payments/test_payments_client.cc
@@ -12,12 +12,12 @@ namespace payments {
TestPaymentsClient::TestPaymentsClient(
net::URLRequestContextGetter* context_getter,
PrefService* pref_service,
- IdentityProvider* identity_provider,
+ identity::IdentityManager* identity_manager,
payments::PaymentsClientUnmaskDelegate* unmask_delegate,
payments::PaymentsClientSaveDelegate* save_delegate)
: PaymentsClient(context_getter,
pref_service,
- identity_provider,
+ identity_manager,
unmask_delegate,
save_delegate),
save_delegate_(save_delegate) {}
diff --git a/chromium/components/autofill/core/browser/payments/test_payments_client.h b/chromium/components/autofill/core/browser/payments/test_payments_client.h
index 49b5ddfcf03..f8b0f4a8392 100644
--- a/chromium/components/autofill/core/browser/payments/test_payments_client.h
+++ b/chromium/components/autofill/core/browser/payments/test_payments_client.h
@@ -17,7 +17,7 @@ class TestPaymentsClient : public payments::PaymentsClient {
public:
TestPaymentsClient(net::URLRequestContextGetter* context_getter,
PrefService* pref_service,
- IdentityProvider* identity_provider,
+ identity::IdentityManager* identity_manager,
payments::PaymentsClientUnmaskDelegate* unmask_delegate,
payments::PaymentsClientSaveDelegate* save_delegate);
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.cc b/chromium/components/autofill/core/browser/personal_data_manager.cc
index 327f2cbb0c0..a3a62f5e049 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager.cc
@@ -41,12 +41,10 @@
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/signin_manager.h"
-#include "components/signin/core/browser/signin_pref_names.h"
#include "components/sync/driver/sync_service.h"
#include "components/variations/variations_associated_data.h"
#include "components/version_info/version_info.h"
+#include "services/identity/public/cpp/identity_manager.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h"
@@ -358,22 +356,20 @@ PersonalDataManager::PersonalDataManager(const std::string& app_locale)
pending_server_creditcards_query_(0),
app_locale_(app_locale),
pref_service_(nullptr),
- account_tracker_(nullptr),
+ identity_manager_(nullptr),
is_off_the_record_(false),
has_logged_stored_profile_metrics_(false),
has_logged_stored_credit_card_metrics_(false) {}
void PersonalDataManager::Init(scoped_refptr<AutofillWebDataService> database,
PrefService* pref_service,
- AccountTrackerService* account_tracker,
- SigninManagerBase* signin_manager,
+ identity::IdentityManager* identity_manager,
bool is_off_the_record) {
CountryNames::SetLocaleString(app_locale_);
database_ = database;
SetPrefService(pref_service);
- account_tracker_ = account_tracker;
- signin_manager_ = signin_manager;
+ identity_manager_ = identity_manager;
is_off_the_record_ = is_off_the_record;
if (!is_off_the_record_)
@@ -1992,9 +1988,8 @@ std::string PersonalDataManager::MergeServerAddressesIntoProfiles(
// Wallet addresses don't have an email address, use the one from the
// currently signed-in account.
- std::string account_id = signin_manager_->GetAuthenticatedAccountId();
base::string16 email =
- base::UTF8ToUTF16(account_tracker_->GetAccountInfo(account_id).email);
+ base::UTF8ToUTF16(identity_manager_->GetPrimaryAccountInfo().email);
if (!email.empty())
existing_profiles->back().SetRawInfo(EMAIL_ADDRESS, email);
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.h b/chromium/components/autofill/core/browser/personal_data_manager.h
index ce8f498aa67..178de2fb16b 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/personal_data_manager.h
@@ -29,11 +29,9 @@
#include "components/prefs/pref_member.h"
#include "components/webdata/common/web_data_service_consumer.h"
-class AccountTrackerService;
class Browser;
class PrefService;
class RemoveAutofillTester;
-class SigninManagerBase;
namespace autofill {
class AutofillInteractiveTest;
@@ -46,6 +44,10 @@ void SetProfiles(int, std::vector<autofill::AutofillProfile>*);
void SetCreditCards(int, std::vector<autofill::CreditCard>*);
} // namespace autofill_helper
+namespace identity {
+class IdentityManager;
+}
+
namespace syncer {
class SyncService;
} // namespace syncer
@@ -72,8 +74,7 @@ class PersonalDataManager : public KeyedService,
// context.
void Init(scoped_refptr<AutofillWebDataService> database,
PrefService* pref_service,
- AccountTrackerService* account_tracker,
- SigninManagerBase* signin_manager,
+ identity::IdentityManager* identity_manager,
bool is_off_the_record);
// Called once the sync service is known to be instantiated. Note that it may
@@ -149,7 +150,7 @@ class PersonalDataManager : public KeyedService,
// Updates the use stats and billing address id for the server |credit_card|.
// Looks up the card by server_id.
- void UpdateServerCardMetadata(const CreditCard& credit_card);
+ virtual void UpdateServerCardMetadata(const CreditCard& credit_card);
// Resets the card for |guid| to the masked state.
void ResetFullServerCard(const std::string& guid);
@@ -424,14 +425,6 @@ class PersonalDataManager : public KeyedService,
database_ = database;
}
- void set_account_tracker(AccountTrackerService* account_tracker) {
- account_tracker_ = account_tracker;
- }
-
- void set_signin_manager(SigninManagerBase* signin_manager) {
- signin_manager_ = signin_manager;
- }
-
// The backing database that this PersonalDataManager uses.
scoped_refptr<AutofillWebDataService> database_;
@@ -581,12 +574,8 @@ class PersonalDataManager : public KeyedService,
// The PrefService that this instance uses. Must outlive this instance.
PrefService* pref_service_;
- // The AccountTrackerService that this instance uses. Must outlive this
- // instance.
- AccountTrackerService* account_tracker_;
-
- // The signin manager that this instance uses. Must outlive this instance.
- SigninManagerBase* signin_manager_;
+ // The identity manager that this instance uses. Must outlive this instance.
+ identity::IdentityManager* identity_manager_;
// Whether the user is currently operating in an off-the-record context.
// Default value is 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 c8601ef1a79..36ec3b39174 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -45,13 +45,10 @@
#include "components/autofill/core/common/form_data.h"
#include "components/os_crypt/os_crypt_mocker.h"
#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/fake_signin_manager.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/test_signin_client.h"
#include "components/variations/variations_params_manager.h"
#include "components/webdata/common/web_data_service_base.h"
#include "components/webdata/common/web_database_service.h"
+#include "services/identity/public/cpp/identity_test_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -125,8 +122,7 @@ class PersonalDataManagerTestBase {
personal_data_.reset(new PersonalDataManager("en"));
personal_data_->Init(
scoped_refptr<AutofillWebDataService>(autofill_database_service_),
- prefs_.get(), account_tracker_.get(), signin_manager_.get(),
- is_incognito);
+ prefs_.get(), identity_test_env_.identity_manager(), is_incognito);
personal_data_->AddObserver(&personal_data_observer_);
personal_data_->OnSyncServiceInitialized(nullptr);
@@ -142,8 +138,7 @@ class PersonalDataManagerTestBase {
}
void EnableWalletCardImport() {
- signin_manager_->SetAuthenticatedAccountInfo("12345",
- "syncuser@example.com");
+ identity_test_env_.MakePrimaryAccountAvailable("syncuser@example.com");
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableOfferStoreUnmaskedWalletCards);
}
@@ -252,9 +247,7 @@ class PersonalDataManagerTestBase {
base::ScopedTempDir temp_dir_;
base::MessageLoopForUI message_loop_;
std::unique_ptr<PrefService> prefs_;
- std::unique_ptr<AccountTrackerService> account_tracker_;
- std::unique_ptr<FakeSigninManagerBase> signin_manager_;
- std::unique_ptr<TestSigninClient> signin_client_;
+ identity::IdentityTestEnvironment identity_test_env_;
scoped_refptr<AutofillWebDataService> autofill_database_service_;
scoped_refptr<WebDatabaseService> web_database_;
AutofillTable* autofill_table_; // weak ref
@@ -275,14 +268,6 @@ class PersonalDataManagerTest : public PersonalDataManagerTestBase,
new WebDatabaseService(path, base::ThreadTaskRunnerHandle::Get(),
base::ThreadTaskRunnerHandle::Get());
- // Set up account tracker.
- signin_client_.reset(new TestSigninClient(prefs_.get()));
- account_tracker_.reset(new AccountTrackerService());
- account_tracker_->Initialize(signin_client_.get());
- signin_manager_.reset(new FakeSigninManagerBase(signin_client_.get(),
- account_tracker_.get()));
- signin_manager_->Initialize(prefs_.get());
-
// Hacky: hold onto a pointer but pass ownership.
autofill_table_ = new AutofillTable;
web_database_->AddTable(std::unique_ptr<WebDatabaseTable>(autofill_table_));
@@ -306,13 +291,6 @@ class PersonalDataManagerTest : public PersonalDataManagerTestBase,
void TearDown() override {
// Order of destruction is important as AutofillManager relies on
// PersonalDataManager to be around when it gets destroyed.
- signin_manager_->Shutdown();
- signin_manager_.reset();
-
- account_tracker_->Shutdown();
- account_tracker_.reset();
- signin_client_.reset();
-
test::ReenableSystemServices();
OSCryptMocker::TearDown();
}
@@ -2965,14 +2943,6 @@ class SaveImportedProfileTest
new WebDatabaseService(path, base::ThreadTaskRunnerHandle::Get(),
base::ThreadTaskRunnerHandle::Get());
- // Set up account tracker.
- signin_client_.reset(new TestSigninClient(prefs_.get()));
- account_tracker_.reset(new AccountTrackerService());
- account_tracker_->Initialize(signin_client_.get());
- signin_manager_.reset(new FakeSigninManagerBase(signin_client_.get(),
- account_tracker_.get()));
- signin_manager_->Initialize(prefs_.get());
-
// Hacky: hold onto a pointer but pass ownership.
autofill_table_ = new AutofillTable;
web_database_->AddTable(std::unique_ptr<WebDatabaseTable>(autofill_table_));
@@ -2994,15 +2964,6 @@ class SaveImportedProfileTest
}
void TearDown() override {
- // Order of destruction is important as AutofillManager relies on
- // PersonalDataManager to be around when it gets destroyed.
- signin_manager_->Shutdown();
- signin_manager_.reset();
-
- account_tracker_->Shutdown();
- account_tracker_.reset();
- signin_client_.reset();
-
test::DisableSystemServices(prefs_.get());
OSCryptMocker::TearDown();
}
diff --git a/chromium/components/autofill/core/browser/state_names.h b/chromium/components/autofill/core/browser/state_names.h
index cd71539de6a..ebeab8e1fe5 100644
--- a/chromium/components/autofill/core/browser/state_names.h
+++ b/chromium/components/autofill/core/browser/state_names.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/strings/string16.h"
-
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_STATE_NAMES_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_STATE_NAMES_H_
+#include "base/strings/string16.h"
+
namespace autofill {
namespace state_names {
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.cc b/chromium/components/autofill/core/browser/test_autofill_client.cc
index b72be19d713..62a36f7331b 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_client.cc
@@ -12,8 +12,7 @@
namespace autofill {
TestAutofillClient::TestAutofillClient()
- : token_service_(new FakeOAuth2TokenService()),
- identity_provider_(new FakeIdentityProvider(token_service_.get())),
+ :
#if !defined(OS_ANDROID)
save_card_bubble_controller_(new MockSaveCardBubbleController()),
#endif
@@ -38,8 +37,8 @@ syncer::SyncService* TestAutofillClient::GetSyncService() {
return nullptr;
}
-IdentityProvider* TestAutofillClient::GetIdentityProvider() {
- return identity_provider_.get();
+identity::IdentityManager* TestAutofillClient::GetIdentityManager() {
+ return identity_test_env_.identity_manager();
}
ukm::UkmRecorder* TestAutofillClient::GetUkmRecorder() {
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.h b/chromium/components/autofill/core/browser/test_autofill_client.h
index 4974ed68c69..e4ae77dcc86 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.h
+++ b/chromium/components/autofill/core/browser/test_autofill_client.h
@@ -16,8 +16,7 @@
#include "components/autofill/core/browser/autofill_client.h"
#include "components/prefs/pref_service.h"
#include "components/ukm/test_ukm_recorder.h"
-#include "google_apis/gaia/fake_identity_provider.h"
-#include "google_apis/gaia/fake_oauth2_token_service.h"
+#include "services/identity/public/cpp/identity_test_environment.h"
namespace autofill {
@@ -32,7 +31,7 @@ class TestAutofillClient : public AutofillClient {
scoped_refptr<AutofillWebDataService> GetDatabase() override;
PrefService* GetPrefs() override;
syncer::SyncService* GetSyncService() override;
- IdentityProvider* GetIdentityProvider() override;
+ identity::IdentityManager* GetIdentityManager() override;
ukm::UkmRecorder* GetUkmRecorder() override;
AddressNormalizer* GetAddressNormalizer() override;
SaveCardBubbleController* GetSaveCardBubbleController() override;
@@ -85,10 +84,10 @@ class TestAutofillClient : public AutofillClient {
void set_form_origin(const GURL& url) { form_origin_ = url; }
private:
+ identity::IdentityTestEnvironment identity_test_env_;
+
// NULL by default.
std::unique_ptr<PrefService> prefs_;
- std::unique_ptr<FakeOAuth2TokenService> token_service_;
- std::unique_ptr<FakeIdentityProvider> identity_provider_;
#if !defined(OS_ANDROID)
std::unique_ptr<SaveCardBubbleController> save_card_bubble_controller_;
#endif
diff --git a/chromium/components/autofill/core/browser/test_autofill_clock.cc b/chromium/components/autofill/core/browser/test_autofill_clock.cc
index 4d5829b8a26..a43489ebced 100644
--- a/chromium/components/autofill/core/browser/test_autofill_clock.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_clock.cc
@@ -12,13 +12,7 @@
namespace autofill {
TestAutofillClock::TestAutofillClock() {
- // Create a new test clock and set it as the AutofillClock clock and keep a
- // pointer to manipulate the time it returns.
- std::unique_ptr<base::SimpleTestClock> unique_test_clock(
- new base::SimpleTestClock());
- // Keep a pointer to the clock to be able to use its SetNow() function.
- test_clock_ = unique_test_clock.get();
- AutofillClock::SetTestClock(std::move(unique_test_clock));
+ AutofillClock::SetTestClock(&test_clock_);
}
TestAutofillClock::~TestAutofillClock() {
@@ -27,7 +21,7 @@ TestAutofillClock::~TestAutofillClock() {
}
void TestAutofillClock::SetNow(base::Time now) {
- test_clock_->SetNow(now);
+ test_clock_.SetNow(now);
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_autofill_clock.h b/chromium/components/autofill/core/browser/test_autofill_clock.h
index a40f54fbd2f..71bc8825475 100644
--- a/chromium/components/autofill/core/browser/test_autofill_clock.h
+++ b/chromium/components/autofill/core/browser/test_autofill_clock.h
@@ -8,9 +8,9 @@
#include <memory>
#include "base/macros.h"
+#include "base/test/simple_test_clock.h"
namespace base {
-class SimpleTestClock;
class Time;
} // namespace base
@@ -29,7 +29,7 @@ class TestAutofillClock {
void SetNow(base::Time now);
private:
- base::SimpleTestClock* test_clock_;
+ base::SimpleTestClock test_clock_;
DISALLOW_COPY_AND_ASSIGN(TestAutofillClock);
};
diff --git a/chromium/components/autofill/core/browser/test_autofill_manager.cc b/chromium/components/autofill/core/browser/test_autofill_manager.cc
index 2fab42d9855..1ef5b047513 100644
--- a/chromium/components/autofill/core/browser/test_autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_manager.cc
@@ -23,7 +23,7 @@ TestAutofillManager::TestAutofillManager(AutofillDriver* driver,
personal_data_(personal_data),
context_getter_(driver->GetURLRequestContext()) {
set_payments_client(new payments::PaymentsClient(
- context_getter_, client->GetPrefs(), client->GetIdentityProvider(),
+ context_getter_, client->GetPrefs(), client->GetIdentityManager(),
/*unmask_delegate=*/this,
/*save_delegate=*/nullptr));
}
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 31947b87d1b..44d20684d65 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
@@ -368,8 +368,8 @@ void AutocompleteSyncBridge::AutocompleteSyncBridge::GetData(
DCHECK(thread_checker_.CalledOnValidThread());
std::vector<AutofillEntry> entries;
if (!GetAutofillTable()->GetAllAutofillEntries(&entries)) {
- change_processor()->ReportError(FROM_HERE,
- "Failed to load entries from table.");
+ change_processor()->ReportError(
+ {FROM_HERE, "Failed to load entries from table."});
return;
}
@@ -390,8 +390,8 @@ void AutocompleteSyncBridge::GetAllData(DataCallback callback) {
std::vector<AutofillEntry> entries;
if (!GetAutofillTable()->GetAllAutofillEntries(&entries)) {
- change_processor()->ReportError(FROM_HERE,
- "Failed to load entries from table.");
+ change_processor()->ReportError(
+ {FROM_HERE, "Failed to load entries from table."});
return;
}
@@ -422,7 +422,7 @@ void AutocompleteSyncBridge::ActOnLocalChanges(
&date_last_used);
if (!success) {
change_processor()->ReportError(
- FROM_HERE, "Failed reading autofill entry from WebDatabase.");
+ {FROM_HERE, "Failed reading autofill entry from WebDatabase."});
return;
}
@@ -439,21 +439,21 @@ void AutocompleteSyncBridge::ActOnLocalChanges(
}
if (Optional<ModelError> error = metadata_change_list->TakeError())
- change_processor()->ReportError(error.value());
+ change_processor()->ReportError(*error);
}
void AutocompleteSyncBridge::LoadMetadata() {
if (!web_data_backend_ || !web_data_backend_->GetDatabase() ||
!GetAutofillTable()) {
- change_processor()->ReportError(FROM_HERE,
- "Failed to load AutofillWebDatabase.");
+ change_processor()->ReportError(
+ {FROM_HERE, "Failed to load AutofillWebDatabase."});
return;
}
auto batch = std::make_unique<syncer::MetadataBatch>();
if (!GetAutofillTable()->GetAllSyncMetadata(syncer::AUTOFILL, batch.get())) {
change_processor()->ReportError(
- FROM_HERE, "Failed reading autofill metadata from WebDatabase.");
+ {FROM_HERE, "Failed reading autofill metadata from WebDatabase."});
return;
}
change_processor()->ModelReadyToSync(std::move(batch));
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller_unittest.cc
index 78b169253e5..5424b1a2f47 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_data_type_controller_unittest.cc
@@ -92,7 +92,7 @@ class AutofillDataTypeControllerTest : public testing::Test,
new FakeWebDataService(base::ThreadTaskRunnerHandle::Get(),
base::ThreadTaskRunnerHandle::Get());
autofill_dtc_ = std::make_unique<AutofillDataTypeController>(
- base::ThreadTaskRunnerHandle::Get(), base::Bind(&base::DoNothing), this,
+ base::ThreadTaskRunnerHandle::Get(), base::DoNothing(), this,
web_data_service_);
last_type_ = syncer::UNSPECIFIED;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
index 90d6408695e..3ff3a516adb 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -139,69 +140,58 @@ AutofillProfile ProfileFromSpecifics(
return profile;
}
-// This function handles conditionally updating the AutofillTable with either
-// a set of CreditCards or AutocompleteProfiles only when the existing data
-// doesn't match.
-//
-// It's passed the getter and setter function on the AutofillTable for the
-// corresponding data type, and expects the types to implement a Compare
-// function. Note that the guid can't be used here as a key since these are
-// generated locally and will be different each time, and the server ID can't
-// be used because it's empty for addresses (though it could be used for credit
-// cards if we wanted separate implementations).
-//
-// Returns true if anything changed. The previous number of items in the table
-// (for sync tracking) will be placed into *prev_item_count.
-template <class Data>
-bool SetDataIfChanged(
- AutofillTable* table,
- const std::vector<Data>& data,
- bool (AutofillTable::*getter)(std::vector<std::unique_ptr<Data>>*) const,
- void (AutofillTable::*setter)(const std::vector<Data>&),
- size_t* prev_item_count) {
- std::vector<std::unique_ptr<Data>> existing_data;
- (table->*getter)(&existing_data);
- *prev_item_count = existing_data.size();
-
- // If the user has a large number of addresses, don't bother verifying
- // anything changed and just rewrite the data.
- const size_t kTooBigToCheckThreshold = 8;
-
- bool difference_found;
- if (existing_data.size() != data.size() ||
- data.size() > kTooBigToCheckThreshold) {
- difference_found = true;
- } else {
- difference_found = false;
-
- // Implement brute-force searching. Address and card counts are typically
- // small, and comparing them is relatively expensive (many string
- // compares). A std::set only uses operator< requiring multiple calls to
- // check equality, giving 8 compares for 2 elements and 16 for 3. For these
- // set sizes, brute force O(n^2) is faster.
- for (const auto& cur_existing : existing_data) {
- bool found_match_for_cur_existing = false;
- for (const Data& cur_new : data) {
- if (cur_existing->Compare(cur_new) == 0) {
- found_match_for_cur_existing = true;
- break;
- }
- }
- if (!found_match_for_cur_existing) {
- difference_found = true;
- break;
- }
+} // namespace
+
+// static
+template <class Item>
+AutofillWalletSyncableService::Diff AutofillWalletSyncableService::ComputeDiff(
+ const std::vector<std::unique_ptr<Item>>& old_data,
+ const std::vector<Item>& new_data) {
+ // Build vectors of pointers, so that we can mutate (sort) them.
+ std::vector<const Item*> old_ptrs;
+ old_ptrs.reserve(old_data.size());
+ for (const std::unique_ptr<Item>& old_item : old_data)
+ old_ptrs.push_back(old_item.get());
+ std::vector<const Item*> new_ptrs;
+ new_ptrs.reserve(new_data.size());
+ for (const Item& new_item : new_data)
+ new_ptrs.push_back(&new_item);
+
+ // Sort our vectors.
+ auto compare = [](const Item* lhs, const Item* rhs) {
+ return lhs->Compare(*rhs) < 0;
+ };
+ std::sort(old_ptrs.begin(), old_ptrs.end(), compare);
+ std::sort(new_ptrs.begin(), new_ptrs.end(), compare);
+
+ // Walk over both of them and count added/removed elements.
+ Diff result;
+ auto old_it = old_ptrs.begin();
+ auto new_it = new_ptrs.begin();
+ while (old_it != old_ptrs.end()) {
+ if (new_it == new_ptrs.end()) {
+ result.items_removed += std::distance(old_it, old_ptrs.end());
+ break;
+ }
+ int cmp = (*old_it)->Compare(**new_it);
+ if (cmp < 0) {
+ ++result.items_removed;
+ ++old_it;
+ } else if (cmp == 0) {
+ ++old_it;
+ ++new_it;
+ } else {
+ ++result.items_added;
+ ++new_it;
}
}
+ result.items_added += std::distance(new_it, new_ptrs.end());
- if (difference_found) {
- (table->*setter)(data);
- return true;
- }
- return false;
-}
+ DCHECK_EQ(old_data.size() + result.items_added - result.items_removed,
+ new_data.size());
-} // namespace
+ return result;
+}
AutofillWalletSyncableService::AutofillWalletSyncableService(
AutofillWebDataBackend* webdata_backend,
@@ -217,7 +207,8 @@ syncer::SyncMergeResult AutofillWalletSyncableService::MergeDataAndStartSyncing(
std::unique_ptr<syncer::SyncErrorFactory> sync_error_factory) {
DCHECK(thread_checker_.CalledOnValidThread());
sync_processor_ = std::move(sync_processor);
- syncer::SyncMergeResult result = SetSyncData(initial_sync_data);
+ syncer::SyncMergeResult result =
+ SetSyncData(initial_sync_data, /*is_initial_data=*/true);
if (webdata_backend_)
webdata_backend_->NotifyThatSyncHasStarted(type);
return result;
@@ -243,7 +234,8 @@ syncer::SyncError AutofillWalletSyncableService::ProcessSyncChanges(
DCHECK(thread_checker_.CalledOnValidThread());
// Don't bother handling incremental updates. Wallet data changes very rarely
// and has few items. Instead, just get all the current data and save it.
- SetSyncData(sync_processor_->GetAllSyncData(syncer::AUTOFILL_WALLET_DATA));
+ SetSyncData(sync_processor_->GetAllSyncData(syncer::AUTOFILL_WALLET_DATA),
+ /*is_initial_data=*/false);
return syncer::SyncError();
}
@@ -334,7 +326,8 @@ void AutofillWalletSyncableService::CopyRelevantMetadataFromDisk(
}
syncer::SyncMergeResult AutofillWalletSyncableService::SetSyncData(
- const syncer::SyncDataList& data_list) {
+ const syncer::SyncDataList& data_list,
+ bool is_initial_data) {
std::vector<CreditCard> wallet_cards;
std::vector<AutofillProfile> wallet_addresses;
PopulateWalletCardsAndAddresses(data_list, &wallet_cards, &wallet_addresses);
@@ -351,22 +344,42 @@ syncer::SyncMergeResult AutofillWalletSyncableService::SetSyncData(
// to the database will require at least one DB page write and will schedule
// a fsync. To avoid this I/O, it should be more efficient to do a read and
// only do the writes if something changed.
- size_t prev_card_count = 0;
- size_t prev_address_count = 0;
- bool changed_cards = SetDataIfChanged(
- table, wallet_cards, &AutofillTable::GetServerCreditCards,
- &AutofillTable::SetServerCreditCards, &prev_card_count);
- bool changed_addresses = SetDataIfChanged(
- table, wallet_addresses, &AutofillTable::GetServerProfiles,
- &AutofillTable::SetServerProfiles, &prev_address_count);
+ std::vector<std::unique_ptr<CreditCard>> existing_cards;
+ table->GetServerCreditCards(&existing_cards);
+ Diff cards_diff = ComputeDiff(existing_cards, wallet_cards);
+ if (!cards_diff.IsEmpty())
+ table->SetServerCreditCards(wallet_cards);
+
+ std::vector<std::unique_ptr<AutofillProfile>> existing_addresses;
+ table->GetServerProfiles(&existing_addresses);
+ Diff addresses_diff = ComputeDiff(existing_addresses, wallet_addresses);
+ if (!addresses_diff.IsEmpty())
+ table->SetServerProfiles(wallet_addresses);
syncer::SyncMergeResult merge_result(syncer::AUTOFILL_WALLET_DATA);
merge_result.set_num_items_before_association(
- static_cast<int>(prev_card_count + prev_address_count));
+ static_cast<int>(existing_cards.size() + existing_addresses.size()));
merge_result.set_num_items_after_association(
static_cast<int>(wallet_cards.size() + wallet_addresses.size()));
- if (webdata_backend_ && (changed_cards || changed_addresses))
+ if (!is_initial_data) {
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCardsAdded",
+ cards_diff.items_added);
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCardsRemoved",
+ cards_diff.items_removed);
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCardsAddedOrRemoved",
+ cards_diff.items_added + cards_diff.items_removed);
+
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddressesAdded",
+ addresses_diff.items_added);
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddressesRemoved",
+ addresses_diff.items_removed);
+ UMA_HISTOGRAM_COUNTS_100(
+ "Autofill.WalletAddressesAddedOrRemoved",
+ addresses_diff.items_added + addresses_diff.items_removed);
+ }
+
+ if (webdata_backend_ && (!cards_diff.IsEmpty() || !addresses_diff.IsEmpty()))
webdata_backend_->NotifyOfMultipleAutofillChanges();
return merge_result;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
index 9b4e92a229c..c27626c36fd 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
@@ -77,8 +77,30 @@ class AutofillWalletSyncableService
CopyRelevantMetadataFromDisk_KeepUseStats);
FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest, NewWalletCard);
FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest, EmptyNameOnCard);
-
- syncer::SyncMergeResult SetSyncData(const syncer::SyncDataList& data_list);
+ FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest, ComputeCardsDiff);
+ FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest,
+ ComputeAddressesDiff);
+
+ struct Diff {
+ int items_added = 0;
+ int items_removed = 0;
+
+ bool IsEmpty() const { return items_added == 0 && items_removed == 0; }
+ };
+
+ // Computes a "diff" (items added, items removed) of two vectors of items,
+ // which should be either CreditCard or AutofillProfile. This is used for two
+ // purposes:
+ // 1) Detecting if anything has changed, so that we don't write to disk in the
+ // common case where nothing has changed.
+ // 2) Recording metrics on the number of added/removed items.
+ // This is exposed as a static method so that it can be tested.
+ template <class Item>
+ static Diff ComputeDiff(const std::vector<std::unique_ptr<Item>>& old_data,
+ const std::vector<Item>& new_data);
+
+ syncer::SyncMergeResult SetSyncData(const syncer::SyncDataList& data_list,
+ bool is_initial_data);
// Populates the wallet cards and addresses from the sync data and uses the
// sync data to link the card to its billing address.
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc
index f407085d98f..c31ea73a9d5 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <vector>
+#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
@@ -246,4 +247,110 @@ TEST(AutofillWalletSyncableServiceTest, EmptyNameOnCard) {
wallet_cards.back().GetRawInfo(autofill::CREDIT_CARD_NAME_LAST).empty());
}
+TEST(AutofillWalletSyncableServiceTest, ComputeCardsDiff) {
+ // Some arbitrary cards for testing.
+ CreditCard card0(CreditCard::MASKED_SERVER_CARD, "a");
+ CreditCard card1(CreditCard::MASKED_SERVER_CARD, "b");
+ CreditCard card2(CreditCard::MASKED_SERVER_CARD, "c");
+ CreditCard card3(CreditCard::MASKED_SERVER_CARD, "d");
+ // Make sure that card0 < card1 < card2 < card3.
+ ASSERT_LT(card0.Compare(card1), 0);
+ ASSERT_LT(card1.Compare(card2), 0);
+ ASSERT_LT(card2.Compare(card3), 0);
+
+ struct TestCase {
+ const char* name;
+ const std::vector<CreditCard> old_cards;
+ const std::vector<CreditCard> new_cards;
+ int expected_added;
+ int expected_removed;
+ } test_cases[] = {
+ {"Both empty", {}, {}, 0, 0},
+ {"Old empty", {}, {card0}, 1, 0},
+ {"New empty", {card0}, {}, 0, 1},
+ {"Identical", {card0, card1}, {card0, card1}, 0, 0},
+ {"Identical unsorted", {card0, card1}, {card1, card0}, 0, 0},
+ {"Added one", {card0}, {card0, card1}, 1, 0},
+ {"Added two", {card1}, {card0, card1, card2}, 2, 0},
+ {"Removed one", {card0, card1}, {card1}, 0, 1},
+ {"Removed two", {card0, card1, card2}, {card1}, 0, 2},
+ {"Replaced one", {card0}, {card1}, 1, 1},
+ {"Replaced two", {card0, card1}, {card2, card3}, 2, 2},
+ {"Added and removed one", {card0, card1}, {card1, card2}, 1, 1},
+ };
+
+ for (const TestCase& test_case : test_cases) {
+ SCOPED_TRACE(test_case.name);
+
+ // ComputeDiff expects a vector of unique_ptrs for the old data.
+ std::vector<std::unique_ptr<CreditCard>> old_cards_ptrs;
+ for (const CreditCard& card : test_case.old_cards)
+ old_cards_ptrs.push_back(std::make_unique<CreditCard>(card));
+
+ AutofillWalletSyncableService::Diff diff =
+ AutofillWalletSyncableService::ComputeDiff(old_cards_ptrs,
+ test_case.new_cards);
+
+ EXPECT_EQ(test_case.expected_added, diff.items_added);
+ EXPECT_EQ(test_case.expected_removed, diff.items_removed);
+ }
+}
+
+TEST(AutofillWalletSyncableServiceTest, ComputeAddressesDiff) {
+ // Some arbitrary addresses for testing.
+ AutofillProfile address0(AutofillProfile::SERVER_PROFILE, "a");
+ AutofillProfile address1(AutofillProfile::SERVER_PROFILE, "b");
+ AutofillProfile address2(AutofillProfile::SERVER_PROFILE, "c");
+ AutofillProfile address3(AutofillProfile::SERVER_PROFILE, "d");
+ address0.SetRawInfo(NAME_FULL, base::ASCIIToUTF16("a"));
+ address1.SetRawInfo(NAME_FULL, base::ASCIIToUTF16("b"));
+ address2.SetRawInfo(NAME_FULL, base::ASCIIToUTF16("c"));
+ address3.SetRawInfo(NAME_FULL, base::ASCIIToUTF16("d"));
+ // Make sure that address0 < address1 < address2 < address3.
+ ASSERT_LT(address0.Compare(address1), 0);
+ ASSERT_LT(address1.Compare(address2), 0);
+ ASSERT_LT(address2.Compare(address3), 0);
+
+ struct TestCase {
+ const char* name;
+ const std::vector<AutofillProfile> old_addresses;
+ const std::vector<AutofillProfile> new_addresses;
+ int expected_added;
+ int expected_removed;
+ } test_cases[] = {
+ {"Both empty", {}, {}, 0, 0},
+ {"Old empty", {}, {address0}, 1, 0},
+ {"New empty", {address0}, {}, 0, 1},
+ {"Identical", {address0, address1}, {address0, address1}, 0, 0},
+ {"Identical unsorted", {address0, address1}, {address1, address0}, 0, 0},
+ {"Added one", {address0}, {address0, address1}, 1, 0},
+ {"Added two", {address1}, {address0, address1, address2}, 2, 0},
+ {"Removed one", {address0, address1}, {address1}, 0, 1},
+ {"Removed two", {address0, address1, address2}, {address1}, 0, 2},
+ {"Replaced one", {address0}, {address1}, 1, 1},
+ {"Replaced two", {address0, address1}, {address2, address3}, 2, 2},
+ {"Added and removed one",
+ {address0, address1},
+ {address1, address2},
+ 1,
+ 1},
+ };
+
+ for (const TestCase& test_case : test_cases) {
+ SCOPED_TRACE(test_case.name);
+
+ // ComputeDiff expects a vector of unique_ptrs for the old data.
+ std::vector<std::unique_ptr<AutofillProfile>> old_addresses_ptrs;
+ for (const AutofillProfile& address : test_case.old_addresses)
+ old_addresses_ptrs.push_back(std::make_unique<AutofillProfile>(address));
+
+ AutofillWalletSyncableService::Diff diff =
+ AutofillWalletSyncableService::ComputeDiff(old_addresses_ptrs,
+ test_case.new_addresses);
+
+ EXPECT_EQ(test_case.expected_added, diff.items_added);
+ EXPECT_EQ(test_case.expected_removed, diff.items_removed);
+ }
+}
+
} // 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 7a6f5536f43..67de7896c07 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
@@ -30,22 +30,21 @@ AutofillWebDataBackendImpl::AutofillWebDataBackendImpl(
const base::Closure& on_changed_callback,
const base::Callback<void(syncer::ModelType)>& on_sync_started_callback)
: base::RefCountedDeleteOnSequence<AutofillWebDataBackendImpl>(
- db_task_runner),
+ std::move(db_task_runner)),
ui_task_runner_(ui_task_runner),
- db_task_runner_(db_task_runner),
web_database_backend_(web_database_backend),
on_changed_callback_(on_changed_callback),
on_sync_started_callback_(on_sync_started_callback) {}
void AutofillWebDataBackendImpl::AddObserver(
AutofillWebDataServiceObserverOnDBSequence* observer) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
db_observer_list_.AddObserver(observer);
}
void AutofillWebDataBackendImpl::RemoveObserver(
AutofillWebDataServiceObserverOnDBSequence* observer) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
db_observer_list_.RemoveObserver(observer);
}
@@ -54,7 +53,7 @@ AutofillWebDataBackendImpl::~AutofillWebDataBackendImpl() {
}
WebDatabase* AutofillWebDataBackendImpl::GetDatabase() {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
return web_database_backend_->database();
}
@@ -65,7 +64,7 @@ void AutofillWebDataBackendImpl::RemoveExpiredFormElements() {
}
void AutofillWebDataBackendImpl::NotifyOfMultipleAutofillChanges() {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
// DB sequence notification.
for (auto& db_observer : db_observer_list_)
@@ -77,7 +76,7 @@ void AutofillWebDataBackendImpl::NotifyOfMultipleAutofillChanges() {
void AutofillWebDataBackendImpl::NotifyThatSyncHasStarted(
syncer::ModelType model_type) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (on_sync_started_callback_.is_null())
return;
@@ -88,7 +87,7 @@ void AutofillWebDataBackendImpl::NotifyThatSyncHasStarted(
}
base::SupportsUserData* AutofillWebDataBackendImpl::GetDBUserData() {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (!user_data_)
user_data_.reset(new SupportsUserDataAggregatable());
return user_data_.get();
@@ -100,7 +99,7 @@ void AutofillWebDataBackendImpl::ResetUserData() {
WebDatabase::State AutofillWebDataBackendImpl::AddFormElements(
const std::vector<FormFieldData>& fields, WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
AutofillChangeList changes;
if (!AutofillTable::FromWebDatabase(db)->AddFormFieldValues(
fields, &changes)) {
@@ -123,7 +122,7 @@ AutofillWebDataBackendImpl::GetFormValuesForElementName(
const base::string16& prefix,
int limit,
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
std::vector<base::string16> values;
AutofillTable::FromWebDatabase(db)->GetFormValuesForElementName(
name, prefix, &values, limit);
@@ -135,7 +134,7 @@ WebDatabase::State AutofillWebDataBackendImpl::RemoveFormElementsAddedBetween(
const base::Time& delete_begin,
const base::Time& delete_end,
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
AutofillChangeList changes;
if (AutofillTable::FromWebDatabase(db)->RemoveFormElementsAddedBetween(
@@ -154,7 +153,7 @@ WebDatabase::State AutofillWebDataBackendImpl::RemoveFormElementsAddedBetween(
WebDatabase::State AutofillWebDataBackendImpl::RemoveFormValueForElementName(
const base::string16& name, const base::string16& value, WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (AutofillTable::FromWebDatabase(db)->RemoveFormElement(name, value)) {
AutofillChangeList changes;
@@ -172,7 +171,7 @@ WebDatabase::State AutofillWebDataBackendImpl::RemoveFormValueForElementName(
WebDatabase::State AutofillWebDataBackendImpl::AddAutofillProfile(
const AutofillProfile& profile, WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (!AutofillTable::FromWebDatabase(db)->AddAutofillProfile(profile)) {
NOTREACHED();
return WebDatabase::COMMIT_NOT_NEEDED;
@@ -189,7 +188,7 @@ WebDatabase::State AutofillWebDataBackendImpl::AddAutofillProfile(
WebDatabase::State AutofillWebDataBackendImpl::UpdateAutofillProfile(
const AutofillProfile& profile, WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
// Only perform the update if the profile exists. It is currently
// valid to try to update a missing profile. We simply drop the write and
// the caller will detect this on the next refresh.
@@ -214,7 +213,7 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateAutofillProfile(
WebDatabase::State AutofillWebDataBackendImpl::RemoveAutofillProfile(
const std::string& guid, WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
std::unique_ptr<AutofillProfile> profile =
AutofillTable::FromWebDatabase(db)->GetAutofillProfile(guid);
if (!profile) {
@@ -237,7 +236,7 @@ WebDatabase::State AutofillWebDataBackendImpl::RemoveAutofillProfile(
std::unique_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetAutofillProfiles(
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
std::vector<std::unique_ptr<AutofillProfile>> profiles;
AutofillTable::FromWebDatabase(db)->GetAutofillProfiles(&profiles);
return std::unique_ptr<WDTypedResult>(
@@ -247,7 +246,7 @@ std::unique_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetAutofillProfiles(
std::unique_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetServerProfiles(
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
std::vector<std::unique_ptr<AutofillProfile>> profiles;
AutofillTable::FromWebDatabase(db)->GetServerProfiles(&profiles);
return std::unique_ptr<WDTypedResult>(
@@ -260,7 +259,7 @@ AutofillWebDataBackendImpl::GetCountOfValuesContainedBetween(
const base::Time& begin,
const base::Time& end,
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
int value = AutofillTable::FromWebDatabase(db)
->GetCountOfValuesContainedBetween(begin, end);
return std::unique_ptr<WDTypedResult>(
@@ -270,7 +269,7 @@ AutofillWebDataBackendImpl::GetCountOfValuesContainedBetween(
WebDatabase::State AutofillWebDataBackendImpl::UpdateAutofillEntries(
const std::vector<AutofillEntry>& autofill_entries,
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (!AutofillTable::FromWebDatabase(db)
->UpdateAutofillEntries(autofill_entries))
return WebDatabase::COMMIT_NOT_NEEDED;
@@ -280,7 +279,7 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateAutofillEntries(
WebDatabase::State AutofillWebDataBackendImpl::AddCreditCard(
const CreditCard& credit_card, WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (!AutofillTable::FromWebDatabase(db)->AddCreditCard(credit_card)) {
NOTREACHED();
return WebDatabase::COMMIT_NOT_NEEDED;
@@ -295,7 +294,7 @@ WebDatabase::State AutofillWebDataBackendImpl::AddCreditCard(
WebDatabase::State AutofillWebDataBackendImpl::UpdateCreditCard(
const CreditCard& credit_card, WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
// It is currently valid to try to update a missing profile. We simply drop
// the write and the caller will detect this on the next refresh.
std::unique_ptr<CreditCard> original_credit_card =
@@ -317,7 +316,7 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateCreditCard(
WebDatabase::State AutofillWebDataBackendImpl::RemoveCreditCard(
const std::string& guid, WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (!AutofillTable::FromWebDatabase(db)->RemoveCreditCard(guid)) {
NOTREACHED();
return WebDatabase::COMMIT_NOT_NEEDED;
@@ -333,7 +332,7 @@ WebDatabase::State AutofillWebDataBackendImpl::RemoveCreditCard(
WebDatabase::State AutofillWebDataBackendImpl::AddFullServerCreditCard(
const CreditCard& credit_card,
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (!AutofillTable::FromWebDatabase(db)->AddFullServerCreditCard(
credit_card)) {
NOTREACHED();
@@ -349,7 +348,7 @@ WebDatabase::State AutofillWebDataBackendImpl::AddFullServerCreditCard(
std::unique_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetCreditCards(
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
std::vector<std::unique_ptr<CreditCard>> credit_cards;
AutofillTable::FromWebDatabase(db)->GetCreditCards(&credit_cards);
return std::unique_ptr<WDTypedResult>(
@@ -359,7 +358,7 @@ std::unique_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetCreditCards(
std::unique_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetServerCreditCards(
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
std::vector<std::unique_ptr<CreditCard>> credit_cards;
AutofillTable::FromWebDatabase(db)->GetServerCreditCards(&credit_cards);
return std::unique_ptr<WDTypedResult>(
@@ -371,7 +370,7 @@ WebDatabase::State AutofillWebDataBackendImpl::UnmaskServerCreditCard(
const CreditCard& card,
const base::string16& full_number,
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (AutofillTable::FromWebDatabase(db)->UnmaskServerCreditCard(
card, full_number))
return WebDatabase::COMMIT_NEEDED;
@@ -382,7 +381,7 @@ WebDatabase::State
AutofillWebDataBackendImpl::MaskServerCreditCard(
const std::string& id,
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (AutofillTable::FromWebDatabase(db)->MaskServerCreditCard(id))
return WebDatabase::COMMIT_NEEDED;
return WebDatabase::COMMIT_NOT_NEEDED;
@@ -391,7 +390,7 @@ WebDatabase::State
WebDatabase::State AutofillWebDataBackendImpl::UpdateServerCardMetadata(
const CreditCard& card,
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (!AutofillTable::FromWebDatabase(db)->UpdateServerCardMetadata(card))
return WebDatabase::COMMIT_NOT_NEEDED;
@@ -406,7 +405,7 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateServerCardMetadata(
WebDatabase::State AutofillWebDataBackendImpl::UpdateServerAddressMetadata(
const AutofillProfile& profile,
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (!AutofillTable::FromWebDatabase(db)->UpdateServerAddressMetadata(
profile)) {
return WebDatabase::COMMIT_NOT_NEEDED;
@@ -422,7 +421,7 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateServerAddressMetadata(
WebDatabase::State AutofillWebDataBackendImpl::ClearAllServerData(
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
if (AutofillTable::FromWebDatabase(db)->ClearAllServerData()) {
NotifyOfMultipleAutofillChanges();
return WebDatabase::COMMIT_NEEDED;
@@ -435,7 +434,7 @@ WebDatabase::State
const base::Time& delete_begin,
const base::Time& delete_end,
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
std::vector<std::string> profile_guids;
std::vector<std::string> credit_card_guids;
if (AutofillTable::FromWebDatabase(db)->RemoveAutofillDataModifiedBetween(
@@ -466,7 +465,7 @@ WebDatabase::State AutofillWebDataBackendImpl::RemoveOriginURLsModifiedBetween(
const base::Time& delete_begin,
const base::Time& delete_end,
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
std::vector<std::unique_ptr<AutofillProfile>> profiles;
if (!AutofillTable::FromWebDatabase(db)->RemoveOriginURLsModifiedBetween(
delete_begin, delete_end, &profiles)) {
@@ -486,7 +485,7 @@ WebDatabase::State AutofillWebDataBackendImpl::RemoveOriginURLsModifiedBetween(
WebDatabase::State AutofillWebDataBackendImpl::RemoveExpiredFormElementsImpl(
WebDatabase* db) {
- DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
AutofillChangeList changes;
if (AutofillTable::FromWebDatabase(db)->RemoveExpiredFormElements(&changes)) {
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 3720bd72214..9fcbc877a4b 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
@@ -202,9 +202,6 @@ class AutofillWebDataBackendImpl
// The task runner that this class uses for its UI tasks.
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
- // The task runner that this class uses for its DB tasks.
- scoped_refptr<base::SingleThreadTaskRunner> db_task_runner_;
-
// Storage for user data to be accessed only on the DB sequence. May
// be used e.g. for SyncableService subclasses that need to be owned
// by this object. Is created on first call to |GetDBUserData()|.
diff --git a/chromium/components/autofill/core/common/autofill_clock.cc b/chromium/components/autofill/core/common/autofill_clock.cc
index ffdf9043f8f..0336eb95132 100644
--- a/chromium/components/autofill/core/common/autofill_clock.cc
+++ b/chromium/components/autofill/core/common/autofill_clock.cc
@@ -4,40 +4,30 @@
#include "components/autofill/core/common/autofill_clock.h"
-#include <utility>
-
#include "base/time/clock.h"
#include "base/time/default_clock.h"
namespace autofill {
-
namespace {
-
-static base::LazyInstance<AutofillClock>::DestructorAtExit g_autofill_clock =
- LAZY_INSTANCE_INITIALIZER;
-
+base::Clock* g_autofill_clock = nullptr;
} // namespace
// static
base::Time AutofillClock::Now() {
- if (!g_autofill_clock.Get().clock_)
+ if (!g_autofill_clock)
SetClock();
-
- return g_autofill_clock.Get().clock_->Now();
+ return g_autofill_clock->Now();
}
-AutofillClock::AutofillClock(){};
-AutofillClock::~AutofillClock(){};
-
// static
void AutofillClock::SetClock() {
- g_autofill_clock.Get().clock_ = std::make_unique<base::DefaultClock>();
+ g_autofill_clock = base::DefaultClock::GetInstance();
}
// static
-void AutofillClock::SetTestClock(std::unique_ptr<base::Clock> clock) {
+void AutofillClock::SetTestClock(base::Clock* clock) {
DCHECK(clock);
- g_autofill_clock.Get().clock_ = std::move(clock);
+ g_autofill_clock = clock;
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_clock.h b/chromium/components/autofill/core/common/autofill_clock.h
index b94ff272ab4..651d9cdf496 100644
--- a/chromium/components/autofill/core/common/autofill_clock.h
+++ b/chromium/components/autofill/core/common/autofill_clock.h
@@ -5,11 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_CLOCK_H_
#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_CLOCK_H_
-#include <memory>
-
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-
namespace base {
class Clock;
class Time;
@@ -26,21 +21,15 @@ class AutofillClock {
private:
friend class TestAutofillClock;
- friend struct base::LazyInstanceTraitsBase<AutofillClock>;
// Resets a normal clock.
static void SetClock();
// Sets the clock to be used for tests.
- static void SetTestClock(std::unique_ptr<base::Clock> clock);
-
- AutofillClock();
- ~AutofillClock();
-
- // The clock used to return the current time.
- std::unique_ptr<base::Clock> clock_;
+ static void SetTestClock(base::Clock* clock);
- DISALLOW_COPY_AND_ASSIGN(AutofillClock);
+ AutofillClock() = delete;
+ ~AutofillClock() = delete;
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_features.cc b/chromium/components/autofill/core/common/autofill_features.cc
index 11bb2f1ff1c..9e10c9af475 100644
--- a/chromium/components/autofill/core/common/autofill_features.cc
+++ b/chromium/components/autofill/core/common/autofill_features.cc
@@ -47,11 +47,22 @@ const base::Feature kAutofillRestrictUnownedFieldsToFormlessCheckout{
const base::Feature kAutofillShowTypePredictions{
"AutofillShowTypePredictions", base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether inferred label is considered for comparing in
+// FormFieldData.SimilarFieldAs.
+const base::Feature kAutofillSkipComparingInferredLabels{
+ "AutofillSkipComparingInferredLabels", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls whether the credit card upload bubble shows the Google Pay logo and
// a shorter "Save card?" header message.
const base::Feature kAutofillUpstreamUseGooglePayBranding{
"AutofillUpstreamUseGooglePayBranding", base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether the credit card upload bubble shows the Google Pay logo and
+// a shorter "Save card?" header message on Android.
+const base::Feature kAutofillUpstreamUseGooglePayOnAndroidBranding{
+ "AutofillUpstreamUseGooglePayOnAndroidBranding",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls whether to show new settings name in Autofill dropdown.
const base::Feature kAutofillUseNewSettingsNameInDropdown{
"AutofillUseNewSettingsNameInDropdown", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chromium/components/autofill/core/common/autofill_features.h b/chromium/components/autofill/core/common/autofill_features.h
index 9dbbdace48c..6c3b45024f3 100644
--- a/chromium/components/autofill/core/common/autofill_features.h
+++ b/chromium/components/autofill/core/common/autofill_features.h
@@ -18,7 +18,9 @@ extern const base::Feature kAutofillEnforceMinRequiredFieldsForQuery;
extern const base::Feature kAutofillEnforceMinRequiredFieldsForUpload;
extern const base::Feature kAutofillRestrictUnownedFieldsToFormlessCheckout;
extern const base::Feature kAutofillShowTypePredictions;
+extern const base::Feature kAutofillSkipComparingInferredLabels;
extern const base::Feature kAutofillUpstreamUseGooglePayBranding;
+extern const base::Feature kAutofillUpstreamUseGooglePayOnAndroidBranding;
extern const base::Feature kAutofillUseNewSettingsNameInDropdown;
} // namespace features
diff --git a/chromium/components/autofill/core/common/autofill_regexes.cc b/chromium/components/autofill/core/common/autofill_regexes.cc
index db66dd4b767..3c289e3430c 100644
--- a/chromium/components/autofill/core/common/autofill_regexes.cc
+++ b/chromium/components/autofill/core/common/autofill_regexes.cc
@@ -8,18 +8,23 @@
#include <unordered_map>
#include <utility>
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/singleton.h"
#include "base/strings/string16.h"
+#include "base/threading/thread_local.h"
#include "third_party/icu/source/i18n/unicode/regex.h"
namespace {
-// A singleton class that serves as a cache of compiled regex patterns.
+// 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
+// mode, and this class offers per-thread instance instead of per-process
+// singleton instance (https://crbug.com/812182).
class AutofillRegexes {
public:
- static AutofillRegexes* GetInstance();
+ static AutofillRegexes* ThreadSpecificInstance();
// Returns the compiled regex matcher corresponding to |pattern|.
icu::RegexMatcher* GetMatcher(const base::string16& pattern);
@@ -27,7 +32,6 @@ class AutofillRegexes {
private:
AutofillRegexes();
~AutofillRegexes();
- friend struct base::DefaultSingletonTraits<AutofillRegexes>;
// Maps patterns to their corresponding regex matchers.
std::unordered_map<base::string16, std::unique_ptr<icu::RegexMatcher>>
@@ -36,15 +40,22 @@ class AutofillRegexes {
DISALLOW_COPY_AND_ASSIGN(AutofillRegexes);
};
+base::LazyInstance<base::ThreadLocalPointer<AutofillRegexes>>::Leaky
+ g_autofill_regexes_tls = LAZY_INSTANCE_INITIALIZER;
+
// static
-AutofillRegexes* AutofillRegexes::GetInstance() {
- return base::Singleton<AutofillRegexes>::get();
+AutofillRegexes* AutofillRegexes::ThreadSpecificInstance() {
+ if (g_autofill_regexes_tls.Pointer()->Get())
+ return g_autofill_regexes_tls.Pointer()->Get();
+ return new AutofillRegexes;
}
AutofillRegexes::AutofillRegexes() {
+ g_autofill_regexes_tls.Pointer()->Set(this);
}
AutofillRegexes::~AutofillRegexes() {
+ g_autofill_regexes_tls.Pointer()->Set(nullptr);
}
icu::RegexMatcher* AutofillRegexes::GetMatcher(const base::string16& pattern) {
@@ -72,7 +83,7 @@ namespace autofill {
bool MatchesPattern(const base::string16& input,
const base::string16& pattern) {
icu::RegexMatcher* matcher =
- AutofillRegexes::GetInstance()->GetMatcher(pattern);
+ AutofillRegexes::ThreadSpecificInstance()->GetMatcher(pattern);
icu::UnicodeString icu_input(FALSE, input.data(), input.length());
matcher->reset(icu_input);
diff --git a/chromium/components/autofill/core/common/form_field_data.cc b/chromium/components/autofill/core/common/form_field_data.cc
index b26f3f956b7..56dea7012e6 100644
--- a/chromium/components/autofill/core/common/form_field_data.cc
+++ b/chromium/components/autofill/core/common/form_field_data.cc
@@ -7,6 +7,7 @@
#include "base/pickle.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_util.h"
namespace autofill {
@@ -119,6 +120,20 @@ bool DeserializeSection10(base::PickleIterator* iter,
return iter->ReadString16(&field_data->id);
}
+bool HaveSameLabel(const FormFieldData& field1, const FormFieldData& field2) {
+ if (field1.label == field2.label)
+ return true;
+
+ // Assume the labels same if they come from same source but not LABEL tag
+ // when kAutofillSkipComparingInferredLabels is enabled.
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillSkipComparingInferredLabels)) {
+ return field1.label_source == field2.label_source &&
+ field1.label_source != FormFieldData::LABEL_TAG;
+ }
+ return false;
+}
+
} // namespace
FormFieldData::FormFieldData()
@@ -129,7 +144,8 @@ FormFieldData::FormFieldData()
should_autocomplete(true),
role(ROLE_ATTRIBUTE_OTHER),
text_direction(base::i18n::UNKNOWN_DIRECTION),
- properties_mask(0) {}
+ properties_mask(0),
+ label_source(LabelSource::UNKNOWN) {}
FormFieldData::FormFieldData(const FormFieldData& other) = default;
@@ -138,7 +154,7 @@ FormFieldData::~FormFieldData() {}
bool FormFieldData::SameFieldAs(const FormFieldData& field) const {
// A FormFieldData stores a value, but the value is not part of the identity
// of the field, so we don't want to compare the values.
- return label == field.label && name == field.name && id == field.id &&
+ return name == field.name && id == field.id &&
form_control_type == field.form_control_type &&
autocomplete_attribute == field.autocomplete_attribute &&
placeholder == field.placeholder && max_length == field.max_length &&
@@ -148,7 +164,8 @@ bool FormFieldData::SameFieldAs(const FormFieldData& field) const {
IsCheckable(check_status) == IsCheckable(field.check_status) &&
is_focusable == field.is_focusable &&
should_autocomplete == field.should_autocomplete &&
- role == field.role && text_direction == field.text_direction;
+ role == field.role && text_direction == field.text_direction &&
+ HaveSameLabel(*this, field);
// The option values/contents which are the list of items in the list
// of a drop-down are currently not considered part of the identity of
// a form element. This is debatable, since one might base heuristics
@@ -159,7 +176,7 @@ bool FormFieldData::SameFieldAs(const FormFieldData& field) const {
}
bool FormFieldData::SimilarFieldAs(const FormFieldData& field) const {
- return label == field.label && name == field.name && id == field.id &&
+ return HaveSameLabel(*this, field) && name == field.name && id == field.id &&
form_control_type == field.form_control_type &&
IsCheckable(check_status) == IsCheckable(field.check_status);
}
@@ -414,7 +431,8 @@ std::ostream& operator<<(std::ostream& os, const FormFieldData& field) {
<< "should_autocomplete=" << field.should_autocomplete << " "
<< "role=" << role_str << " "
<< "text_direction=" << field.text_direction << " "
- << "properties_mask=" << field.properties_mask;
+ << "properties_mask=" << field.properties_mask << " "
+ << "label_source=" << field.label_source;
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/form_field_data.h b/chromium/components/autofill/core/common/form_field_data.h
index 1466bedc0cb..527372459a9 100644
--- a/chromium/components/autofill/core/common/form_field_data.h
+++ b/chromium/components/autofill/core/common/form_field_data.h
@@ -49,6 +49,20 @@ struct FormFieldData {
CHECKED,
};
+ // From which source the label is inferred.
+ enum LabelSource {
+ UNKNOWN, // The source is unknown.
+ LABEL_TAG,
+ P_TAG,
+ DIV_TABLE,
+ TD_TAG,
+ DD_TAG,
+ LI_TAG,
+ PLACE_HOLDER,
+ COMBINED, // Combined with various elements.
+ VALUE, // label is the value of element.
+ };
+
FormFieldData();
FormFieldData(const FormFieldData& other);
~FormFieldData();
@@ -99,6 +113,10 @@ struct FormFieldData {
// value is "US" and the contents are "United States".
std::vector<base::string16> option_values;
std::vector<base::string16> option_contents;
+
+ // Password Manager doesn't use labels nor client side nor server side, so
+ // label_source isn't in serialize methods.
+ LabelSource label_source;
};
// Serialize and deserialize FormFieldData. These are used when FormData objects
diff --git a/chromium/components/autofill/core/common/save_password_progress_logger.cc b/chromium/components/autofill/core/common/save_password_progress_logger.cc
index 3eb32852cc5..fd221d456e2 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.cc
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.cc
@@ -272,8 +272,8 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Ignore other possible usernames";
case SavePasswordProgressLogger::STRING_ON_PASSWORD_FORMS_RENDERED_METHOD:
return "PasswordManager::OnPasswordFormsRendered";
- case SavePasswordProgressLogger::STRING_ON_IN_PAGE_NAVIGATION:
- return "PasswordManager::OnInPageNavigation";
+ case SavePasswordProgressLogger::STRING_ON_SAME_DOCUMENT_NAVIGATION:
+ return "PasswordManager::OnSameDocumentNavigation";
case SavePasswordProgressLogger::STRING_ON_ASK_USER_OR_SAVE_PASSWORD:
return "PasswordManager::AskUserOrSavePassword";
case SavePasswordProgressLogger::STRING_CAN_PROVISIONAL_MANAGER_SAVE_METHOD:
diff --git a/chromium/components/autofill/core/common/save_password_progress_logger.h b/chromium/components/autofill/core/common/save_password_progress_logger.h
index e2770ac9d3a..5e0679d8068 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.h
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.h
@@ -94,7 +94,7 @@ class SavePasswordProgressLogger {
STRING_PROVISIONALLY_SAVED_FORM,
STRING_IGNORE_POSSIBLE_USERNAMES,
STRING_ON_PASSWORD_FORMS_RENDERED_METHOD,
- STRING_ON_IN_PAGE_NAVIGATION,
+ STRING_ON_SAME_DOCUMENT_NAVIGATION,
STRING_ON_ASK_USER_OR_SAVE_PASSWORD,
STRING_CAN_PROVISIONAL_MANAGER_SAVE_METHOD,
STRING_NO_PROVISIONAL_SAVE_MANAGER,
diff --git a/chromium/components/autofill/ios/browser/BUILD.gn b/chromium/components/autofill/ios/browser/BUILD.gn
index a02d9c023b7..53cba6a9bb1 100644
--- a/chromium/components/autofill/ios/browser/BUILD.gn
+++ b/chromium/components/autofill/ios/browser/BUILD.gn
@@ -13,6 +13,8 @@ source_set("browser") {
"autofill_driver_ios.h",
"autofill_driver_ios.mm",
"autofill_driver_ios_bridge.h",
+ "autofill_switches.cc",
+ "autofill_switches.h",
"autofill_util.h",
"autofill_util.mm",
"credit_card_util.h",
diff --git a/chromium/components/autofill/ios/browser/autofill_agent.mm b/chromium/components/autofill/ios/browser/autofill_agent.mm
index 53851ff4097..a2458ab795a 100644
--- a/chromium/components/autofill/ios/browser/autofill_agent.mm
+++ b/chromium/components/autofill/ios/browser/autofill_agent.mm
@@ -390,14 +390,9 @@ void GetFormAndField(autofill::FormData* form,
return NO;
}
- // Returned data should be a dictionary.
- const base::DictionaryValue* data;
- if (!dataJson->GetAsDictionary(&data))
- return NO;
-
- // Get the list of forms.
+ // Returned data should be a list of forms.
const base::ListValue* formsList;
- if (!data->GetList("forms", &formsList))
+ if (!dataJson->GetAsList(&formsList))
return NO;
// Iterate through all the extracted forms and copy the data from JSON into
@@ -721,6 +716,7 @@ void GetFormAndField(autofill::FormData* form,
if (pageProcessed_)
return;
pageProcessed_ = YES;
+ [jsAutofillManager_ addJSDelay];
popupDelegate_.reset();
suggestionsAvailableCompletion_ = nil;
diff --git a/chromium/components/autofill/ios/browser/autofill_switches.cc b/chromium/components/autofill/ios/browser/autofill_switches.cc
new file mode 100644
index 00000000000..50df19338ac
--- /dev/null
+++ b/chromium/components/autofill/ios/browser/autofill_switches.cc
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/ios/browser/autofill_switches.h"
+#include "build/build_config.h"
+
+namespace autofill {
+namespace switches {
+
+// The delay between filling two fields.
+const char kAutofillIOSDelayBetweenFields[] =
+ "autofill-ios-delay-between-fields";
+
+} // namespace switches
+} // namespace autofill
diff --git a/chromium/components/autofill/ios/browser/autofill_switches.h b/chromium/components/autofill/ios/browser/autofill_switches.h
new file mode 100644
index 00000000000..c48dea0e2db
--- /dev/null
+++ b/chromium/components/autofill/ios/browser/autofill_switches.h
@@ -0,0 +1,18 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_SWITCHES_H_
+#define COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_SWITCHES_H_
+
+#include "build/build_config.h"
+
+namespace autofill {
+namespace switches {
+
+extern const char kAutofillIOSDelayBetweenFields[];
+
+} // namespace switches
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_SWITCHES_H_
diff --git a/chromium/components/autofill/ios/browser/js_autofill_manager.h b/chromium/components/autofill/ios/browser/js_autofill_manager.h
index 741826254fa..02764c445e7 100644
--- a/chromium/components/autofill/ios/browser/js_autofill_manager.h
+++ b/chromium/components/autofill/ios/browser/js_autofill_manager.h
@@ -49,6 +49,9 @@
// Marks up the form with autofill field prediction data (diagnostic tool).
- (void)fillPredictionData:(NSString*)dataString;
+// Adds a delay between filling the form fields.
+- (void)addJSDelay;
+
// Designated initializer. |receiver| should not be nil.
- (instancetype)initWithReceiver:(CRWJSInjectionReceiver*)receiver
NS_DESIGNATED_INITIALIZER;
diff --git a/chromium/components/autofill/ios/browser/js_autofill_manager.mm b/chromium/components/autofill/ios/browser/js_autofill_manager.mm
index ea192bccaa9..765b2eec95e 100644
--- a/chromium/components/autofill/ios/browser/js_autofill_manager.mm
+++ b/chromium/components/autofill/ios/browser/js_autofill_manager.mm
@@ -4,10 +4,13 @@
#import "components/autofill/ios/browser/js_autofill_manager.h"
+#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/json/string_escape.h"
#include "base/logging.h"
#include "base/mac/foundation_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "components/autofill/ios/browser/autofill_switches.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
@@ -27,6 +30,23 @@
return self;
}
+- (void)addJSDelay {
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(
+ autofill::switches::kAutofillIOSDelayBetweenFields)) {
+ std::string delayString = command_line->GetSwitchValueASCII(
+ autofill::switches::kAutofillIOSDelayBetweenFields);
+ int commandLineDelay = 0;
+ if (base::StringToInt(delayString, &commandLineDelay)) {
+ NSString* setDelayJS =
+ [NSString stringWithFormat:@"__gCrWeb.autofill.setDelay(%d);",
+ commandLineDelay];
+ [_receiver executeJavaScript:setDelayJS completionHandler:nil];
+ }
+ }
+}
+
- (void)fetchFormsWithMinimumRequiredFieldsCount:(NSUInteger)requiredFieldsCount
completionHandler:
(void (^)(NSString*))completionHandler {
diff --git a/chromium/components/autofill/ios/browser/resources/autofill_controller.js b/chromium/components/autofill/ios/browser/resources/autofill_controller.js
index 7d7ad0314ab..a6995b4277f 100644
--- a/chromium/components/autofill/ios/browser/resources/autofill_controller.js
+++ b/chromium/components/autofill/ios/browser/resources/autofill_controller.js
@@ -18,32 +18,31 @@
goog.provide('__crWeb.autofill');
/**
- * @typedef {{
- * name: string,
- * value: string,
- * form_control_type: string,
- * autocomplete_attributes: string,
- * max_length: number,
- * is_autofilled: boolean,
- * is_checkable: boolean,
- * is_focusable: boolean,
- * should_autocomplete: boolean,
- * role: number,
- * option_contents: Array<string>,
- * option_values: Array<string>
- * }}
- */
+ * @typedef {{
+ * name: string,
+ * value: string,
+ * form_control_type: string,
+ * autocomplete_attributes: string,
+ * max_length: number,
+ * is_autofilled: boolean,
+ * is_checkable: boolean,
+ * is_focusable: boolean,
+ * should_autocomplete: boolean,
+ * role: number,
+ * option_contents: Array<string>,
+ * option_values: Array<string>
+ * }}
+ */
var AutofillFormFieldData;
/**
- * @typedef {{
- * name: string,
- * method: string,
- * origin: string,
- * action: string,
- * fields: Array<AutofillFormFieldData>
- * }}
- */
+ * @typedef {{
+ * name: string,
+ * origin: string,
+ * action: string,
+ * fields: Array<AutofillFormFieldData>
+ * }}
+ */
var AutofillFormData;
/* Beginning of anonymous object. */
@@ -141,6 +140,16 @@ __gCrWeb.autofill.EXTRACT_MASK_OPTIONS = 1 << 2;
__gCrWeb.autofill.ROLE_ATTRIBUTE_PRESENTATION = 0;
/**
+ * The delay between filling two fields
+ *
+ * Page need time to propagate the events after setting one field. Add a delay
+ * between filling two fields. In milliseconds.
+ *
+ * @type {number}
+ */
+__gCrWeb.autofill.delayBetweenFieldFillingMs = 50;
+
+/**
* The last element that was autofilled.
*
* @type {Element}
@@ -155,6 +164,15 @@ __gCrWeb.autofill.lastAutoFilledElement = null;
__gCrWeb.autofill.styleInjected = false;
/**
+ * Sets the delay between fields when autofilling forms.
+ *
+ * @param {number} delay The new delay in milliseconds.
+ */
+__gCrWeb.autofill.setDelay = function(delay) {
+ __gCrWeb.autofill.delayBetweenFieldFillingMs = delay;
+};
+
+/**
* Searches an element's ancestors to see if the element is inside a <form> or
* <fieldset>.
*
@@ -265,7 +283,7 @@ function scanFormControlElements_(controlElements) {
function getUnownedAutofillableFormFieldElements_(elements, fieldsets) {
var unownedFieldsetChildren = [];
for (var i = 0; i < elements.length; ++i) {
- if (__gCrWeb.common.isFormControlElement(elements[i])) {
+ if (__gCrWeb.form.isFormControlElement(elements[i])) {
if (!elements[i].form) {
unownedFieldsetChildren.push(elements[i]);
}
@@ -309,8 +327,8 @@ function getUnownedAutofillableFormFieldElements_(elements, fieldsets) {
* @return {boolean} Whether there are fields and not too many fields in the
* form.
*/
-function extractFieldsFromControlElements_(controlElements, extractMask,
- formFields, fieldsExtracted, elementArray) {
+function extractFieldsFromControlElements_(
+ controlElements, extractMask, formFields, fieldsExtracted, elementArray) {
for (var i = 0; i < controlElements.length; ++i) {
fieldsExtracted[i] = false;
elementArray[i] = null;
@@ -347,13 +365,11 @@ function extractFieldsFromControlElements_(controlElements, extractMask,
* @return {boolean} Whether the node is visible or not.
*/
function isVisibleNode_(node) {
- if (!node)
- return false;
+ if (!node) return false;
if (node.nodeType === Node.ELEMENT_NODE) {
- var style = window.getComputedStyle(/** @type {Element} */(node));
- if (style.visibility == 'hidden' || style.display == 'none')
- return false;
+ var style = window.getComputedStyle(/** @type {Element} */ (node));
+ if (style.visibility == 'hidden' || style.display == 'none') return false;
}
// Verify all ancestors are focusable.
@@ -385,8 +401,8 @@ function isVisibleNode_(node) {
* were processed.
* @param {Array<?AutofillFormFieldData>} elementArray The extracted fields.
*/
-function matchLabelsAndFields_(labels, formElement, controlElements,
- elementArray) {
+function matchLabelsAndFields_(
+ labels, formElement, controlElements, elementArray) {
for (var index = 0; index < labels.length; ++index) {
var label = labels[index];
var fieldElement = label.control;
@@ -395,8 +411,7 @@ function matchLabelsAndFields_(labels, formElement, controlElements,
// Sometimes site authors will incorrectly specify the corresponding
// field element's name rather than its id, so we compensate here.
var elementName = label.htmlFor;
- if (!elementName)
- continue;
+ if (!elementName) continue;
// Look through the list for elements with this name. There can actually
// be more than one. In this case, the label may not be particularly
// useful, so just discard it.
@@ -412,8 +427,8 @@ function matchLabelsAndFields_(labels, formElement, controlElements,
}
}
}
- } else if (fieldElement.form != formElement ||
- fieldElement.type === 'hidden') {
+ } else if (
+ fieldElement.form != formElement || fieldElement.type === 'hidden') {
continue;
} else {
// Typical case: look up |fieldData| in |elementArray|.
@@ -426,8 +441,7 @@ function matchLabelsAndFields_(labels, formElement, controlElements,
}
}
- if (!fieldData)
- continue;
+ if (!fieldData) continue;
if (!('label' in fieldData)) {
fieldData['label'] = '';
@@ -471,13 +485,14 @@ function matchLabelsAndFields_(labels, formElement, controlElements,
* formElement.
* @param {AutofillFormData} form Form to fill in the AutofillFormData
* information of formElement.
- * @param {AutofillFormFieldData|null} field Field to fill in the form field
+ * @param {?AutofillFormFieldData} field Field to fill in the form field
* information of formControlElement.
* @return {boolean} Whether there are fields and not too many fields in the
* form.
*/
-function formOrFieldsetsToFormData_(formElement, formControlElement,
- fieldsets, controlElements, extractMask, form, field) {
+function formOrFieldsetsToFormData_(
+ formElement, formControlElement, fieldsets, controlElements, extractMask,
+ form, field) {
// This should be a map from a control element to the AutofillFormFieldData.
// However, without Map support, it's just an Array of AutofillFormFieldData.
var elementArray = [];
@@ -489,9 +504,9 @@ function formOrFieldsetsToFormData_(formElement, formControlElement,
// meets the requirements and thus will be in the resulting |form|.
var fieldsExtracted = [];
- if (!extractFieldsFromControlElements_(controlElements, extractMask,
- formFields, fieldsExtracted,
- elementArray)) {
+ if (!extractFieldsFromControlElements_(
+ controlElements, extractMask, formFields, fieldsExtracted,
+ elementArray)) {
return false;
}
@@ -519,8 +534,7 @@ function formOrFieldsetsToFormData_(formElement, formControlElement,
i < controlElements.length && fieldIdx < formFields.length; ++i) {
// This field didn't meet the requirements, so don't try to find a label
// for it.
- if (!fieldsExtracted[i])
- continue;
+ if (!fieldsExtracted[i]) continue;
var controlElement = controlElements[i];
var currentField = formFields[fieldIdx];
@@ -533,8 +547,7 @@ function formOrFieldsetsToFormData_(formElement, formControlElement,
currentField['label'].substr(0, __gCrWeb.autofill.MAX_DATA_LENGTH);
}
- if (controlElement === formControlElement)
- field = formFields[fieldIdx];
+ if (controlElement === formControlElement) field = formFields[fieldIdx];
++fieldIdx;
}
@@ -551,13 +564,11 @@ function formOrFieldsetsToFormData_(formElement, formControlElement,
*
* @param {number} requiredFields The minimum number of fields forms must have
* to be extracted.
- * @return {string} A JSON encoded object with object['forms'] containing the
- * forms data.
+ * @return {string} A JSON encoded an array of the forms data.
*/
__gCrWeb.autofill['extractForms'] = function(requiredFields) {
- var results = new __gCrWeb.common.JSONSafeObject;
- results['forms'] = __gCrWeb.autofill.extractNewForms(requiredFields);
- return __gCrWeb.stringify(results);
+ var forms = __gCrWeb.autofill.extractNewForms(requiredFields);
+ return __gCrWeb.stringify(forms);
};
/**
@@ -567,7 +578,7 @@ __gCrWeb.autofill['extractForms'] = function(requiredFields) {
*/
__gCrWeb.autofill['fillActiveFormField'] = function(data) {
var activeElement = document.activeElement;
- if (data['name'] !== __gCrWeb['common'].getFieldIdentifier(activeElement)) {
+ if (data['name'] !== __gCrWeb.form.getFieldIdentifier(activeElement)) {
return;
}
__gCrWeb.autofill.lastAutoFilledElement = activeElement;
@@ -589,10 +600,10 @@ __gCrWeb.autofill['fillForm'] = function(data, forceFillFieldName) {
if (!__gCrWeb.autofill.styleInjected) {
var style = document.createElement('style');
style.textContent = '[chrome-autofilled] {' +
- 'background-color:#FAFFBD !important;' +
- 'background-image:none !important;' +
- 'color:#000000 !important;' +
- '}';
+ 'background-color:#FAFFBD !important;' +
+ 'background-image:none !important;' +
+ 'color:#000000 !important;' +
+ '}';
document.head.appendChild(style);
__gCrWeb.autofill.styleInjected = true;
}
@@ -606,21 +617,22 @@ __gCrWeb.autofill['fillForm'] = function(data, forceFillFieldName) {
}
};
- var form = __gCrWeb.common.getFormElementFromIdentifier(data.formName);
+ var form = __gCrWeb.form.getFormElementFromIdentifier(data.formName);
var controlElements = [];
if (form) {
- controlElements = __gCrWeb.common.getFormControlElements(form);
+ controlElements = __gCrWeb.form.getFormControlElements(form);
} else {
var fieldsets = [];
controlElements =
getUnownedAutofillableFormFieldElements_(document.all, fieldsets);
}
+ var delay = 0;
for (var i = 0; i < controlElements.length; ++i) {
var element = controlElements[i];
if (!__gCrWeb.autofill.isAutofillableElement(element)) {
continue;
}
- var fieldName = __gCrWeb['common'].getFieldIdentifier(element);
+ var fieldName = __gCrWeb.form.getFieldIdentifier(element);
// Skip non-empty fields unless this is the forceFillFieldName or it's a
// 'select-one' element. 'select-one' elements are always autofilled even
@@ -633,20 +645,24 @@ __gCrWeb.autofill['fillForm'] = function(data, forceFillFieldName) {
// Don't fill field if source value is empty or missing.
var value = data.fields[fieldName];
- if (!value)
- continue;
+ if (!value) continue;
if (__gCrWeb.autofill.isTextInput(element) ||
__gCrWeb.autofill.isTextAreaElement(element) ||
__gCrWeb.autofill.isSelectElement(element)) {
- __gCrWeb.common.setInputElementValue(value, element, true);
+ (function (_element, _value, _delay) {
+ window.setTimeout(function() {
+ __gCrWeb.fill.setInputElementValue(_value, _element, true);
+ _element.setAttribute('chrome-autofilled', '');
+ _element.isAutofilled = true;
+ _element.addEventListener('input', controlElementInputListener);
+ }, _delay);})(element, value, delay);
+ delay = delay + __gCrWeb.autofill.delayBetweenFieldFillingMs;
+ } else if (__gCrWeb.autofill.isCheckableElement(element)) {
+ // TODO(bondd): Handle __gCrWeb.autofill.isCheckableElement(element) ==
+ // true. |is_checked| is not currently passed in by the caller.
}
- // TODO(bondd): Handle __gCrWeb.autofill.isCheckableElement(element) ==
- // true. |is_checked| is not currently passed in by the caller.
- element.setAttribute('chrome-autofilled', '');
- element.isAutofilled = true;
- element.addEventListener('input', controlElementInputListener);
}
if (form) {
@@ -654,7 +670,7 @@ __gCrWeb.autofill['fillForm'] = function(data, forceFillFieldName) {
// Individual control elements may be left with 'input' event listeners but
// they are harmless.
var formResetListener = function(evt) {
- var controlElements = __gCrWeb.common.getFormControlElements(evt.target);
+ var controlElements = __gCrWeb.form.getFormControlElements(evt.target);
for (var i = 0; i < controlElements.length; ++i) {
controlElements[i].removeAttribute('chrome-autofilled');
controlElements[i].isAutofilled = false;
@@ -676,36 +692,42 @@ __gCrWeb.autofill['fillForm'] = function(data, forceFillFieldName) {
* getFormIdentifier).
*/
__gCrWeb.autofill['clearAutofilledFields'] = function(formName) {
- var form = __gCrWeb.common.getFormElementFromIdentifier(formName);
+ var form = __gCrWeb.form.getFormElementFromIdentifier(formName);
var controlElements = [];
if (form) {
- controlElements = __gCrWeb.common.getFormControlElements(form);
+ controlElements = __gCrWeb.form.getFormControlElements(form);
} else {
var fieldsets = [];
controlElements =
getUnownedAutofillableFormFieldElements_(document.all, fieldsets);
}
+ var delay = 0;
for (var i = 0; i < controlElements.length; ++i) {
var element = controlElements[i];
- if (!element.isAutofilled || element.disabled)
- continue;
+ if (!element.isAutofilled || element.disabled) continue;
+ var value = null;
if (__gCrWeb.autofill.isTextInput(element) ||
__gCrWeb.autofill.isTextAreaElement(element)) {
- __gCrWeb.common.setInputElementValue('', element, true);
+ value = '';
} else if (__gCrWeb.autofill.isSelectElement(element)) {
// Reset to the first index.
// TODO(bondd): Store initial values and reset to the correct one here.
- __gCrWeb.common.setInputElementValue(element.options[0].value,
- element, true);
+ value = element.options[0].value;
} else if (__gCrWeb.autofill.isCheckableElement(element)) {
// TODO(bondd): Handle checkable elements. They aren't properly supported
// by iOS Autofill yet.
}
-
- element.removeAttribute('chrome-autofilled');
- element.isAutofilled = false;
+ if (value !== null) {
+ (function (_element, _value, _delay) {
+ window.setTimeout(function() {
+ __gCrWeb.fill.setInputElementValue(_value, _element, true);
+ _element.removeAttribute('chrome-autofilled');
+ _element.isAutofilled = false;
+ }, _delay);})(element, value, delay);
+ delay = delay + __gCrWeb.autofill.delayBetweenFieldFillingMs;
+ }
}
};
@@ -733,7 +755,9 @@ __gCrWeb.autofill['clearAutofilledFields'] = function(formName) {
__gCrWeb.autofill.extractNewForms = function(minimumRequiredFields) {
var forms = [];
// Protect against custom implementation of Array.toJSON in host pages.
- /** @suppress {checkTypes} */(function() { forms.toJSON = null; })();
+ /** @suppress {checkTypes} */ (function() {
+ forms.toJSON = null;
+ })();
/** @type {HTMLCollection} */
var webForms = document.forms;
@@ -754,7 +778,7 @@ __gCrWeb.autofill.extractNewForms = function(minimumRequiredFields) {
var form = new __gCrWeb['common'].JSONSafeObject;
if (!__gCrWeb.autofill.webFormElementToFormData(
- window, formElement, null, extractMask, form, null /* field */)) {
+ window, formElement, null, extractMask, form, null /* field */)) {
continue;
}
@@ -781,8 +805,8 @@ __gCrWeb.autofill.extractNewForms = function(minimumRequiredFields) {
if (hasUnownedForm) {
numFieldsSeen += unownedForm['fields'].length;
if (numFieldsSeen <= __gCrWeb.autofill.MAX_PARSEABLE_FIELDS) {
- var interesting = isFormInteresting_(unownedForm,
- numEditableUnownedElements, minimumRequiredFields);
+ var interesting = isFormInteresting_(
+ unownedForm, numEditableUnownedElements, minimumRequiredFields);
if (interesting) {
forms.push(unownedForm);
}
@@ -818,7 +842,7 @@ __gCrWeb.autofill.extractNewForms = function(minimumRequiredFields) {
* formElement.
* @param {AutofillFormData} form Form to fill in the AutofillFormData
* information of formElement.
- * @param {AutofillFormFieldData|null} field Field to fill in the form field
+ * @param {?AutofillFormFieldData} field Field to fill in the form field
* information of formControlElement.
* @return {boolean} Whether there are fields and not too many fields in the
* form.
@@ -829,17 +853,11 @@ __gCrWeb.autofill.webFormElementToFormData = function(
return false;
}
- form['name'] = __gCrWeb.common.getFormIdentifier(formElement);
- // TODO(thestig): Check if method is unused and remove.
- var method = formElement.getAttribute('method');
- if (method) {
- form['method'] = method;
- }
- form['origin'] = __gCrWeb.common.removeQueryAndReferenceFromURL(
- frame.location.href);
+ form['name'] = __gCrWeb.form.getFormIdentifier(formElement);
+ form['origin'] =
+ __gCrWeb.common.removeQueryAndReferenceFromURL(frame.location.href);
form['action'] = __gCrWeb.common.absoluteURL(
- frame.document,
- formElement.getAttribute('action'));
+ frame.document, formElement.getAttribute('action'));
// Note different from form_autofill_util.cc version of this method, which
// computes |form.action| using document.completeURL(form_element.action())
@@ -848,10 +866,11 @@ __gCrWeb.autofill.webFormElementToFormData = function(
// valid, which is computed by creating a <a> element, and we don't check if
// the action is valid.
- var controlElements = __gCrWeb['common'].getFormControlElements(formElement);
+ var controlElements = __gCrWeb.form.getFormControlElements(formElement);
- return formOrFieldsetsToFormData_(formElement, formControlElement,
- [] /* fieldsets */, controlElements, extractMask, form, field);
+ return formOrFieldsetsToFormData_(
+ formElement, formControlElement, [] /* fieldsets */, controlElements,
+ extractMask, form, field);
};
/**
@@ -898,17 +917,17 @@ function unownedFormElementsAndFieldSetsToFormData_(
}
form['name'] = '';
- form['origin'] = __gCrWeb.common.removeQueryAndReferenceFromURL(
- frame.location.href);
- form['action'] = ''
+ form['origin'] =
+ __gCrWeb.common.removeQueryAndReferenceFromURL(frame.location.href);
+ form['action'] = '';
form['is_form_tag'] = false;
// For now this restriction only applies to English-language pages, because
// the keywords are not translated. Note that an empty "lang" attribute
// counts as English.
if (document.documentElement.hasAttribute('lang') &&
- !document.documentElement.getAttribute('lang').
- toLowerCase().startsWith('en')) {
+ !document.documentElement.getAttribute('lang').toLowerCase().startsWith(
+ 'en')) {
return formOrFieldsetsToFormData_(
null /* formElement*/, null /* formControlElement */, fieldsets,
controlElements, extractMask, form, null /* field */);
@@ -919,14 +938,8 @@ function unownedFormElementsAndFieldSetsToFormData_(
// The keywords are defined in
// UnownedCheckoutFormElementsAndFieldSetsToFormData in
// components/autofill/content/renderer/form_autofill_util.cc
- var keywords = [
- 'payment',
- 'checkout',
- 'address',
- 'delivery',
- 'shipping',
- 'wallet'
- ];
+ var keywords =
+ ['payment', 'checkout', 'address', 'delivery', 'shipping', 'wallet'];
var count = keywords.length;
for (var index = 0; index < count; index++) {
@@ -957,7 +970,7 @@ function unownedFormElementsAndFieldSetsToFormData_(
*/
__gCrWeb.autofill.hasTagName = function(node, tag) {
return node.nodeType === Node.ELEMENT_NODE &&
- /** @type {Element} */(node).tagName === tag.toUpperCase();
+ /** @type {Element} */ (node).tagName === tag.toUpperCase();
};
/**
@@ -973,8 +986,8 @@ __gCrWeb.autofill.hasTagName = function(node, tag) {
*/
__gCrWeb.autofill.isAutofillableElement = function(element) {
return __gCrWeb.autofill.isAutofillableInputElement(element) ||
- __gCrWeb.autofill.isSelectElement(element) ||
- __gCrWeb.autofill.isTextAreaElement(element);
+ __gCrWeb.autofill.isSelectElement(element) ||
+ __gCrWeb.autofill.isTextAreaElement(element);
};
/**
@@ -1055,8 +1068,8 @@ __gCrWeb.autofill.findChildTextInner = function(node, depth, divsToSkip) {
// Skip over comments.
if (node.nodeType === Node.COMMENT_NODE) {
- return __gCrWeb.autofill.findChildTextInner(node.nextSibling, depth - 1,
- divsToSkip);
+ return __gCrWeb.autofill.findChildTextInner(
+ node.nextSibling, depth - 1, divsToSkip);
}
if (node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.TEXT_NODE) {
@@ -1065,12 +1078,11 @@ __gCrWeb.autofill.findChildTextInner = function(node, depth, divsToSkip) {
// Ignore elements known not to contain inferable labels.
if (node.nodeType === Node.ELEMENT_NODE) {
- if (node.tagName === 'OPTION' ||
- node.tagName === 'SCRIPT' ||
+ if (node.tagName === 'OPTION' || node.tagName === 'SCRIPT' ||
node.tagName === 'NOSCRIPT') {
return '';
}
- if (__gCrWeb.common.isFormControlElement(/** @type {Element} */ (node))) {
+ if (__gCrWeb.form.isFormControlElement(/** @type {Element} */ (node))) {
var input = /** @type {FormControlElement} */ (node);
if (__gCrWeb.autofill.isAutofillableElement(input)) {
return '';
@@ -1091,31 +1103,29 @@ __gCrWeb.autofill.findChildTextInner = function(node, depth, divsToSkip) {
if (node.nodeType === Node.TEXT_NODE && !nodeText) {
// In the C++ version, this text node would have been stripped completely.
// Just pass the buck.
- return __gCrWeb.autofill.findChildTextInner(node.nextSibling, depth,
- divsToSkip);
+ return __gCrWeb.autofill.findChildTextInner(
+ node.nextSibling, depth, divsToSkip);
}
// Recursively compute the children's text.
// Preserve inter-element whitespace separation.
- var childText = __gCrWeb.autofill.findChildTextInner(node.firstChild,
- depth - 1,
- divsToSkip);
+ var childText = __gCrWeb.autofill.findChildTextInner(
+ node.firstChild, depth - 1, divsToSkip);
var addSpace = node.nodeType === Node.TEXT_NODE && !nodeText;
// Emulate apparently incorrect Chromium behavior tracked in crbug 239819.
addSpace = false;
- nodeText = __gCrWeb.autofill.combineAndCollapseWhitespace(nodeText,
- childText, addSpace);
+ nodeText = __gCrWeb.autofill.combineAndCollapseWhitespace(
+ nodeText, childText, addSpace);
// Recursively compute the siblings' text.
// Again, preserve inter-element whitespace separation.
- var siblingText = __gCrWeb.autofill.findChildTextInner(node.nextSibling,
- depth - 1,
- divsToSkip);
+ var siblingText = __gCrWeb.autofill.findChildTextInner(
+ node.nextSibling, depth - 1, divsToSkip);
addSpace = node.nodeType === Node.TEXT_NODE && !nodeText;
// Emulate apparently incorrect Chromium behavior tracked in crbug 239819.
addSpace = false;
- nodeText = __gCrWeb.autofill.combineAndCollapseWhitespace(nodeText,
- siblingText, addSpace);
+ nodeText = __gCrWeb.autofill.combineAndCollapseWhitespace(
+ nodeText, siblingText, addSpace);
return nodeText;
};
@@ -1139,8 +1149,8 @@ __gCrWeb.autofill.findChildTextWithIgnoreList = function(node, divsToSkip) {
var child = node.firstChild;
var kChildSearchDepth = 10;
- var nodeText = __gCrWeb.autofill.findChildTextInner(child, kChildSearchDepth,
- divsToSkip);
+ var nodeText = __gCrWeb.autofill.findChildTextInner(
+ child, kChildSearchDepth, divsToSkip);
nodeText = nodeText.trim();
return nodeText;
};
@@ -1216,9 +1226,8 @@ __gCrWeb.autofill.inferLabelFromSibling = function(element, forward) {
var value = __gCrWeb.autofill.findChildText(sibling);
// A text node's value will be empty if it is for a line break.
var addSpace = nodeType === Node.TEXT_NODE && value.length === 0;
- inferredLabel =
- __gCrWeb.autofill.combineAndCollapseWhitespace(
- value, inferredLabel, addSpace);
+ inferredLabel = __gCrWeb.autofill.combineAndCollapseWhitespace(
+ value, inferredLabel, addSpace);
continue;
}
@@ -1302,20 +1311,20 @@ __gCrWeb.autofill.inferLabelFromPlaceholder = function(element) {
};
/**
-* Helper for |InferLabelForElement()| that infers a label, if possible, from
-* the value attribute when it is present and user has not typed in (if
-* element's value attribute is same as the element's value).
-*
-* It is based on the logic in
-* string16 InferLabelFromValueAttr(const WebFormControlElement& element)
-* in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
-*
-* @param {FormControlElement} element An element to examine.
-* @return {string} The label of element.
-*/
+ * Helper for |InferLabelForElement()| that infers a label, if possible, from
+ * the value attribute when it is present and user has not typed in (if
+ * element's value attribute is same as the element's value).
+ *
+ * It is based on the logic in
+ * string16 InferLabelFromValueAttr(const WebFormControlElement& element)
+ * in chromium/src/components/autofill/content/renderer/form_autofill_util.cc.
+ *
+ * @param {FormControlElement} element An element to examine.
+ * @return {string} The label of element.
+ */
__gCrWeb.autofill.InferLabelFromValueAttr = function(element) {
- if (!element || !element.value || !element.hasAttribute("value") ||
- element.value != element.getAttribute("value")) {
+ if (!element || !element.value || !element.hasAttribute('value') ||
+ element.value != element.getAttribute('value')) {
return '';
}
@@ -1358,8 +1367,7 @@ __gCrWeb.autofill.inferLabelFromListItem = function(element) {
}
var parentNode = element.parentNode;
- while (parentNode &&
- parentNode.nodeType === Node.ELEMENT_NODE &&
+ while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
!__gCrWeb.autofill.hasTagName(parentNode, 'li')) {
parentNode = parentNode.parentNode;
}
@@ -1391,8 +1399,7 @@ __gCrWeb.autofill.inferLabelFromTableColumn = function(element) {
}
var parentNode = element.parentNode;
- while (parentNode &&
- parentNode.nodeType === Node.ELEMENT_NODE &&
+ while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
!__gCrWeb.autofill.hasTagName(parentNode, 'td')) {
parentNode = parentNode.parentNode;
}
@@ -1479,12 +1486,11 @@ __gCrWeb.autofill.inferLabelFromTableRow = function(element) {
// Combine left + right.
cellCount += cellPosition;
- cellPositionEnd += cellPosition
+ cellPositionEnd += cellPosition;
// Find the current row.
var parentNode = element.parentNode;
- while (parentNode &&
- parentNode.nodeType === Node.ELEMENT_NODE &&
+ while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
!__gCrWeb.autofill.hasTagName(parentNode, 'tr')) {
parentNode = parentNode.parentNode;
}
@@ -1562,13 +1568,10 @@ __gCrWeb.autofill.isTraversableContainerElement = function(node) {
return false;
}
- var tagName = /** @type {Element} */(node).tagName;
- return (tagName === "DD" ||
- tagName === "DIV" ||
- tagName === "FIELDSET" ||
- tagName === "LI" ||
- tagName === "TD" ||
- tagName === "TABLE");
+ var tagName = /** @type {Element} */ (node).tagName;
+ return (
+ tagName === 'DD' || tagName === 'DIV' || tagName === 'FIELDSET' ||
+ tagName === 'LI' || tagName === 'TD' || tagName === 'TABLE');
};
/**
@@ -1596,7 +1599,7 @@ __gCrWeb.autofill.inferLabelFromEnclosingLabel = function(element) {
return __gCrWeb.autofill.findChildText(node);
}
return '';
-}
+};
/**
* Helper for |InferLabelForElement()| that infers a label, if possible, from
@@ -1652,13 +1655,14 @@ __gCrWeb.autofill.inferLabelFromDivTable = function(element) {
}
lookingForParent = false;
- } else if (!lookingForParent &&
- __gCrWeb.autofill.hasTagName(node, 'label')) {
+ } else if (
+ !lookingForParent && __gCrWeb.autofill.hasTagName(node, 'label')) {
if (!node.control) {
inferredLabel = __gCrWeb.autofill.findChildText(node);
}
- } else if (lookingForParent &&
- __gCrWeb.autofill.isTraversableContainerElement(node)) {
+ } else if (
+ lookingForParent &&
+ __gCrWeb.autofill.isTraversableContainerElement(node)) {
// If the element is in a non-div container, its label most likely is too.
break;
}
@@ -1698,8 +1702,7 @@ __gCrWeb.autofill.inferLabelFromDefinitionList = function(element) {
}
var parentNode = element.parentNode;
- while (parentNode &&
- parentNode.nodeType === Node.ELEMENT_NODE &&
+ while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
!__gCrWeb.autofill.hasTagName(parentNode, 'dd')) {
parentNode = parentNode.parentNode;
}
@@ -1714,8 +1717,7 @@ __gCrWeb.autofill.inferLabelFromDefinitionList = function(element) {
previous = previous.previousSibling;
}
- if (!previous || !__gCrWeb.autofill.hasTagName(previous, 'dt'))
- return '';
+ if (!previous || !__gCrWeb.autofill.hasTagName(previous, 'dt')) return '';
return __gCrWeb.autofill.findChildText(previous);
};
@@ -1741,7 +1743,7 @@ __gCrWeb.autofill.ancestorTagNames = function(element) {
parentNode = parentNode.parentNode;
}
return tagNames;
-}
+};
/**
* Infers corresponding label for |element| from surrounding context in the DOM,
@@ -1785,19 +1787,19 @@ __gCrWeb.autofill.inferLabelForElement = function(element) {
}
seenTagNames[tagName] = true;
- if (tagName === "LABEL") {
+ if (tagName === 'LABEL') {
inferredLabel = __gCrWeb.autofill.inferLabelFromEnclosingLabel(element);
- } else if (tagName === "DIV") {
+ } else if (tagName === 'DIV') {
inferredLabel = __gCrWeb.autofill.inferLabelFromDivTable(element);
- } else if (tagName === "TD") {
+ } else if (tagName === 'TD') {
inferredLabel = __gCrWeb.autofill.inferLabelFromTableColumn(element);
if (!__gCrWeb.autofill.IsLabelValid(inferredLabel))
inferredLabel = __gCrWeb.autofill.inferLabelFromTableRow(element);
- } else if (tagName === "DD") {
+ } else if (tagName === 'DD') {
inferredLabel = __gCrWeb.autofill.inferLabelFromDefinitionList(element);
- } else if (tagName === "LI") {
+ } else if (tagName === 'LI') {
inferredLabel = __gCrWeb.autofill.inferLabelFromListItem(element);
- } else if (tagName === "FIELDSET") {
+ } else if (tagName === 'FIELDSET') {
break;
}
@@ -1829,8 +1831,7 @@ __gCrWeb.autofill.inferLabelForElement = function(element) {
* @param {Object} field A field that will contain the extracted option
* information.
*/
-__gCrWeb.autofill.getOptionStringsFromElement = function(
- selectElement, field) {
+__gCrWeb.autofill.getOptionStringsFromElement = function(selectElement, field) {
field['option_values'] = [];
// Protect against custom implementation of Array.toJSON in host pages.
field['option_values'].toJSON = null;
@@ -1880,13 +1881,13 @@ __gCrWeb.autofill.fillFormField = function(data, field) {
sanitizedValue = data['value'].substr(0, maxLength);
}
- __gCrWeb.common.setInputElementValue(sanitizedValue, field, true);
+ __gCrWeb.fill.setInputElementValue(sanitizedValue, field, true);
field.isAutofilled = true;
- } else if (__gCrWeb.autofill.isSelectElement(field)) {
- __gCrWeb.common.setInputElementValue(data['value'], field, true);
- } else if (__gCrWeb.autofill.isCheckableElement(field)) {
- __gCrWeb.common.setInputElementValue(data['is_checked'], field, true);
- }
+ } else if (__gCrWeb.autofill.isSelectElement(field)) {
+ __gCrWeb.fill.setInputElementValue(data['value'], field, true);
+ } else if (__gCrWeb.autofill.isCheckableElement(field)) {
+ __gCrWeb.fill.setInputElementValue(data['is_checked'], field, true);
+ }
};
/**
@@ -1971,7 +1972,7 @@ __gCrWeb.autofill.isCheckableElement = function(element) {
*/
__gCrWeb.autofill.isAutofillableInputElement = function(element) {
return __gCrWeb.autofill.isTextInput(element) ||
- __gCrWeb.autofill.isCheckableElement(element);
+ __gCrWeb.autofill.isCheckableElement(element);
};
/**
@@ -2002,21 +2003,21 @@ __gCrWeb.autofill.nodeValue = function(node) {
* @return {string} The value for |element|.
*/
__gCrWeb.autofill.value = function(element) {
- var value = element.value;
- if (__gCrWeb.autofill.isSelectElement(element)) {
- if (element.options.length > 0 && element.selectedIndex == 0 &&
- element.options[0].disabled &&
- !element.options[0].hasAttribute('selected')) {
- for (var i = 0; i < element.options.length; i++) {
- if (!element.options[i].disabled ||
- element.options[i].hasAttribute('selected')) {
- value = element.options[i].value;
- break;
- }
- }
- }
- }
- return (value || '').replace(/[\n\t]/gm, '');
+ var value = element.value;
+ if (__gCrWeb.autofill.isSelectElement(element)) {
+ if (element.options.length > 0 && element.selectedIndex == 0 &&
+ element.options[0].disabled &&
+ !element.options[0].hasAttribute('selected')) {
+ for (var i = 0; i < element.options.length; i++) {
+ if (!element.options[i].disabled ||
+ element.options[i].hasAttribute('selected')) {
+ value = element.options[i].value;
+ break;
+ }
+ }
+ }
+ }
+ return (value || '').replace(/[\n\t]/gm, '');
};
/**
@@ -2031,8 +2032,8 @@ __gCrWeb.autofill.value = function(element) {
* @param {Array<FormControlElement>} controlElements Set of control elements.
* @return {Array<FormControlElement>} The array of autofillable elements.
*/
-__gCrWeb.autofill.extractAutofillableElementsFromSet =
- function(controlElements) {
+__gCrWeb.autofill.extractAutofillableElementsFromSet = function(
+ controlElements) {
var autofillableElements = [];
for (var i = 0; i < controlElements.length; ++i) {
var element = controlElements[i];
@@ -2056,7 +2057,7 @@ __gCrWeb.autofill.extractAutofillableElementsFromSet =
* @return {Array<FormControlElement>} The array of autofillable elements.
*/
__gCrWeb.autofill.extractAutofillableElementsInForm = function(formElement) {
- var controlElements = __gCrWeb.common.getFormControlElements(formElement);
+ var controlElements = __gCrWeb.form.getFormControlElements(formElement);
return __gCrWeb.autofill.extractAutofillableElementsFromSet(controlElements);
};
@@ -2087,7 +2088,7 @@ __gCrWeb.autofill.webFormControlElementToFormField = function(
// The label is not officially part of a form control element; however, the
// labels for all form control elements are scraped from the DOM and set in
// form data.
- field['name'] = __gCrWeb['common'].getFieldIdentifier(element);
+ field['name'] = __gCrWeb.form.getFieldIdentifier(element);
field['form_control_type'] = element.type;
var autocomplete_attribute = element.getAttribute('autocomplete');
if (autocomplete_attribute) {
@@ -2112,10 +2113,10 @@ __gCrWeb.autofill.webFormControlElementToFormField = function(
}
if (__gCrWeb.autofill.isAutofillableInputElement(element) ||
- __gCrWeb.autofill.isTextAreaElement(element) ||
- __gCrWeb.autofill.isSelectElement(element)) {
+ __gCrWeb.autofill.isTextAreaElement(element) ||
+ __gCrWeb.autofill.isSelectElement(element)) {
field['is_autofilled'] = element.isAutofilled;
- field['should_autocomplete'] = __gCrWeb.common.autoComplete(element);
+ field['should_autocomplete'] = __gCrWeb.fill.autoComplete(element);
field['is_focusable'] = !element.disabled && !element.readOnly &&
element.tabIndex >= 0 && isVisibleNode_(element);
}
@@ -2175,15 +2176,15 @@ __gCrWeb.autofill.webFormControlElementToFormField = function(
*/
__gCrWeb.autofill['fillPredictionData'] = function(data) {
for (var formName in data) {
- var form = __gCrWeb.common.getFormElementFromIdentifier(formName);
+ var form = __gCrWeb.form.getFormElementFromIdentifier(formName);
var formData = data[formName];
- var controlElements = __gCrWeb.common.getFormControlElements(form);
+ var controlElements = __gCrWeb.form.getFormControlElements(form);
for (var i = 0; i < controlElements.length; ++i) {
var element = controlElements[i];
if (!__gCrWeb.autofill.isAutofillableElement(element)) {
continue;
}
- var elementName = __gCrWeb['common'].getFieldIdentifier(element);
+ var elementName = __gCrWeb.form.getFieldIdentifier(element);
var value = formData[elementName];
if (value) {
element.placeholder = value;
diff --git a/chromium/components/autofill/ios/browser/resources/suggestion_controller.js b/chromium/components/autofill/ios/browser/resources/suggestion_controller.js
index 456e6ef3481..91c9dfe21c6 100644
--- a/chromium/components/autofill/ios/browser/resources/suggestion_controller.js
+++ b/chromium/components/autofill/ios/browser/resources/suggestion_controller.js
@@ -24,25 +24,23 @@ __gCrWeb.suggestion = {};
// minification.
__gCrWeb['suggestion'] = __gCrWeb.suggestion;
- /**
- * Returns the element with the specified name that is a child of the
- * specified parent element.
- * @param {Element} parent The parent of the desired element.
- * @param {string} name The name of the desired element.
- * @return {Element} The element if found, otherwise null;
- */
- var getElementByNameWithParent_ = function(parent, name) {
- if (parent.name === name)
- return parent;
+/**
+ * Returns the element with the specified name that is a child of the
+ * specified parent element.
+ * @param {Element} parent The parent of the desired element.
+ * @param {string} name The name of the desired element.
+ * @return {Element} The element if found, otherwise null;
+ */
+var getElementByNameWithParent_ = function(parent, name) {
+ if (parent.name === name) return parent;
- var el;
- for (var i = 0; i < parent.children.length; i++) {
- el = getElementByNameWithParent_(parent.children[i], name);
- if (el)
- return el;
- }
- return null;
- };
+ var el;
+ for (var i = 0; i < parent.children.length; i++) {
+ el = getElementByNameWithParent_(parent.children[i], name);
+ if (el) return el;
+ }
+ return null;
+};
/**
* Returns the first element in |elements| that is later than |elementToCompare|
@@ -57,8 +55,8 @@ __gCrWeb['suggestion'] = __gCrWeb.suggestion;
* @return {Element} the first element in |elements| that is later than
* |elementToCompare| in tab order if there is one; null otherwise.
*/
-__gCrWeb.suggestion.getNextElementInTabOrder =
- function(elementToCompare, elementList) {
+__gCrWeb.suggestion.getNextElementInTabOrder = function(
+ elementToCompare, elementList) {
var elements = [];
for (var i = 0; i < elementList.length; ++i) {
elements[i] = elementList[i];
@@ -87,10 +85,10 @@ __gCrWeb.suggestion.getNextElementInTabOrder =
// |element2| that has DOM tree position |index2| in tab order. It is assumed
// |index1 !== index2|.
var comparator = function(element1, index1, element2, index2) {
- var tabOrder1 = __gCrWeb.suggestion.getTabOrder(element1);
- var tabOrder2 = __gCrWeb.suggestion.getTabOrder(element2);
- return tabOrder1 > tabOrder2 ||
- (tabOrder1 === tabOrder2 && index1 > index2);
+ var tabOrder1 = __gCrWeb.suggestion.getTabOrder(element1);
+ var tabOrder2 = __gCrWeb.suggestion.getTabOrder(element2);
+ return tabOrder1 > tabOrder2 ||
+ (tabOrder1 === tabOrder2 && index1 > index2);
};
return __gCrWeb.suggestion.getFormElementAfter(
elementToCompare, elements, comparator);
@@ -109,8 +107,8 @@ __gCrWeb.suggestion.getNextElementInTabOrder =
* @return {Element} the last element in |elements| that is earlier than
* |elementToCompare| in tab order if there is one; null otherwise.
*/
-__gCrWeb.suggestion.getPreviousElementInTabOrder =
- function(elementToCompare, elementList) {
+__gCrWeb.suggestion.getPreviousElementInTabOrder = function(
+ elementToCompare, elementList) {
var elements = [];
for (var i = 0; i < elementList.length; ++i) {
elements[i] = elementList[i];
@@ -136,10 +134,10 @@ __gCrWeb.suggestion.getPreviousElementInTabOrder =
// |element2| that has DOM tree position |index2| in tab order. It is assumed
// |index1 !== index2|.
var comparator = function(element1, index1, element2, index2) {
- var tabOrder1 = __gCrWeb.suggestion.getTabOrder(element1);
- var tabOrder2 = __gCrWeb.suggestion.getTabOrder(element2);
- return tabOrder1 < tabOrder2 ||
- (tabOrder1 === tabOrder2 && index1 < index2);
+ var tabOrder1 = __gCrWeb.suggestion.getTabOrder(element1);
+ var tabOrder2 = __gCrWeb.suggestion.getTabOrder(element2);
+ return tabOrder1 < tabOrder2 ||
+ (tabOrder1 === tabOrder2 && index1 < index2);
};
return __gCrWeb.suggestion.getFormElementAfter(
@@ -165,8 +163,8 @@ __gCrWeb.suggestion.getPreviousElementInTabOrder =
* tree order.
* @return {Element} The element that satisfies the conditions given above.
*/
-__gCrWeb.suggestion.getFormElementAfter =
- function(elementToCompare, elements, comparator) {
+__gCrWeb.suggestion.getFormElementAfter = function(
+ elementToCompare, elements, comparator) {
// Computes the index |indexToCompare| of |elementToCompare| in |element|.
var indexToCompare = elements.indexOf(elementToCompare);
if (indexToCompare === -1) {
@@ -234,8 +232,7 @@ __gCrWeb.suggestion.isSequentiallyReachable = function(element) {
// on this condition, false is returned for an iframe (as Mobile Safari does
// not navigate to elements in an iframe, there is no need to recursively
// check if there is a reachable element in an iframe).
- if (element.tagName !== 'INPUT' &&
- element.tagName !== 'SELECT' &&
+ if (element.tagName !== 'INPUT' && element.tagName !== 'SELECT' &&
element.tagName !== 'TEXTAREA') {
return false;
}
@@ -243,12 +240,9 @@ __gCrWeb.suggestion.isSequentiallyReachable = function(element) {
// The following elements are skipped when navigating using 'Prev' and "Next'
// buttons in Mobile Safari.
if (element.tagName === 'INPUT' &&
- (element.type === 'submit' ||
- element.type === 'reset' ||
- element.type === 'image' ||
- element.type === 'button' ||
- element.type === 'range' ||
- element.type === 'radio' ||
+ (element.type === 'submit' || element.type === 'reset' ||
+ element.type === 'image' || element.type === 'button' ||
+ element.type === 'range' || element.type === 'radio' ||
element.type === 'checkbox')) {
return false;
}
@@ -288,9 +282,8 @@ __gCrWeb.suggestion.getTabOrder = function(element) {
* @return {Element} The element if found, otherwise null.
*/
__gCrWeb.suggestion.getFormElement = function(formName, fieldName) {
- var form = __gCrWeb.common.getFormElementFromIdentifier(formName);
- if (!form)
- return null;
+ var form = __gCrWeb.form.getFormElementFromIdentifier(formName);
+ if (!form) return null;
return getElementByNameWithParent_(form, fieldName);
};
@@ -299,11 +292,11 @@ __gCrWeb.suggestion.getFormElement = function(formName, fieldName) {
* if there is no such element.
*/
__gCrWeb.suggestion['selectNextElement'] = function(formName, fieldName) {
- var currentElement =
- formName ? __gCrWeb.suggestion.getFormElement(formName, fieldName) :
- document.activeElement;
- var nextElement = __gCrWeb.suggestion.getNextElementInTabOrder(currentElement,
- document.all);
+ var currentElement = formName ?
+ __gCrWeb.suggestion.getFormElement(formName, fieldName) :
+ document.activeElement;
+ var nextElement = __gCrWeb.suggestion.getNextElementInTabOrder(
+ currentElement, document.all);
if (nextElement) {
nextElement.focus();
}
@@ -314,9 +307,9 @@ __gCrWeb.suggestion['selectNextElement'] = function(formName, fieldName) {
* operation if there is no such element.
*/
__gCrWeb.suggestion['selectPreviousElement'] = function(formName, fieldName) {
- var currentElement =
- formName ? __gCrWeb.suggestion.getFormElement(formName, fieldName) :
- document.activeElement;
+ var currentElement = formName ?
+ __gCrWeb.suggestion.getFormElement(formName, fieldName) :
+ document.activeElement;
var prevElement = __gCrWeb.suggestion.getPreviousElementInTabOrder(
currentElement, document.all);
if (prevElement) {
@@ -325,25 +318,29 @@ __gCrWeb.suggestion['selectPreviousElement'] = function(formName, fieldName) {
};
/**
+ * @param {string} formName The name of the form containing the element.
+ * @param {string} fieldName The name of the field containing the element.
* @return {boolean} Whether there is an element in the sequential navigation
* after the currently active element.
*/
__gCrWeb.suggestion['hasNextElement'] = function(formName, fieldName) {
- var currentElement =
- formName ? __gCrWeb.suggestion.getFormElement(formName, fieldName) :
- document.activeElement;
- return __gCrWeb.suggestion.getNextElementInTabOrder(currentElement,
- document.all) !== null;
+ var currentElement = formName ?
+ __gCrWeb.suggestion.getFormElement(formName, fieldName) :
+ document.activeElement;
+ return __gCrWeb.suggestion.getNextElementInTabOrder(
+ currentElement, document.all) !== null;
};
/**
+ * @param {string} formName The name of the form containing the element.
+ * @param {string} fieldName The name of the field containing the element.
* @return {boolean} Whether there is an element in the sequential navigation
* before the currently active element.
*/
__gCrWeb.suggestion['hasPreviousElement'] = function(formName, fieldName) {
- var currentElement =
- formName ? __gCrWeb.suggestion.getFormElement(formName, fieldName) :
- document.activeElement;
+ var currentElement = formName ?
+ __gCrWeb.suggestion.getFormElement(formName, fieldName) :
+ document.activeElement;
return __gCrWeb.suggestion.getPreviousElementInTabOrder(
currentElement, document.all) !== null;
};
diff --git a/chromium/components/autofill/ios/fill/resources/fill.js b/chromium/components/autofill/ios/fill/resources/fill.js
new file mode 100644
index 00000000000..2993cec50ba
--- /dev/null
+++ b/chromium/components/autofill/ios/fill/resources/fill.js
@@ -0,0 +1,313 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file provides methods used to fill forms in JavaScript.
+
+goog.module('__crWeb.fill');
+
+/**
+ * Namespace for this file. It depends on |__gCrWeb| having already been
+ * injected. String 'fill' is used in |__gCrWeb['fill']| as it needs to be
+ * accessed in Objective-C code.
+ */
+__gCrWeb.fill = {};
+
+// Store fill namespace object in a global __gCrWeb object referenced by a
+// string, so it does not get renamed by closure compiler during the
+// minification.
+__gCrWeb['fill'] = __gCrWeb.fill;
+
+/* Beginning of anonymous object. */
+(function() {
+
+/**
+ * Returns true if an element can be autocompleted.
+ *
+ * This method aims to provide the same logic as method
+ * bool autoComplete() const
+ * in chromium/src/third_party/WebKit/Source/WebKit/chromium/src/
+ * WebFormElement.cpp.
+ *
+ * @param {Element} element An element to check if it can be autocompleted.
+ * @return {boolean} true if element can be autocompleted.
+ */
+__gCrWeb.fill.autoComplete = function(element) {
+ if (!element) {
+ return false;
+ }
+ if (__gCrWeb.common.getLowerCaseAttribute(element, 'autocomplete') == 'off') {
+ return false;
+ }
+ if (__gCrWeb.common.getLowerCaseAttribute(element.form, 'autocomplete') ==
+ 'off') {
+ return false;
+ }
+ return true;
+};
+
+/**
+ * Sets the value of a data-bound input using AngularJS.
+ *
+ * The method first set the value using the val() method. Then, if input is
+ * bound to a model value, it sets the model value.
+ * Documentation of relevant modules of AngularJS can be found at
+ * https://docs.angularjs.org/guide/databinding
+ * https://docs.angularjs.org/api/auto/service/$injector
+ * https://docs.angularjs.org/api/ng/service/$parse
+ *
+ * @param {string} value The value the input element will be set.
+ * @param {Element} input The input element of which the value is set.
+ **/
+function setInputElementAngularValue_(value, input) {
+ if (!input || !window['angular']) {
+ return;
+ }
+ var angular_element =
+ window['angular'].element && window['angular'].element(input);
+ if (!angular_element) {
+ return;
+ }
+ angular_element.val(value);
+ var angular_model = angular_element.data && angular_element.data('ngModel');
+ if (!angular_model) {
+ return;
+ }
+ angular_element.injector().invoke([
+ '$parse',
+ function(parse) {
+ var setter = parse(angular_model);
+ setter.assign(angular_element.scope(), value);
+ }
+ ]);
+}
+
+/**
+ * Sets the value of an input and dispatches a change event if
+ * |shouldSendChangeEvent|.
+ *
+ * It is based on the logic in
+ *
+ * void setValue(const WebString&, bool sendChangeEvent = false)
+ *
+ * in chromium/src/third_party/WebKit/Source/WebKit/chromium/src/
+ * WebInputElement.cpp, which calls
+ * void setValue(const String& value, TextFieldEventBehavior eventBehavior)
+ * or
+ * void setChecked(bool nowChecked, TextFieldEventBehavior eventBehavior)
+ * in chromium/src/third_party/WebKit/Source/core/html/HTMLInputElement.cpp.
+ *
+ * @param {string} value The value the input element will be set.
+ * @param {Element} input The input element of which the value is set.
+ * @param {boolean} shouldSendChangeEvent Whether a change event should be
+ * dispatched.
+ */
+__gCrWeb.fill.setInputElementValue = function(
+ value, input, shouldSendChangeEvent) {
+ if (!input) {
+ return;
+ }
+ var changed = false;
+ if (input.type === 'checkbox' || input.type === 'radio') {
+ changed = input.checked !== value;
+ input.checked = value;
+ } else if (input.type === 'select-one') {
+ changed = input.value !== value;
+ input.value = value;
+ } else {
+ // In HTMLInputElement.cpp there is a check on canSetValue(value), which
+ // returns false only for file input. As file input is not relevant for
+ // autofill and this method is only used for autofill for now, there is no
+ // such check in this implementation.
+ var sanitizedValue =
+ __gCrWeb.fill.sanitizeValueForInputElement(value, input);
+ changed = sanitizedValue !== input.value;
+ input.value = sanitizedValue;
+ }
+ if (window['angular']) {
+ // The page uses the AngularJS framework. Update the angular value before
+ // sending events.
+ setInputElementAngularValue_(value, input);
+ }
+ if (changed && shouldSendChangeEvent) {
+ __gCrWeb.fill.notifyElementValueChanged(input);
+ }
+};
+
+/**
+ * Returns a sanitized value of proposedValue for a given input element type.
+ * The logic is based on
+ *
+ * String sanitizeValue(const String&) const
+ *
+ * in chromium/src/third_party/WebKit/Source/core/html/InputType.h
+ *
+ * @param {string} proposedValue The proposed value.
+ * @param {Element} element The element for which the proposedValue is to be
+ * sanitized.
+ * @return {string} The sanitized value.
+ */
+__gCrWeb.fill.sanitizeValueForInputElement = function(proposedValue, element) {
+ if (!proposedValue) {
+ return '';
+ }
+
+ // Method HTMLInputElement::sanitizeValue() calls InputType::sanitizeValue()
+ // (chromium/src/third_party/WebKit/Source/core/html/InputType.cpp) for
+ // non-null proposedValue. InputType::sanitizeValue() returns the original
+ // proposedValue by default and it is overridden in classes
+ // BaseDateAndTimeInputType, ColorInputType, RangeInputType and
+ // TextFieldInputType (all are in
+ // chromium/src/third_party/WebKit/Source/core/html/). Currently only
+ // TextFieldInputType is relevant and sanitizeValue() for other types of
+ // input elements has not been implemented.
+ if (__gCrWeb.common.isTextField(element)) {
+ return __gCrWeb.fill.sanitizeValueForTextFieldInputType(
+ proposedValue, element);
+ }
+ return proposedValue;
+};
+
+/**
+ * Returns a sanitized value for a text field.
+ *
+ * The logic is based on |String sanitizeValue(const String&)|
+ * in chromium/src/third_party/WebKit/Source/core/html/TextFieldInputType.h
+ * Note this method is overridden in EmailInputType and NumberInputType.
+ *
+ * @param {string} proposedValue The proposed value.
+ * @param {Element} element The element for which the proposedValue is to be
+ * sanitized.
+ * @return {string} The sanitized value.
+ */
+__gCrWeb.fill.sanitizeValueForTextFieldInputType = function(
+ proposedValue, element) {
+ var textFieldElementType = element.type;
+ if (textFieldElementType === 'email') {
+ return __gCrWeb.fill.sanitizeValueForEmailInputType(proposedValue, element);
+ } else if (textFieldElementType === 'number') {
+ return __gCrWeb.fill.sanitizeValueForNumberInputType(proposedValue);
+ }
+ var valueWithLineBreakRemoved = proposedValue.replace(/(\r\n|\n|\r)/gm, '');
+ // TODO(chenyu): Should we also implement numCharactersInGraphemeClusters()
+ // in chromium/src/third_party/WebKit/Source/core/platform/text/
+ // TextBreakIterator.cpp and call it here when computing newLength?
+ // Different from the implementation in TextFieldInputType.h, where a limit
+ // on the text length is considered due to
+ // https://bugs.webkit.org/show_bug.cgi?id=14536, no such limit is
+ // considered here for now.
+ var newLength = valueWithLineBreakRemoved.length;
+ // This logic is from method String limitLength() in TextFieldInputType.h
+ for (var i = 0; i < newLength; ++i) {
+ var current = valueWithLineBreakRemoved[i];
+ if (current < ' ' && current != '\t') {
+ newLength = i;
+ break;
+ }
+ }
+ return valueWithLineBreakRemoved.substring(0, newLength);
+};
+
+/**
+ * Returns the sanitized value for an email input.
+ *
+ * The logic is based on
+ *
+ * String EmailInputType::sanitizeValue(const String& proposedValue) const
+ *
+ * in chromium/src/third_party/WebKit/Source/core/html/EmailInputType.cpp
+ *
+ * @param {string} proposedValue The proposed value.
+ * @param {Element} element The element for which the proposedValue is to be
+ * sanitized.
+ * @return {string} The sanitized value.
+ */
+__gCrWeb.fill.sanitizeValueForEmailInputType = function(
+ proposedValue, element) {
+ var valueWithLineBreakRemoved = proposedValue.replace(/(\r\n|\n\r)/gm, '');
+
+ if (!element.multiple) {
+ return __gCrWeb.common.trim(proposedValue);
+ }
+ var addresses = valueWithLineBreakRemoved.split(',');
+ for (var i = 0; i < addresses.length; ++i) {
+ addresses[i] = __gCrWeb.common.trim(addresses[i]);
+ }
+ return addresses.join(',');
+};
+
+/**
+ * Returns the sanitized value of a proposed value for a number input.
+ *
+ * The logic is based on
+ *
+ * String NumberInputType::sanitizeValue(const String& proposedValue)
+ * const
+ *
+ * in chromium/src/third_party/WebKit/Source/core/html/NumberInputType.cpp
+ *
+ * Note in this implementation method Number() is used in the place of method
+ * parseToDoubleForNumberType() called in NumberInputType.cpp.
+ *
+ * @param {string} proposedValue The proposed value.
+ * @return {string} The sanitized value.
+ */
+__gCrWeb.fill.sanitizeValueForNumberInputType = function(proposedValue) {
+ var sanitizedValue = Number(proposedValue);
+ if (isNaN(sanitizedValue)) {
+ return '';
+ }
+ return sanitizedValue.toString();
+};
+
+/**
+ * Trims any whitespace from the start and end of a string.
+ * Used in preference to String.prototype.trim as this can be overridden by
+ * sites.
+ *
+ * @param {string} str The string to be trimmed.
+ * @return {string} The string after trimming.
+ */
+
+
+/**
+ * Creates and sends notification that element has changed.
+ *
+ * Most handlers react to 'change' or 'input' event, so sent both.
+ *
+ * @param {Element} element The element that changed.
+ */
+__gCrWeb.fill.notifyElementValueChanged = function(element) {
+ __gCrWeb.fill.createAndDispatchHTMLEvent(element, 'keydown', true, false);
+ __gCrWeb.fill.createAndDispatchHTMLEvent(element, 'change', true, false);
+ __gCrWeb.fill.createAndDispatchHTMLEvent(element, 'input', true, false);
+ __gCrWeb.fill.createAndDispatchHTMLEvent(element, 'keyup', true, false);
+};
+
+/**
+ * Creates and dispatches an HTML event.
+ *
+ * @param {Element} element The element for which an event is created.
+ * @param {string} type The type of the event.
+ * @param {boolean} bubbles A boolean indicating whether the event should
+ * bubble up through the event chain or not.
+ * @param {boolean} cancelable A boolean indicating whether the event can be
+ * canceled.
+ */
+__gCrWeb.fill.createAndDispatchHTMLEvent = function(
+ element, type, bubbles, cancelable) {
+ var changeEvent =
+ /** @type {!Event} */ (element.ownerDocument.createEvent('HTMLEvents'));
+ changeEvent.initEvent(type, bubbles, cancelable);
+ // Some frameworks will use the data field to update their cache value.
+ changeEvent.data = element.value;
+
+ // Adding a |simulated| flag on the event will force the React framework to
+ // update the backend store.
+ changeEvent.simulated = true;
+
+ element.dispatchEvent(changeEvent);
+};
+
+
+}()); // End of anonymous object
diff --git a/chromium/components/autofill_strings.grdp b/chromium/components/autofill_strings.grdp
index c1037fc3441..ccada7f7744 100644
--- a/chromium/components/autofill_strings.grdp
+++ b/chromium/components/autofill_strings.grdp
@@ -174,7 +174,7 @@
</message>
</if>
<if expr="use_titlecase">
- <message name="IDS_AUTOFILL_SHOW_ALL_SAVED_FALLBACK" desc="Mac/In Title Case::The text shown as an option in the suggestion drop down when a password field is clicked">
+ <message name="IDS_AUTOFILL_SHOW_ALL_SAVED_FALLBACK" desc="In Title Case: The text shown as an option in the suggestion drop down when a password field is clicked">
Show All Saved Passwords
</message>
</if>
diff --git a/chromium/components/background_task_scheduler/BUILD.gn b/chromium/components/background_task_scheduler/BUILD.gn
index 50eb165d0b5..9525aff8171 100644
--- a/chromium/components/background_task_scheduler/BUILD.gn
+++ b/chromium/components/background_task_scheduler/BUILD.gn
@@ -92,8 +92,8 @@ if (is_android) {
"$google_play_services_package:google_play_services_tasks_java",
"//base:base_java",
"//base:base_java_test_support",
+ "//base:base_junit_test_support",
"//third_party/junit",
]
- srcjar_deps = [ "//base:base_build_config_gen" ]
}
}
diff --git a/chromium/components/background_task_scheduler/README.md b/chromium/components/background_task_scheduler/README.md
index bc83b48d005..db2322de82d 100644
--- a/chromium/components/background_task_scheduler/README.md
+++ b/chromium/components/background_task_scheduler/README.md
@@ -30,13 +30,9 @@ available (or available but not considered stable enough). That is, the
JobScheduler API is used on Android M+; and the GcmNetworkManager is used
otherwise.
-> **WARNING: The GcmNetworkManager fallback is not yet implemented.** Please
-> treat the above as a target state, and do not yet add any dependencies on the
-> BackgroundTaskScheduler API that require pre-M compatibility.
-
-> NOTE: Even with the GcmNetworkManager fallback, there are devices that would
-> remain unsupported, as not all devices have Google Play services
-> available. Ultimately, this component hopes to provide a full compatibility
+> NOTE: Some of the pre-M devices do not include Google Play services and
+> therefore remain unsupported by `background_task_scheduler`.
+> Ultimately, this component hopes to provide a full compatibility
> layer on top of `JobScheduler`. However, until that is implemented, please be
> thoughtful about whether this component provides the coverage that your
> background task needs.
@@ -179,3 +175,27 @@ if the task needs to be rescheduled since it was canceled, or false otherwise.
**The system will hold a wakelock from the time `onStartTask(...)` is invoked
until either the task itself invokes the `TaskFinishedCallback`, or
`onStopTask(...)` is invoked.**
+
+## Loading Native parts
+
+Some of the tasks running in the background require native parts of the browser
+to be initialized. In order to simplify implementation of such tasks, we provide
+an base `NativeBackgroundTask`
+[implementation](https://cs.chromium.org/chromium/src/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java)
+in the browser layer. It requires extending classes to implement 4 methods:
+
+ * `onStartTaskBeforeNativeLoaded(...)` where the background task can decide
+ whether conditions are correct to proceed with native initialization;
+ * `onStartTaskWithNative(...)` where the background task can be sure that
+ native initialization was completed, therefore it can depend on that part of
+ the browser;
+ * `onStopTaskBeforeNativeLoaded(...)` which is delivered to the background task
+ just like `onStopTask(...)` and the native parts of the browser are not
+ loaded;
+ * `onStopTaskWithNative(...)` which is delivered to the background task just
+ like `onStopTask(...)` and the native parts of the browser are loaded.
+
+While in a normal execution, both `onStart...` methods are called, only one of
+the stopping methods will be triggered, depending on whether the native parts of
+the browser are loaded at the time the underlying scheduler decides to stop the
+task.
diff --git a/chromium/components/bookmark_component_strings.grdp b/chromium/components/bookmark_component_strings.grdp
index c5dc4811d16..8d4958ac3ac 100644
--- a/chromium/components/bookmark_component_strings.grdp
+++ b/chromium/components/bookmark_component_strings.grdp
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
+ <message name="IDS_BOOKMARK_EDITOR_TITLE" desc="Title of the window the bookmark editor is in.">
+ Edit bookmark
+ </message>
<message name="IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME" desc="Name for newly created groups">
New folder
</message>
@@ -7,9 +10,6 @@
<message name="IDS_BOOKMARK_BUBBLE_REMOVE_BOOKMARK" desc="Title of the button for removing the bookmark">
Remove
</message>
- <message name="IDS_BOOKMARK_EDITOR_TITLE" desc="Title of the window the bookmark editor is in.">
- Edit bookmark
- </message>
<message name="IDS_BOOKMARK_MANAGER_NAME_INPUT_PLACE_HOLDER" desc="Text to show in the URL input field when editing or creating bookmarks.">
Name
</message>
@@ -21,9 +21,6 @@
<message name="IDS_BOOKMARK_BUBBLE_REMOVE_BOOKMARK" desc="In Title Case: Title of the button for removing the bookmark">
Remove
</message>
- <message name="IDS_BOOKMARK_EDITOR_TITLE" desc="In Title Case: Title of the window the bookmark editor is in.">
- Edit Bookmark
- </message>
<message name="IDS_BOOKMARK_MANAGER_NAME_INPUT_PLACE_HOLDER" desc="In Title Case: Text to show in the URL input field when editing or creating bookmarks.">
Name
</message>
diff --git a/chromium/components/bookmarks/browser/bookmark_codec.cc b/chromium/components/bookmarks/browser/bookmark_codec.cc
index 37d68f45d99..04adafb1f38 100644
--- a/chromium/components/bookmarks/browser/bookmark_codec.cc
+++ b/chromium/components/bookmarks/browser/bookmark_codec.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <algorithm>
+#include <memory>
#include <utility>
#include "base/json/json_string_value_serializer.h"
diff --git a/chromium/components/bookmarks/browser/bookmark_index_unittest.cc b/chromium/components/bookmarks/browser/bookmark_index_unittest.cc
index c4eef10cc1c..2d03597c73b 100644
--- a/chromium/components/bookmarks/browser/bookmark_index_unittest.cc
+++ b/chromium/components/bookmarks/browser/bookmark_index_unittest.cc
@@ -4,6 +4,7 @@
#include <stddef.h>
+#include <memory>
#include <string>
#include <vector>
diff --git a/chromium/components/bookmarks/browser/bookmark_model.cc b/chromium/components/bookmarks/browser/bookmark_model.cc
index c4b76b9d652..9f15abf5655 100644
--- a/chromium/components/bookmarks/browser/bookmark_model.cc
+++ b/chromium/components/bookmarks/browser/bookmark_model.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include <functional>
+#include <memory>
#include <string>
#include <utility>
diff --git a/chromium/components/bookmarks/browser/bookmark_model_unittest.cc b/chromium/components/bookmarks/browser/bookmark_model_unittest.cc
index 4fe226c12a9..52253758ee0 100644
--- a/chromium/components/bookmarks/browser/bookmark_model_unittest.cc
+++ b/chromium/components/bookmarks/browser/bookmark_model_unittest.cc
@@ -10,6 +10,8 @@
#include <string>
#include <utility>
+#include <memory>
+
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
diff --git a/chromium/components/bookmarks/browser/bookmark_storage.cc b/chromium/components/bookmarks/browser/bookmark_storage.cc
index c32af8af931..cf64723c3a6 100644
--- a/chromium/components/bookmarks/browser/bookmark_storage.cc
+++ b/chromium/components/bookmarks/browser/bookmark_storage.cc
@@ -82,6 +82,15 @@ void LoadCallback(const base::FilePath& path,
codec.model_sync_transaction_version());
UMA_HISTOGRAM_TIMES("Bookmarks.DecodeTime",
TimeTicks::Now() - start_time);
+ int64_t size = 0;
+ if (base::GetFileSize(path, &size)) {
+ int64_t size_kb = size / 1024;
+ // For 0 bookmarks, file size is 700 bytes (less than 1KB)
+ // Bookmarks file size is not expected to exceed 50000KB (50MB) for most
+ // of the users.
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Bookmarks.FileSize", size_kb, 1, 50000,
+ 25);
+ }
load_index = true;
}
@@ -111,9 +120,9 @@ void LoadCallback(const base::FilePath& path,
TimeTicks::Now() - start_time);
}
- task_runner->PostTask(FROM_HERE,
- base::Bind(&BookmarkStorage::OnLoadFinished, storage,
- base::Passed(&details)));
+ task_runner->PostTask(
+ FROM_HERE, base::BindOnce(&BookmarkStorage::OnLoadFinished, storage,
+ std::move(details)));
}
} // namespace
@@ -169,8 +178,8 @@ void BookmarkStorage::LoadBookmarks(
const scoped_refptr<base::SequencedTaskRunner>& task_runner) {
sequenced_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&LoadCallback, writer_.path(), weak_factory_.GetWeakPtr(),
- base::Passed(&details), base::RetainedRef(task_runner)));
+ base::BindOnce(&LoadCallback, writer_.path(), weak_factory_.GetWeakPtr(),
+ std::move(details), base::RetainedRef(task_runner)));
}
void BookmarkStorage::ScheduleSave() {
diff --git a/chromium/components/bookmarks/managed/managed_bookmark_service.cc b/chromium/components/bookmarks/managed/managed_bookmark_service.cc
index d50ca6ad753..4fd197884de 100644
--- a/chromium/components/bookmarks/managed/managed_bookmark_service.cc
+++ b/chromium/components/bookmarks/managed/managed_bookmark_service.cc
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <stdlib.h>
+#include <memory>
#include <utility>
#include <vector>
diff --git a/chromium/components/bookmarks/managed/managed_bookmarks_tracker.cc b/chromium/components/bookmarks/managed/managed_bookmarks_tracker.cc
index 12e59f8fea3..3a5ae175a2d 100644
--- a/chromium/components/bookmarks/managed/managed_bookmarks_tracker.cc
+++ b/chromium/components/bookmarks/managed/managed_bookmarks_tracker.cc
@@ -4,6 +4,7 @@
#include "components/bookmarks/managed/managed_bookmarks_tracker.h"
+#include <memory>
#include <string>
#include "base/bind.h"
diff --git a/chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc b/chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
index c5aa3cb00de..857306e1e04 100644
--- a/chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
+++ b/chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/components/browser_sync/BUILD.gn b/chromium/components/browser_sync/BUILD.gn
index 1bddf05f365..d8c3092bfd1 100644
--- a/chromium/components/browser_sync/BUILD.gn
+++ b/chromium/components/browser_sync/BUILD.gn
@@ -53,7 +53,6 @@ source_set("unit_tests") {
"profile_sync_service_autofill_unittest.cc",
"profile_sync_service_bookmark_unittest.cc",
"profile_sync_service_startup_unittest.cc",
- "profile_sync_service_typed_url_unittest.cc",
"profile_sync_service_unittest.cc",
]
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 9c4a83ab8e6..ac89e31d6ad 100644
--- a/chromium/components/browser_sync/profile_sync_components_factory_impl.cc
+++ b/chromium/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -22,7 +22,6 @@
#include "components/browser_sync/profile_sync_service.h"
#include "components/dom_distiller/core/dom_distiller_features.h"
#include "components/history/core/browser/history_delete_directives_data_type_controller.h"
-#include "components/history/core/browser/typed_url_data_type_controller.h"
#include "components/history/core/browser/typed_url_model_type_controller.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/sync/browser/password_data_type_controller.h"
@@ -37,10 +36,7 @@
#include "components/sync/driver/proxy_data_type_controller.h"
#include "components/sync/driver/sync_client.h"
#include "components/sync/driver/sync_driver_switches.h"
-#include "components/sync/engine/attachments/attachment_downloader.h"
-#include "components/sync/engine/attachments/attachment_uploader.h"
#include "components/sync/engine/sync_engine.h"
-#include "components/sync/model/attachments/attachment_service.h"
#include "components/sync_bookmarks/bookmark_change_processor.h"
#include "components/sync_bookmarks/bookmark_data_type_controller.h"
#include "components/sync_bookmarks/bookmark_model_associator.h"
@@ -150,17 +146,11 @@ void ProfileSyncComponentsFactoryImpl::RegisterCommonDataTypes(
// Autocomplete sync is enabled by default. Register unless explicitly
// disabled.
if (!disabled_types.Has(syncer::AUTOFILL)) {
- if (FeatureList::IsEnabled(switches::kSyncUSSAutocomplete)) {
- sync_service->RegisterDataTypeController(
- std::make_unique<autofill::WebDataModelTypeController>(
- syncer::AUTOFILL, sync_client_, db_thread_, web_data_service_,
- base::Bind(
- &autofill::AutocompleteSyncBridge::FromWebDataService)));
- } else {
- sync_service->RegisterDataTypeController(
- std::make_unique<AutofillDataTypeController>(
- db_thread_, error_callback, sync_client_, web_data_service_));
- }
+ sync_service->RegisterDataTypeController(
+ std::make_unique<autofill::WebDataModelTypeController>(
+ syncer::AUTOFILL, sync_client_, db_thread_, web_data_service_,
+ base::Bind(
+ &autofill::AutocompleteSyncBridge::FromWebDataService)));
}
// Autofill sync is enabled by default. Register unless explicitly
@@ -211,15 +201,9 @@ void ProfileSyncComponentsFactoryImpl::RegisterCommonDataTypes(
// TypedUrl sync is enabled by default. Register unless explicitly
// disabled.
if (!disabled_types.Has(syncer::TYPED_URLS)) {
- if (base::FeatureList::IsEnabled(switches::kSyncUSSTypedURL)) {
- sync_service->RegisterDataTypeController(
- std::make_unique<history::TypedURLModelTypeController>(
- sync_client_, history_disabled_pref_));
- } else {
- sync_service->RegisterDataTypeController(
- std::make_unique<TypedUrlDataTypeController>(
- error_callback, sync_client_, history_disabled_pref_));
- }
+ sync_service->RegisterDataTypeController(
+ std::make_unique<history::TypedURLModelTypeController>(
+ sync_client_, history_disabled_pref_));
}
// Delete directive sync is enabled by default.
@@ -382,54 +366,6 @@ OAuth2TokenService* TokenServiceProvider::GetTokenService() {
return token_service_;
}
-std::unique_ptr<syncer::AttachmentService>
-ProfileSyncComponentsFactoryImpl::CreateAttachmentService(
- std::unique_ptr<syncer::AttachmentStoreForSync> attachment_store,
- const syncer::UserShare& user_share,
- const std::string& store_birthday,
- syncer::ModelType model_type,
- syncer::AttachmentService::Delegate* delegate) {
- std::unique_ptr<syncer::AttachmentUploader> attachment_uploader;
- std::unique_ptr<syncer::AttachmentDownloader> attachment_downloader;
- // Only construct an AttachmentUploader and AttachmentDownload if we have sync
- // credentials. We may not have sync credentials because there may not be a
- // signed in sync user.
- if (!user_share.sync_credentials.account_id.empty() &&
- !user_share.sync_credentials.scope_set.empty()) {
- scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>
- token_service_provider(
- new TokenServiceProvider(ui_thread_, token_service_));
- // TODO(maniscalco): Use shared (one per profile) thread-safe instances of
- // AttachmentUploader and AttachmentDownloader instead of creating a new one
- // per AttachmentService (bug 369536).
- attachment_uploader = syncer::AttachmentUploader::Create(
- sync_service_url_, url_request_context_getter_,
- user_share.sync_credentials.account_id,
- user_share.sync_credentials.scope_set, token_service_provider,
- store_birthday, model_type);
-
- token_service_provider =
- new TokenServiceProvider(ui_thread_, token_service_);
- attachment_downloader = syncer::AttachmentDownloader::Create(
- sync_service_url_, url_request_context_getter_,
- user_share.sync_credentials.account_id,
- user_share.sync_credentials.scope_set, token_service_provider,
- store_birthday, model_type);
- }
-
- // It is important that the initial backoff delay is relatively large. For
- // whatever reason, the server may fail all requests for a short period of
- // time. When this happens we don't want to overwhelm the server with
- // requests so we use a large initial backoff.
- const base::TimeDelta initial_backoff_delay =
- base::TimeDelta::FromMinutes(30);
- const base::TimeDelta max_backoff_delay = base::TimeDelta::FromHours(4);
- return syncer::AttachmentService::Create(
- std::move(attachment_store), std::move(attachment_uploader),
- std::move(attachment_downloader), delegate, initial_backoff_delay,
- max_backoff_delay);
-}
-
syncer::SyncApiComponentFactory::SyncComponents
ProfileSyncComponentsFactoryImpl::CreateBookmarkSyncComponents(
syncer::SyncService* sync_service,
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 351e688f4f5..fa0259a4b31 100644
--- a/chromium/components/browser_sync/profile_sync_components_factory_impl.h
+++ b/chromium/components/browser_sync/profile_sync_components_factory_impl.h
@@ -79,12 +79,6 @@ class ProfileSyncComponentsFactoryImpl
const base::FilePath& sync_data_folder) override;
std::unique_ptr<syncer::LocalDeviceInfoProvider>
CreateLocalDeviceInfoProvider() override;
- std::unique_ptr<syncer::AttachmentService> CreateAttachmentService(
- std::unique_ptr<syncer::AttachmentStoreForSync> attachment_store,
- const syncer::UserShare& user_share,
- const std::string& store_birthday,
- syncer::ModelType model_type,
- syncer::AttachmentService::Delegate* delegate) override;
syncer::SyncApiComponentFactory::SyncComponents CreateBookmarkSyncComponents(
syncer::SyncService* sync_service,
std::unique_ptr<syncer::DataTypeErrorHandler> error_handler) override;
diff --git a/chromium/components/browser_sync/profile_sync_service.cc b/chromium/components/browser_sync/profile_sync_service.cc
index f76497cfab6..4d99038c24c 100644
--- a/chromium/components/browser_sync/profile_sync_service.cc
+++ b/chromium/components/browser_sync/profile_sync_service.cc
@@ -19,18 +19,18 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/browser_sync/browser_sync_switches.h"
-#include "components/history/core/browser/typed_url_data_type_controller.h"
#include "components/invalidation/impl/invalidation_prefs.h"
#include "components/invalidation/public/invalidation_service.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/json_pref_store.h"
-#include "components/reading_list/features/reading_list_enable_flags.h"
+#include "components/reading_list/features/reading_list_buildflags.h"
#include "components/signin/core/browser/about_signin_internals.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_manager.h"
@@ -235,10 +235,7 @@ void ProfileSyncService::Initialize() {
sync_client_->GetSyncSessionsClient(), &sync_prefs_, local_device_.get(),
router,
base::Bind(&ProfileSyncService::NotifyForeignSessionUpdated,
- sync_enabled_weak_factory_.GetWeakPtr()),
- base::Bind(&ProfileSyncService::TriggerRefresh,
- sync_enabled_weak_factory_.GetWeakPtr(),
- syncer::ModelTypeSet(syncer::SESSIONS)));
+ sync_enabled_weak_factory_.GetWeakPtr()));
device_info_sync_bridge_ = std::make_unique<DeviceInfoSyncBridge>(
local_device_.get(), model_type_store_factory_,
@@ -384,9 +381,12 @@ sync_sessions::OpenTabsUIDelegate* ProfileSyncService::GetOpenTabsUIDelegate() {
DCHECK(thread_checker_.CalledOnValidThread());
// Although the backing data actually is of type |SESSIONS|, the desire to use
// open tabs functionality is tracked by the state of the |PROXY_TABS| type.
- return IsDataTypeControllerRunning(syncer::PROXY_TABS)
- ? sessions_sync_manager_.get()
- : nullptr;
+ if (!IsDataTypeControllerRunning(syncer::PROXY_TABS)) {
+ return nullptr;
+ }
+
+ DCHECK(sessions_sync_manager_);
+ return sessions_sync_manager_->GetOpenTabsUIDelegate();
}
sync_sessions::FaviconCache* ProfileSyncService::GetFaviconCache() {
@@ -605,7 +605,7 @@ void ProfileSyncService::OnGetTokenFailure(
UMA_HISTOGRAM_ENUMERATION("Sync.SyncAuthError", AUTH_ERROR_ENCOUNTERED,
AUTH_ERROR_LIMIT);
}
- // Fallthrough.
+ FALLTHROUGH;
}
default: {
if (error.state() != GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) {
@@ -903,8 +903,7 @@ void ProfileSyncService::OnEngineInitialized(
} else {
SigninClient* signin_client = signin_->GetOriginal()->signin_client();
DCHECK(signin_client);
- std::string signin_scoped_device_id =
- signin_client->GetSigninScopedDeviceId();
+ signin_scoped_device_id = signin_client->GetSigninScopedDeviceId();
}
// Initialize local device info.
@@ -1123,7 +1122,7 @@ void ProfileSyncService::OnActionableError(const SyncProtocolError& error) {
// On every platform except ChromeOS, sign out the user after a dashboard
// clear.
if (!IsLocalSyncEnabled()) {
- static_cast<SigninManager*>(signin_->GetOriginal())
+ SigninManager::FromSigninManagerBase(signin_->GetOriginal())
->SignOut(signin_metrics::SERVER_FORCED_DISABLE,
signin_metrics::SignoutDelete::IGNORE_METRIC);
}
@@ -1623,13 +1622,13 @@ void ProfileSyncService::SetPlatformSyncAllowedProvider(
}
// static
-syncer::ModelTypeStoreFactory ProfileSyncService::GetModelTypeStoreFactory(
- const base::FilePath& base_path) {
+syncer::RepeatingModelTypeStoreFactory
+ProfileSyncService::GetModelTypeStoreFactory(const base::FilePath& base_path) {
// TODO(skym): Verify using AsUTF8Unsafe is okay here. Should work as long
// as the Local State file is guaranteed to be UTF-8.
const std::string path =
FormatSharedModelTypeStorePath(base_path).AsUTF8Unsafe();
- return base::Bind(&ModelTypeStore::CreateStore, path);
+ return base::BindRepeating(&ModelTypeStore::CreateStore, path);
}
void ProfileSyncService::ConfigureDataTypeManager() {
@@ -2092,7 +2091,7 @@ void ProfileSyncService::GetAllNodes(
}
syncer::GlobalIdMapper* ProfileSyncService::GetGlobalIdMapper() const {
- return sessions_sync_manager_.get();
+ return sessions_sync_manager_->GetGlobalIdMapper();
}
base::WeakPtr<syncer::JsController> ProfileSyncService::GetJsController() {
diff --git a/chromium/components/browser_sync/profile_sync_service.h b/chromium/components/browser_sync/profile_sync_service.h
index d63cd92f61d..5a04d94f19a 100644
--- a/chromium/components/browser_sync/profile_sync_service.h
+++ b/chromium/components/browser_sync/profile_sync_service.h
@@ -20,7 +20,6 @@
#include "base/message_loop/message_loop.h"
#include "base/observer_list.h"
#include "base/strings/string16.h"
-#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -237,7 +236,7 @@ class ProfileSyncService : public syncer::SyncServiceBase,
scoped_refptr<net::URLRequestContextGetter> url_request_context;
std::string debug_identifier;
version_info::Channel channel = version_info::Channel::UNKNOWN;
- syncer::ModelTypeStoreFactory model_type_store_factory;
+ syncer::RepeatingModelTypeStoreFactory model_type_store_factory;
private:
DISALLOW_COPY_AND_ASSIGN(InitParams);
@@ -559,7 +558,7 @@ class ProfileSyncService : public syncer::SyncServiceBase,
// Returns a function that will create a ModelTypeStore that shares
// the sync LevelDB backend. |base_path| should be set to profile path.
- static syncer::ModelTypeStoreFactory GetModelTypeStoreFactory(
+ static syncer::RepeatingModelTypeStoreFactory GetModelTypeStoreFactory(
const base::FilePath& base_path);
// Needed to test whether the directory is deleted properly.
@@ -886,7 +885,7 @@ class ProfileSyncService : public syncer::SyncServiceBase,
// sync bridges created by the ProfileSyncService. The default factory
// creates an on disk leveldb-backed ModelTypeStore; one might override this
// default to, e.g., use an in-memory db for unit tests.
- syncer::ModelTypeStoreFactory model_type_store_factory_;
+ syncer::RepeatingModelTypeStoreFactory model_type_store_factory_;
// This weak factory invalidates its issued pointers when Sync is disabled.
base::WeakPtrFactory<ProfileSyncService> sync_enabled_weak_factory_;
diff --git a/chromium/components/browser_sync/profile_sync_service_autofill_unittest.cc b/chromium/components/browser_sync/profile_sync_service_autofill_unittest.cc
index 19652a16e8a..54dd4a7ddfb 100644
--- a/chromium/components/browser_sync/profile_sync_service_autofill_unittest.cc
+++ b/chromium/components/browser_sync/profile_sync_service_autofill_unittest.cc
@@ -433,10 +433,9 @@ class ProfileSyncServiceAutofillTest
EXPECT_CALL(personal_data_manager(), LoadProfiles());
EXPECT_CALL(personal_data_manager(), LoadCreditCards());
- personal_data_manager_->Init(
- web_data_service_, profile_sync_service_bundle()->pref_service(),
- profile_sync_service_bundle()->account_tracker(),
- profile_sync_service_bundle()->signin_manager(), false);
+ personal_data_manager_->Init(web_data_service_,
+ profile_sync_service_bundle()->pref_service(),
+ nullptr, false);
web_data_service_->StartSyncableService();
@@ -625,12 +624,12 @@ class ProfileSyncServiceAutofillTest
DCHECK(type == AUTOFILL || type == AUTOFILL_PROFILE);
if (type == AUTOFILL) {
return std::make_unique<AutofillDataTypeController>(
- data_type_thread()->task_runner(), base::Bind(&base::DoNothing),
- sync_client_, web_data_service_);
+ data_type_thread()->task_runner(), base::DoNothing(), sync_client_,
+ web_data_service_);
} else {
return std::make_unique<AutofillProfileDataTypeController>(
- data_type_thread()->task_runner(), base::Bind(&base::DoNothing),
- sync_client_, web_data_service_);
+ data_type_thread()->task_runner(), base::DoNothing(), sync_client_,
+ web_data_service_);
}
}
diff --git a/chromium/components/browser_sync/profile_sync_service_mock.cc b/chromium/components/browser_sync/profile_sync_service_mock.cc
index 4102a954b0b..56ed2496ba9 100644
--- a/chromium/components/browser_sync/profile_sync_service_mock.cc
+++ b/chromium/components/browser_sync/profile_sync_service_mock.cc
@@ -26,4 +26,9 @@ ProfileSyncServiceMock::GetOpenTabsUIDelegate() {
: ProfileSyncService::GetOpenTabsUIDelegate();
}
+std::unique_ptr<syncer::SyncSetupInProgressHandle>
+ProfileSyncServiceMock::GetSetupInProgressHandleConcrete() {
+ return browser_sync::ProfileSyncService::GetSetupInProgressHandle();
+}
+
} // namespace browser_sync
diff --git a/chromium/components/browser_sync/profile_sync_service_mock.h b/chromium/components/browser_sync/profile_sync_service_mock.h
index 588c74e95d9..cb5003ff577 100644
--- a/chromium/components/browser_sync/profile_sync_service_mock.h
+++ b/chromium/components/browser_sync/profile_sync_service_mock.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_BROWSER_SYNC_PROFILE_SYNC_SERVICE_MOCK_H_
#define COMPONENTS_BROWSER_SYNC_PROFILE_SYNC_SERVICE_MOCK_H_
+#include <memory>
#include <string>
#include <vector>
@@ -43,6 +44,9 @@ class ProfileSyncServiceMock : public ProfileSyncService {
MOCK_METHOD1(OnSyncCycleCompleted, void(const syncer::SyncCycleSnapshot&));
MOCK_METHOD2(OnUserChoseDatatypes,
void(bool sync_everything, syncer::ModelTypeSet chosen_types));
+ MOCK_METHOD0(SetFirstSetupComplete, void());
+ MOCK_METHOD0(GetSetupInProgressHandle,
+ std::unique_ptr<syncer::SyncSetupInProgressHandle>());
MOCK_METHOD2(OnUnrecoverableError,
void(const base::Location& location,
@@ -103,6 +107,10 @@ class ProfileSyncServiceMock : public ProfileSyncService {
void(const std::string& passphrase, PassphraseType type));
MOCK_METHOD0(OnSetupInProgressHandleDestroyed, void());
+
+ // Gives access to the real implementation of ProfileSyncService methods:
+ std::unique_ptr<syncer::SyncSetupInProgressHandle>
+ GetSetupInProgressHandleConcrete();
};
} // namespace browser_sync
diff --git a/chromium/components/browser_sync/profile_sync_service_typed_url_unittest.cc b/chromium/components/browser_sync/profile_sync_service_typed_url_unittest.cc
deleted file mode 100644
index 964ae968ab8..00000000000
--- a/chromium/components/browser_sync/profile_sync_service_typed_url_unittest.cc
+++ /dev/null
@@ -1,1044 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "components/browser_sync/abstract_profile_sync_service_test.h"
-#include "components/browser_sync/test_profile_sync_service.h"
-#include "components/history/core/browser/history_backend.h"
-#include "components/history/core/browser/history_backend_client.h"
-#include "components/history/core/browser/history_backend_notifier.h"
-#include "components/history/core/browser/history_db_task.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/history/core/browser/typed_url_data_type_controller.h"
-#include "components/signin/core/browser/signin_manager.h"
-#include "components/sync/driver/data_type_manager_impl.h"
-#include "components/sync/model/data_type_error_handler_mock.h"
-#include "components/sync/protocol/typed_url_specifics.pb.h"
-#include "components/sync/syncable/read_node.h"
-#include "components/sync/syncable/read_transaction.h"
-#include "components/sync/syncable/write_node.h"
-#include "components/sync/syncable/write_transaction.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-using history::HistoryBackend;
-using history::HistoryBackendNotifier;
-using history::TypedUrlSyncableService;
-using testing::DoAll;
-using testing::Return;
-using testing::SetArgPointee;
-using testing::_;
-
-namespace browser_sync {
-
-namespace {
-
-const char kDummySavingBrowserHistoryDisabled[] = "dummyPref";
-
-// Visits with this timestamp are treated as expired.
-static const int EXPIRED_VISIT = -1;
-
-ACTION_P(ReturnNewDataTypeManager, sync_client) {
- return new syncer::DataTypeManagerImpl(sync_client, arg0, arg1, arg2, arg3,
- arg4, arg5);
-}
-
-class HistoryBackendMock : public HistoryBackend {
- public:
- HistoryBackendMock()
- : HistoryBackend(nullptr, nullptr, base::ThreadTaskRunnerHandle::Get()) {}
- bool IsExpiredVisitTime(const base::Time& time) override {
- return time.ToInternalValue() == EXPIRED_VISIT;
- }
- MOCK_METHOD1(GetAllTypedURLs, bool(history::URLRows* entries));
- MOCK_METHOD3(GetMostRecentVisitsForURL,
- bool(history::URLID id,
- int max_visits,
- history::VisitVector* visits));
- MOCK_METHOD2(UpdateURL, bool(history::URLID id, const history::URLRow& url));
- MOCK_METHOD3(AddVisits,
- bool(const GURL& url,
- const std::vector<history::VisitInfo>& visits,
- history::VisitSource visit_source));
- MOCK_METHOD2(GetURL, bool(const GURL& url_id, history::URLRow* url_row));
- MOCK_METHOD2(SetPageTitle,
- void(const GURL& url, const base::string16& title));
- MOCK_METHOD1(DeleteURL, void(const GURL& url));
-
- private:
- friend class ProfileSyncServiceTypedUrlTest;
-
- virtual ~HistoryBackendMock() {}
-};
-
-class HistoryServiceMock : public history::HistoryService {
- public:
- HistoryServiceMock() : history::HistoryService(), backend_(nullptr) {}
-
- base::CancelableTaskTracker::TaskId ScheduleDBTask(
- std::unique_ptr<history::HistoryDBTask> task,
- base::CancelableTaskTracker* tracker) override {
- // Explicitly copy out the raw pointer -- compilers might decide to
- // evaluate task.release() before the arguments for the first Bind().
- history::HistoryDBTask* task_raw = task.get();
- task_runner_->PostTaskAndReply(
- FROM_HERE, base::Bind(&HistoryServiceMock::RunTaskOnDBThread,
- base::Unretained(this), task_raw),
- base::Bind(&base::DeletePointer<history::HistoryDBTask>,
- task.release()));
- return base::CancelableTaskTracker::kBadTaskId; // unused
- }
-
- ~HistoryServiceMock() override {}
-
- void set_task_runner(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- DCHECK(task_runner.get());
- task_runner_ = task_runner;
- }
-
- void set_backend(scoped_refptr<history::HistoryBackend> backend) {
- backend_ = backend;
- }
-
- private:
- void RunTaskOnDBThread(history::HistoryDBTask* task) {
- EXPECT_TRUE(task->RunOnDBThread(backend_.get(), nullptr));
- }
-
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- scoped_refptr<history::HistoryBackend> backend_;
-};
-
-class TestTypedUrlSyncableService : public TypedUrlSyncableService {
- // TODO(gangwu): remove TestProfileSyncService or even remove whole test
- // suite, and make sure typed_url_syncable_service_unittest.cc and the various
- // typed url integration tests.
- public:
- explicit TestTypedUrlSyncableService(history::HistoryBackend* history_backend)
- : TypedUrlSyncableService(history_backend) {}
-
- static void WriteToSyncNode(const history::URLRow& url,
- const history::VisitVector& visits,
- syncer::WriteNode* node) {
- sync_pb::TypedUrlSpecifics typed_url;
- ASSERT_TRUE(WriteToTypedUrlSpecifics(url, visits, &typed_url));
- node->SetTypedUrlSpecifics(typed_url);
- }
-
- protected:
- // Don't clear error stats - that way we can verify their values in our
- // tests.
- void ClearErrorStats() override {}
-};
-
-class ProfileSyncServiceTypedUrlTest : public AbstractProfileSyncServiceTest {
- public:
- void AddTypedUrlSyncNode(const history::URLRow& url,
- const history::VisitVector& visits) {
- syncer::WriteTransaction trans(FROM_HERE, sync_service()->GetUserShare());
-
- syncer::WriteNode node(&trans);
- std::string tag = url.url().spec();
- syncer::WriteNode::InitUniqueByCreationResult result =
- node.InitUniqueByCreation(syncer::TYPED_URLS, tag);
- ASSERT_EQ(syncer::WriteNode::INIT_SUCCESS, result);
- TestTypedUrlSyncableService::WriteToSyncNode(url, visits, &node);
- }
-
- protected:
- ProfileSyncServiceTypedUrlTest() {
- profile_sync_service_bundle()
- ->pref_service()
- ->registry()
- ->RegisterBooleanPref(kDummySavingBrowserHistoryDisabled, false);
-
- data_type_thread()->Start();
- base::RunLoop run_loop;
- data_type_thread()->task_runner()->PostTaskAndReply(
- FROM_HERE,
- base::Bind(&ProfileSyncServiceTypedUrlTest::CreateHistoryService,
- base::Unretained(this)),
- run_loop.QuitClosure());
- run_loop.Run();
- history_service_ = base::WrapUnique(new HistoryServiceMock);
- history_service_->set_task_runner(data_type_thread()->task_runner());
- history_service_->set_backend(history_backend_);
-
- ProfileSyncServiceBundle::SyncClientBuilder builder(
- profile_sync_service_bundle());
- builder.SetHistoryService(history_service_.get());
- builder.SetSyncServiceCallback(GetSyncServiceCallback());
- builder.SetSyncableServiceCallback(
- base::Bind(&ProfileSyncServiceTypedUrlTest::GetSyncableServiceForType,
- base::Unretained(this)));
- builder.set_activate_model_creation();
- sync_client_ = builder.Build();
- }
-
- void CreateHistoryService() {
- history_backend_ = new HistoryBackendMock();
- syncable_service_ =
- std::make_unique<TestTypedUrlSyncableService>(history_backend_.get());
- }
-
- void DeleteSyncableService() {
- syncable_service_.reset();
- history_backend_ = nullptr;
- }
-
- ~ProfileSyncServiceTypedUrlTest() override {
- history_service_->Shutdown();
-
- // Request stop to get deletion tasks related to the HistoryService posted
- // on the Sync thread. It is important to not Shutdown at this moment,
- // because after shutdown the Sync thread is not returned to the sync
- // service, so we could not get the thread's message loop to wait for the
- // deletions to be finished.
- sync_service()->RequestStop(syncer::SyncService::CLEAR_DATA);
- // Spin the sync thread.
- {
- base::RunLoop run_loop;
- sync_service()->GetSyncLoopForTest()->task_runner()->PostTaskAndReply(
- FROM_HERE, base::Bind(&base::DoNothing), run_loop.QuitClosure());
- run_loop.Run();
- }
-
- // Spin the loop again for deletion tasks posted from the Sync thread.
- base::RunLoop().RunUntilIdle();
-
- {
- base::RunLoop run_loop;
- data_type_thread()->task_runner()->PostTaskAndReply(
- FROM_HERE,
- base::Bind(&ProfileSyncServiceTypedUrlTest::DeleteSyncableService,
- base::Unretained(this)),
- run_loop.QuitClosure());
- run_loop.Run();
- }
- }
-
- TypedUrlSyncableService* StartSyncService(const base::Closure& callback) {
- if (!sync_service()) {
- std::string account_id =
- profile_sync_service_bundle()->account_tracker()->SeedAccountInfo(
- "gaia_id", "test");
- SigninManagerBase* signin =
- profile_sync_service_bundle()->signin_manager();
- signin->SetAuthenticatedAccountInfo("gaia_id", "test");
- EXPECT_CALL(*profile_sync_service_bundle()->component_factory(),
- CreateDataTypeManager(_, _, _, _, _, _))
- .WillOnce(ReturnNewDataTypeManager(sync_client_.get()));
- CreateSyncService(std::move(sync_client_), callback);
-
- profile_sync_service_bundle()->auth_service()->UpdateCredentials(
- account_id, "oauth2_login_token");
-
- sync_service()->RegisterDataTypeController(
- std::make_unique<TypedUrlDataTypeController>(
- base::Bind(&base::DoNothing), sync_service()->GetSyncClient(),
- kDummySavingBrowserHistoryDisabled));
-
- sync_service()->Initialize();
- base::RunLoop().Run();
- }
- return syncable_service_.get();
- }
-
- void GetTypedUrlsFromSyncDB(history::URLRows* urls) {
- urls->clear();
- syncer::ReadTransaction trans(FROM_HERE, sync_service()->GetUserShare());
- syncer::ReadNode typed_url_root(&trans);
- if (typed_url_root.InitTypeRoot(syncer::TYPED_URLS) !=
- syncer::BaseNode::INIT_OK)
- return;
-
- int64_t child_id = typed_url_root.GetFirstChildId();
- while (child_id != syncer::kInvalidId) {
- syncer::ReadNode child_node(&trans);
- if (child_node.InitByIdLookup(child_id) != syncer::BaseNode::INIT_OK)
- return;
-
- const sync_pb::TypedUrlSpecifics& typed_url(
- child_node.GetTypedUrlSpecifics());
- history::URLRow new_url(GURL(typed_url.url()));
-
- new_url.set_title(base::UTF8ToUTF16(typed_url.title()));
- DCHECK(typed_url.visits_size());
- DCHECK_EQ(typed_url.visits_size(), typed_url.visit_transitions_size());
- new_url.set_last_visit(base::Time::FromInternalValue(
- typed_url.visits(typed_url.visits_size() - 1)));
- new_url.set_hidden(typed_url.hidden());
-
- urls->push_back(new_url);
- child_id = child_node.GetSuccessorId();
- }
- }
-
- void SetIdleChangeProcessorExpectations() {
- EXPECT_CALL((history_backend()), SetPageTitle(_, _)).Times(0);
- EXPECT_CALL((history_backend()), UpdateURL(_, _)).Times(0);
- EXPECT_CALL((history_backend()), GetURL(_, _)).Times(0);
- EXPECT_CALL((history_backend()), DeleteURL(_)).Times(0);
- }
-
- void SendNotification(const base::Closure& task) {
- data_type_thread()->task_runner()->PostTaskAndReply(
- FROM_HERE, task, base::Bind(&base::RunLoop::QuitCurrentDeprecated));
- base::RunLoop().Run();
- }
-
- void SendNotificationURLVisited(ui::PageTransition transition,
- const history::URLRow& row) {
- base::Time visit_time;
- history::RedirectList redirects;
- SendNotification(base::Bind(&HistoryBackendNotifier::NotifyURLVisited,
- base::Unretained(history_backend_.get()),
- transition, row, redirects, visit_time));
- }
-
- void SendNotificationURLsModified(const history::URLRows& rows) {
- SendNotification(base::Bind(&HistoryBackendNotifier::NotifyURLsModified,
- base::Unretained(history_backend_.get()),
- rows));
- }
-
- void SendNotificationURLsDeleted(bool all_history,
- bool expired,
- const history::URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) {
- SendNotification(base::Bind(&HistoryBackendNotifier::NotifyURLsDeleted,
- base::Unretained(history_backend_.get()),
- all_history, expired, deleted_rows,
- favicon_urls));
- }
-
- static bool URLsEqual(const history::URLRow& lhs,
- const history::URLRow& rhs) {
- // Only verify the fields we explicitly sync (i.e. don't verify typed_count
- // or visit_count because we rely on the history DB to manage those values
- // and they are left unchanged by HistoryBackendMock).
- return (lhs.url().spec().compare(rhs.url().spec()) == 0) &&
- (lhs.title().compare(rhs.title()) == 0) &&
- (lhs.last_visit() == rhs.last_visit()) &&
- (lhs.hidden() == rhs.hidden());
- }
-
- static history::URLRow MakeTypedUrlEntry(const char* url,
- const char* title,
- int typed_count,
- int64_t last_visit,
- bool hidden,
- history::VisitVector* visits) {
- // Give each URL a unique ID, to mimic the behavior of the real database.
- static int unique_url_id = 0;
- GURL gurl(url);
- history::URLRow history_url(gurl, ++unique_url_id);
- history_url.set_title(base::UTF8ToUTF16(title));
- history_url.set_typed_count(typed_count);
- history_url.set_last_visit(base::Time::FromInternalValue(last_visit));
- history_url.set_hidden(hidden);
- visits->push_back(history::VisitRow(history_url.id(),
- history_url.last_visit(), 0,
- ui::PAGE_TRANSITION_TYPED, 0));
- history_url.set_visit_count(visits->size());
- return history_url;
- }
-
- base::WeakPtr<syncer::SyncableService> GetSyncableServiceForType(
- syncer::ModelType type) {
- DCHECK_EQ(syncer::TYPED_URLS, type);
- return syncable_service_->AsWeakPtr();
- }
-
- HistoryBackendMock& history_backend() { return *history_backend_.get(); }
-
- private:
- scoped_refptr<HistoryBackendMock> history_backend_;
- std::unique_ptr<HistoryServiceMock> history_service_;
- syncer::DataTypeErrorHandlerMock error_handler_;
- std::unique_ptr<TestTypedUrlSyncableService> syncable_service_;
- std::unique_ptr<syncer::FakeSyncClient> sync_client_;
-
- DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceTypedUrlTest);
-};
-
-void AddTypedUrlEntries(ProfileSyncServiceTypedUrlTest* test,
- const history::URLRows& entries) {
- test->CreateRoot(syncer::TYPED_URLS);
- for (size_t i = 0; i < entries.size(); ++i) {
- history::VisitVector visits;
- visits.push_back(history::VisitRow(entries[i].id(), entries[i].last_visit(),
- 0, ui::PageTransitionFromInt(1), 0));
- test->AddTypedUrlSyncNode(entries[i], visits);
- }
-}
-
-} // namespace
-
-TEST_F(ProfileSyncServiceTypedUrlTest, EmptyNativeEmptySync) {
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_)).WillOnce(Return(true));
- SetIdleChangeProcessorExpectations();
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- TypedUrlSyncableService* syncable_service =
- StartSyncService(create_root.callback());
- history::URLRows sync_entries;
- GetTypedUrlsFromSyncDB(&sync_entries);
- EXPECT_EQ(0U, sync_entries.size());
- ASSERT_EQ(0, syncable_service->GetErrorPercentage());
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeEmptySync) {
- history::URLRows entries;
- history::VisitVector visits;
- entries.push_back(
- MakeTypedUrlEntry("http://foo.com", "bar", 2, 15, false, &visits));
-
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(entries), Return(true)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>(visits), Return(true)));
- SetIdleChangeProcessorExpectations();
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- TypedUrlSyncableService* syncable_service =
- StartSyncService(create_root.callback());
- history::URLRows sync_entries;
- GetTypedUrlsFromSyncDB(&sync_entries);
- ASSERT_EQ(1U, sync_entries.size());
- EXPECT_TRUE(URLsEqual(entries[0], sync_entries[0]));
- ASSERT_EQ(0, syncable_service->GetErrorPercentage());
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeErrorReadingVisits) {
- history::URLRows entries;
- history::VisitVector visits;
- history::URLRow native_entry1(
- MakeTypedUrlEntry("http://foo.com", "bar", 2, 15, false, &visits));
- history::URLRow native_entry2(
- MakeTypedUrlEntry("http://foo2.com", "bar", 3, 15, false, &visits));
- entries.push_back(native_entry1);
- entries.push_back(native_entry2);
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(entries), Return(true)));
- // Return an error from GetMostRecentVisitsForURL() for the second URL.
- EXPECT_CALL((history_backend()),
- GetMostRecentVisitsForURL(native_entry1.id(), _, _))
- .WillRepeatedly(Return(true));
- EXPECT_CALL((history_backend()),
- GetMostRecentVisitsForURL(native_entry2.id(), _, _))
- .WillRepeatedly(Return(false));
- SetIdleChangeProcessorExpectations();
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
- history::URLRows sync_entries;
- GetTypedUrlsFromSyncDB(&sync_entries);
- ASSERT_EQ(1U, sync_entries.size());
- EXPECT_TRUE(URLsEqual(native_entry1, sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeWithBlankEmptySync) {
- std::vector<history::URLRow> entries;
- history::VisitVector visits;
- // Add an empty URL.
- entries.push_back(MakeTypedUrlEntry("", "bar", 2, 15, false, &visits));
- entries.push_back(
- MakeTypedUrlEntry("http://foo.com", "bar", 2, 15, false, &visits));
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(entries), Return(true)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>(visits), Return(true)));
- SetIdleChangeProcessorExpectations();
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
- std::vector<history::URLRow> sync_entries;
- GetTypedUrlsFromSyncDB(&sync_entries);
- // The empty URL should be ignored.
- ASSERT_EQ(1U, sync_entries.size());
- EXPECT_TRUE(URLsEqual(entries[1], sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeHasSyncNoMerge) {
- history::VisitVector native_visits;
- history::VisitVector sync_visits;
- history::URLRow native_entry(MakeTypedUrlEntry("http://native.com", "entry",
- 2, 15, false, &native_visits));
- history::URLRow sync_entry(MakeTypedUrlEntry("http://sync.com", "entry", 3,
- 16, false, &sync_visits));
-
- history::URLRows native_entries;
- native_entries.push_back(native_entry);
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(native_entries), Return(true)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>(native_visits), Return(true)));
- EXPECT_CALL((history_backend()), AddVisits(_, _, history::SOURCE_SYNCED))
- .WillRepeatedly(Return(true));
-
- history::URLRows sync_entries;
- sync_entries.push_back(sync_entry);
-
- EXPECT_CALL((history_backend()), UpdateURL(_, _))
- .WillRepeatedly(Return(true));
- StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));
-
- std::map<std::string, history::URLRow> expected;
- expected[native_entry.url().spec()] = native_entry;
- expected[sync_entry.url().spec()] = sync_entry;
-
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
-
- EXPECT_EQ(expected.size(), new_sync_entries.size());
- for (history::URLRows::iterator entry = new_sync_entries.begin();
- entry != new_sync_entries.end(); ++entry) {
- EXPECT_TRUE(URLsEqual(expected[entry->url().spec()], *entry));
- }
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, EmptyNativeExpiredSync) {
- history::VisitVector sync_visits;
- history::URLRow sync_entry(MakeTypedUrlEntry(
- "http://sync.com", "entry", 3, EXPIRED_VISIT, false, &sync_visits));
- history::URLRows sync_entries;
- sync_entries.push_back(sync_entry);
-
- // Since all our URLs are expired, no backend calls to add new URLs will be
- // made.
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_)).WillOnce(Return(true));
- SetIdleChangeProcessorExpectations();
-
- StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeHasSyncMerge) {
- history::VisitVector native_visits;
- history::URLRow native_entry(MakeTypedUrlEntry("http://native.com", "entry",
- 2, 15, false, &native_visits));
- history::VisitVector sync_visits;
- history::URLRow sync_entry(MakeTypedUrlEntry("http://native.com", "name", 1,
- 17, false, &sync_visits));
- history::VisitVector merged_visits;
- merged_visits.push_back(
- history::VisitRow(sync_entry.id(), base::Time::FromInternalValue(15), 0,
- ui::PageTransitionFromInt(0), 0));
-
- history::URLRow merged_entry(MakeTypedUrlEntry("http://native.com", "name", 2,
- 17, false, &merged_visits));
-
- history::URLRows native_entries;
- native_entries.push_back(native_entry);
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(native_entries), Return(true)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>(native_visits), Return(true)));
- EXPECT_CALL((history_backend()), AddVisits(_, _, history::SOURCE_SYNCED))
- .WillRepeatedly(Return(true));
-
- history::URLRows sync_entries;
- sync_entries.push_back(sync_entry);
-
- EXPECT_CALL((history_backend()), UpdateURL(_, _))
- .WillRepeatedly(Return(true));
- EXPECT_CALL((history_backend()), SetPageTitle(_, _)).WillRepeatedly(Return());
- StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));
-
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(merged_entry, new_sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeWithErrorHasSyncMerge) {
- history::VisitVector native_visits;
- history::URLRow native_entry(MakeTypedUrlEntry("http://native.com", "native",
- 2, 15, false, &native_visits));
- history::VisitVector sync_visits;
- history::URLRow sync_entry(MakeTypedUrlEntry("http://native.com", "sync", 1,
- 17, false, &sync_visits));
-
- history::URLRows native_entries;
- native_entries.push_back(native_entry);
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(native_entries), Return(true)));
- // Return an error getting the visits for the native URL.
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(Return(false));
- EXPECT_CALL((history_backend()), GetURL(_, _))
- .WillRepeatedly(DoAll(SetArgPointee<1>(native_entry), Return(true)));
- EXPECT_CALL((history_backend()), AddVisits(_, _, history::SOURCE_SYNCED))
- .WillRepeatedly(Return(true));
-
- history::URLRows sync_entries;
- sync_entries.push_back(sync_entry);
-
- EXPECT_CALL((history_backend()), UpdateURL(_, _))
- .WillRepeatedly(Return(true));
- EXPECT_CALL((history_backend()), SetPageTitle(_, _)).WillRepeatedly(Return());
- StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));
-
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(sync_entry, new_sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeAdd) {
- history::VisitVector added_visits;
- history::URLRow added_entry(MakeTypedUrlEntry("http://added.com", "entry", 2,
- 15, false, &added_visits));
-
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_)).WillOnce(Return(true));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillOnce(DoAll(SetArgPointee<2>(added_visits), Return(true)));
-
- SetIdleChangeProcessorExpectations();
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
-
- history::URLRows changed_urls;
- changed_urls.push_back(added_entry);
- SendNotificationURLsModified(changed_urls);
-
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(added_entry, new_sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeAddWithBlank) {
- history::VisitVector added_visits;
- history::URLRow empty_entry(
- MakeTypedUrlEntry("", "entry", 2, 15, false, &added_visits));
- history::URLRow added_entry(MakeTypedUrlEntry("http://added.com", "entry", 2,
- 15, false, &added_visits));
-
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_)).WillOnce(Return(true));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>(added_visits), Return(true)));
-
- SetIdleChangeProcessorExpectations();
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
-
- history::URLRows changed_urls;
- changed_urls.push_back(empty_entry);
- changed_urls.push_back(added_entry);
- SendNotificationURLsModified(changed_urls);
-
- std::vector<history::URLRow> new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(added_entry, new_sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeUpdate) {
- history::VisitVector original_visits;
- history::URLRow original_entry(MakeTypedUrlEntry(
- "http://mine.com", "entry", 2, 15, false, &original_visits));
- history::URLRows original_entries;
- original_entries.push_back(original_entry);
-
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(original_entries), Return(true)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillOnce(DoAll(SetArgPointee<2>(original_visits), Return(true)));
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
-
- history::VisitVector updated_visits;
- history::URLRow updated_entry(MakeTypedUrlEntry("http://mine.com", "entry", 7,
- 17, false, &updated_visits));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillOnce(DoAll(SetArgPointee<2>(updated_visits), Return(true)));
-
- history::URLRows changed_urls;
- changed_urls.push_back(updated_entry);
- SendNotificationURLsModified(changed_urls);
-
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(updated_entry, new_sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeAddFromVisit) {
- history::VisitVector added_visits;
- history::URLRow added_entry(MakeTypedUrlEntry("http://added.com", "entry", 2,
- 15, false, &added_visits));
-
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_)).WillOnce(Return(true));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillOnce(DoAll(SetArgPointee<2>(added_visits), Return(true)));
-
- SetIdleChangeProcessorExpectations();
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
-
- SendNotificationURLVisited(ui::PAGE_TRANSITION_TYPED, added_entry);
-
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(added_entry, new_sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeUpdateFromVisit) {
- history::VisitVector original_visits;
- history::URLRow original_entry(MakeTypedUrlEntry(
- "http://mine.com", "entry", 2, 15, false, &original_visits));
- history::URLRows original_entries;
- original_entries.push_back(original_entry);
-
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(original_entries), Return(true)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillOnce(DoAll(SetArgPointee<2>(original_visits), Return(true)));
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
-
- history::VisitVector updated_visits;
- history::URLRow updated_entry(MakeTypedUrlEntry("http://mine.com", "entry", 7,
- 17, false, &updated_visits));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillOnce(DoAll(SetArgPointee<2>(updated_visits), Return(true)));
-
- SendNotificationURLVisited(ui::PAGE_TRANSITION_TYPED, updated_entry);
-
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(updated_entry, new_sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserIgnoreChangeUpdateFromVisit) {
- history::VisitVector original_visits;
- history::URLRow original_entry(MakeTypedUrlEntry(
- "http://mine.com", "entry", 2, 15, false, &original_visits));
- history::URLRows original_entries;
- original_entries.push_back(original_entry);
-
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(original_entries), Return(true)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>(original_visits), Return(true)));
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(original_entry, new_sync_entries[0]));
-
- history::VisitVector updated_visits;
- history::URLRow updated_entry(MakeTypedUrlEntry("http://mine.com", "entry", 7,
- 15, false, &updated_visits));
-
- // Should ignore this change because it's not TYPED.
- SendNotificationURLVisited(ui::PAGE_TRANSITION_RELOAD, updated_entry);
- GetTypedUrlsFromSyncDB(&new_sync_entries);
-
- // Should be no changes to the sync DB from this notification.
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(original_entry, new_sync_entries[0]));
-
- // Now, try updating it with a large number of visits not divisible by 10
- // (should ignore this visit).
- history::URLRow twelve_visits(MakeTypedUrlEntry(
- "http://mine.com", "entry", 12, 15, false, &updated_visits));
- SendNotificationURLVisited(ui::PAGE_TRANSITION_TYPED, twelve_visits);
- GetTypedUrlsFromSyncDB(&new_sync_entries);
-
- // Should be no changes to the sync DB from this notification.
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(original_entry, new_sync_entries[0]));
-
- // Now, try updating it with a large number of visits that is divisible by 10
- // (should *not* be ignored).
- history::URLRow twenty_visits(MakeTypedUrlEntry(
- "http://mine.com", "entry", 20, 15, false, &updated_visits));
- SendNotificationURLVisited(ui::PAGE_TRANSITION_TYPED, twenty_visits);
- GetTypedUrlsFromSyncDB(&new_sync_entries);
-
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(twenty_visits, new_sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeRemove) {
- history::VisitVector original_visits1;
- history::URLRow original_entry1(MakeTypedUrlEntry(
- "http://mine.com", "entry", 2, 15, false, &original_visits1));
- history::VisitVector original_visits2;
- history::URLRow original_entry2(MakeTypedUrlEntry(
- "http://mine2.com", "entry2", 3, 15, false, &original_visits2));
- history::URLRows original_entries;
- original_entries.push_back(original_entry1);
- original_entries.push_back(original_entry2);
-
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(original_entries), Return(true)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>(original_visits1), Return(true)));
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
-
- history::URLRows rows;
- rows.push_back(history::URLRow(GURL("http://mine.com")));
- SendNotificationURLsDeleted(false, false, rows, std::set<GURL>());
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(original_entry2, new_sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeRemoveExpired) {
- history::VisitVector original_visits1;
- history::URLRow original_entry1(MakeTypedUrlEntry(
- "http://mine.com", "entry", 2, 15, false, &original_visits1));
- history::VisitVector original_visits2;
- history::URLRow original_entry2(MakeTypedUrlEntry(
- "http://mine2.com", "entry2", 3, 15, false, &original_visits2));
- history::URLRows original_entries;
- original_entries.push_back(original_entry1);
- original_entries.push_back(original_entry2);
-
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(original_entries), Return(true)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>(original_visits1), Return(true)));
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
-
- // Setting expired=true should cause the sync code to ignore this deletion.
- history::URLRows rows;
- rows.push_back(history::URLRow(GURL("http://mine.com")));
- SendNotificationURLsDeleted(false, true, rows, std::set<GURL>());
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
- // Both URLs should still be there.
- ASSERT_EQ(2U, new_sync_entries.size());
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeRemoveAll) {
- history::VisitVector original_visits1;
- history::URLRow original_entry1(MakeTypedUrlEntry(
- "http://mine.com", "entry", 2, 15, false, &original_visits1));
- history::VisitVector original_visits2;
- history::URLRow original_entry2(MakeTypedUrlEntry(
- "http://mine2.com", "entry2", 3, 15, false, &original_visits2));
- history::URLRows original_entries;
- original_entries.push_back(original_entry1);
- original_entries.push_back(original_entry2);
-
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(original_entries), Return(true)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>(original_visits1), Return(true)));
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
-
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
- ASSERT_EQ(2U, new_sync_entries.size());
-
- SendNotificationURLsDeleted(true, false, history::URLRows(),
- std::set<GURL>());
-
- GetTypedUrlsFromSyncDB(&new_sync_entries);
- ASSERT_EQ(0U, new_sync_entries.size());
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, FailWriteToHistoryBackend) {
- history::VisitVector native_visits;
- history::VisitVector sync_visits;
- history::URLRow native_entry(MakeTypedUrlEntry("http://native.com", "entry",
- 2, 15, false, &native_visits));
- history::URLRow sync_entry(MakeTypedUrlEntry("http://sync.com", "entry", 3,
- 16, false, &sync_visits));
-
- history::URLRows native_entries;
- native_entries.push_back(native_entry);
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(native_entries), Return(true)));
- EXPECT_CALL((history_backend()), GetURL(_, _))
- .WillOnce(DoAll(SetArgPointee<1>(native_entry), Return(false)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>(native_visits), Return(true)));
- EXPECT_CALL((history_backend()), AddVisits(_, _, history::SOURCE_SYNCED))
- .WillRepeatedly(Return(false));
-
- history::URLRows sync_entries;
- sync_entries.push_back(sync_entry);
-
- EXPECT_CALL((history_backend()), UpdateURL(_, _))
- .WillRepeatedly(Return(false));
- TypedUrlSyncableService* syncable_service =
- StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));
- // Errors writing to the DB should be recorded, but should not cause an
- // unrecoverable error.
- ASSERT_FALSE(sync_service()->data_type_status_table().GetFailedTypes().Has(
- syncer::TYPED_URLS));
- // Some calls should have succeeded, so the error percentage should be
- // somewhere > 0 and < 100.
- ASSERT_NE(0, syncable_service->GetErrorPercentage());
- ASSERT_NE(100, syncable_service->GetErrorPercentage());
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, FailToGetTypedURLs) {
- history::VisitVector native_visits;
- history::VisitVector sync_visits;
- history::URLRow native_entry(MakeTypedUrlEntry("http://native.com", "entry",
- 2, 15, false, &native_visits));
- history::URLRow sync_entry(MakeTypedUrlEntry("http://sync.com", "entry", 3,
- 16, false, &sync_visits));
-
- history::URLRows native_entries;
- native_entries.push_back(native_entry);
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillOnce(DoAll(SetArgPointee<0>(native_entries), Return(false)));
-
- history::URLRows sync_entries;
- sync_entries.push_back(sync_entry);
-
- StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));
- // Errors getting typed URLs will cause an unrecoverable error (since we can
- // do *nothing* in that case).
- ASSERT_TRUE(sync_service()->data_type_status_table().GetFailedTypes().Has(
- syncer::TYPED_URLS));
- ASSERT_EQ(1u,
- sync_service()->data_type_status_table().GetFailedTypes().Size());
- // Can't check GetErrorPercentage(), because generating an unrecoverable
- // error will free the model associator.
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, IgnoreLocalFileURL) {
- history::VisitVector original_visits;
- // Create http and file url.
- history::URLRow url_entry(MakeTypedUrlEntry("http://yey.com", "yey", 12, 15,
- false, &original_visits));
- history::URLRow file_entry(MakeTypedUrlEntry(
- "file:///kitty.jpg", "kitteh", 12, 15, false, &original_visits));
-
- history::URLRows original_entries;
- original_entries.push_back(url_entry);
- original_entries.push_back(file_entry);
-
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillRepeatedly(DoAll(SetArgPointee<0>(original_entries), Return(true)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>(original_visits), Return(true)));
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
-
- history::VisitVector updated_visits;
- // Create updates for the previous urls + a new file one.
- history::URLRow updated_url_entry(MakeTypedUrlEntry(
- "http://yey.com", "yey", 20, 15, false, &updated_visits));
- history::URLRow updated_file_entry(MakeTypedUrlEntry(
- "file:///cat.jpg", "cat", 20, 15, false, &updated_visits));
- history::URLRow new_file_entry(MakeTypedUrlEntry("file:///dog.jpg", "dog", 20,
- 15, false, &updated_visits));
-
- history::URLRows changed_urls;
- changed_urls.push_back(updated_url_entry);
- changed_urls.push_back(updated_file_entry);
- changed_urls.push_back(new_file_entry);
- SendNotificationURLsModified(changed_urls);
-
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
-
- // We should ignore the local file urls (existing and updated),
- // and only be left with the updated http url.
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(updated_url_entry, new_sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, IgnoreLocalhostURL) {
- history::VisitVector original_visits;
- // Create http and localhost url.
- history::URLRow url_entry(MakeTypedUrlEntry("http://yey.com", "yey", 12, 15,
- false, &original_visits));
- history::URLRow localhost_entry(MakeTypedUrlEntry(
- "http://localhost", "localhost", 12, 15, false, &original_visits));
-
- history::URLRows original_entries;
- original_entries.push_back(url_entry);
- original_entries.push_back(localhost_entry);
-
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillRepeatedly(DoAll(SetArgPointee<0>(original_entries), Return(true)));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>(original_visits), Return(true)));
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
-
- history::VisitVector updated_visits;
- // Update the previous entries and add a new localhost.
- history::URLRow updated_url_entry(MakeTypedUrlEntry(
- "http://yey.com", "yey", 20, 15, false, &updated_visits));
- history::URLRow updated_localhost_entry(MakeTypedUrlEntry(
- "http://localhost:80", "localhost", 20, 15, false, &original_visits));
- history::URLRow localhost_ip_entry(MakeTypedUrlEntry(
- "http://127.0.0.1", "localhost", 12, 15, false, &original_visits));
-
- history::URLRows changed_urls;
- changed_urls.push_back(updated_url_entry);
- changed_urls.push_back(updated_localhost_entry);
- changed_urls.push_back(localhost_ip_entry);
- SendNotificationURLsModified(changed_urls);
-
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
-
- // We should ignore the localhost urls and left only with http url.
- ASSERT_EQ(1U, new_sync_entries.size());
- EXPECT_TRUE(URLsEqual(updated_url_entry, new_sync_entries[0]));
-}
-
-TEST_F(ProfileSyncServiceTypedUrlTest, IgnoreModificationWithoutValidVisit) {
- EXPECT_CALL((history_backend()), GetAllTypedURLs(_))
- .WillRepeatedly(Return(true));
- EXPECT_CALL((history_backend()), GetMostRecentVisitsForURL(_, _, _))
- .WillRepeatedly(Return(true));
-
- CreateRootHelper create_root(this, syncer::TYPED_URLS);
- StartSyncService(create_root.callback());
-
- history::VisitVector updated_visits;
- history::URLRow updated_url_entry(MakeTypedUrlEntry(
- "http://yey.com", "yey", 20, 0, false, &updated_visits));
-
- history::URLRows changed_urls;
- changed_urls.push_back(updated_url_entry);
- SendNotificationURLsModified(changed_urls);
-
- history::URLRows new_sync_entries;
- GetTypedUrlsFromSyncDB(&new_sync_entries);
-
- // The change should be ignored.
- ASSERT_EQ(0U, new_sync_entries.size());
-}
-
-} // namespace browser_sync
diff --git a/chromium/components/browser_sync/profile_sync_service_unittest.cc b/chromium/components/browser_sync/profile_sync_service_unittest.cc
index fa95486dc49..ffcb16bdb94 100644
--- a/chromium/components/browser_sync/profile_sync_service_unittest.cc
+++ b/chromium/components/browser_sync/profile_sync_service_unittest.cc
@@ -15,7 +15,6 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
-#include "base/test/sequenced_worker_pool_owner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "components/browser_sync/browser_sync_switches.h"
@@ -162,10 +161,6 @@ ACTION_P(ReturnNewMockHostCaptureClearServerData, captured_callback) {
&OnClearServerDataCalled, base::Unretained(captured_callback)));
}
-void DoNothing(DataTypeController::ConfigureResult ignored1,
- const SyncMergeResult& ignored2,
- const SyncMergeResult& ignored3) {}
-
// A test harness that uses a real ProfileSyncService and in most cases a
// MockSyncEngine.
//
@@ -992,7 +987,7 @@ TEST_F(ProfileSyncServiceTest, GetOpenTabsUIDelegate) {
std::make_unique<syncer::FakeDataTypeController>(syncer::PROXY_TABS);
// Progress the controller to RUNNING first, which is how the service
// determines whether a type is enabled.
- controller->StartAssociating(base::Bind(&DoNothing));
+ controller->StartAssociating(base::DoNothing());
controller->FinishStart(DataTypeController::OK_FIRST_RUN);
service()->RegisterDataTypeController(std::move(controller));
EXPECT_NE(nullptr, service()->GetOpenTabsUIDelegate());
diff --git a/chromium/components/browser_sync/profile_sync_test_util.cc b/chromium/components/browser_sync/profile_sync_test_util.cc
index 956573725ce..249c55b7e3e 100644
--- a/chromium/components/browser_sync/profile_sync_test_util.cc
+++ b/chromium/components/browser_sync/profile_sync_test_util.cc
@@ -13,7 +13,6 @@
#include "components/history/core/browser/history_model_worker.h"
#include "components/history/core/browser/history_service.h"
#include "components/pref_registry/pref_registry_syncable.h"
-#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/signin_manager_base.h"
#include "components/sync/base/sync_prefs.h"
#include "components/sync/driver/signin_manager_wrapper.h"
@@ -166,17 +165,12 @@ bookmarks::BookmarkModel* BundleSyncClient::GetBookmarkModel() {
} // namespace
-void EmptyNetworkTimeUpdate(const base::Time&,
- const base::TimeDelta&,
- const base::TimeDelta&) {}
-
void RegisterPrefsForProfileSyncService(
user_prefs::PrefRegistrySyncable* registry) {
syncer::SyncPrefs::RegisterProfilePrefs(registry);
AccountTrackerService::RegisterPrefs(registry);
SigninManagerBase::RegisterProfilePrefs(registry);
SigninManagerBase::RegisterPrefs(registry);
- signin::RegisterAccountConsistencyProfilePrefs(registry);
}
ProfileSyncServiceBundle::SyncClientBuilder::~SyncClientBuilder() = default;
@@ -229,7 +223,6 @@ ProfileSyncServiceBundle::SyncClientBuilder::Build() {
ProfileSyncServiceBundle::ProfileSyncServiceBundle()
: db_thread_(base::ThreadTaskRunnerHandle::Get()),
- worker_pool_owner_(2, "sync test worker pool"),
signin_client_(&pref_service_),
#if defined(OS_CHROMEOS)
signin_manager_(&signin_client_, &account_tracker_),
@@ -242,7 +235,6 @@ ProfileSyncServiceBundle::ProfileSyncServiceBundle()
url_request_context_(new net::TestURLRequestContextGetter(
base::ThreadTaskRunnerHandle::Get())) {
RegisterPrefsForProfileSyncService(pref_service_.registry());
- signin::SetGaiaOriginIsolatedCallback(base::Bind([] { return true; }));
auth_service_.set_auto_post_fetch_response_on_message_loop(true);
account_tracker_.Initialize(&signin_client_);
signin_manager_.Initialize(&pref_service_);
@@ -260,8 +252,7 @@ ProfileSyncService::InitParams ProfileSyncServiceBundle::CreateBasicInitParams(
init_params.signin_wrapper =
std::make_unique<SigninManagerWrapper>(signin_manager());
init_params.oauth2_token_service = auth_service();
- init_params.network_time_update_callback =
- base::Bind(&EmptyNetworkTimeUpdate);
+ init_params.network_time_update_callback = base::DoNothing();
EXPECT_TRUE(base_directory_.CreateUniqueTempDir());
init_params.base_directory = base_directory_.GetPath();
init_params.url_request_context = url_request_context();
diff --git a/chromium/components/browser_sync/profile_sync_test_util.h b/chromium/components/browser_sync/profile_sync_test_util.h
index 63252044d6d..44eccf009f0 100644
--- a/chromium/components/browser_sync/profile_sync_test_util.h
+++ b/chromium/components/browser_sync/profile_sync_test_util.h
@@ -11,9 +11,6 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/test/sequenced_worker_pool_owner.h"
-#include "base/time/time.h"
#include "components/browser_sync/profile_sync_service.h"
#include "components/invalidation/impl/fake_invalidation_service.h"
#include "components/signin/core/browser/account_tracker_service.h"
@@ -23,12 +20,7 @@
#include "components/sync/driver/fake_sync_client.h"
#include "components/sync/driver/sync_api_component_factory_mock.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "components/sync_sessions/fake_sync_sessions_client.h"
-
-namespace base {
-class Time;
-class TimeDelta;
-}
+#include "components/sync_sessions/mock_sync_sessions_client.h"
namespace history {
class HistoryService;
@@ -44,12 +36,6 @@ class PrefRegistrySyncable;
namespace browser_sync {
-// An empty syncer::NetworkTimeUpdateCallback. Used in various tests to
-// instantiate ProfileSyncService.
-void EmptyNetworkTimeUpdate(const base::Time&,
- const base::TimeDelta&,
- const base::TimeDelta&);
-
// Call this to register preferences needed for ProfileSyncService creation.
void RegisterPrefsForProfileSyncService(
user_prefs::PrefRegistrySyncable* registry);
@@ -152,7 +138,7 @@ class ProfileSyncServiceBundle {
return &component_factory_;
}
- sync_sessions::FakeSyncSessionsClient* sync_sessions_client() {
+ sync_sessions::MockSyncSessionsClient* sync_sessions_client() {
return &sync_sessions_client_;
}
@@ -169,14 +155,14 @@ class ProfileSyncServiceBundle {
private:
scoped_refptr<base::SingleThreadTaskRunner> db_thread_;
- base::SequencedWorkerPoolOwner worker_pool_owner_;
sync_preferences::TestingPrefServiceSyncable pref_service_;
TestSigninClient signin_client_;
AccountTrackerService account_tracker_;
FakeSigninManagerType signin_manager_;
FakeProfileOAuth2TokenService auth_service_;
syncer::SyncApiComponentFactoryMock component_factory_;
- sync_sessions::FakeSyncSessionsClient sync_sessions_client_;
+ testing::NiceMock<sync_sessions::MockSyncSessionsClient>
+ sync_sessions_client_;
invalidation::FakeInvalidationService fake_invalidation_service_;
scoped_refptr<net::URLRequestContextGetter> url_request_context_;
base::ScopedTempDir base_directory_;
diff --git a/chromium/components/browser_sync/signin_confirmation_helper.cc b/chromium/components/browser_sync/signin_confirmation_helper.cc
index 1300ae0384b..1270e0aedae 100644
--- a/chromium/components/browser_sync/signin_confirmation_helper.cc
+++ b/chromium/components/browser_sync/signin_confirmation_helper.cc
@@ -94,6 +94,7 @@ void SigninConfirmationHelper::CheckHasTypedURLs() {
return;
}
history_service_->ScheduleDBTask(
+ FROM_HERE,
std::unique_ptr<history::HistoryDBTask>(new HasTypedURLsTask(base::Bind(
&SigninConfirmationHelper::ReturnResult, base::Unretained(this)))),
&task_tracker_);
diff --git a/chromium/components/browser_watcher/BUILD.gn b/chromium/components/browser_watcher/BUILD.gn
index 6ec8d23c0c0..59683c59ab5 100644
--- a/chromium/components/browser_watcher/BUILD.gn
+++ b/chromium/components/browser_watcher/BUILD.gn
@@ -49,20 +49,18 @@ if (is_win) {
"postmortem_minidump_writer_win.cc",
"postmortem_report_collector.cc",
"postmortem_report_collector.h",
- "system_session_analyzer_win.cc",
- "system_session_analyzer_win.h",
]
deps = [
":stability_client",
":stability_common",
":stability_report_proto",
"//base",
+ "//components/metrics:metrics",
"//components/variations",
"//third_party/crashpad/crashpad/client",
"//third_party/crashpad/crashpad/minidump",
"//third_party/crashpad/crashpad/util",
]
- libs = [ "wevtapi.lib" ]
ldflags = [ "/DELAYLOAD:wevtapi.dll" ] # Only used after unclean shutdowns.
}
@@ -128,7 +126,6 @@ if (is_win) {
"stability_debugging_win_unittest.cc",
"stability_paths_unittest.cc",
"stability_report_extractor_unittest.cc",
- "system_session_analyzer_win_unittest.cc",
"watcher_client_win_unittest.cc",
"watcher_metrics_provider_win_unittest.cc",
"window_hang_monitor_win_unittest.cc",
@@ -143,6 +140,7 @@ if (is_win) {
":stability_report_proto",
"//base",
"//base/test:test_support",
+ "//components/metrics:metrics",
"//testing/gmock",
"//testing/gtest",
"//third_party/crashpad/crashpad/client",
@@ -171,6 +169,7 @@ if (is_win) {
deps = [
":postmortem_stability",
"//base",
+ "//components/metrics:metrics",
]
}
}
diff --git a/chromium/components/browser_watcher/fetch_system_session_events_main_win.cc b/chromium/components/browser_watcher/fetch_system_session_events_main_win.cc
index 2f17b9333c7..d264a6b3b31 100644
--- a/chromium/components/browser_watcher/fetch_system_session_events_main_win.cc
+++ b/chromium/components/browser_watcher/fetch_system_session_events_main_win.cc
@@ -9,26 +9,26 @@
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
-#include "components/browser_watcher/system_session_analyzer_win.h"
+#include "components/metrics/system_session_analyzer_win.h"
namespace {
-using browser_watcher::SystemSessionAnalyzer;
+using metrics::SystemSessionAnalyzer;
class SystemSessionEventFetcher : public SystemSessionAnalyzer {
public:
- explicit SystemSessionEventFetcher(uint32_t session_cnt)
- : SystemSessionAnalyzer(session_cnt) {}
+ explicit SystemSessionEventFetcher() : SystemSessionAnalyzer(0) {}
using SystemSessionAnalyzer::FetchEvents;
};
} // namespace
int main(int argc, char** argv) {
- // Retrieve events for the last 5 sessions.
- SystemSessionEventFetcher fetcher(5U);
+ SystemSessionEventFetcher fetcher;
std::vector<SystemSessionEventFetcher::EventInfo> events;
- if (!fetcher.FetchEvents(&events)) {
+ // Retrieve events for the last 5 sessions. We expect our own sessions start
+ // event, and then 2 events per each preceding session for 11 total.
+ if (!fetcher.FetchEvents(11U, &events)) {
std::cerr << "Failed to fetch events." << std::endl;
return 1;
}
diff --git a/chromium/components/browser_watcher/postmortem_minidump_writer.h b/chromium/components/browser_watcher/postmortem_minidump_writer.h
index 15079aee932..0c82cfc9ff4 100644
--- a/chromium/components/browser_watcher/postmortem_minidump_writer.h
+++ b/chromium/components/browser_watcher/postmortem_minidump_writer.h
@@ -9,8 +9,8 @@
#include <string>
-#include "base/files/file.h"
#include "components/browser_watcher/stability_report.pb.h"
+#include "third_party/crashpad/crashpad/util/file/file_writer.h"
#include "third_party/crashpad/crashpad/util/misc/uuid.h"
namespace browser_watcher {
@@ -20,7 +20,7 @@ namespace browser_watcher {
// Note: the caller owns |minidump_file| and is responsible for keeping it valid
// for this function's duration. |minidump_file| is expected to be empty
// and a binary stream.
-bool WritePostmortemDump(base::PlatformFile minidump_file,
+bool WritePostmortemDump(crashpad::FileWriterInterface* minidump_file,
const crashpad::UUID& client_id,
const crashpad::UUID& report_id,
StabilityReport* report);
diff --git a/chromium/components/browser_watcher/postmortem_minidump_writer_win.cc b/chromium/components/browser_watcher/postmortem_minidump_writer_win.cc
index 30222db2ce9..4b398d7fe2f 100644
--- a/chromium/components/browser_watcher/postmortem_minidump_writer_win.cc
+++ b/chromium/components/browser_watcher/postmortem_minidump_writer_win.cc
@@ -73,19 +73,6 @@ bool GetProductDetails(
&(product_details->version));
}
-int64_t GetFileOffset(base::File* file) {
- DCHECK(file);
- return file->Seek(base::File::FROM_CURRENT, 0LL);
-}
-
-// Returns true if the file is empty, and false if the file is not empty or if
-// there is an error.
-bool IsFileEmpty(base::File* file) {
- DCHECK(file);
- int64_t end = file->Seek(base::File::FROM_END, 0LL);
- return end == 0LL;
-}
-
// A class with functionality for writing minimal minidump containers to wrap
// postmortem stability reports.
// TODO(manzagop): remove this class once Crashpad takes over writing postmortem
@@ -102,16 +89,13 @@ class PostmortemMinidumpWriter {
WRITE_STATUS_MAX = 3
};
- PostmortemMinidumpWriter();
+ // |minidump_file| is expected to be empty and a binary stream.
+ PostmortemMinidumpWriter(crashpad::FileWriterInterface* minidump_file);
~PostmortemMinidumpWriter();
- // Write to |minidump_file| a minimal minidump that wraps |report|. Returns
+ // Write to |minidump_file_| a minimal minidump that wraps |report|. Returns
// true on success, false otherwise.
- // Note: the caller owns |minidump_file| and is responsible for keeping it
- // valid for this object's lifetime. |minidump_file| is expected to be empty
- // and a binary stream.
- bool WriteDump(base::PlatformFile minidump_file,
- const crashpad::UUID& client_id,
+ bool WriteDump(const crashpad::UUID& client_id,
const crashpad::UUID& report_id,
StabilityReport* report);
@@ -172,8 +156,8 @@ class PostmortemMinidumpWriter {
// Storage for the directory during writes.
std::vector<MINIDUMP_DIRECTORY> directory_;
- // The file to write to. Only valid within the scope of a call to WriteDump.
- base::File* minidump_file_;
+ // The file to write to.
+ crashpad::FileWriterInterface* minidump_file_;
DISALLOW_COPY_AND_ASSIGN(PostmortemMinidumpWriter);
};
@@ -184,24 +168,24 @@ void RecordWriteDumpStatus(PostmortemMinidumpWriter::WriteStatus status) {
PostmortemMinidumpWriter::WRITE_STATUS_MAX);
}
-PostmortemMinidumpWriter::PostmortemMinidumpWriter()
- : next_available_byte_(0U), minidump_file_(nullptr) {}
-
-PostmortemMinidumpWriter::~PostmortemMinidumpWriter() {
- DCHECK_EQ(nullptr, minidump_file_);
+PostmortemMinidumpWriter::PostmortemMinidumpWriter(
+ crashpad::FileWriterInterface* minidump_file)
+ : next_available_byte_(0U), minidump_file_(minidump_file) {
+ DCHECK_NE(nullptr, minidump_file_);
+ DCHECK_EQ(0LL, minidump_file_->SeekGet());
+ DCHECK_EQ(0LL, minidump_file_->Seek(0LL, SEEK_END));
}
+PostmortemMinidumpWriter::~PostmortemMinidumpWriter() {}
+
bool PostmortemMinidumpWriter::WriteDump(
- base::PlatformFile minidump_platform_file,
const crashpad::UUID& client_id,
const crashpad::UUID& report_id,
StabilityReport* report) {
- DCHECK_NE(base::kInvalidPlatformFile, minidump_platform_file);
DCHECK(report);
DCHECK_EQ(0U, next_available_byte_);
DCHECK(directory_.empty());
- DCHECK_EQ(nullptr, minidump_file_);
// Ensure the report contains the crasher's product details.
ProductDetails product_details = {};
@@ -218,27 +202,10 @@ bool PostmortemMinidumpWriter::WriteDump(
report->mutable_global_data()->erase(kStabilityPlatform);
report->mutable_global_data()->erase(kStabilityVersion);
- // We do not own |minidump_platform_file|, but we want to rely on base::File's
- // API, and so we need to duplicate it.
- HANDLE duplicated_handle;
- BOOL duplicate_success = ::DuplicateHandle(
- ::GetCurrentProcess(), minidump_platform_file, ::GetCurrentProcess(),
- &duplicated_handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
- if (!duplicate_success) {
- RecordWriteDumpStatus(FAILED);
- return false;
- }
- base::File minidump_file(duplicated_handle);
- DCHECK(minidump_file.IsValid());
- minidump_file_ = &minidump_file;
- DCHECK_EQ(0LL, GetFileOffset(minidump_file_));
- DCHECK(IsFileEmpty(minidump_file_));
-
// Write the minidump, then reset members.
bool success = WriteDumpImpl(*report, client_id, report_id, product_details);
next_available_byte_ = 0U;
directory_.clear();
- minidump_file_ = nullptr;
RecordWriteDumpStatus(success ? SUCCESS : FAILED);
return success;
@@ -383,16 +350,11 @@ bool PostmortemMinidumpWriter::Allocate(size_t size_bytes, FilePosition* pos) {
}
bool PostmortemMinidumpWriter::SeekCursor(FilePosition destination) {
- DCHECK_NE(nullptr, minidump_file_);
- DCHECK(minidump_file_->IsValid());
-
// Validate the write does not extend past the allocated space.
if (destination > next_available_byte_)
return false;
- int64_t new_pos = minidump_file_->Seek(base::File::FROM_BEGIN,
- static_cast<int64_t>(destination));
- return new_pos != -1;
+ return minidump_file_->SeekSet(destination);
}
template <class DataType>
@@ -406,9 +368,7 @@ bool PostmortemMinidumpWriter::WriteBytes(FilePosition pos,
size_t size_bytes,
const char* data) {
DCHECK(data);
- DCHECK_NE(nullptr, minidump_file_);
- DCHECK(minidump_file_->IsValid());
- DCHECK_EQ(static_cast<int64_t>(pos), GetFileOffset(minidump_file_));
+ DCHECK_EQ(static_cast<int64_t>(pos), minidump_file_->SeekGet());
// Validate the write does not extend past the next available byte.
base::CheckedNumeric<FilePosition> pos_end = pos;
@@ -416,14 +376,7 @@ bool PostmortemMinidumpWriter::WriteBytes(FilePosition pos,
if (!pos_end.IsValid() || pos_end.ValueOrDie() > next_available_byte_)
return false;
- int size_bytes_signed = static_cast<int>(size_bytes);
- CHECK_LE(0, size_bytes_signed);
-
- int written_bytes =
- minidump_file_->WriteAtCurrentPos(data, size_bytes_signed);
- if (written_bytes < 0)
- return false;
- return static_cast<size_t>(written_bytes) == size_bytes;
+ return minidump_file_->Write(data, size_bytes);
}
template <class DataType>
@@ -482,14 +435,14 @@ void PostmortemMinidumpWriter::RegisterDirectoryEntry(uint32_t stream_type,
} // namespace
-bool WritePostmortemDump(base::PlatformFile minidump_file,
+bool WritePostmortemDump(crashpad::FileWriterInterface* minidump_file,
const crashpad::UUID& client_id,
const crashpad::UUID& report_id,
StabilityReport* report) {
DCHECK(report);
- PostmortemMinidumpWriter writer;
- return writer.WriteDump(minidump_file, client_id, report_id, report);
+ PostmortemMinidumpWriter writer(minidump_file);
+ return writer.WriteDump(client_id, report_id, report);
}
} // namespace browser_watcher
diff --git a/chromium/components/browser_watcher/postmortem_minidump_writer_win_unittest.cc b/chromium/components/browser_watcher/postmortem_minidump_writer_win_unittest.cc
index c46e6799d11..8520b1bbda4 100644
--- a/chromium/components/browser_watcher/postmortem_minidump_writer_win_unittest.cc
+++ b/chromium/components/browser_watcher/postmortem_minidump_writer_win_unittest.cc
@@ -63,14 +63,13 @@ class WritePostmortemDumpTest : public testing::Test {
global_data[kStabilityVersion].set_string_value(kVersion);
}
- base::win::ScopedHandle file_handle(::CreateFile(
- minidump_path_.value().c_str(), GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_NEW,
- FILE_ATTRIBUTE_NORMAL, nullptr));
- if (!file_handle.IsValid())
+ crashpad::FileWriter writer;
+ if (!writer.Open(minidump_path_, crashpad::FileWriteMode::kCreateOrFail,
+ crashpad::FilePermissions::kWorldReadable)) {
return false;
+ }
- return WritePostmortemDump(file_handle.Get(), expected_client_id_,
+ return WritePostmortemDump(&writer, expected_client_id_,
expected_report_id_, &report);
}
diff --git a/chromium/components/browser_watcher/postmortem_report_collector.cc b/chromium/components/browser_watcher/postmortem_report_collector.cc
index d59b526cddd..1155c054929 100644
--- a/chromium/components/browser_watcher/postmortem_report_collector.cc
+++ b/chromium/components/browser_watcher/postmortem_report_collector.cc
@@ -60,14 +60,14 @@ void LogCollectionStatus(CollectionStatus status) {
} // namespace
PostmortemReportCollector::PostmortemReportCollector(
- SystemSessionAnalyzer* analyzer)
+ metrics::SystemSessionAnalyzer* analyzer)
: report_database_(nullptr), system_session_analyzer_(analyzer) {}
PostmortemReportCollector::PostmortemReportCollector(
const std::string& product_name,
const std::string& version_number,
const std::string& channel_name,
crashpad::CrashReportDatabase* report_database,
- SystemSessionAnalyzer* analyzer)
+ metrics::SystemSessionAnalyzer* analyzer)
: product_name_(product_name),
version_number_(version_number),
channel_name_(channel_name),
@@ -193,19 +193,19 @@ void PostmortemReportCollector::RecordSystemShutdownState(
} else if (!system_session_analyzer_) {
status = SYSTEM_SESSION_ANALYSIS_NO_ANALYZER;
} else {
- SystemSessionAnalyzer::Status analyzer_status =
+ metrics::SystemSessionAnalyzer::Status analyzer_status =
system_session_analyzer_->IsSessionUnclean(time);
switch (analyzer_status) {
- case SystemSessionAnalyzer::FAILED:
+ case metrics::SystemSessionAnalyzer::FAILED:
status = SYSTEM_SESSION_ANALYSIS_FAILED;
break;
- case SystemSessionAnalyzer::CLEAN:
+ case metrics::SystemSessionAnalyzer::CLEAN:
session_state = SystemState::CLEAN;
break;
- case SystemSessionAnalyzer::UNCLEAN:
+ case metrics::SystemSessionAnalyzer::UNCLEAN:
session_state = SystemState::UNCLEAN;
break;
- case SystemSessionAnalyzer::OUTSIDE_RANGE:
+ case metrics::SystemSessionAnalyzer::OUTSIDE_RANGE:
status = SYSTEM_SESSION_ANALYSIS_OUTSIDE_RANGE;
break;
}
@@ -263,7 +263,8 @@ bool PostmortemReportCollector::WriteReportToMinidump(
base::PlatformFile minidump_file) {
DCHECK(report);
- return WritePostmortemDump(minidump_file, client_id, report_id, report);
+ crashpad::WeakFileHandleFileWriter writer(minidump_file);
+ return WritePostmortemDump(&writer, client_id, report_id, report);
}
} // namespace browser_watcher
diff --git a/chromium/components/browser_watcher/postmortem_report_collector.h b/chromium/components/browser_watcher/postmortem_report_collector.h
index 09a32845eb4..367250a87eb 100644
--- a/chromium/components/browser_watcher/postmortem_report_collector.h
+++ b/chromium/components/browser_watcher/postmortem_report_collector.h
@@ -23,7 +23,7 @@
#include "base/strings/string16.h"
#include "components/browser_watcher/stability_report.pb.h"
#include "components/browser_watcher/stability_report_extractor.h"
-#include "components/browser_watcher/system_session_analyzer_win.h"
+#include "components/metrics/system_session_analyzer_win.h"
#include "third_party/crashpad/crashpad/client/crash_report_database.h"
namespace browser_watcher {
@@ -39,12 +39,12 @@ class PostmortemReportCollector {
// crash reports. If |report_database| is set, postmortem crash reports are
// generated and registered against it. If |analyzer| is set, it used to
// analyze the containing system session.
- PostmortemReportCollector(SystemSessionAnalyzer* analyzer);
+ PostmortemReportCollector(metrics::SystemSessionAnalyzer* analyzer);
PostmortemReportCollector(const std::string& product_name,
const std::string& version_number,
const std::string& channel_name,
crashpad::CrashReportDatabase* report_database,
- SystemSessionAnalyzer* analyzer);
+ metrics::SystemSessionAnalyzer* analyzer);
~PostmortemReportCollector();
// Analyzes |stability_files|, logs postmortem user metrics and optionally
@@ -104,7 +104,7 @@ class PostmortemReportCollector {
std::string channel_name_;
crashpad::CrashReportDatabase* report_database_; // Not owned.
- SystemSessionAnalyzer* system_session_analyzer_; // Not owned.
+ metrics::SystemSessionAnalyzer* system_session_analyzer_; // Not owned.
DISALLOW_COPY_AND_ASSIGN(PostmortemReportCollector);
};
diff --git a/chromium/components/browser_watcher/postmortem_report_collector_unittest.cc b/chromium/components/browser_watcher/postmortem_report_collector_unittest.cc
index 9192551a55d..eb4a1034087 100644
--- a/chromium/components/browser_watcher/postmortem_report_collector_unittest.cc
+++ b/chromium/components/browser_watcher/postmortem_report_collector_unittest.cc
@@ -28,6 +28,7 @@
#include "base/threading/platform_thread.h"
#include "components/browser_watcher/stability_data_names.h"
#include "components/browser_watcher/stability_report_extractor.h"
+#include "components/metrics/system_session_analyzer_win.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/crashpad/crashpad/client/crash_report_database.h"
@@ -59,48 +60,6 @@ const char kProductName[] = "TestProduct";
const char kVersionNumber[] = "TestVersionNumber";
const char kChannelName[] = "TestChannel";
-// Exposes a public constructor in order to create a dummy database.
-class MockCrashReportDatabase : public CrashReportDatabase {
- public:
- MockCrashReportDatabase() {}
- MOCK_METHOD0(GetSettings, Settings*());
- MOCK_METHOD1(PrepareNewCrashReport,
- CrashReportDatabase::CrashReportDatabase::OperationStatus(
- NewReport** report));
- MOCK_METHOD2(FinishedWritingCrashReport,
- CrashReportDatabase::CrashReportDatabase::OperationStatus(
- CrashReportDatabase::NewReport* report,
- crashpad::UUID* uuid));
- MOCK_METHOD1(ErrorWritingCrashReport,
- CrashReportDatabase::CrashReportDatabase::OperationStatus(
- NewReport* report));
- MOCK_METHOD2(LookUpCrashReport,
- CrashReportDatabase::CrashReportDatabase::OperationStatus(
- const UUID& uuid,
- Report* report));
- MOCK_METHOD1(
- GetPendingReports,
- CrashReportDatabase::OperationStatus(std::vector<Report>* reports));
- MOCK_METHOD1(
- GetCompletedReports,
- CrashReportDatabase::OperationStatus(std::vector<Report>* reports));
- MOCK_METHOD2(GetReportForUploading,
- CrashReportDatabase::OperationStatus(const UUID& uuid,
- const Report** report));
- MOCK_METHOD3(RecordUploadAttempt,
- CrashReportDatabase::OperationStatus(const Report* report,
- bool successful,
- const std::string& id));
- MOCK_METHOD2(SkipReportUpload,
- CrashReportDatabase::OperationStatus(
- const UUID& uuid,
- crashpad::Metrics::CrashSkippedReason reason));
- MOCK_METHOD1(DeleteReport,
- CrashReportDatabase::OperationStatus(const UUID& uuid));
- MOCK_METHOD1(RequestUpload,
- CrashReportDatabase::OperationStatus(const UUID& uuid));
-};
-
class MockPostmortemReportCollector final : public PostmortemReportCollector {
public:
explicit MockPostmortemReportCollector(CrashReportDatabase* crash_database)
@@ -119,7 +78,7 @@ class MockPostmortemReportCollector final : public PostmortemReportCollector {
base::PlatformFile minidump_file));
};
-class MockSystemSessionAnalyzer : public SystemSessionAnalyzer {
+class MockSystemSessionAnalyzer : public metrics::SystemSessionAnalyzer {
public:
MockSystemSessionAnalyzer() : SystemSessionAnalyzer(10U) {}
MOCK_METHOD1(IsSessionUnclean, Status(base::Time timestamp));
@@ -152,9 +111,6 @@ class PostmortemReportCollectorProcessTest
void SetUpTest(bool system_session_clean,
bool expect_write_dump,
bool provide_crash_db) {
- collector_.reset(new MockPostmortemReportCollector(
- provide_crash_db ? &database_ : nullptr));
-
// Create a dummy debug file.
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
debug_file_ = temp_dir_.GetPath().AppendASCII("foo-1.pma");
@@ -164,8 +120,12 @@ class PostmortemReportCollectorProcessTest
}
ASSERT_TRUE(base::PathExists(debug_file_));
- if (provide_crash_db)
- EXPECT_CALL(database_, GetSettings()).Times(1).WillOnce(Return(nullptr));
+ if (provide_crash_db) {
+ database_ = CrashReportDatabase::Initialize(
+ temp_dir_.GetPath().AppendASCII("db"));
+ }
+
+ collector_.reset(new MockPostmortemReportCollector(database_.get()));
// Expect a single collection call.
StabilityReport report;
@@ -175,28 +135,11 @@ class PostmortemReportCollectorProcessTest
.Times(1)
.WillOnce(DoAll(SetArgPointee<1>(report), Return(SUCCESS)));
- if (!expect_write_dump)
- return;
-
- // Expect the call to write the proto to a minidump. This involves
- // requesting a report from the crashpad database, writing the report, then
- // finalizing it with the database.
- FilePath minidump_path = temp_dir_.GetPath().AppendASCII("foo-1.dmp");
- base::File minidump_file(
- minidump_path, base::File::FLAG_CREATE | base::File::File::FLAG_WRITE);
- crashpad::UUID new_report_uuid;
- new_report_uuid.InitializeWithNew();
- crashpad_report_ = {minidump_file.GetPlatformFile(), new_report_uuid,
- minidump_path};
- EXPECT_CALL(database_, PrepareNewCrashReport(_))
- .Times(1)
- .WillOnce(DoAll(SetArgPointee<0>(&crashpad_report_),
- Return(CrashReportDatabase::kNoError)));
-
- EXPECT_CALL(*collector_,
- WriteReportToMinidump(_, _, _, minidump_file.GetPlatformFile()))
- .Times(1)
- .WillOnce(Return(true));
+ if (expect_write_dump) {
+ EXPECT_CALL(*collector_, WriteReportToMinidump(_, _, _, _))
+ .Times(1)
+ .WillOnce(Return(true));
+ }
}
void ValidateHistograms(int unclean_cnt, int unclean_system_cnt) {
histogram_tester_.ExpectBucketCount("ActivityTracker.Collect.Status",
@@ -207,25 +150,25 @@ class PostmortemReportCollectorProcessTest
void CollectReports(bool is_session_clean, bool provide_crash_db) {
SetUpTest(is_session_clean, provide_crash_db, provide_crash_db);
- if (provide_crash_db) {
- EXPECT_CALL(database_, FinishedWritingCrashReport(&crashpad_report_, _))
- .Times(1)
- .WillOnce(Return(CrashReportDatabase::kNoError));
- }
-
// Run the test.
std::vector<FilePath> debug_files{debug_file_};
collector_->Process(debug_files);
ASSERT_FALSE(base::PathExists(debug_file_));
+
+ if (provide_crash_db) {
+ std::vector<CrashReportDatabase::Report> reports;
+ ASSERT_EQ(CrashReportDatabase::kNoError,
+ database_->GetPendingReports(&reports));
+ EXPECT_EQ(1u, reports.size());
+ }
}
protected:
base::HistogramTester histogram_tester_;
base::ScopedTempDir temp_dir_;
FilePath debug_file_;
- MockCrashReportDatabase database_;
+ std::unique_ptr<CrashReportDatabase> database_;
std::unique_ptr<MockPostmortemReportCollector> collector_;
- CrashReportDatabase::NewReport crashpad_report_;
};
TEST_P(PostmortemReportCollectorProcessTest, ProcessCleanSession) {
@@ -285,9 +228,10 @@ TEST(PostmortemReportCollectorTest, CollectEmptyFile) {
ASSERT_TRUE(PathExists(file_path));
// Validate collection: an empty file cannot suppport an analyzer.
- MockCrashReportDatabase crash_db;
+ std::unique_ptr<CrashReportDatabase> crash_db(
+ CrashReportDatabase::Initialize(temp_dir.GetPath().AppendASCII("db")));
PostmortemReportCollector collector(kProductName, kVersionNumber,
- kChannelName, &crash_db, nullptr);
+ kChannelName, crash_db.get(), nullptr);
StabilityReport report;
ASSERT_EQ(ANALYZER_CREATION_FAILED,
collector.CollectOneReport(file_path, &report));
@@ -312,9 +256,10 @@ TEST(PostmortemReportCollectorTest, CollectRandomFile) {
// Validate collection: random content appears as though there is not
// stability data.
- MockCrashReportDatabase crash_db;
+ std::unique_ptr<CrashReportDatabase> crash_db(
+ CrashReportDatabase::Initialize(temp_dir.GetPath().AppendASCII("db")));
PostmortemReportCollector collector(kProductName, kVersionNumber,
- kChannelName, &crash_db, nullptr);
+ kChannelName, crash_db.get(), nullptr);
StabilityReport report;
ASSERT_NE(SUCCESS, collector.CollectOneReport(file_path, &report));
}
@@ -361,10 +306,11 @@ TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest,
EXPECT_CALL(analyzer,
IsSessionUnclean(base::Time::FromInternalValue(12345LL)))
.Times(1)
- .WillOnce(Return(SystemSessionAnalyzer::CLEAN));
- MockCrashReportDatabase crash_db;
+ .WillOnce(Return(metrics::SystemSessionAnalyzer::CLEAN));
+ std::unique_ptr<CrashReportDatabase> crash_db(
+ CrashReportDatabase::Initialize(temp_dir_.GetPath().AppendASCII("db")));
PostmortemReportCollector collector(kProductName, kVersionNumber,
- kChannelName, &crash_db, &analyzer);
+ kChannelName, crash_db.get(), &analyzer);
StabilityReport report;
ASSERT_EQ(SUCCESS, collector.CollectOneReport(debug_file_path(), &report));
diff --git a/chromium/components/browser_watcher/stability_debugging_win_unittest.cc b/chromium/components/browser_watcher/stability_debugging_win_unittest.cc
index d4bd107ba6c..831cad660a8 100644
--- a/chromium/components/browser_watcher/stability_debugging_win_unittest.cc
+++ b/chromium/components/browser_watcher/stability_debugging_win_unittest.cc
@@ -14,6 +14,7 @@
#include "base/process/process.h"
#include "base/test/multiprocess_test.h"
#include "base/test/test_timeouts.h"
+#include "build/build_config.h"
#include "components/browser_watcher/stability_report.pb.h"
#include "components/browser_watcher/stability_report_extractor.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -55,7 +56,13 @@ class StabilityDebuggingTest : public testing::Test {
base::FilePath debug_path_;
};
-TEST_F(StabilityDebuggingTest, CrashingTest) {
+#if defined(ADDRESS_SANITIZER) && defined(OS_WIN)
+// The test does not pass under WinASan. See crbug.com/809524.
+#define MAYBE_CrashingTest DISABLED_CrashingTest
+#else
+#define MAYBE_CrashingTest CrashingTest
+#endif
+TEST_F(StabilityDebuggingTest, MAYBE_CrashingTest) {
RegisterStabilityVEH();
// Raise an exception, then continue.
diff --git a/chromium/components/browser_watcher/watcher_metrics_provider_win.cc b/chromium/components/browser_watcher/watcher_metrics_provider_win.cc
index 2e842e33f3f..3850f07f89a 100644
--- a/chromium/components/browser_watcher/watcher_metrics_provider_win.cc
+++ b/chromium/components/browser_watcher/watcher_metrics_provider_win.cc
@@ -29,7 +29,7 @@
#include "components/browser_watcher/features.h"
#include "components/browser_watcher/postmortem_report_collector.h"
#include "components/browser_watcher/stability_paths.h"
-#include "components/browser_watcher/system_session_analyzer_win.h"
+#include "components/metrics/system_session_analyzer_win.h"
#include "third_party/crashpad/crashpad/client/crash_report_database.h"
namespace browser_watcher {
@@ -285,7 +285,7 @@ void WatcherMetricsProviderWin::CollectPostmortemReportsImpl() {
LogCollectionInitStatus(INIT_SUCCESS);
const size_t kSystemSessionsToInspect = 5U;
- SystemSessionAnalyzer analyzer(kSystemSessionsToInspect);
+ metrics::SystemSessionAnalyzer analyzer(kSystemSessionsToInspect);
if (should_collect) {
base::string16 product_name, version_number, channel_name;
diff --git a/chromium/components/browser_watcher/window_hang_monitor_win_unittest.cc b/chromium/components/browser_watcher/window_hang_monitor_win_unittest.cc
index e5a31bf2fe2..9bdedec3462 100644
--- a/chromium/components/browser_watcher/window_hang_monitor_win_unittest.cc
+++ b/chromium/components/browser_watcher/window_hang_monitor_win_unittest.cc
@@ -5,6 +5,7 @@
#include "components/browser_watcher/window_hang_monitor_win.h"
#include <memory>
+#include <utility>
#include "base/base_paths.h"
#include "base/base_switches.h"
@@ -266,9 +267,9 @@ class HangMonitorThread {
base::WaitableEvent::InitialState::NOT_SIGNALED);
if (!thread_.task_runner()->PostTask(
FROM_HERE,
- base::Bind(&HangMonitorThread::StartupOnThread,
- base::Unretained(this), base::Passed(std::move(process)),
- base::Unretained(&complete)))) {
+ base::BindOnce(&HangMonitorThread::StartupOnThread,
+ base::Unretained(this), std::move(process),
+ base::Unretained(&complete)))) {
return false;
}
diff --git a/chromium/components/browsing_data/core/BUILD.gn b/chromium/components/browsing_data/core/BUILD.gn
index c54f351d1bc..4e1a1b8e25b 100644
--- a/chromium/components/browsing_data/core/BUILD.gn
+++ b/chromium/components/browsing_data/core/BUILD.gn
@@ -23,6 +23,8 @@ static_library("core") {
"counters/passwords_counter.h",
"counters/sync_tracker.cc",
"counters/sync_tracker.h",
+ "features.cc",
+ "features.h",
"history_notice_utils.cc",
"history_notice_utils.h",
"pref_names.cc",
diff --git a/chromium/components/browsing_data/core/browsing_data_utils.cc b/chromium/components/browsing_data/core/browsing_data_utils.cc
index d404e993222..63c6beacebf 100644
--- a/chromium/components/browsing_data/core/browsing_data_utils.cc
+++ b/chromium/components/browsing_data/core/browsing_data_utils.cc
@@ -325,18 +325,4 @@ BrowsingDataType GetDataTypeFromDeletionPreference(
return iter->second;
}
-void MigratePreferencesToBasic(PrefService* prefs) {
- if (!prefs->GetBoolean(prefs::kPreferencesMigratedToBasic)) {
- prefs->SetBoolean(prefs::kDeleteBrowsingHistoryBasic,
- prefs->GetBoolean(prefs::kDeleteBrowsingHistory));
- prefs->SetBoolean(prefs::kDeleteCacheBasic,
- prefs->GetBoolean(prefs::kDeleteCache));
- prefs->SetBoolean(prefs::kDeleteCookiesBasic,
- prefs->GetBoolean(prefs::kDeleteCookies));
- prefs->SetInteger(prefs::kDeleteTimePeriodBasic,
- prefs->GetInteger(prefs::kDeleteTimePeriod));
- prefs->SetBoolean(prefs::kPreferencesMigratedToBasic, true);
- }
-}
-
} // namespace browsing_data
diff --git a/chromium/components/browsing_data/core/browsing_data_utils.h b/chromium/components/browsing_data/core/browsing_data_utils.h
index 6c5d00ec96e..4400d0b58dc 100644
--- a/chromium/components/browsing_data/core/browsing_data_utils.h
+++ b/chromium/components/browsing_data/core/browsing_data_utils.h
@@ -79,11 +79,6 @@ bool GetDeletionPreferenceFromDataType(
BrowsingDataType GetDataTypeFromDeletionPreference(
const std::string& pref_name);
-// Copies the deletion preferences for timeperiod, cache, history and cookies
-// to a separate preferences that are used to on the basic CBD tab.
-// This only happens the first time this method is called.
-void MigratePreferencesToBasic(PrefService* prefs);
-
} // namespace browsing_data
#endif // COMPONENTS_BROWSING_DATA_CORE_BROWSING_DATA_UTILS_H_
diff --git a/chromium/components/browsing_data/core/browsing_data_utils_unittest.cc b/chromium/components/browsing_data/core/browsing_data_utils_unittest.cc
index 12a870ed8df..30e049baf4f 100644
--- a/chromium/components/browsing_data/core/browsing_data_utils_unittest.cc
+++ b/chromium/components/browsing_data/core/browsing_data_utils_unittest.cc
@@ -123,32 +123,3 @@ TEST_F(BrowsingDataUtilsTest, PasswordsCounterResult) {
}
store->ShutdownOnUIThread();
}
-
-TEST_F(BrowsingDataUtilsTest, MigratePreferencesToBasic) {
- using namespace browsing_data::prefs;
-
- prefs()->SetBoolean(kDeleteBrowsingHistory, true);
- prefs()->SetBoolean(kDeleteCookies, false);
- prefs()->SetBoolean(kDeleteCache, false);
- prefs()->SetInteger(kDeleteTimePeriod, 42);
-
- // History, cookies and cache should be migrated to their basic counterpart.
- browsing_data::MigratePreferencesToBasic(prefs());
- EXPECT_TRUE(prefs()->GetBoolean(kDeleteBrowsingHistoryBasic));
- EXPECT_FALSE(prefs()->GetBoolean(kDeleteCookiesBasic));
- EXPECT_FALSE(prefs()->GetBoolean(kDeleteCacheBasic));
- EXPECT_EQ(42, prefs()->GetInteger(kDeleteTimePeriodBasic));
-
- prefs()->SetBoolean(kDeleteBrowsingHistory, true);
- prefs()->SetBoolean(kDeleteCookies, true);
- prefs()->SetBoolean(kDeleteCache, true);
- prefs()->SetInteger(kDeleteTimePeriod, 100);
-
- // After the first migration all settings should stay the same if the
- // migration is executed again.
- browsing_data::MigratePreferencesToBasic(prefs());
- EXPECT_TRUE(prefs()->GetBoolean(kDeleteBrowsingHistoryBasic));
- EXPECT_FALSE(prefs()->GetBoolean(kDeleteCookiesBasic));
- EXPECT_FALSE(prefs()->GetBoolean(kDeleteCacheBasic));
- EXPECT_EQ(42, prefs()->GetInteger(kDeleteTimePeriodBasic));
-}
diff --git a/chromium/components/browsing_data/core/counters/autofill_counter.cc b/chromium/components/browsing_data/core/counters/autofill_counter.cc
index 8e62d7c9233..065c7ae294f 100644
--- a/chromium/components/browsing_data/core/counters/autofill_counter.cc
+++ b/chromium/components/browsing_data/core/counters/autofill_counter.cc
@@ -5,10 +5,10 @@
#include "components/browsing_data/core/counters/autofill_counter.h"
#include <algorithm>
+#include <memory>
#include <utility>
#include <vector>
-#include "base/memory/ptr_util.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
@@ -179,7 +179,7 @@ void AutofillCounter::OnWebDataServiceRequestDone(
if (suggestions_query_ || credit_cards_query_ || addresses_query_)
return;
- auto reported_result = base::MakeUnique<AutofillResult>(
+ auto reported_result = std::make_unique<AutofillResult>(
this, num_suggestions_, num_credit_cards_, num_addresses_,
sync_tracker_.IsSyncActive());
ReportResult(std::move(reported_result));
diff --git a/chromium/components/browsing_data/core/counters/browsing_data_counter.cc b/chromium/components/browsing_data/core/counters/browsing_data_counter.cc
index 7e4edb3dd7c..86405559767 100644
--- a/chromium/components/browsing_data/core/counters/browsing_data_counter.cc
+++ b/chromium/components/browsing_data/core/counters/browsing_data_counter.cc
@@ -4,9 +4,10 @@
#include "components/browsing_data/core/counters/browsing_data_counter.h"
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
+#include "base/trace_event/trace_event.h"
#include "components/browsing_data/core/browsing_data_utils.h"
#include "components/browsing_data/core/pref_names.h"
#include "components/prefs/pref_service.h"
@@ -66,6 +67,8 @@ base::Time BrowsingDataCounter::GetPeriodEnd() {
void BrowsingDataCounter::Restart() {
DCHECK(initialized_);
+ TRACE_EVENT_ASYNC_BEGIN1("browsing_data", "BrowsingDataCounter::Restart",
+ this, "data_type", GetPrefName());
if (state_ == State::IDLE) {
DCHECK(!timer_.IsRunning());
DCHECK(!staged_result_);
@@ -85,17 +88,20 @@ void BrowsingDataCounter::Restart() {
} else {
state_ = State::READY_TO_REPORT_RESULT;
}
+ TRACE_EVENT1("browsing_data", "BrowsingDataCounter::Count", "data_type",
+ GetPrefName());
Count();
}
void BrowsingDataCounter::ReportResult(ResultInt value) {
- ReportResult(base::MakeUnique<FinishedResult>(this, value));
+ ReportResult(std::make_unique<FinishedResult>(this, value));
}
void BrowsingDataCounter::ReportResult(std::unique_ptr<Result> result) {
DCHECK(initialized_);
DCHECK(result->Finished());
-
+ TRACE_EVENT_ASYNC_END1("browsing_data", "BrowsingDataCounter::Restart", this,
+ "data_type", GetPrefName());
switch (state_) {
case State::RESTARTED:
case State::READY_TO_REPORT_RESULT:
@@ -138,7 +144,7 @@ void BrowsingDataCounter::TransitionToShowCalculating() {
state_ = State::SHOW_CALCULATING;
state_transitions_.push_back(state_);
- callback_.Run(base::MakeUnique<Result>(this));
+ callback_.Run(std::make_unique<Result>(this));
timer_.Start(
FROM_HERE,
base::TimeDelta::FromMilliseconds(kDelayUntilReadyToShowResultMs),
diff --git a/chromium/components/browsing_data/core/counters/history_counter.cc b/chromium/components/browsing_data/core/counters/history_counter.cc
index cf1f746fc18..dfa5433862f 100644
--- a/chromium/components/browsing_data/core/counters/history_counter.cc
+++ b/chromium/components/browsing_data/core/counters/history_counter.cc
@@ -6,8 +6,8 @@
#include <limits.h>
#include <stdint.h>
+#include <memory>
-#include "base/memory/ptr_util.h"
#include "base/timer/timer.h"
#include "components/browsing_data/core/pref_names.h"
@@ -88,7 +88,7 @@ void HistoryCounter::Count() {
history::QueryOptions options;
options.max_count = 1;
options.begin_time = GetPeriodStart();
- options.end_time = base::Time::Max();
+ options.end_time = GetPeriodEnd();
net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
net::DefinePartialNetworkTrafficAnnotation("web_history_counter",
"web_history_service",
@@ -176,7 +176,7 @@ void HistoryCounter::MergeResults() {
if (!local_counting_finished_ || !web_counting_finished_)
return;
- ReportResult(base::MakeUnique<HistoryResult>(
+ ReportResult(std::make_unique<HistoryResult>(
this, local_result_, sync_tracker_.IsSyncActive(), has_synced_visits_));
}
diff --git a/chromium/components/browsing_data/core/counters/passwords_counter.cc b/chromium/components/browsing_data/core/counters/passwords_counter.cc
index e606a670006..717d54d0e10 100644
--- a/chromium/components/browsing_data/core/counters/passwords_counter.cc
+++ b/chromium/components/browsing_data/core/counters/passwords_counter.cc
@@ -4,6 +4,8 @@
#include "components/browsing_data/core/counters/passwords_counter.h"
+#include <memory>
+
#include "components/browsing_data/core/pref_names.h"
#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/browser/password_store.h"
@@ -55,12 +57,13 @@ void PasswordsCounter::Count() {
void PasswordsCounter::OnGetPasswordStoreResults(
std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
base::Time start = GetPeriodStart();
+ base::Time end = GetPeriodEnd();
int num_passwords = std::count_if(
results.begin(), results.end(),
- [start](const std::unique_ptr<autofill::PasswordForm>& form) {
- return form->date_created >= start;
+ [start, end](const std::unique_ptr<autofill::PasswordForm>& form) {
+ return (form->date_created >= start && form->date_created < end);
});
- ReportResult(base::MakeUnique<SyncResult>(this, num_passwords,
+ ReportResult(std::make_unique<SyncResult>(this, num_passwords,
sync_tracker_.IsSyncActive()));
}
diff --git a/chromium/components/browsing_data/core/features.cc b/chromium/components/browsing_data/core/features.cc
new file mode 100644
index 00000000000..01224261391
--- /dev/null
+++ b/chromium/components/browsing_data/core/features.cc
@@ -0,0 +1,14 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/browsing_data/core/features.h"
+
+namespace browsing_data {
+namespace features {
+
+const base::Feature kRemoveNavigationHistory{"RemoveNavigationHistory",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+} // namespace features
+} // namespace browsing_data
diff --git a/chromium/components/browsing_data/core/features.h b/chromium/components/browsing_data/core/features.h
new file mode 100644
index 00000000000..5ec27f32056
--- /dev/null
+++ b/chromium/components/browsing_data/core/features.h
@@ -0,0 +1,19 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_BROWSING_DATA_FEATURES_H_
+#define COMPONENTS_BROWSING_DATA_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace browsing_data {
+namespace features {
+
+// Enable propagation of history deletions to navigation history.
+extern const base::Feature kRemoveNavigationHistory;
+
+} // namespace features
+} // namespace browsing_data
+
+#endif // COMPONENTS_BROWSING_DATA_FEATURES_H_
diff --git a/chromium/components/captive_portal/BUILD.gn b/chromium/components/captive_portal/BUILD.gn
index 5966edde4ab..b64c9b0b3b4 100644
--- a/chromium/components/captive_portal/BUILD.gn
+++ b/chromium/components/captive_portal/BUILD.gn
@@ -19,6 +19,7 @@ component("captive_portal") {
"//base",
"//components/data_use_measurement/core",
"//net",
+ "//services/network/public/cpp",
"//url",
]
}
@@ -34,6 +35,7 @@ static_library("test_support") {
":captive_portal",
"//base",
"//net:test_support",
+ "//services/network:test_support",
"//url",
]
}
diff --git a/chromium/components/captive_portal/DEPS b/chromium/components/captive_portal/DEPS
index a07acff5466..f7e461751d7 100644
--- a/chromium/components/captive_portal/DEPS
+++ b/chromium/components/captive_portal/DEPS
@@ -1,5 +1,8 @@
include_rules = [
"+components/data_use_measurement/core",
+ "+services/network/public/cpp",
+ "+services/network/public/mojom",
+ "+services/network/test",
"+net",
"+url",
]
diff --git a/chromium/components/captive_portal/captive_portal_detector.cc b/chromium/components/captive_portal/captive_portal_detector.cc
index 0328dce8636..b9397c09453 100644
--- a/chromium/components/captive_portal/captive_portal_detector.cc
+++ b/chromium/components/captive_portal/captive_portal_detector.cc
@@ -18,9 +18,8 @@ const char CaptivePortalDetector::kDefaultURL[] =
"http://www.gstatic.com/generate_204";
CaptivePortalDetector::CaptivePortalDetector(
- const scoped_refptr<net::URLRequestContextGetter>& request_context)
- : request_context_(request_context) {
-}
+ network::mojom::URLLoaderFactory* loader_factory)
+ : loader_factory_(loader_factory) {}
CaptivePortalDetector::~CaptivePortalDetector() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -36,56 +35,72 @@ void CaptivePortalDetector::DetectCaptivePortal(
detection_callback_ = detection_callback;
- // The first 0 means this can use a TestURLFetcherFactory in unit tests.
- url_fetcher_ = net::URLFetcher::Create(0, url, net::URLFetcher::GET, this,
- traffic_annotation);
- url_fetcher_->SetAutomaticallyRetryOn5xx(false);
- url_fetcher_->SetRequestContext(request_context_.get());
- data_use_measurement::DataUseUserData::AttachToFetcher(
- url_fetcher_.get(),
- data_use_measurement::DataUseUserData::CAPTIVE_PORTAL);
+ auto resource_request = std::make_unique<network::ResourceRequest>();
+ resource_request->url = url;
// Can't safely use net::LOAD_DISABLE_CERT_REVOCATION_CHECKING here,
// since then the connection may be reused without checking the cert.
- url_fetcher_->SetLoadFlags(
- net::LOAD_BYPASS_CACHE |
- net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DO_NOT_SEND_AUTH_DATA);
- url_fetcher_->Start();
+ resource_request->load_flags =
+ net::LOAD_BYPASS_CACHE | net::LOAD_DO_NOT_SAVE_COOKIES |
+ net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SEND_AUTH_DATA;
+
+ // TODO(jam): switch to using ServiceURLLoader to track data measurement once
+ // https://crbug.com/808498 is fixed.
+ simple_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
+ traffic_annotation);
+ simple_loader_->SetAllowHttpErrorResults(true);
+ network::SimpleURLLoader::BodyAsStringCallback callback = base::BindOnce(
+ &CaptivePortalDetector::OnSimpleLoaderComplete, base::Unretained(this));
+ simple_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+ loader_factory_, std::move(callback));
}
void CaptivePortalDetector::Cancel() {
- url_fetcher_.reset();
+ simple_loader_.reset();
detection_callback_.Reset();
}
-void CaptivePortalDetector::OnURLFetchComplete(const net::URLFetcher* source) {
+void CaptivePortalDetector::OnSimpleLoaderComplete(
+ std::unique_ptr<std::string> response_body) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(FetchingURL());
- DCHECK_EQ(url_fetcher_.get(), source);
DCHECK(!detection_callback_.is_null());
+ int response_code = 0;
+ net::HttpResponseHeaders* headers = nullptr;
+ if (simple_loader_->ResponseInfo() &&
+ simple_loader_->ResponseInfo()->headers) {
+ headers = simple_loader_->ResponseInfo()->headers.get();
+ response_code = simple_loader_->ResponseInfo()->headers->response_code();
+ }
+ OnSimpleLoaderCompleteInternal(simple_loader_->NetError(), response_code,
+ simple_loader_->GetFinalURL(), headers);
+}
+
+void CaptivePortalDetector::OnSimpleLoaderCompleteInternal(
+ int net_error,
+ int response_code,
+ const GURL& url,
+ net::HttpResponseHeaders* headers) {
Results results;
- GetCaptivePortalResultFromResponse(url_fetcher_.get(), &results);
+ GetCaptivePortalResultFromResponse(net_error, response_code, url, headers,
+ &results);
DetectionCallback callback = detection_callback_;
- url_fetcher_.reset();
+ simple_loader_.reset();
detection_callback_.Reset();
callback.Run(results);
}
-// Takes a net::URLFetcher that has finished trying to retrieve the test
-// URL, and returns a CaptivePortalService::Result based on its result.
void CaptivePortalDetector::GetCaptivePortalResultFromResponse(
- const net::URLFetcher* url_fetcher,
+ int net_error,
+ int response_code,
+ const GURL& url,
+ net::HttpResponseHeaders* headers,
Results* results) const {
- DCHECK(results);
- DCHECK(!url_fetcher->GetStatus().is_io_pending());
-
results->result = captive_portal::RESULT_NO_RESPONSE;
- results->response_code = url_fetcher->GetResponseCode();
+ results->response_code = response_code;
results->retry_after_delta = base::TimeDelta();
- results->landing_url = url_fetcher->GetURL();
+ results->landing_url = url;
VLOG(1) << "Getting captive portal result"
<< " response code: " << results->response_code
@@ -95,12 +110,11 @@ void CaptivePortalDetector::GetCaptivePortalResultFromResponse(
// there may be a networking problem, rather than a captive portal.
// TODO(mmenke): Consider special handling for redirects that end up at
// errors, especially SSL certificate errors.
- if (url_fetcher->GetStatus().status() != net::URLRequestStatus::SUCCESS)
+ if (net_error != net::OK)
return;
// In the case of 503 errors, look for the Retry-After header.
if (results->response_code == 503) {
- net::HttpResponseHeaders* headers = url_fetcher->GetResponseHeaders();
std::string retry_after_string;
// If there's no Retry-After header, nothing else to do.
@@ -108,9 +122,8 @@ void CaptivePortalDetector::GetCaptivePortalResultFromResponse(
return;
base::TimeDelta retry_after_delta;
- if (net::HttpUtil::ParseRetryAfterHeader(retry_after_string,
- GetCurrentTime(),
- &retry_after_delta)) {
+ if (net::HttpUtil::ParseRetryAfterHeader(
+ retry_after_string, GetCurrentTime(), &retry_after_delta)) {
results->retry_after_delta = retry_after_delta;
}
@@ -146,7 +159,7 @@ base::Time CaptivePortalDetector::GetCurrentTime() const {
}
bool CaptivePortalDetector::FetchingURL() const {
- return url_fetcher_.get() != nullptr;
+ return simple_loader_.get() != nullptr;
}
} // namespace captive_portal
diff --git a/chromium/components/captive_portal/captive_portal_detector.h b/chromium/components/captive_portal/captive_portal_detector.h
index b5a26331cf2..e4d3fbd3894 100644
--- a/chromium/components/captive_portal/captive_portal_detector.h
+++ b/chromium/components/captive_portal/captive_portal_detector.h
@@ -16,25 +16,19 @@
#include "components/captive_portal/captive_portal_export.h"
#include "components/captive_portal/captive_portal_types.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_fetcher_delegate.h"
-#include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
class GURL;
namespace captive_portal {
-class CAPTIVE_PORTAL_EXPORT CaptivePortalDetector
- : public net::URLFetcherDelegate {
+class CAPTIVE_PORTAL_EXPORT CaptivePortalDetector {
public:
struct Results {
- Results()
- : result(captive_portal::RESULT_NO_RESPONSE),
- response_code(net::URLFetcher::RESPONSE_CODE_INVALID) {
- }
-
- captive_portal::CaptivePortalResult result;
- int response_code;
+ captive_portal::CaptivePortalResult result =
+ captive_portal::RESULT_NO_RESPONSE;
+ int response_code = 0;
base::TimeDelta retry_after_delta;
GURL landing_url;
};
@@ -49,8 +43,8 @@ class CAPTIVE_PORTAL_EXPORT CaptivePortalDetector
static const char kDefaultURL[];
explicit CaptivePortalDetector(
- const scoped_refptr<net::URLRequestContextGetter>& request_context);
- ~CaptivePortalDetector() override;
+ network::mojom::URLLoaderFactory* loader_factory);
+ ~CaptivePortalDetector();
// Triggers a check for a captive portal. After completion, runs the
// |callback|.
@@ -65,15 +59,21 @@ class CAPTIVE_PORTAL_EXPORT CaptivePortalDetector
private:
friend class CaptivePortalDetectorTestBase;
- // net::URLFetcherDelegate:
- void OnURLFetchComplete(const net::URLFetcher* source) override;
+ void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body);
+
+ void OnSimpleLoaderCompleteInternal(int net_error,
+ int response_code,
+ const GURL& url,
+ net::HttpResponseHeaders* headers);
- // Takes a net::URLFetcher that has finished trying to retrieve the
- // test URL, and fills a Results struct based on its result. If the
+ // Fills a Results struct based on the response from SimpleURLLoader. If the
// response is a 503 with a Retry-After header, |retry_after| field
// of |results| is populated accordingly. Otherwise, it's set to
// base::TimeDelta().
- void GetCaptivePortalResultFromResponse(const net::URLFetcher* url_fetcher,
+ void GetCaptivePortalResultFromResponse(int net_error,
+ int response_code,
+ const GURL& url,
+ net::HttpResponseHeaders* headers,
Results* results) const;
// Returns the current time. Used only when determining time until a
@@ -93,12 +93,10 @@ class CAPTIVE_PORTAL_EXPORT CaptivePortalDetector
time_for_testing_ += delta;
}
- // URL request context.
- scoped_refptr<net::URLRequestContextGetter> request_context_;
-
DetectionCallback detection_callback_;
- std::unique_ptr<net::URLFetcher> url_fetcher_;
+ network::mojom::URLLoaderFactory* loader_factory_ = nullptr;
+ std::unique_ptr<network::SimpleURLLoader> simple_loader_;
// Test time used by unit tests.
base::Time time_for_testing_;
diff --git a/chromium/components/captive_portal/captive_portal_detector_unittest.cc b/chromium/components/captive_portal/captive_portal_detector_unittest.cc
index a95729b7cf3..b14b093d021 100644
--- a/chromium/components/captive_portal/captive_portal_detector_unittest.cc
+++ b/chromium/components/captive_portal/captive_portal_detector_unittest.cc
@@ -16,7 +16,6 @@
#include "components/captive_portal/captive_portal_testing_utils.h"
#include "net/base/net_errors.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -58,11 +57,7 @@ class CaptivePortalDetectorTest : public testing::Test,
~CaptivePortalDetectorTest() override {}
void SetUp() override {
- scoped_refptr<net::URLRequestContextGetter> request_context_getter(
- new net::TestURLRequestContextGetter(
- base::ThreadTaskRunnerHandle::Get()));
-
- detector_.reset(new CaptivePortalDetector(request_context_getter.get()));
+ detector_.reset(new CaptivePortalDetector(test_loader_factory()));
set_detector(detector_.get());
}
@@ -139,9 +134,8 @@ TEST_F(CaptivePortalDetectorTest, CaptivePortalResultCodes) {
// Generic network error case.
results.result = captive_portal::RESULT_NO_RESPONSE;
- results.response_code = net::URLFetcher::RESPONSE_CODE_INVALID;
- RunTest(results, net::ERR_TIMED_OUT, net::URLFetcher::RESPONSE_CODE_INVALID,
- nullptr);
+ results.response_code = 0;
+ RunTest(results, net::ERR_TIMED_OUT, 0, nullptr);
// In the general captive portal case, the portal will return a page with a
// 200 status.
diff --git a/chromium/components/captive_portal/captive_portal_testing_utils.cc b/chromium/components/captive_portal/captive_portal_testing_utils.cc
index 0124e73b0bf..60b884549b7 100644
--- a/chromium/components/captive_portal/captive_portal_testing_utils.cc
+++ b/chromium/components/captive_portal/captive_portal_testing_utils.cc
@@ -45,20 +45,11 @@ void CaptivePortalDetectorTestBase::CompleteURLFetch(
int net_error,
int status_code,
const char* response_headers) {
- if (net_error != net::OK) {
- DCHECK(!response_headers);
- fetcher()->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
- net_error));
- } else {
- fetcher()->set_response_code(status_code);
- if (response_headers) {
- scoped_refptr<net::HttpResponseHeaders> headers(
- CreateResponseHeaders(response_headers));
- DCHECK_EQ(status_code, headers->response_code());
- fetcher()->set_response_headers(headers);
- }
- }
- detector()->OnURLFetchComplete(fetcher());
+ scoped_refptr<net::HttpResponseHeaders> headers;
+ if (response_headers)
+ headers = CreateResponseHeaders(response_headers);
+ detector()->OnSimpleLoaderCompleteInternal(net_error, status_code, GURL(),
+ headers.get());
}
} // namespace captive_portal
diff --git a/chromium/components/captive_portal/captive_portal_testing_utils.h b/chromium/components/captive_portal/captive_portal_testing_utils.h
index 042de8a8fba..559e36d2e3f 100644
--- a/chromium/components/captive_portal/captive_portal_testing_utils.h
+++ b/chromium/components/captive_portal/captive_portal_testing_utils.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "components/captive_portal/captive_portal_detector.h"
-#include "net/url_request/test_url_fetcher_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
namespace base {
class Time;
@@ -37,14 +37,15 @@ class CaptivePortalDetectorTestBase {
void set_detector(CaptivePortalDetector* detector) { detector_ = detector; }
- CaptivePortalDetector* detector() { return detector_; }
+ network::TestURLLoaderFactory* test_loader_factory() {
+ return &test_loader_factory_;
+ }
- net::TestURLFetcher* fetcher() { return factory_.GetFetcherByID(0); }
+ CaptivePortalDetector* detector() { return detector_; }
protected:
CaptivePortalDetector* detector_;
-
- net::TestURLFetcherFactory factory_;
+ network::TestURLLoaderFactory test_loader_factory_;
DISALLOW_COPY_AND_ASSIGN(CaptivePortalDetectorTestBase);
};
diff --git a/chromium/components/cast_certificate/cast_cert_validator.cc b/chromium/components/cast_certificate/cast_cert_validator.cc
index 8557634c673..f70455e861f 100644
--- a/chromium/components/cast_certificate/cast_cert_validator.cc
+++ b/chromium/components/cast_certificate/cast_cert_validator.cc
@@ -11,7 +11,6 @@
#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "base/memory/singleton.h"
#include "base/stl_util.h"
#include "components/cast_certificate/cast_crl.h"
@@ -332,7 +331,7 @@ std::unique_ptr<CertVerificationContext> CertVerificationContextImplForTest(
const base::StringPiece& spki) {
// Use a bogus CommonName, since this is just exposed for testing signature
// verification by unittests.
- return base::MakeUnique<CertVerificationContextImpl>(net::der::Input(spki),
+ return std::make_unique<CertVerificationContextImpl>(net::der::Input(spki),
"CommonName");
}
diff --git a/chromium/components/cast_certificate/cast_cert_validator_unittest.cc b/chromium/components/cast_certificate/cast_cert_validator_unittest.cc
index 9fe86979475..53dfd0ad791 100644
--- a/chromium/components/cast_certificate/cast_cert_validator_unittest.cc
+++ b/chromium/components/cast_certificate/cast_cert_validator_unittest.cc
@@ -256,9 +256,9 @@ TEST(VerifyCastDeviceCertTest, Unchained) {
// trust anchors after all) it fails the test as it is not a *device
// certificate*.
TEST(VerifyCastDeviceCertTest, CastRootCa) {
- RunTest(CastCertError::ERR_CERTS_VERIFY_GENERIC, "",
- CastDeviceCertPolicy::NONE, "certificates/cast_root_ca.pem",
- AprilFirst2016(), TRUST_STORE_BUILTIN, "");
+ RunTest(CastCertError::ERR_CERTS_RESTRICTIONS, "", CastDeviceCertPolicy::NONE,
+ "certificates/cast_root_ca.pem", AprilFirst2016(),
+ TRUST_STORE_BUILTIN, "");
}
// Tests verifying a valid certificate chain of length 2:
diff --git a/chromium/components/cast_certificate/cast_crl.cc b/chromium/components/cast_certificate/cast_crl.cc
index 93d8af6e5c2..67f7ccb503e 100644
--- a/chromium/components/cast_certificate/cast_crl.cc
+++ b/chromium/components/cast_certificate/cast_crl.cc
@@ -7,6 +7,8 @@
#include <unordered_map>
#include <unordered_set>
+#include <memory>
+
#include "base/base64.h"
#include "base/memory/ptr_util.h"
#include "base/memory/singleton.h"
@@ -337,7 +339,7 @@ std::unique_ptr<CastCRL> ParseAndVerifyCRLUsingCustomTrustStore(
LOG(ERROR) << "CRL - Verification failed.";
return nullptr;
}
- return base::MakeUnique<CastCRLImpl>(tbs_crl, overall_not_after);
+ return std::make_unique<CastCRLImpl>(tbs_crl, overall_not_after);
}
LOG(ERROR) << "No supported version of revocation data.";
return nullptr;
diff --git a/chromium/components/cast_channel/BUILD.gn b/chromium/components/cast_channel/BUILD.gn
index 2ca9b39b344..64a0bdcbcfc 100644
--- a/chromium/components/cast_channel/BUILD.gn
+++ b/chromium/components/cast_channel/BUILD.gn
@@ -12,6 +12,8 @@ static_library("cast_channel") {
"cast_channel_util.h",
"cast_framer.cc",
"cast_framer.h",
+ "cast_message_handler.cc",
+ "cast_message_handler.h",
"cast_message_util.cc",
"cast_message_util.h",
"cast_socket.cc",
@@ -31,7 +33,9 @@ static_library("cast_channel") {
"//components/cast_channel/proto:cast_channel_proto",
"//components/keyed_service/content",
"//components/keyed_service/core",
+ "//components/version_info",
"//content/public/browser",
+ "//content/public/common",
"//crypto",
"//net",
]
@@ -59,6 +63,7 @@ source_set("unit_tests") {
sources = [
"cast_auth_util_unittest.cc",
"cast_framer_unittest.cc",
+ "cast_message_handler_unittest.cc",
"cast_socket_service_unittest.cc",
"cast_socket_unittest.cc",
"cast_transport_unittest.cc",
diff --git a/chromium/components/cast_channel/cast_message_handler.cc b/chromium/components/cast_channel/cast_message_handler.cc
new file mode 100644
index 00000000000..86a154b51de
--- /dev/null
+++ b/chromium/components/cast_channel/cast_message_handler.cc
@@ -0,0 +1,234 @@
+// Copyright 2018 The Chromium Authors. All 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_channel/cast_message_handler.h"
+
+#include <tuple>
+
+#include "base/rand_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/default_tick_clock.h"
+#include "components/cast_channel/cast_socket_service.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+
+namespace cast_channel {
+
+namespace {
+
+constexpr net::NetworkTrafficAnnotationTag kMessageTrafficAnnotation =
+ net::DefineNetworkTrafficAnnotation("cast_message_handler", R"(
+ semantics {
+ sender: "Cast Message Handler"
+ description:
+ "A Cast protocol or application-level message sent to a Cast "
+ "device."
+ trigger:
+ "Triggered by user gesture from using Cast functionality, or "
+ "a webpage using the Presentation API, or "
+ "Cast device discovery internal logic."
+ data:
+ "A serialized Cast protocol or application-level protobuf message. "
+ "A non-exhaustive list of Cast protocol messages:\n"
+ "- Virtual connection requests,\n"
+ "- App availability / media status / receiver status requests,\n"
+ "- Launch / stop Cast session requests,\n"
+ "- Media commands, such as play/pause.\n"
+ "Application-level messages may contain data specific to the Cast "
+ "application."
+ destination: OTHER
+ destination_other:
+ "Data will be sent to a Cast device in local network."
+ }
+ policy {
+ cookies_allowed: NO
+ setting:
+ "This request cannot be disabled, but it would not be sent if user "
+ "does not connect a Cast device to the local network."
+ policy_exception_justification: "Not implemented."
+ })");
+
+} // namespace
+
+GetAppAvailabilityRequest::GetAppAvailabilityRequest(
+ int channel_id,
+ const std::string& app_id,
+ GetAppAvailabilityCallback callback,
+ base::TickClock* clock)
+ : channel_id(channel_id),
+ app_id(app_id),
+ callback(std::move(callback)),
+ timeout_timer(clock) {}
+
+GetAppAvailabilityRequest::~GetAppAvailabilityRequest() = default;
+
+VirtualConnection::VirtualConnection(int channel_id,
+ const std::string& source_id,
+ const std::string& destination_id)
+ : channel_id(channel_id),
+ source_id(source_id),
+ destination_id(destination_id) {}
+VirtualConnection::~VirtualConnection() = default;
+
+bool VirtualConnection::operator<(const VirtualConnection& other) const {
+ return std::tie(channel_id, source_id, destination_id) <
+ std::tie(other.channel_id, other.source_id, other.destination_id);
+}
+
+CastMessageHandler::CastMessageHandler(CastSocketService* socket_service,
+ const std::string& user_agent,
+ const std::string& browser_version)
+ : sender_id_(base::StringPrintf("sender-%d", base::RandInt(0, 1000000))),
+ user_agent_(user_agent),
+ browser_version_(browser_version),
+ socket_service_(socket_service),
+ clock_(base::DefaultTickClock::GetInstance()),
+ weak_ptr_factory_(this) {
+ DETACH_FROM_SEQUENCE(sequence_checker_);
+ socket_service_->task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(&CastSocketService::AddObserver,
+ base::Unretained(socket_service_),
+ base::Unretained(this)));
+}
+
+CastMessageHandler::~CastMessageHandler() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ socket_service_->RemoveObserver(this);
+}
+
+void CastMessageHandler::RequestAppAvailability(
+ CastSocket* socket,
+ const std::string& app_id,
+ GetAppAvailabilityCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ int channel_id = socket->id();
+ auto pending_it = std::find_if(
+ pending_app_availability_requests_.begin(),
+ pending_app_availability_requests_.end(),
+ [&channel_id, &app_id](
+ const std::pair<int, std::unique_ptr<GetAppAvailabilityRequest>>&
+ entry) {
+ const auto& request = entry.second;
+ return request->channel_id == channel_id && app_id == request->app_id;
+ });
+ if (pending_it != pending_app_availability_requests_.end())
+ return;
+
+ int request_id = NextRequestId();
+
+ DVLOG(2) << __func__ << ", socket_id: " << socket->id()
+ << ", app_id: " << app_id << ", request_id: " << request_id;
+ CastMessage message =
+ CreateGetAppAvailabilityRequest(sender_id_, request_id, app_id);
+
+ auto request = std::make_unique<GetAppAvailabilityRequest>(
+ channel_id, app_id, std::move(callback), clock_);
+ request->timeout_timer.Start(
+ FROM_HERE, base::TimeDelta::FromSeconds(5),
+ base::Bind(&CastMessageHandler::AppAvailabilityTimedOut,
+ base::Unretained(this), request_id));
+ pending_app_availability_requests_.emplace(request_id, std::move(request));
+
+ SendCastMessage(socket, message);
+}
+
+void CastMessageHandler::AppAvailabilityTimedOut(int request_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DVLOG(1) << __func__ << ", request_id: " << request_id;
+ auto it = pending_app_availability_requests_.find(request_id);
+ if (it == pending_app_availability_requests_.end())
+ return;
+
+ std::move(it->second->callback)
+ .Run(it->second->app_id, GetAppAvailabilityResult::kUnknown);
+ pending_app_availability_requests_.erase(it);
+}
+
+void CastMessageHandler::OnError(const CastSocket& socket,
+ ChannelError error_state) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ base::EraseIf(virtual_connections_,
+ [&socket](const VirtualConnection& connection) {
+ return connection.channel_id == socket.id();
+ });
+
+ auto it = pending_app_availability_requests_.begin();
+ while (it != pending_app_availability_requests_.end()) {
+ if (it->second->channel_id == socket.id()) {
+ std::move(it->second->callback)
+ .Run(it->second->app_id, GetAppAvailabilityResult::kUnknown);
+ it = pending_app_availability_requests_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+void CastMessageHandler::OnMessage(const CastSocket& socket,
+ const CastMessage& message) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(crbug.com/698940): Handle other messages.
+ DVLOG(2) << __func__ << ", socket_id: " << socket.id()
+ << ", message: " << CastMessageToString(message);
+ if (!IsReceiverMessage(message) || message.destination_id() != sender_id_)
+ return;
+
+ std::unique_ptr<base::DictionaryValue> payload =
+ GetDictionaryFromCastMessage(message);
+ if (!payload)
+ return;
+
+ int request_id = 0;
+ if (!GetRequestIdFromResponse(*payload, &request_id))
+ return;
+
+ auto it = pending_app_availability_requests_.find(request_id);
+ if (it != pending_app_availability_requests_.end()) {
+ GetAppAvailabilityResult result =
+ GetAppAvailabilityResultFromResponse(*payload, it->second->app_id);
+ std::move(it->second->callback).Run(it->second->app_id, result);
+ pending_app_availability_requests_.erase(it);
+ }
+}
+
+void CastMessageHandler::SendCastMessage(CastSocket* socket,
+ const CastMessage& message) {
+ // A virtual connection must be opened to the receiver before other messages
+ // can be sent.
+ VirtualConnection connection(socket->id(), message.source_id(),
+ message.destination_id());
+ if (virtual_connections_.find(connection) == virtual_connections_.end()) {
+ DVLOG(1) << "Creating VC for channel: " << connection.channel_id
+ << ", source: " << connection.source_id
+ << ", dest: " << connection.destination_id;
+ CastMessage virtual_connection_request = CreateVirtualConnectionRequest(
+ connection.source_id, connection.destination_id,
+ connection.destination_id == kPlatformReceiverId
+ ? VirtualConnectionType::kStrong
+ : VirtualConnectionType::kInvisible,
+ user_agent_, browser_version_);
+ socket->transport()->SendMessage(
+ virtual_connection_request,
+ base::Bind(&CastMessageHandler::OnMessageSent,
+ weak_ptr_factory_.GetWeakPtr()),
+ kMessageTrafficAnnotation);
+
+ // We assume the virtual connection request will succeed; otherwise this
+ // will eventually self-correct.
+ virtual_connections_.insert(connection);
+ }
+ socket->transport()->SendMessage(
+ message,
+ base::Bind(&CastMessageHandler::OnMessageSent,
+ weak_ptr_factory_.GetWeakPtr()),
+ kMessageTrafficAnnotation);
+}
+
+void CastMessageHandler::OnMessageSent(int result) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DVLOG_IF(2, result < 0) << "SendMessage failed with code: " << result;
+}
+
+} // namespace cast_channel
diff --git a/chromium/components/cast_channel/cast_message_handler.h b/chromium/components/cast_channel/cast_message_handler.h
new file mode 100644
index 00000000000..8c1cc334e48
--- /dev/null
+++ b/chromium/components/cast_channel/cast_message_handler.h
@@ -0,0 +1,150 @@
+// Copyright 2018 The Chromium Authors. All 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_CHANNEL_CAST_MESSAGE_HANDLER_H_
+#define COMPONENTS_CAST_CHANNEL_CAST_MESSAGE_HANDLER_H_
+
+#include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/time/tick_clock.h"
+#include "base/values.h"
+#include "components/cast_channel/cast_message_util.h"
+#include "components/cast_channel/cast_socket.h"
+
+namespace cast_channel {
+
+class CastSocketService;
+
+// |app_id|: ID of app the result is for.
+// |result|: Availability result from the receiver.
+using GetAppAvailabilityCallback =
+ base::OnceCallback<void(const std::string& app_id,
+ GetAppAvailabilityResult result)>;
+
+// Represents an app availability request to a Cast sink.
+struct GetAppAvailabilityRequest {
+ GetAppAvailabilityRequest(int channel_id,
+ const std::string& app_id,
+ GetAppAvailabilityCallback callback,
+ base::TickClock* clock);
+ ~GetAppAvailabilityRequest();
+
+ // ID of channel the request is sent over.
+ int channel_id;
+
+ // App ID of the request.
+ std::string app_id;
+
+ // Callback to invoke when availability has been determined.
+ GetAppAvailabilityCallback callback;
+
+ // Timer to fail the request on timeout.
+ base::OneShotTimer timeout_timer;
+};
+
+// Represents a virtual connection on a cast channel. A virtual connection is
+// given by a source and destination ID pair, and must be created before
+// messages can be sent. Virtual connections are managed by CastMessageHandler.
+struct VirtualConnection {
+ VirtualConnection(int channel_id,
+ const std::string& source_id,
+ const std::string& destination_id);
+ ~VirtualConnection();
+
+ bool operator<(const VirtualConnection& other) const;
+
+ // ID of cast channel.
+ int channel_id;
+
+ // Source ID (e.g. sender-0).
+ std::string source_id;
+
+ // Destination ID (e.g. receiver-0).
+ std::string destination_id;
+};
+
+// Handles messages that are sent between this browser instance and the Cast
+// devices connected to it. This class also manages virtual connections (VCs)
+// with each connected Cast device and ensures a proper VC exists before the
+// message is sent. This makes the concept of VC transparent to the client.
+// This class currently provides only supports requesting app availability from
+// a device, but will be expanded to support additional types of messages.
+// This class may be created on any sequence, but other methods (including
+// destructor) must be run on the same sequence that CastSocketService runs on.
+class CastMessageHandler : public CastSocket::Observer {
+ public:
+ explicit CastMessageHandler(CastSocketService* socket_service,
+ const std::string& user_agent,
+ const std::string& browser_version);
+ ~CastMessageHandler() override;
+
+ // Sends an app availability for |app_id| to the device given by |socket|.
+ // |callback| is always invoked asynchronously, and will be invoked when a
+ // response is received, or if the request timed out. No-ops if there is
+ // already a pending request with the same socket and app ID.
+ virtual void RequestAppAvailability(CastSocket* socket,
+ const std::string& app_id,
+ GetAppAvailabilityCallback callback);
+
+ const std::string& sender_id() const { return sender_id_; }
+
+ private:
+ friend class CastMessageHandlerTest;
+ FRIEND_TEST_ALL_PREFIXES(CastMessageHandlerTest, RequestAppAvailability);
+ FRIEND_TEST_ALL_PREFIXES(CastMessageHandlerTest,
+ RecreateVirtualConnectionAfterError);
+
+ // Used internally to generate the next ID to use in a request type message.
+ int NextRequestId() { return ++next_request_id_; }
+
+ // CastSocket::Observer implementation.
+ void OnError(const CastSocket& socket, ChannelError error_state) override;
+ void OnMessage(const CastSocket& socket, const CastMessage& message) override;
+
+ // Sends |message| over |socket|. This also ensures the necessary virtual
+ // connection exists before sending the message.
+ void SendCastMessage(CastSocket* socket, const CastMessage& message);
+
+ // Callback for CastTransport::SendMessage.
+ void OnMessageSent(int result);
+
+ // Invokes the pending callback associated with |request_id| with kUnknown.
+ void AppAvailabilityTimedOut(int request_id);
+
+ // App availability requests pending responses, keyed by request ID.
+ base::flat_map<int, std::unique_ptr<GetAppAvailabilityRequest>>
+ pending_app_availability_requests_;
+
+ // Source ID used for platform messages. The suffix is randomized to
+ // distinguish it from other Cast senders on the same network.
+ const std::string sender_id_;
+
+ // User agent and browser version strings included in virtual connection
+ // messages.
+ const std::string user_agent_;
+ const std::string browser_version_;
+
+ int next_request_id_ = 0;
+
+ // Set of virtual connections opened to receivers.
+ base::flat_set<VirtualConnection> virtual_connections_;
+
+ CastSocketService* const socket_service_;
+
+ // Non-owned pointer to TickClock used for request timeouts.
+ base::TickClock* const clock_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+ base::WeakPtrFactory<CastMessageHandler> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CastMessageHandler);
+};
+
+} // namespace cast_channel
+
+#endif // COMPONENTS_CAST_CHANNEL_CAST_MESSAGE_HANDLER_H_
diff --git a/chromium/components/cast_channel/cast_message_handler_unittest.cc b/chromium/components/cast_channel/cast_message_handler_unittest.cc
new file mode 100644
index 00000000000..c528bf83e1e
--- /dev/null
+++ b/chromium/components/cast_channel/cast_message_handler_unittest.cc
@@ -0,0 +1,180 @@
+// Copyright 2018 The Chromium Authors. All 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_channel/cast_message_handler.h"
+
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/test/test_simple_task_runner.h"
+#include "components/cast_channel/cast_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::SaveArg;
+
+namespace cast_channel {
+
+namespace {
+
+constexpr char kTestUserAgentString[] =
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) "
+ "Chrome/66.0.3331.0 Safari/537.36";
+
+std::string GetMessageType(const CastMessage& message) {
+ std::unique_ptr<base::Value> dict = GetDictionaryFromCastMessage(message);
+ if (!dict)
+ return std::string();
+ const base::Value* message_type =
+ dict->FindKeyOfType("type", base::Value::Type::STRING);
+ if (!message_type)
+ return std::string();
+ return message_type->GetString();
+}
+
+} // namespace
+
+class CastMessageHandlerTest : public testing::Test {
+ public:
+ CastMessageHandlerTest()
+ : environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+ cast_socket_service_(new base::TestSimpleTaskRunner()),
+ handler_(&cast_socket_service_, kTestUserAgentString, "66.0.3331.0") {}
+ ~CastMessageHandlerTest() override {}
+
+ MOCK_METHOD2(OnAppAvailability,
+ void(const std::string& app_id,
+ GetAppAvailabilityResult result));
+
+ protected:
+ base::test::ScopedTaskEnvironment environment_;
+ MockCastSocketService cast_socket_service_;
+ CastMessageHandler handler_;
+ MockCastSocket cast_socket_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CastMessageHandlerTest);
+};
+
+TEST_F(CastMessageHandlerTest, VirtualConnectionCreatedOnlyOnce) {
+ CastMessage virtual_connection_request;
+ CastMessage app_availability_request1;
+ CastMessage app_availability_request2;
+ EXPECT_CALL(*cast_socket_.mock_transport(), SendMessage(_, _, _))
+ .WillOnce(SaveArg<0>(&virtual_connection_request))
+ .WillOnce(SaveArg<0>(&app_availability_request1))
+ .WillOnce(SaveArg<0>(&app_availability_request2));
+
+ handler_.RequestAppAvailability(
+ &cast_socket_, "AAAAAAAA",
+ base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
+ base::Unretained(this)));
+ handler_.RequestAppAvailability(
+ &cast_socket_, "BBBBBBBB",
+ base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
+ base::Unretained(this)));
+
+ EXPECT_EQ("CONNECT", GetMessageType(virtual_connection_request));
+ EXPECT_EQ("GET_APP_AVAILABILITY", GetMessageType(app_availability_request1));
+ EXPECT_EQ("GET_APP_AVAILABILITY", GetMessageType(app_availability_request2));
+}
+
+TEST_F(CastMessageHandlerTest, RecreateVirtualConnectionAfterError) {
+ CastMessage virtual_connection_request;
+ CastMessage app_availability_request;
+ EXPECT_CALL(*cast_socket_.mock_transport(), SendMessage(_, _, _))
+ .WillOnce(SaveArg<0>(&virtual_connection_request))
+ .WillOnce(SaveArg<0>(&app_availability_request));
+
+ handler_.RequestAppAvailability(
+ &cast_socket_, "AAAAAAAA",
+ base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
+ base::Unretained(this)));
+ EXPECT_EQ("CONNECT", GetMessageType(virtual_connection_request));
+ EXPECT_EQ("GET_APP_AVAILABILITY", GetMessageType(app_availability_request));
+
+ EXPECT_CALL(
+ *this, OnAppAvailability("AAAAAAAA", GetAppAvailabilityResult::kUnknown));
+ handler_.OnError(cast_socket_, ChannelError::TRANSPORT_ERROR);
+
+ EXPECT_CALL(*cast_socket_.mock_transport(), SendMessage(_, _, _))
+ .WillOnce(SaveArg<0>(&virtual_connection_request))
+ .WillOnce(SaveArg<0>(&app_availability_request));
+
+ handler_.RequestAppAvailability(
+ &cast_socket_, "BBBBBBBB",
+ base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
+ base::Unretained(this)));
+ EXPECT_EQ("CONNECT", GetMessageType(virtual_connection_request));
+ EXPECT_EQ("GET_APP_AVAILABILITY", GetMessageType(app_availability_request));
+}
+
+TEST_F(CastMessageHandlerTest, RequestAppAvailability) {
+ CastMessage virtual_connection_request;
+ CastMessage app_availability_request;
+ EXPECT_CALL(*cast_socket_.mock_transport(), SendMessage(_, _, _))
+ .WillOnce(SaveArg<0>(&virtual_connection_request))
+ .WillOnce(SaveArg<0>(&app_availability_request));
+
+ handler_.RequestAppAvailability(
+ &cast_socket_, "ABCDEFAB",
+ base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
+ base::Unretained(this)));
+
+ EXPECT_EQ("CONNECT", GetMessageType(virtual_connection_request));
+ EXPECT_EQ("GET_APP_AVAILABILITY", GetMessageType(app_availability_request));
+
+ std::unique_ptr<base::Value> dict =
+ GetDictionaryFromCastMessage(app_availability_request);
+ ASSERT_TRUE(dict);
+ const base::Value* request_id_value =
+ dict->FindKeyOfType("requestId", base::Value::Type::INTEGER);
+ ASSERT_TRUE(request_id_value);
+ int request_id = request_id_value->GetInt();
+ EXPECT_GT(request_id, 0);
+
+ CastMessage response;
+ response.set_namespace_("urn:x-cast:com.google.cast.receiver");
+ response.set_source_id("receiver-0");
+ response.set_destination_id(handler_.sender_id());
+ response.set_payload_type(
+ CastMessage::PayloadType::CastMessage_PayloadType_STRING);
+ response.set_payload_utf8(
+ base::StringPrintf("{\"requestId\": %d, \"availability\": {\"ABCDEFAB\": "
+ "\"APP_AVAILABLE\"}}",
+ request_id));
+
+ EXPECT_CALL(*this, OnAppAvailability("ABCDEFAB",
+ GetAppAvailabilityResult::kAvailable));
+ handler_.OnMessage(cast_socket_, response);
+}
+
+TEST_F(CastMessageHandlerTest, RequestAppAvailabilityTimesOut) {
+ EXPECT_CALL(*cast_socket_.mock_transport(), SendMessage(_, _, _)).Times(2);
+ handler_.RequestAppAvailability(
+ &cast_socket_, "ABCDEFAB",
+ base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
+ base::Unretained(this)));
+ EXPECT_CALL(
+ *this, OnAppAvailability("ABCDEFAB", GetAppAvailabilityResult::kUnknown));
+ environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+}
+
+TEST_F(CastMessageHandlerTest, AppAvailabilitySentOnlyOnceWhilePending) {
+ EXPECT_CALL(*cast_socket_.mock_transport(), SendMessage(_, _, _)).Times(2);
+ handler_.RequestAppAvailability(
+ &cast_socket_, "ABCDEFAB",
+ base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
+ base::Unretained(this)));
+
+ EXPECT_CALL(*cast_socket_.mock_transport(), SendMessage(_, _, _)).Times(0);
+ handler_.RequestAppAvailability(
+ &cast_socket_, "ABCDEFAB",
+ base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
+ base::Unretained(this)));
+}
+
+} // namespace cast_channel
diff --git a/chromium/components/cast_channel/cast_message_util.cc b/chromium/components/cast_channel/cast_message_util.cc
index acd9848dbc7..415556f50b1 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/json/json_writer.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
+#include "build/build_config.h"
#include "components/cast_channel/cast_auth_util.h"
#include "components/cast_channel/proto/cast_channel.pb.h"
@@ -26,10 +27,6 @@ constexpr char kConnectionNamespace[] =
"urn:x-cast:com.google.cast.tp.connection";
constexpr char kReceiverNamespace[] = "urn:x-cast:com.google.cast.receiver";
-// Sender and receiver IDs to use for platform messages.
-constexpr char kPlatformSenderId[] = "sender-0";
-constexpr char kPlatformReceiverId[] = "receiver-0";
-
// Text payload keys.
constexpr char kTypeNodeId[] = "type";
constexpr char kRequestIdNodeId[] = "requestId";
@@ -40,6 +37,14 @@ constexpr char kKeepAlivePongType[] = "PONG";
constexpr char kGetAppAvailabilityRequestType[] = "GET_APP_AVAILABILITY";
constexpr char kConnectionRequestType[] = "CONNECT";
+// The value used for "sdkType" in a virtual connect request. Historically, this
+// value is used in the Media Router extension, but here it is reused in Chrome.
+constexpr int kVirtualConnectSdkType = 2;
+
+// The value used for "connectionType" in a virtual connect request. This value
+// stands for CONNECTION_TYPE_LOCAL, which is the only type used in Chrome.
+constexpr int kVirtualConnectTypeLocal = 1;
+
void FillCommonCastMessageFields(CastMessage* message,
const std::string& source_id,
const std::string& destination_id,
@@ -63,6 +68,23 @@ CastMessage CreateKeepAliveMessage(const char* keep_alive_type) {
return output;
}
+// Returns the value to be set as the "platform" value in a virtual connect
+// request. The value is platform-dependent and is taken from the Platform enum
+// defined in third_party/metrics_proto/cast_logs.proto.
+int GetVirtualConnectPlatformValue() {
+#if defined(OS_WIN)
+ return 3;
+#elif defined(OS_MACOSX)
+ return 4;
+#elif defined(OS_CHROMEOS)
+ return 5;
+#elif defined(OS_LINUX)
+ return 6;
+#else
+ return 0;
+#endif
+}
+
} // namespace
bool IsCastMessageValid(const CastMessage& message_proto) {
@@ -76,26 +98,23 @@ bool IsCastMessageValid(const CastMessage& message_proto) {
message_proto.has_payload_binary());
}
-std::unique_ptr<Value> GetDictionaryFromCastMessage(
+std::unique_ptr<base::DictionaryValue> GetDictionaryFromCastMessage(
const CastMessage& message) {
if (!message.has_payload_utf8())
return nullptr;
- std::unique_ptr<Value> parsed_payload(
+ return base::DictionaryValue::From(
base::JSONReader::Read(message.payload_utf8()));
- if (!parsed_payload || !parsed_payload->is_dict())
- return nullptr;
-
- return parsed_payload;
}
CastMessageType ParseMessageType(const CastMessage& message) {
- std::unique_ptr<Value> dictionary = GetDictionaryFromCastMessage(message);
+ std::unique_ptr<base::DictionaryValue> dictionary =
+ GetDictionaryFromCastMessage(message);
if (!dictionary)
return CastMessageType::kOther;
- const base::Value* type_string =
- dictionary->FindKeyOfType(kTypeNodeId, base::Value::Type::STRING);
+ const Value* type_string =
+ dictionary->FindKeyOfType(kTypeNodeId, Value::Type::STRING);
if (!type_string)
return CastMessageType::kOther;
@@ -193,17 +212,48 @@ CastMessage CreateKeepAlivePongMessage() {
return CreateKeepAliveMessage(kKeepAlivePongType);
}
-CastMessage CreateVirtualConnectionRequest(const std::string& source_id,
- const std::string& destination_id) {
+CastMessage CreateVirtualConnectionRequest(
+ const std::string& source_id,
+ const std::string& destination_id,
+ VirtualConnectionType connection_type,
+ const std::string& user_agent,
+ const std::string& browser_version) {
+ DCHECK(destination_id != kPlatformReceiverId || connection_type == kStrong);
+
CastMessage output;
FillCommonCastMessageFields(&output, source_id, destination_id,
kConnectionNamespace);
output.set_payload_type(
CastMessage::PayloadType::CastMessage_PayloadType_STRING);
+ // Parse system_version from user agent string. It contains platform, OS and
+ // CPU info and is contained in the first set of parentheses of the user
+ // agent string (e.g., X11; Linux x86_64).
+ std::string system_version;
+ size_t start_index = user_agent.find('(');
+ if (start_index != std::string::npos) {
+ size_t end_index = user_agent.find(')', start_index + 1);
+ if (end_index != std::string::npos) {
+ system_version =
+ user_agent.substr(start_index + 1, end_index - start_index - 1);
+ }
+ }
+
Value dict(Value::Type::DICTIONARY);
dict.SetKey(kTypeNodeId, Value(kConnectionRequestType));
- // TODO(crbug.com/698940): Populate other optional fields.
+ dict.SetKey("userAgent", Value(user_agent));
+ dict.SetKey("connType", Value(connection_type));
+
+ Value sender_info(Value::Type::DICTIONARY);
+ sender_info.SetKey("sdkType", Value(kVirtualConnectSdkType));
+ sender_info.SetKey("version", Value(browser_version));
+ sender_info.SetKey("browserVersion", Value(browser_version));
+ sender_info.SetKey("platform", Value(GetVirtualConnectPlatformValue()));
+ sender_info.SetKey("connectionType", Value(kVirtualConnectTypeLocal));
+ if (!system_version.empty())
+ sender_info.SetKey("systemVersion", Value(system_version));
+
+ dict.SetKey("senderInfo", std::move(sender_info));
CHECK(base::JSONWriter::Write(dict, output.mutable_payload_utf8()));
return output;
}
diff --git a/chromium/components/cast_channel/cast_message_util.h b/chromium/components/cast_channel/cast_message_util.h
index 343d2f9e640..c0882cc52ed 100644
--- a/chromium/components/cast_channel/cast_message_util.h
+++ b/chromium/components/cast_channel/cast_message_util.h
@@ -15,6 +15,10 @@ class AuthContext;
class CastMessage;
class DeviceAuthMessage;
+// Sender and receiver IDs to use for platform messages.
+constexpr char kPlatformSenderId[] = "sender-0";
+constexpr char kPlatformReceiverId[] = "receiver-0";
+
// Cast application protocol message types.
enum class CastMessageType { kOther, kPing, kPong };
@@ -23,7 +27,7 @@ bool IsCastMessageValid(const CastMessage& message_proto);
// Parses and returns the UTF-8 payload from |message|. Returns nullptr
// if the UTF-8 payload doesn't exist, or if it is not a dictionary.
-std::unique_ptr<base::Value> GetDictionaryFromCastMessage(
+std::unique_ptr<base::DictionaryValue> GetDictionaryFromCastMessage(
const CastMessage& message);
// Parses the JSON-encoded payload of |message| and returns the value in the
@@ -58,10 +62,23 @@ bool IsPlatformSenderMessage(const CastMessage& message);
CastMessage CreateKeepAlivePingMessage();
CastMessage CreateKeepAlivePongMessage();
+enum VirtualConnectionType {
+ kStrong = 0,
+ // kWeak = 1 not used.
+ kInvisible = 2
+};
+
// Creates a virtual connection request message for |source_id| and
-// |destination_id|.
-CastMessage CreateVirtualConnectionRequest(const std::string& source_id,
- const std::string& destination_id);
+// |destination_id|. |user_agent| and |browser_version| will be included with
+// the request.
+// If |destination_id| is kPlatformReceiverId, then |connection_type| must be
+// kStrong. Otherwise |connection_type| can be either kStrong or kInvisible.
+CastMessage CreateVirtualConnectionRequest(
+ const std::string& source_id,
+ const std::string& destination_id,
+ VirtualConnectionType connection_type,
+ const std::string& user_agent,
+ const std::string& browser_version);
// Creates an app availability request for |app_id| from |source_id| with
// ID |request_id|.
diff --git a/chromium/components/cast_channel/cast_socket.cc b/chromium/components/cast_channel/cast_socket.cc
index 93995871461..ccfc0049afe 100644
--- a/chromium/components/cast_channel/cast_socket.cc
+++ b/chromium/components/cast_channel/cast_socket.cc
@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <string.h>
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -47,6 +48,7 @@
#include "net/socket/tcp_client_socket.h"
#include "net/ssl/ssl_config_service.h"
#include "net/ssl/ssl_info.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
// Helper for logging data with remote host IP and authentication state.
// Assumes |ip_endpoint_| of type net::IPEndPoint and |channel_auth_| of enum
@@ -105,9 +107,10 @@ CastSocketImpl::CastSocketImpl(const CastSocketOpenParams& open_params,
ready_state_(ReadyState::NONE),
auth_delegate_(nullptr) {
DCHECK(open_params.ip_endpoint.address().IsValid());
- DCHECK(open_params_.net_log);
- net_log_source_.type = net::NetLogSourceType::SOCKET;
- net_log_source_.id = open_params_.net_log->NextID();
+ if (open_params_.net_log) {
+ net_log_source_.type = net::NetLogSourceType::SOCKET;
+ net_log_source_.id = open_params_.net_log->NextID();
+ }
}
CastSocketImpl::~CastSocketImpl() {
@@ -251,7 +254,7 @@ void CastSocketImpl::Connect() {
DCHECK_EQ(ReadyState::NONE, ready_state_);
DCHECK_EQ(ConnectionState::START_CONNECT, connect_state_);
- delegate_ = base::MakeUnique<CastSocketMessageDelegate>(this);
+ delegate_ = std::make_unique<CastSocketMessageDelegate>(this);
SetReadyState(ReadyState::CONNECTING);
SetConnectState(ConnectionState::TCP_CONNECT);
@@ -455,9 +458,33 @@ int CastSocketImpl::DoAuthChallengeSend() {
<< CastMessageToString(challenge_message);
ResetConnectLoopCallback();
- // TODO(https://crbug.com/656607): Add proper annotation.
+
+ net::NetworkTrafficAnnotationTag traffic_annotation =
+ net::DefineNetworkTrafficAnnotation("cast_socket", R"(
+ semantics {
+ sender: "Cast Socket"
+ description:
+ "An auth challenge request sent to a Cast device as a part of "
+ "establishing a connection to it."
+ trigger:
+ "A new Cast device has been discovered via mDNS in the local "
+ "network."
+ data:
+ "A serialized protobuf message containing the nonce challenge. No "
+ "user data."
+ destination: OTHER
+ destination_other:
+ "Data will be sent to a Cast device in local network."
+ }
+ policy {
+ cookies_allowed: NO
+ setting:
+ "This request cannot be disabled, but it would not be sent if user "
+ "does not connect a Cast device to the local network."
+ policy_exception_justification: "Not implemented."
+ })");
transport_->SendMessage(challenge_message, connect_loop_callback_.callback(),
- NO_TRAFFIC_ANNOTATION_BUG_656607);
+ traffic_annotation);
// Always return IO_PENDING since the result is always asynchronous.
return net::ERR_IO_PENDING;
diff --git a/chromium/components/cast_channel/cast_socket_service.h b/chromium/components/cast_channel/cast_socket_service.h
index 94bbf434485..64fd9d4f419 100644
--- a/chromium/components/cast_channel/cast_socket_service.h
+++ b/chromium/components/cast_channel/cast_socket_service.h
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
+#include "base/single_thread_task_runner.h"
#include "components/cast_channel/cast_socket.h"
namespace cast_channel {
diff --git a/chromium/components/cast_channel/cast_socket_service_unittest.cc b/chromium/components/cast_channel/cast_socket_service_unittest.cc
index d0a519bef1c..3aafc5eebb5 100644
--- a/chromium/components/cast_channel/cast_socket_service_unittest.cc
+++ b/chromium/components/cast_channel/cast_socket_service_unittest.cc
@@ -41,18 +41,18 @@ class CastSocketServiceTest : public testing::Test {
};
TEST_F(CastSocketServiceTest, TestAddSocket) {
- auto socket1 = base::MakeUnique<MockCastSocket>();
+ auto socket1 = std::make_unique<MockCastSocket>();
auto* socket_ptr1 = AddSocket(std::move(socket1));
EXPECT_NE(0, socket_ptr1->id());
- auto socket2 = base::MakeUnique<MockCastSocket>();
+ auto socket2 = std::make_unique<MockCastSocket>();
auto* socket_ptr2 = AddSocket(std::move(socket2));
EXPECT_NE(socket_ptr1->id(), socket_ptr2->id());
auto removed_socket = cast_socket_service_->RemoveSocket(socket_ptr2->id());
EXPECT_EQ(socket_ptr2, removed_socket.get());
- auto socket3 = base::MakeUnique<MockCastSocket>();
+ auto socket3 = std::make_unique<MockCastSocket>();
auto* socket_ptr3 = AddSocket(std::move(socket3));
EXPECT_NE(socket_ptr1->id(), socket_ptr3->id());
EXPECT_NE(socket_ptr2->id(), socket_ptr3->id());
@@ -65,7 +65,7 @@ TEST_F(CastSocketServiceTest, TestRemoveAndGetSocket) {
auto socket = cast_socket_service_->RemoveSocket(channel_id);
EXPECT_FALSE(socket);
- auto mock_socket = base::MakeUnique<MockCastSocket>();
+ auto mock_socket = std::make_unique<MockCastSocket>();
auto* mock_socket_ptr = AddSocket(std::move(mock_socket));
channel_id = mock_socket_ptr->id();
diff --git a/chromium/components/cast_channel/cast_socket_unittest.cc b/chromium/components/cast_channel/cast_socket_unittest.cc
index 37626eb1fdd..9951586d912 100644
--- a/chromium/components/cast_channel/cast_socket_unittest.cc
+++ b/chromium/components/cast_channel/cast_socket_unittest.cc
@@ -538,7 +538,7 @@ class SslCastSocketTest : public CastSocketTestBase {
net::TestCompletionCallback write_callback;
int write_result = write_callback.GetResult(server_socket_->Write(
draining_buffer.get(), draining_buffer->BytesRemaining(),
- write_callback.callback()));
+ write_callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_GT(write_result, 0);
draining_buffer->DidConsume(write_result);
}
diff --git a/chromium/components/cast_channel/cast_test_util.cc b/chromium/components/cast_channel/cast_test_util.cc
index cabff1b3d88..f90d13d3ce7 100644
--- a/chromium/components/cast_channel/cast_test_util.cc
+++ b/chromium/components/cast_channel/cast_test_util.cc
@@ -48,4 +48,10 @@ net::IPEndPoint CreateIPEndPointForTest() {
return net::IPEndPoint(net::IPAddress(192, 168, 1, 1), 8009);
}
+MockCastMessageHandler::MockCastMessageHandler(
+ MockCastSocketService* socket_service)
+ : CastMessageHandler(socket_service, "userAgent", "1.2.3.4") {}
+
+MockCastMessageHandler::~MockCastMessageHandler() = default;
+
} // namespace cast_channel
diff --git a/chromium/components/cast_channel/cast_test_util.h b/chromium/components/cast_channel/cast_test_util.h
index 4fff1ad89c1..87813250760 100644
--- a/chromium/components/cast_channel/cast_test_util.h
+++ b/chromium/components/cast_channel/cast_test_util.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "components/cast_channel/cast_message_handler.h"
#include "components/cast_channel/cast_socket.h"
#include "components/cast_channel/cast_socket_service.h"
#include "components/cast_channel/cast_transport.h"
@@ -143,6 +144,26 @@ class MockCastSocket : public CastSocket {
DISALLOW_COPY_AND_ASSIGN(MockCastSocket);
};
+class MockCastMessageHandler : public CastMessageHandler {
+ public:
+ explicit MockCastMessageHandler(MockCastSocketService* socket_service);
+ ~MockCastMessageHandler() override;
+
+ void RequestAppAvailability(CastSocket* socket,
+ const std::string& app_id,
+ GetAppAvailabilityCallback callback) override {
+ DoRequestAppAvailability(socket, app_id, callback);
+ }
+
+ MOCK_METHOD3(DoRequestAppAvailability,
+ void(CastSocket*,
+ const std::string&,
+ GetAppAvailabilityCallback&));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockCastMessageHandler);
+};
+
// Creates the IPEndpoint 192.168.1.1.
net::IPEndPoint CreateIPEndPointForTest();
diff --git a/chromium/components/cast_channel/keep_alive_delegate.cc b/chromium/components/cast_channel/keep_alive_delegate.cc
index cce03044d05..082ecc838d8 100644
--- a/chromium/components/cast_channel/keep_alive_delegate.cc
+++ b/chromium/components/cast_channel/keep_alive_delegate.cc
@@ -12,6 +12,7 @@
#include "components/cast_channel/logger.h"
#include "components/cast_channel/proto/cast_channel.pb.h"
#include "net/base/net_errors.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
namespace cast_channel {
@@ -85,12 +86,34 @@ void KeepAliveDelegate::SendKeepAliveMessage(const CastMessage& message,
CastMessageType message_type) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DVLOG(2) << "Sending " << CastMessageTypeToString(message_type);
- // TODO(https://crbug.com/656607): Add proper annotation.
+
+ net::NetworkTrafficAnnotationTag traffic_annotation =
+ net::DefineNetworkTrafficAnnotation("cast_keep_alive_delegate", R"(
+ semantics {
+ sender: "Cast Socket Keep Alive Delegate"
+ description:
+ "A ping/pong message sent periodically to a Cast device to keep "
+ "the connection alive."
+ trigger:
+ "Periodically while a connection to a Cast device is established."
+ data:
+ "A protobuf message representing a ping/pong message. No user data."
+ destination: OTHER
+ destination_other:
+ "Data will be sent to a Cast device in local network."
+ }
+ policy {
+ cookies_allowed: NO
+ setting:
+ "This request cannot be disabled, but it would not be sent if user "
+ "does not connect to a Cast device."
+ policy_exception_justification: "Not implemented."
+ })");
socket_->transport()->SendMessage(
message,
base::Bind(&KeepAliveDelegate::SendKeepAliveMessageComplete,
base::Unretained(this), message_type),
- NO_TRAFFIC_ANNOTATION_BUG_656607);
+ traffic_annotation);
}
void KeepAliveDelegate::SendKeepAliveMessageComplete(
diff --git a/chromium/components/cast_channel/keep_alive_delegate_unittest.cc b/chromium/components/cast_channel/keep_alive_delegate_unittest.cc
index 284560697fa..feb23dd726d 100644
--- a/chromium/components/cast_channel/keep_alive_delegate_unittest.cc
+++ b/chromium/components/cast_channel/keep_alive_delegate_unittest.cc
@@ -236,9 +236,9 @@ TEST_F(KeepAliveDelegateTest, TestLivenessTimerResetAfterSendingMessage) {
mock_time_task_runner->GetMockTickClock();
std::unique_ptr<base::Timer> liveness_timer =
- base::MakeUnique<base::Timer>(true, false, tick_clock.get());
+ std::make_unique<base::Timer>(true, false, tick_clock.get());
std::unique_ptr<base::Timer> ping_timer =
- base::MakeUnique<base::Timer>(true, false, tick_clock.get());
+ std::make_unique<base::Timer>(true, false, tick_clock.get());
ping_timer->SetTaskRunner(mock_time_task_runner);
liveness_timer->SetTaskRunner(mock_time_task_runner);
keep_alive_->SetTimersForTest(std::move(ping_timer),
diff --git a/chromium/components/cbor/cbor_binary.h b/chromium/components/cbor/cbor_binary.h
index f1790658a92..27f675b77a5 100644
--- a/chromium/components/cbor/cbor_binary.h
+++ b/chromium/components/cbor/cbor_binary.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <stdint.h>
-
#ifndef COMPONENTS_CBOR_CBOR_BINARY_H_
#define COMPONENTS_CBOR_CBOR_BINARY_H_
+#include <stdint.h>
+
namespace cbor {
namespace constants {
diff --git a/chromium/components/cbor/cbor_reader.cc b/chromium/components/cbor/cbor_reader.cc
index c21f4df3cb9..1c63f85520d 100644
--- a/chromium/components/cbor/cbor_reader.cc
+++ b/chromium/components/cbor/cbor_reader.cc
@@ -5,6 +5,7 @@
#include "components/cbor/cbor_reader.h"
#include <math.h>
+
#include <utility>
#include "base/numerics/checked_math.h"
@@ -35,7 +36,7 @@ const char kUnknownAdditionalInfo[] =
const char kIncompleteCBORData[] =
"Prematurely terminated CBOR data byte array.";
const char kIncorrectMapKeyType[] =
- "Map keys other than utf-8 encoded strings are not allowed.";
+ "Specified map key type is not supported by the current implementation.";
const char kTooMuchNesting[] = "Too much nesting.";
const char kInvalidUTF8[] = "String encoding other than utf8 are not allowed.";
const char kExtraneousData[] = "Trailing data bytes are not allowed.";
@@ -54,16 +55,21 @@ const char kOutOfRangeIntegerValue[] =
} // namespace
-CBORReader::CBORReader(Bytes::const_iterator it, Bytes::const_iterator end)
- : it_(it), end_(end), error_code_(DecoderError::CBOR_NO_ERROR) {}
+CBORReader::CBORReader(base::span<const uint8_t>::const_iterator begin,
+ const base::span<const uint8_t>::const_iterator end)
+ : begin_(begin),
+ it_(begin),
+ end_(end),
+ error_code_(DecoderError::CBOR_NO_ERROR) {}
CBORReader::~CBORReader() {}
// static
-base::Optional<CBORValue> CBORReader::Read(const Bytes& data,
+base::Optional<CBORValue> CBORReader::Read(base::span<uint8_t const> data,
DecoderError* error_code_out,
int max_nesting_level) {
- CBORReader reader(data.begin(), data.end());
- base::Optional<CBORValue> decoded_cbor = reader.DecodeCBOR(max_nesting_level);
+ CBORReader reader(data.cbegin(), data.cend());
+ base::Optional<CBORValue> decoded_cbor =
+ reader.DecodeCompleteDataItem(max_nesting_level);
if (decoded_cbor)
reader.CheckExtraneousData();
@@ -75,40 +81,73 @@ base::Optional<CBORValue> CBORReader::Read(const Bytes& data,
return decoded_cbor;
}
-base::Optional<CBORValue> CBORReader::DecodeCBOR(int max_nesting_level) {
- if (max_nesting_level < 0 || max_nesting_level > kCBORMaxDepth) {
- error_code_ = DecoderError::TOO_MUCH_NESTING;
+// static
+base::Optional<CBORValue> CBORReader::Read(base::span<uint8_t const> data,
+ size_t* num_bytes_consumed,
+ DecoderError* error_code_out,
+ int max_nesting_level) {
+ CBORReader reader(data.cbegin(), data.cend());
+ base::Optional<CBORValue> decoded_cbor =
+ reader.DecodeCompleteDataItem(max_nesting_level);
+
+ if (error_code_out)
+ *error_code_out = reader.GetErrorCode();
+
+ if (reader.GetErrorCode() != DecoderError::CBOR_NO_ERROR) {
+ *num_bytes_consumed = 0;
return base::nullopt;
}
- if (!CanConsume(1)) {
- error_code_ = DecoderError::INCOMPLETE_CBOR_DATA;
+ *num_bytes_consumed = reader.num_bytes_consumed();
+ return decoded_cbor;
+}
+
+// static
+base::Optional<CBORReader::DataItemHeader> CBORReader::ReadDataItemHeader(
+ base::span<const uint8_t> data,
+ size_t* num_bytes_consumed,
+ DecoderError* error_code_out) {
+ CBORReader reader(data.cbegin(), data.cend());
+ base::Optional<DataItemHeader> decoded_header = reader.DecodeDataItemHeader();
+
+ if (error_code_out)
+ *error_code_out = reader.GetErrorCode();
+
+ if (reader.GetErrorCode() != DecoderError::CBOR_NO_ERROR) {
+ *num_bytes_consumed = 0;
return base::nullopt;
}
- const uint8_t initial_byte = *it_++;
- const auto major_type = GetMajorType(initial_byte);
- const uint8_t additional_info = GetAdditionalInfo(initial_byte);
+ *num_bytes_consumed = reader.num_bytes_consumed();
+ return decoded_header;
+}
- uint64_t value;
- if (!ReadVariadicLengthInteger(additional_info, &value))
+base::Optional<CBORValue> CBORReader::DecodeCompleteDataItem(
+ int max_nesting_level) {
+ if (max_nesting_level < 0 || max_nesting_level > kCBORMaxDepth) {
+ error_code_ = DecoderError::TOO_MUCH_NESTING;
+ return base::nullopt;
+ }
+
+ base::Optional<DataItemHeader> header = DecodeDataItemHeader();
+ if (!header.has_value())
return base::nullopt;
- switch (major_type) {
+ switch (header->type) {
case CBORValue::Type::UNSIGNED:
- return DecodeValueToUnsigned(value);
+ return DecodeValueToUnsigned(header->value);
case CBORValue::Type::NEGATIVE:
- return DecodeValueToNegative(value);
+ return DecodeValueToNegative(header->value);
case CBORValue::Type::BYTE_STRING:
- return ReadBytes(value);
+ return ReadByteStringContent(*header);
case CBORValue::Type::STRING:
- return ReadString(value);
+ return ReadStringContent(*header);
case CBORValue::Type::ARRAY:
- return ReadCBORArray(value, max_nesting_level);
+ return ReadArrayContent(*header, max_nesting_level);
case CBORValue::Type::MAP:
- return ReadCBORMap(value, max_nesting_level);
+ return ReadMapContent(*header, max_nesting_level);
case CBORValue::Type::SIMPLE_VALUE:
- return ReadSimpleValue(additional_info, value);
+ return DecodeToSimpleValue(*header);
case CBORValue::Type::NONE:
break;
}
@@ -117,6 +156,23 @@ base::Optional<CBORValue> CBORReader::DecodeCBOR(int max_nesting_level) {
return base::nullopt;
}
+base::Optional<CBORReader::DataItemHeader> CBORReader::DecodeDataItemHeader() {
+ if (!CanConsume(1)) {
+ error_code_ = DecoderError::INCOMPLETE_CBOR_DATA;
+ return base::nullopt;
+ }
+
+ const uint8_t initial_byte = *it_++;
+ const auto major_type = GetMajorType(initial_byte);
+ const uint8_t additional_info = GetAdditionalInfo(initial_byte);
+
+ uint64_t value;
+ if (!ReadVariadicLengthInteger(additional_info, &value))
+ return base::nullopt;
+
+ return DataItemHeader{major_type, additional_info, value};
+}
+
bool CBORReader::ReadVariadicLengthInteger(uint8_t additional_info,
uint64_t* value) {
uint8_t additional_bytes = 0;
@@ -169,17 +225,17 @@ base::Optional<CBORValue> CBORReader::DecodeValueToUnsigned(uint64_t value) {
return CBORValue(unsigned_value.ValueOrDie());
}
-base::Optional<CBORValue> CBORReader::ReadSimpleValue(uint8_t additional_info,
- uint64_t value) {
+base::Optional<CBORValue> CBORReader::DecodeToSimpleValue(
+ const DataItemHeader& header) {
// Floating point numbers are not supported.
- if (additional_info > 24 && additional_info < 28) {
+ if (header.additional_info > 24 && header.additional_info < 28) {
error_code_ = DecoderError::UNSUPPORTED_FLOATING_POINT_VALUE;
return base::nullopt;
}
- CHECK_LE(value, 255u);
+ CHECK_LE(header.value, 255u);
CBORValue::SimpleValue possibly_unsupported_simple_value =
- static_cast<CBORValue::SimpleValue>(static_cast<int>(value));
+ static_cast<CBORValue::SimpleValue>(static_cast<int>(header.value));
switch (possibly_unsupported_simple_value) {
case CBORValue::SimpleValue::FALSE_VALUE:
case CBORValue::SimpleValue::TRUE_VALUE:
@@ -192,7 +248,9 @@ base::Optional<CBORValue> CBORReader::ReadSimpleValue(uint8_t additional_info,
return base::nullopt;
}
-base::Optional<CBORValue> CBORReader::ReadString(uint64_t num_bytes) {
+base::Optional<CBORValue> CBORReader::ReadStringContent(
+ const CBORReader::DataItemHeader& header) {
+ uint64_t num_bytes = header.value;
if (!CanConsume(num_bytes)) {
error_code_ = DecoderError::INCOMPLETE_CBOR_DATA;
return base::nullopt;
@@ -206,23 +264,29 @@ base::Optional<CBORValue> CBORReader::ReadString(uint64_t num_bytes) {
: base::nullopt;
}
-base::Optional<CBORValue> CBORReader::ReadBytes(uint64_t num_bytes) {
+base::Optional<CBORValue> CBORReader::ReadByteStringContent(
+ const CBORReader::DataItemHeader& header) {
+ uint64_t num_bytes = header.value;
if (!CanConsume(num_bytes)) {
error_code_ = DecoderError::INCOMPLETE_CBOR_DATA;
return base::nullopt;
}
- Bytes cbor_byte_string(it_, it_ + num_bytes);
+ std::vector<uint8_t> cbor_byte_string(it_, it_ + num_bytes);
it_ += num_bytes;
return CBORValue(std::move(cbor_byte_string));
}
-base::Optional<CBORValue> CBORReader::ReadCBORArray(uint64_t length,
- int max_nesting_level) {
+base::Optional<CBORValue> CBORReader::ReadArrayContent(
+ const CBORReader::DataItemHeader& header,
+ int max_nesting_level) {
+ uint64_t length = header.value;
+
CBORValue::ArrayValue cbor_array;
- while (length-- > 0) {
- base::Optional<CBORValue> cbor_element = DecodeCBOR(max_nesting_level - 1);
+ for (uint64_t i = 0; i < length; ++i) {
+ base::Optional<CBORValue> cbor_element =
+ DecodeCompleteDataItem(max_nesting_level - 1);
if (!cbor_element.has_value())
return base::nullopt;
cbor_array.push_back(std::move(cbor_element.value()));
@@ -230,20 +294,29 @@ base::Optional<CBORValue> CBORReader::ReadCBORArray(uint64_t length,
return CBORValue(std::move(cbor_array));
}
-base::Optional<CBORValue> CBORReader::ReadCBORMap(uint64_t length,
- int max_nesting_level) {
+base::Optional<CBORValue> CBORReader::ReadMapContent(
+ const CBORReader::DataItemHeader& header,
+ int max_nesting_level) {
+ uint64_t length = header.value;
+
CBORValue::MapValue cbor_map;
- while (length-- > 0) {
- base::Optional<CBORValue> key = DecodeCBOR(max_nesting_level - 1);
- base::Optional<CBORValue> value = DecodeCBOR(max_nesting_level - 1);
+ for (uint64_t i = 0; i < length; ++i) {
+ base::Optional<CBORValue> key =
+ DecodeCompleteDataItem(max_nesting_level - 1);
+ base::Optional<CBORValue> value =
+ DecodeCompleteDataItem(max_nesting_level - 1);
if (!key.has_value() || !value.has_value())
return base::nullopt;
- // Only CBOR maps with integer or string type keys are allowed.
- if (key.value().type() != CBORValue::Type::STRING &&
- key.value().type() != CBORValue::Type::UNSIGNED) {
- error_code_ = DecoderError::INCORRECT_MAP_KEY_TYPE;
- return base::nullopt;
+ switch (key.value().type()) {
+ case CBORValue::Type::UNSIGNED:
+ case CBORValue::Type::NEGATIVE:
+ case CBORValue::Type::STRING:
+ case CBORValue::Type::BYTE_STRING:
+ break;
+ default:
+ error_code_ = DecoderError::INCORRECT_MAP_KEY_TYPE;
+ return base::nullopt;
}
if (!CheckDuplicateKey(key.value(), &cbor_map) ||
!CheckOutOfOrderKey(key.value(), &cbor_map)) {
diff --git a/chromium/components/cbor/cbor_reader.h b/chromium/components/cbor/cbor_reader.h
index 35558891a45..c17c5f7c3c3 100644
--- a/chromium/components/cbor/cbor_reader.h
+++ b/chromium/components/cbor/cbor_reader.h
@@ -6,9 +6,11 @@
#define COMPONENTS_CBOR_CBOR_READER_H_
#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/cbor_values.h"
@@ -50,8 +52,6 @@ namespace cbor {
class CBOR_EXPORT CBORReader {
public:
- using Bytes = std::vector<uint8_t>;
-
enum class DecoderError {
CBOR_NO_ERROR = 0,
UNSUPPORTED_MAJOR_TYPE,
@@ -69,6 +69,25 @@ class CBOR_EXPORT CBORReader {
OUT_OF_RANGE_INTEGER_VALUE,
};
+ // Encapsulates information extracted from the header of a CBOR data item,
+ // which consists of the initial byte, and a variable-length-encoded integer
+ // (if any).
+ //
+ // TODO(crbug.com/811717): This is an CBORReader internal detail which should
+ // not be exposed outside. We should switch to an event-based interface
+ // before adding another customer.
+ struct CBOR_EXPORT DataItemHeader {
+ // The major type decoded from the initial byte.
+ CBORValue::Type type;
+
+ // The raw 5-bit additional information from the initial byte.
+ uint8_t additional_info;
+
+ // The integer |value| decoded from the |additional_info| and the
+ // variable-length-encoded integer, if any.
+ uint64_t value;
+ };
+
// CBOR nested depth sufficient for most use cases.
static const int kCBORMaxDepth = 16;
@@ -79,26 +98,48 @@ class CBOR_EXPORT CBORReader {
// CBOR data- then an empty optional is returned. Optional |error_code_out|
// can be provided by the caller to obtain additional information about
// decoding failures.
- static base::Optional<CBORValue> Read(const Bytes& input_data,
+ //
+ // Fails if not all the data was consumed and sets |error_code_out| to
+ // EXTRANEOUS_DATA in this case.
+ static base::Optional<CBORValue> Read(base::span<const uint8_t> input_data,
DecoderError* error_code_out = nullptr,
int max_nesting_level = kCBORMaxDepth);
+ // Never fails with EXTRANEOUS_DATA, but informs the caller of how many bytes
+ // were consumed through |num_bytes_consumed|.
+ static base::Optional<CBORValue> Read(base::span<const uint8_t> input_data,
+ size_t* num_bytes_consumed,
+ DecoderError* error_code_out = nullptr,
+ int max_nesting_level = kCBORMaxDepth);
+
+ // Reads and parses the header of CBOR data item from |input_data|. Optional
+ // |error_code_out| can be provided by the caller to obtain additional
+ // information about decoding failures. Never fails with EXTRANEOUS_DATA, but
+ // informs the caller of how many bytes were consumed through
+ // |num_bytes_consumed|.
+ static base::Optional<DataItemHeader> ReadDataItemHeader(
+ base::span<const uint8_t> input_data,
+ size_t* num_bytes_consumed = nullptr,
+ DecoderError* error_code_out = nullptr);
+
// Translates errors to human-readable error messages.
static const char* ErrorCodeToString(DecoderError error_code);
private:
- CBORReader(Bytes::const_iterator it, const Bytes::const_iterator end);
- base::Optional<CBORValue> DecodeCBOR(int max_nesting_level);
+ CBORReader(base::span<const uint8_t>::const_iterator it,
+ const base::span<const uint8_t>::const_iterator end);
+ base::Optional<DataItemHeader> DecodeDataItemHeader();
+ base::Optional<CBORValue> DecodeCompleteDataItem(int max_nesting_level);
base::Optional<CBORValue> DecodeValueToNegative(uint64_t value);
base::Optional<CBORValue> DecodeValueToUnsigned(uint64_t value);
- base::Optional<CBORValue> ReadSimpleValue(uint8_t additional_info,
- uint64_t value);
+ base::Optional<CBORValue> DecodeToSimpleValue(const DataItemHeader& header);
bool ReadVariadicLengthInteger(uint8_t additional_info, uint64_t* value);
- base::Optional<CBORValue> ReadBytes(uint64_t num_bytes);
- base::Optional<CBORValue> ReadString(uint64_t num_bytes);
- base::Optional<CBORValue> ReadCBORArray(uint64_t length,
- int max_nesting_level);
- base::Optional<CBORValue> ReadCBORMap(uint64_t length, int max_nesting_level);
+ base::Optional<CBORValue> ReadByteStringContent(const DataItemHeader& header);
+ base::Optional<CBORValue> ReadStringContent(const DataItemHeader& header);
+ base::Optional<CBORValue> ReadArrayContent(const DataItemHeader& header,
+ int max_nesting_level);
+ base::Optional<CBORValue> ReadMapContent(const DataItemHeader& header,
+ int max_nesting_level);
bool CanConsume(uint64_t bytes);
void CheckExtraneousData();
bool CheckDuplicateKey(const CBORValue& new_key, CBORValue::MapValue* map);
@@ -108,8 +149,11 @@ class CBOR_EXPORT CBORReader {
DecoderError GetErrorCode();
- Bytes::const_iterator it_;
- const Bytes::const_iterator end_;
+ size_t num_bytes_consumed() const { return it_ - begin_; }
+
+ const base::span<const uint8_t>::const_iterator begin_;
+ base::span<const uint8_t>::const_iterator it_;
+ const base::span<const uint8_t>::const_iterator end_;
DecoderError error_code_;
DISALLOW_COPY_AND_ASSIGN(CBORReader);
diff --git a/chromium/components/cbor/cbor_reader_unittest.cc b/chromium/components/cbor/cbor_reader_unittest.cc
index e9819bf9498..277b428a563 100644
--- a/chromium/components/cbor/cbor_reader_unittest.cc
+++ b/chromium/components/cbor/cbor_reader_unittest.cc
@@ -7,6 +7,7 @@
#include "components/cbor/cbor_reader.h"
+#include "base/containers/span.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -14,6 +15,104 @@
https://github.com/cbor/test-vectors/blob/master/appendix_a.json. */
namespace cbor {
+namespace {
+
+std::vector<uint8_t> WithExtraneousData(base::span<const uint8_t> original) {
+ std::vector<uint8_t> ret(original.cbegin(), original.cend());
+ // Add a valid one byte long CBOR data item, namely, an unsigned integer
+ // with value "1".
+ ret.push_back(0x01);
+ return ret;
+}
+
+} // namespace
+
+TEST(CBORReaderTest, TestDecodeDataItemHeader) {
+ static const struct {
+ CBORReader::DataItemHeader expected_header;
+ const std::vector<uint8_t> cbor_data;
+ } kTestCases[] = {
+ {{CBORValue::Type::UNSIGNED, 0, 0}, {0x00}},
+ {{CBORValue::Type::UNSIGNED, 24, 24}, {0x18, 0x18}},
+ {{CBORValue::Type::UNSIGNED, 25, 12345}, {0x19, 0x30, 0x39}},
+ {{CBORValue::Type::UNSIGNED, 27, 1234567890123456789ull},
+ {0x1B, 0x11, 0x22, 0x10, 0xF4, 0x7D, 0xE9, 0x81, 0x15}},
+ {{CBORValue::Type::NEGATIVE, 24, 255}, {0x38, 0xff}},
+ {{CBORValue::Type::NEGATIVE, 26, 12345677},
+ {0x3a, 0x00, 0xbc, 0x61, 0x4d}},
+ {{CBORValue::Type::BYTE_STRING, 4, 4}, {0x44}},
+ {{CBORValue::Type::STRING, 3, 3}, {0x63}},
+ {{CBORValue::Type::ARRAY, 24, 25}, {0x98, 0x19}},
+ {{CBORValue::Type::MAP, 4, 4}, {0xa4}},
+ {{CBORValue::Type::SIMPLE_VALUE,
+ static_cast<uint8_t>(CBORValue::SimpleValue::FALSE_VALUE), 20},
+ {0xf4}},
+ };
+
+ int test_element_index = 0;
+ for (const auto& test_case : kTestCases) {
+ SCOPED_TRACE(testing::Message() << "testing case " << test_element_index++);
+ size_t consumed_bytes;
+ CBORReader::DecoderError error_code;
+ base::Optional<CBORReader::DataItemHeader> header =
+ CBORReader::ReadDataItemHeader(test_case.cbor_data, &consumed_bytes,
+ &error_code);
+
+ ASSERT_TRUE(header.has_value());
+ EXPECT_EQ(header->type, test_case.expected_header.type);
+ EXPECT_EQ(header->additional_info,
+ test_case.expected_header.additional_info);
+ EXPECT_EQ(header->value, test_case.expected_header.value);
+ EXPECT_EQ(consumed_bytes, test_case.cbor_data.size());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(test_case.cbor_data);
+ header = CBORReader::ReadDataItemHeader(cbor_data_with_extra_byte,
+ &consumed_bytes, &error_code);
+ ASSERT_TRUE(header.has_value());
+ EXPECT_EQ(header->type, test_case.expected_header.type);
+ EXPECT_EQ(header->additional_info,
+ test_case.expected_header.additional_info);
+ EXPECT_EQ(header->value, test_case.expected_header.value);
+ EXPECT_EQ(consumed_bytes, test_case.cbor_data.size());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ }
+}
+
+TEST(CBORReaderTest, TestDecodeIncompleteDataItemHeader) {
+ static const std::vector<uint8_t> kTestCases[] = {
+ // clang-format off
+ {0x18}, // unsigned with pending 1 byte of numeric value.
+ {0x99}, // array with pending 2 byte of numeric value (length).
+ {0xba}, // map with pending 4 byte of numeric value (length).
+ {0x5b}, // byte string with pending 4 byte of numeric value (length).
+ {0x3b}, // negative integer with pending 8 byte of numeric value.
+ {0x99, 0x01}, // array with pending 2 byte of numeric value (length),
+ // with only 1 byte of additional data.
+ {0xba, 0x01, 0x02, 0x03}, // map with pending 4 byte of numeric value
+ // (length), with only 3 bytes of additional
+ // data.
+ {0x3b, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07}, // negative integer with pending 8 byte of
+ // numeric value, with only 7 bytes of
+ // additional data.
+ // clang-format on
+ };
+
+ int test_element_index = 0;
+ for (const auto& test_case : kTestCases) {
+ SCOPED_TRACE(testing::Message() << "testing case " << test_element_index++);
+ size_t consumed_bytes;
+ CBORReader::DecoderError error_code;
+ base::Optional<CBORReader::DataItemHeader> header =
+ CBORReader::ReadDataItemHeader(test_case, &consumed_bytes, &error_code);
+
+ ASSERT_FALSE(header.has_value());
+ EXPECT_EQ(consumed_bytes, 0u);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::INCOMPLETE_CBOR_DATA);
+ }
+}
+
TEST(CBORReaderTest, TestReadUint) {
struct UintTestCase {
const int64_t value;
@@ -42,6 +141,21 @@ TEST(CBORReaderTest, TestReadUint) {
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor.value().type(), CBORValue::Type::UNSIGNED);
EXPECT_EQ(cbor.value().GetInteger(), test_case.value);
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(test_case.cbor_data);
+ CBORReader::DecoderError error_code;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor.value().type(), CBORValue::Type::UNSIGNED);
+ EXPECT_EQ(cbor.value().GetInteger(), test_case.value);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, test_case.cbor_data.size());
}
}
@@ -120,6 +234,21 @@ TEST(CBORReaderTest, TestReadNegativeInt) {
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor.value().type(), CBORValue::Type::NEGATIVE);
EXPECT_EQ(cbor.value().GetInteger(), test_case.negative_int);
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(test_case.cbor_data);
+ CBORReader::DecoderError error_code;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor.value().type(), CBORValue::Type::NEGATIVE);
+ EXPECT_EQ(cbor.value().GetInteger(), test_case.negative_int);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, test_case.cbor_data.size());
}
}
@@ -145,6 +274,21 @@ TEST(CBORReaderTest, TestReadBytes) {
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor.value().type(), CBORValue::Type::BYTE_STRING);
EXPECT_EQ(cbor.value().GetBytestring(), test_case.value);
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(test_case.cbor_data);
+ CBORReader::DecoderError error_code;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor.value().type(), CBORValue::Type::BYTE_STRING);
+ EXPECT_EQ(cbor.value().GetBytestring(), test_case.value);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, test_case.cbor_data.size());
}
}
@@ -172,6 +316,21 @@ TEST(CBORReaderTest, TestReadString) {
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor.value().type(), CBORValue::Type::STRING);
EXPECT_EQ(cbor.value().GetString(), test_case.value);
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(test_case.cbor_data);
+ CBORReader::DecoderError error_code;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor.value().type(), CBORValue::Type::STRING);
+ EXPECT_EQ(cbor.value().GetString(), test_case.value);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, test_case.cbor_data.size());
}
}
@@ -202,6 +361,21 @@ TEST(CBORReaderTest, TestReadStringWithNUL) {
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor.value().type(), CBORValue::Type::STRING);
EXPECT_EQ(cbor.value().GetString(), test_case.value);
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(test_case.cbor_data);
+ CBORReader::DecoderError error_code;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor.value().type(), CBORValue::Type::STRING);
+ EXPECT_EQ(cbor.value().GetString(), test_case.value);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, test_case.cbor_data.size());
}
}
@@ -243,6 +417,21 @@ TEST(CBORReaderTest, TestReadArray) {
EXPECT_EQ(cbor_array.GetArray()[i].GetInteger(),
static_cast<int64_t>(i + 1));
}
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(kArrayTestCaseCbor);
+ CBORReader::DecoderError error_code;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor_array.type(), CBORValue::Type::ARRAY);
+ ASSERT_THAT(cbor_array.GetArray(), testing::SizeIs(25));
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, kArrayTestCaseCbor.size());
}
TEST(CBORReaderTest, TestReadMapWithMapValue) {
@@ -292,6 +481,21 @@ TEST(CBORReaderTest, TestReadMapWithMapValue) {
ASSERT_EQ(cbor_val.GetMap().find(key_aa)->second.type(),
CBORValue::Type::STRING);
EXPECT_EQ(cbor_val.GetMap().find(key_aa)->second.GetString(), "AA");
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(kMapTestCaseCbor);
+ CBORReader::DecoderError error_code;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor_val.type(), CBORValue::Type::MAP);
+ ASSERT_EQ(cbor_val.GetMap().size(), 4u);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, kMapTestCaseCbor.size());
}
TEST(CBORReaderTest, TestReadMapWithIntegerKeys) {
@@ -341,6 +545,76 @@ TEST(CBORReaderTest, TestReadMapWithIntegerKeys) {
ASSERT_EQ(cbor_val.GetMap().find(key_1111)->second.type(),
CBORValue::Type::STRING);
EXPECT_EQ(cbor_val.GetMap().find(key_1111)->second.GetString(), "d");
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(kMapWithIntegerKeyCbor);
+ CBORReader::DecoderError error_code;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor_val.type(), CBORValue::Type::MAP);
+ ASSERT_EQ(cbor_val.GetMap().size(), 4u);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, kMapWithIntegerKeyCbor.size());
+}
+
+TEST(CBORReaderTest, TestReadMapWithNegativeIntegersKeys) {
+ static const std::vector<uint8_t> kMapWithIntegerKeyCbor = {
+ // clang-format off
+ 0xA3, // map with 3 key value pairs
+ 0x20, // key : -1
+ 0x01,
+
+ 0x21, // key : -2
+ 0x02,
+
+ 0x38, 0x63, // key : -100
+ 0x03,
+ // clang-format on
+ };
+
+ base::Optional<CBORValue> cbor = CBORReader::Read(kMapWithIntegerKeyCbor);
+ ASSERT_TRUE(cbor.has_value());
+ const CBORValue cbor_val = std::move(cbor.value());
+ ASSERT_EQ(cbor_val.type(), CBORValue::Type::MAP);
+ ASSERT_EQ(cbor_val.GetMap().size(), 3u);
+
+ const CBORValue key_1(-1);
+ ASSERT_EQ(cbor_val.GetMap().count(key_1), 1u);
+ ASSERT_EQ(cbor_val.GetMap().find(key_1)->second.type(),
+ CBORValue::Type::UNSIGNED);
+ EXPECT_EQ(cbor_val.GetMap().find(key_1)->second.GetInteger(), 1);
+
+ const CBORValue key_2(-2);
+ ASSERT_EQ(cbor_val.GetMap().count(key_2), 1u);
+ ASSERT_EQ(cbor_val.GetMap().find(key_2)->second.type(),
+ CBORValue::Type::UNSIGNED);
+ EXPECT_EQ(cbor_val.GetMap().find(key_2)->second.GetInteger(), 2);
+
+ const CBORValue key_100(-100);
+ ASSERT_EQ(cbor_val.GetMap().count(key_100), 1u);
+ ASSERT_EQ(cbor_val.GetMap().find(key_100)->second.type(),
+ CBORValue::Type::UNSIGNED);
+ EXPECT_EQ(cbor_val.GetMap().find(key_100)->second.GetInteger(), 3);
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(kMapWithIntegerKeyCbor);
+ CBORReader::DecoderError error_code;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor_val.type(), CBORValue::Type::MAP);
+ ASSERT_EQ(cbor_val.GetMap().size(), 3u);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, kMapWithIntegerKeyCbor.size());
}
TEST(CBORReaderTest, TestReadMapWithArray) {
@@ -381,6 +655,187 @@ TEST(CBORReaderTest, TestReadMapWithArray) {
EXPECT_EQ(nested_array.GetArray()[i].GetInteger(),
static_cast<int64_t>(i + 2));
}
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(kMapArrayTestCaseCbor);
+ CBORReader::DecoderError error_code;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor_val.type(), CBORValue::Type::MAP);
+ ASSERT_EQ(cbor_val.GetMap().size(), 2u);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, kMapArrayTestCaseCbor.size());
+}
+
+TEST(CBORReaderTest, TestReadMapWithTextStringKeys) {
+ static const std::vector<uint8_t> kMapTestCase{
+ // clang-format off
+ 0xa2, // map of 2 pairs
+ 0x61, 'k', // text string "k"
+ 0x61, 'v',
+
+ 0x63, 'f', 'o', 'o', // text string "foo"
+ 0x63, 'b', 'a', 'r',
+ // clang-format on
+ };
+
+ CBORReader::DecoderError error_code;
+ base::Optional<CBORValue> cbor = CBORReader::Read(kMapTestCase, &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor->type(), CBORValue::Type::MAP);
+ ASSERT_EQ(cbor->GetMap().size(), 2u);
+
+ const CBORValue key_k("k");
+ ASSERT_EQ(cbor->GetMap().count(key_k), 1u);
+ ASSERT_EQ(cbor->GetMap().find(key_k)->second.type(), CBORValue::Type::STRING);
+ EXPECT_EQ(cbor->GetMap().find(key_k)->second.GetString(), "v");
+
+ const CBORValue key_foo("foo");
+ ASSERT_EQ(cbor->GetMap().count(key_foo), 1u);
+ ASSERT_EQ(cbor->GetMap().find(key_foo)->second.type(),
+ CBORValue::Type::STRING);
+ EXPECT_EQ(cbor->GetMap().find(key_foo)->second.GetString(), "bar");
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(kMapTestCase);
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor->type(), CBORValue::Type::MAP);
+ ASSERT_EQ(cbor->GetMap().size(), 2u);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, kMapTestCase.size());
+}
+
+TEST(CBORReaderTest, TestReadMapWithByteStringKeys) {
+ static const std::vector<uint8_t> kMapTestCase{
+ // clang-format off
+ 0xa2, // map of 2 pairs
+ 0x41, 'k', // byte string "k"
+ 0x41, 'v',
+
+ 0x43, 'f', 'o', 'o', // byte string "foo"
+ 0x43, 'b', 'a', 'r',
+ // clang-format on
+ };
+
+ CBORReader::DecoderError error_code;
+ base::Optional<CBORValue> cbor = CBORReader::Read(kMapTestCase, &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor->type(), CBORValue::Type::MAP);
+ ASSERT_EQ(cbor->GetMap().size(), 2u);
+
+ const CBORValue key_k(std::vector<uint8_t>{'k'});
+ ASSERT_EQ(cbor->GetMap().count(key_k), 1u);
+ ASSERT_EQ(cbor->GetMap().find(key_k)->second.type(),
+ CBORValue::Type::BYTE_STRING);
+ EXPECT_EQ(cbor->GetMap().find(key_k)->second.GetBytestring(),
+ std::vector<uint8_t>{'v'});
+
+ const CBORValue key_foo(std::vector<uint8_t>{'f', 'o', 'o'});
+ ASSERT_EQ(cbor->GetMap().count(key_foo), 1u);
+ ASSERT_EQ(cbor->GetMap().find(key_foo)->second.type(),
+ CBORValue::Type::BYTE_STRING);
+ static const std::vector<uint8_t> kBarBytes{'b', 'a', 'r'};
+ EXPECT_EQ(cbor->GetMap().find(key_foo)->second.GetBytestring(), kBarBytes);
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(kMapTestCase);
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor->type(), CBORValue::Type::MAP);
+ ASSERT_EQ(cbor->GetMap().size(), 2u);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, kMapTestCase.size());
+}
+
+TEST(CBORReaderTest, TestReadMapWithMixedKeys) {
+ // Example adopted from:
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html
+ static const uint8_t kMapTestCase[] = {
+ // clang-format off
+ 0xa6, // map of 6 pairs
+ 0x0a, // 10
+ 0x00,
+
+ 0x18, 0x64, // 100
+ 0x01,
+
+ 0x20, // -1
+ 0x02,
+
+ // This entry is not in the example, but added to test byte string key
+ 0x42, 'x', 'y', // byte string "xy"
+ 0x03,
+
+ 0x61, 'z', // text string "z"
+ 0x04,
+
+ 0x62, 'a', 'a', // text string "aa"
+ 0x05,
+
+ /*
+ 0x81, 0x18, 0x64, // [100] (array as map key is not yet supported)
+ 0x06,
+
+ 0x81, 0x20, // [-1] (array as map key is not yet supported)
+ 0x07,
+
+ 0xf4, // false (boolean as map key is not yet supported)
+ 0x08,
+ */
+ // clang-format on
+ };
+
+ CBORReader::DecoderError error_code;
+ base::Optional<CBORValue> cbor = CBORReader::Read(kMapTestCase, &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor->type(), CBORValue::Type::MAP);
+ ASSERT_EQ(cbor->GetMap().size(), 6u);
+
+ std::vector<CBORValue> keys;
+ keys.emplace_back(10);
+ keys.emplace_back(100);
+ keys.emplace_back(-1);
+ keys.emplace_back(CBORValue::BinaryValue{'x', 'y'});
+ keys.emplace_back("z");
+ keys.emplace_back("aa");
+ for (size_t i = 0; i < keys.size(); ++i) {
+ SCOPED_TRACE(testing::Message() << "testing key at index: " << i);
+ ASSERT_EQ(cbor->GetMap().count(keys[i]), 1u);
+ ASSERT_EQ(cbor->GetMap().find(keys[i])->second.type(),
+ CBORValue::Type::UNSIGNED);
+ EXPECT_EQ(cbor->GetMap().find(keys[i])->second.GetInteger(),
+ static_cast<int>(i));
+ }
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(kMapTestCase);
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor->type(), CBORValue::Type::MAP);
+ ASSERT_EQ(cbor->GetMap().size(), 6u);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, arraysize(kMapTestCase));
}
TEST(CBORReaderTest, TestReadNestedMap) {
@@ -487,6 +942,21 @@ TEST(CBORReaderTest, TestReadSimpleValue) {
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor.value().type(), CBORValue::Type::SIMPLE_VALUE);
EXPECT_EQ(cbor.value().GetSimpleValue(), test_case.value);
+
+ auto cbor_data_with_extra_byte = WithExtraneousData(test_case.cbor_data);
+ CBORReader::DecoderError error_code;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::EXTRANEOUS_DATA);
+
+ size_t num_bytes_consumed;
+ cbor = CBORReader::Read(cbor_data_with_extra_byte, &num_bytes_consumed,
+ &error_code);
+ ASSERT_TRUE(cbor.has_value());
+ ASSERT_EQ(cbor.value().type(), CBORValue::Type::SIMPLE_VALUE);
+ EXPECT_EQ(cbor.value().GetSimpleValue(), test_case.value);
+ EXPECT_EQ(error_code, CBORReader::DecoderError::CBOR_NO_ERROR);
+ EXPECT_EQ(num_bytes_consumed, test_case.cbor_data.size());
}
}
@@ -675,6 +1145,22 @@ TEST(CBORReaderTest, TestOutOfOrderKeyError) {
0x0a, // key 10
0x61, 0x62}, // value "b"
+ {0xa2, // map with 2 text string keys
+ 0x62, 'a', 'a', // key text string "aa"
+ // (out of order due to longer length)
+ 0x02,
+
+ 0x61, 'b', // key "b"
+ 0x01,
+ },
+ {0xa2, // map with 2 byte string keys
+ 0x42, 'x', 'x', // key byte string "xx"
+ // (out of order due to longer length)
+ 0x02,
+
+ 0x41, 'y', // key byte string "y"
+ 0x01,
+ },
//clang-format on
};
@@ -818,4 +1304,19 @@ TEST(CBORReaderTest, TestUnsupportedSimplevalue) {
}
}
+TEST(CBORReaderTest, TestSuperLongContentDontCrash) {
+ static const std::vector<uint8_t> kTestCases[] = {
+ // CBOR array of 0xffffffff length.
+ {0x9b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ // CBOR map of 0xffffffff pairs.
+ {0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ };
+ for (const auto& test_case : kTestCases) {
+ CBORReader::DecoderError error_code;
+ base::Optional<CBORValue> cbor = CBORReader::Read(test_case, &error_code);
+ EXPECT_FALSE(cbor.has_value());
+ EXPECT_EQ(error_code, CBORReader::DecoderError::INCOMPLETE_CBOR_DATA);
+ }
+}
+
} // namespace cbor
diff --git a/chromium/components/cbor/cbor_values.cc b/chromium/components/cbor/cbor_values.cc
index b4517650b45..42454aac633 100644
--- a/chromium/components/cbor/cbor_values.cc
+++ b/chromium/components/cbor/cbor_values.cc
@@ -46,6 +46,16 @@ CBORValue::CBORValue(Type type) : type_(type) {
NOTREACHED();
}
+CBORValue::CBORValue(SimpleValue in_simple)
+ : type_(Type::SIMPLE_VALUE), simple_value_(in_simple) {
+ CHECK(static_cast<int>(in_simple) >= 20 && static_cast<int>(in_simple) <= 23);
+}
+
+CBORValue::CBORValue(bool boolean_value) : type_(Type::SIMPLE_VALUE) {
+ simple_value_ = boolean_value ? CBORValue::SimpleValue::TRUE_VALUE
+ : CBORValue::SimpleValue::FALSE_VALUE;
+}
+
CBORValue::CBORValue(int integer_value)
: CBORValue(base::checked_cast<int64_t>(integer_value)) {}
@@ -59,16 +69,41 @@ CBORValue::CBORValue(const BinaryValue& in_bytes)
CBORValue::CBORValue(BinaryValue&& in_bytes) noexcept
: type_(Type::BYTE_STRING), bytestring_value_(std::move(in_bytes)) {}
-CBORValue::CBORValue(const char* in_string)
- : CBORValue(std::string(in_string)) {}
+CBORValue::CBORValue(const char* in_string, Type type)
+ : CBORValue(base::StringPiece(in_string), type) {}
-CBORValue::CBORValue(std::string&& in_string) noexcept
- : type_(Type::STRING), string_value_(std::move(in_string)) {
- DCHECK(base::IsStringUTF8(string_value_));
+CBORValue::CBORValue(std::string&& in_string, Type type) noexcept
+ : type_(type) {
+ switch (type_) {
+ case Type::STRING:
+ new (&string_value_) std::string();
+ string_value_ = std::move(in_string);
+ DCHECK(base::IsStringUTF8(string_value_));
+ break;
+ case Type::BYTE_STRING:
+ new (&bytestring_value_) BinaryValue();
+ bytestring_value_ = BinaryValue(in_string.begin(), in_string.end());
+ break;
+ default:
+ NOTREACHED();
+ }
}
-CBORValue::CBORValue(base::StringPiece in_string)
- : CBORValue(in_string.as_string()) {}
+CBORValue::CBORValue(base::StringPiece in_string, Type type) : type_(type) {
+ switch (type_) {
+ case Type::STRING:
+ new (&string_value_) std::string();
+ string_value_ = in_string.as_string();
+ DCHECK(base::IsStringUTF8(string_value_));
+ break;
+ case Type::BYTE_STRING:
+ new (&bytestring_value_) BinaryValue();
+ bytestring_value_ = BinaryValue(in_string.begin(), in_string.end());
+ break;
+ default:
+ NOTREACHED();
+ }
+}
CBORValue::CBORValue(const ArrayValue& in_array)
: type_(Type::ARRAY), array_value_() {
@@ -90,11 +125,6 @@ CBORValue::CBORValue(const MapValue& in_map) : type_(Type::MAP), map_value_() {
CBORValue::CBORValue(MapValue&& in_map) noexcept
: type_(Type::MAP), map_value_(std::move(in_map)) {}
-CBORValue::CBORValue(SimpleValue in_simple)
- : type_(Type::SIMPLE_VALUE), simple_value_(in_simple) {
- CHECK(static_cast<int>(in_simple) >= 20 && static_cast<int>(in_simple) <= 23);
-}
-
CBORValue& CBORValue::operator=(CBORValue&& that) noexcept {
InternalCleanup();
InternalMoveConstructFrom(std::move(that));
@@ -129,6 +159,16 @@ CBORValue CBORValue::Clone() const {
return CBORValue();
}
+CBORValue::SimpleValue CBORValue::GetSimpleValue() const {
+ CHECK(is_simple());
+ return simple_value_;
+}
+
+bool CBORValue::GetBool() const {
+ CHECK(is_bool());
+ return simple_value_ == SimpleValue::TRUE_VALUE;
+}
+
const int64_t& CBORValue::GetInteger() const {
CHECK(is_integer());
return integer_value_;
@@ -156,6 +196,14 @@ const CBORValue::BinaryValue& CBORValue::GetBytestring() const {
return bytestring_value_;
}
+base::StringPiece CBORValue::GetBytestringAsString() const {
+ CHECK(is_bytestring());
+ const auto& bytestring_value = GetBytestring();
+ return base::StringPiece(
+ reinterpret_cast<const char*>(bytestring_value.data()),
+ bytestring_value.size());
+}
+
const CBORValue::ArrayValue& CBORValue::GetArray() const {
CHECK(is_array());
return array_value_;
@@ -166,11 +214,6 @@ const CBORValue::MapValue& CBORValue::GetMap() const {
return map_value_;
}
-CBORValue::SimpleValue CBORValue::GetSimpleValue() const {
- CHECK(is_simple());
- return simple_value_;
-}
-
void CBORValue::InternalMoveConstructFrom(CBORValue&& that) {
type_ = that.type_;
diff --git a/chromium/components/cbor/cbor_values.h b/chromium/components/cbor/cbor_values.h
index 53eea212a0c..6003054c488 100644
--- a/chromium/components/cbor/cbor_values.h
+++ b/chromium/components/cbor/cbor_values.h
@@ -6,6 +6,7 @@
#define COMPONENTS_CBOR_CBOR_VALUES_H_
#include <stdint.h>
+
#include <string>
#include <tuple>
#include <vector>
@@ -23,34 +24,35 @@ namespace cbor {
// * Indefinite-length encodings.
class CBOR_EXPORT CBORValue {
public:
- struct CTAPLess {
+ struct Less {
// Comparison predicate to order keys in a dictionary as required by the
- // Client-to-Authenticator Protocol (CTAP) spec 2.0.
- //
- // The sort order defined in CTAP is:
- // • If the major types are different, the one with the lower value in
- // numerical order sorts earlier.
- // • If two keys have different lengths, the shorter one sorts earlier.
- // • If two keys have the same length, the one with the lower value in
- // (byte-wise) lexical order sorts earlier.
- //
- // See section 6 of https://fidoalliance.org/specs/fido-v2.0-rd-20170927/
- // fido-client-to-authenticator-protocol-v2.0-rd-20170927.html.
- //
- // THE CTAP SORT ORDER IMPLEMENTED HERE DIFFERS FROM THE CANONICAL CBOR
- // ORDER defined in https://tools.ietf.org/html/rfc7049#section-3.9, in that
- // the latter sorts purely by serialised key and doesn't specify that major
- // types are compared first. Thus the shortest key sorts first by the RFC
- // rules (irrespective of the major type), but may not by CTAP rules.
+ // canonical CBOR order defined in
+ // https://tools.ietf.org/html/rfc7049#section-3.9
+ // TODO(808022): Clarify where this stands.
bool operator()(const CBORValue& a, const CBORValue& b) const {
- DCHECK((a.is_integer() || a.is_string()) &&
- (b.is_integer() || b.is_string()));
+ // The current implementation only supports integer, text string,
+ // and byte string keys.
+ DCHECK((a.is_integer() || a.is_string() || a.is_bytestring()) &&
+ (b.is_integer() || b.is_string() || b.is_bytestring()));
+
+ // Below text from https://tools.ietf.org/html/rfc7049 errata 4409:
+ // * If the major types are different, the one with the lower value
+ // in numerical order sorts earlier.
if (a.type() != b.type())
return a.type() < b.type();
+
+ // * If two keys have different lengths, the shorter one sorts
+ // earlier;
+ // * If two keys have the same length, the one with the lower value
+ // in (byte-wise) lexical order sorts earlier.
switch (a.type()) {
case Type::UNSIGNED:
+ // For unsigned integers, the smaller value has shorter length,
+ // and (byte-wise) lexical representation.
return a.GetInteger() < b.GetInteger();
case Type::NEGATIVE:
+ // For negative integers, the value closer to zero has shorter length,
+ // and (byte-wise) lexical representation.
return a.GetInteger() > b.GetInteger();
case Type::STRING: {
const auto& a_str = a.GetString();
@@ -59,6 +61,13 @@ class CBOR_EXPORT CBORValue {
const size_t b_length = b_str.size();
return std::tie(a_length, a_str) < std::tie(b_length, b_str);
}
+ case Type::BYTE_STRING: {
+ const auto& a_str = a.GetBytestring();
+ const size_t a_length = a_str.size();
+ const auto& b_str = b.GetBytestring();
+ const size_t b_length = b_str.size();
+ return std::tie(a_length, a_str) < std::tie(b_length, b_str);
+ }
default:
break;
}
@@ -72,7 +81,7 @@ class CBOR_EXPORT CBORValue {
using BinaryValue = std::vector<uint8_t>;
using ArrayValue = std::vector<CBORValue>;
- using MapValue = base::flat_map<CBORValue, CBORValue, CTAPLess>;
+ using MapValue = base::flat_map<CBORValue, CBORValue, Less>;
enum class Type {
UNSIGNED = 0,
@@ -96,6 +105,10 @@ class CBOR_EXPORT CBORValue {
CBORValue() noexcept; // A NONE value.
explicit CBORValue(Type type);
+
+ explicit CBORValue(SimpleValue in_simple);
+ explicit CBORValue(bool boolean_value);
+
explicit CBORValue(int integer_value);
explicit CBORValue(int64_t integer_value);
explicit CBORValue(uint64_t integer_value) = delete;
@@ -103,9 +116,10 @@ class CBOR_EXPORT CBORValue {
explicit CBORValue(const BinaryValue& in_bytes);
explicit CBORValue(BinaryValue&& in_bytes) noexcept;
- explicit CBORValue(const char* in_string);
- explicit CBORValue(std::string&& in_string) noexcept;
- explicit CBORValue(base::StringPiece in_string);
+ explicit CBORValue(const char* in_string, Type type = Type::STRING);
+ explicit CBORValue(std::string&& in_string,
+ Type type = Type::STRING) noexcept;
+ explicit CBORValue(base::StringPiece in_string, Type type = Type::STRING);
explicit CBORValue(const ArrayValue& in_array);
explicit CBORValue(ArrayValue&& in_array) noexcept;
@@ -113,8 +127,6 @@ class CBOR_EXPORT CBORValue {
explicit CBORValue(const MapValue& in_map);
explicit CBORValue(MapValue&& in_map) noexcept;
- explicit CBORValue(SimpleValue in_simple);
-
CBORValue& operator=(CBORValue&& that) noexcept;
~CBORValue();
@@ -129,6 +141,11 @@ class CBOR_EXPORT CBORValue {
// Returns true if the current object represents a given type.
bool is_type(Type type) const { return type == type_; }
bool is_none() const { return type() == Type::NONE; }
+ bool is_simple() const { return type() == Type::SIMPLE_VALUE; }
+ bool is_bool() const {
+ return is_simple() && (simple_value_ == SimpleValue::TRUE_VALUE ||
+ simple_value_ == SimpleValue::FALSE_VALUE);
+ }
bool is_unsigned() const { return type() == Type::UNSIGNED; }
bool is_negative() const { return type() == Type::NEGATIVE; }
bool is_integer() const { return is_unsigned() || is_negative(); }
@@ -136,14 +153,15 @@ class CBOR_EXPORT CBORValue {
bool is_string() const { return type() == Type::STRING; }
bool is_array() const { return type() == Type::ARRAY; }
bool is_map() const { return type() == Type::MAP; }
- bool is_simple() const { return type() == Type::SIMPLE_VALUE; }
// These will all fatally assert if the type doesn't match.
SimpleValue GetSimpleValue() const;
+ bool GetBool() const;
const int64_t& GetInteger() const;
const int64_t& GetUnsigned() const;
const int64_t& GetNegative() const;
const BinaryValue& GetBytestring() const;
+ base::StringPiece GetBytestringAsString() const;
// Returned string may contain NUL characters.
const std::string& GetString() const;
const ArrayValue& GetArray() const;
diff --git a/chromium/components/cbor/cbor_values_unittest.cc b/chromium/components/cbor/cbor_values_unittest.cc
index b003e83be9b..23a959ece17 100644
--- a/chromium/components/cbor/cbor_values_unittest.cc
+++ b/chromium/components/cbor/cbor_values_unittest.cc
@@ -69,6 +69,14 @@ TEST(CBORValuesTest, ConstructBytestring) {
value.GetBytestring());
}
+TEST(CBORValuesTest, ConstructBytestringFromString) {
+ CBORValue value(CBORValue("hello", CBORValue::Type::BYTE_STRING));
+ ASSERT_EQ(CBORValue::Type::BYTE_STRING, value.type());
+ EXPECT_EQ(CBORValue::BinaryValue({'h', 'e', 'l', 'l', 'o'}),
+ value.GetBytestring());
+ EXPECT_EQ("hello", value.GetBytestringAsString());
+}
+
TEST(CBORValuesTest, ConstructArray) {
CBORValue::ArrayValue array;
array.emplace_back(CBORValue("foo"));
@@ -133,6 +141,16 @@ TEST(CBORValuesTest, ConstructSimpleValue) {
undefined_value.GetSimpleValue());
}
+TEST(CBORValuesTest, ConstructSimpleBooleanValue) {
+ CBORValue true_value(true);
+ ASSERT_EQ(CBORValue::Type::SIMPLE_VALUE, true_value.type());
+ EXPECT_TRUE(true_value.GetBool());
+
+ CBORValue false_value(false);
+ ASSERT_EQ(CBORValue::Type::SIMPLE_VALUE, false_value.type());
+ EXPECT_FALSE(false_value.GetBool());
+}
+
// Test copy constructors
TEST(CBORValuesTest, CopyUnsigned) {
CBORValue value(74);
diff --git a/chromium/components/cbor/cbor_writer_unittest.cc b/chromium/components/cbor/cbor_writer_unittest.cc
index 5b047b6d2f4..955a19b8104 100644
--- a/chromium/components/cbor/cbor_writer_unittest.cc
+++ b/chromium/components/cbor/cbor_writer_unittest.cc
@@ -137,10 +137,10 @@ TEST(CBORWriterTest, TestWriteArray) {
arraysize(kArrayTestCaseCbor)));
}
-TEST(CBORWriterTest, TestWriteMapWithMapValue) {
+TEST(CBORWriterTest, TestWriteMap) {
static const uint8_t kMapTestCaseCbor[] = {
// clang-format off
- 0xb6, // map of 8 pairs:
+ 0xb8, 0x19, // map of 25 pairs:
0x00, // key 0
0x61, 0x61, // value "a"
@@ -202,6 +202,15 @@ TEST(CBORWriterTest, TestWriteMapWithMapValue) {
0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x61, 0x73, // value "s"
+ 0x41, 'a', // byte string "a"
+ 0x02,
+
+ 0x43, 'b', 'a', 'r', // byte string "bar"
+ 0x03,
+
+ 0x43, 'f', 'o', 'o', // byte string "foo"
+ 0x04,
+
0x60, // key ""
0x61, 0x2e, // value "."
@@ -233,6 +242,9 @@ TEST(CBORWriterTest, TestWriteMapWithMapValue) {
map[CBORValue(int64_t(-4294967296))] = CBORValue("q");
map[CBORValue(int64_t(-4294967297))] = CBORValue("r");
map[CBORValue(std::numeric_limits<int64_t>::min())] = CBORValue("s");
+ map[CBORValue(CBORValue::BinaryValue{'a'})] = CBORValue(2);
+ map[CBORValue(CBORValue::BinaryValue{'b', 'a', 'r'})] = CBORValue(3);
+ map[CBORValue(CBORValue::BinaryValue{'f', 'o', 'o'})] = CBORValue(4);
map[CBORValue(0)] = CBORValue("a");
map[CBORValue(23)] = CBORValue("b");
map[CBORValue(24)] = CBORValue("c");
@@ -305,6 +317,53 @@ TEST(CBORWriterTest, TestWriteNestedMap) {
arraysize(kNestedMapTestCase)));
}
+TEST(CBORWriterTest, TestSignedExchangeExample) {
+ // Example adopted from:
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html
+ static const uint8_t kSignedExchangeExample[] = {
+ // clang-format off
+ 0xa5, // map of 5 pairs
+ 0x0a, // 10
+ 0x01,
+
+ 0x18, 0x64, // 100
+ 0x02,
+
+ 0x20, // -1
+ 0x03,
+
+ 0x61, 'z', // text string "z"
+ 0x04,
+
+ 0x62, 'a', 'a', // text string "aa"
+ 0x05,
+
+ /*
+ 0x81, 0x18, 0x64, // [100] (array as map key is not yet supported)
+ 0x06,
+
+ 0x81, 0x20, // [-1] (array as map key is not yet supported)
+ 0x07,
+
+ 0xf4, // false (boolean as map key is not yet supported)
+ 0x08,
+ */
+ // clang-format on
+ };
+ CBORValue::MapValue map;
+ map[CBORValue(10)] = CBORValue(1);
+ map[CBORValue(100)] = CBORValue(2);
+ map[CBORValue(-1)] = CBORValue(3);
+ map[CBORValue("z")] = CBORValue(4);
+ map[CBORValue("aa")] = CBORValue(5);
+
+ auto cbor = CBORWriter::Write(CBORValue(map));
+ ASSERT_TRUE(cbor.has_value());
+ EXPECT_THAT(cbor.value(),
+ testing::ElementsAreArray(kSignedExchangeExample,
+ arraysize(kSignedExchangeExample)));
+}
+
TEST(CBORWriterTest, TestWriteSimpleValue) {
static const struct {
CBORValue::SimpleValue simple_value;
diff --git a/chromium/components/cdm/browser/cdm_message_filter_android.cc b/chromium/components/cdm/browser/cdm_message_filter_android.cc
index 91e5f6cf967..e025a22e2fa 100644
--- a/chromium/components/cdm/browser/cdm_message_filter_android.cc
+++ b/chromium/components/cdm/browser/cdm_message_filter_android.cc
@@ -39,6 +39,8 @@ struct CodecInfo {
const CodecInfo<media::VideoCodec> kVideoCodecsToQuery[] = {
{media::EME_CODEC_WEBM_VP8, media::kCodecVP8, "video/webm"},
{media::EME_CODEC_WEBM_VP9, media::kCodecVP9, "video/webm"},
+ {media::EME_CODEC_COMMON_VP9, media::kCodecVP9, "video/webm"},
+ {media::EME_CODEC_COMMON_VP9, media::kCodecVP9, "video/mp4"},
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
{media::EME_CODEC_MP4_AVC1, media::kCodecH264, "video/mp4"},
#if BUILDFLAG(ENABLE_HEVC_DEMUXING)
diff --git a/chromium/components/cdm/browser/media_drm_storage_impl.cc b/chromium/components/cdm/browser/media_drm_storage_impl.cc
index 8e78bbe4c36..0360962c013 100644
--- a/chromium/components/cdm/browser/media_drm_storage_impl.cc
+++ b/chromium/components/cdm/browser/media_drm_storage_impl.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/value_conversions.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
@@ -75,7 +74,7 @@ class OriginData {
base::Time provision_time() const { return provision_time_; }
std::unique_ptr<base::DictionaryValue> ToDictValue() const {
- auto dict = base::MakeUnique<base::DictionaryValue>();
+ auto dict = std::make_unique<base::DictionaryValue>();
dict->Set(kOriginId, base::CreateUnguessableTokenValue(origin_id_));
dict->SetDouble(kCreationTime, provision_time_.ToDoubleT());
@@ -121,7 +120,7 @@ class SessionData {
base::Time creation_time() const { return creation_time_; }
std::unique_ptr<base::DictionaryValue> ToDictValue() const {
- auto dict = base::MakeUnique<base::DictionaryValue>();
+ auto dict = std::make_unique<base::DictionaryValue>();
dict->SetString(
kKeySetId,
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 30e93d5e6b8..1dc150a7a75 100644
--- a/chromium/components/cdm/browser/media_drm_storage_impl_unittest.cc
+++ b/chromium/components/cdm/browser/media_drm_storage_impl_unittest.cc
@@ -5,6 +5,7 @@
#include "components/cdm/browser/media_drm_storage_impl.h"
#include <memory>
+#include <utility>
#include "base/run_loop.h"
#include "base/unguessable_token.h"
@@ -64,7 +65,7 @@ class MediaDrmStorageImplTest : public content::RenderViewHostTestHarness {
media::mojom::MediaDrmStoragePtr media_drm_storage_ptr;
auto request = mojo::MakeRequest(&media_drm_storage_ptr);
- auto media_drm_storage = base::MakeUnique<media::MojoMediaDrmStorage>(
+ auto media_drm_storage = std::make_unique<media::MojoMediaDrmStorage>(
std::move(media_drm_storage_ptr));
content::RenderFrameHost* rfh = web_contents()->GetMainFrame();
@@ -104,7 +105,7 @@ class MediaDrmStorageImplTest : public content::RenderViewHostTestHarness {
const std::vector<uint8_t>& expected_key_set_id,
const std::string& expected_mime_type) {
media_drm_storage_->LoadPersistentSession(
- session_id, ExpectResult(base::MakeUnique<SessionData>(
+ session_id, ExpectResult(std::make_unique<SessionData>(
expected_key_set_id, expected_mime_type)));
}
@@ -135,7 +136,7 @@ class MediaDrmStorageImplTest : public content::RenderViewHostTestHarness {
std::unique_ptr<SessionData> expected_session_data) {
return base::BindOnce(&MediaDrmStorageImplTest::CheckLoadedSession,
base::Unretained(this),
- base::Passed(&expected_session_data));
+ std::move(expected_session_data));
}
void CheckResult(bool expected_result, bool result) {
diff --git a/chromium/components/certificate_reporting/cert_logger.proto b/chromium/components/certificate_reporting/cert_logger.proto
index 998c29316aa..7a06f29750f 100644
--- a/chromium/components/certificate_reporting/cert_logger.proto
+++ b/chromium/components/certificate_reporting/cert_logger.proto
@@ -121,6 +121,7 @@ message CertLoggerRequest {
ERR_CERT_NO_REVOCATION_MECHANISM = 12;
ERR_CERT_NON_UNIQUE_NAME = 13;
ERR_CERTIFICATE_TRANSPARENCY_REQUIRED = 14;
+ ERR_CERT_SYMANTEC_LEGACY = 15;
};
// Certificate errors encountered (if any) when validating this
diff --git a/chromium/components/certificate_reporting/error_report.cc b/chromium/components/certificate_reporting/error_report.cc
index 2026db808c9..d8e6474a1d6 100644
--- a/chromium/components/certificate_reporting/error_report.cc
+++ b/chromium/components/certificate_reporting/error_report.cc
@@ -47,6 +47,7 @@ void AddCertStatusToReportErrors(net::CertStatus cert_status,
COPY_CERT_STATUS(NO_REVOCATION_MECHANISM)
RENAME_CERT_STATUS(CERTIFICATE_TRANSPARENCY_REQUIRED,
CERTIFICATE_TRANSPARENCY_REQUIRED)
+ COPY_CERT_STATUS(SYMANTEC_LEGACY)
#undef RENAME_CERT_STATUS
#undef COPY_CERT_STATUS
diff --git a/chromium/components/certificate_reporting/error_report_unittest.cc b/chromium/components/certificate_reporting/error_report_unittest.cc
index ab510258409..8ebe4893035 100644
--- a/chromium/components/certificate_reporting/error_report_unittest.cc
+++ b/chromium/components/certificate_reporting/error_report_unittest.cc
@@ -7,9 +7,10 @@
#include <set>
#include <string>
+#include <memory>
+
#include "base/files/file_path.h"
#include "base/files/file_util.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/threading/thread.h"
@@ -221,8 +222,8 @@ TEST(ErrorReportTest, NetworkTimeQueryingFeatureInfo) {
TestingPrefServiceSimple pref_service;
network_time::NetworkTimeTracker::RegisterPrefs(pref_service.registry());
network_time::NetworkTimeTracker network_time_tracker(
- base::MakeUnique<base::DefaultClock>(),
- base::MakeUnique<base::DefaultTickClock>(), &pref_service,
+ std::make_unique<base::DefaultClock>(),
+ std::make_unique<base::DefaultTickClock>(), &pref_service,
new net::TestURLRequestContextGetter(io_thread.task_runner()));
// Serialize a report containing information about the network time querying
diff --git a/chromium/components/certificate_reporting/error_reporter.cc b/chromium/components/certificate_reporting/error_reporter.cc
index 599fc5351d6..e8cc59cc160 100644
--- a/chromium/components/certificate_reporting/error_reporter.cc
+++ b/chromium/components/certificate_reporting/error_reporter.cc
@@ -9,8 +9,9 @@
#include <set>
#include <utility>
+#include <memory>
+
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/string_piece.h"
#include "components/encrypted_messages/encrypted_message.pb.h"
#include "components/encrypted_messages/message_encrypter.h"
@@ -76,7 +77,7 @@ ErrorReporter::ErrorReporter(net::URLRequestContext* request_context,
: ErrorReporter(upload_url,
kServerPublicKey,
kServerPublicKeyVersion,
- base::MakeUnique<net::ReportSender>(request_context,
+ std::make_unique<net::ReportSender>(request_context,
kTrafficAnnotation)) {}
ErrorReporter::ErrorReporter(
diff --git a/chromium/components/certificate_reporting/error_reporter_unittest.cc b/chromium/components/certificate_reporting/error_reporter_unittest.cc
index e1fdc8d911f..a5d1d9be6b4 100644
--- a/chromium/components/certificate_reporting/error_reporter_unittest.cc
+++ b/chromium/components/certificate_reporting/error_reporter_unittest.cc
@@ -91,7 +91,7 @@ class MockCertificateReportSender : public net::ReportSender {
class TestCertificateReporterNetworkDelegate : public net::NetworkDelegateImpl {
public:
TestCertificateReporterNetworkDelegate()
- : url_request_destroyed_callback_(base::Bind(&base::DoNothing)) {}
+ : url_request_destroyed_callback_(base::DoNothing()) {}
void set_url_request_destroyed_callback(const base::Closure& callback) {
url_request_destroyed_callback_ = callback;
diff --git a/chromium/components/certificate_transparency/log_dns_client_unittest.cc b/chromium/components/certificate_transparency/log_dns_client_unittest.cc
index 51397c6ca64..d971560199f 100644
--- a/chromium/components/certificate_transparency/log_dns_client_unittest.cc
+++ b/chromium/components/certificate_transparency/log_dns_client_unittest.cc
@@ -11,7 +11,6 @@
#include <vector>
#include "base/format_macros.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
@@ -102,7 +101,7 @@ class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> {
std::unique_ptr<LogDnsClient> CreateLogDnsClient(
size_t max_concurrent_queries) {
- return base::MakeUnique<LogDnsClient>(mock_dns_.CreateDnsClient(),
+ return std::make_unique<LogDnsClient>(mock_dns_.CreateDnsClient(),
net::NetLogWithSource(),
max_concurrent_queries);
}
diff --git a/chromium/components/certificate_transparency/single_tree_tracker.cc b/chromium/components/certificate_transparency/single_tree_tracker.cc
index 3636f4ab9c9..c4a61fe7cf7 100644
--- a/chromium/components/certificate_transparency/single_tree_tracker.cc
+++ b/chromium/components/certificate_transparency/single_tree_tracker.cc
@@ -515,7 +515,8 @@ void SingleTreeTracker::OnMemoryPressure(
break;
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
pending_entries_.clear();
- // Fall through to clearing the other cache.
+ // Fall through to clearing the other cache.
+ FALLTHROUGH;
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
checked_entries_.Clear();
break;
diff --git a/chromium/components/certificate_transparency/single_tree_tracker_unittest.cc b/chromium/components/certificate_transparency/single_tree_tracker_unittest.cc
index 59ba2af0081..d1fb0b1247a 100644
--- a/chromium/components/certificate_transparency/single_tree_tracker_unittest.cc
+++ b/chromium/components/certificate_transparency/single_tree_tracker_unittest.cc
@@ -7,6 +7,8 @@
#include <string>
#include <utility>
+#include <memory>
+
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
@@ -204,10 +206,10 @@ class SingleTreeTrackerTest : public ::testing::Test {
protected:
void CreateTreeTracker() {
- log_dns_client_ = base::MakeUnique<LogDnsClient>(
+ log_dns_client_ = std::make_unique<LogDnsClient>(
mock_dns_.CreateDnsClient(), net_log_with_source_, 1);
- tree_tracker_ = base::MakeUnique<SingleTreeTracker>(
+ tree_tracker_ = std::make_unique<SingleTreeTracker>(
log_, log_dns_client_.get(), &host_resolver_, &net_log_);
}
diff --git a/chromium/components/certificate_transparency/tree_state_tracker.cc b/chromium/components/certificate_transparency/tree_state_tracker.cc
index 2bffdf3be27..958769c694c 100644
--- a/chromium/components/certificate_transparency/tree_state_tracker.cc
+++ b/chromium/components/certificate_transparency/tree_state_tracker.cc
@@ -4,8 +4,9 @@
#include "components/certificate_transparency/tree_state_tracker.h"
+#include <memory>
+
#include "base/feature_list.h"
-#include "base/memory/ptr_util.h"
#include "components/certificate_transparency/log_dns_client.h"
#include "components/certificate_transparency/single_tree_tracker.h"
#include "net/base/network_change_notifier.h"
@@ -41,7 +42,7 @@ TreeStateTracker::TreeStateTracker(
std::unique_ptr<net::DnsClient> dns_client =
net::DnsClient::CreateClient(net_log);
- dns_client_ = base::MakeUnique<LogDnsClient>(
+ dns_client_ = std::make_unique<LogDnsClient>(
std::move(dns_client),
net::NetLogWithSource::Make(net_log,
net::NetLogSourceType::CT_TREE_STATE_TRACKER),
diff --git a/chromium/components/certificate_transparency/tree_state_tracker_unittest.cc b/chromium/components/certificate_transparency/tree_state_tracker_unittest.cc
index c4d2c5789ae..c8f61ce1190 100644
--- a/chromium/components/certificate_transparency/tree_state_tracker_unittest.cc
+++ b/chromium/components/certificate_transparency/tree_state_tracker_unittest.cc
@@ -7,8 +7,9 @@
#include <string>
#include <utility>
+#include <memory>
+
#include "base/feature_list.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
@@ -81,7 +82,7 @@ TEST_F(TreeStateTrackerTest, TestDelegatesCorrectly) {
feature_list.InitAndEnableFeature(kCTLogAuditing);
tree_tracker_ =
- base::MakeUnique<TreeStateTracker>(verifiers, &host_resolver_, &net_log_);
+ std::make_unique<TreeStateTracker>(verifiers, &host_resolver_, &net_log_);
// Add a cache entry for kHostname that indicates it was looked up over DNS.
// SingleTreeTracker requires this before it will request an inclusion proof,
diff --git a/chromium/components/chrome_cleaner/OWNERS b/chromium/components/chrome_cleaner/OWNERS
index 7d85a1a6a1d..eec9dad1995 100644
--- a/chromium/components/chrome_cleaner/OWNERS
+++ b/chromium/components/chrome_cleaner/OWNERS
@@ -1,7 +1,4 @@
-csharp@chromium.org
-joenotcharles@chromium.org
-proberge@chromium.org
-robertshield@chromium.org
+file://chrome_cleaner/OWNERS
# TEAM: security-dev@chromium.org
# COMPONENT: UI>Browser>Preferences>Protector
diff --git a/chromium/components/chrome_cleaner/README.md b/chromium/components/chrome_cleaner/README.md
new file mode 100644
index 00000000000..cab0b94daaf
--- /dev/null
+++ b/chromium/components/chrome_cleaner/README.md
@@ -0,0 +1,5 @@
+This directory contains shared constants and interfaces used for communication
+between the [Chrome Cleanup Tool](/chrome_cleaner) and [Chrome's Safe Browsing
+service](/chrome/browser/safe_browsing/chrome_cleaner).
+
+
diff --git a/chromium/components/client_update_protocol/DEPS b/chromium/components/client_update_protocol/DEPS
index 4ef4138e48f..741468a1a96 100644
--- a/chromium/components/client_update_protocol/DEPS
+++ b/chromium/components/client_update_protocol/DEPS
@@ -1,3 +1,4 @@
include_rules = [
+ "-content",
"+crypto",
]
diff --git a/chromium/components/cloud_devices/common/description_items_inl.h b/chromium/components/cloud_devices/common/description_items_inl.h
index 02fc0237253..ad82045ad26 100644
--- a/chromium/components/cloud_devices/common/description_items_inl.h
+++ b/chromium/components/cloud_devices/common/description_items_inl.h
@@ -11,7 +11,6 @@
#include <utility>
#include <vector>
-#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
#include "base/values.h"
#include "components/cloud_devices/common/description_items.h"
@@ -128,9 +127,9 @@ template <class Option, class Traits>
void SelectionCapability<Option, Traits>::SaveTo(
CloudDeviceDescription* description) const {
DCHECK(IsValid());
- auto options_list = base::MakeUnique<base::ListValue>();
+ auto options_list = std::make_unique<base::ListValue>();
for (size_t i = 0; i < options_.size(); ++i) {
- auto option_value = base::MakeUnique<base::DictionaryValue>();
+ auto option_value = std::make_unique<base::DictionaryValue>();
if (base::checked_cast<int>(i) == default_idx_)
option_value->SetBoolean(json::kKeyIsDefault, true);
Traits::Save(options_[i], option_value.get());
diff --git a/chromium/components/cloud_devices/common/printer_description.cc b/chromium/components/cloud_devices/common/printer_description.cc
index 7f3ae78a906..878b398f185 100644
--- a/chromium/components/cloud_devices/common/printer_description.cc
+++ b/chromium/components/cloud_devices/common/printer_description.cc
@@ -13,7 +13,6 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "components/cloud_devices/common/cloud_device_description_consts.h"
@@ -775,9 +774,9 @@ class PageRangeTraits : public ItemsTraits<kOptionPageRange> {
static void Save(const PageRange& option, base::DictionaryValue* dict) {
if (!option.empty()) {
- auto list = base::MakeUnique<base::ListValue>();
+ auto list = std::make_unique<base::ListValue>();
for (size_t i = 0; i < option.size(); ++i) {
- auto interval = base::MakeUnique<base::DictionaryValue>();
+ auto interval = std::make_unique<base::DictionaryValue>();
interval->SetInteger(kPageRangeStart, option[i].start);
if (option[i].end < kMaxPageNumber)
interval->SetInteger(kPageRangeEnd, option[i].end);
diff --git a/chromium/components/component_updater/component_installer.cc b/chromium/components/component_updater/component_installer.cc
index 499b32aab34..3918172fc60 100644
--- a/chromium/components/component_updater/component_installer.cc
+++ b/chromium/components/component_updater/component_installer.cc
@@ -22,6 +22,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "base/version.h"
+#include "build/build_config.h"
#include "components/component_updater/component_updater_paths.h"
#include "components/component_updater/component_updater_service.h"
#include "components/update_client/component_unpacker.h"
@@ -182,7 +183,7 @@ void ComponentInstaller::Install(const base::FilePath& unpack_path,
// returned.
main_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&ComponentInstaller::ComponentReady, this,
- base::Passed(std::move(manifest))));
+ std::move(manifest)));
main_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), result));
}
@@ -205,7 +206,7 @@ bool ComponentInstaller::Uninstall() {
bool ComponentInstaller::FindPreinstallation(
const base::FilePath& root,
- const scoped_refptr<RegistrationInfo>& registration_info) {
+ scoped_refptr<RegistrationInfo> registration_info) {
base::FilePath path = root.Append(installer_policy_->GetRelativeInstallDir());
if (!base::PathExists(path)) {
DVLOG(1) << "Relative install dir does not exist: " << path.MaybeAsASCII();
@@ -248,7 +249,7 @@ bool ComponentInstaller::FindPreinstallation(
}
void ComponentInstaller::StartRegistration(
- const scoped_refptr<RegistrationInfo>& registration_info) {
+ scoped_refptr<RegistrationInfo> registration_info) {
VLOG(1) << __func__ << " for " << installer_policy_->GetName();
DCHECK(task_runner_.get());
DCHECK(task_runner_->RunsTasksInCurrentSequence());
@@ -390,7 +391,7 @@ void ComponentInstaller::UninstallOnTaskRunner() {
}
void ComponentInstaller::FinishRegistration(
- const scoped_refptr<RegistrationInfo>& registration_info,
+ scoped_refptr<RegistrationInfo> registration_info,
ComponentUpdateService* cus,
base::OnceClosure callback) {
VLOG(1) << __func__ << " for " << installer_policy_->GetName();
diff --git a/chromium/components/component_updater/component_installer.h b/chromium/components/component_updater/component_installer.h
index 5da302a9973..3404ec7d764 100644
--- a/chromium/components/component_updater/component_installer.h
+++ b/chromium/components/component_updater/component_installer.h
@@ -153,20 +153,17 @@ class ComponentInstaller final : public update_client::CrxInstaller {
// files (as opposed to in the user data directory), sets current_* to the
// values associated with that installation and returns true; otherwise,
// returns false.
- bool FindPreinstallation(
- const base::FilePath& root,
- const scoped_refptr<RegistrationInfo>& registration_info);
+ bool FindPreinstallation(const base::FilePath& root,
+ scoped_refptr<RegistrationInfo> registration_info);
update_client::CrxInstaller::Result InstallHelper(
const base::FilePath& unpack_path,
std::unique_ptr<base::DictionaryValue>* manifest,
base::Version* version,
base::FilePath* install_path);
- void StartRegistration(
- const scoped_refptr<RegistrationInfo>& registration_info);
- void FinishRegistration(
- const scoped_refptr<RegistrationInfo>& registration_info,
- ComponentUpdateService* cus,
- base::OnceClosure callback);
+ void StartRegistration(scoped_refptr<RegistrationInfo> registration_info);
+ void FinishRegistration(scoped_refptr<RegistrationInfo> registration_info,
+ ComponentUpdateService* cus,
+ base::OnceClosure callback);
void ComponentReady(std::unique_ptr<base::DictionaryValue> manifest);
void UninstallOnTaskRunner();
diff --git a/chromium/components/component_updater/component_installer_unittest.cc b/chromium/components/component_updater/component_installer_unittest.cc
index c558149c29e..a1f67172841 100644
--- a/chromium/components/component_updater/component_installer_unittest.cc
+++ b/chromium/components/component_updater/component_installer_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <iterator>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -12,7 +13,6 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
#include "base/run_loop.h"
@@ -204,7 +204,7 @@ class ComponentInstallerTest : public testing::Test {
ComponentInstallerTest::ComponentInstallerTest() {
EXPECT_CALL(update_client(), AddObserver(_)).Times(1);
component_updater_ =
- base::MakeUnique<CrxUpdateService>(config_, update_client_);
+ std::make_unique<CrxUpdateService>(config_, update_client_);
}
ComponentInstallerTest::~ComponentInstallerTest() {
@@ -217,9 +217,10 @@ void ComponentInstallerTest::RunThreads() {
}
void ComponentInstallerTest::Unpack(const base::FilePath& crx_path) {
+ auto config = base::MakeRefCounted<TestConfigurator>();
auto component_unpacker = base::MakeRefCounted<ComponentUnpacker>(
std::vector<uint8_t>(std::begin(kSha256Hash), std::end(kSha256Hash)),
- crx_path, nullptr, nullptr);
+ crx_path, nullptr, config->CreateServiceManagerConnector());
component_unpacker->Unpack(base::BindOnce(
&ComponentInstallerTest::UnpackComplete, base::Unretained(this)));
RunThreads();
@@ -272,7 +273,7 @@ TEST_F(ComponentInstallerTest, RegisterComponent) {
EXPECT_CALL(update_client(), Stop()).Times(1);
auto installer = base::MakeRefCounted<ComponentInstaller>(
- base::MakeUnique<FakeInstallerPolicy>());
+ std::make_unique<FakeInstallerPolicy>());
installer->Register(component_updater(), base::OnceClosure());
RunThreads();
@@ -299,7 +300,7 @@ TEST_F(ComponentInstallerTest, RegisterComponent) {
// Tests that the unpack path is removed when the install succeeded.
TEST_F(ComponentInstallerTest, UnpackPathInstallSuccess) {
auto installer = base::MakeRefCounted<ComponentInstaller>(
- base::MakeUnique<FakeInstallerPolicy>());
+ std::make_unique<FakeInstallerPolicy>());
Unpack(test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
@@ -327,7 +328,7 @@ TEST_F(ComponentInstallerTest, UnpackPathInstallSuccess) {
// Tests that the unpack path is removed when the install failed.
TEST_F(ComponentInstallerTest, UnpackPathInstallError) {
auto installer = base::MakeRefCounted<ComponentInstaller>(
- base::MakeUnique<FakeInstallerPolicy>());
+ std::make_unique<FakeInstallerPolicy>());
Unpack(test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
diff --git a/chromium/components/component_updater/component_updater_service.cc b/chromium/components/component_updater/component_updater_service.cc
index cd03f5c54af..5fbf7495878 100644
--- a/chromium/components/component_updater/component_updater_service.cc
+++ b/chromium/components/component_updater/component_updater_service.cc
@@ -17,7 +17,6 @@
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_checker.h"
@@ -57,9 +56,8 @@ ComponentInfo::ComponentInfo(const ComponentInfo& other) = default;
ComponentInfo::ComponentInfo(ComponentInfo&& other) = default;
ComponentInfo::~ComponentInfo() {}
-CrxUpdateService::CrxUpdateService(
- const scoped_refptr<Configurator>& config,
- const scoped_refptr<UpdateClient>& update_client)
+CrxUpdateService::CrxUpdateService(scoped_refptr<Configurator> config,
+ scoped_refptr<UpdateClient> update_client)
: config_(config), update_client_(update_client) {
AddObserver(this);
}
@@ -202,7 +200,7 @@ std::unique_ptr<ComponentInfo> CrxUpdateService::GetComponentForMimeType(
auto* const component = GetComponent(it->second);
if (!component)
return nullptr;
- return base::MakeUnique<ComponentInfo>(
+ return std::make_unique<ComponentInfo>(
GetCrxComponentID(*component), component->fingerprint,
base::UTF8ToUTF16(component->name), component->version);
}
@@ -401,7 +399,8 @@ void CrxUpdateService::OnEvent(Events event, const std::string& id) {
// Unblock all throttles for the component.
if (event == Observer::Events::COMPONENT_UPDATED ||
- event == Observer::Events::COMPONENT_NOT_UPDATED) {
+ event == Observer::Events::COMPONENT_NOT_UPDATED ||
+ event == Observer::Events::COMPONENT_UPDATE_ERROR) {
auto callbacks = ready_callbacks_.equal_range(id);
for (auto it = callbacks.first; it != callbacks.second; ++it) {
std::move(it->second).Run();
@@ -434,10 +433,10 @@ void CrxUpdateService::OnEvent(Events event, const std::string& id) {
// is the job of the browser process.
// TODO(sorin): consider making this a singleton.
std::unique_ptr<ComponentUpdateService> ComponentUpdateServiceFactory(
- const scoped_refptr<Configurator>& config) {
+ scoped_refptr<Configurator> config) {
DCHECK(config);
auto update_client = update_client::UpdateClientFactory(config);
- return base::MakeUnique<CrxUpdateService>(config, std::move(update_client));
+ return std::make_unique<CrxUpdateService>(config, std::move(update_client));
}
} // namespace component_updater
diff --git a/chromium/components/component_updater/component_updater_service.h b/chromium/components/component_updater/component_updater_service.h
index 6ddae4a34e3..718e7fbb0dc 100644
--- a/chromium/components/component_updater/component_updater_service.h
+++ b/chromium/components/component_updater/component_updater_service.h
@@ -156,7 +156,6 @@ class OnDemandUpdater {
friend class OnDemandTester;
friend class policy::ComponentUpdaterPolicyTest;
friend class SupervisedUserWhitelistInstaller;
- friend class DownloadableStringsComponentInstallerPolicy;
friend class ::ComponentsUI;
friend class ::PluginObserver;
friend class SwReporterOnDemandFetcher;
@@ -176,7 +175,7 @@ class OnDemandUpdater {
// Creates the component updater.
std::unique_ptr<ComponentUpdateService> ComponentUpdateServiceFactory(
- const scoped_refptr<Configurator>& config);
+ scoped_refptr<Configurator> config);
} // namespace component_updater
diff --git a/chromium/components/component_updater/component_updater_service_internal.h b/chromium/components/component_updater/component_updater_service_internal.h
index c5b87cfc28e..7ad6243dca9 100644
--- a/chromium/components/component_updater/component_updater_service_internal.h
+++ b/chromium/components/component_updater/component_updater_service_internal.h
@@ -36,8 +36,8 @@ class CrxUpdateService : public ComponentUpdateService,
using Observer = ComponentUpdateService::Observer;
public:
- CrxUpdateService(const scoped_refptr<Configurator>& config,
- const scoped_refptr<UpdateClient>& update_client);
+ CrxUpdateService(scoped_refptr<Configurator> config,
+ scoped_refptr<UpdateClient> update_client);
~CrxUpdateService() override;
// Overrides for ComponentUpdateService.
diff --git a/chromium/components/component_updater/component_updater_service_unittest.cc b/chromium/components/component_updater/component_updater_service_unittest.cc
index 4dfbc93934b..60a081c0ed2 100644
--- a/chromium/components/component_updater/component_updater_service_unittest.cc
+++ b/chromium/components/component_updater/component_updater_service_unittest.cc
@@ -15,7 +15,6 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/task_scheduler/post_task.h"
@@ -201,16 +200,16 @@ void OnDemandTester::OnDemandComplete(update_client::Error error) {
}
std::unique_ptr<ComponentUpdateService> TestComponentUpdateServiceFactory(
- const scoped_refptr<Configurator>& config) {
+ scoped_refptr<Configurator> config) {
DCHECK(config);
- return base::MakeUnique<CrxUpdateService>(
+ return std::make_unique<CrxUpdateService>(
config, base::MakeRefCounted<MockUpdateClient>());
}
ComponentUpdaterTest::ComponentUpdaterTest() {
EXPECT_CALL(update_client(), AddObserver(_)).Times(1);
component_updater_ =
- base::MakeUnique<CrxUpdateService>(config_, update_client_);
+ std::make_unique<CrxUpdateService>(config_, update_client_);
}
ComponentUpdaterTest::~ComponentUpdaterTest() {
diff --git a/chromium/components/component_updater/configurator_impl.cc b/chromium/components/component_updater/configurator_impl.cc
index 07a0dcf9fc2..144d250e3a9 100644
--- a/chromium/components/component_updater/configurator_impl.cc
+++ b/chromium/components/component_updater/configurator_impl.cc
@@ -81,12 +81,9 @@ std::string GetSwitchArgument(const std::vector<std::string>& vec,
} // namespace
-ConfiguratorImpl::ConfiguratorImpl(
- const base::CommandLine* cmdline,
- net::URLRequestContextGetter* url_request_getter,
- bool require_encryption)
- : url_request_getter_(url_request_getter),
- fast_update_(false),
+ConfiguratorImpl::ConfiguratorImpl(const base::CommandLine* cmdline,
+ bool require_encryption)
+ : fast_update_(false),
pings_enabled_(false),
deltas_enabled_(false),
background_downloads_enabled_(false),
@@ -177,10 +174,6 @@ std::string ConfiguratorImpl::GetDownloadPreference() const {
return std::string();
}
-net::URLRequestContextGetter* ConfiguratorImpl::RequestContext() const {
- return url_request_getter_;
-}
-
bool ConfiguratorImpl::EnabledDeltas() const {
return deltas_enabled_;
}
diff --git a/chromium/components/component_updater/configurator_impl.h b/chromium/components/component_updater/configurator_impl.h
index afc3d2d3fb6..bbe013529ac 100644
--- a/chromium/components/component_updater/configurator_impl.h
+++ b/chromium/components/component_updater/configurator_impl.h
@@ -18,10 +18,6 @@ class CommandLine;
class Version;
}
-namespace net {
-class URLRequestContextGetter;
-}
-
namespace component_updater {
// Helper class for the implementations of update_client::Configurator.
@@ -29,7 +25,6 @@ namespace component_updater {
class ConfiguratorImpl {
public:
ConfiguratorImpl(const base::CommandLine* cmdline,
- net::URLRequestContextGetter* url_request_getter,
bool require_encryption);
~ConfiguratorImpl();
@@ -71,9 +66,6 @@ class ConfiguratorImpl {
// download urls are returned.
std::string GetDownloadPreference() const;
- // The source of contexts for all the url requests.
- net::URLRequestContextGetter* RequestContext() const;
-
// True means that this client can handle delta updates.
bool EnabledDeltas() const;
@@ -91,7 +83,6 @@ class ConfiguratorImpl {
std::vector<uint8_t> GetRunActionKeyHash() const;
private:
- net::URLRequestContextGetter* url_request_getter_;
std::string extra_info_;
GURL url_source_override_;
bool fast_update_;
diff --git a/chromium/components/component_updater/configurator_impl_unittest.cc b/chromium/components/component_updater/configurator_impl_unittest.cc
index 39b5f2f5cbf..35a41bea336 100644
--- a/chromium/components/component_updater/configurator_impl_unittest.cc
+++ b/chromium/components/component_updater/configurator_impl_unittest.cc
@@ -32,8 +32,8 @@ class ComponentUpdaterConfiguratorImplTest : public testing::Test {
TEST_F(ComponentUpdaterConfiguratorImplTest, FastUpdate) {
// Test the default timing values when no command line argument is present.
base::CommandLine cmdline(base::CommandLine::NO_PROGRAM);
- std::unique_ptr<ConfiguratorImpl> config(
- new ConfiguratorImpl(&cmdline, nullptr, false));
+ std::unique_ptr<ConfiguratorImpl> config =
+ std::make_unique<ConfiguratorImpl>(&cmdline, false);
CHECK_EQ(6 * kDelayOneMinute, config->InitialDelay());
CHECK_EQ(5 * kDelayOneHour, config->NextCheckDelay());
CHECK_EQ(30 * kDelayOneMinute, config->OnDemandDelay());
@@ -41,7 +41,7 @@ TEST_F(ComponentUpdaterConfiguratorImplTest, FastUpdate) {
// Test the fast-update timings.
cmdline.AppendSwitchASCII("--component-updater", "fast-update");
- config.reset(new ConfiguratorImpl(&cmdline, nullptr, false));
+ config = std::make_unique<ConfiguratorImpl>(&cmdline, false);
CHECK_EQ(10, config->InitialDelay());
CHECK_EQ(5 * kDelayOneHour, config->NextCheckDelay());
CHECK_EQ(2, config->OnDemandDelay());
diff --git a/chromium/components/components_strings.grd b/chromium/components/components_strings.grd
index 5e282e4cdbc..de570070dba 100644
--- a/chromium/components/components_strings.grd
+++ b/chromium/components/components_strings.grd
@@ -205,6 +205,7 @@
<part file="pdf_strings.grdp" />
<part file="physical_web_ui_strings.grdp" />
<part file="policy_strings.grdp" />
+ <part file="printing_strings.grdp" />
<part file="safe_browsing_strings.grdp" />
<part file="security_interstitials_strings.grdp" />
<part file="security_state_strings.grdp" />
@@ -299,6 +300,9 @@
<message name="IDS_ACCNAME_CLOSE" desc="The accessible name for the Close button.">
Close
</message>
+ <message name="IDS_ACCNAME_OPEN" desc="The accessible name for the Open button.">
+ Open
+ </message>
<message name="IDS_ACCNAME_PREVIOUS" desc="The accessible name for the previous button.">
Previous
</message>
diff --git a/chromium/components/consent_auditor/BUILD.gn b/chromium/components/consent_auditor/BUILD.gn
index d308cefa405..4de0bce45fb 100644
--- a/chromium/components/consent_auditor/BUILD.gn
+++ b/chromium/components/consent_auditor/BUILD.gn
@@ -2,6 +2,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+if (is_android) {
+ import("//build/config/android/rules.gni")
+}
+
static_library("consent_auditor") {
sources = [
"consent_auditor.cc",
@@ -17,6 +21,14 @@ static_library("consent_auditor") {
]
}
+if (is_android) {
+ java_cpp_enum("consent_auditor_java") {
+ sources = [
+ "consent_auditor.h",
+ ]
+ }
+}
+
source_set("unit_tests") {
testonly = true
sources = [
diff --git a/chromium/components/consent_auditor/OWNERS b/chromium/components/consent_auditor/OWNERS
index 8a99c77672f..50aa5fa9a4e 100644
--- a/chromium/components/consent_auditor/OWNERS
+++ b/chromium/components/consent_auditor/OWNERS
@@ -1,4 +1,5 @@
dullweber@chromium.org
+markusheintz@chromium.org
msramek@chromium.org
# COMPONENT: Privacy
diff --git a/chromium/components/consent_auditor/consent_auditor.cc b/chromium/components/consent_auditor/consent_auditor.cc
index d86c85f7f53..5e49fd420a5 100644
--- a/chromium/components/consent_auditor/consent_auditor.cc
+++ b/chromium/components/consent_auditor/consent_auditor.cc
@@ -6,7 +6,7 @@
#include <memory>
-#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
#include "base/values.h"
#include "components/consent_auditor/pref_names.h"
#include "components/prefs/pref_registry_simple.h"
@@ -27,16 +27,32 @@ const char kLocalConsentConfirmationKey[] = "confirmation";
const char kLocalConsentVersionKey[] = "version";
const char kLocalConsentLocaleKey[] = "locale";
-UserEventSpecifics::UserConsent::ConsentStatus ToProtoEnum(
+UserEventSpecifics::UserConsent::Feature FeatureToProtoEnum(
+ consent_auditor::Feature feature) {
+ switch (feature) {
+ case consent_auditor::Feature::CHROME_SYNC:
+ return UserEventSpecifics::UserConsent::CHROME_SYNC;
+ case consent_auditor::Feature::PLAY_STORE:
+ return UserEventSpecifics::UserConsent::PLAY_STORE;
+ case consent_auditor::Feature::BACKUP_AND_RESTORE:
+ return UserEventSpecifics::UserConsent::BACKUP_AND_RESTORE;
+ case consent_auditor::Feature::GOOGLE_LOCATION_SERVICE:
+ return UserEventSpecifics::UserConsent::GOOGLE_LOCATION_SERVICE;
+ }
+ NOTREACHED();
+ return UserEventSpecifics::UserConsent::FEATURE_UNSPECIFIED;
+}
+
+UserEventSpecifics::UserConsent::ConsentStatus StatusToProtoEnum(
consent_auditor::ConsentStatus status) {
switch (status) {
- case consent_auditor::ConsentStatus::REVOKED:
- return UserEventSpecifics::UserConsent::REVOKED;
+ case consent_auditor::ConsentStatus::NOT_GIVEN:
+ return UserEventSpecifics::UserConsent::NOT_GIVEN;
case consent_auditor::ConsentStatus::GIVEN:
return UserEventSpecifics::UserConsent::GIVEN;
}
NOTREACHED();
- return UserEventSpecifics::UserConsent::UNSPECIFIED;
+ return UserEventSpecifics::UserConsent::CONSENT_STATUS_UNSPECIFIED;
}
} // namespace
@@ -65,45 +81,70 @@ void ConsentAuditor::RegisterProfilePrefs(PrefRegistrySimple* registry) {
}
void ConsentAuditor::RecordGaiaConsent(
- const std::string& feature,
- const std::vector<int>& consent_grd_ids,
- const std::vector<std::string>& placeholder_replacements,
+ Feature feature,
+ const std::vector<int>& description_grd_ids,
+ int confirmation_grd_id,
ConsentStatus status) {
if (!base::FeatureList::IsEnabled(switches::kSyncUserConsentEvents))
return;
+
+ DCHECK_LE(feature, consent_auditor::Feature::FEATURE_LAST);
+
+ switch (status) {
+ case ConsentStatus::GIVEN:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Privacy.ConsentAuditor.ConsentGiven.Feature", feature,
+ static_cast<int>(consent_auditor::Feature::FEATURE_LAST) + 1);
+ break;
+ case ConsentStatus::NOT_GIVEN:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Privacy.ConsentAuditor.ConsentNotGiven.Feature", feature,
+ static_cast<int>(consent_auditor::Feature::FEATURE_LAST) + 1);
+ break;
+ }
+
std::unique_ptr<sync_pb::UserEventSpecifics> specifics = ConstructUserConsent(
- feature, consent_grd_ids, placeholder_replacements, status);
- // For real usage, UserEventSyncBridge should always be ready to receive
- // events when a consent gets recorded.
- // FakeUserEventService doesn't have a sync bridge.
- // TODO(crbug.com/709094, crbug.com/761485): Remove this check when the store
- // initializes synchronously and is instantly ready to receive data.
- DCHECK(!user_event_service_->GetSyncBridge() ||
- user_event_service_->GetSyncBridge()
- ->change_processor()
- ->IsTrackingMetadata());
+ feature, description_grd_ids, confirmation_grd_id, status);
+ // UserEventSyncBridge initializes asynchronously. Currently, instantiating
+ // UserEventService early in the Profile lifetime bootstraps
+ // the initialization so that it should be ready in practice, but this is
+ // not certain. Exit if it is not the case. Record a histogram to measure
+ // how often that happens.
+ // TODO(crbug.com/709094, crbug.com/761485): Remove this check and histogram
+ // when the store initializes synchronously and is instantly ready to receive
+ // data.
+ bool event_service_ready = !user_event_service_->GetSyncBridge() ||
+ user_event_service_->GetSyncBridge()
+ ->change_processor()
+ ->IsTrackingMetadata();
+ UMA_HISTOGRAM_BOOLEAN("Privacy.ConsentAuditor.UserEventServiceReady",
+ event_service_ready);
+ if (!event_service_ready) {
+ VLOG(1) << "Consent recording failed. The UserEventService has not been "
+ "initialized.";
+ return;
+ }
+
user_event_service_->RecordUserEvent(std::move(specifics));
}
std::unique_ptr<sync_pb::UserEventSpecifics>
ConsentAuditor::ConstructUserConsent(
- const std::string& feature,
- const std::vector<int>& consent_grd_ids,
- const std::vector<std::string>& placeholder_replacements,
+ Feature feature,
+ const std::vector<int>& description_grd_ids,
+ int confirmation_grd_id,
ConsentStatus status) {
- auto specifics = base::MakeUnique<sync_pb::UserEventSpecifics>();
+ auto specifics = std::make_unique<sync_pb::UserEventSpecifics>();
specifics->set_event_time_usec(
base::Time::Now().since_origin().InMicroseconds());
auto* consent = specifics->mutable_user_consent();
- consent->set_feature(feature);
- for (int id : consent_grd_ids) {
- consent->add_consent_grd_ids(id);
- }
- for (const auto& string : placeholder_replacements) {
- consent->add_placeholder_replacements(string);
+ consent->set_feature(FeatureToProtoEnum(feature));
+ for (int id : description_grd_ids) {
+ consent->add_description_grd_ids(id);
}
+ consent->set_confirmation_grd_id(confirmation_grd_id);
consent->set_locale(app_locale_);
- consent->set_status(ToProtoEnum(status));
+ consent->set_status(StatusToProtoEnum(status));
return specifics;
}
diff --git a/chromium/components/consent_auditor/consent_auditor.h b/chromium/components/consent_auditor/consent_auditor.h
index f8de2eaf059..723c2ce7f94 100644
--- a/chromium/components/consent_auditor/consent_auditor.h
+++ b/chromium/components/consent_auditor/consent_auditor.h
@@ -25,7 +25,28 @@ class PrefRegistrySimple;
namespace consent_auditor {
-enum class ConsentStatus { REVOKED, GIVEN };
+// Feature for which a consent moment is to be recorded.
+//
+// This enum is used in histograms. 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.chrome.browser.consent_auditor
+// GENERATED_JAVA_CLASS_NAME_OVERRIDE: ConsentAuditorFeature
+enum class Feature {
+ CHROME_SYNC = 0,
+ PLAY_STORE = 1,
+ BACKUP_AND_RESTORE = 2,
+ GOOGLE_LOCATION_SERVICE = 3,
+
+ FEATURE_LAST = GOOGLE_LOCATION_SERVICE
+};
+
+// Whether a consent is given or not given.
+//
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.consent_auditor
+enum class ConsentStatus { NOT_GIVEN, GIVEN };
class ConsentAuditor : public KeyedService {
public:
@@ -43,15 +64,13 @@ class ConsentAuditor : public KeyedService {
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
// Records a consent for |feature| for the signed-in GAIA account.
- // Descriptions and button texts presented to the user were
- // |consent_grd_ids|. Strings put into placeholders are passed as
- // |placeholder_replacements|.
- // Whether the consent was GIVEN or REVOKED is passed as |status|.
- void RecordGaiaConsent(
- const std::string& feature,
- const std::vector<int>& consent_grd_ids,
- const std::vector<std::string>& placeholder_replacements,
- ConsentStatus status);
+ // Consent text consisted of strings with |consent_grd_ids|, and the UI
+ // element the user clicked had the ID |confirmation_grd_id|.
+ // Whether the consent was GIVEN or NOT_GIVEN is passed as |status|.
+ virtual void RecordGaiaConsent(Feature feature,
+ const std::vector<int>& description_grd_ids,
+ int confirmation_grd_id,
+ ConsentStatus status);
// Records that the user consented to a |feature|. The user was presented with
// |description_text| and accepted it by interacting |confirmation_text|
@@ -63,9 +82,9 @@ class ConsentAuditor : public KeyedService {
private:
std::unique_ptr<sync_pb::UserEventSpecifics> ConstructUserConsent(
- const std::string& feature,
- const std::vector<int>& consent_grd_ids,
- const std::vector<std::string>& placeholder_replacements,
+ Feature feature,
+ const std::vector<int>& description_grd_ids,
+ int confirmation_grd_id,
ConsentStatus status);
PrefService* pref_service_;
diff --git a/chromium/components/consent_auditor/consent_auditor_unittest.cc b/chromium/components/consent_auditor/consent_auditor_unittest.cc
index c3cd3099675..845cb18f382 100644
--- a/chromium/components/consent_auditor/consent_auditor_unittest.cc
+++ b/chromium/components/consent_auditor/consent_auditor_unittest.cc
@@ -67,10 +67,10 @@ void LoadEntriesFromLocalConsentRecord(const base::Value* consents,
class ConsentAuditorTest : public testing::Test {
public:
void SetUp() override {
- pref_service_ = base::MakeUnique<TestingPrefServiceSimple>();
- user_event_service_ = base::MakeUnique<syncer::FakeUserEventService>();
+ pref_service_ = std::make_unique<TestingPrefServiceSimple>();
+ user_event_service_ = std::make_unique<syncer::FakeUserEventService>();
ConsentAuditor::RegisterProfilePrefs(pref_service_->registry());
- consent_auditor_ = base::MakeUnique<ConsentAuditor>(
+ consent_auditor_ = std::make_unique<ConsentAuditor>(
pref_service_.get(), user_event_service_.get(), kCurrentAppVersion,
kCurrentAppLocale);
}
@@ -80,7 +80,7 @@ class ConsentAuditorTest : public testing::Test {
// We'll have to recreate |consent_auditor| in order to update the version
// and locale. This is not a problem, as in reality we'd have to restart
// Chrome to update both, let alone just recreate this class.
- consent_auditor_ = base::MakeUnique<ConsentAuditor>(
+ consent_auditor_ = std::make_unique<ConsentAuditor>(
pref_service_.get(), user_event_service_.get(), new_product_version,
new_app_locale);
}
@@ -161,7 +161,7 @@ TEST_F(ConsentAuditorTest, LocalConsentPrefRepresentation) {
}
TEST_F(ConsentAuditorTest, RecordingEnabled) {
- consent_auditor()->RecordGaiaConsent("feature1", {}, {},
+ consent_auditor()->RecordGaiaConsent(Feature::CHROME_SYNC, {}, 0,
ConsentStatus::GIVEN);
auto& events = user_event_service()->GetRecordedUserEvents();
EXPECT_EQ(1U, events.size());
@@ -170,18 +170,19 @@ TEST_F(ConsentAuditorTest, RecordingEnabled) {
TEST_F(ConsentAuditorTest, RecordingDisabled) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(switches::kSyncUserConsentEvents);
- consent_auditor()->RecordGaiaConsent("feature1", {}, {},
+ consent_auditor()->RecordGaiaConsent(Feature::CHROME_SYNC, {}, 0,
ConsentStatus::GIVEN);
auto& events = user_event_service()->GetRecordedUserEvents();
EXPECT_EQ(0U, events.size());
}
TEST_F(ConsentAuditorTest, RecordGaiaConsent) {
- std::vector<int> kMessageIds = {12, 37, 42};
- std::vector<std::string> kPlaceholders = {"OK.", "user@example.com"};
+ std::vector<int> kDescriptionMessageIds = {12, 37, 42};
+ int kConfirmationMessageId = 47;
base::Time t1 = base::Time::Now();
- consent_auditor()->RecordGaiaConsent("feature1", kMessageIds, kPlaceholders,
- ConsentStatus::GIVEN);
+ consent_auditor()->RecordGaiaConsent(
+ Feature::CHROME_SYNC, kDescriptionMessageIds, kConfirmationMessageId,
+ ConsentStatus::GIVEN);
base::Time t2 = base::Time::Now();
auto& events = user_event_service()->GetRecordedUserEvents();
EXPECT_EQ(1U, events.size());
@@ -190,14 +191,12 @@ TEST_F(ConsentAuditorTest, RecordGaiaConsent) {
EXPECT_FALSE(events[0].has_navigation_id());
EXPECT_TRUE(events[0].has_user_consent());
auto& consent = events[0].user_consent();
- EXPECT_EQ("feature1", consent.feature());
- EXPECT_EQ(3, consent.consent_grd_ids_size());
- EXPECT_EQ(12, consent.consent_grd_ids(0));
- EXPECT_EQ(37, consent.consent_grd_ids(1));
- EXPECT_EQ(42, consent.consent_grd_ids(2));
- EXPECT_EQ(2, consent.placeholder_replacements_size());
- EXPECT_EQ("OK.", consent.placeholder_replacements(0));
- EXPECT_EQ("user@example.com", consent.placeholder_replacements(1));
+ EXPECT_EQ(UserEventSpecifics::UserConsent::CHROME_SYNC, consent.feature());
+ EXPECT_EQ(3, consent.description_grd_ids_size());
+ EXPECT_EQ(kDescriptionMessageIds[0], consent.description_grd_ids(0));
+ EXPECT_EQ(kDescriptionMessageIds[1], consent.description_grd_ids(1));
+ EXPECT_EQ(kDescriptionMessageIds[2], consent.description_grd_ids(2));
+ EXPECT_EQ(kConfirmationMessageId, consent.confirmation_grd_id());
EXPECT_EQ(kCurrentAppLocale, consent.locale());
}
diff --git a/chromium/components/consent_auditor/pref_names.h b/chromium/components/consent_auditor/pref_names.h
index ef0049aee95..978e020eeb2 100644
--- a/chromium/components/consent_auditor/pref_names.h
+++ b/chromium/components/consent_auditor/pref_names.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef COMPONENTS_CONSENT_AUDITOR_PREF_NAMES_H_
+#define COMPONENTS_CONSENT_AUDITOR_PREF_NAMES_H_
+
namespace consent_auditor {
namespace prefs {
@@ -9,3 +12,5 @@ extern const char kLocalConsentsDictionary[];
} // namespace prefs
} // namespace consent_auditor
+
+#endif // COMPONENTS_CONSENT_AUDITOR_PREF_NAMES_H_
diff --git a/chromium/components/constrained_window/constrained_window_views_unittest.cc b/chromium/components/constrained_window/constrained_window_views_unittest.cc
index cf90bc88e88..21ea2eb9f7d 100644
--- a/chromium/components/constrained_window/constrained_window_views_unittest.cc
+++ b/chromium/components/constrained_window/constrained_window_views_unittest.cc
@@ -8,7 +8,6 @@
#include <vector>
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "components/constrained_window/constrained_window_views_client.h"
#include "components/web_modal/test_web_contents_modal_dialog_host.h"
#include "ui/display/display.h"
@@ -217,7 +216,7 @@ TEST_F(ConstrainedWindowViewsTest, NullModalParent) {
test_views_delegate()->set_use_desktop_native_widgets(true);
SetConstrainedWindowViewsClient(
- base::MakeUnique<TestConstrainedWindowViewsClient>());
+ std::make_unique<TestConstrainedWindowViewsClient>());
DialogContents* contents = new DialogContents;
contents->set_modal_type(ui::MODAL_TYPE_WINDOW);
views::Widget* widget = CreateBrowserModalDialogViews(contents, nullptr);
diff --git a/chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views_mac.h b/chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views_mac.h
index deb28bc3f07..cc8a37dbf9f 100644
--- a/chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views_mac.h
+++ b/chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views_mac.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef COMPONENTS_CONSTRAINED_WINDOW_NATIVE_WEB_CONTENTS_MODAL_DIALOG_MANAGER_VIEWS_MAC_H_
+#define COMPONENTS_CONSTRAINED_WINDOW_NATIVE_WEB_CONTENTS_MODAL_DIALOG_MANAGER_VIEWS_MAC_H_
+
#include "components/constrained_window/native_web_contents_modal_dialog_manager_views.h"
namespace web_modal {
@@ -31,3 +34,5 @@ class NativeWebContentsModalDialogManagerViewsMac
};
} // namespace constrained_window
+
+#endif // COMPONENTS_CONSTRAINED_WINDOW_NATIVE_WEB_CONTENTS_MODAL_DIALOG_MANAGER_VIEWS_MAC_H_
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 85516b97b45..eb3d42e9eeb 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
@@ -4,12 +4,12 @@
#include "components/content_settings/core/browser/content_settings_default_provider.h"
+#include <memory>
#include <string>
#include <vector>
#include "base/auto_reset.h"
#include "base/bind.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "components/content_settings/core/browser/content_settings_info.h"
#include "components/content_settings/core/browser/content_settings_registry.h"
@@ -272,7 +272,7 @@ std::unique_ptr<RuleIterator> DefaultProvider::GetRuleIterator(
NOTREACHED();
return nullptr;
}
- return base::MakeUnique<DefaultRuleIterator>(it->second.get());
+ return std::make_unique<DefaultRuleIterator>(it->second.get());
}
void DefaultProvider::ClearAllContentSettingsRules(
diff --git a/chromium/components/content_settings/core/browser/content_settings_global_value_map.cc b/chromium/components/content_settings/core/browser/content_settings_global_value_map.cc
index 85644a318aa..bbf50c981f4 100644
--- a/chromium/components/content_settings/core/browser/content_settings_global_value_map.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_global_value_map.cc
@@ -4,9 +4,9 @@
#include "components/content_settings/core/browser/content_settings_global_value_map.h"
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "base/synchronization/lock.h"
#include "components/content_settings/core/browser/content_settings_rule.h"
#include "components/content_settings/core/common/content_settings.h"
@@ -51,7 +51,7 @@ std::unique_ptr<RuleIterator> GlobalValueMap::GetRuleIterator(
if (it == settings_.end())
return nullptr;
- return base::MakeUnique<RuleIteratorSimple>(it->second);
+ return std::make_unique<RuleIteratorSimple>(it->second);
}
void GlobalValueMap::SetContentSetting(ContentSettingsType content_type,
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 e791367cb26..7f91a3cf2bc 100644
--- a/chromium/components/content_settings/core/browser/content_settings_pref.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_pref.cc
@@ -8,7 +8,6 @@
#include "base/auto_reset.h"
#include "base/bind.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -371,7 +370,7 @@ void ContentSettingsPref::UpdatePref(
if (!found && value) {
settings_dictionary =
pattern_pairs_settings->SetDictionaryWithoutPathExpansion(
- pattern_str, base::MakeUnique<base::DictionaryValue>());
+ pattern_str, std::make_unique<base::DictionaryValue>());
}
if (settings_dictionary) {
@@ -386,7 +385,7 @@ void ContentSettingsPref::UpdatePref(
resource_dictionary =
settings_dictionary->SetDictionaryWithoutPathExpansion(
kPerResourceIdentifierPrefName,
- base::MakeUnique<base::DictionaryValue>());
+ std::make_unique<base::DictionaryValue>());
}
// Update resource dictionary.
if (value == nullptr) {
diff --git a/chromium/components/content_settings/core/browser/content_settings_pref_provider.cc b/chromium/components/content_settings/core/browser/content_settings_pref_provider.cc
index 62834c227f9..5e4ed353a4e 100644
--- a/chromium/components/content_settings/core/browser/content_settings_pref_provider.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_pref_provider.cc
@@ -13,7 +13,6 @@
#include "base/auto_reset.h"
#include "base/bind.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/default_clock.h"
#include "components/content_settings/core/browser/content_settings_pref.h"
@@ -113,7 +112,7 @@ PrefProvider::PrefProvider(PrefService* prefs,
for (const WebsiteSettingsInfo* info : *website_settings) {
content_settings_prefs_.insert(std::make_pair(
info->type(),
- base::MakeUnique<ContentSettingsPref>(
+ std::make_unique<ContentSettingsPref>(
info->type(), prefs_, &pref_change_registrar_, info->pref_name(),
is_incognito_,
base::Bind(&PrefProvider::Notify, base::Unretained(this)))));
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 1f564bc2bcb..c19ffd0ed5c 100644
--- a/chromium/components/content_settings/core/browser/content_settings_registry.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_registry.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "build/build_config.h"
@@ -345,6 +344,16 @@ void ContentSettingsRegistry::Init() {
WebsiteSettingsRegistry::DESKTOP |
WebsiteSettingsRegistry::PLATFORM_ANDROID,
ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE);
+
+ Register(CONTENT_SETTINGS_TYPE_PAYMENT_HANDLER, "payment-handler",
+ CONTENT_SETTING_ASK, WebsiteSettingsInfo::UNSYNCABLE,
+ WhitelistedSchemes(),
+ ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK,
+ CONTENT_SETTING_ASK),
+ WebsiteSettingsInfo::REQUESTING_ORIGIN_AND_TOP_LEVEL_ORIGIN_SCOPE,
+ WebsiteSettingsRegistry::DESKTOP |
+ WebsiteSettingsRegistry::PLATFORM_ANDROID,
+ ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE);
}
void ContentSettingsRegistry::Register(
@@ -373,7 +382,7 @@ void ContentSettingsRegistry::Register(
return;
DCHECK(!base::ContainsKey(content_settings_info_, type));
- content_settings_info_[type] = base::MakeUnique<ContentSettingsInfo>(
+ content_settings_info_[type] = std::make_unique<ContentSettingsInfo>(
website_settings_info, whitelisted_schemes, valid_settings,
incognito_behavior);
}
diff --git a/chromium/components/content_settings/core/browser/cookie_settings.cc b/chromium/components/content_settings/core/browser/cookie_settings.cc
index 0deb011cec0..124c51b3644 100644
--- a/chromium/components/content_settings/core/browser/cookie_settings.cc
+++ b/chromium/components/content_settings/core/browser/cookie_settings.cc
@@ -32,6 +32,12 @@ bool IsAllowed(ContentSetting setting) {
setting == CONTENT_SETTING_SESSION_ONLY);
}
+GURL ToHttps(GURL url) {
+ GURL::Replacements replace_scheme;
+ replace_scheme.SetSchemeStr(url::kHttpsScheme);
+ return url.ReplaceComponents(replace_scheme);
+}
+
} // namespace
namespace content_settings {
@@ -71,10 +77,16 @@ bool CookieSettings::IsCookieSessionOnly(const GURL& origin) const {
return (setting == CONTENT_SETTING_SESSION_ONLY);
}
-bool CookieSettings::IsCookieSessionOnlyOrBlocked(const GURL& origin) const {
+bool CookieSettings::ShouldDeleteCookieOnExit(const GURL& origin) const {
ContentSetting setting;
GetCookieSetting(origin, origin, nullptr, &setting);
DCHECK(IsValidSetting(setting));
+
+ if (setting == CONTENT_SETTING_BLOCK && origin.SchemeIs(url::kHttpScheme)) {
+ // Keep blocked, non-secure cookies if the secure origin is set to ALLOW.
+ GURL https_origin = ToHttps(origin);
+ return ShouldDeleteCookieOnExit(https_origin);
+ }
return (setting == CONTENT_SETTING_SESSION_ONLY) ||
(setting == CONTENT_SETTING_BLOCK);
}
diff --git a/chromium/components/content_settings/core/browser/cookie_settings.h b/chromium/components/content_settings/core/browser/cookie_settings.h
index f7f2b8b7ea2..7a15d8dfe2e 100644
--- a/chromium/components/content_settings/core/browser/cookie_settings.h
+++ b/chromium/components/content_settings/core/browser/cookie_settings.h
@@ -61,9 +61,12 @@ class CookieSettings : public RefcountedKeyedService {
// Returns true if the cookie set by a page identified by |url| should be
// session only or blocked.
+ // If an http |url| is BLOCKED, but the https version of |url| is ALLOWED,
+ // the cookie will not be deleted to allow blocking http cookie without
+ // affecting cookies from https sites that are not marked as "Secure".
//
// This may be called on any thread.
- bool IsCookieSessionOnlyOrBlocked(const GURL& url) const;
+ bool ShouldDeleteCookieOnExit(const GURL& url) const;
// Returns all patterns with a non-default cookie setting, mapped to their
// actual settings, in the precedence order of the setting rules. |settings|
diff --git a/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc b/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc
index f606004be5e..b073e790cfd 100644
--- a/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc
+++ b/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc
@@ -113,6 +113,29 @@ TEST_F(CookieSettingsTest, CookiesExplicitSessionOnly) {
EXPECT_TRUE(cookie_settings_->IsCookieSessionOnly(kBlockedSite));
}
+TEST_F(CookieSettingsTest, CookiesDeleteSessionOnlyAndBlocked) {
+ // Delete blocked cookies.
+ cookie_settings_->SetCookieSetting(kBlockedSite, CONTENT_SETTING_BLOCK);
+ EXPECT_FALSE(cookie_settings_->ShouldDeleteCookieOnExit(kHttpSite));
+ EXPECT_TRUE(cookie_settings_->ShouldDeleteCookieOnExit(kBlockedSite));
+
+ // Delete session_only cookies.
+ cookie_settings_->SetCookieSetting(kHttpSite, CONTENT_SETTING_SESSION_ONLY);
+ cookie_settings_->SetCookieSetting(kHttpsSite, CONTENT_SETTING_ALLOW);
+ EXPECT_TRUE(cookie_settings_->ShouldDeleteCookieOnExit(kHttpSite));
+ EXPECT_FALSE(cookie_settings_->ShouldDeleteCookieOnExit(kHttpsSite));
+
+ // Keep blocked http cookies if https is allowed.
+ cookie_settings_->SetCookieSetting(kHttpSite, CONTENT_SETTING_BLOCK);
+ EXPECT_FALSE(cookie_settings_->ShouldDeleteCookieOnExit(kHttpSite));
+ EXPECT_FALSE(cookie_settings_->ShouldDeleteCookieOnExit(kHttpsSite));
+
+ // Delete cookies if http is blocked and https session only.
+ cookie_settings_->SetCookieSetting(kHttpsSite, CONTENT_SETTING_SESSION_ONLY);
+ EXPECT_TRUE(cookie_settings_->ShouldDeleteCookieOnExit(kHttpSite));
+ EXPECT_TRUE(cookie_settings_->ShouldDeleteCookieOnExit(kHttpsSite));
+}
+
TEST_F(CookieSettingsTest, CookiesThirdPartyBlockedExplicitAllow) {
cookie_settings_->SetCookieSetting(kAllowedSite, CONTENT_SETTING_ALLOW);
prefs_.SetBoolean(prefs::kBlockThirdPartyCookies, true);
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 78e80b3bd91..f41087e7c40 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
@@ -7,11 +7,11 @@
#include <stddef.h>
#include <algorithm>
+#include <memory>
#include <utility>
#include "base/command_line.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -218,11 +218,12 @@ HostContentSettingsMap::HostContentSettingsMap(PrefService* prefs,
if (is_guest_profile)
pref_provider_->ClearPrefs();
- auto default_provider = base::MakeUnique<content_settings::DefaultProvider>(
+ auto default_provider = std::make_unique<content_settings::DefaultProvider>(
prefs_, is_incognito_);
default_provider->AddObserver(this);
content_settings_providers_[DEFAULT_PROVIDER] = std::move(default_provider);
+ InitializePluginsDataSettings();
RecordExceptionMetrics();
}
@@ -533,6 +534,10 @@ base::WeakPtr<HostContentSettingsMap> HostContentSettingsMap::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
+void HostContentSettingsMap::SetClockForTesting(base::Clock* clock) {
+ pref_provider_->SetClockForTesting(clock);
+}
+
void HostContentSettingsMap::RecordExceptionMetrics() {
for (const content_settings::WebsiteSettingsInfo* info :
*content_settings::WebsiteSettingsRegistry::GetInstance()) {
@@ -689,7 +694,7 @@ void HostContentSettingsMap::AddSettingsForOneType(
const content_settings::Rule& rule = rule_iterator->Next();
settings->push_back(ContentSettingPatternSource(
rule.primary_pattern, rule.secondary_pattern,
- base::MakeUnique<base::Value>(rule.value->Clone()),
+ std::make_unique<base::Value>(rule.value->Clone()),
kProviderNamesSourceMap[provider_type].provider_name, incognito));
}
}
@@ -849,6 +854,32 @@ HostContentSettingsMap::GetContentSettingValueAndPatterns(
return std::unique_ptr<base::Value>();
}
-void HostContentSettingsMap::SetClockForTesting(base::Clock* clock) {
- pref_provider_->SetClockForTesting(clock);
+void HostContentSettingsMap::InitializePluginsDataSettings() {
+ if (!content_settings::WebsiteSettingsRegistry::GetInstance()->Get(
+ CONTENT_SETTINGS_TYPE_PLUGINS_DATA)) {
+ return;
+ }
+ ContentSettingsForOneType host_settings;
+ GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS_DATA, std::string(),
+ &host_settings);
+ if (host_settings.empty()) {
+ GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS, std::string(),
+ &host_settings);
+ for (ContentSettingPatternSource pattern : host_settings) {
+ if (pattern.source != "preference")
+ continue;
+ const GURL primary(pattern.primary_pattern.ToString());
+ if (!primary.is_valid())
+ continue;
+ DCHECK_EQ(ContentSettingsPattern::Relation::IDENTITY,
+ ContentSettingsPattern::Wildcard().Compare(
+ pattern.secondary_pattern));
+ auto dict = std::make_unique<base::DictionaryValue>();
+ constexpr char kFlagKey[] = "flashPreviouslyChanged";
+ dict->SetKey(kFlagKey, base::Value(true));
+ SetWebsiteSettingDefaultScope(primary, primary,
+ CONTENT_SETTINGS_TYPE_PLUGINS_DATA,
+ std::string(), std::move(dict));
+ }
+ }
}
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 890e8959ae1..be6ca47337b 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
@@ -18,6 +18,7 @@
#include "base/observer_list.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_checker.h"
+#include "build/build_config.h"
#include "components/content_settings/core/browser/content_settings_observer.h"
#include "components/content_settings/core/browser/content_settings_utils.h"
#include "components/content_settings/core/browser/user_modifiable_provider.h"
@@ -372,6 +373,11 @@ class HostContentSettingsMap : public content_settings::Observer,
ContentSettingsPattern* primary_pattern,
ContentSettingsPattern* secondary_pattern);
+ // Make sure existing non-default Flash settings set by the user are marked to
+ // always show the Flash setting for this site in Page Info.
+ // TODO(patricialor): Remove after m66 (migration code).
+ void InitializePluginsDataSettings();
+
#ifndef NDEBUG
// This starts as the thread ID of the thread that constructs this
// object, and remains until used by a different thread, at which
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 b33ded94568..5c74c36aa39 100644
--- a/chromium/components/content_settings/core/browser/website_settings_registry.cc
+++ b/chromium/components/content_settings/core/browser/website_settings_registry.cc
@@ -181,6 +181,10 @@ void WebsiteSettingsRegistry::Init() {
WebsiteSettingsInfo::REQUESTING_ORIGIN_ONLY_SCOPE,
DESKTOP | PLATFORM_ANDROID,
WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
+ Register(CONTENT_SETTINGS_TYPE_PLUGINS_DATA, "flash-data", nullptr,
+ WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
+ WebsiteSettingsInfo::REQUESTING_ORIGIN_ONLY_SCOPE, DESKTOP,
+ WebsiteSettingsInfo::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 d1a9b879d70..0f0f3c9fea7 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
@@ -4,8 +4,9 @@
#include "components/content_settings/core/browser/website_settings_registry.h"
+#include <memory>
+
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "components/content_settings/core/browser/website_settings_info.h"
#include "components/content_settings/core/common/content_settings.h"
@@ -88,7 +89,7 @@ TEST_F(WebsiteSettingsRegistryTest, Properties) {
// Register a new setting.
registry()->Register(static_cast<ContentSettingsType>(10), "test",
- base::MakeUnique<base::Value>(999),
+ std::make_unique<base::Value>(999),
WebsiteSettingsInfo::SYNCABLE,
WebsiteSettingsInfo::LOSSY,
WebsiteSettingsInfo::TOP_LEVEL_ORIGIN_ONLY_SCOPE,
@@ -117,7 +118,7 @@ TEST_F(WebsiteSettingsRegistryTest, Properties) {
TEST_F(WebsiteSettingsRegistryTest, Iteration) {
registry()->Register(static_cast<ContentSettingsType>(10), "test",
- base::MakeUnique<base::Value>(999),
+ std::make_unique<base::Value>(999),
WebsiteSettingsInfo::SYNCABLE,
WebsiteSettingsInfo::LOSSY,
WebsiteSettingsInfo::TOP_LEVEL_ORIGIN_ONLY_SCOPE,
diff --git a/chromium/components/content_settings/core/common/content_settings.cc b/chromium/components/content_settings/core/common/content_settings.cc
index 513fd4062d2..e03af266e14 100644
--- a/chromium/components/content_settings/core/common/content_settings.cc
+++ b/chromium/components/content_settings/core/common/content_settings.cc
@@ -5,6 +5,7 @@
#include "components/content_settings/core/common/content_settings.h"
#include <algorithm>
+#include <memory>
#include "base/logging.h"
#include "base/macros.h"
@@ -28,7 +29,7 @@ struct HistogramValue {
// content settings type name instead.
//
// The array size must be explicit for the static_asserts below.
-constexpr size_t kNumHistogramValues = 35;
+constexpr size_t kNumHistogramValues = 37;
constexpr HistogramValue kHistogramValue[kNumHistogramValues] = {
{CONTENT_SETTINGS_TYPE_COOKIES, 0},
{CONTENT_SETTINGS_TYPE_IMAGES, 1},
@@ -65,6 +66,8 @@ constexpr HistogramValue kHistogramValue[kNumHistogramValues] = {
{CONTENT_SETTINGS_TYPE_ACCESSIBILITY_EVENTS, 39},
{CONTENT_SETTINGS_TYPE_CLIPBOARD_READ, 40},
{CONTENT_SETTINGS_TYPE_CLIPBOARD_WRITE, 41},
+ {CONTENT_SETTINGS_TYPE_PLUGINS_DATA, 42},
+ {CONTENT_SETTINGS_TYPE_PAYMENT_HANDLER, 43},
};
} // namespace
@@ -124,7 +127,7 @@ ContentSettingPatternSource& ContentSettingPatternSource::operator=(
primary_pattern = other.primary_pattern;
secondary_pattern = other.secondary_pattern;
if (other.setting_value)
- setting_value = base::MakeUnique<base::Value>(other.setting_value->Clone());
+ setting_value = std::make_unique<base::Value>(other.setting_value->Clone());
source = other.source;
incognito = other.incognito;
return *this;
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 a7f5e80c52b..6c84bfb22e7 100644
--- a/chromium/components/content_settings/core/common/content_settings_pattern.cc
+++ b/chromium/components/content_settings/core/common/content_settings_pattern.cc
@@ -10,7 +10,6 @@
#include <vector>
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "components/content_settings/core/common/content_settings_pattern_parser.h"
@@ -322,7 +321,7 @@ const int ContentSettingsPattern::kContentSettingsPatternVersion = 1;
// static
std::unique_ptr<BuilderInterface> ContentSettingsPattern::CreateBuilder() {
- return base::MakeUnique<Builder>();
+ return std::make_unique<Builder>();
}
// static
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 ef4c1f0933c..8b894ce28de 100644
--- a/chromium/components/content_settings/core/common/content_settings_types.h
+++ b/chromium/components/content_settings/core/common/content_settings_types.h
@@ -100,6 +100,13 @@ enum ContentSettingsType {
// such doesn't have associated prefs data.
CONTENT_SETTINGS_TYPE_CLIPBOARD_WRITE,
+ // Used to store whether the user has ever changed the Flash permission for
+ // a site.
+ CONTENT_SETTINGS_TYPE_PLUGINS_DATA,
+
+ // Used to store whether to allow a website to install a payment handler.
+ CONTENT_SETTINGS_TYPE_PAYMENT_HANDLER,
+
CONTENT_SETTINGS_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 3f86905a69b..415d73983de 100644
--- a/chromium/components/content_settings/core/common/content_settings_utils.cc
+++ b/chromium/components/content_settings/core/common/content_settings_utils.cc
@@ -4,7 +4,8 @@
#include "components/content_settings/core/common/content_settings_utils.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "base/values.h"
namespace content_settings {
@@ -41,7 +42,7 @@ std::unique_ptr<base::Value> ContentSettingToValue(ContentSetting setting) {
setting >= CONTENT_SETTING_NUM_SETTINGS) {
return nullptr;
}
- return base::MakeUnique<base::Value>(setting);
+ return std::make_unique<base::Value>(setting);
}
} // namespace content_settings
diff --git a/chromium/components/content_view/BUILD.gn b/chromium/components/content_view/BUILD.gn
new file mode 100644
index 00000000000..c50f552d3c5
--- /dev/null
+++ b/chromium/components/content_view/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+android_library("content_view_java") {
+ deps = [
+ "//base:base_java",
+ "//content/public/android:content_java",
+ "//ui/android:ui_java",
+ ]
+ java_files =
+ [ "java/src/org/chromium/components/content_view/ContentView.java" ]
+}
diff --git a/chromium/components/content_view/DEPS b/chromium/components/content_view/DEPS
new file mode 100644
index 00000000000..f20cebbb3be
--- /dev/null
+++ b/chromium/components/content_view/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+ "-content/public/android/java",
+ "+content/public/android/java/src/org/chromium/content_public",
+
+ "+ui/android/java",
+]
diff --git a/chromium/components/content_view/OWNERS b/chromium/components/content_view/OWNERS
new file mode 100644
index 00000000000..7bf23a78474
--- /dev/null
+++ b/chromium/components/content_view/OWNERS
@@ -0,0 +1,6 @@
+boliu@chromium.org
+jinsukkim@chromium.org
+tedchoc@chromium.org
+
+# COMPONENT: Internals>Core
+# OS: Android
diff --git a/chromium/components/content_view/README b/chromium/components/content_view/README
new file mode 100644
index 00000000000..e8196ae12f9
--- /dev/null
+++ b/chromium/components/content_view/README
@@ -0,0 +1,2 @@
+- ContentView exists in Android UI view hierarchy, and exposes various
+view functionality to content layer.
diff --git a/chromium/components/contextual_search/BUILD.gn b/chromium/components/contextual_search/BUILD.gn
index b8331d1db13..308a1c2de7f 100644
--- a/chromium/components/contextual_search/BUILD.gn
+++ b/chromium/components/contextual_search/BUILD.gn
@@ -9,7 +9,7 @@ mojom("mojo_bindings") {
"common/contextual_search_js_api_service.mojom",
]
public_deps = [
- "//url/mojo:url_mojom_gurl",
+ "//url/mojom:url_mojom_gurl",
]
}
diff --git a/chromium/components/contextual_search/browser/contextual_search_js_api_service_impl.cc b/chromium/components/contextual_search/browser/contextual_search_js_api_service_impl.cc
index db92f874ac4..9dc6a06d4dd 100644
--- a/chromium/components/contextual_search/browser/contextual_search_js_api_service_impl.cc
+++ b/chromium/components/contextual_search/browser/contextual_search_js_api_service_impl.cc
@@ -4,9 +4,9 @@
#include "components/contextual_search/browser/contextual_search_js_api_service_impl.h"
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "components/contextual_search/browser/contextual_search_js_api_handler.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -36,7 +36,7 @@ void ContextualSearchJsApiServiceImpl::HandleSetCaption(
void CreateContextualSearchJsApiService(
ContextualSearchJsApiHandler* contextual_search_js_api_handler,
mojom::ContextualSearchJsApiServiceRequest request) {
- mojo::MakeStrongBinding(base::MakeUnique<ContextualSearchJsApiServiceImpl>(
+ mojo::MakeStrongBinding(std::make_unique<ContextualSearchJsApiServiceImpl>(
contextual_search_js_api_handler),
std::move(request));
}
diff --git a/chromium/components/contextual_search/common/contextual_search_js_api_service.mojom b/chromium/components/contextual_search/common/contextual_search_js_api_service.mojom
index 7185815d3dd..34841f75e47 100644
--- a/chromium/components/contextual_search/common/contextual_search_js_api_service.mojom
+++ b/chromium/components/contextual_search/common/contextual_search_js_api_service.mojom
@@ -4,7 +4,7 @@
module contextual_search.mojom;
-import "url/mojo/url.mojom";
+import "url/mojom/url.mojom";
// This service is implemented by the browser process and is used by the
// renderer when a Contextual Search JavaScript API function is called.
diff --git a/chromium/components/crash/content/app/BUILD.gn b/chromium/components/crash/content/app/BUILD.gn
index ec51ed51d09..f8be4ff23ec 100644
--- a/chromium/components/crash/content/app/BUILD.gn
+++ b/chromium/components/crash/content/app/BUILD.gn
@@ -74,7 +74,19 @@ static_library("app") {
}
if (is_win) {
- deps += [ "//third_party/crashpad/crashpad/handler" ]
+ sources += [
+ "dump_hung_process_with_ptype.cc",
+ "dump_hung_process_with_ptype.h",
+ "minidump_with_crashpad_info.cc",
+ "minidump_with_crashpad_info.h",
+ ]
+
+ deps += [
+ "//third_party/crashpad/crashpad/client",
+ "//third_party/crashpad/crashpad/handler",
+ "//third_party/crashpad/crashpad/minidump",
+ "//third_party/crashpad/crashpad/util",
+ ]
}
if (is_android) {
@@ -93,6 +105,8 @@ if (is_win) {
"fallback_crash_handler_win.h",
"fallback_crash_handling_win.cc",
"fallback_crash_handling_win.h",
+ "minidump_with_crashpad_info.cc",
+ "minidump_with_crashpad_info.h",
"run_as_crashpad_handler_win.cc",
"run_as_crashpad_handler_win.h",
]
@@ -103,6 +117,7 @@ if (is_win) {
"//third_party/crashpad/crashpad/client",
"//third_party/crashpad/crashpad/handler",
"//third_party/crashpad/crashpad/minidump",
+ "//third_party/crashpad/crashpad/util",
]
}
diff --git a/chromium/components/crash/content/app/breakpad_linux.cc b/chromium/components/crash/content/app/breakpad_linux.cc
index c72cd3622b8..460f7ac4def 100644
--- a/chromium/components/crash/content/app/breakpad_linux.cc
+++ b/chromium/components/crash/content/app/breakpad_linux.cc
@@ -556,16 +556,20 @@ void CrashReporterWriter::AddFileContents(const char* filename_msg,
#if defined(OS_ANDROID)
// Writes the "package" field, which is in the format:
-// $PACKAGE_NAME v$VERSION_CODE ($VERSION_NAME)
+// $FIREBASE_APP_ID v$VERSION_CODE ($VERSION_NAME)
void WriteAndroidPackage(MimeWriter& writer,
base::android::BuildInfo* android_build_info) {
+ // Don't write the field if no Firebase ID is set.
+ if (android_build_info->firebase_app_id()[0] == '\0') {
+ return;
+ }
// The actual size limits on packageId and versionName are quite generous.
// Limit to a reasonable size rather than allocating theoretical limits.
const int kMaxSize = 1024;
char buf[kMaxSize];
// Not using sprintf to ensure no heap allocations.
- my_strlcpy(buf, android_build_info->package_name(), kMaxSize);
+ my_strlcpy(buf, android_build_info->firebase_app_id(), kMaxSize);
my_strlcat(buf, " v", kMaxSize);
my_strlcat(buf, android_build_info->package_version_code(), kMaxSize);
my_strlcat(buf, " (", kMaxSize);
diff --git a/chromium/components/crash/content/app/breakpad_win.cc b/chromium/components/crash/content/app/breakpad_win.cc
index dd3cab653f5..47cce0d451f 100644
--- a/chromium/components/crash/content/app/breakpad_win.cc
+++ b/chromium/components/crash/content/app/breakpad_win.cc
@@ -4,12 +4,13 @@
#include "components/crash/content/app/breakpad_win.h"
-#include <windows.h>
+#include <crtdbg.h>
#include <intrin.h>
#include <shellapi.h>
#include <stddef.h>
#include <tchar.h>
#include <userenv.h>
+#include <windows.h>
#include <winnt.h>
#include <algorithm>
diff --git a/chromium/components/crash/content/app/crash_export_stubs.cc b/chromium/components/crash/content/app/crash_export_stubs.cc
index 462b5d8bfba..3ff51649906 100644
--- a/chromium/components/crash/content/app/crash_export_stubs.cc
+++ b/chromium/components/crash/content/app/crash_export_stubs.cc
@@ -31,6 +31,15 @@ HANDLE InjectDumpForHungInput_ExportThunk(HANDLE process) {
return nullptr;
}
+const wchar_t* GetCrashpadDatabasePath_ExportThunk() {
+ return nullptr;
+}
+
+bool DumpHungProcessWithPtype_ExportThunk(HANDLE process_handle,
+ const char* ptype) {
+ return false;
+}
+
#if defined(ARCH_CPU_X86_64)
void RegisterNonABICompliantCodeRange_ExportThunk(void* start,
diff --git a/chromium/components/crash/content/app/crash_export_thunks.cc b/chromium/components/crash/content/app/crash_export_thunks.cc
index ea2ffdacda9..5a4e3f1781d 100644
--- a/chromium/components/crash/content/app/crash_export_thunks.cc
+++ b/chromium/components/crash/content/app/crash_export_thunks.cc
@@ -7,10 +7,12 @@
#include <algorithm>
#include <type_traits>
+#include "base/process/process.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/crash/content/app/crashpad.h"
+#include "components/crash/content/app/dump_hung_process_with_ptype.h"
#include "third_party/crashpad/crashpad/client/crashpad_client.h"
void RequestSingleCrashUpload_ExportThunk(const char* local_id) {
@@ -60,6 +62,17 @@ HANDLE InjectDumpForHungInput_ExportThunk(HANDLE process) {
nullptr);
}
+const wchar_t* GetCrashpadDatabasePath_ExportThunk() {
+ return crash_reporter::GetCrashpadDatabasePathImpl();
+}
+
+bool DumpHungProcessWithPtype_ExportThunk(HANDLE process_handle,
+ const char* ptype) {
+ base::Process process(process_handle);
+
+ return crash_reporter::DumpHungProcessWithPtypeImpl(process, ptype);
+}
+
#if defined(ARCH_CPU_X86_64)
void RegisterNonABICompliantCodeRange_ExportThunk(void* start,
diff --git a/chromium/components/crash/content/app/crash_export_thunks.h b/chromium/components/crash/content/app/crash_export_thunks.h
index 43d0a4eae34..e676e8ccc01 100644
--- a/chromium/components/crash/content/app/crash_export_thunks.h
+++ b/chromium/components/crash/content/app/crash_export_thunks.h
@@ -55,6 +55,14 @@ void SetUploadConsent_ExportThunk(bool consent);
// This method is used solely to classify hung input.
HANDLE InjectDumpForHungInput_ExportThunk(HANDLE process);
+// Returns the crashpad database path.
+const wchar_t* GetCrashpadDatabasePath_ExportThunk();
+
+// Immediately dump |process| to a crash dump adorned with |ptype|.
+// Takes ownership of |process|, does not kill nor affect the exit code of
+// |process|.
+bool DumpHungProcessWithPtype_ExportThunk(HANDLE process, const char* ptype);
+
#if defined(ARCH_CPU_X86_64)
// V8 support functions.
void RegisterNonABICompliantCodeRange_ExportThunk(void* start,
diff --git a/chromium/components/crash/content/app/crashpad.cc b/chromium/components/crash/content/app/crashpad.cc
index dde11eab445..36ff7c219ad 100644
--- a/chromium/components/crash/content/app/crashpad.cc
+++ b/chromium/components/crash/content/app/crashpad.cc
@@ -46,6 +46,8 @@ namespace crash_reporter {
namespace {
+base::FilePath* g_database_path;
+
crashpad::CrashReportDatabase* g_database;
bool LogMessageHandler(int severity,
@@ -87,6 +89,13 @@ bool LogMessageHandler(int severity,
return false;
}
+void InitializeDatabasePath(const base::FilePath& database_path) {
+ DCHECK(!g_database_path);
+
+ // Intentionally leaked.
+ g_database_path = new base::FilePath(database_path);
+}
+
void InitializeCrashpadImpl(bool initial_client,
const std::string& process_type,
const std::string& user_data_dir,
@@ -172,6 +181,8 @@ void InitializeCrashpadImpl(bool initial_client,
const bool should_initialize_database_and_set_upload_policy = initial_client;
#endif
if (should_initialize_database_and_set_upload_policy) {
+ InitializeDatabasePath(database_path);
+
g_database =
crashpad::CrashReportDatabase::Initialize(database_path).release();
@@ -275,6 +286,14 @@ void RequestSingleCrashUpload(const std::string& local_id) {
#endif
}
+base::FilePath GetCrashpadDatabasePath() {
+#if defined(OS_WIN)
+ return base::FilePath(GetCrashpadDatabasePath_ExportThunk());
+#else
+ return base::FilePath(GetCrashpadDatabasePathImpl());
+#endif
+}
+
void GetReportsImpl(std::vector<Report>* reports) {
reports->clear();
@@ -343,4 +362,11 @@ void RequestSingleCrashUploadImpl(const std::string& local_id) {
g_database->RequestUpload(uuid);
}
+base::FilePath::StringType::const_pointer GetCrashpadDatabasePathImpl() {
+ if (!g_database_path)
+ return nullptr;
+
+ return g_database_path->value().c_str();
+}
+
} // namespace crash_reporter
diff --git a/chromium/components/crash/content/app/crashpad.h b/chromium/components/crash/content/app/crashpad.h
index b77e1cc88d5..e4774815893 100644
--- a/chromium/components/crash/content/app/crashpad.h
+++ b/chromium/components/crash/content/app/crashpad.h
@@ -114,12 +114,18 @@ void RequestSingleCrashUpload(const std::string& local_id);
void DumpWithoutCrashing();
+// Returns the Crashpad database path, only valid in the browser.
+base::FilePath GetCrashpadDatabasePath();
+
// The implementation function for GetReports.
void GetReportsImpl(std::vector<Report>* reports);
// The implementation function for RequestSingleCrashUpload.
void RequestSingleCrashUploadImpl(const std::string& local_id);
+// The implementation function for GetCrashpadDatabasePath.
+base::FilePath::StringType::const_pointer GetCrashpadDatabasePathImpl();
+
namespace internal {
#if defined(OS_WIN)
diff --git a/chromium/components/crash/content/app/dump_hung_process_with_ptype.cc b/chromium/components/crash/content/app/dump_hung_process_with_ptype.cc
new file mode 100644
index 00000000000..5112ad9b871
--- /dev/null
+++ b/chromium/components/crash/content/app/dump_hung_process_with_ptype.cc
@@ -0,0 +1,56 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/crash/content/app/minidump_with_crashpad_info.h"
+
+#include "base/files/file_util.h"
+#include "components/crash/content/app/crash_export_thunks.h"
+#include "components/crash/content/app/crash_reporter_client.h"
+#include "components/crash/content/app/crashpad.h"
+#include "third_party/crashpad/crashpad/client/crash_report_database.h"
+#include "third_party/crashpad/crashpad/client/crashpad_info.h"
+#include "third_party/crashpad/crashpad/client/settings.h"
+#include "third_party/crashpad/crashpad/minidump/minidump_extensions.h"
+
+namespace crash_reporter {
+
+bool DumpHungProcessWithPtype(const base::Process& process, const char* ptype) {
+ // We need to pass a handle across the export thunk, which takes ownership
+ // of it.
+ HANDLE process_handle = nullptr;
+ if (!::DuplicateHandle(::GetCurrentProcess(), process.Handle(),
+ ::GetCurrentProcess(), &process_handle, 0, FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ return false;
+ }
+
+ return DumpHungProcessWithPtype_ExportThunk(process_handle, ptype);
+}
+
+bool DumpHungProcessWithPtypeImpl(const base::Process& process,
+ const char* ptype) {
+ // Get annotations on the crash report to set the product name, version,
+ // channel and so forth to what's appropriate for this process.
+ StringStringMap annotations;
+ internal::GetPlatformCrashpadAnnotations(&annotations);
+
+ // Override the process type, as this is dumping |process| rather than this
+ // process.
+ annotations["ptype"] = ptype;
+
+ uint32_t minidump_type = MiniDumpWithUnloadedModules |
+ MiniDumpWithProcessThreadData |
+ MiniDumpWithFullMemoryInfo | MiniDumpWithThreadInfo;
+
+ // Capture more detail for canary and dev channels. The prefix search caters
+ // for the soon to be outdated "-m" suffixed multi-install channels.
+ std::string channel_name = annotations["channel"];
+ if (channel_name.find("canary") == 0 || channel_name.find("dev") == 0)
+ minidump_type |= MiniDumpWithIndirectlyReferencedMemory;
+
+ return DumpAndReportProcess(process, minidump_type, nullptr, annotations,
+ crash_reporter::GetCrashpadDatabasePath());
+}
+
+} // namespace crash_reporter
diff --git a/chromium/components/crash/content/app/dump_hung_process_with_ptype.h b/chromium/components/crash/content/app/dump_hung_process_with_ptype.h
new file mode 100644
index 00000000000..8eff4bb5f65
--- /dev/null
+++ b/chromium/components/crash/content/app/dump_hung_process_with_ptype.h
@@ -0,0 +1,23 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CRASH_CONTENT_APP_DUMP_HUNG_PROCESS_WITH_PTYPE_H_
+#define COMPONENTS_CRASH_CONTENT_APP_DUMP_HUNG_PROCESS_WITH_PTYPE_H_
+
+#include "base/process/process.h"
+
+namespace crash_reporter {
+
+// Captures a crash dump for |process|, which is assumed to be hung, to the
+// crashpad database. Annotates the crash with suitable annotations, plus a
+// "ptype" annotation set to |ptype|.
+bool DumpHungProcessWithPtype(const base::Process& process, const char* ptype);
+
+// Implementation function for the above, hosted inside chrome_elf.dll.
+bool DumpHungProcessWithPtypeImpl(const base::Process& process,
+ const char* ptype);
+
+} // namespace crash_reporter
+
+#endif // COMPONENTS_CRASH_CONTENT_APP_DUMP_HUNG_PROCESS_WITH_PTYPE_H_
diff --git a/chromium/components/crash/content/app/fallback_crash_handler_win.cc b/chromium/components/crash/content/app/fallback_crash_handler_win.cc
index a57ea77a93a..c04570dae6a 100644
--- a/chromium/components/crash/content/app/fallback_crash_handler_win.cc
+++ b/chromium/components/crash/content/app/fallback_crash_handler_win.cc
@@ -15,26 +15,18 @@
#include "base/command_line.h"
#include "base/files/file.h"
-#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/process/process_handle.h"
#include "base/strings/string_number_conversions.h"
#include "base/win/scoped_handle.h"
#include "base/win/win_util.h"
-#include "third_party/crashpad/crashpad/client/crash_report_database.h"
-#include "third_party/crashpad/crashpad/client/settings.h"
-#include "third_party/crashpad/crashpad/minidump/minidump_extensions.h"
+#include "components/crash/content/app/minidump_with_crashpad_info.h"
namespace crash_reporter {
namespace {
-using FilePosition = uint32_t;
-const FilePosition kInvalidFilePos = static_cast<FilePosition>(-1);
-
-using StringStringMap = std::map<std::string, std::string>;
-
void AcquireMemoryMetrics(const base::Process& process,
StringStringMap* crash_keys) {
// Grab the process private memory.
@@ -73,299 +65,6 @@ void AcquireMemoryMetrics(const base::Process& process,
}
}
-// This class is a helper to edit minidump files written by MiniDumpWriteDump.
-// It assumes the minidump file it operates on has a directory entry pointing to
-// a CrashpadInfo entry, which it updates to point to the SimpleDictionary data
-// it appends to the file contents.
-class MinidumpUpdater {
- public:
- MinidumpUpdater();
-
- // Reads the existing directory from |file|.
- bool Initialize(base::File* file);
-
- // Appends the simple dictionary with |crash_keys| to the file, and updates
- // the CrashpadInfo with its location.
- bool AppendSimpleDictionary(const StringStringMap& crash_keys);
-
- private:
- // Writes |data_len| bytes from |data| to the file at the current location.
- bool WriteData(const void* data, size_t data_len);
- bool WriteAndAdvance(const void* data,
- size_t data_len,
- FilePosition* position);
-
- base::File* file_;
- std::vector<MINIDUMP_DIRECTORY> directory_;
-
- DISALLOW_COPY_AND_ASSIGN(MinidumpUpdater);
-};
-
-MinidumpUpdater::MinidumpUpdater() : file_(nullptr) {}
-
-bool MinidumpUpdater::Initialize(base::File* file) {
- DCHECK(file && file->IsValid());
- DCHECK(!file_);
-
- // Read the file header.
- MINIDUMP_HEADER header = {};
- int bytes_read =
- file->Read(0, reinterpret_cast<char*>(&header), sizeof(header));
- if (bytes_read != sizeof(header))
- return false;
- if (header.Signature != MINIDUMP_SIGNATURE || header.NumberOfStreams == 0)
- return false;
-
- // Read the stream directory.
- directory_.resize(header.NumberOfStreams);
- int bytes_to_read = header.NumberOfStreams * sizeof(directory_[0]);
- bytes_read =
- file->Read(header.StreamDirectoryRva,
- reinterpret_cast<char*>(&directory_[0]), bytes_to_read);
- if (bytes_read != bytes_to_read)
- return false;
-
- // Crashpad has some fairly unreasonable checking on the minidump header and
- // directory. Match with those checks for now to allow Crashpad to read the
- // CrashpadInfo and upload these dumps.
-
- // Start by removing any unused directory entries.
- // TODO(siggi): Fix Crashpad to ignore unused streams.
- directory_.erase(std::remove_if(directory_.begin(), directory_.end(),
- [](const MINIDUMP_DIRECTORY& entry) {
- return entry.StreamType == UnusedStream;
- }),
- directory_.end());
-
- // Update the header.
- // TODO(siggi): Fix Crashpad's version checking.
- header.Version = MINIDUMP_VERSION;
- header.NumberOfStreams = base::saturated_cast<ULONG32>(directory_.size());
-
- // Write back the potentially shortened and packed dictionary.
- int bytes_to_write = header.NumberOfStreams * sizeof(directory_[0]);
- int bytes_written = file->Write(header.StreamDirectoryRva,
- reinterpret_cast<const char*>(&directory_[0]),
- bytes_to_write);
- if (bytes_written != bytes_to_write)
- return false;
-
- // Write back the header.
- bytes_written =
- file->Write(0, reinterpret_cast<const char*>(&header), sizeof(header));
- if (bytes_written != sizeof(header))
- return false;
-
- // Success, stash the file.
- file_ = file;
-
- return true;
-}
-
-bool MinidumpUpdater::AppendSimpleDictionary(
- const StringStringMap& crash_keys) {
- DCHECK(file_);
-
- // Start by finding the Crashpad directory entry and reading the CrashpadInfo.
- FilePosition crashpad_info_pos = 0;
- crashpad::MinidumpCrashpadInfo crashpad_info;
- for (const auto& entry : directory_) {
- if (entry.StreamType == crashpad::kMinidumpStreamTypeCrashpadInfo) {
- // This file is freshly written, so it must contain the same version
- // CrashpadInfo structure this code compiled against.
- if (entry.Location.DataSize != sizeof(crashpad_info))
- return false;
-
- crashpad_info_pos = entry.Location.Rva;
- break;
- }
- }
-
- // No CrashpadInfo directory entry found.
- if (crashpad_info_pos == 0)
- return false;
-
- int bytes_read =
- file_->Read(crashpad_info_pos, reinterpret_cast<char*>(&crashpad_info),
- sizeof(crashpad_info));
- if (bytes_read != sizeof(crashpad_info))
- return false;
-
- if (crashpad_info.version != crashpad::MinidumpCrashpadInfo::kVersion)
- return false;
-
- // Seek to the tail of the file, where we're going to extend it.
- FilePosition next_available_byte = file_->Seek(base::File::FROM_END, 0);
- if (next_available_byte == kInvalidFilePos)
- return false;
-
- // Write the key/value pairs and collect their locations.
- std::vector<crashpad::MinidumpSimpleStringDictionaryEntry> entries;
- for (const auto& kv : crash_keys) {
- // The key of a key/value pair should never be empty.
- DCHECK(!kv.first.empty());
-
- crashpad::MinidumpSimpleStringDictionaryEntry entry = {0};
-
- // Skip this key/value if the value is empty.
- if (!kv.second.empty()) {
- entry.key = next_available_byte;
- uint32_t key_len = base::saturated_cast<uint32_t>(kv.first.size());
- if (!WriteAndAdvance(&key_len, sizeof(key_len), &next_available_byte) ||
- !WriteAndAdvance(&kv.first[0], key_len, &next_available_byte)) {
- return false;
- }
-
- entry.value = next_available_byte;
- uint32_t value_len = base::saturated_cast<uint32_t>(kv.second.size());
- if (!WriteAndAdvance(&value_len, sizeof(value_len),
- &next_available_byte) ||
- !WriteAndAdvance(&kv.second[0], value_len, &next_available_byte)) {
- return false;
- }
-
- entries.push_back(entry);
- }
- }
-
- // Write the dictionary array itself - note the array is count-prefixed.
- FilePosition dict_pos = next_available_byte;
- uint32_t entry_count = base::saturated_cast<uint32_t>(entries.size());
- if (!WriteAndAdvance(&entry_count, sizeof(entry_count),
- &next_available_byte) ||
- !WriteAndAdvance(&entries[0], entry_count * sizeof(entries[0]),
- &next_available_byte)) {
- return false;
- }
-
- // Touch up the CrashpadInfo and write it back to the file.
- crashpad_info.simple_annotations.DataSize = next_available_byte - dict_pos;
- crashpad_info.simple_annotations.Rva = dict_pos;
-
- int bytes_written = file_->Write(
- crashpad_info_pos, reinterpret_cast<const char*>(&crashpad_info),
- sizeof(crashpad_info));
- if (bytes_written != sizeof(crashpad_info))
- return false;
-
- return true;
-}
-
-bool MinidumpUpdater::WriteData(const void* data, size_t data_len) {
- DCHECK(file_);
- DCHECK(data);
- DCHECK_NE(0U, data_len);
-
- if (data_len > INT_MAX)
- return false;
-
- int bytes_to_write = static_cast<int>(data_len);
- int written_bytes = file_->WriteAtCurrentPos(
- reinterpret_cast<const char*>(data), bytes_to_write);
- if (written_bytes == -1)
- return false;
-
- return true;
-}
-
-bool MinidumpUpdater::WriteAndAdvance(const void* data,
- size_t data_len,
- FilePosition* position) {
- DCHECK(position);
- DCHECK_EQ(file_->Seek(base::File::FROM_CURRENT, 0), *position);
-
- if (!WriteData(data, data_len))
- return false;
-
- *position += base::saturated_cast<FilePosition>(data_len);
- return true;
-}
-
-// Writes a minidump file for |process| to |dump_file| with embedded
-// CrashpadInfo, containing |crash_keys|, |client_id| and |report_id|.
-// The |dump_file| must be open for read as well as write.
-bool MiniDumpWriteDumpWithCrashpadInfo(const base::Process& process,
- uint32_t minidump_type,
- MINIDUMP_EXCEPTION_INFORMATION* exc_info,
- const StringStringMap& crash_keys,
- const crashpad::UUID& client_id,
- const crashpad::UUID& report_id,
- base::File* dump_file) {
- DCHECK(process.IsValid());
- DCHECK(exc_info);
- DCHECK(dump_file && dump_file->IsValid());
-
- // The CrashpadInfo structure and its associated directory entry are injected
- // into the minidump, to minimize the work to patching up the dump.
- crashpad::MinidumpCrashpadInfo crashpad_info;
- crashpad_info.version = crashpad::MinidumpCrashpadInfo::kVersion;
- crashpad_info.client_id = client_id;
- crashpad_info.report_id = report_id;
-
- MINIDUMP_USER_STREAM crashpad_info_stream = {
- crashpad::kMinidumpStreamTypeCrashpadInfo, // Type
- sizeof(crashpad_info), // BufferSize
- &crashpad_info // Buffer
- };
- MINIDUMP_USER_STREAM_INFORMATION user_stream_info = {
- 1, // UserStreamCount
- &crashpad_info_stream // UserStreamArray
- };
-
- // Write the minidump to the provided dump file.
- if (!MiniDumpWriteDump(
- process.Handle(), // Process handle.
- process.Pid(), // Process Id.
- dump_file->GetPlatformFile(), // File handle.
- static_cast<MINIDUMP_TYPE>(minidump_type), // Minidump type.
- exc_info, // Exception Param
- &user_stream_info, // UserStreamParam,
- nullptr)) { // CallbackParam
- return false;
- }
-
- // Retouch the minidump to make it Crashpad compatible.
- MinidumpUpdater updater;
- if (!updater.Initialize(dump_file))
- return false;
- if (!updater.AppendSimpleDictionary(crash_keys))
- return false;
-
- return true;
-}
-
-// Appends the full contents of |source| to |dest| from the current position
-// of |dest|.
-bool AppendFileContents(base::File* source, base::PlatformFile dest) {
- DCHECK(source && source->IsValid());
- DCHECK_NE(base::kInvalidPlatformFile, dest);
-
- // Rewind the source.
- if (source->Seek(base::File::FROM_BEGIN, 0) == kInvalidFilePos)
- return false;
-
- std::vector<char> buf;
- buf.resize(1024);
- while (true) {
- int bytes_read =
- source->ReadAtCurrentPos(&buf[0], static_cast<int>(buf.size()));
- if (bytes_read == -1)
- return false;
- if (bytes_read == 0)
- break;
-
- DWORD bytes_written = 0;
- // Due to handle instrumentation, the destination can't be wrapped in
- // a base::File, so we go basic Win32 API here.
- if (!WriteFile(dest, &buf[0], bytes_read, &bytes_written, nullptr) ||
- static_cast<int>(bytes_written) != bytes_read) {
- return false;
- }
- }
-
- return true;
-}
-
} // namespace
FallbackCrashHandler::FallbackCrashHandler()
@@ -417,22 +116,6 @@ bool FallbackCrashHandler::GenerateCrashDump(const std::string& product,
const std::string& version,
const std::string& channel,
const std::string& process_type) {
- std::unique_ptr<crashpad::CrashReportDatabase> database =
- crashpad::CrashReportDatabase::InitializeWithoutCreating(database_dir_);
-
- if (!database)
- return false;
-
- crashpad::CrashReportDatabase::NewReport* report = nullptr;
- crashpad::CrashReportDatabase::OperationStatus status =
- database->PrepareNewCrashReport(&report);
- if (status != crashpad::CrashReportDatabase::kNoError)
- return false;
-
- // Make sure we release the report on early exit.
- crashpad::CrashReportDatabase::CallErrorWritingCrashReport on_error(
- database.get(), report);
-
MINIDUMP_EXCEPTION_INFORMATION exc_info = {};
exc_info.ThreadId = thread_id_;
exc_info.ExceptionPointers =
@@ -456,27 +139,6 @@ bool FallbackCrashHandler::GenerateCrashDump(const std::string& product,
// Add memory metrics relating to system-wide and target process memory usage.
AcquireMemoryMetrics(process_, &crash_keys);
- crashpad::UUID client_id;
- crashpad::Settings* settings = database->GetSettings();
- if (settings) {
- // If GetSettings() or GetClientID() fails client_id will be left at its
- // default value, all zeroes, which is appropriate.
- settings->GetClientID(&client_id);
- }
-
- base::FilePath dump_file_path;
- if (!base::CreateTemporaryFile(&dump_file_path))
- return false;
-
- // Open the file with delete on close, to try and ensure it's cleaned up on
- // any kind of failure.
- base::File dump_file(dump_file_path, base::File::FLAG_OPEN |
- base::File::FLAG_READ |
- base::File::FLAG_WRITE |
- base::File::FLAG_DELETE_ON_CLOSE);
- if (!dump_file.IsValid())
- return false;
-
uint32_t minidump_type = MiniDumpWithUnloadedModules |
MiniDumpWithProcessThreadData |
MiniDumpWithFullMemoryInfo |
@@ -487,23 +149,8 @@ bool FallbackCrashHandler::GenerateCrashDump(const std::string& product,
if (channel.find("canary") == 0 || channel.find("dev") == 0)
minidump_type |= MiniDumpWithIndirectlyReferencedMemory;
- // Write the minidump to the temp file, and then copy the data to the
- // Crashpad-provided handle, as the latter is only open for write.
- if (!MiniDumpWriteDumpWithCrashpadInfo(process_, minidump_type, &exc_info,
- crash_keys, client_id, report->uuid,
- &dump_file) ||
- !AppendFileContents(&dump_file, report->handle)) {
- return false;
- }
-
- on_error.Disarm();
-
- crashpad::UUID report_id = {};
- status = database->FinishedWritingCrashReport(report, &report_id);
- if (status != crashpad::CrashReportDatabase::kNoError)
- return false;
-
- return true;
+ return DumpAndReportProcess(process_, minidump_type, &exc_info, crash_keys,
+ database_dir_);
}
} // namespace crash_reporter
diff --git a/chromium/components/crash/content/app/minidump_with_crashpad_info.cc b/chromium/components/crash/content/app/minidump_with_crashpad_info.cc
new file mode 100644
index 00000000000..a6ee276403f
--- /dev/null
+++ b/chromium/components/crash/content/app/minidump_with_crashpad_info.cc
@@ -0,0 +1,376 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/crash/content/app/minidump_with_crashpad_info.h"
+
+#include "base/files/file_util.h"
+#include "third_party/crashpad/crashpad/client/crash_report_database.h"
+#include "third_party/crashpad/crashpad/client/crashpad_info.h"
+#include "third_party/crashpad/crashpad/client/settings.h"
+#include "third_party/crashpad/crashpad/minidump/minidump_extensions.h"
+
+namespace crash_reporter {
+
+namespace {
+
+using FilePosition = uint32_t;
+const FilePosition kInvalidFilePos = static_cast<FilePosition>(-1);
+
+// This class is a helper to edit minidump files written by MiniDumpWriteDump.
+// It assumes the minidump file it operates on has a directory entry pointing to
+// a CrashpadInfo entry, which it updates to point to the SimpleDictionary data
+// it appends to the file contents.
+class MinidumpUpdater {
+ public:
+ MinidumpUpdater();
+
+ // Reads the existing directory from |file|.
+ bool Initialize(base::File* file);
+
+ // Appends the simple dictionary with |crash_keys| to the file, and updates
+ // the CrashpadInfo with its location.
+ bool AppendSimpleDictionary(const StringStringMap& crash_keys);
+
+ private:
+ // Writes |data_len| bytes from |data| to the file at the current location.
+ bool WriteData(const void* data, size_t data_len);
+ bool WriteAndAdvance(const void* data,
+ size_t data_len,
+ FilePosition* position);
+
+ base::File* file_;
+ std::vector<MINIDUMP_DIRECTORY> directory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpUpdater);
+};
+
+MinidumpUpdater::MinidumpUpdater() : file_(nullptr) {}
+
+bool MinidumpUpdater::Initialize(base::File* file) {
+ DCHECK(file && file->IsValid());
+ DCHECK(!file_);
+
+ // Read the file header.
+ MINIDUMP_HEADER header = {};
+ int bytes_read =
+ file->Read(0, reinterpret_cast<char*>(&header), sizeof(header));
+ if (bytes_read != sizeof(header))
+ return false;
+ if (header.Signature != MINIDUMP_SIGNATURE || header.NumberOfStreams == 0)
+ return false;
+
+ // Read the stream directory.
+ directory_.resize(header.NumberOfStreams);
+ int bytes_to_read = header.NumberOfStreams * sizeof(directory_[0]);
+ bytes_read =
+ file->Read(header.StreamDirectoryRva,
+ reinterpret_cast<char*>(&directory_[0]), bytes_to_read);
+ if (bytes_read != bytes_to_read)
+ return false;
+
+ // Crashpad has some fairly unreasonable checking on the minidump header and
+ // directory. Match with those checks for now to allow Crashpad to read the
+ // CrashpadInfo and upload these dumps.
+
+ // Start by removing any unused directory entries.
+ // TODO(siggi): Fix Crashpad to ignore unused streams.
+ directory_.erase(std::remove_if(directory_.begin(), directory_.end(),
+ [](const MINIDUMP_DIRECTORY& entry) {
+ return entry.StreamType == UnusedStream;
+ }),
+ directory_.end());
+
+ // Update the header.
+ // TODO(siggi): Fix Crashpad's version checking.
+ header.Version = MINIDUMP_VERSION;
+ header.NumberOfStreams = base::saturated_cast<ULONG32>(directory_.size());
+
+ // Write back the potentially shortened and packed dictionary.
+ int bytes_to_write = header.NumberOfStreams * sizeof(directory_[0]);
+ int bytes_written = file->Write(header.StreamDirectoryRva,
+ reinterpret_cast<const char*>(&directory_[0]),
+ bytes_to_write);
+ if (bytes_written != bytes_to_write)
+ return false;
+
+ // Write back the header.
+ bytes_written =
+ file->Write(0, reinterpret_cast<const char*>(&header), sizeof(header));
+ if (bytes_written != sizeof(header))
+ return false;
+
+ // Success, stash the file.
+ file_ = file;
+
+ return true;
+}
+
+bool MinidumpUpdater::AppendSimpleDictionary(
+ const StringStringMap& crash_keys) {
+ DCHECK(file_);
+
+ // Start by finding the Crashpad directory entry and reading the CrashpadInfo.
+ FilePosition crashpad_info_pos = 0;
+ crashpad::MinidumpCrashpadInfo crashpad_info;
+ for (const auto& entry : directory_) {
+ if (entry.StreamType == crashpad::kMinidumpStreamTypeCrashpadInfo) {
+ // This file is freshly written, so it must contain the same version
+ // CrashpadInfo structure this code compiled against.
+ if (entry.Location.DataSize != sizeof(crashpad_info))
+ return false;
+
+ crashpad_info_pos = entry.Location.Rva;
+ break;
+ }
+ }
+
+ // No CrashpadInfo directory entry found.
+ if (crashpad_info_pos == 0)
+ return false;
+
+ int bytes_read =
+ file_->Read(crashpad_info_pos, reinterpret_cast<char*>(&crashpad_info),
+ sizeof(crashpad_info));
+ if (bytes_read != sizeof(crashpad_info))
+ return false;
+
+ if (crashpad_info.version != crashpad::MinidumpCrashpadInfo::kVersion)
+ return false;
+
+ // Seek to the tail of the file, where we're going to extend it.
+ FilePosition next_available_byte = file_->Seek(base::File::FROM_END, 0);
+ if (next_available_byte == kInvalidFilePos)
+ return false;
+
+ // Write the key/value pairs and collect their locations.
+ std::vector<crashpad::MinidumpSimpleStringDictionaryEntry> entries;
+ for (const auto& kv : crash_keys) {
+ // The key of a key/value pair should never be empty.
+ DCHECK(!kv.first.empty());
+
+ crashpad::MinidumpSimpleStringDictionaryEntry entry = {0};
+
+ // Skip this key/value if the value is empty.
+ if (!kv.second.empty()) {
+ entry.key = next_available_byte;
+ uint32_t key_len = base::saturated_cast<uint32_t>(kv.first.size());
+ if (!WriteAndAdvance(&key_len, sizeof(key_len), &next_available_byte) ||
+ !WriteAndAdvance(&kv.first[0], key_len, &next_available_byte)) {
+ return false;
+ }
+
+ entry.value = next_available_byte;
+ uint32_t value_len = base::saturated_cast<uint32_t>(kv.second.size());
+ if (!WriteAndAdvance(&value_len, sizeof(value_len),
+ &next_available_byte) ||
+ !WriteAndAdvance(&kv.second[0], value_len, &next_available_byte)) {
+ return false;
+ }
+
+ entries.push_back(entry);
+ }
+ }
+
+ // Write the dictionary array itself - note the array is count-prefixed.
+ FilePosition dict_pos = next_available_byte;
+ uint32_t entry_count = base::saturated_cast<uint32_t>(entries.size());
+ if (!WriteAndAdvance(&entry_count, sizeof(entry_count),
+ &next_available_byte) ||
+ !WriteAndAdvance(&entries[0], entry_count * sizeof(entries[0]),
+ &next_available_byte)) {
+ return false;
+ }
+
+ // Touch up the CrashpadInfo and write it back to the file.
+ crashpad_info.simple_annotations.DataSize = next_available_byte - dict_pos;
+ crashpad_info.simple_annotations.Rva = dict_pos;
+
+ int bytes_written = file_->Write(
+ crashpad_info_pos, reinterpret_cast<const char*>(&crashpad_info),
+ sizeof(crashpad_info));
+ if (bytes_written != sizeof(crashpad_info))
+ return false;
+
+ return true;
+}
+
+bool MinidumpUpdater::WriteData(const void* data, size_t data_len) {
+ DCHECK(file_);
+ DCHECK(data);
+ DCHECK_NE(0U, data_len);
+
+ if (data_len > INT_MAX)
+ return false;
+
+ int bytes_to_write = static_cast<int>(data_len);
+ int written_bytes = file_->WriteAtCurrentPos(
+ reinterpret_cast<const char*>(data), bytes_to_write);
+ if (written_bytes == -1)
+ return false;
+
+ return true;
+}
+
+bool MinidumpUpdater::WriteAndAdvance(const void* data,
+ size_t data_len,
+ FilePosition* position) {
+ DCHECK(position);
+ DCHECK_EQ(file_->Seek(base::File::FROM_CURRENT, 0), *position);
+
+ if (!WriteData(data, data_len))
+ return false;
+
+ *position += base::saturated_cast<FilePosition>(data_len);
+ return true;
+}
+
+// Writes a minidump file for |process| to |dump_file| with embedded
+// CrashpadInfo, containing |crash_keys|, |client_id| and |report_id|.
+// The |dump_file| must be open for read as well as write.
+bool MiniDumpWriteDumpWithCrashpadInfo(const base::Process& process,
+ uint32_t minidump_type,
+ MINIDUMP_EXCEPTION_INFORMATION* exc_info,
+ const StringStringMap& crash_keys,
+ const crashpad::UUID& client_id,
+ const crashpad::UUID& report_id,
+ base::File* dump_file) {
+ DCHECK(process.IsValid());
+ DCHECK(dump_file && dump_file->IsValid());
+
+ // The CrashpadInfo structure and its associated directory entry are injected
+ // into the minidump, to minimize the work to patching up the dump.
+ crashpad::MinidumpCrashpadInfo crashpad_info;
+ crashpad_info.version = crashpad::MinidumpCrashpadInfo::kVersion;
+ crashpad_info.client_id = client_id;
+ crashpad_info.report_id = report_id;
+
+ MINIDUMP_USER_STREAM crashpad_info_stream = {
+ crashpad::kMinidumpStreamTypeCrashpadInfo, // Type
+ sizeof(crashpad_info), // BufferSize
+ &crashpad_info // Buffer
+ };
+ MINIDUMP_USER_STREAM_INFORMATION user_stream_info = {
+ 1, // UserStreamCount
+ &crashpad_info_stream // UserStreamArray
+ };
+
+ // Write the minidump to the provided dump file.
+ if (!MiniDumpWriteDump(
+ process.Handle(), // Process handle.
+ process.Pid(), // Process Id.
+ dump_file->GetPlatformFile(), // File handle.
+ static_cast<MINIDUMP_TYPE>(minidump_type), // Minidump type.
+ exc_info, // Exception Param
+ &user_stream_info, // UserStreamParam,
+ nullptr)) { // CallbackParam
+ return false;
+ }
+
+ // Retouch the minidump to make it Crashpad compatible.
+ MinidumpUpdater updater;
+ if (!updater.Initialize(dump_file))
+ return false;
+ if (!updater.AppendSimpleDictionary(crash_keys))
+ return false;
+
+ return true;
+}
+
+// Appends the full contents of |source| to |dest| from the current position
+// of |dest|.
+bool AppendFileContents(base::File* source, base::PlatformFile dest) {
+ DCHECK(source && source->IsValid());
+ DCHECK_NE(base::kInvalidPlatformFile, dest);
+
+ // Rewind the source.
+ if (source->Seek(base::File::FROM_BEGIN, 0) == -1)
+ return false;
+
+ std::vector<char> buf;
+ buf.resize(1024);
+ while (true) {
+ int bytes_read =
+ source->ReadAtCurrentPos(&buf[0], static_cast<int>(buf.size()));
+ if (bytes_read == -1)
+ return false;
+ if (bytes_read == 0)
+ break;
+
+ DWORD bytes_written = 0;
+ // Due to handle instrumentation, the destination can't be wrapped in
+ // a base::File, so we go basic Win32 API here.
+ if (!WriteFile(dest, &buf[0], bytes_read, &bytes_written, nullptr) ||
+ static_cast<int>(bytes_written) != bytes_read) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace
+
+bool DumpAndReportProcess(const base::Process& process,
+ uint32_t minidump_type,
+ MINIDUMP_EXCEPTION_INFORMATION* exc_info,
+ const StringStringMap& crash_keys,
+ const base::FilePath& crashpad_database_path) {
+ std::unique_ptr<crashpad::CrashReportDatabase> database =
+ crashpad::CrashReportDatabase::InitializeWithoutCreating(
+ crashpad_database_path);
+
+ if (!database)
+ return false;
+
+ crashpad::CrashReportDatabase::NewReport* report = nullptr;
+ crashpad::CrashReportDatabase::OperationStatus status =
+ database->PrepareNewCrashReport(&report);
+ if (status != crashpad::CrashReportDatabase::kNoError)
+ return false;
+
+ // Make sure we release the report on early exit.
+ crashpad::CrashReportDatabase::CallErrorWritingCrashReport on_error(
+ database.get(), report);
+
+ crashpad::UUID client_id;
+ crashpad::Settings* settings = database->GetSettings();
+ if (settings) {
+ // If GetSettings() or GetClientID() fails client_id will be left at its
+ // default value, all zeroes, which is appropriate.
+ settings->GetClientID(&client_id);
+ }
+
+ base::FilePath dump_file_path;
+ if (!base::CreateTemporaryFile(&dump_file_path))
+ return false;
+
+ // Open the file with delete on close, to try and ensure it's cleaned up on
+ // any kind of failure.
+ base::File dump_file(dump_file_path, base::File::FLAG_OPEN |
+ base::File::FLAG_READ |
+ base::File::FLAG_WRITE |
+ base::File::FLAG_DELETE_ON_CLOSE);
+ if (!dump_file.IsValid())
+ return false;
+
+ // Write the minidump to the temp file, and then copy the data to the
+ // Crashpad-provided handle, as the latter is only open for write.
+ if (!MiniDumpWriteDumpWithCrashpadInfo(process, minidump_type, exc_info,
+ crash_keys, client_id, report->uuid,
+ &dump_file) ||
+ !AppendFileContents(&dump_file, report->handle)) {
+ return false;
+ }
+
+ on_error.Disarm();
+
+ crashpad::UUID report_id = {};
+ status = database->FinishedWritingCrashReport(report, &report_id);
+ if (status != crashpad::CrashReportDatabase::kNoError)
+ return false;
+
+ return true;
+}
+
+} // namespace crash_reporter
diff --git a/chromium/components/crash/content/app/minidump_with_crashpad_info.h b/chromium/components/crash/content/app/minidump_with_crashpad_info.h
new file mode 100644
index 00000000000..358a206a84c
--- /dev/null
+++ b/chromium/components/crash/content/app/minidump_with_crashpad_info.h
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CRASH_CONTENT_APP_MINIDUMP_WITH_CRASHPAD_INFO_H_
+#define COMPONENTS_CRASH_CONTENT_APP_MINIDUMP_WITH_CRASHPAD_INFO_H_
+
+// Needed for dbghelp.h.
+#include <windows.h>
+
+#include <dbghelp.h>
+
+#include <map>
+#include <string>
+
+#include "base/files/file.h"
+#include "base/process/process.h"
+
+namespace crash_reporter {
+
+using StringStringMap = std::map<std::string, std::string>;
+
+// Captures a crash dump for |process| to the crashpad database at
+// |crashpad_database_path|. The crash dump will contain |crash_keys|,
+// which must at minimum include the following keys:
+// - prod: product name, e.g. "Chrome"
+// - ver: product version, e.g. "1.2.3.4"
+bool DumpAndReportProcess(const base::Process& process,
+ uint32_t minidump_type,
+ MINIDUMP_EXCEPTION_INFORMATION* exc_info,
+ const StringStringMap& crash_keys,
+ const base::FilePath& crashpad_database_path);
+
+} // namespace crash_reporter
+
+#endif // COMPONENTS_CRASH_CONTENT_APP_MINIDUMP_WITH_CRASHPAD_INFO_H_
diff --git a/chromium/components/crash/content/app/run_as_crashpad_handler_win.cc b/chromium/components/crash/content/app/run_as_crashpad_handler_win.cc
index 9e5b05b4a6d..c3b7fd9c2e8 100644
--- a/chromium/components/crash/content/app/run_as_crashpad_handler_win.cc
+++ b/chromium/components/crash/content/app/run_as_crashpad_handler_win.cc
@@ -11,7 +11,6 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
#include "base/process/memory.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -82,7 +81,7 @@ int RunAsCrashpadHandler(const base::CommandLine& command_line,
// will be invoked for any registered process' crashes, but information only
// exists for instrumented browser processes.
user_stream_data_sources.push_back(
- base::MakeUnique<browser_watcher::StabilityReportUserStreamDataSource>(
+ std::make_unique<browser_watcher::StabilityReportUserStreamDataSource>(
user_data_dir));
}
diff --git a/chromium/components/crash/content/browser/crash_dump_observer_android.cc b/chromium/components/crash/content/browser/crash_dump_observer_android.cc
index 61ad569c59c..678b52b4cf6 100644
--- a/chromium/components/crash/content/browser/crash_dump_observer_android.cc
+++ b/chromium/components/crash/content/browser/crash_dump_observer_android.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/stl_util.h"
-#include "base/threading/sequenced_worker_pool.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/notification_service.h"
diff --git a/chromium/components/crash/content/browser/crash_handler_host_linux.cc b/chromium/components/crash/content/browser/crash_handler_host_linux.cc
index 706bf5c8826..1c0fd983b11 100644
--- a/chromium/components/crash/content/browser/crash_handler_host_linux.cc
+++ b/chromium/components/crash/content/browser/crash_handler_host_linux.cc
@@ -12,6 +12,7 @@
#include <sys/syscall.h>
#include <unistd.h>
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -23,7 +24,6 @@
#include "base/linux_util.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/path_service.h"
#include "base/posix/eintr_wrapper.h"
#include "base/rand_util.h"
@@ -135,7 +135,7 @@ CrashHandlerHostLinux::~CrashHandlerHostLinux() {
void CrashHandlerHostLinux::StartUploaderThread() {
uploader_thread_ =
- base::MakeUnique<base::Thread>(process_type_ + "_crash_uploader");
+ std::make_unique<base::Thread>(process_type_ + "_crash_uploader");
uploader_thread_->Start();
}
@@ -165,13 +165,13 @@ void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) {
struct msghdr msg = {nullptr};
struct iovec iov[kCrashIovSize];
- auto crash_context = base::MakeUnique<char[]>(kCrashContextSize);
+ auto crash_context = std::make_unique<char[]>(kCrashContextSize);
#if defined(ADDRESS_SANITIZER)
- auto asan_report = base::MakeUnique<char[]>(kMaxAsanReportSize + 1);
+ auto asan_report = std::make_unique<char[]>(kMaxAsanReportSize + 1);
#endif
auto crash_keys =
- base::MakeUnique<crash_reporter::internal::TransitionalCrashKeyStorage>();
+ std::make_unique<crash_reporter::internal::TransitionalCrashKeyStorage>();
google_breakpad::SerializedNonAllocatingMap* serialized_crash_keys;
size_t crash_keys_size = crash_keys->Serialize(
const_cast<const google_breakpad::SerializedNonAllocatingMap**>(
@@ -330,21 +330,16 @@ void CrashHandlerHostLinux::FindCrashingThreadAndDump(
LOG(WARNING) << "Could not translate tid, attempt = " << attempt
<< " retry ...";
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&CrashHandlerHostLinux::FindCrashingThreadAndDump,
- base::Unretained(this),
- crashing_pid,
- expected_syscall_data,
- base::Passed(&crash_context),
- base::Passed(&crash_keys),
+ FROM_HERE,
+ base::BindOnce(&CrashHandlerHostLinux::FindCrashingThreadAndDump,
+ base::Unretained(this), crashing_pid,
+ expected_syscall_data, std::move(crash_context),
+ std::move(crash_keys),
#if defined(ADDRESS_SANITIZER)
- base::Passed(&asan_report),
+ std::move(asan_report),
#endif
- uptime,
- oom_size,
- signal_fd,
- attempt),
- base::TimeDelta::FromMilliseconds(kRetryIntervalTranslatingTidInMs));
+ uptime, oom_size, signal_fd, attempt),
+ base::TimeDelta::FromMilliseconds(kRetryIntervalTranslatingTidInMs));
return;
}
@@ -365,7 +360,7 @@ void CrashHandlerHostLinux::FindCrashingThreadAndDump(
reinterpret_cast<ExceptionHandler::CrashContext*>(crash_context.get());
bad_context->tid = crashing_tid;
- auto info = base::MakeUnique<BreakpadInfo>();
+ auto info = std::make_unique<BreakpadInfo>();
info->fd = -1;
info->process_type_length = process_type_.length();
// Freed in CrashDumpTask().
@@ -396,10 +391,10 @@ void CrashHandlerHostLinux::FindCrashingThreadAndDump(
blocking_task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&CrashHandlerHostLinux::WriteDumpFile,
- base::Unretained(this), info_ptr,
- base::Passed(&crash_context), crashing_pid),
+ base::Unretained(this), info_ptr, std::move(crash_context),
+ crashing_pid),
base::BindOnce(&CrashHandlerHostLinux::QueueCrashDumpTask,
- base::Unretained(this), base::Passed(&info), signal_fd));
+ base::Unretained(this), std::move(info), signal_fd));
}
void CrashHandlerHostLinux::WriteDumpFile(BreakpadInfo* info,
@@ -477,7 +472,7 @@ void CrashHandlerHostLinux::QueueCrashDumpTask(
uploader_thread_->task_runner()->PostTask(
FROM_HERE,
- base::Bind(&CrashDumpTask, base::Unretained(this), base::Passed(&info)));
+ base::BindOnce(&CrashDumpTask, base::Unretained(this), std::move(info)));
}
void CrashHandlerHostLinux::WillDestroyCurrentMessageLoop() {
diff --git a/chromium/components/crash/content/tools/generate_breakpad_symbols.py b/chromium/components/crash/content/tools/generate_breakpad_symbols.py
index d076e8faae4..dbf7961b491 100755
--- a/chromium/components/crash/content/tools/generate_breakpad_symbols.py
+++ b/chromium/components/crash/content/tools/generate_breakpad_symbols.py
@@ -212,11 +212,10 @@ def GenerateSymbols(options, binaries):
with print_lock:
print "Generating symbols for %s" % binary
- syms = GetCommandOutput([dump_syms, '-r', binary])
mkdir_p(os.path.dirname(output_path))
try:
with open(output_path, 'wb') as f:
- f.write(syms)
+ subprocess.check_call([dump_syms, '-r', binary], stdout=f)
except Exception, e:
# Not much we can do about this.
with print_lock:
diff --git a/chromium/components/crash/core/common/crash_keys.cc b/chromium/components/crash/core/common/crash_keys.cc
index 4af07a02692..bbb0af7cb05 100644
--- a/chromium/components/crash/core/common/crash_keys.cc
+++ b/chromium/components/crash/core/common/crash_keys.cc
@@ -4,10 +4,17 @@
#include "components/crash/core/common/crash_keys.h"
+#include <deque>
+#include <vector>
+
#include "base/command_line.h"
+#include "base/format_macros.h"
+#include "base/no_destructor.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 "build/build_config.h"
#include "components/crash/core/common/crash_key.h"
@@ -60,24 +67,11 @@ void ClearMetricsClientId() {
#endif
}
-using SwitchesCrashKey = crash_reporter::CrashKeyString<64>;
-static SwitchesCrashKey switches_keys[] = {
- {"switch-1", SwitchesCrashKey::Tag::kArray},
- {"switch-2", SwitchesCrashKey::Tag::kArray},
- {"switch-3", SwitchesCrashKey::Tag::kArray},
- {"switch-4", SwitchesCrashKey::Tag::kArray},
- {"switch-5", SwitchesCrashKey::Tag::kArray},
- {"switch-6", SwitchesCrashKey::Tag::kArray},
- {"switch-7", SwitchesCrashKey::Tag::kArray},
- {"switch-8", SwitchesCrashKey::Tag::kArray},
- {"switch-9", SwitchesCrashKey::Tag::kArray},
- {"switch-10", SwitchesCrashKey::Tag::kArray},
- {"switch-11", SwitchesCrashKey::Tag::kArray},
- {"switch-12", SwitchesCrashKey::Tag::kArray},
- {"switch-13", SwitchesCrashKey::Tag::kArray},
- {"switch-14", SwitchesCrashKey::Tag::kArray},
- {"switch-15", SwitchesCrashKey::Tag::kArray},
-};
+using SwitchesCrashKeys = std::deque<crash_reporter::CrashKeyString<64>>;
+SwitchesCrashKeys& GetSwitchesCrashKeys() {
+ static base::NoDestructor<SwitchesCrashKeys> switches_keys;
+ return *switches_keys;
+}
static crash_reporter::CrashKeyString<4> num_switches_key("num-switches");
@@ -85,14 +79,15 @@ void SetSwitchesFromCommandLine(const base::CommandLine& command_line,
SwitchFilterFunction skip_filter) {
const base::CommandLine::StringVector& argv = command_line.argv();
- // Set the number of switches in case size > kNumSwitches.
+ // Set the number of switches in case of uninteresting switches in
+ // command_line.
num_switches_key.Set(base::NumberToString(argv.size() - 1));
size_t key_i = 0;
// Go through the argv, skipping the exec path. Stop if there are too many
// switches to hold in crash keys.
- for (size_t i = 1; i < argv.size() && key_i < arraysize(switches_keys); ++i) {
+ for (size_t i = 1; i < argv.size(); ++i) {
#if defined(OS_WIN)
std::string switch_str = base::WideToUTF8(argv[i]);
#else
@@ -103,19 +98,50 @@ void SetSwitchesFromCommandLine(const base::CommandLine& command_line,
if (skip_filter && (*skip_filter)(switch_str))
continue;
- switches_keys[key_i++].Set(switch_str);
+ if (key_i >= GetSwitchesCrashKeys().size()) {
+ static base::NoDestructor<std::deque<std::string>> crash_keys_names;
+ crash_keys_names->emplace_back(
+ base::StringPrintf("switch-%" PRIuS, key_i + 1));
+ GetSwitchesCrashKeys().emplace_back(crash_keys_names->back().c_str());
+ }
+ GetSwitchesCrashKeys()[key_i++].Set(switch_str);
}
// Clear any remaining switches.
- for (; key_i < arraysize(switches_keys); ++key_i)
- switches_keys[key_i].Clear();
+ for (; key_i < GetSwitchesCrashKeys().size(); ++key_i)
+ GetSwitchesCrashKeys()[key_i].Clear();
}
void ResetCommandLineForTesting() {
num_switches_key.Clear();
- for (auto& key : switches_keys) {
+ for (auto& key : GetSwitchesCrashKeys()) {
key.Clear();
}
}
+using PrinterInfoKey = crash_reporter::CrashKeyString<64>;
+static PrinterInfoKey printer_info_keys[] = {
+ {"prn-info-1", PrinterInfoKey::Tag::kArray},
+ {"prn-info-2", PrinterInfoKey::Tag::kArray},
+ {"prn-info-3", PrinterInfoKey::Tag::kArray},
+ {"prn-info-4", PrinterInfoKey::Tag::kArray},
+};
+
+ScopedPrinterInfo::ScopedPrinterInfo(base::StringPiece data) {
+ std::vector<base::StringPiece> info = base::SplitStringPiece(
+ data, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ for (size_t i = 0; i < arraysize(printer_info_keys); ++i) {
+ if (i < info.size())
+ printer_info_keys[i].Set(info[i]);
+ else
+ printer_info_keys[i].Clear();
+ }
+}
+
+ScopedPrinterInfo::~ScopedPrinterInfo() {
+ for (auto& crash_key : printer_info_keys) {
+ crash_key.Clear();
+ }
+}
+
} // namespace crash_keys
diff --git a/chromium/components/crash/core/common/crash_keys.h b/chromium/components/crash/core/common/crash_keys.h
index b85e70a3795..20eb4426bf1 100644
--- a/chromium/components/crash/core/common/crash_keys.h
+++ b/chromium/components/crash/core/common/crash_keys.h
@@ -7,6 +7,8 @@
#include <string>
+#include "base/strings/string_piece.h"
+
namespace base {
class CommandLine;
} // namespace base
@@ -32,6 +34,17 @@ void SetSwitchesFromCommandLine(const base::CommandLine& command_line,
// Clears all the CommandLine-related crash keys.
void ResetCommandLineForTesting();
+// Sets the printer info. Data should be separated by ';' up to 4 substrings.
+// Each substring will be truncated if necessary.
+class ScopedPrinterInfo {
+ public:
+ explicit ScopedPrinterInfo(base::StringPiece data);
+ ~ScopedPrinterInfo();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedPrinterInfo);
+};
+
} // namespace crash_keys
#endif // COMPONENTS_CRASH_CORE_COMMON_CRASH_KEYS_H_
diff --git a/chromium/components/crash/core/common/crash_keys_unittest.cc b/chromium/components/crash/core/common/crash_keys_unittest.cc
index edebbfcf710..603cc36c8b3 100644
--- a/chromium/components/crash/core/common/crash_keys_unittest.cc
+++ b/chromium/components/crash/core/common/crash_keys_unittest.cc
@@ -51,7 +51,7 @@ TEST_F(CrashKeysTest, Switches) {
EXPECT_TRUE(GetCrashKeyValue("switch-4").empty());
}
- // Set more than the max switches.
+ // Set more than 15 switches.
{
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
const size_t kMax = kSwitchesMaxCount + 2;
@@ -62,8 +62,8 @@ TEST_F(CrashKeysTest, Switches) {
EXPECT_EQ("--many-1", GetCrashKeyValue("switch-1"));
EXPECT_EQ("--many-9", GetCrashKeyValue("switch-9"));
EXPECT_EQ("--many-15", GetCrashKeyValue("switch-15"));
- EXPECT_TRUE(GetCrashKeyValue("switch-16").empty());
- EXPECT_TRUE(GetCrashKeyValue("switch-17").empty());
+ EXPECT_FALSE(GetCrashKeyValue("switch-16").empty());
+ EXPECT_FALSE(GetCrashKeyValue("switch-17").empty());
}
// Set fewer to ensure that old ones are erased.
diff --git a/chromium/components/cronet/BUILD.gn b/chromium/components/cronet/BUILD.gn
index a1fee45030f..31d4ebf1d67 100644
--- a/chromium/components/cronet/BUILD.gn
+++ b/chromium/components/cronet/BUILD.gn
@@ -65,3 +65,53 @@ source_set("cronet_common_unittests") {
"url_request_context_config_unittest.cc",
]
}
+
+# For platforms on which the native Cronet library is used, build the library,
+# a cronet_tests binary that exercises it, and a unit-tests binary.
+# Android and iOS have their own platform-specific rules to build Cronet.
+# TODO(https://crbug.com/812268): Fix Windows build, and enable it.
+if (!is_ios && !is_android && !is_win) {
+ shared_library("cronet") {
+ deps = [
+ "//base",
+
+ # Explicitly add the exe_and_shlib_deps, otherwise the library will fail
+ # to link in component builds, due to missing libc++ symbols.
+ "//build/config:exe_and_shlib_deps",
+ "//components/cronet:cronet_common",
+ "//components/cronet/native:cronet_native_impl",
+ "//net",
+ ]
+
+ sources = [
+ "cronet_global_state_stubs.cc",
+ ]
+ }
+
+ test("cronet_tests") {
+ deps = [
+ ":cronet",
+ "//base",
+ "//base/test:test_support",
+ "//components/cronet/native/test:cronet_native_tests",
+ ]
+
+ sources = [
+ "run_all_unittests.cc",
+ ]
+ }
+
+ test("cronet_unittests") {
+ deps = [
+ ":cronet_common",
+ ":cronet_common_unittests",
+ "//base",
+ "//components/cronet/native:cronet_native_unittests",
+ "//net",
+ ]
+
+ sources = [
+ "cronet_global_state_stubs.cc",
+ ]
+ }
+}
diff --git a/chromium/components/cronet/android/BUILD.gn b/chromium/components/cronet/android/BUILD.gn
index f06ccd44cca..f8136fa504c 100644
--- a/chromium/components/cronet/android/BUILD.gn
+++ b/chromium/components/cronet/android/BUILD.gn
@@ -275,9 +275,12 @@ cronet_impl_common_java_srcjar_deps = [
":rtt_throughput_values_java",
]
-# cronet_impl_common_java.jar - common Cronet code that is shared
+cronet_impl_common_java_deps_to_package =
+ [ "//net/android:net_thread_stats_uid_java" ]
+
+# cronet_impl_common_java_base.jar - common Cronet code that is shared
# by all Cronet engine implementations.
-android_library("cronet_impl_common_java") {
+android_library("cronet_impl_common_java_base") {
java_files = [
"java/src/org/chromium/net/impl/CallbackExceptionImpl.java",
"java/src/org/chromium/net/impl/CronetExceptionImpl.java",
@@ -298,6 +301,7 @@ android_library("cronet_impl_common_java") {
":cronet_api_java",
"//third_party/android_tools:android_support_annotations_java",
]
+ deps += cronet_impl_common_java_deps_to_package
srcjar_deps = cronet_impl_common_java_srcjar_deps
}
@@ -314,7 +318,7 @@ android_library("cronet_impl_platform_java") {
deps = [
":cronet_api_java",
- ":cronet_impl_common_java",
+ ":cronet_impl_common_java_base",
"//third_party/android_tools:android_support_annotations_java",
"//third_party/jsr-305:jsr_305_javalib",
]
@@ -326,6 +330,12 @@ cronet_impl_native_java_srcjar_deps = [
":url_request_error_java",
]
+cronet_impl_native_java_deps_to_package = [
+ "//base:base_java",
+ "//net/android:net_java",
+ "//url:url_java",
+]
+
# cronet_impl_native_java.jar - native implementation of the Cronet engine.
android_library("cronet_impl_native_java") {
java_files = [
@@ -353,12 +363,11 @@ android_library("cronet_impl_native_java") {
deps = [
":cronet_api_java",
- ":cronet_impl_common_java",
- "//base:base_java",
- "//net/android:net_java",
+ ":cronet_impl_common_java_base",
"//third_party/android_tools:android_support_annotations_java",
"//third_party/jsr-305:jsr_305_javalib",
]
+ deps += cronet_impl_native_java_deps_to_package
srcjar_deps = cronet_impl_native_java_srcjar_deps
}
@@ -366,7 +375,7 @@ android_library("cronet_impl_native_java") {
# Groups all Cronet implementations and the common code into a single Java dependency.
java_group("cronet_impl_all_java") {
deps = [
- ":cronet_impl_common_java",
+ ":cronet_impl_common_java_base",
":cronet_impl_native_java",
":cronet_impl_platform_java",
]
@@ -499,7 +508,6 @@ shared_library("cronet_tests") {
"//base:i18n",
"//base/test:test_support",
"//components/cronet:cronet_version_header",
- "//components/cronet/native:cronet_native_tests",
"//components/prefs",
"//net",
"//net:simple_quic_tools",
@@ -616,7 +624,6 @@ android_library("cronet_javatests") {
"test/javatests/src/org/chromium/net/Criteria.java",
"test/javatests/src/org/chromium/net/CronetEngineBuilderTest.java",
"test/javatests/src/org/chromium/net/CronetStressTest.java",
- "test/javatests/src/org/chromium/net/CronetTestCommon.java",
"test/javatests/src/org/chromium/net/CronetTestRule.java",
"test/javatests/src/org/chromium/net/CronetTestRuleTest.java",
"test/javatests/src/org/chromium/net/CronetUploadTest.java",
@@ -662,7 +669,7 @@ android_library("cronet_javatests") {
"//third_party/junit",
]
data = [
- "test/assets/test/",
+ "//components/cronet/test/data/",
]
}
@@ -726,7 +733,7 @@ android_apk("cronet_smoketests_platform_only_apk") {
deps = [
":cronet_api_java",
- ":cronet_impl_common_java",
+ ":cronet_impl_common_java_base",
":cronet_impl_platform_java",
":cronet_smoketests_platform_only_apk_resources",
]
@@ -769,7 +776,7 @@ android_apk("cronet_smoketests_missing_native_library_apk") {
deps = [
":cronet_api_java",
":cronet_combine_proguard_flags",
- ":cronet_impl_common_java",
+ ":cronet_impl_common_java_base",
":cronet_impl_platform_java",
":cronet_test_apk_resources",
]
@@ -837,18 +844,20 @@ android_apk("cronet_perf_test_apk") {
]
}
-test("cronet_unittests") {
+test("cronet_unittests_android") {
sources = [
"//components/cronet/android/cert/cert_verifier_cache_serializer_unittest.cc",
]
deps = [
":cronet_android_cert_proto",
+ ":cronet_impl_native_java",
":cronet_static",
"//base",
"//base/test:test_support",
"//components/cronet:cronet_common_unittests",
"//components/cronet/native:cronet_native_unittests",
+ "//components/cronet/native/test:cronet_native_tests",
"//components/metrics",
"//components/prefs:test_support",
"//net",
@@ -857,6 +866,10 @@ test("cronet_unittests") {
"//testing/gtest",
]
+ data = [
+ "//components/cronet/test/data/",
+ ]
+
if (is_android) {
shard_timeout = 180
}
@@ -864,10 +877,11 @@ test("cronet_unittests") {
_package_dir = "$root_out_dir/cronet"
_test_package_dir = "$root_out_dir/cronet/test"
-_extract_cronet_jars_dir = "$target_gen_dir/cronet_jar_extract"
+_extract_cronet_native_jars_dir = "$target_gen_dir/cronet_native_jar_extract"
+_extract_cronet_common_jars_dir = "$target_gen_dir/cronet_common_jar_extract"
_extract_cronet_test_jars_dir = "$target_gen_dir/cronet_test_jar_extract"
-action("extract_cronet_jars") {
+action("extract_cronet_native_jars") {
# extract_from_jars.py deletes the target directory before extracting.
script = "//components/cronet/tools/extract_from_jars.py"
depfile = "$target_gen_dir/$target_name.d"
@@ -879,10 +893,8 @@ action("extract_cronet_jars") {
deps = [
":cronet_impl_native_java",
- "//base:base_java",
- "//net/android:net_java",
- "//url:url_java",
]
+ deps += cronet_impl_native_java_deps_to_package
sources = []
foreach(dep, deps) {
@@ -894,7 +906,7 @@ action("extract_cronet_jars") {
args = [
"--classes-dir",
- rebase_path(_extract_cronet_jars_dir, root_build_dir),
+ rebase_path(_extract_cronet_native_jars_dir, root_build_dir),
"--jars=${_rebased_sources}",
"--depfile",
rebase_path(depfile, root_build_dir),
@@ -903,7 +915,7 @@ action("extract_cronet_jars") {
]
}
-action("repackage_extracted_jars") {
+action("repackage_extracted_native_jars") {
_output_jar = "$_package_dir/cronet_impl_native_java.jar"
script = "//build/android/gyp/jar.py"
@@ -913,13 +925,67 @@ action("repackage_extracted_jars") {
args = [
"--classes-dir",
- rebase_path(_extract_cronet_jars_dir, root_build_dir),
+ rebase_path(_extract_cronet_native_jars_dir, root_build_dir),
+ "--jar-path",
+ rebase_path(_output_jar, root_build_dir),
+ ]
+
+ deps = [
+ ":extract_cronet_native_jars",
+ ]
+}
+
+action("extract_cronet_common_jars") {
+ # extract_from_jars.py deletes the target directory before extracting.
+ script = "//components/cronet/tools/extract_from_jars.py"
+ depfile = "$target_gen_dir/$target_name.d"
+
+ _stamp_file = "$target_gen_dir/$target_name.stamp"
+ outputs = [
+ _stamp_file,
+ ]
+
+ deps = [
+ ":cronet_impl_common_java_base",
+ ]
+ deps += cronet_impl_common_java_deps_to_package
+
+ sources = []
+ foreach(dep, deps) {
+ sources += [ get_label_info(dep, "target_gen_dir") + "/" +
+ get_label_info(dep, "name") + ".javac.jar" ]
+ }
+
+ _rebased_sources = rebase_path(sources, root_build_dir)
+
+ args = [
+ "--classes-dir",
+ rebase_path(_extract_cronet_common_jars_dir, root_build_dir),
+ "--jars=${_rebased_sources}",
+ "--depfile",
+ rebase_path(depfile, root_build_dir),
+ "--stamp",
+ rebase_path(_stamp_file, root_build_dir),
+ ]
+}
+
+action("repackage_extracted_common_jars") {
+ _output_jar = "$_package_dir/cronet_impl_common_java.jar"
+
+ script = "//build/android/gyp/jar.py"
+ outputs = [
+ _output_jar,
+ ]
+
+ args = [
+ "--classes-dir",
+ rebase_path(_extract_cronet_common_jars_dir, root_build_dir),
"--jar-path",
rebase_path(_output_jar, root_build_dir),
]
deps = [
- ":extract_cronet_jars",
+ ":extract_cronet_common_jars",
]
}
@@ -1068,7 +1134,7 @@ jar_src("jar_cronet_api_source") {
jar_src("jar_cronet_impl_common_java_source") {
src_search_dirs = [ "java/src" ]
- source_deps = [ ":cronet_impl_common_java" ]
+ source_deps = [ ":cronet_impl_common_java_base" ]
srcjar_deps = cronet_impl_common_java_srcjar_deps
jar_path = "$_package_dir/cronet_impl_common_java-src.jar"
}
@@ -1185,7 +1251,7 @@ copy("cronet_package_copy") {
deps = [
":cronet_api_java",
":cronet_combine_proguard_flags",
- ":cronet_impl_common_java",
+ ":cronet_impl_common_java_base",
":cronet_impl_platform_java",
]
}
@@ -1227,7 +1293,6 @@ template("copy_java8_jars") {
copy_java8_jars("copy_cronet_java8_jars") {
deps = [
":cronet_api_java",
- ":cronet_impl_common_java",
":cronet_impl_platform_java",
]
}
@@ -1302,10 +1367,10 @@ copy("cronet_package_copy_native_test_lib_unstripped") {
copy("cronet_package_copy_test_assets") {
testonly = true
sources = [
- "test/assets",
+ "//components/cronet/test/data",
]
outputs = [
- "$_test_package_dir/assets",
+ "$_test_package_dir/assets/test",
]
}
@@ -1386,7 +1451,7 @@ action("api_static_checks") {
root_build_dir),
"--impl_jar",
rebase_path(
- "$root_out_dir/lib.java/components/cronet/android/cronet_impl_common_java.jar",
+ "$root_out_dir/lib.java/components/cronet/android/cronet_impl_common_java_base.jar",
root_build_dir),
"--impl_jar",
rebase_path(
@@ -1401,7 +1466,7 @@ action("api_static_checks") {
]
deps = [
":cronet_api_java",
- ":cronet_impl_common_java",
+ ":cronet_impl_common_java_base",
":cronet_impl_native_java",
":cronet_impl_platform_java",
]
@@ -1438,7 +1503,8 @@ group("cronet_package") {
":jar_cronet_impl_native_java_source",
":jar_cronet_impl_platform_java_source",
":jar_cronet_sample_source",
- ":repackage_extracted_jars",
+ ":repackage_extracted_common_jars",
+ ":repackage_extracted_native_jars",
]
if (current_cpu == "arm" && arm_version == 7) {
deps += [ ":enforce_no_neon" ]
diff --git a/chromium/components/cronet/ios/BUILD.gn b/chromium/components/cronet/ios/BUILD.gn
index 282a1e97b16..95866b48529 100644
--- a/chromium/components/cronet/ios/BUILD.gn
+++ b/chromium/components/cronet/ios/BUILD.gn
@@ -6,8 +6,6 @@ import("//build/buildflag_header.gni")
import("//build/config/ios/rules.gni")
import("//build/config/mac/symbols.gni")
import("//build/mac/tweak_info_plist.gni")
-import("//build/util/process_version.gni")
-import("//build/util/version.gni")
import("//components/cronet/native/include/headers.gni")
import("//components/grpc_support/include/headers.gni")
import("//testing/test.gni")
@@ -21,18 +19,6 @@ group("cronet_consumer_group") {
]
}
-process_version("cronet_version_header") {
- template_file = "//components/cronet/version.h.in"
- sources = [
- "//chrome/VERSION",
- ]
- output = "$target_gen_dir/version.h"
- extra_args = [
- "-e",
- "VERSION_FULL=\"%s.%s.%s.%s\" % (MAJOR,MINOR,BUILD,PATCH)",
- ]
-}
-
config("cronet_include_config") {
include_dirs = [ "//components/grpc_support/include" ]
}
@@ -51,13 +37,12 @@ config("cronet_static_config") {
}
_cronet_deps = [
- ":cronet_version_header",
":generate_accept_languages",
"//base:base",
+ "//components/cronet:cronet_common",
+ "//components/cronet:cronet_version_header",
"//components/cronet/native:cronet_native_impl",
"//components/grpc_support",
- "//components/metrics:metrics",
- "//third_party/metrics_proto",
"//components/prefs:prefs",
"//ios/net:net",
"//ios/web/public:user_agent",
@@ -67,20 +52,11 @@ _cronet_deps = [
]
_cronet_sources = [
- "../cronet_prefs_manager.cc",
- "../cronet_prefs_manager.h",
- "../histogram_manager.cc",
- "../histogram_manager.h",
- "../host_cache_persistence_manager.cc",
- "../host_cache_persistence_manager.h",
- "../stale_host_resolver.cc",
- "../stale_host_resolver.h",
- "../url_request_context_config.cc",
- "../url_request_context_config.h",
"Cronet.h",
"Cronet.mm",
"cronet_environment.h",
"cronet_environment.mm",
+ "cronet_global_state_ios.mm",
"cronet_metrics.h",
"cronet_metrics.mm",
]
@@ -154,17 +130,13 @@ ios_framework_bundle("cronet_framework") {
test("cronet_unittests_ios") {
testonly = true
- sources = [
- "//components/cronet/histogram_manager_unittest.cc",
- "//components/cronet/run_all_unittests.cc",
- "//components/cronet/stale_host_resolver_unittest.cc",
- "//components/cronet/url_request_context_config_unittest.cc",
- ]
+ sources = []
deps = [
":cronet_sources_with_global_state",
"//base",
"//base/test:test_support",
+ "//components/cronet:cronet_common_unittests",
"//components/cronet/native:cronet_native_unittests",
"//components/metrics",
"//net",
diff --git a/chromium/components/cronet/ios/test/BUILD.gn b/chromium/components/cronet/ios/test/BUILD.gn
index 575f2728f86..7a074f53b53 100644
--- a/chromium/components/cronet/ios/test/BUILD.gn
+++ b/chromium/components/cronet/ios/test/BUILD.gn
@@ -21,15 +21,14 @@ test("cronet_test") {
"get_stream_engine.mm",
"start_cronet.h",
"start_cronet.mm",
- "test_server.cc",
- "test_server.h",
]
deps = [
"//base",
"//base:i18n",
"//components/cronet/ios:cronet_framework+link",
- "//components/cronet/native:cronet_native_tests",
+ "//components/cronet/native/test:cronet_native_tests",
+ "//components/cronet/test:test_support",
"//components/grpc_support:bidirectional_stream_unittest",
"//components/grpc_support/test:quic_test_server",
"//net",
diff --git a/chromium/components/cronet/native/BUILD.gn b/chromium/components/cronet/native/BUILD.gn
index afba5a767e9..2e9bb65c3e4 100644
--- a/chromium/components/cronet/native/BUILD.gn
+++ b/chromium/components/cronet/native/BUILD.gn
@@ -1,28 +1,66 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
import("//components/cronet/native/include/headers.gni")
import("//testing/test.gni")
-# Cronet native API implementation.
-source_set("cronet_native_impl") {
- sources = [
- "buffer.cc",
+config("cronet_native_include_config") {
+ include_dirs = [
+ "//components/cronet/native/generated",
+ "//components/cronet/native/include",
+ ]
+}
+
+source_set("cronet_native_headers") {
+ deps = [
+ "//base",
+ ]
+
+ configs += [ ":cronet_native_include_config" ]
+ public_configs = [ ":cronet_native_include_config" ]
+
+ public = [
"include/cronet_c.h",
- "runnables.cc",
- "runnables.h",
+ "include/cronet_export.h",
# Generated from cronet.idl.
"generated/cronet.idl_c.h",
- "generated/cronet.idl_impl_interface.cc",
"generated/cronet.idl_impl_interface.h",
- "generated/cronet.idl_impl_struct.cc",
"generated/cronet.idl_impl_struct.h",
]
+}
+
+# Cross-platform portion of Cronet native API implementation.
+source_set("cronet_native_impl") {
deps = [
+ ":cronet_native_headers",
"//base",
+ "//components/cronet:cronet_common",
+ "//components/cronet:cronet_version_header",
"//net",
]
- include_dirs = [
- "//components/cronet/native/generated",
- "//components/cronet/native/include",
+
+ configs += [ ":cronet_native_include_config" ]
+ public_configs = [ ":cronet_native_include_config" ]
+ public_deps = [
+ ":cronet_native_headers",
+ ]
+
+ sources = [
+ "buffer.cc",
+ "engine.cc",
+ "engine.h",
+ "io_buffer_with_cronet_buffer.cc",
+ "io_buffer_with_cronet_buffer.h",
+ "runnables.cc",
+ "runnables.h",
+ "url_request.cc",
+ "url_request.h",
+
+ # Generated from cronet.idl.
+ "generated/cronet.idl_impl_interface.cc",
+ "generated/cronet.idl_impl_struct.cc",
]
}
@@ -33,44 +71,18 @@ source_set("cronet_native_unittests") {
deps = [
":cronet_native_impl",
+ "//components/cronet/native/test:cronet_native_testutil",
"//net:test_support",
+ "//testing/gtest",
]
- include_dirs = [
- "//components/cronet/native/generated",
- "//components/cronet/native/include",
- ]
+ configs += [ ":cronet_native_include_config" ]
sources = [
"runnables_unittest.cc",
- "test_util.cc",
- "test_util.h",
# Generated from cronet.idl.
"generated/cronet.idl_impl_interface_unittest.cc",
"generated/cronet.idl_impl_struct_unittest.cc",
]
}
-
-# Tests for publicly exported Cronet Native API. This target does NOT depend on
-# cronet_native_impl to prevent static linking of implementation into test app.
-source_set("cronet_native_tests") {
- testonly = true
-
- deps = [
- "//base",
- "//base/test:test_support",
- "//testing/gtest",
- ]
-
- include_dirs = [
- "//components/cronet/native/generated",
- "//components/cronet/native/include",
- ]
- sources = [
- "buffer_test.cc",
- "executors_test.cc",
- "test_util.cc",
- "test_util.h",
- ]
-}
diff --git a/chromium/components/cronet/native/test/BUILD.gn b/chromium/components/cronet/native/test/BUILD.gn
new file mode 100644
index 00000000000..4e3d61b66fe
--- /dev/null
+++ b/chromium/components/cronet/native/test/BUILD.gn
@@ -0,0 +1,51 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//components/cronet/native/include/headers.gni")
+import("//testing/test.gni")
+
+source_set("cronet_native_testutil") {
+ testonly = true
+
+ deps = [
+ "//base",
+ "//components/cronet/native:cronet_native_headers",
+ "//net:test_support",
+ ]
+
+ configs += [ "//components/cronet/native:cronet_native_include_config" ]
+ public_configs = [ "//components/cronet/native:cronet_native_include_config" ]
+
+ sources = [
+ "test_util.cc",
+ "test_util.h",
+ ]
+}
+
+# Tests for publicly exported Cronet Native API. This target does NOT depend on
+# cronet_native_impl to prevent static linking of implementation into test app.
+source_set("cronet_native_tests") {
+ testonly = true
+
+ deps = [
+ ":cronet_native_testutil",
+ "//base",
+ "//base/test:test_support",
+ "//components/cronet/native:cronet_native_headers",
+ "//components/cronet/test:test_support",
+ "//net:test_support",
+ "//testing/gtest",
+ ]
+
+ configs += [ "//components/cronet/native:cronet_native_include_config" ]
+
+ sources = [
+ "buffer_test.cc",
+ "engine_test.cc",
+ "executors_test.cc",
+ "test_url_request_callback.cc",
+ "test_url_request_callback.h",
+ "url_request_test.cc",
+ ]
+}
diff --git a/chromium/components/cronet/test/BUILD.gn b/chromium/components/cronet/test/BUILD.gn
new file mode 100644
index 00000000000..f83f07850c1
--- /dev/null
+++ b/chromium/components/cronet/test/BUILD.gn
@@ -0,0 +1,61 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+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/crx_file/crx_verifier.cc b/chromium/components/crx_file/crx_verifier.cc
index 77fde4e0b25..36c1c91f71e 100644
--- a/chromium/components/crx_file/crx_verifier.cc
+++ b/chromium/components/crx_file/crx_verifier.cc
@@ -15,7 +15,6 @@
#include "base/callback.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "components/crx_file/crx3.pb.h"
#include "components/crx_file/crx_file.h"
@@ -161,7 +160,7 @@ VerifierResult VerifyCrx3(
std::vector<uint8_t> key_hash(crypto::kSHA256Length);
crypto::SHA256HashString(key, key_hash.data(), key_hash.size());
required_key_set.erase(key_hash);
- auto v = base::MakeUnique<crypto::SignatureVerifier>();
+ auto v = std::make_unique<crypto::SignatureVerifier>();
static_assert(sizeof(unsigned char) == sizeof(uint8_t),
"Unsupported char size.");
if (!v->VerifyInit(
@@ -221,7 +220,7 @@ VerifierResult VerifyCrx2(
static_cast<int>(sig_size))
return VerifierResult::ERROR_HEADER_INVALID;
std::vector<std::unique_ptr<crypto::SignatureVerifier>> verifiers;
- verifiers.push_back(base::MakeUnique<crypto::SignatureVerifier>());
+ verifiers.push_back(std::make_unique<crypto::SignatureVerifier>());
if (!verifiers[0]->VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
sig.data(), sig.size(), key.data(),
key.size())) {
diff --git a/chromium/components/cryptauth/BUILD.gn b/chromium/components/cryptauth/BUILD.gn
index fc01780e3b1..3691029d41b 100644
--- a/chromium/components/cryptauth/BUILD.gn
+++ b/chromium/components/cryptauth/BUILD.gn
@@ -24,11 +24,15 @@ static_library("cryptauth") {
"cryptauth_client_impl.h",
"cryptauth_device_manager.cc",
"cryptauth_device_manager.h",
+ "cryptauth_device_manager_impl.cc",
+ "cryptauth_device_manager_impl.h",
"cryptauth_enroller.h",
"cryptauth_enroller_impl.cc",
"cryptauth_enroller_impl.h",
"cryptauth_enrollment_manager.cc",
"cryptauth_enrollment_manager.h",
+ "cryptauth_enrollment_manager_impl.cc",
+ "cryptauth_enrollment_manager_impl.h",
"cryptauth_enrollment_utils.cc",
"cryptauth_enrollment_utils.h",
"cryptauth_gcm_manager.cc",
@@ -116,6 +120,10 @@ static_library("test_support") {
"fake_authenticator.h",
"fake_connection.cc",
"fake_connection.h",
+ "fake_cryptauth_device_manager.cc",
+ "fake_cryptauth_device_manager.h",
+ "fake_cryptauth_enrollment_manager.cc",
+ "fake_cryptauth_enrollment_manager.h",
"fake_cryptauth_gcm_manager.cc",
"fake_cryptauth_gcm_manager.h",
"fake_cryptauth_service.cc",
@@ -164,9 +172,9 @@ source_set("unit_tests") {
"cryptauth_access_token_fetcher_impl_unittest.cc",
"cryptauth_api_call_flow_unittest.cc",
"cryptauth_client_impl_unittest.cc",
- "cryptauth_device_manager_unittest.cc",
+ "cryptauth_device_manager_impl_unittest.cc",
"cryptauth_enroller_impl_unittest.cc",
- "cryptauth_enrollment_manager_unittest.cc",
+ "cryptauth_enrollment_manager_impl_unittest.cc",
"cryptauth_gcm_manager_impl_unittest.cc",
"device_capability_manager_impl_unittest.cc",
"device_to_device_authenticator_unittest.cc",
diff --git a/chromium/components/cryptauth/background_eid_generator.cc b/chromium/components/cryptauth/background_eid_generator.cc
index 1666c34f464..d7f8e0305ef 100644
--- a/chromium/components/cryptauth/background_eid_generator.cc
+++ b/chromium/components/cryptauth/background_eid_generator.cc
@@ -5,8 +5,8 @@
#include "components/cryptauth/background_eid_generator.h"
#include <cstring>
+#include <memory>
-#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
@@ -43,7 +43,7 @@ const BeaconSeed* GetBeaconSeedForTimestamp(
} // namespace
BackgroundEidGenerator::BackgroundEidGenerator()
- : BackgroundEidGenerator(base::MakeUnique<RawEidGeneratorImpl>(),
+ : BackgroundEidGenerator(std::make_unique<RawEidGeneratorImpl>(),
base::DefaultClock::GetInstance()) {}
BackgroundEidGenerator::~BackgroundEidGenerator() {}
@@ -88,7 +88,7 @@ std::unique_ptr<DataWithTimestamp> BackgroundEidGenerator::GenerateEid(
std::string eid = raw_eid_generator_->GenerateEid(
beacon_seed->data(), start_of_period_ms, nullptr);
- return base::MakeUnique<DataWithTimestamp>(eid, start_of_period_ms,
+ return std::make_unique<DataWithTimestamp>(eid, start_of_period_ms,
start_of_period_ms + kEidPeriodMs);
}
diff --git a/chromium/components/cryptauth/background_eid_generator_unittest.cc b/chromium/components/cryptauth/background_eid_generator_unittest.cc
index be9c24c743d..dbbae6b1bc7 100644
--- a/chromium/components/cryptauth/background_eid_generator_unittest.cc
+++ b/chromium/components/cryptauth/background_eid_generator_unittest.cc
@@ -8,7 +8,6 @@
#include <string>
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
@@ -94,7 +93,7 @@ class CryptAuthBackgroundEidGeneratorTest : public testing::Test {
SetTestTime(kCurrentTimeMs);
eid_generator_.reset(new BackgroundEidGenerator(
- base::MakeUnique<TestRawEidGenerator>(), &test_clock_));
+ std::make_unique<TestRawEidGenerator>(), &test_clock_));
}
void SetTestTime(int64_t timestamp_ms) {
diff --git a/chromium/components/cryptauth/ble/ble_advertisement_generator.cc b/chromium/components/cryptauth/ble/ble_advertisement_generator.cc
index da4f92be229..066827be7f1 100644
--- a/chromium/components/cryptauth/ble/ble_advertisement_generator.cc
+++ b/chromium/components/cryptauth/ble/ble_advertisement_generator.cc
@@ -4,9 +4,9 @@
#include "components/cryptauth/ble/ble_advertisement_generator.h"
+#include <memory>
#include <vector>
-#include "base/memory/ptr_util.h"
#include "components/cryptauth/local_device_data_provider.h"
#include "components/cryptauth/remote_beacon_seed_fetcher.h"
#include "components/cryptauth/remote_device.h"
@@ -37,7 +37,7 @@ void BleAdvertisementGenerator::SetInstanceForTesting(
}
BleAdvertisementGenerator::BleAdvertisementGenerator()
- : eid_generator_(base::MakeUnique<cryptauth::ForegroundEidGenerator>()) {}
+ : eid_generator_(std::make_unique<cryptauth::ForegroundEidGenerator>()) {}
BleAdvertisementGenerator::~BleAdvertisementGenerator() {}
diff --git a/chromium/components/cryptauth/ble/ble_advertisement_generator_unittest.cc b/chromium/components/cryptauth/ble/ble_advertisement_generator_unittest.cc
index 33bd0d7e99d..5cd1369c80f 100644
--- a/chromium/components/cryptauth/ble/ble_advertisement_generator_unittest.cc
+++ b/chromium/components/cryptauth/ble/ble_advertisement_generator_unittest.cc
@@ -4,6 +4,8 @@
#include "components/cryptauth/ble/ble_advertisement_generator.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/callback_forward.h"
#include "base/stl_util.h"
@@ -48,15 +50,15 @@ class CryptAuthBleAdvertisementGeneratorTest : public testing::Test {
fake_advertisement_("advertisement1", 1000L, 2000L) {}
void SetUp() override {
- mock_seed_fetcher_ = base::MakeUnique<MockRemoteBeaconSeedFetcher>();
+ mock_seed_fetcher_ = std::make_unique<MockRemoteBeaconSeedFetcher>();
std::vector<BeaconSeed> device_0_beacon_seeds =
CreateFakeBeaconSeedsForDevice(fake_device_);
mock_seed_fetcher_->SetSeedsForDeviceId(fake_device_.GetDeviceId(),
&device_0_beacon_seeds);
- mock_local_data_provider_ = base::MakeUnique<MockLocalDeviceDataProvider>();
+ mock_local_data_provider_ = std::make_unique<MockLocalDeviceDataProvider>();
mock_local_data_provider_->SetPublicKey(
- base::MakeUnique<std::string>(kFakePublicKey));
+ std::make_unique<std::string>(kFakePublicKey));
generator_ = base::WrapUnique(new BleAdvertisementGenerator());
@@ -93,7 +95,7 @@ TEST_F(CryptAuthBleAdvertisementGeneratorTest, TestCannotFetchPublicKey) {
}
TEST_F(CryptAuthBleAdvertisementGeneratorTest, EmptyPublicKey) {
- mock_local_data_provider_->SetPublicKey(base::MakeUnique<std::string>(""));
+ mock_local_data_provider_->SetPublicKey(std::make_unique<std::string>(""));
EXPECT_EQ(nullptr, GenerateBleAdvertisement());
}
@@ -116,7 +118,7 @@ TEST_F(CryptAuthBleAdvertisementGeneratorTest, CannotGenerateAdvertisement) {
TEST_F(CryptAuthBleAdvertisementGeneratorTest, AdvertisementGenerated) {
mock_eid_generator_->set_advertisement(
- base::MakeUnique<DataWithTimestamp>(fake_advertisement_));
+ std::make_unique<DataWithTimestamp>(fake_advertisement_));
EXPECT_EQ(fake_advertisement_, *GenerateBleAdvertisement());
}
diff --git a/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc b/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc
index 7bbbce231fe..d338b05ac01 100644
--- a/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc
+++ b/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc
@@ -4,12 +4,12 @@
#include "components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h"
+#include <memory>
#include <sstream>
#include <utility>
#include "base/bind.h"
#include "base/location.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/task_runner.h"
@@ -82,7 +82,7 @@ BluetoothLowEnergyWeaveClientConnection::Factory::BuildInstance(
const device::BluetoothUUID remote_service_uuid,
device::BluetoothDevice* bluetooth_device,
bool should_set_low_connection_latency) {
- return base::MakeUnique<BluetoothLowEnergyWeaveClientConnection>(
+ return std::make_unique<BluetoothLowEnergyWeaveClientConnection>(
remote_device, adapter, remote_service_uuid, bluetooth_device,
should_set_low_connection_latency);
}
@@ -151,15 +151,15 @@ BluetoothLowEnergyWeaveClientConnection::
adapter_(adapter),
remote_service_({remote_service_uuid, std::string()}),
packet_generator_(
- base::MakeUnique<BluetoothLowEnergyWeavePacketGenerator>()),
- packet_receiver_(base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketGenerator>()),
+ packet_receiver_(std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
BluetoothLowEnergyWeavePacketReceiver::ReceiverType::CLIENT)),
tx_characteristic_(
{device::BluetoothUUID(kTXCharacteristicUUID), std::string()}),
rx_characteristic_(
{device::BluetoothUUID(kRXCharacteristicUUID), std::string()}),
task_runner_(base::ThreadTaskRunnerHandle::Get()),
- timer_(base::MakeUnique<base::OneShotTimer>()),
+ timer_(std::make_unique<base::OneShotTimer>()),
sub_status_(SubStatus::DISCONNECTED),
weak_ptr_factory_(this) {
adapter_->AddObserver(this);
@@ -167,6 +167,19 @@ BluetoothLowEnergyWeaveClientConnection::
BluetoothLowEnergyWeaveClientConnection::
~BluetoothLowEnergyWeaveClientConnection() {
+ if (sub_status() != SubStatus::DISCONNECTED) {
+ // Deleting this object without calling Disconnect() may result in the
+ // connection staying active longer than intended, which can lead to errors.
+ // See https://crbug.com/763604.
+ PA_LOG(WARNING) << "Warning: Deleting "
+ << "BluetoothLowEnergyWeaveClientConnection object with an "
+ << "active connection to " << GetDeviceInfoLogString()
+ << ". This may result in disconnection errors; trying to "
+ << "send uWeave \"connection close\" packet before "
+ << "deleting.";
+ ClearQueueAndSendConnectionClose();
+ }
+
DestroyConnection(
BleWeaveConnectionResult::BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
}
@@ -233,6 +246,11 @@ void BluetoothLowEnergyWeaveClientConnection::CreateGattConnection() {
void BluetoothLowEnergyWeaveClientConnection::Disconnect() {
if (IsConnected()) {
+ // If a disconnection is already in progress, there is nothing to do.
+ if (has_triggered_disconnection_)
+ return;
+
+ has_triggered_disconnection_ = true;
PA_LOG(INFO) << "Disconnection requested; sending \"connection close\" "
<< "uWeave packet to " << GetDeviceInfoLogString() << ".";
@@ -378,7 +396,7 @@ void BluetoothLowEnergyWeaveClientConnection::SendMessageImpl(
WriteRequestType request_type = (i != weave_packets.size() - 1)
? WriteRequestType::REGULAR
: WriteRequestType::MESSAGE_COMPLETE;
- queued_write_requests_.emplace(base::MakeUnique<WriteRequest>(
+ queued_write_requests_.emplace(std::make_unique<WriteRequest>(
weave_packets[i], request_type, message.get()));
}
@@ -646,7 +664,7 @@ void BluetoothLowEnergyWeaveClientConnection::SendConnectionRequest() {
PA_LOG(INFO) << "Sending \"connection request\" uWeave packet to "
<< GetDeviceInfoLogString();
- queued_write_requests_.emplace(base::MakeUnique<WriteRequest>(
+ queued_write_requests_.emplace(std::make_unique<WriteRequest>(
packet_generator_->CreateConnectionRequest(),
WriteRequestType::CONNECTION_REQUEST));
ProcessNextWriteRequest();
@@ -721,6 +739,8 @@ void BluetoothLowEnergyWeaveClientConnection::OnRemoteCharacteristicWritten() {
WriteRequestType::CONNECTION_CLOSE) {
// Once a "connection close" uWeave packet has been sent, the connection
// is ready to be disconnected.
+ PA_LOG(INFO) << "uWeave \"connection close\" packet sent to "
+ << GetDeviceInfoLogString() << ". Destroying connection.";
DestroyConnection(
BleWeaveConnectionResult::BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
return;
@@ -833,15 +853,17 @@ void BluetoothLowEnergyWeaveClientConnection::
// write, we must wait for it to complete before the "connection close" can
// be sent.
queued_write_requests_.emplace(
- base::MakeUnique<WriteRequest>(packet_generator_->CreateConnectionClose(
+ std::make_unique<WriteRequest>(packet_generator_->CreateConnectionClose(
packet_receiver_->GetReasonToClose()),
WriteRequestType::CONNECTION_CLOSE));
if (pending_write_request_) {
PA_LOG(WARNING) << "Waiting for current write to complete, then will send "
- << "a \"connection close\" uWeave packet.";
+ << "a \"connection close\" uWeave packet to "
+ << GetDeviceInfoLogString() << ".";
} else {
- PA_LOG(INFO) << "Sending a \"connection close\" uWeave packet.";
+ PA_LOG(INFO) << "Sending a \"connection close\" uWeave packet to "
+ << GetDeviceInfoLogString() << ".";
}
ProcessNextWriteRequest();
diff --git a/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h b/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h
index 75d76e3561e..fe5e5c4a78a 100644
--- a/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h
+++ b/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h
@@ -173,6 +173,8 @@ class BluetoothLowEnergyWeaveClientConnection
FRIEND_TEST_ALL_PREFIXES(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
ConnectSuccessDisconnect);
FRIEND_TEST_ALL_PREFIXES(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
+ DisconnectCalledTwice);
+ FRIEND_TEST_ALL_PREFIXES(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
ConnectSuccessDisconnect_DoNotSetLowLatency);
FRIEND_TEST_ALL_PREFIXES(
CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
@@ -358,6 +360,8 @@ class BluetoothLowEnergyWeaveClientConnection
bool should_set_low_connection_latency_;
+ bool has_triggered_disconnection_ = false;
+
// Tracks if the result of this connection has been recorded (using
// BleWeaveConnectionResult). The result of a connection should only be
// recorded once.
diff --git a/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc b/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc
index 3864a1e81af..9aea84df355 100644
--- a/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc
+++ b/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc
@@ -352,18 +352,18 @@ class CryptAuthBluetoothLowEnergyWeaveClientConnectionTest
task_runner_ = base::MakeRefCounted<base::TestSimpleTaskRunner>();
mock_bluetooth_device_ =
- base::MakeUnique<NiceMock<device::MockBluetoothDevice>>(
+ std::make_unique<NiceMock<device::MockBluetoothDevice>>(
adapter_.get(), 0, kTestRemoteDeviceName,
kTestRemoteDeviceBluetoothAddress, false, false);
- service_ = base::MakeUnique<NiceMock<device::MockBluetoothGattService>>(
+ service_ = std::make_unique<NiceMock<device::MockBluetoothGattService>>(
mock_bluetooth_device_.get(), kServiceID, service_uuid_, true, false);
tx_characteristic_ =
- base::MakeUnique<NiceMock<device::MockBluetoothGattCharacteristic>>(
+ std::make_unique<NiceMock<device::MockBluetoothGattCharacteristic>>(
service_.get(), kTXCharacteristicID, tx_characteristic_uuid_, false,
kCharacteristicProperties,
device::BluetoothRemoteGattCharacteristic::PERMISSION_NONE);
rx_characteristic_ =
- base::MakeUnique<NiceMock<device::MockBluetoothGattCharacteristic>>(
+ std::make_unique<NiceMock<device::MockBluetoothGattCharacteristic>>(
service_.get(), kRXCharacteristicID, rx_characteristic_uuid_, false,
kCharacteristicProperties,
device::BluetoothRemoteGattCharacteristic::PERMISSION_NONE);
@@ -464,7 +464,7 @@ class CryptAuthBluetoothLowEnergyWeaveClientConnectionTest
Return(new NiceMock<MockBluetoothLowEnergyCharacteristicsFinder>)));
create_gatt_connection_success_callback_.Run(
- base::MakeUnique<NiceMock<device::MockBluetoothGattConnection>>(
+ std::make_unique<NiceMock<device::MockBluetoothGattConnection>>(
adapter_, kTestRemoteDeviceBluetoothAddress));
EXPECT_EQ(connection->sub_status(), SubStatus::WAITING_CHARACTERISTICS);
@@ -564,9 +564,6 @@ class CryptAuthBluetoothLowEnergyWeaveClientConnectionTest
connection->Disconnect();
if (connection->IsConnected()) {
- connection->DestroyConnection(
- BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult::
- BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
EXPECT_EQ(last_value_written_on_tx_characteristic_,
kConnectionCloseSuccess);
RunWriteCharacteristicSuccessCallback();
@@ -576,6 +573,21 @@ class CryptAuthBluetoothLowEnergyWeaveClientConnectionTest
EXPECT_EQ(connection->status(), Connection::DISCONNECTED);
}
+ void DeleteConnectionWithoutCallingDisconnect(
+ std::unique_ptr<TestBluetoothLowEnergyWeaveClientConnection>*
+ connection) {
+ bool was_connected = (*connection)->IsConnected();
+ if (was_connected) {
+ EXPECT_CALL(*tx_characteristic_, WriteRemoteCharacteristic(_, _, _))
+ .WillOnce(
+ DoAll(SaveArg<0>(&last_value_written_on_tx_characteristic_),
+ SaveArg<1>(&write_remote_characteristic_success_callback_),
+ SaveArg<2>(&write_remote_characteristic_error_callback_)));
+ }
+
+ connection->reset();
+ }
+
void InitializeConnection(
TestBluetoothLowEnergyWeaveClientConnection* connection,
uint32_t selected_packet_size) {
@@ -691,7 +703,7 @@ class CryptAuthBluetoothLowEnergyWeaveClientConnectionTest
TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
CreateAndDestroyWithoutConnectCallDoesntCrash) {
std::unique_ptr<BluetoothLowEnergyWeaveClientConnection> connection =
- base::MakeUnique<BluetoothLowEnergyWeaveClientConnection>(
+ std::make_unique<BluetoothLowEnergyWeaveClientConnection>(
remote_device_, adapter_, service_uuid_, mock_bluetooth_device_.get(),
true /* should_set_low_connection_latency */);
@@ -707,7 +719,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
CreateConnection(true /* should_set_low_connection_latency */));
Disconnect(connection.get());
- connection.reset();
+ DeleteConnectionWithoutCallingDisconnect(&connection);
VerifyBleWeaveConnectionResult(
BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult::
BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
@@ -722,7 +734,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
NotifySessionStarted(connection.get());
ConnectionResponseReceived(connection.get(), kDefaultMaxPacketSize);
- connection.reset();
+ DeleteConnectionWithoutCallingDisconnect(&connection);
VerifyBleWeaveConnectionResult(
BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult::
BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
@@ -742,6 +754,34 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
}
TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
+ DisconnectCalledTwice) {
+ std::unique_ptr<TestBluetoothLowEnergyWeaveClientConnection> connection(
+ CreateConnection(true /* should_set_low_connection_latency */));
+ InitializeConnection(connection.get(), kDefaultMaxPacketSize);
+ EXPECT_EQ(connection->sub_status(), SubStatus::CONNECTED_AND_IDLE);
+
+ EXPECT_CALL(*tx_characteristic_, WriteRemoteCharacteristic(_, _, _))
+ .WillOnce(
+ DoAll(SaveArg<0>(&last_value_written_on_tx_characteristic_),
+ SaveArg<1>(&write_remote_characteristic_success_callback_),
+ SaveArg<2>(&write_remote_characteristic_error_callback_)));
+
+ // Call Disconnect() twice; this should only result in one "close connection"
+ // message (verified via WillOnce() above).
+ connection->Disconnect();
+ connection->Disconnect();
+
+ EXPECT_EQ(last_value_written_on_tx_characteristic_, kConnectionCloseSuccess);
+ RunWriteCharacteristicSuccessCallback();
+
+ EXPECT_EQ(connection->sub_status(), SubStatus::DISCONNECTED);
+ EXPECT_EQ(connection->status(), Connection::DISCONNECTED);
+ VerifyBleWeaveConnectionResult(
+ BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult::
+ BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
+}
+
+TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
ConnectSuccessDisconnect_DoNotSetLowLatency) {
std::unique_ptr<TestBluetoothLowEnergyWeaveClientConnection> connection(
CreateConnection(false /* should_set_low_connection_latency */));
@@ -774,7 +814,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
CharacteristicsFound(connection.get());
Disconnect(connection.get());
- connection.reset();
+ DeleteConnectionWithoutCallingDisconnect(&connection);
VerifyBleWeaveConnectionResult(
BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult::
BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
@@ -922,7 +962,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
EXPECT_EQ(received_bytes, kSmallMessage);
- connection.reset();
+ DeleteConnectionWithoutCallingDisconnect(&connection);
VerifyBleWeaveConnectionResult(
BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult::
BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
@@ -947,7 +987,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
}
EXPECT_EQ(received_bytes, kLargeMessage);
- connection.reset();
+ DeleteConnectionWithoutCallingDisconnect(&connection);
VerifyBleWeaveConnectionResult(
BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult::
BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
@@ -968,7 +1008,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
SaveArg<2>(&write_remote_characteristic_error_callback_)));
connection->SendMessage(
- base::MakeUnique<FakeWireMessage>(kSmallMessage, kTestFeature));
+ std::make_unique<FakeWireMessage>(kSmallMessage, kTestFeature));
EXPECT_EQ(last_value_written_on_tx_characteristic_, kSmallPackets0);
@@ -979,7 +1019,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
EXPECT_EQ(kSmallMessage, connection_observer_->GetLastDeserializedMessage());
EXPECT_TRUE(connection_observer_->last_send_success());
- connection.reset();
+ DeleteConnectionWithoutCallingDisconnect(&connection);
VerifyBleWeaveConnectionResult(
BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult::
BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
@@ -1001,7 +1041,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
SaveArg<2>(&write_remote_characteristic_error_callback_)));
connection->SendMessage(
- base::MakeUnique<FakeWireMessage>(kLargeMessage, kTestFeature));
+ std::make_unique<FakeWireMessage>(kLargeMessage, kTestFeature));
EXPECT_EQ(last_value_written_on_tx_characteristic_, kLargePackets0);
std::vector<uint8_t> bytes_received(
@@ -1030,7 +1070,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
EXPECT_EQ(kLargeMessage, connection_observer_->GetLastDeserializedMessage());
EXPECT_TRUE(connection_observer_->last_send_success());
- connection.reset();
+ DeleteConnectionWithoutCallingDisconnect(&connection);
VerifyBleWeaveConnectionResult(
BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult::
BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
@@ -1050,7 +1090,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
SaveArg<2>(&write_remote_characteristic_error_callback_)));
connection->SendMessage(
- base::MakeUnique<FakeWireMessage>(kSmallMessage, kTestFeature));
+ std::make_unique<FakeWireMessage>(kSmallMessage, kTestFeature));
for (int i = 0; i < kMaxNumberOfTries; i++) {
EXPECT_EQ(last_value_written_on_tx_characteristic_, kSmallPackets0);
@@ -1141,7 +1181,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
SaveArg<2>(&write_remote_characteristic_error_callback_)));
connection->SendMessage(
- base::MakeUnique<FakeWireMessage>(kLargeMessage, kTestFeature));
+ std::make_unique<FakeWireMessage>(kLargeMessage, kTestFeature));
connection->GattCharacteristicValueChanged(
adapter_.get(), rx_characteristic_.get(), kErroneousPacket);
@@ -1214,13 +1254,14 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
InitializeConnection(connection, kDefaultMaxPacketSize);
EXPECT_CALL(*tx_characteristic_, WriteRemoteCharacteristic(_, _, _))
- .WillOnce(
+ .Times(2)
+ .WillRepeatedly(
DoAll(SaveArg<0>(&last_value_written_on_tx_characteristic_),
SaveArg<1>(&write_remote_characteristic_success_callback_),
SaveArg<2>(&write_remote_characteristic_error_callback_)));
connection->SendMessage(
- base::MakeUnique<FakeWireMessage>(kSmallMessage, kTestFeature));
+ std::make_unique<FakeWireMessage>(kSmallMessage, kTestFeature));
EXPECT_EQ(last_value_written_on_tx_characteristic_, kSmallPackets0);
RunWriteCharacteristicSuccessCallback();
@@ -1230,6 +1271,9 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
EXPECT_EQ(kSmallMessage, connection_observer_->GetLastDeserializedMessage());
EXPECT_TRUE(connection_observer_->last_send_success());
+ // Connection close packet should have been sent when the object was deleted.
+ EXPECT_EQ(last_value_written_on_tx_characteristic_, kConnectionCloseSuccess);
+
// We cannot check if connection's status and sub_status are DISCONNECTED
// because it has been deleted.
@@ -1321,7 +1365,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
Return(new NiceMock<MockBluetoothLowEnergyCharacteristicsFinder>)));
create_gatt_connection_success_callback_.Run(
- base::MakeUnique<NiceMock<device::MockBluetoothGattConnection>>(
+ std::make_unique<NiceMock<device::MockBluetoothGattConnection>>(
adapter_, kTestRemoteDeviceBluetoothAddress));
CharacteristicsFound(connection.get());
@@ -1330,7 +1374,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
VerifyGattConnectionResultSuccess();
- connection.reset();
+ DeleteConnectionWithoutCallingDisconnect(&connection);
VerifyBleWeaveConnectionResult(
BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult::
BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
@@ -1366,7 +1410,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
Return(new NiceMock<MockBluetoothLowEnergyCharacteristicsFinder>)));
create_gatt_connection_success_callback_.Run(
- base::MakeUnique<NiceMock<device::MockBluetoothGattConnection>>(
+ std::make_unique<NiceMock<device::MockBluetoothGattConnection>>(
adapter_, kTestRemoteDeviceBluetoothAddress));
CharacteristicsFound(connection.get());
@@ -1375,7 +1419,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest,
VerifyGattConnectionResultSuccess();
- connection.reset();
+ DeleteConnectionWithoutCallingDisconnect(&connection);
VerifyBleWeaveConnectionResult(
BluetoothLowEnergyWeaveClientConnection::BleWeaveConnectionResult::
BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY);
diff --git a/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_packet_generator_unittest.cc b/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_packet_generator_unittest.cc
index f9bf22575f4..0dbe5b86452 100644
--- a/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_packet_generator_unittest.cc
+++ b/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_packet_generator_unittest.cc
@@ -5,11 +5,11 @@
#include "components/cryptauth/ble/bluetooth_low_energy_weave_packet_generator.h"
#include <algorithm>
+#include <memory>
#include <string>
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -24,7 +24,7 @@ class CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest
void TestConnectionCloseWithReason(ReasonForClose reason_for_close,
uint8_t expected_reason_for_close) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
- base::MakeUnique<BluetoothLowEnergyWeavePacketGenerator>();
+ std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
Packet packet = generator->CreateConnectionClose(reason_for_close);
@@ -52,7 +52,7 @@ class CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
CreateConnectionRequestTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
- base::MakeUnique<BluetoothLowEnergyWeavePacketGenerator>();
+ std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
Packet packet = generator->CreateConnectionRequest();
@@ -77,7 +77,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
CreateConnectionResponseWithDefaultPacketSizeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
- base::MakeUnique<BluetoothLowEnergyWeavePacketGenerator>();
+ std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
Packet packet = generator->CreateConnectionResponse();
@@ -97,7 +97,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
CreateConnectionResponseWithSelectedPacketSizeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
- base::MakeUnique<BluetoothLowEnergyWeavePacketGenerator>();
+ std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
const uint8_t kSelectedPacketSize = 30;
const uint16_t kResponseSize = 5;
@@ -138,7 +138,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
EncodeDataMessageWithDefaultPacketSizeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
- base::MakeUnique<BluetoothLowEnergyWeavePacketGenerator>();
+ std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
std::string data = "abcdefghijklmnopqrstuvwxyz";
@@ -171,7 +171,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
EncodeDataMessageWithSelectedPacketSizeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
- base::MakeUnique<BluetoothLowEnergyWeavePacketGenerator>();
+ std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
const uint32_t packet_size = 30;
const uint32_t residual_packet_size = 2;
@@ -223,7 +223,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
PacketCounterForMixedPacketTypesTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
- base::MakeUnique<BluetoothLowEnergyWeavePacketGenerator>();
+ std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
Packet packet = generator->CreateConnectionRequest();
@@ -242,7 +242,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketGeneratorTest,
PacketCounterWrappedAroundTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> generator =
- base::MakeUnique<BluetoothLowEnergyWeavePacketGenerator>();
+ std::make_unique<BluetoothLowEnergyWeavePacketGenerator>();
const uint8_t kNumPackets = 100;
std::string data(kNumPackets * kByteDefaultMaxPacketSize, 'a');
diff --git a/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_packet_receiver_unittest.cc b/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_packet_receiver_unittest.cc
index a76d19bd2fb..db5e612fde0 100644
--- a/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_packet_receiver_unittest.cc
+++ b/chromium/components/cryptauth/ble/bluetooth_low_energy_weave_packet_receiver_unittest.cc
@@ -5,10 +5,10 @@
#include "components/cryptauth/ble/bluetooth_low_energy_weave_packet_receiver.h"
#include <algorithm>
+#include <memory>
#include <string>
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -50,7 +50,7 @@ class CryptAuthBluetoothLowEnergyWeavePacketReceiverTest
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
WellBehavingServerPacketsNoControlDataTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
@@ -111,7 +111,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
WellBehavingServerPacketsWithFullControlDataTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader,
@@ -177,7 +177,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
WellBehavingServerPacketsWithSomeControlDataTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
@@ -227,7 +227,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
WellBehavingClientPacketsNoControlDataTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
const uint8_t kSelectedPacketSize = 30;
@@ -266,7 +266,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
WellBehavingClientPacketsWithFullControlDataTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
std::vector<uint8_t> p0{kControlResponseHeader,
@@ -319,7 +319,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
WellBehavingClientPacketsWithSomeControlDataTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
std::vector<uint8_t> p0{kControlResponseHeader,
@@ -360,7 +360,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
LegacyCloseWithoutReasonTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
@@ -384,7 +384,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
OneBytePacketTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
std::vector<uint8_t> p0{kControlResponseHeader, kEmptyUpperByte,
@@ -409,7 +409,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
EmptyPacketTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
std::vector<uint8_t> p0;
@@ -422,7 +422,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
ServerReceivingConnectionResponseTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlResponseHeader, kEmptyUpperByte,
kByteWeaveVersion, kEmptyUpperByte,
@@ -437,7 +437,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
ClientReceivingConnectionRequestTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
kByteWeaveVersion, kEmptyUpperByte,
@@ -453,7 +453,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
ReceiveConnectionCloseInConnecting) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
// uWeave Header:
@@ -472,7 +472,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
ReceiveDataInConnecting) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
// uWeave Header:
@@ -493,7 +493,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
ConnectionRequestTooSmallTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
kByteWeaveVersion, kEmptyUpperByte,
@@ -508,7 +508,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
ConnectionRequestTooLargeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0(kByteDefaultMaxPacketSize + 1, 0);
@@ -525,7 +525,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
ConnectionResponseTooSmallTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
std::vector<uint8_t> p0{kControlResponseHeader, kEmptyUpperByte,
@@ -540,7 +540,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
ConnectionResponseTooLargeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
std::vector<uint8_t> p0(kByteDefaultMaxPacketSize + 1, 0);
@@ -557,7 +557,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
ConnectionCloseTooLargeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
@@ -582,7 +582,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
DataPacketTooLargeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
@@ -611,7 +611,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
FirstPacketNoFirstNorLastBitTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
@@ -640,7 +640,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
FirstPacketNoFirstYesLastBitTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
@@ -669,7 +669,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
NonFirstPacketYesFirstBitTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
@@ -709,7 +709,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
OutOfOrderPacketTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
@@ -738,7 +738,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
InvalidVersionInConnectionRequestTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
const uint8_t kWrongVersion = 2;
@@ -759,7 +759,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
const uint8_t kSmallMaxPacketSize = 19;
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
@@ -776,7 +776,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
InvalidSelectedVersionInConnectionResponseTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
std::vector<uint8_t> p0{kControlResponseHeader, kByteWeaveVersion,
@@ -793,7 +793,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
InvalidSelectedMaxPacketSizeInConnectionResponseTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
const uint8_t kSmallMaxPacketSize = 19;
@@ -810,7 +810,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
UnrecognizedReasonForCloseInConnectionCloseTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
std::vector<uint8_t> p0{kControlResponseHeader, kEmptyUpperByte,
@@ -836,7 +836,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
UnrecognizedControlCommandBitTwoTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
// uWeave Header:
@@ -861,7 +861,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
InvalidControlCommandBitThreeTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
// uWeave Header:
@@ -881,7 +881,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
InvalidBitOneInDataPacketHeaderTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
std::vector<uint8_t> p0{kControlResponseHeader, kEmptyUpperByte,
@@ -908,7 +908,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
InvalidBitZeroInDataPacketHeaderTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
std::vector<uint8_t> p0{kControlResponseHeader, kEmptyUpperByte,
@@ -935,7 +935,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
ReceivedPacketInErrorState) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::CLIENT);
std::vector<uint8_t> p0;
@@ -955,7 +955,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
ReceivedPacketInConnectionClosedStateTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
@@ -993,7 +993,7 @@ TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
TEST_F(CryptAuthBluetoothLowEnergyWeavePacketReceiverTest,
MultipleControlPacketTest) {
std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> receiver =
- base::MakeUnique<BluetoothLowEnergyWeavePacketReceiver>(
+ std::make_unique<BluetoothLowEnergyWeavePacketReceiver>(
ReceiverType::SERVER);
std::vector<uint8_t> p0{kControlRequestHeader, kEmptyUpperByte,
diff --git a/chromium/components/cryptauth/cryptauth_client_impl.cc b/chromium/components/cryptauth/cryptauth_client_impl.cc
index 8fbe82e07a1..f16b4a29bf1 100644
--- a/chromium/components/cryptauth/cryptauth_client_impl.cc
+++ b/chromium/components/cryptauth/cryptauth_client_impl.cc
@@ -4,6 +4,7 @@
#include "components/cryptauth/cryptauth_client_impl.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -333,7 +334,7 @@ CryptAuthClientFactoryImpl::~CryptAuthClientFactoryImpl() {
}
std::unique_ptr<CryptAuthClient> CryptAuthClientFactoryImpl::CreateInstance() {
- return base::MakeUnique<CryptAuthClientImpl>(
+ return std::make_unique<CryptAuthClientImpl>(
base::WrapUnique(new CryptAuthApiCallFlow()),
base::WrapUnique(
new CryptAuthAccessTokenFetcherImpl(token_service_, account_id_)),
diff --git a/chromium/components/cryptauth/cryptauth_device_manager.cc b/chromium/components/cryptauth/cryptauth_device_manager.cc
index c32e6f38d80..dd522ee6832 100644
--- a/chromium/components/cryptauth/cryptauth_device_manager.cc
+++ b/chromium/components/cryptauth/cryptauth_device_manager.cc
@@ -4,373 +4,11 @@
#include "components/cryptauth/cryptauth_device_manager.h"
-#include <stddef.h>
-#include <stdexcept>
-#include <utility>
-
-#include "base/base64url.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "components/cryptauth/cryptauth_client.h"
#include "components/cryptauth/pref_names.h"
-#include "components/cryptauth/sync_scheduler_impl.h"
#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/scoped_user_pref_update.h"
-#include "components/proximity_auth/logging/logging.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
namespace cryptauth {
-namespace {
-
-// The normal period between successful syncs, in hours.
-const int kRefreshPeriodHours = 24;
-
-// A more aggressive period between sync attempts to recover when the last
-// sync attempt fails, in minutes. This is a base time that increases for each
-// subsequent failure.
-const int kDeviceSyncBaseRecoveryPeriodMinutes = 10;
-
-// The bound on the amount to jitter the period between syncs.
-const double kDeviceSyncMaxJitterRatio = 0.2;
-
-// Keys for ExternalDeviceInfo dictionaries that are stored in the user's prefs.
-const char kExternalDeviceKeyPublicKey[] = "public_key";
-const char kExternalDeviceKeyDeviceName[] = "device_name";
-const char kExternalDeviceKeyBluetoothAddress[] = "bluetooth_address";
-const char kExternalDeviceKeyUnlockKey[] = "unlock_key";
-const char kExternalDeviceKeyUnlockable[] = "unlockable";
-const char kExternalDeviceKeyLastUpdateTimeMillis[] = "last_update_time_millis";
-const char kExternalDeviceKeyMobileHotspotSupported[] =
- "mobile_hotspot_supported";
-const char kExternalDeviceKeyDeviceType[] = "device_type";
-const char kExternalDeviceKeyBeaconSeeds[] = "beacon_seeds";
-const char kExternalDeviceKeyArcPlusPlus[] = "arc_plus_plus";
-const char kExternalDeviceKeyPixelPhone[] = "pixel_phone";
-const char kExternalDeviceKeyBeaconSeedData[] = "beacon_seed_data";
-const char kExternalDeviceKeyBeaconSeedStartMs[] = "beacon_seed_start_ms";
-const char kExternalDeviceKeyBeaconSeedEndMs[] = "beacon_seed_end_ms";
-
-// Converts BeaconSeed protos to a list value that can be stored in user prefs.
-std::unique_ptr<base::ListValue> BeaconSeedsToListValue(
- const google::protobuf::RepeatedPtrField<BeaconSeed>& seeds) {
- std::unique_ptr<base::ListValue> list(new base::ListValue());
-
- for (int i = 0; i < seeds.size(); i++) {
- BeaconSeed seed = seeds.Get(i);
-
- if (!seed.has_data()
- || !seed.has_start_time_millis()
- || !seed.has_end_time_millis()) {
- PA_LOG(WARNING) << "Unable to serialize BeaconSeed due to missing data; "
- << "skipping.";
- continue;
- }
-
- std::unique_ptr<base::DictionaryValue> beacon_seed_value(
- new base::DictionaryValue());
-
- // Note that the |BeaconSeed|s' data is stored in Base64Url encoding because
- // dictionary values must be valid UTF8 strings.
- std::string seed_data_b64;
- base::Base64UrlEncode(seed.data(),
- base::Base64UrlEncodePolicy::INCLUDE_PADDING,
- &seed_data_b64);
- beacon_seed_value->SetString(kExternalDeviceKeyBeaconSeedData,
- seed_data_b64);
-
- // Set the timestamps as string representations of their numeric value
- // since there is no notion of a base::LongValue.
- beacon_seed_value->SetString(
- kExternalDeviceKeyBeaconSeedStartMs,
- std::to_string(seed.start_time_millis()));
- beacon_seed_value->SetString(
- kExternalDeviceKeyBeaconSeedEndMs,
- std::to_string(seed.end_time_millis()));
-
- list->Append(std::move(beacon_seed_value));
- }
-
- return list;
-}
-
-// Converts an unlock key proto to a dictionary that can be stored in user
-// prefs.
-std::unique_ptr<base::DictionaryValue> UnlockKeyToDictionary(
- const ExternalDeviceInfo& device) {
- // The device public key is a required value.
- if (!device.has_public_key()) {
- return nullptr;
- }
-
- std::unique_ptr<base::DictionaryValue> dictionary(
- new base::DictionaryValue());
-
- // Note that the device public key, name, and Bluetooth addresses are stored
- // in Base64Url form because dictionary values must be valid UTF8 strings.
-
- std::string public_key_b64;
- base::Base64UrlEncode(device.public_key(),
- base::Base64UrlEncodePolicy::INCLUDE_PADDING,
- &public_key_b64);
- dictionary->SetString(kExternalDeviceKeyPublicKey, public_key_b64);
-
- if (device.has_friendly_device_name()) {
- std::string device_name_b64;
- base::Base64UrlEncode(device.friendly_device_name(),
- base::Base64UrlEncodePolicy::INCLUDE_PADDING,
- &device_name_b64);
- dictionary->SetString(kExternalDeviceKeyDeviceName, device_name_b64);
- }
-
- if (device.has_bluetooth_address()) {
- std::string bluetooth_address_b64;
- base::Base64UrlEncode(device.bluetooth_address(),
- base::Base64UrlEncodePolicy::INCLUDE_PADDING,
- &bluetooth_address_b64);
- dictionary->SetString(kExternalDeviceKeyBluetoothAddress,
- bluetooth_address_b64);
- }
-
- if (device.has_unlock_key()) {
- dictionary->SetBoolean(kExternalDeviceKeyUnlockKey,
- device.unlock_key());
- }
-
- if (device.has_unlockable()) {
- dictionary->SetBoolean(kExternalDeviceKeyUnlockable,
- device.unlockable());
- }
-
- if (device.has_last_update_time_millis()) {
- dictionary->SetString(kExternalDeviceKeyLastUpdateTimeMillis,
- std::to_string(device.last_update_time_millis()));
- }
-
- if (device.has_mobile_hotspot_supported()) {
- dictionary->SetBoolean(kExternalDeviceKeyMobileHotspotSupported,
- device.mobile_hotspot_supported());
- }
-
- if (device.has_device_type() && DeviceType_IsValid(device.device_type())) {
- dictionary->SetInteger(kExternalDeviceKeyDeviceType,
- device.device_type());
- }
-
- if (device.has_arc_plus_plus()) {
- dictionary->SetBoolean(kExternalDeviceKeyArcPlusPlus,
- device.arc_plus_plus());
- }
-
- if (device.has_pixel_phone()) {
- dictionary->SetBoolean(kExternalDeviceKeyPixelPhone, device.pixel_phone());
- }
-
- std::unique_ptr<base::ListValue> beacon_seed_list =
- BeaconSeedsToListValue(device.beacon_seeds());
- dictionary->Set(kExternalDeviceKeyBeaconSeeds, std::move(beacon_seed_list));
-
- return dictionary;
-}
-
-void AddBeaconSeedsToExternalDevice(
- const base::ListValue& beacon_seeds,
- ExternalDeviceInfo& external_device) {
- for (size_t i = 0; i < beacon_seeds.GetSize(); i++) {
- const base::DictionaryValue* seed_dictionary = nullptr;
- if (!beacon_seeds.GetDictionary(i, &seed_dictionary)) {
- PA_LOG(WARNING) << "Unable to retrieve BeaconSeed dictionary; "
- << "skipping.";
- continue;
- }
-
- std::string seed_data_b64, start_time_millis_str, end_time_millis_str;
- if (!seed_dictionary->GetString(kExternalDeviceKeyBeaconSeedData,
- &seed_data_b64) ||
- !seed_dictionary->GetString(kExternalDeviceKeyBeaconSeedStartMs,
- &start_time_millis_str) ||
- !seed_dictionary->GetString(kExternalDeviceKeyBeaconSeedEndMs,
- &end_time_millis_str)) {
- PA_LOG(WARNING) << "Unable to deserialize BeaconSeed due to missing "
- << "data; skipping.";
- continue;
- }
-
- // Seed data is returned as raw data, not in Base64 encoding.
- std::string seed_data;
- if (!base::Base64UrlDecode(seed_data_b64,
- base::Base64UrlDecodePolicy::REQUIRE_PADDING,
- &seed_data)) {
- PA_LOG(WARNING) << "Decoding seed data failed.";
- continue;
- }
-
- int64_t start_time_millis, end_time_millis;
- if (!base::StringToInt64(start_time_millis_str, &start_time_millis)
- || !base::StringToInt64(end_time_millis_str, &end_time_millis)) {
- PA_LOG(WARNING) << "Unable to convert stored timestamp to int64_t: "
- << start_time_millis_str << " or " << end_time_millis_str;
- continue;
- }
-
- BeaconSeed* seed = external_device.add_beacon_seeds();
- seed->set_data(seed_data);
- seed->set_start_time_millis(start_time_millis);
- seed->set_end_time_millis(end_time_millis);
- }
-}
-
-// Converts an unlock key dictionary stored in user prefs to an
-// ExternalDeviceInfo proto. Returns true if the dictionary is valid, and the
-// parsed proto is written to |external_device|.
-bool DictionaryToUnlockKey(const base::DictionaryValue& dictionary,
- ExternalDeviceInfo* external_device) {
- std::string public_key_b64;
- if (!dictionary.GetString(kExternalDeviceKeyPublicKey, &public_key_b64)) {
- // The public key is a required field, so if it is absent, there is no
- // valid data to return.
- return false;
- }
-
- std::string public_key;
- if (!base::Base64UrlDecode(public_key_b64,
- base::Base64UrlDecodePolicy::REQUIRE_PADDING,
- &public_key)) {
- // The public key is stored as a Base64Url, so if it cannot be decoded,
- // there is no valid data to return.
- return false;
- }
- external_device->set_public_key(public_key);
-
- std::string device_name_b64;
- if (dictionary.GetString(kExternalDeviceKeyDeviceName, &device_name_b64)) {
- std::string device_name;
- if (base::Base64UrlDecode(device_name_b64,
- base::Base64UrlDecodePolicy::REQUIRE_PADDING,
- &device_name)) {
- external_device->set_friendly_device_name(device_name);
- }
- }
-
- std::string bluetooth_address_b64;
- if (dictionary.GetString(
- kExternalDeviceKeyBluetoothAddress, &bluetooth_address_b64)) {
- std::string bluetooth_address;
- if (base::Base64UrlDecode(bluetooth_address_b64,
- base::Base64UrlDecodePolicy::REQUIRE_PADDING,
- &bluetooth_address)) {
- external_device->set_bluetooth_address(bluetooth_address);
- }
- }
-
- bool unlock_key;
- if (dictionary.GetBoolean(kExternalDeviceKeyUnlockKey, &unlock_key))
- external_device->set_unlock_key(unlock_key);
-
- bool unlockable;
- if (dictionary.GetBoolean(kExternalDeviceKeyUnlockable, &unlockable))
- external_device->set_unlockable(unlockable);
-
- std::string last_update_time_millis_str;
- if (dictionary.GetString(
- kExternalDeviceKeyLastUpdateTimeMillis, &last_update_time_millis_str)) {
- int64_t last_update_time_millis;
- if (base::StringToInt64(
- last_update_time_millis_str, &last_update_time_millis)) {
- external_device->set_last_update_time_millis(last_update_time_millis);
- } else {
- PA_LOG(WARNING) << "Unable to convert stored update time to int64_t: "
- << last_update_time_millis_str;
- }
- }
-
- bool mobile_hotspot_supported;
- if (dictionary.GetBoolean(
- kExternalDeviceKeyMobileHotspotSupported, &mobile_hotspot_supported)) {
- external_device->set_mobile_hotspot_supported(mobile_hotspot_supported);
- }
-
- int device_type;
- if (dictionary.GetInteger(kExternalDeviceKeyDeviceType, &device_type)) {
- if (DeviceType_IsValid(device_type)) {
- external_device->set_device_type(static_cast<DeviceType>(device_type));
- }
- }
-
- const base::ListValue* beacon_seeds = nullptr;
- dictionary.GetList(kExternalDeviceKeyBeaconSeeds, &beacon_seeds);
- if (beacon_seeds)
- AddBeaconSeedsToExternalDevice(*beacon_seeds, *external_device);
-
- bool arc_plus_plus;
- if (dictionary.GetBoolean(kExternalDeviceKeyArcPlusPlus, &arc_plus_plus))
- external_device->set_arc_plus_plus(arc_plus_plus);
-
- bool pixel_phone;
- if (dictionary.GetBoolean(kExternalDeviceKeyPixelPhone, &pixel_phone))
- external_device->set_pixel_phone(pixel_phone);
-
- return true;
-}
-
-std::unique_ptr<SyncSchedulerImpl> CreateSyncScheduler(
- SyncScheduler::Delegate* delegate) {
- return base::MakeUnique<SyncSchedulerImpl>(
- delegate, base::TimeDelta::FromHours(kRefreshPeriodHours),
- base::TimeDelta::FromMinutes(kDeviceSyncBaseRecoveryPeriodMinutes),
- kDeviceSyncMaxJitterRatio, "CryptAuth DeviceSync");
-}
-
-} // namespace
-
-CryptAuthDeviceManager::CryptAuthDeviceManager(
- base::Clock* clock,
- std::unique_ptr<CryptAuthClientFactory> client_factory,
- CryptAuthGCMManager* gcm_manager,
- PrefService* pref_service)
- : clock_(clock),
- client_factory_(std::move(client_factory)),
- gcm_manager_(gcm_manager),
- pref_service_(pref_service),
- scheduler_(CreateSyncScheduler(this)),
- weak_ptr_factory_(this) {
- UpdateUnlockKeysFromPrefs();
-}
-
-// Test-only constructor.
-CryptAuthDeviceManager::CryptAuthDeviceManager()
- : clock_(nullptr),
- client_factory_(nullptr),
- gcm_manager_(nullptr),
- pref_service_(nullptr),
- weak_ptr_factory_(this) {}
-
-CryptAuthDeviceManager::~CryptAuthDeviceManager() {
- if (gcm_manager_) {
- gcm_manager_->RemoveObserver(this);
- }
-}
-
-void CryptAuthDeviceManager::SetSyncSchedulerForTest(
- std::unique_ptr<SyncScheduler> sync_scheduler) {
- scheduler_ = std::move(sync_scheduler);
-}
-
-void CryptAuthDeviceManager::NotifySyncStarted() {
- for (auto& observer : observers_) {
- observer.OnSyncStarted();
- }
-}
-
-void CryptAuthDeviceManager::NotifySyncFinished(
- SyncResult sync_result,
- DeviceChangeResult device_change_result) {
- for (auto& observer : observers_) {
- observer.OnSyncFinished(sync_result, device_change_result);
- }
-}
-
// static
void CryptAuthDeviceManager::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterDoublePref(prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds,
@@ -382,23 +20,9 @@ void CryptAuthDeviceManager::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterListPref(prefs::kCryptAuthDeviceSyncUnlockKeys);
}
-void CryptAuthDeviceManager::Start() {
- gcm_manager_->AddObserver(this);
-
- base::Time last_successful_sync = GetLastSyncTime();
- base::TimeDelta elapsed_time_since_last_sync =
- clock_->Now() - last_successful_sync;
+CryptAuthDeviceManager::CryptAuthDeviceManager() = default;
- bool is_recovering_from_failure =
- pref_service_->GetBoolean(
- prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure) ||
- last_successful_sync.is_null();
-
- scheduler_->Start(elapsed_time_since_last_sync,
- is_recovering_from_failure
- ? SyncScheduler::Strategy::AGGRESSIVE_RECOVERY
- : SyncScheduler::Strategy::PERIODIC_REFRESH);
-}
+CryptAuthDeviceManager::~CryptAuthDeviceManager() = default;
void CryptAuthDeviceManager::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
@@ -408,225 +32,16 @@ void CryptAuthDeviceManager::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
-void CryptAuthDeviceManager::ForceSyncNow(
- InvocationReason invocation_reason) {
- pref_service_->SetInteger(prefs::kCryptAuthDeviceSyncReason,
- invocation_reason);
- scheduler_->ForceSync();
-}
-
-base::Time CryptAuthDeviceManager::GetLastSyncTime() const {
- return base::Time::FromDoubleT(
- pref_service_->GetDouble(prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds));
-}
-
-base::TimeDelta CryptAuthDeviceManager::GetTimeToNextAttempt() const {
- return scheduler_->GetTimeToNextSync();
-}
-
-bool CryptAuthDeviceManager::IsSyncInProgress() const {
- return scheduler_->GetSyncState() ==
- SyncScheduler::SyncState::SYNC_IN_PROGRESS;
-}
-
-bool CryptAuthDeviceManager::IsRecoveringFromFailure() const {
- return scheduler_->GetStrategy() ==
- SyncScheduler::Strategy::AGGRESSIVE_RECOVERY;
-}
-
-std::vector<ExternalDeviceInfo>
-CryptAuthDeviceManager::GetSyncedDevices() const {
- return synced_devices_;
-}
-
-std::vector<ExternalDeviceInfo> CryptAuthDeviceManager::GetUnlockKeys() const {
- std::vector<ExternalDeviceInfo> unlock_keys;
- for (const auto& device : synced_devices_) {
- if (device.unlock_key()) {
- unlock_keys.push_back(device);
- }
- }
- return unlock_keys;
-}
-
-std::vector<ExternalDeviceInfo> CryptAuthDeviceManager::GetPixelUnlockKeys()
- const {
- std::vector<ExternalDeviceInfo> unlock_keys;
- for (const auto& device : synced_devices_) {
- if (device.unlock_key() && device.pixel_phone()) {
- unlock_keys.push_back(device);
- }
- }
- return unlock_keys;
-}
-
-std::vector<ExternalDeviceInfo> CryptAuthDeviceManager::GetTetherHosts() const {
- std::vector<ExternalDeviceInfo> tether_hosts;
- for (const auto& device : synced_devices_) {
- if (device.mobile_hotspot_supported()) {
- tether_hosts.push_back(device);
- }
- }
- return tether_hosts;
-}
-
-std::vector<ExternalDeviceInfo> CryptAuthDeviceManager::GetPixelTetherHosts()
- const {
- std::vector<ExternalDeviceInfo> tether_hosts;
- for (const auto& device : synced_devices_) {
- if (device.mobile_hotspot_supported() && device.pixel_phone()) {
- tether_hosts.push_back(device);
- }
- }
- return tether_hosts;
-}
-
-void CryptAuthDeviceManager::OnGetMyDevicesSuccess(
- const GetMyDevicesResponse& response) {
- // Update the synced devices stored in the user's prefs.
- std::unique_ptr<base::ListValue> devices_as_list(new base::ListValue());
-
- if (!response.devices().empty())
- PA_LOG(INFO) << "Devices were successfully synced.";
-
- for (const auto& device : response.devices()) {
- std::unique_ptr<base::DictionaryValue> device_dictionary =
- UnlockKeyToDictionary(device);
-
- const std::string& device_name = device.has_friendly_device_name()
- ? device.friendly_device_name()
- : "[unknown]";
- PA_LOG(INFO) << "Synced device '" << device_name
- << "': " << *device_dictionary;
-
- devices_as_list->Append(std::move(device_dictionary));
- }
-
- bool unlock_keys_changed = !devices_as_list->Equals(
- pref_service_->GetList(prefs::kCryptAuthDeviceSyncUnlockKeys));
- {
- ListPrefUpdate update(pref_service_, prefs::kCryptAuthDeviceSyncUnlockKeys);
- update.Get()->Swap(devices_as_list.get());
- }
- UpdateUnlockKeysFromPrefs();
-
- // Reset metadata used for scheduling syncing.
- pref_service_->SetBoolean(prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure,
- false);
- pref_service_->SetDouble(prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds,
- clock_->Now().ToDoubleT());
- pref_service_->SetInteger(prefs::kCryptAuthDeviceSyncReason,
- INVOCATION_REASON_UNKNOWN);
-
- sync_request_->OnDidComplete(true);
- cryptauth_client_.reset();
- sync_request_.reset();
- NotifySyncFinished(SyncResult::SUCCESS, unlock_keys_changed
- ? DeviceChangeResult::CHANGED
- : DeviceChangeResult::UNCHANGED);
-}
-
-void CryptAuthDeviceManager::OnGetMyDevicesFailure(const std::string& error) {
- PA_LOG(ERROR) << "GetMyDevices API failed: " << error;
- pref_service_->SetBoolean(prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure,
- true);
- sync_request_->OnDidComplete(false);
- cryptauth_client_.reset();
- sync_request_.reset();
- NotifySyncFinished(SyncResult::FAILURE, DeviceChangeResult::UNCHANGED);
-}
-
-void CryptAuthDeviceManager::OnResyncMessage() {
- ForceSyncNow(INVOCATION_REASON_SERVER_INITIATED);
-}
-
-void CryptAuthDeviceManager::UpdateUnlockKeysFromPrefs() {
- const base::ListValue* unlock_key_list =
- pref_service_->GetList(prefs::kCryptAuthDeviceSyncUnlockKeys);
- synced_devices_.clear();
- for (size_t i = 0; i < unlock_key_list->GetSize(); ++i) {
- const base::DictionaryValue* unlock_key_dictionary;
- if (unlock_key_list->GetDictionary(i, &unlock_key_dictionary)) {
- ExternalDeviceInfo unlock_key;
- if (DictionaryToUnlockKey(*unlock_key_dictionary, &unlock_key)) {
- synced_devices_.push_back(unlock_key);
- } else {
- PA_LOG(ERROR) << "Unable to deserialize unlock key dictionary "
- << "(index=" << i << "):\n" << *unlock_key_dictionary;
- }
- } else {
- PA_LOG(ERROR) << "Can not get dictionary in list of unlock keys "
- << "(index=" << i << "):\n" << *unlock_key_list;
- }
- }
+void CryptAuthDeviceManager::NotifySyncStarted() {
+ for (auto& observer : observers_)
+ observer.OnSyncStarted();
}
-void CryptAuthDeviceManager::OnSyncRequested(
- std::unique_ptr<SyncScheduler::SyncRequest> sync_request) {
- NotifySyncStarted();
-
- sync_request_ = std::move(sync_request);
- cryptauth_client_ = client_factory_->CreateInstance();
-
- InvocationReason invocation_reason =
- INVOCATION_REASON_UNKNOWN;
-
- int reason_stored_in_prefs =
- pref_service_->GetInteger(prefs::kCryptAuthDeviceSyncReason);
-
- // If the sync attempt is not forced, it is acceptable for CryptAuth to return
- // a cached copy of the user's devices, rather taking a database hit for the
- // freshest data.
- bool is_sync_speculative =
- reason_stored_in_prefs != INVOCATION_REASON_UNKNOWN;
-
- if (InvocationReason_IsValid(reason_stored_in_prefs) &&
- reason_stored_in_prefs != INVOCATION_REASON_UNKNOWN) {
- invocation_reason =
- static_cast<InvocationReason>(reason_stored_in_prefs);
- } else if (GetLastSyncTime().is_null()) {
- invocation_reason = INVOCATION_REASON_INITIALIZATION;
- } else if (IsRecoveringFromFailure()) {
- invocation_reason = INVOCATION_REASON_FAILURE_RECOVERY;
- } else {
- invocation_reason = INVOCATION_REASON_PERIODIC;
- }
-
- GetMyDevicesRequest request;
- request.set_invocation_reason(invocation_reason);
- request.set_allow_stale_read(is_sync_speculative);
- net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
- net::DefinePartialNetworkTrafficAnnotation("cryptauth_get_my_devices",
- "oauth2_api_call_flow", R"(
- semantics {
- sender: "CryptAuth Device Manager"
- description:
- "Gets a list of the devices registered (for the same user) on "
- "CryptAuth."
- trigger:
- "Once every day, or by API request. Periodic calls happen because "
- "devides that do not re-enrolled for more than X days (currently 45) "
- "are automatically removed from the server."
- data: "OAuth 2.0 token."
- destination: GOOGLE_OWNED_SERVICE
- }
- policy {
- setting:
- "This feature cannot be disabled in settings. However, this request "
- "is made only for signed-in users."
- chrome_policy {
- SigninAllowed {
- SigninAllowed: false
- }
- }
- })");
- cryptauth_client_->GetMyDevices(
- request,
- base::Bind(&CryptAuthDeviceManager::OnGetMyDevicesSuccess,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&CryptAuthDeviceManager::OnGetMyDevicesFailure,
- weak_ptr_factory_.GetWeakPtr()),
- partial_traffic_annotation);
+void CryptAuthDeviceManager::NotifySyncFinished(
+ SyncResult sync_result,
+ DeviceChangeResult device_change_result) {
+ for (auto& observer : observers_)
+ observer.OnSyncFinished(sync_result, device_change_result);
}
} // namespace cryptauth
diff --git a/chromium/components/cryptauth/cryptauth_device_manager.h b/chromium/components/cryptauth/cryptauth_device_manager.h
index 77ee707215a..475c3c040d9 100644
--- a/chromium/components/cryptauth/cryptauth_device_manager.h
+++ b/chromium/components/cryptauth/cryptauth_device_manager.h
@@ -8,31 +8,24 @@
#include <memory>
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/time/clock.h"
-#include "base/time/time.h"
-#include "components/cryptauth/cryptauth_gcm_manager.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
-#include "components/cryptauth/sync_scheduler.h"
-class PrefService;
class PrefRegistrySimple;
namespace cryptauth {
-class CryptAuthClient;
-class CryptAuthClientFactory;
-
-// This class manages syncing and storing the user's phones that are registered
-// with CryptAuth and are capable of unlocking the user's other devices. These
-// phones are called "unlock keys".
-// The manager periodically syncs the user's devices from CryptAuth to keep the
-// list of unlock keys fresh. If a sync attempts fails, the manager will
-// schedule the next sync more aggressively to recover.
-class CryptAuthDeviceManager : public SyncScheduler::Delegate,
- public CryptAuthGCMManager::Observer {
+// Manages syncing and storing the user's devices that are registered with
+// CryptAuth.
+//
+// CryptAuthDeviceManager periodically syncs the user's devices from CryptAuth
+// to keep the list of unlock keys fresh. If a sync attempts fails, the manager
+// will schedule the next sync more aggressively to recover.
+class CryptAuthDeviceManager {
public:
+ // Registers the prefs used by this class to the given |registry|.
+ static void RegisterPrefs(PrefRegistrySimple* registry);
+
// Respresents the success result of a sync attempt.
enum class SyncResult { SUCCESS, FAILURE };
@@ -54,77 +47,53 @@ class CryptAuthDeviceManager : public SyncScheduler::Delegate,
virtual void OnSyncFinished(SyncResult sync_result,
DeviceChangeResult device_change_result) {}
- virtual ~Observer() {}
+ virtual ~Observer() = default;
};
- // Creates the manager:
- // |clock|: Used to determine the time between sync attempts.
- // |client_factory|: Creates CryptAuthClient instances to perform each sync.
- // |gcm_manager|: Notifies when GCM push messages trigger device syncs.
- // Not owned and must outlive this instance.
- // |pref_service|: Stores syncing metadata and unlock key information to
- // persist across browser restarts. Must already be registered
- // with RegisterPrefs().
- CryptAuthDeviceManager(base::Clock* clock,
- std::unique_ptr<CryptAuthClientFactory> client_factory,
- CryptAuthGCMManager* gcm_manager,
- PrefService* pref_service);
-
- ~CryptAuthDeviceManager() override;
-
- // Registers the prefs used by this class to the given |registry|.
- static void RegisterPrefs(PrefRegistrySimple* registry);
-
- // Starts device manager to begin syncing devices.
- void Start();
+ CryptAuthDeviceManager();
+ virtual ~CryptAuthDeviceManager();
- // Adds an observer.
void AddObserver(Observer* observer);
-
- // Removes an observer.
void RemoveObserver(Observer* observer);
+ // Starts device manager to begin syncing devices.
+ virtual void Start() = 0;
+
// Skips the waiting period and forces a sync immediately. If a
// sync attempt is already in progress, this function does nothing.
// |invocation_reason| specifies the reason that the sync was triggered,
// which is upload to the server.
- void ForceSyncNow(InvocationReason invocation_reason);
+ virtual void ForceSyncNow(InvocationReason invocation_reason) = 0;
// Returns the timestamp of the last successful sync. If no sync
// has ever been made, then returns a null base::Time object.
- base::Time GetLastSyncTime() const;
+ virtual base::Time GetLastSyncTime() const = 0;
// Returns the time to the next sync attempt.
- base::TimeDelta GetTimeToNextAttempt() const;
+ virtual base::TimeDelta GetTimeToNextAttempt() const = 0;
// Returns true if a device sync attempt is currently in progress.
- bool IsSyncInProgress() const;
+ virtual bool IsSyncInProgress() const = 0;
// Returns true if the last device sync failed and the manager is now
// scheduling sync attempts more aggressively to recover. If no enrollment
// has ever been recorded, then this function will also return true.
- bool IsRecoveringFromFailure() const;
+ virtual bool IsRecoveringFromFailure() const = 0;
// Returns a list of all remote devices that have been synced.
- virtual std::vector<ExternalDeviceInfo> GetSyncedDevices() const;
+ virtual std::vector<ExternalDeviceInfo> GetSyncedDevices() const = 0;
// Returns a list of remote devices that can unlock the user's other devices.
- virtual std::vector<ExternalDeviceInfo> GetUnlockKeys() const;
+ virtual std::vector<ExternalDeviceInfo> GetUnlockKeys() const = 0;
// Like GetUnlockKeys(), but only returns Pixel devices.
- virtual std::vector<ExternalDeviceInfo> GetPixelUnlockKeys() const;
+ virtual std::vector<ExternalDeviceInfo> GetPixelUnlockKeys() const = 0;
// Returns a list of remote devices that can host tether hotspots.
- virtual std::vector<ExternalDeviceInfo> GetTetherHosts() const;
+ virtual std::vector<ExternalDeviceInfo> GetTetherHosts() const = 0;
// Like GetTetherHosts(), but only returns Pixel devices.
- virtual std::vector<ExternalDeviceInfo> GetPixelTetherHosts() const;
+ virtual std::vector<ExternalDeviceInfo> GetPixelTetherHosts() const = 0;
protected:
- // Empty constructor, to be used by tests to mock the device manager. Do not
- // use this constructor outside of tests.
- CryptAuthDeviceManager();
-
- void SetSyncSchedulerForTest(std::unique_ptr<SyncScheduler> sync_scheduler);
-
// Invokes OnSyncStarted() on all observers.
void NotifySyncStarted();
@@ -134,54 +103,8 @@ class CryptAuthDeviceManager : public SyncScheduler::Delegate,
DeviceChangeResult device_change_result);
private:
- // CryptAuthGCMManager::Observer:
- void OnResyncMessage() override;
-
- // Updates |unlock_keys_| by fetching the list stored in |pref_service_|.
- void UpdateUnlockKeysFromPrefs();
-
- // SyncScheduler::Delegate:
- void OnSyncRequested(
- std::unique_ptr<SyncScheduler::SyncRequest> sync_request) override;
-
- // Callback when |cryptauth_client_| completes with the response.
- void OnGetMyDevicesSuccess(const GetMyDevicesResponse& response);
- void OnGetMyDevicesFailure(const std::string& error);
-
- // Used to determine the time.
- base::Clock* clock_;
-
- // Creates CryptAuthClient instances for each sync attempt.
- std::unique_ptr<CryptAuthClientFactory> client_factory_;
-
- // Notifies when GCM push messages trigger device sync. Not owned and must
- // outlive this instance.
- CryptAuthGCMManager* gcm_manager_;
-
- // Contains preferences that outlive the lifetime of this object and across
- // process restarts. |pref_service_| must outlive the lifetime of this
- // instance.
- PrefService* const pref_service_;
-
- // All devices currently synced from CryptAuth.
- std::vector<ExternalDeviceInfo> synced_devices_;
-
- // Schedules the time between device sync attempts.
- std::unique_ptr<SyncScheduler> scheduler_;
-
- // Contains the SyncRequest that |scheduler_| requests when a device sync
- // attempt is made.
- std::unique_ptr<SyncScheduler::SyncRequest> sync_request_;
-
- // The CryptAuthEnroller instance for the current sync attempt. A new
- // instance will be created for each individual attempt.
- std::unique_ptr<CryptAuthClient> cryptauth_client_;
-
- // List of observers.
base::ObserverList<Observer> observers_;
- base::WeakPtrFactory<CryptAuthDeviceManager> weak_ptr_factory_;
-
DISALLOW_COPY_AND_ASSIGN(CryptAuthDeviceManager);
};
diff --git a/chromium/components/cryptauth/cryptauth_device_manager_impl.cc b/chromium/components/cryptauth/cryptauth_device_manager_impl.cc
new file mode 100644
index 00000000000..b03f075ec04
--- /dev/null
+++ b/chromium/components/cryptauth/cryptauth_device_manager_impl.cc
@@ -0,0 +1,581 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cryptauth/cryptauth_device_manager_impl.h"
+
+#include <stddef.h>
+#include <stdexcept>
+#include <utility>
+
+#include <memory>
+
+#include "base/base64url.h"
+#include "base/strings/string_number_conversions.h"
+#include "components/cryptauth/cryptauth_client.h"
+#include "components/cryptauth/pref_names.h"
+#include "components/cryptauth/sync_scheduler_impl.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/proximity_auth/logging/logging.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+
+namespace cryptauth {
+
+namespace {
+
+// The normal period between successful syncs, in hours.
+const int kRefreshPeriodHours = 24;
+
+// A more aggressive period between sync attempts to recover when the last
+// sync attempt fails, in minutes. This is a base time that increases for each
+// subsequent failure.
+const int kDeviceSyncBaseRecoveryPeriodMinutes = 10;
+
+// The bound on the amount to jitter the period between syncs.
+const double kDeviceSyncMaxJitterRatio = 0.2;
+
+// Keys for ExternalDeviceInfo dictionaries that are stored in the user's prefs.
+const char kExternalDeviceKeyPublicKey[] = "public_key";
+const char kExternalDeviceKeyDeviceName[] = "device_name";
+const char kExternalDeviceKeyBluetoothAddress[] = "bluetooth_address";
+const char kExternalDeviceKeyUnlockKey[] = "unlock_key";
+const char kExternalDeviceKeyUnlockable[] = "unlockable";
+const char kExternalDeviceKeyLastUpdateTimeMillis[] = "last_update_time_millis";
+const char kExternalDeviceKeyMobileHotspotSupported[] =
+ "mobile_hotspot_supported";
+const char kExternalDeviceKeyDeviceType[] = "device_type";
+const char kExternalDeviceKeyBeaconSeeds[] = "beacon_seeds";
+const char kExternalDeviceKeyArcPlusPlus[] = "arc_plus_plus";
+const char kExternalDeviceKeyPixelPhone[] = "pixel_phone";
+const char kExternalDeviceKeyBeaconSeedData[] = "beacon_seed_data";
+const char kExternalDeviceKeyBeaconSeedStartMs[] = "beacon_seed_start_ms";
+const char kExternalDeviceKeyBeaconSeedEndMs[] = "beacon_seed_end_ms";
+
+// Converts BeaconSeed protos to a list value that can be stored in user prefs.
+std::unique_ptr<base::ListValue> BeaconSeedsToListValue(
+ const google::protobuf::RepeatedPtrField<BeaconSeed>& seeds) {
+ std::unique_ptr<base::ListValue> list(new base::ListValue());
+
+ for (int i = 0; i < seeds.size(); i++) {
+ BeaconSeed seed = seeds.Get(i);
+
+ if (!seed.has_data() || !seed.has_start_time_millis() ||
+ !seed.has_end_time_millis()) {
+ PA_LOG(WARNING) << "Unable to serialize BeaconSeed due to missing data; "
+ << "skipping.";
+ continue;
+ }
+
+ std::unique_ptr<base::DictionaryValue> beacon_seed_value(
+ new base::DictionaryValue());
+
+ // Note that the |BeaconSeed|s' data is stored in Base64Url encoding because
+ // dictionary values must be valid UTF8 strings.
+ std::string seed_data_b64;
+ base::Base64UrlEncode(seed.data(),
+ base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ &seed_data_b64);
+ beacon_seed_value->SetString(kExternalDeviceKeyBeaconSeedData,
+ seed_data_b64);
+
+ // Set the timestamps as string representations of their numeric value
+ // since there is no notion of a base::LongValue.
+ beacon_seed_value->SetString(kExternalDeviceKeyBeaconSeedStartMs,
+ std::to_string(seed.start_time_millis()));
+ beacon_seed_value->SetString(kExternalDeviceKeyBeaconSeedEndMs,
+ std::to_string(seed.end_time_millis()));
+
+ list->Append(std::move(beacon_seed_value));
+ }
+
+ return list;
+}
+
+// Converts an unlock key proto to a dictionary that can be stored in user
+// prefs.
+std::unique_ptr<base::DictionaryValue> UnlockKeyToDictionary(
+ const ExternalDeviceInfo& device) {
+ // The device public key is a required value.
+ if (!device.has_public_key())
+ return nullptr;
+
+ std::unique_ptr<base::DictionaryValue> dictionary(
+ new base::DictionaryValue());
+
+ // Note that the device public key, name, and Bluetooth addresses are stored
+ // in Base64Url form because dictionary values must be valid UTF8 strings.
+
+ std::string public_key_b64;
+ base::Base64UrlEncode(device.public_key(),
+ base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ &public_key_b64);
+ dictionary->SetString(kExternalDeviceKeyPublicKey, public_key_b64);
+
+ if (device.has_friendly_device_name()) {
+ std::string device_name_b64;
+ base::Base64UrlEncode(device.friendly_device_name(),
+ base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ &device_name_b64);
+ dictionary->SetString(kExternalDeviceKeyDeviceName, device_name_b64);
+ }
+
+ if (device.has_bluetooth_address()) {
+ std::string bluetooth_address_b64;
+ base::Base64UrlEncode(device.bluetooth_address(),
+ base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ &bluetooth_address_b64);
+ dictionary->SetString(kExternalDeviceKeyBluetoothAddress,
+ bluetooth_address_b64);
+ }
+
+ if (device.has_unlock_key()) {
+ dictionary->SetBoolean(kExternalDeviceKeyUnlockKey, device.unlock_key());
+ }
+
+ if (device.has_unlockable()) {
+ dictionary->SetBoolean(kExternalDeviceKeyUnlockable, device.unlockable());
+ }
+
+ if (device.has_last_update_time_millis()) {
+ dictionary->SetString(kExternalDeviceKeyLastUpdateTimeMillis,
+ std::to_string(device.last_update_time_millis()));
+ }
+
+ if (device.has_mobile_hotspot_supported()) {
+ dictionary->SetBoolean(kExternalDeviceKeyMobileHotspotSupported,
+ device.mobile_hotspot_supported());
+ }
+
+ if (device.has_device_type() && DeviceType_IsValid(device.device_type())) {
+ dictionary->SetInteger(kExternalDeviceKeyDeviceType, device.device_type());
+ }
+
+ if (device.has_arc_plus_plus()) {
+ dictionary->SetBoolean(kExternalDeviceKeyArcPlusPlus,
+ device.arc_plus_plus());
+ }
+
+ if (device.has_pixel_phone()) {
+ dictionary->SetBoolean(kExternalDeviceKeyPixelPhone, device.pixel_phone());
+ }
+
+ std::unique_ptr<base::ListValue> beacon_seed_list =
+ BeaconSeedsToListValue(device.beacon_seeds());
+ dictionary->Set(kExternalDeviceKeyBeaconSeeds, std::move(beacon_seed_list));
+
+ return dictionary;
+}
+
+void AddBeaconSeedsToExternalDevice(const base::ListValue& beacon_seeds,
+ ExternalDeviceInfo& external_device) {
+ for (size_t i = 0; i < beacon_seeds.GetSize(); i++) {
+ const base::DictionaryValue* seed_dictionary = nullptr;
+ if (!beacon_seeds.GetDictionary(i, &seed_dictionary)) {
+ PA_LOG(WARNING) << "Unable to retrieve BeaconSeed dictionary; "
+ << "skipping.";
+ continue;
+ }
+
+ std::string seed_data_b64, start_time_millis_str, end_time_millis_str;
+ if (!seed_dictionary->GetString(kExternalDeviceKeyBeaconSeedData,
+ &seed_data_b64) ||
+ !seed_dictionary->GetString(kExternalDeviceKeyBeaconSeedStartMs,
+ &start_time_millis_str) ||
+ !seed_dictionary->GetString(kExternalDeviceKeyBeaconSeedEndMs,
+ &end_time_millis_str)) {
+ PA_LOG(WARNING) << "Unable to deserialize BeaconSeed due to missing "
+ << "data; skipping.";
+ continue;
+ }
+
+ // Seed data is returned as raw data, not in Base64 encoding.
+ std::string seed_data;
+ if (!base::Base64UrlDecode(seed_data_b64,
+ base::Base64UrlDecodePolicy::REQUIRE_PADDING,
+ &seed_data)) {
+ PA_LOG(WARNING) << "Decoding seed data failed.";
+ continue;
+ }
+
+ int64_t start_time_millis, end_time_millis;
+ if (!base::StringToInt64(start_time_millis_str, &start_time_millis) ||
+ !base::StringToInt64(end_time_millis_str, &end_time_millis)) {
+ PA_LOG(WARNING) << "Unable to convert stored timestamp to int64_t: "
+ << start_time_millis_str << " or " << end_time_millis_str;
+ continue;
+ }
+
+ BeaconSeed* seed = external_device.add_beacon_seeds();
+ seed->set_data(seed_data);
+ seed->set_start_time_millis(start_time_millis);
+ seed->set_end_time_millis(end_time_millis);
+ }
+}
+
+// Converts an unlock key dictionary stored in user prefs to an
+// ExternalDeviceInfo proto. Returns true if the dictionary is valid, and the
+// parsed proto is written to |external_device|.
+bool DictionaryToUnlockKey(const base::DictionaryValue& dictionary,
+ ExternalDeviceInfo* external_device) {
+ std::string public_key_b64;
+ if (!dictionary.GetString(kExternalDeviceKeyPublicKey, &public_key_b64)) {
+ // The public key is a required field, so if it is absent, there is no
+ // valid data to return.
+ return false;
+ }
+
+ std::string public_key;
+ if (!base::Base64UrlDecode(public_key_b64,
+ base::Base64UrlDecodePolicy::REQUIRE_PADDING,
+ &public_key)) {
+ // The public key is stored as a Base64Url, so if it cannot be decoded,
+ // there is no valid data to return.
+ return false;
+ }
+ external_device->set_public_key(public_key);
+
+ std::string device_name_b64;
+ if (dictionary.GetString(kExternalDeviceKeyDeviceName, &device_name_b64)) {
+ std::string device_name;
+ if (base::Base64UrlDecode(device_name_b64,
+ base::Base64UrlDecodePolicy::REQUIRE_PADDING,
+ &device_name)) {
+ external_device->set_friendly_device_name(device_name);
+ }
+ }
+
+ std::string bluetooth_address_b64;
+ if (dictionary.GetString(kExternalDeviceKeyBluetoothAddress,
+ &bluetooth_address_b64)) {
+ std::string bluetooth_address;
+ if (base::Base64UrlDecode(bluetooth_address_b64,
+ base::Base64UrlDecodePolicy::REQUIRE_PADDING,
+ &bluetooth_address)) {
+ external_device->set_bluetooth_address(bluetooth_address);
+ }
+ }
+
+ bool unlock_key;
+ if (dictionary.GetBoolean(kExternalDeviceKeyUnlockKey, &unlock_key))
+ external_device->set_unlock_key(unlock_key);
+
+ bool unlockable;
+ if (dictionary.GetBoolean(kExternalDeviceKeyUnlockable, &unlockable))
+ external_device->set_unlockable(unlockable);
+
+ std::string last_update_time_millis_str;
+ if (dictionary.GetString(kExternalDeviceKeyLastUpdateTimeMillis,
+ &last_update_time_millis_str)) {
+ int64_t last_update_time_millis;
+ if (base::StringToInt64(last_update_time_millis_str,
+ &last_update_time_millis)) {
+ external_device->set_last_update_time_millis(last_update_time_millis);
+ } else {
+ PA_LOG(WARNING) << "Unable to convert stored update time to int64_t: "
+ << last_update_time_millis_str;
+ }
+ }
+
+ bool mobile_hotspot_supported;
+ if (dictionary.GetBoolean(kExternalDeviceKeyMobileHotspotSupported,
+ &mobile_hotspot_supported)) {
+ external_device->set_mobile_hotspot_supported(mobile_hotspot_supported);
+ }
+
+ int device_type;
+ if (dictionary.GetInteger(kExternalDeviceKeyDeviceType, &device_type) &&
+ DeviceType_IsValid(device_type)) {
+ external_device->set_device_type(static_cast<DeviceType>(device_type));
+ }
+
+ const base::ListValue* beacon_seeds = nullptr;
+ dictionary.GetList(kExternalDeviceKeyBeaconSeeds, &beacon_seeds);
+ if (beacon_seeds)
+ AddBeaconSeedsToExternalDevice(*beacon_seeds, *external_device);
+
+ bool arc_plus_plus;
+ if (dictionary.GetBoolean(kExternalDeviceKeyArcPlusPlus, &arc_plus_plus))
+ external_device->set_arc_plus_plus(arc_plus_plus);
+
+ bool pixel_phone;
+ if (dictionary.GetBoolean(kExternalDeviceKeyPixelPhone, &pixel_phone))
+ external_device->set_pixel_phone(pixel_phone);
+
+ return true;
+}
+
+std::unique_ptr<SyncSchedulerImpl> CreateSyncScheduler(
+ SyncScheduler::Delegate* delegate) {
+ return std::make_unique<SyncSchedulerImpl>(
+ delegate, base::TimeDelta::FromHours(kRefreshPeriodHours),
+ base::TimeDelta::FromMinutes(kDeviceSyncBaseRecoveryPeriodMinutes),
+ kDeviceSyncMaxJitterRatio, "CryptAuth DeviceSync");
+}
+
+} // namespace
+
+CryptAuthDeviceManagerImpl::CryptAuthDeviceManagerImpl(
+ base::Clock* clock,
+ std::unique_ptr<CryptAuthClientFactory> client_factory,
+ CryptAuthGCMManager* gcm_manager,
+ PrefService* pref_service)
+ : clock_(clock),
+ client_factory_(std::move(client_factory)),
+ gcm_manager_(gcm_manager),
+ pref_service_(pref_service),
+ scheduler_(CreateSyncScheduler(this)),
+ weak_ptr_factory_(this) {
+ UpdateUnlockKeysFromPrefs();
+}
+
+CryptAuthDeviceManagerImpl::~CryptAuthDeviceManagerImpl() {
+ if (gcm_manager_)
+ gcm_manager_->RemoveObserver(this);
+}
+
+void CryptAuthDeviceManagerImpl::SetSyncSchedulerForTest(
+ std::unique_ptr<SyncScheduler> sync_scheduler) {
+ scheduler_ = std::move(sync_scheduler);
+}
+
+void CryptAuthDeviceManagerImpl::Start() {
+ gcm_manager_->AddObserver(this);
+
+ base::Time last_successful_sync = GetLastSyncTime();
+ base::TimeDelta elapsed_time_since_last_sync =
+ clock_->Now() - last_successful_sync;
+
+ bool is_recovering_from_failure =
+ pref_service_->GetBoolean(
+ prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure) ||
+ last_successful_sync.is_null();
+
+ scheduler_->Start(elapsed_time_since_last_sync,
+ is_recovering_from_failure
+ ? SyncScheduler::Strategy::AGGRESSIVE_RECOVERY
+ : SyncScheduler::Strategy::PERIODIC_REFRESH);
+}
+
+void CryptAuthDeviceManagerImpl::ForceSyncNow(
+ InvocationReason invocation_reason) {
+ pref_service_->SetInteger(prefs::kCryptAuthDeviceSyncReason,
+ invocation_reason);
+ scheduler_->ForceSync();
+}
+
+base::Time CryptAuthDeviceManagerImpl::GetLastSyncTime() const {
+ return base::Time::FromDoubleT(
+ pref_service_->GetDouble(prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds));
+}
+
+base::TimeDelta CryptAuthDeviceManagerImpl::GetTimeToNextAttempt() const {
+ return scheduler_->GetTimeToNextSync();
+}
+
+bool CryptAuthDeviceManagerImpl::IsSyncInProgress() const {
+ return scheduler_->GetSyncState() ==
+ SyncScheduler::SyncState::SYNC_IN_PROGRESS;
+}
+
+bool CryptAuthDeviceManagerImpl::IsRecoveringFromFailure() const {
+ return scheduler_->GetStrategy() ==
+ SyncScheduler::Strategy::AGGRESSIVE_RECOVERY;
+}
+
+std::vector<ExternalDeviceInfo> CryptAuthDeviceManagerImpl::GetSyncedDevices()
+ const {
+ return synced_devices_;
+}
+
+std::vector<ExternalDeviceInfo> CryptAuthDeviceManagerImpl::GetUnlockKeys()
+ const {
+ std::vector<ExternalDeviceInfo> unlock_keys;
+ for (const auto& device : synced_devices_) {
+ if (device.unlock_key())
+ unlock_keys.push_back(device);
+ }
+ return unlock_keys;
+}
+
+std::vector<ExternalDeviceInfo> CryptAuthDeviceManagerImpl::GetPixelUnlockKeys()
+ const {
+ std::vector<ExternalDeviceInfo> unlock_keys;
+ for (const auto& device : synced_devices_) {
+ if (device.unlock_key() && device.pixel_phone())
+ unlock_keys.push_back(device);
+ }
+ return unlock_keys;
+}
+
+std::vector<ExternalDeviceInfo> CryptAuthDeviceManagerImpl::GetTetherHosts()
+ const {
+ std::vector<ExternalDeviceInfo> tether_hosts;
+ for (const auto& device : synced_devices_) {
+ if (device.mobile_hotspot_supported())
+ tether_hosts.push_back(device);
+ }
+ return tether_hosts;
+}
+
+std::vector<ExternalDeviceInfo>
+CryptAuthDeviceManagerImpl::GetPixelTetherHosts() const {
+ std::vector<ExternalDeviceInfo> tether_hosts;
+ for (const auto& device : synced_devices_) {
+ if (device.mobile_hotspot_supported() && device.pixel_phone())
+ tether_hosts.push_back(device);
+ }
+ return tether_hosts;
+}
+
+void CryptAuthDeviceManagerImpl::OnGetMyDevicesSuccess(
+ const GetMyDevicesResponse& response) {
+ // Update the synced devices stored in the user's prefs.
+ std::unique_ptr<base::ListValue> devices_as_list(new base::ListValue());
+
+ if (!response.devices().empty())
+ PA_LOG(INFO) << "Devices were successfully synced.";
+
+ for (const auto& device : response.devices()) {
+ std::unique_ptr<base::DictionaryValue> device_dictionary =
+ UnlockKeyToDictionary(device);
+
+ const std::string& device_name = device.has_friendly_device_name()
+ ? device.friendly_device_name()
+ : "[unknown]";
+ PA_LOG(INFO) << "Synced device '" << device_name
+ << "': " << *device_dictionary;
+
+ devices_as_list->Append(std::move(device_dictionary));
+ }
+
+ bool unlock_keys_changed = !devices_as_list->Equals(
+ pref_service_->GetList(prefs::kCryptAuthDeviceSyncUnlockKeys));
+ {
+ ListPrefUpdate update(pref_service_, prefs::kCryptAuthDeviceSyncUnlockKeys);
+ update.Get()->Swap(devices_as_list.get());
+ }
+ UpdateUnlockKeysFromPrefs();
+
+ // Reset metadata used for scheduling syncing.
+ pref_service_->SetBoolean(prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure,
+ false);
+ pref_service_->SetDouble(prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds,
+ clock_->Now().ToDoubleT());
+ pref_service_->SetInteger(prefs::kCryptAuthDeviceSyncReason,
+ INVOCATION_REASON_UNKNOWN);
+
+ sync_request_->OnDidComplete(true);
+ cryptauth_client_.reset();
+ sync_request_.reset();
+ NotifySyncFinished(SyncResult::SUCCESS, unlock_keys_changed
+ ? DeviceChangeResult::CHANGED
+ : DeviceChangeResult::UNCHANGED);
+}
+
+void CryptAuthDeviceManagerImpl::OnGetMyDevicesFailure(
+ const std::string& error) {
+ PA_LOG(ERROR) << "GetMyDevices API failed: " << error;
+ pref_service_->SetBoolean(prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure,
+ true);
+ sync_request_->OnDidComplete(false);
+ cryptauth_client_.reset();
+ sync_request_.reset();
+ NotifySyncFinished(SyncResult::FAILURE, DeviceChangeResult::UNCHANGED);
+}
+
+void CryptAuthDeviceManagerImpl::OnResyncMessage() {
+ ForceSyncNow(INVOCATION_REASON_SERVER_INITIATED);
+}
+
+void CryptAuthDeviceManagerImpl::UpdateUnlockKeysFromPrefs() {
+ const base::ListValue* unlock_key_list =
+ pref_service_->GetList(prefs::kCryptAuthDeviceSyncUnlockKeys);
+ synced_devices_.clear();
+ for (size_t i = 0; i < unlock_key_list->GetSize(); ++i) {
+ const base::DictionaryValue* unlock_key_dictionary;
+ if (unlock_key_list->GetDictionary(i, &unlock_key_dictionary)) {
+ ExternalDeviceInfo unlock_key;
+ if (DictionaryToUnlockKey(*unlock_key_dictionary, &unlock_key)) {
+ synced_devices_.push_back(unlock_key);
+ } else {
+ PA_LOG(ERROR) << "Unable to deserialize unlock key dictionary "
+ << "(index=" << i << "):\n"
+ << *unlock_key_dictionary;
+ }
+ } else {
+ PA_LOG(ERROR) << "Can not get dictionary in list of unlock keys "
+ << "(index=" << i << "):\n"
+ << *unlock_key_list;
+ }
+ }
+}
+
+void CryptAuthDeviceManagerImpl::OnSyncRequested(
+ std::unique_ptr<SyncScheduler::SyncRequest> sync_request) {
+ NotifySyncStarted();
+
+ sync_request_ = std::move(sync_request);
+ cryptauth_client_ = client_factory_->CreateInstance();
+
+ InvocationReason invocation_reason = INVOCATION_REASON_UNKNOWN;
+
+ int reason_stored_in_prefs =
+ pref_service_->GetInteger(prefs::kCryptAuthDeviceSyncReason);
+
+ // If the sync attempt is not forced, it is acceptable for CryptAuth to return
+ // a cached copy of the user's devices, rather taking a database hit for the
+ // freshest data.
+ bool is_sync_speculative =
+ reason_stored_in_prefs != INVOCATION_REASON_UNKNOWN;
+
+ if (InvocationReason_IsValid(reason_stored_in_prefs) &&
+ reason_stored_in_prefs != INVOCATION_REASON_UNKNOWN) {
+ invocation_reason = static_cast<InvocationReason>(reason_stored_in_prefs);
+ } else if (GetLastSyncTime().is_null()) {
+ invocation_reason = INVOCATION_REASON_INITIALIZATION;
+ } else if (IsRecoveringFromFailure()) {
+ invocation_reason = INVOCATION_REASON_FAILURE_RECOVERY;
+ } else {
+ invocation_reason = INVOCATION_REASON_PERIODIC;
+ }
+
+ GetMyDevicesRequest request;
+ request.set_invocation_reason(invocation_reason);
+ request.set_allow_stale_read(is_sync_speculative);
+ net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
+ net::DefinePartialNetworkTrafficAnnotation("cryptauth_get_my_devices",
+ "oauth2_api_call_flow", R"(
+ semantics {
+ sender: "CryptAuth Device Manager"
+ description:
+ "Gets a list of the devices registered (for the same user) on "
+ "CryptAuth."
+ trigger:
+ "Once every day, or by API request. Periodic calls happen because "
+ "devides that do not re-enrolled for more than X days (currently 45) "
+ "are automatically removed from the server."
+ data: "OAuth 2.0 token."
+ destination: GOOGLE_OWNED_SERVICE
+ }
+ policy {
+ setting:
+ "This feature cannot be disabled in settings. However, this request "
+ "is made only for signed-in users."
+ chrome_policy {
+ SigninAllowed {
+ SigninAllowed: false
+ }
+ }
+ })");
+ cryptauth_client_->GetMyDevices(
+ request,
+ base::Bind(&CryptAuthDeviceManagerImpl::OnGetMyDevicesSuccess,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&CryptAuthDeviceManagerImpl::OnGetMyDevicesFailure,
+ weak_ptr_factory_.GetWeakPtr()),
+ partial_traffic_annotation);
+}
+
+} // namespace cryptauth
diff --git a/chromium/components/cryptauth/cryptauth_device_manager_impl.h b/chromium/components/cryptauth/cryptauth_device_manager_impl.h
new file mode 100644
index 00000000000..41b3ff19f97
--- /dev/null
+++ b/chromium/components/cryptauth/cryptauth_device_manager_impl.h
@@ -0,0 +1,112 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CRYPTAUTH_CRYPTAUTH_DEVICE_MANAGER_IMPL_H_
+#define COMPONENTS_CRYPTAUTH_CRYPTAUTH_DEVICE_MANAGER_IMPL_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/clock.h"
+#include "base/time/time.h"
+#include "components/cryptauth/cryptauth_device_manager.h"
+#include "components/cryptauth/cryptauth_gcm_manager.h"
+#include "components/cryptauth/proto/cryptauth_api.pb.h"
+#include "components/cryptauth/sync_scheduler.h"
+
+class PrefService;
+
+namespace cryptauth {
+
+class CryptAuthClient;
+class CryptAuthClientFactory;
+
+class CryptAuthDeviceManagerImpl : public CryptAuthDeviceManager,
+ public SyncScheduler::Delegate,
+ public CryptAuthGCMManager::Observer {
+ public:
+ // Creates the manager:
+ // |clock|: Used to determine the time between sync attempts.
+ // |client_factory|: Creates CryptAuthClient instances to perform each sync.
+ // |gcm_manager|: Notifies when GCM push messages trigger device syncs.
+ // Not owned and must outlive this instance.
+ // |pref_service|: Stores syncing metadata and unlock key information to
+ // persist across browser restarts. Must already be registered
+ // with RegisterPrefs().
+ CryptAuthDeviceManagerImpl(
+ base::Clock* clock,
+ std::unique_ptr<CryptAuthClientFactory> client_factory,
+ CryptAuthGCMManager* gcm_manager,
+ PrefService* pref_service);
+ ~CryptAuthDeviceManagerImpl() override;
+
+ // CryptAuthDeviceManager:
+ void Start() override;
+ void ForceSyncNow(InvocationReason invocation_reason) override;
+ base::Time GetLastSyncTime() const override;
+ base::TimeDelta GetTimeToNextAttempt() const override;
+ bool IsSyncInProgress() const override;
+ bool IsRecoveringFromFailure() const override;
+ std::vector<ExternalDeviceInfo> GetSyncedDevices() const override;
+ std::vector<ExternalDeviceInfo> GetUnlockKeys() const override;
+ std::vector<ExternalDeviceInfo> GetPixelUnlockKeys() const override;
+ std::vector<ExternalDeviceInfo> GetTetherHosts() const override;
+ std::vector<ExternalDeviceInfo> GetPixelTetherHosts() const override;
+
+ protected:
+ void SetSyncSchedulerForTest(std::unique_ptr<SyncScheduler> sync_scheduler);
+
+ private:
+ // CryptAuthGCMManager::Observer:
+ void OnResyncMessage() override;
+
+ // Updates |unlock_keys_| by fetching the list stored in |pref_service_|.
+ void UpdateUnlockKeysFromPrefs();
+
+ // SyncScheduler::Delegate:
+ void OnSyncRequested(
+ std::unique_ptr<SyncScheduler::SyncRequest> sync_request) override;
+
+ // Callback when |cryptauth_client_| completes with the response.
+ void OnGetMyDevicesSuccess(const GetMyDevicesResponse& response);
+ void OnGetMyDevicesFailure(const std::string& error);
+
+ // Used to determine the time.
+ base::Clock* clock_;
+
+ // Creates CryptAuthClient instances for each sync attempt.
+ std::unique_ptr<CryptAuthClientFactory> client_factory_;
+
+ // Notifies when GCM push messages trigger device sync. Not owned and must
+ // outlive this instance.
+ CryptAuthGCMManager* gcm_manager_;
+
+ // Contains preferences that outlive the lifetime of this object and across
+ // process restarts. |pref_service_| must outlive the lifetime of this
+ // instance.
+ PrefService* const pref_service_;
+
+ // All devices currently synced from CryptAuth.
+ std::vector<ExternalDeviceInfo> synced_devices_;
+
+ // Schedules the time between device sync attempts.
+ std::unique_ptr<SyncScheduler> scheduler_;
+
+ // Contains the SyncRequest that |scheduler_| requests when a device sync
+ // attempt is made.
+ std::unique_ptr<SyncScheduler::SyncRequest> sync_request_;
+
+ // The CryptAuthEnroller instance for the current sync attempt. A new
+ // instance will be created for each individual attempt.
+ std::unique_ptr<CryptAuthClient> cryptauth_client_;
+
+ base::WeakPtrFactory<CryptAuthDeviceManagerImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CryptAuthDeviceManagerImpl);
+};
+
+} // namespace cryptauth
+
+#endif // COMPONENTS_CRYPTAUTH_CRYPTAUTH_DEVICE_MANAGER_IMPL_H_
diff --git a/chromium/components/cryptauth/cryptauth_device_manager_unittest.cc b/chromium/components/cryptauth/cryptauth_device_manager_impl_unittest.cc
index 44227998478..7ee6c377bb9 100644
--- a/chromium/components/cryptauth/cryptauth_device_manager_unittest.cc
+++ b/chromium/components/cryptauth/cryptauth_device_manager_impl_unittest.cc
@@ -1,16 +1,16 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/cryptauth/cryptauth_device_manager.h"
+#include "components/cryptauth/cryptauth_device_manager_impl.h"
#include <stddef.h>
+#include <memory>
#include <utility>
#include "base/base64url.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
@@ -94,8 +94,7 @@ void ExpectSyncedDevicesAreEqual(
const auto& device = devices.at(i);
EXPECT_TRUE(expected_device.has_public_key());
EXPECT_TRUE(device.has_public_key());
- EXPECT_EQ(expected_device.public_key(),
- device.public_key());
+ EXPECT_EQ(expected_device.public_key(), device.public_key());
EXPECT_EQ(expected_device.has_friendly_device_name(),
device.has_friendly_device_name());
@@ -104,18 +103,13 @@ void ExpectSyncedDevicesAreEqual(
EXPECT_EQ(expected_device.has_bluetooth_address(),
device.has_bluetooth_address());
- EXPECT_EQ(expected_device.bluetooth_address(),
- device.bluetooth_address());
+ EXPECT_EQ(expected_device.bluetooth_address(), device.bluetooth_address());
- EXPECT_EQ(expected_device.has_unlock_key(),
- device.has_unlock_key());
- EXPECT_EQ(expected_device.unlock_key(),
- device.unlock_key());
+ EXPECT_EQ(expected_device.has_unlock_key(), device.has_unlock_key());
+ EXPECT_EQ(expected_device.unlock_key(), device.unlock_key());
- EXPECT_EQ(expected_device.has_unlockable(),
- device.has_unlockable());
- EXPECT_EQ(expected_device.unlockable(),
- device.unlockable());
+ EXPECT_EQ(expected_device.has_unlockable(), device.has_unlockable());
+ EXPECT_EQ(expected_device.unlockable(), device.unlockable());
EXPECT_EQ(expected_device.has_last_update_time_millis(),
device.has_last_update_time_millis());
@@ -127,16 +121,12 @@ void ExpectSyncedDevicesAreEqual(
EXPECT_EQ(expected_device.mobile_hotspot_supported(),
device.mobile_hotspot_supported());
- EXPECT_EQ(expected_device.has_device_type(),
- device.has_device_type());
- EXPECT_EQ(expected_device.device_type(),
- device.device_type());
+ EXPECT_EQ(expected_device.has_device_type(), device.has_device_type());
+ EXPECT_EQ(expected_device.device_type(), device.device_type());
- ASSERT_EQ(expected_device.beacon_seeds_size(),
- device.beacon_seeds_size());
+ ASSERT_EQ(expected_device.beacon_seeds_size(), device.beacon_seeds_size());
for (int i = 0; i < expected_device.beacon_seeds_size(); i++) {
- const BeaconSeed expected_seed =
- expected_device.beacon_seeds(i);
+ const BeaconSeed expected_seed = expected_device.beacon_seeds(i);
const BeaconSeed seed = device.beacon_seeds(i);
EXPECT_TRUE(expected_seed.has_data());
EXPECT_TRUE(seed.has_data());
@@ -173,8 +163,7 @@ void ExpectSyncedDevicesAndPrefAreEqual(
const auto& expected_device = expected_devices[i];
std::string public_key_b64, public_key;
- EXPECT_TRUE(
- device_dictionary->GetString("public_key", &public_key_b64));
+ EXPECT_TRUE(device_dictionary->GetString("public_key", &public_key_b64));
EXPECT_TRUE(base::Base64UrlDecode(
public_key_b64, base::Base64UrlDecodePolicy::REQUIRE_PADDING,
&public_key));
@@ -194,7 +183,7 @@ void ExpectSyncedDevicesAndPrefAreEqual(
std::string bluetooth_address_b64, bluetooth_address;
if (device_dictionary->GetString("bluetooth_address",
- &bluetooth_address_b64)) {
+ &bluetooth_address_b64)) {
EXPECT_TRUE(base::Base64UrlDecode(
bluetooth_address_b64, base::Base64UrlDecodePolicy::REQUIRE_PADDING,
&bluetooth_address));
@@ -222,7 +211,7 @@ void ExpectSyncedDevicesAndPrefAreEqual(
std::string last_update_time_millis_str;
if (device_dictionary->GetString("last_update_time_millis",
- &last_update_time_millis_str)) {
+ &last_update_time_millis_str)) {
int64_t last_update_time_millis;
EXPECT_TRUE(base::StringToInt64(last_update_time_millis_str,
&last_update_time_millis));
@@ -235,7 +224,7 @@ void ExpectSyncedDevicesAndPrefAreEqual(
bool mobile_hotspot_supported;
if (device_dictionary->GetBoolean("mobile_hotspot_supported",
- &mobile_hotspot_supported)) {
+ &mobile_hotspot_supported)) {
EXPECT_TRUE(expected_device.has_mobile_hotspot_supported());
EXPECT_EQ(expected_device.mobile_hotspot_supported(),
mobile_hotspot_supported);
@@ -244,21 +233,17 @@ void ExpectSyncedDevicesAndPrefAreEqual(
}
int device_type;
- if (device_dictionary->GetInteger("device_type",
- &device_type)) {
+ if (device_dictionary->GetInteger("device_type", &device_type)) {
EXPECT_TRUE(expected_device.has_device_type());
- EXPECT_EQ(expected_device.device_type(),
- device_type);
+ EXPECT_EQ(expected_device.device_type(), device_type);
} else {
EXPECT_FALSE(expected_device.has_device_type());
}
const base::ListValue* beacon_seeds_from_prefs;
- if (device_dictionary->GetList("beacon_seeds",
- &beacon_seeds_from_prefs)) {
- ASSERT_EQ(
- (size_t) expected_device.beacon_seeds_size(),
- beacon_seeds_from_prefs->GetSize());
+ if (device_dictionary->GetList("beacon_seeds", &beacon_seeds_from_prefs)) {
+ ASSERT_EQ((size_t)expected_device.beacon_seeds_size(),
+ beacon_seeds_from_prefs->GetSize());
for (size_t i = 0; i < beacon_seeds_from_prefs->GetSize(); i++) {
const base::DictionaryValue* seed;
ASSERT_TRUE(beacon_seeds_from_prefs->GetDictionary(i, &seed));
@@ -268,8 +253,7 @@ void ExpectSyncedDevicesAndPrefAreEqual(
EXPECT_TRUE(seed->GetString("beacon_seed_start_ms", &start_ms));
EXPECT_TRUE(seed->GetString("beacon_seed_end_ms", &end_ms));
- const BeaconSeed& expected_seed =
- expected_device.beacon_seeds((int) i);
+ const BeaconSeed& expected_seed = expected_device.beacon_seeds((int)i);
std::string data;
EXPECT_TRUE(base::Base64UrlDecode(
@@ -290,17 +274,17 @@ void ExpectSyncedDevicesAndPrefAreEqual(
}
// Harness for testing CryptAuthDeviceManager.
-class TestCryptAuthDeviceManager : public CryptAuthDeviceManager {
+class TestCryptAuthDeviceManager : public CryptAuthDeviceManagerImpl {
public:
TestCryptAuthDeviceManager(
base::Clock* clock,
std::unique_ptr<CryptAuthClientFactory> client_factory,
CryptAuthGCMManager* gcm_manager,
PrefService* pref_service)
- : CryptAuthDeviceManager(clock,
- std::move(client_factory),
- gcm_manager,
- pref_service),
+ : CryptAuthDeviceManagerImpl(clock,
+ std::move(client_factory),
+ gcm_manager,
+ pref_service),
scoped_sync_scheduler_(new NiceMock<MockSyncScheduler>()),
weak_sync_scheduler_factory_(scoped_sync_scheduler_) {
SetSyncSchedulerForTest(base::WrapUnique(scoped_sync_scheduler_));
@@ -328,12 +312,12 @@ class TestCryptAuthDeviceManager : public CryptAuthDeviceManager {
} // namespace
-class CryptAuthDeviceManagerTest
+class CryptAuthDeviceManagerImplTest
: public testing::Test,
public CryptAuthDeviceManager::Observer,
public MockCryptAuthClientFactory::Observer {
protected:
- CryptAuthDeviceManagerTest()
+ CryptAuthDeviceManagerImplTest()
: client_factory_(new MockCryptAuthClientFactory(
MockCryptAuthClientFactory::MockType::MAKE_STRICT_MOCKS)),
gcm_manager_("existing gcm registration id") {
@@ -377,9 +361,7 @@ class CryptAuthDeviceManagerTest
devices_in_response_.push_back(unlockable_device);
}
- ~CryptAuthDeviceManagerTest() {
- client_factory_->RemoveObserver(this);
- }
+ ~CryptAuthDeviceManagerImplTest() { client_factory_->RemoveObserver(this); }
// testing::Test:
void SetUp() override {
@@ -388,13 +370,13 @@ class CryptAuthDeviceManagerTest
CryptAuthDeviceManager::RegisterPrefs(pref_service_.registry());
pref_service_.SetUserPref(
prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure,
- base::MakeUnique<base::Value>(false));
+ std::make_unique<base::Value>(false));
pref_service_.SetUserPref(
prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds,
- base::MakeUnique<base::Value>(kLastSyncTimeSeconds));
+ std::make_unique<base::Value>(kLastSyncTimeSeconds));
pref_service_.SetUserPref(
prefs::kCryptAuthDeviceSyncReason,
- base::MakeUnique<base::Value>(INVOCATION_REASON_UNKNOWN));
+ std::make_unique<base::Value>(INVOCATION_REASON_UNKNOWN));
std::unique_ptr<base::DictionaryValue> device_dictionary(
new base::DictionaryValue());
@@ -412,11 +394,10 @@ class CryptAuthDeviceManagerTest
device_dictionary->SetString("public_key", public_key_b64);
device_dictionary->SetString("device_name", device_name_b64);
- device_dictionary->SetString("bluetooth_address",
- bluetooth_address_b64);
+ device_dictionary->SetString("bluetooth_address", bluetooth_address_b64);
device_dictionary->SetBoolean("unlock_key", kStoredUnlockKey);
device_dictionary->SetBoolean("unlockable", kStoredUnlockable);
- device_dictionary->Set("beacon_seeds", base::MakeUnique<base::ListValue>());
+ device_dictionary->Set("beacon_seeds", std::make_unique<base::ListValue>());
device_dictionary->SetBoolean("mobile_hotspot_supported",
kStoredMobileHotspotSupported);
{
@@ -454,13 +435,12 @@ class CryptAuthDeviceManagerTest
CryptAuthDeviceManager::DeviceChangeResult));
// Simulates firing the SyncScheduler to trigger a device sync attempt.
- void FireSchedulerForSync(
- InvocationReason expected_invocation_reason) {
+ void FireSchedulerForSync(InvocationReason expected_invocation_reason) {
SyncScheduler::Delegate* delegate =
static_cast<SyncScheduler::Delegate*>(device_manager_.get());
std::unique_ptr<SyncScheduler::SyncRequest> sync_request =
- base::MakeUnique<SyncScheduler::SyncRequest>(
+ std::make_unique<SyncScheduler::SyncRequest>(
device_manager_->GetSyncScheduler());
EXPECT_CALL(*this, OnSyncStartedProxy());
delegate->OnSyncRequested(std::move(sync_request));
@@ -508,10 +488,10 @@ class CryptAuthDeviceManagerTest
CryptAuthClient::ErrorCallback error_callback_;
- DISALLOW_COPY_AND_ASSIGN(CryptAuthDeviceManagerTest);
+ DISALLOW_COPY_AND_ASSIGN(CryptAuthDeviceManagerImplTest);
};
-TEST_F(CryptAuthDeviceManagerTest, RegisterPrefs) {
+TEST_F(CryptAuthDeviceManagerImplTest, RegisterPrefs) {
TestingPrefServiceSimple pref_service;
CryptAuthDeviceManager::RegisterPrefs(pref_service.registry());
EXPECT_TRUE(pref_service.FindPreference(
@@ -523,7 +503,7 @@ TEST_F(CryptAuthDeviceManagerTest, RegisterPrefs) {
pref_service.FindPreference(prefs::kCryptAuthDeviceSyncUnlockKeys));
}
-TEST_F(CryptAuthDeviceManagerTest, GetSyncState) {
+TEST_F(CryptAuthDeviceManagerImplTest, GetSyncState) {
device_manager_->Start();
ON_CALL(*sync_scheduler(), GetStrategy())
@@ -548,7 +528,7 @@ TEST_F(CryptAuthDeviceManagerTest, GetSyncState) {
EXPECT_FALSE(device_manager_->IsSyncInProgress());
}
-TEST_F(CryptAuthDeviceManagerTest, InitWithDefaultPrefs) {
+TEST_F(CryptAuthDeviceManagerImplTest, InitWithDefaultPrefs) {
base::SimpleTestClock clock;
clock.SetNow(base::Time::FromDoubleT(kInitialTimeNowSeconds));
base::TimeDelta elapsed_time = clock.Now() - base::Time::FromDoubleT(0);
@@ -558,7 +538,7 @@ TEST_F(CryptAuthDeviceManagerTest, InitWithDefaultPrefs) {
TestCryptAuthDeviceManager device_manager(
&clock,
- base::MakeUnique<MockCryptAuthClientFactory>(
+ std::make_unique<MockCryptAuthClientFactory>(
MockCryptAuthClientFactory::MockType::MAKE_STRICT_MOCKS),
&gcm_manager_, &pref_service);
@@ -570,7 +550,7 @@ TEST_F(CryptAuthDeviceManagerTest, InitWithDefaultPrefs) {
EXPECT_EQ(0u, device_manager.GetSyncedDevices().size());
}
-TEST_F(CryptAuthDeviceManagerTest, InitWithExistingPrefs) {
+TEST_F(CryptAuthDeviceManagerImplTest, InitWithExistingPrefs) {
EXPECT_CALL(
*sync_scheduler(),
Start(clock_.Now() - base::Time::FromDoubleT(kLastSyncTimeSeconds),
@@ -589,7 +569,7 @@ TEST_F(CryptAuthDeviceManagerTest, InitWithExistingPrefs) {
EXPECT_EQ(kStoredUnlockable, synced_devices[0].unlockable());
}
-TEST_F(CryptAuthDeviceManagerTest, SyncSucceedsForFirstTime) {
+TEST_F(CryptAuthDeviceManagerImplTest, SyncSucceedsForFirstTime) {
pref_service_.ClearPref(prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds);
device_manager_->Start();
@@ -604,12 +584,11 @@ TEST_F(CryptAuthDeviceManagerTest, SyncSucceedsForFirstTime) {
success_callback_.Run(get_my_devices_response_);
EXPECT_EQ(clock_.Now(), device_manager_->GetLastSyncTime());
- ExpectSyncedDevicesAndPrefAreEqual(devices_in_response_,
- device_manager_->GetSyncedDevices(),
- pref_service_);
+ ExpectSyncedDevicesAndPrefAreEqual(
+ devices_in_response_, device_manager_->GetSyncedDevices(), pref_service_);
}
-TEST_F(CryptAuthDeviceManagerTest, ForceSync) {
+TEST_F(CryptAuthDeviceManagerImplTest, ForceSync) {
device_manager_->Start();
EXPECT_CALL(*sync_scheduler(), ForceSync());
@@ -624,12 +603,11 @@ TEST_F(CryptAuthDeviceManagerTest, ForceSync) {
success_callback_.Run(get_my_devices_response_);
EXPECT_EQ(clock_.Now(), device_manager_->GetLastSyncTime());
- ExpectSyncedDevicesAndPrefAreEqual(devices_in_response_,
- device_manager_->GetSyncedDevices(),
- pref_service_);
+ ExpectSyncedDevicesAndPrefAreEqual(
+ devices_in_response_, device_manager_->GetSyncedDevices(), pref_service_);
}
-TEST_F(CryptAuthDeviceManagerTest, ForceSyncFailsThenSucceeds) {
+TEST_F(CryptAuthDeviceManagerImplTest, ForceSyncFailsThenSucceeds) {
device_manager_->Start();
EXPECT_FALSE(pref_service_.GetBoolean(
prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure));
@@ -662,9 +640,8 @@ TEST_F(CryptAuthDeviceManagerTest, ForceSyncFailsThenSucceeds) {
success_callback_.Run(get_my_devices_response_);
EXPECT_EQ(clock_.Now(), device_manager_->GetLastSyncTime());
- ExpectSyncedDevicesAndPrefAreEqual(devices_in_response_,
- device_manager_->GetSyncedDevices(),
- pref_service_);
+ ExpectSyncedDevicesAndPrefAreEqual(
+ devices_in_response_, device_manager_->GetSyncedDevices(), pref_service_);
EXPECT_FLOAT_EQ(
clock_.Now().ToDoubleT(),
@@ -675,7 +652,7 @@ TEST_F(CryptAuthDeviceManagerTest, ForceSyncFailsThenSucceeds) {
prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure));
}
-TEST_F(CryptAuthDeviceManagerTest, PeriodicSyncFailsThenSucceeds) {
+TEST_F(CryptAuthDeviceManagerImplTest, PeriodicSyncFailsThenSucceeds) {
device_manager_->Start();
base::Time old_sync_time = device_manager_->GetLastSyncTime();
@@ -702,9 +679,8 @@ TEST_F(CryptAuthDeviceManagerTest, PeriodicSyncFailsThenSucceeds) {
success_callback_.Run(get_my_devices_response_);
EXPECT_EQ(clock_.Now(), device_manager_->GetLastSyncTime());
- ExpectSyncedDevicesAndPrefAreEqual(devices_in_response_,
- device_manager_->GetSyncedDevices(),
- pref_service_);
+ ExpectSyncedDevicesAndPrefAreEqual(
+ devices_in_response_, device_manager_->GetSyncedDevices(), pref_service_);
EXPECT_FLOAT_EQ(
clock_.Now().ToDoubleT(),
@@ -713,7 +689,7 @@ TEST_F(CryptAuthDeviceManagerTest, PeriodicSyncFailsThenSucceeds) {
prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure));
}
-TEST_F(CryptAuthDeviceManagerTest, SyncSameDevice) {
+TEST_F(CryptAuthDeviceManagerImplTest, SyncSameDevice) {
device_manager_->Start();
auto original_devices = device_manager_->GetSyncedDevices();
@@ -742,7 +718,7 @@ TEST_F(CryptAuthDeviceManagerTest, SyncSameDevice) {
original_devices, device_manager_->GetSyncedDevices(), pref_service_);
}
-TEST_F(CryptAuthDeviceManagerTest, SyncEmptyDeviceList) {
+TEST_F(CryptAuthDeviceManagerImplTest, SyncEmptyDeviceList) {
GetMyDevicesResponse empty_response;
device_manager_->Start();
@@ -755,13 +731,12 @@ TEST_F(CryptAuthDeviceManagerTest, SyncEmptyDeviceList) {
CryptAuthDeviceManager::DeviceChangeResult::CHANGED));
success_callback_.Run(empty_response);
- ExpectSyncedDevicesAndPrefAreEqual(
- std::vector<ExternalDeviceInfo>(),
- device_manager_->GetSyncedDevices(),
- pref_service_);
+ ExpectSyncedDevicesAndPrefAreEqual(std::vector<ExternalDeviceInfo>(),
+ device_manager_->GetSyncedDevices(),
+ pref_service_);
}
-TEST_F(CryptAuthDeviceManagerTest, SyncThreeDevices) {
+TEST_F(CryptAuthDeviceManagerImplTest, SyncThreeDevices) {
GetMyDevicesResponse response(get_my_devices_response_);
ExternalDeviceInfo synced_device2;
synced_device2.set_public_key("new public key");
@@ -777,8 +752,9 @@ TEST_F(CryptAuthDeviceManagerTest, SyncThreeDevices) {
device_manager_->Start();
EXPECT_EQ(1u, device_manager_->GetSyncedDevices().size());
- EXPECT_EQ(1u, pref_service_.GetList(prefs::kCryptAuthDeviceSyncUnlockKeys)
- ->GetSize());
+ EXPECT_EQ(
+ 1u,
+ pref_service_.GetList(prefs::kCryptAuthDeviceSyncUnlockKeys)->GetSize());
FireSchedulerForSync(INVOCATION_REASON_PERIODIC);
ASSERT_FALSE(success_callback_.is_null());
@@ -791,7 +767,7 @@ TEST_F(CryptAuthDeviceManagerTest, SyncThreeDevices) {
expected_devices, device_manager_->GetSyncedDevices(), pref_service_);
}
-TEST_F(CryptAuthDeviceManagerTest, SyncOnGCMPushMessage) {
+TEST_F(CryptAuthDeviceManagerImplTest, SyncOnGCMPushMessage) {
device_manager_->Start();
EXPECT_CALL(*sync_scheduler(), ForceSync());
@@ -804,12 +780,11 @@ TEST_F(CryptAuthDeviceManagerTest, SyncOnGCMPushMessage) {
CryptAuthDeviceManager::DeviceChangeResult::CHANGED));
success_callback_.Run(get_my_devices_response_);
- ExpectSyncedDevicesAndPrefAreEqual(devices_in_response_,
- device_manager_->GetSyncedDevices(),
- pref_service_);
+ ExpectSyncedDevicesAndPrefAreEqual(
+ devices_in_response_, device_manager_->GetSyncedDevices(), pref_service_);
}
-TEST_F(CryptAuthDeviceManagerTest, SyncDeviceWithNoContents) {
+TEST_F(CryptAuthDeviceManagerImplTest, SyncDeviceWithNoContents) {
device_manager_->Start();
EXPECT_CALL(*sync_scheduler(), ForceSync());
@@ -822,12 +797,11 @@ TEST_F(CryptAuthDeviceManagerTest, SyncDeviceWithNoContents) {
CryptAuthDeviceManager::DeviceChangeResult::CHANGED));
success_callback_.Run(get_my_devices_response_);
- ExpectSyncedDevicesAndPrefAreEqual(devices_in_response_,
- device_manager_->GetSyncedDevices(),
- pref_service_);
+ ExpectSyncedDevicesAndPrefAreEqual(
+ devices_in_response_, device_manager_->GetSyncedDevices(), pref_service_);
}
-TEST_F(CryptAuthDeviceManagerTest, SyncFullyDetailedExternalDeviceInfos) {
+TEST_F(CryptAuthDeviceManagerImplTest, SyncFullyDetailedExternalDeviceInfos) {
GetMyDevicesResponse response;
// First, use a device with only a public key (a public key is the only
@@ -881,22 +855,19 @@ TEST_F(CryptAuthDeviceManagerTest, SyncFullyDetailedExternalDeviceInfos) {
expected_devices, device_manager_->GetSyncedDevices(), pref_service_);
}
-TEST_F(CryptAuthDeviceManagerTest, SubsetsOfSyncedDevices) {
+TEST_F(CryptAuthDeviceManagerImplTest, SubsetsOfSyncedDevices) {
device_manager_->Start();
FireSchedulerForSync(INVOCATION_REASON_PERIODIC);
ASSERT_FALSE(success_callback_.is_null());
- EXPECT_CALL(*this,
- OnSyncFinishedProxy(
- CryptAuthDeviceManager::SyncResult::SUCCESS,
- CryptAuthDeviceManager::DeviceChangeResult::CHANGED));
+ EXPECT_CALL(*this, OnSyncFinishedProxy(
+ CryptAuthDeviceManager::SyncResult::SUCCESS,
+ CryptAuthDeviceManager::DeviceChangeResult::CHANGED));
success_callback_.Run(get_my_devices_response_);
// All synced devices.
ExpectSyncedDevicesAndPrefAreEqual(
- devices_in_response_,
- device_manager_->GetSyncedDevices(),
- pref_service_);
+ devices_in_response_, device_manager_->GetSyncedDevices(), pref_service_);
// Only unlock keys.
ExpectSyncedDevicesAreEqual(
diff --git a/chromium/components/cryptauth/cryptauth_enrollment_manager.cc b/chromium/components/cryptauth/cryptauth_enrollment_manager.cc
index 3645a34bb35..dcb8d91304b 100644
--- a/chromium/components/cryptauth/cryptauth_enrollment_manager.cc
+++ b/chromium/components/cryptauth/cryptauth_enrollment_manager.cc
@@ -4,74 +4,11 @@
#include "components/cryptauth/cryptauth_enrollment_manager.h"
-#include <utility>
-
-#include "base/base64url.h"
-#include "base/memory/ptr_util.h"
-#include "base/time/clock.h"
-#include "base/time/time.h"
-#include "components/cryptauth/cryptauth_enroller.h"
#include "components/cryptauth/pref_names.h"
-#include "components/cryptauth/secure_message_delegate.h"
-#include "components/cryptauth/sync_scheduler_impl.h"
#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/proximity_auth/logging/logging.h"
namespace cryptauth {
-namespace {
-
-// The number of days that an enrollment is valid. Note that we try to refresh
-// the enrollment well before this time elapses.
-const int kValidEnrollmentPeriodDays = 45;
-
-// The normal period between successful enrollments in days.
-const int kEnrollmentRefreshPeriodDays = 30;
-
-// A more aggressive period between enrollments to recover when the last
-// enrollment fails, in minutes. This is a base time that increases for each
-// subsequent failure.
-const int kEnrollmentBaseRecoveryPeriodMinutes = 10;
-
-// The bound on the amount to jitter the period between enrollments.
-const double kEnrollmentMaxJitterRatio = 0.2;
-
-// The value of the device_software_package field in the device info uploaded
-// during enrollment. This value must be the same as the app id used for GCM
-// registration.
-const char kDeviceSoftwarePackage[] = "com.google.chrome.cryptauth";
-
-std::unique_ptr<SyncScheduler> CreateSyncScheduler(
- SyncScheduler::Delegate* delegate) {
- return base::MakeUnique<SyncSchedulerImpl>(
- delegate, base::TimeDelta::FromDays(kEnrollmentRefreshPeriodDays),
- base::TimeDelta::FromMinutes(kEnrollmentBaseRecoveryPeriodMinutes),
- kEnrollmentMaxJitterRatio, "CryptAuth Enrollment");
-}
-
-} // namespace
-
-CryptAuthEnrollmentManager::CryptAuthEnrollmentManager(
- base::Clock* clock,
- std::unique_ptr<CryptAuthEnrollerFactory> enroller_factory,
- std::unique_ptr<SecureMessageDelegate> secure_message_delegate,
- const GcmDeviceInfo& device_info,
- CryptAuthGCMManager* gcm_manager,
- PrefService* pref_service)
- : clock_(clock),
- enroller_factory_(std::move(enroller_factory)),
- secure_message_delegate_(std::move(secure_message_delegate)),
- device_info_(device_info),
- gcm_manager_(gcm_manager),
- pref_service_(pref_service),
- scheduler_(CreateSyncScheduler(this /* delegate */)),
- weak_ptr_factory_(this) {}
-
-CryptAuthEnrollmentManager::~CryptAuthEnrollmentManager() {
- gcm_manager_->RemoveObserver(this);
-}
-
// static
void CryptAuthEnrollmentManager::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(
@@ -86,23 +23,9 @@ void CryptAuthEnrollmentManager::RegisterPrefs(PrefRegistrySimple* registry) {
std::string());
}
-void CryptAuthEnrollmentManager::Start() {
- gcm_manager_->AddObserver(this);
-
- bool is_recovering_from_failure =
- pref_service_->GetBoolean(
- prefs::kCryptAuthEnrollmentIsRecoveringFromFailure) ||
- !IsEnrollmentValid();
+CryptAuthEnrollmentManager::CryptAuthEnrollmentManager() = default;
- base::Time last_successful_enrollment = GetLastEnrollmentTime();
- base::TimeDelta elapsed_time_since_last_sync =
- clock_->Now() - last_successful_enrollment;
-
- scheduler_->Start(elapsed_time_since_last_sync,
- is_recovering_from_failure
- ? SyncScheduler::Strategy::AGGRESSIVE_RECOVERY
- : SyncScheduler::Strategy::PERIODIC_REFRESH);
-}
+CryptAuthEnrollmentManager::~CryptAuthEnrollmentManager() = default;
void CryptAuthEnrollmentManager::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
@@ -112,198 +35,14 @@ void CryptAuthEnrollmentManager::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
-void CryptAuthEnrollmentManager::ForceEnrollmentNow(
- InvocationReason invocation_reason) {
- // We store the invocation reason in a preference so that it can persist
- // across browser restarts. If the sync fails, the next retry should still use
- // this original reason instead of INVOCATION_REASON_FAILURE_RECOVERY.
- pref_service_->SetInteger(prefs::kCryptAuthEnrollmentReason,
- invocation_reason);
- scheduler_->ForceSync();
-}
-
-bool CryptAuthEnrollmentManager::IsEnrollmentValid() const {
- base::Time last_enrollment_time = GetLastEnrollmentTime();
- return !last_enrollment_time.is_null() &&
- (clock_->Now() - last_enrollment_time) <
- base::TimeDelta::FromDays(kValidEnrollmentPeriodDays);
-}
-
-base::Time CryptAuthEnrollmentManager::GetLastEnrollmentTime() const {
- return base::Time::FromDoubleT(pref_service_->GetDouble(
- prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds));
-}
-
-base::TimeDelta CryptAuthEnrollmentManager::GetTimeToNextAttempt() const {
- return scheduler_->GetTimeToNextSync();
-}
-
-bool CryptAuthEnrollmentManager::IsEnrollmentInProgress() const {
- return scheduler_->GetSyncState() ==
- SyncScheduler::SyncState::SYNC_IN_PROGRESS;
-}
-
-bool CryptAuthEnrollmentManager::IsRecoveringFromFailure() const {
- return scheduler_->GetStrategy() ==
- SyncScheduler::Strategy::AGGRESSIVE_RECOVERY;
-}
-
-void CryptAuthEnrollmentManager::OnEnrollmentFinished(bool success) {
- if (success) {
- pref_service_->SetDouble(
- prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds,
- clock_->Now().ToDoubleT());
- pref_service_->SetInteger(prefs::kCryptAuthEnrollmentReason,
- INVOCATION_REASON_UNKNOWN);
- }
-
- pref_service_->SetBoolean(prefs::kCryptAuthEnrollmentIsRecoveringFromFailure,
- !success);
-
- sync_request_->OnDidComplete(success);
- cryptauth_enroller_.reset();
- sync_request_.reset();
- for (auto& observer : observers_)
- observer.OnEnrollmentFinished(success);
-}
-
-std::string CryptAuthEnrollmentManager::GetUserPublicKey() const {
- std::string public_key;
- if (!base::Base64UrlDecode(
- pref_service_->GetString(prefs::kCryptAuthEnrollmentUserPublicKey),
- base::Base64UrlDecodePolicy::REQUIRE_PADDING, &public_key)) {
- PA_LOG(ERROR) << "Invalid public key stored in user prefs.";
- return std::string();
- }
- return public_key;
-}
-
-std::string CryptAuthEnrollmentManager::GetUserPrivateKey() const {
- std::string private_key;
- if (!base::Base64UrlDecode(
- pref_service_->GetString(prefs::kCryptAuthEnrollmentUserPrivateKey),
- base::Base64UrlDecodePolicy::REQUIRE_PADDING, &private_key)) {
- PA_LOG(ERROR) << "Invalid private key stored in user prefs.";
- return std::string();
- }
- return private_key;
-}
-
-void CryptAuthEnrollmentManager::SetSyncSchedulerForTest(
- std::unique_ptr<SyncScheduler> sync_scheduler) {
- scheduler_ = std::move(sync_scheduler);
-}
-
-void CryptAuthEnrollmentManager::OnGCMRegistrationResult(bool success) {
- if (!sync_request_)
- return;
-
- PA_LOG(INFO) << "GCM registration for CryptAuth Enrollment completed: "
- << success;
- if (success)
- DoCryptAuthEnrollment();
- else
- OnEnrollmentFinished(false);
-}
-
-void CryptAuthEnrollmentManager::OnKeyPairGenerated(
- const std::string& public_key,
- const std::string& private_key) {
- if (!public_key.empty() && !private_key.empty()) {
- PA_LOG(INFO) << "Key pair generated for CryptAuth enrollment";
- // Store the keypair in Base64 format because pref values require readable
- // string values.
- std::string public_key_b64, private_key_b64;
- base::Base64UrlEncode(public_key,
- base::Base64UrlEncodePolicy::INCLUDE_PADDING,
- &public_key_b64);
- base::Base64UrlEncode(private_key,
- base::Base64UrlEncodePolicy::INCLUDE_PADDING,
- &private_key_b64);
- pref_service_->SetString(prefs::kCryptAuthEnrollmentUserPublicKey,
- public_key_b64);
- pref_service_->SetString(prefs::kCryptAuthEnrollmentUserPrivateKey,
- private_key_b64);
- DoCryptAuthEnrollment();
- } else {
- OnEnrollmentFinished(false);
- }
-}
-
-void CryptAuthEnrollmentManager::OnReenrollMessage() {
- ForceEnrollmentNow(INVOCATION_REASON_SERVER_INITIATED);
-}
-
-void CryptAuthEnrollmentManager::OnSyncRequested(
- std::unique_ptr<SyncScheduler::SyncRequest> sync_request) {
+void CryptAuthEnrollmentManager::NotifyEnrollmentStarted() {
for (auto& observer : observers_)
observer.OnEnrollmentStarted();
-
- sync_request_ = std::move(sync_request);
- if (gcm_manager_->GetRegistrationId().empty() ||
- pref_service_->GetInteger(prefs::kCryptAuthEnrollmentReason) ==
- INVOCATION_REASON_MANUAL) {
- gcm_manager_->RegisterWithGCM();
- } else {
- DoCryptAuthEnrollment();
- }
-}
-
-void CryptAuthEnrollmentManager::DoCryptAuthEnrollment() {
- if (GetUserPublicKey().empty() || GetUserPrivateKey().empty()) {
- secure_message_delegate_->GenerateKeyPair(
- base::Bind(&CryptAuthEnrollmentManager::OnKeyPairGenerated,
- weak_ptr_factory_.GetWeakPtr()));
- } else {
- DoCryptAuthEnrollmentWithKeys();
- }
}
-void CryptAuthEnrollmentManager::DoCryptAuthEnrollmentWithKeys() {
- DCHECK(sync_request_);
- InvocationReason invocation_reason =
- INVOCATION_REASON_UNKNOWN;
-
- int reason_stored_in_prefs =
- pref_service_->GetInteger(prefs::kCryptAuthEnrollmentReason);
-
- if (InvocationReason_IsValid(reason_stored_in_prefs) &&
- reason_stored_in_prefs != INVOCATION_REASON_UNKNOWN) {
- invocation_reason =
- static_cast<InvocationReason>(reason_stored_in_prefs);
- } else if (GetLastEnrollmentTime().is_null()) {
- invocation_reason = INVOCATION_REASON_INITIALIZATION;
- } else if (!IsEnrollmentValid()) {
- invocation_reason = INVOCATION_REASON_EXPIRATION;
- } else if (scheduler_->GetStrategy() ==
- SyncScheduler::Strategy::PERIODIC_REFRESH) {
- invocation_reason = INVOCATION_REASON_PERIODIC;
- } else if (scheduler_->GetStrategy() ==
- SyncScheduler::Strategy::AGGRESSIVE_RECOVERY) {
- invocation_reason = INVOCATION_REASON_FAILURE_RECOVERY;
- }
-
- // Fill in the current GCM registration id before enrolling, and explicitly
- // make sure that the software package is the same as the GCM app id.
- GcmDeviceInfo device_info(device_info_);
- device_info.set_gcm_registration_id(gcm_manager_->GetRegistrationId());
- device_info.set_device_software_package(kDeviceSoftwarePackage);
-
- std::string public_key_b64;
- base::Base64UrlEncode(GetUserPublicKey(),
- base::Base64UrlEncodePolicy::INCLUDE_PADDING,
- &public_key_b64);
- PA_LOG(INFO) << "Making enrollment:\n"
- << " public_key: " << public_key_b64 << "\n"
- << " invocation_reason: " << invocation_reason << "\n"
- << " gcm_registration_id: "
- << device_info.gcm_registration_id();
-
- cryptauth_enroller_ = enroller_factory_->CreateInstance();
- cryptauth_enroller_->Enroll(
- GetUserPublicKey(), GetUserPrivateKey(), device_info, invocation_reason,
- base::Bind(&CryptAuthEnrollmentManager::OnEnrollmentFinished,
- weak_ptr_factory_.GetWeakPtr()));
+void CryptAuthEnrollmentManager::NotifyEnrollmentFinished(bool success) {
+ for (auto& observer : observers_)
+ observer.OnEnrollmentFinished(success);
}
} // namespace cryptauth
diff --git a/chromium/components/cryptauth/cryptauth_enrollment_manager.h b/chromium/components/cryptauth/cryptauth_enrollment_manager.h
index 2b21c9bd2a7..5b0bb5b6d31 100644
--- a/chromium/components/cryptauth/cryptauth_enrollment_manager.h
+++ b/chromium/components/cryptauth/cryptauth_enrollment_manager.h
@@ -8,33 +8,19 @@
#include <memory>
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
-#include "components/cryptauth/cryptauth_gcm_manager.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
-#include "components/cryptauth/sync_scheduler.h"
class PrefRegistrySimple;
-class PrefService;
-
-namespace base {
-class Clock;
-class Time;
-}
namespace cryptauth {
-class CryptAuthEnroller;
-class CryptAuthEnrollerFactory;
-class SecureMessageDelegate;
-
// This class manages the device's enrollment with CryptAuth, periodically
// re-enrolling to keep the state on the server fresh. If an enrollment fails,
// the manager will schedule the next enrollment more aggressively to recover
// from the failure.
-class CryptAuthEnrollmentManager : public SyncScheduler::Delegate,
- public CryptAuthGCMManager::Observer {
+class CryptAuthEnrollmentManager {
public:
class Observer {
public:
@@ -45,141 +31,60 @@ class CryptAuthEnrollmentManager : public SyncScheduler::Delegate,
// attempt.
virtual void OnEnrollmentFinished(bool success) = 0;
- virtual ~Observer() {}
+ virtual ~Observer() = default;
};
- // Creates the manager:
- // |clock|: Used to determine the time between sync attempts.
- // |enroller_factory|: Creates CryptAuthEnroller instances to perform each
- // enrollment attempt.
- // |secure_message_delegate|: Used to generate the user's keypair if it does
- // not exist.
- // |device_info|: Contains information about the local device that will be
- // uploaded to CryptAuth with each enrollment request.
- // |gcm_manager|: Used to perform GCM registrations and also notifies when GCM
- // push messages trigger re-enrollments.
- // Not owned and must outlive this instance.
- // |pref_service|: Contains preferences across browser restarts, and should
- // have been registered through RegisterPrefs().
- CryptAuthEnrollmentManager(
- base::Clock* clock,
- std::unique_ptr<CryptAuthEnrollerFactory> enroller_factory,
- std::unique_ptr<SecureMessageDelegate> secure_message_delegate,
- const GcmDeviceInfo& device_info,
- CryptAuthGCMManager* gcm_manager,
- PrefService* pref_service);
-
- ~CryptAuthEnrollmentManager() override;
-
// Registers the prefs used by this class to the given |pref_service|.
static void RegisterPrefs(PrefRegistrySimple* registry);
- // Begins scheduling periodic enrollment attempts.
- void Start();
+ CryptAuthEnrollmentManager();
+ virtual ~CryptAuthEnrollmentManager();
- // Adds an observer.
void AddObserver(Observer* observer);
-
- // Removes an observer.
void RemoveObserver(Observer* observer);
+ // Begins scheduling periodic enrollment attempts.
+ virtual void Start() = 0;
+
// Skips the waiting period and forces an enrollment immediately. If an
// enrollment is already in progress, this function does nothing.
// |invocation_reason| specifies the reason that the enrollment was triggered,
// which is upload to the server.
- void ForceEnrollmentNow(InvocationReason invocation_reason);
+ virtual void ForceEnrollmentNow(InvocationReason invocation_reason) = 0;
// Returns true if a successful enrollment has been recorded and this
// enrollment has not expired.
- bool IsEnrollmentValid() const;
+ virtual bool IsEnrollmentValid() const = 0;
// Returns the timestamp of the last successful enrollment. If no enrollment
// has ever been made, then a null base::Time object will be returned.
- base::Time GetLastEnrollmentTime() const;
+ virtual base::Time GetLastEnrollmentTime() const = 0;
// Returns the time to the next enrollment attempt.
- base::TimeDelta GetTimeToNextAttempt() const;
+ virtual base::TimeDelta GetTimeToNextAttempt() const = 0;
// Returns true if an enrollment attempt is currently in progress.
- bool IsEnrollmentInProgress() const;
+ virtual bool IsEnrollmentInProgress() const = 0;
// Returns true if the last enrollment failed and the manager is now
// scheduling enrollments more aggressively to recover. If no enrollment has
// ever been recorded, then this function will also return true.
- bool IsRecoveringFromFailure() const;
+ virtual bool IsRecoveringFromFailure() const = 0;
// Returns the keypair used to enroll with CryptAuth. If no enrollment has
// been completed, then an empty string will be returned.
// Note: These keys are really serialized protocol buffer messages, and should
// only be used by passing to SecureMessageDelegate.
- virtual std::string GetUserPublicKey() const;
- virtual std::string GetUserPrivateKey() const;
+ virtual std::string GetUserPublicKey() const = 0;
+ virtual std::string GetUserPrivateKey() const = 0;
protected:
- void SetSyncSchedulerForTest(std::unique_ptr<SyncScheduler> sync_scheduler);
+ void NotifyEnrollmentStarted();
+ void NotifyEnrollmentFinished(bool success);
private:
- // CryptAuthGCMManager::Observer:
- void OnGCMRegistrationResult(bool success) override;
- void OnReenrollMessage() override;
-
- // Callback when a new keypair is generated.
- void OnKeyPairGenerated(const std::string& public_key,
- const std::string& private_key);
-
- // SyncScheduler::Delegate:
- void OnSyncRequested(
- std::unique_ptr<SyncScheduler::SyncRequest> sync_request) override;
-
- // Starts a CryptAuth enrollment attempt, generating a new keypair if one is
- // not already stored in the user prefs.
- void DoCryptAuthEnrollment();
-
- // Starts a CryptAuth enrollment attempt, after a key-pair is stored in the
- // user prefs.
- void DoCryptAuthEnrollmentWithKeys();
-
- // Callback when |cryptauth_enroller_| completes.
- void OnEnrollmentFinished(bool success);
-
- // Used to determine the time.
- base::Clock* clock_;
-
- // Creates CryptAuthEnroller instances for each enrollment attempt.
- std::unique_ptr<CryptAuthEnrollerFactory> enroller_factory_;
-
- // The SecureMessageDelegate used to generate the user's keypair if it does
- // not already exist.
- std::unique_ptr<SecureMessageDelegate> secure_message_delegate_;
-
- // The local device information to upload to CryptAuth.
- const GcmDeviceInfo device_info_;
-
- // Used to perform GCM registrations and also notifies when GCM push messages
- // trigger re-enrollments. Not owned and must outlive this instance.
- CryptAuthGCMManager* gcm_manager_;
-
- // Contains perferences that outlive the lifetime of this object and across
- // process restarts.
- // Not owned and must outlive this instance.
- PrefService* pref_service_;
-
- // Schedules the time between enrollment attempts.
- std::unique_ptr<SyncScheduler> scheduler_;
-
- // Contains the SyncRequest that |scheduler_| requests when an enrollment
- // attempt is made.
- std::unique_ptr<SyncScheduler::SyncRequest> sync_request_;
-
- // The CryptAuthEnroller instance for the current enrollment attempt. A new
- // instance will be created for each individual attempt.
- std::unique_ptr<CryptAuthEnroller> cryptauth_enroller_;
-
- // List of observers.
base::ObserverList<Observer> observers_;
- base::WeakPtrFactory<CryptAuthEnrollmentManager> weak_ptr_factory_;
-
DISALLOW_COPY_AND_ASSIGN(CryptAuthEnrollmentManager);
};
diff --git a/chromium/components/cryptauth/cryptauth_enrollment_manager_impl.cc b/chromium/components/cryptauth/cryptauth_enrollment_manager_impl.cc
new file mode 100644
index 00000000000..9759d230051
--- /dev/null
+++ b/chromium/components/cryptauth/cryptauth_enrollment_manager_impl.cc
@@ -0,0 +1,284 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cryptauth/cryptauth_enrollment_manager_impl.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/base64url.h"
+#include "base/time/clock.h"
+#include "base/time/time.h"
+#include "components/cryptauth/cryptauth_enroller.h"
+#include "components/cryptauth/pref_names.h"
+#include "components/cryptauth/secure_message_delegate.h"
+#include "components/cryptauth/sync_scheduler_impl.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/proximity_auth/logging/logging.h"
+
+namespace cryptauth {
+
+namespace {
+
+// The number of days that an enrollment is valid. Note that we try to refresh
+// the enrollment well before this time elapses.
+const int kValidEnrollmentPeriodDays = 45;
+
+// The normal period between successful enrollments in days.
+const int kEnrollmentRefreshPeriodDays = 30;
+
+// A more aggressive period between enrollments to recover when the last
+// enrollment fails, in minutes. This is a base time that increases for each
+// subsequent failure.
+const int kEnrollmentBaseRecoveryPeriodMinutes = 10;
+
+// The bound on the amount to jitter the period between enrollments.
+const double kEnrollmentMaxJitterRatio = 0.2;
+
+// The value of the device_software_package field in the device info uploaded
+// during enrollment. This value must be the same as the app id used for GCM
+// registration.
+const char kDeviceSoftwarePackage[] = "com.google.chrome.cryptauth";
+
+std::unique_ptr<SyncScheduler> CreateSyncScheduler(
+ SyncScheduler::Delegate* delegate) {
+ return std::make_unique<SyncSchedulerImpl>(
+ delegate, base::TimeDelta::FromDays(kEnrollmentRefreshPeriodDays),
+ base::TimeDelta::FromMinutes(kEnrollmentBaseRecoveryPeriodMinutes),
+ kEnrollmentMaxJitterRatio, "CryptAuth Enrollment");
+}
+
+} // namespace
+
+CryptAuthEnrollmentManagerImpl::CryptAuthEnrollmentManagerImpl(
+ base::Clock* clock,
+ std::unique_ptr<CryptAuthEnrollerFactory> enroller_factory,
+ std::unique_ptr<SecureMessageDelegate> secure_message_delegate,
+ const GcmDeviceInfo& device_info,
+ CryptAuthGCMManager* gcm_manager,
+ PrefService* pref_service)
+ : clock_(clock),
+ enroller_factory_(std::move(enroller_factory)),
+ secure_message_delegate_(std::move(secure_message_delegate)),
+ device_info_(device_info),
+ gcm_manager_(gcm_manager),
+ pref_service_(pref_service),
+ scheduler_(CreateSyncScheduler(this /* delegate */)),
+ weak_ptr_factory_(this) {}
+
+CryptAuthEnrollmentManagerImpl::~CryptAuthEnrollmentManagerImpl() {
+ gcm_manager_->RemoveObserver(this);
+}
+
+void CryptAuthEnrollmentManagerImpl::Start() {
+ gcm_manager_->AddObserver(this);
+
+ bool is_recovering_from_failure =
+ pref_service_->GetBoolean(
+ prefs::kCryptAuthEnrollmentIsRecoveringFromFailure) ||
+ !IsEnrollmentValid();
+
+ base::Time last_successful_enrollment = GetLastEnrollmentTime();
+ base::TimeDelta elapsed_time_since_last_sync =
+ clock_->Now() - last_successful_enrollment;
+
+ scheduler_->Start(elapsed_time_since_last_sync,
+ is_recovering_from_failure
+ ? SyncScheduler::Strategy::AGGRESSIVE_RECOVERY
+ : SyncScheduler::Strategy::PERIODIC_REFRESH);
+}
+
+void CryptAuthEnrollmentManagerImpl::ForceEnrollmentNow(
+ InvocationReason invocation_reason) {
+ // We store the invocation reason in a preference so that it can persist
+ // across browser restarts. If the sync fails, the next retry should still use
+ // this original reason instead of INVOCATION_REASON_FAILURE_RECOVERY.
+ pref_service_->SetInteger(prefs::kCryptAuthEnrollmentReason,
+ invocation_reason);
+ scheduler_->ForceSync();
+}
+
+bool CryptAuthEnrollmentManagerImpl::IsEnrollmentValid() const {
+ base::Time last_enrollment_time = GetLastEnrollmentTime();
+ return !last_enrollment_time.is_null() &&
+ (clock_->Now() - last_enrollment_time) <
+ base::TimeDelta::FromDays(kValidEnrollmentPeriodDays);
+}
+
+base::Time CryptAuthEnrollmentManagerImpl::GetLastEnrollmentTime() const {
+ return base::Time::FromDoubleT(pref_service_->GetDouble(
+ prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds));
+}
+
+base::TimeDelta CryptAuthEnrollmentManagerImpl::GetTimeToNextAttempt() const {
+ return scheduler_->GetTimeToNextSync();
+}
+
+bool CryptAuthEnrollmentManagerImpl::IsEnrollmentInProgress() const {
+ return scheduler_->GetSyncState() ==
+ SyncScheduler::SyncState::SYNC_IN_PROGRESS;
+}
+
+bool CryptAuthEnrollmentManagerImpl::IsRecoveringFromFailure() const {
+ return scheduler_->GetStrategy() ==
+ SyncScheduler::Strategy::AGGRESSIVE_RECOVERY;
+}
+
+void CryptAuthEnrollmentManagerImpl::OnEnrollmentFinished(bool success) {
+ if (success) {
+ pref_service_->SetDouble(
+ prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds,
+ clock_->Now().ToDoubleT());
+ pref_service_->SetInteger(prefs::kCryptAuthEnrollmentReason,
+ INVOCATION_REASON_UNKNOWN);
+ }
+
+ pref_service_->SetBoolean(prefs::kCryptAuthEnrollmentIsRecoveringFromFailure,
+ !success);
+
+ sync_request_->OnDidComplete(success);
+ cryptauth_enroller_.reset();
+ sync_request_.reset();
+
+ NotifyEnrollmentFinished(success);
+}
+
+std::string CryptAuthEnrollmentManagerImpl::GetUserPublicKey() const {
+ std::string public_key;
+ if (!base::Base64UrlDecode(
+ pref_service_->GetString(prefs::kCryptAuthEnrollmentUserPublicKey),
+ base::Base64UrlDecodePolicy::REQUIRE_PADDING, &public_key)) {
+ PA_LOG(ERROR) << "Invalid public key stored in user prefs.";
+ return std::string();
+ }
+ return public_key;
+}
+
+std::string CryptAuthEnrollmentManagerImpl::GetUserPrivateKey() const {
+ std::string private_key;
+ if (!base::Base64UrlDecode(
+ pref_service_->GetString(prefs::kCryptAuthEnrollmentUserPrivateKey),
+ base::Base64UrlDecodePolicy::REQUIRE_PADDING, &private_key)) {
+ PA_LOG(ERROR) << "Invalid private key stored in user prefs.";
+ return std::string();
+ }
+ return private_key;
+}
+
+void CryptAuthEnrollmentManagerImpl::SetSyncSchedulerForTest(
+ std::unique_ptr<SyncScheduler> sync_scheduler) {
+ scheduler_ = std::move(sync_scheduler);
+}
+
+void CryptAuthEnrollmentManagerImpl::OnGCMRegistrationResult(bool success) {
+ if (!sync_request_)
+ return;
+
+ PA_LOG(INFO) << "GCM registration for CryptAuth Enrollment completed: "
+ << success;
+ if (success)
+ DoCryptAuthEnrollment();
+ else
+ OnEnrollmentFinished(false);
+}
+
+void CryptAuthEnrollmentManagerImpl::OnKeyPairGenerated(
+ const std::string& public_key,
+ const std::string& private_key) {
+ if (!public_key.empty() && !private_key.empty()) {
+ PA_LOG(INFO) << "Key pair generated for CryptAuth enrollment";
+ // Store the keypair in Base64 format because pref values require readable
+ // string values.
+ std::string public_key_b64, private_key_b64;
+ base::Base64UrlEncode(public_key,
+ base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ &public_key_b64);
+ base::Base64UrlEncode(private_key,
+ base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ &private_key_b64);
+ pref_service_->SetString(prefs::kCryptAuthEnrollmentUserPublicKey,
+ public_key_b64);
+ pref_service_->SetString(prefs::kCryptAuthEnrollmentUserPrivateKey,
+ private_key_b64);
+ DoCryptAuthEnrollment();
+ } else {
+ OnEnrollmentFinished(false);
+ }
+}
+
+void CryptAuthEnrollmentManagerImpl::OnReenrollMessage() {
+ ForceEnrollmentNow(INVOCATION_REASON_SERVER_INITIATED);
+}
+
+void CryptAuthEnrollmentManagerImpl::OnSyncRequested(
+ std::unique_ptr<SyncScheduler::SyncRequest> sync_request) {
+ NotifyEnrollmentStarted();
+
+ sync_request_ = std::move(sync_request);
+ if (gcm_manager_->GetRegistrationId().empty() ||
+ pref_service_->GetInteger(prefs::kCryptAuthEnrollmentReason) ==
+ INVOCATION_REASON_MANUAL) {
+ gcm_manager_->RegisterWithGCM();
+ } else {
+ DoCryptAuthEnrollment();
+ }
+}
+
+void CryptAuthEnrollmentManagerImpl::DoCryptAuthEnrollment() {
+ if (GetUserPublicKey().empty() || GetUserPrivateKey().empty()) {
+ secure_message_delegate_->GenerateKeyPair(
+ base::Bind(&CryptAuthEnrollmentManagerImpl::OnKeyPairGenerated,
+ weak_ptr_factory_.GetWeakPtr()));
+ } else {
+ DoCryptAuthEnrollmentWithKeys();
+ }
+}
+
+void CryptAuthEnrollmentManagerImpl::DoCryptAuthEnrollmentWithKeys() {
+ DCHECK(sync_request_);
+ InvocationReason invocation_reason = INVOCATION_REASON_UNKNOWN;
+
+ int reason_stored_in_prefs =
+ pref_service_->GetInteger(prefs::kCryptAuthEnrollmentReason);
+
+ if (InvocationReason_IsValid(reason_stored_in_prefs) &&
+ reason_stored_in_prefs != INVOCATION_REASON_UNKNOWN) {
+ invocation_reason = static_cast<InvocationReason>(reason_stored_in_prefs);
+ } else if (GetLastEnrollmentTime().is_null()) {
+ invocation_reason = INVOCATION_REASON_INITIALIZATION;
+ } else if (!IsEnrollmentValid()) {
+ invocation_reason = INVOCATION_REASON_EXPIRATION;
+ } else if (scheduler_->GetStrategy() ==
+ SyncScheduler::Strategy::PERIODIC_REFRESH) {
+ invocation_reason = INVOCATION_REASON_PERIODIC;
+ } else if (scheduler_->GetStrategy() ==
+ SyncScheduler::Strategy::AGGRESSIVE_RECOVERY) {
+ invocation_reason = INVOCATION_REASON_FAILURE_RECOVERY;
+ }
+
+ // Fill in the current GCM registration id before enrolling, and explicitly
+ // make sure that the software package is the same as the GCM app id.
+ GcmDeviceInfo device_info(device_info_);
+ device_info.set_gcm_registration_id(gcm_manager_->GetRegistrationId());
+ device_info.set_device_software_package(kDeviceSoftwarePackage);
+
+ std::string public_key_b64;
+ base::Base64UrlEncode(GetUserPublicKey(),
+ base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ &public_key_b64);
+ PA_LOG(INFO) << "Making enrollment:\n"
+ << " public_key: " << public_key_b64 << "\n"
+ << " invocation_reason: " << invocation_reason << "\n"
+ << " gcm_registration_id: "
+ << device_info.gcm_registration_id();
+
+ cryptauth_enroller_ = enroller_factory_->CreateInstance();
+ cryptauth_enroller_->Enroll(
+ GetUserPublicKey(), GetUserPrivateKey(), device_info, invocation_reason,
+ base::Bind(&CryptAuthEnrollmentManagerImpl::OnEnrollmentFinished,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+} // namespace cryptauth
diff --git a/chromium/components/cryptauth/cryptauth_enrollment_manager_impl.h b/chromium/components/cryptauth/cryptauth_enrollment_manager_impl.h
new file mode 100644
index 00000000000..52b378ba70d
--- /dev/null
+++ b/chromium/components/cryptauth/cryptauth_enrollment_manager_impl.h
@@ -0,0 +1,137 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CRYPTAUTH_CRYPTAUTH_ENROLLMENT_MANAGER_IMPL_H_
+#define COMPONENTS_CRYPTAUTH_CRYPTAUTH_ENROLLMENT_MANAGER_IMPL_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "base/time/time.h"
+#include "components/cryptauth/cryptauth_enrollment_manager.h"
+#include "components/cryptauth/cryptauth_gcm_manager.h"
+#include "components/cryptauth/proto/cryptauth_api.pb.h"
+#include "components/cryptauth/sync_scheduler.h"
+
+class PrefService;
+
+namespace base {
+class Clock;
+}
+
+namespace cryptauth {
+
+class CryptAuthEnroller;
+class CryptAuthEnrollerFactory;
+class SecureMessageDelegate;
+
+// Concrete CryptAuthEnrollmentManager implementation.
+class CryptAuthEnrollmentManagerImpl : public CryptAuthEnrollmentManager,
+ public SyncScheduler::Delegate,
+ public CryptAuthGCMManager::Observer {
+ public:
+ // Creates the manager:
+ // |clock|: Used to determine the time between sync attempts.
+ // |enroller_factory|: Creates CryptAuthEnroller instances to perform each
+ // enrollment attempt.
+ // |secure_message_delegate|: Used to generate the user's keypair if it does
+ // not exist.
+ // |device_info|: Contains information about the local device that will be
+ // uploaded to CryptAuth with each enrollment request.
+ // |gcm_manager|: Used to perform GCM registrations and also notifies when GCM
+ // push messages trigger re-enrollments.
+ // Not owned and must outlive this instance.
+ // |pref_service|: Contains preferences across browser restarts, and should
+ // have been registered through RegisterPrefs().
+ CryptAuthEnrollmentManagerImpl(
+ base::Clock* clock,
+ std::unique_ptr<CryptAuthEnrollerFactory> enroller_factory,
+ std::unique_ptr<SecureMessageDelegate> secure_message_delegate,
+ const GcmDeviceInfo& device_info,
+ CryptAuthGCMManager* gcm_manager,
+ PrefService* pref_service);
+
+ ~CryptAuthEnrollmentManagerImpl() override;
+
+ // CryptAuthEnrollmentManager:
+ void Start() override;
+ void ForceEnrollmentNow(InvocationReason invocation_reason) override;
+ bool IsEnrollmentValid() const override;
+ base::Time GetLastEnrollmentTime() const override;
+ base::TimeDelta GetTimeToNextAttempt() const override;
+ bool IsEnrollmentInProgress() const override;
+ bool IsRecoveringFromFailure() const override;
+ std::string GetUserPublicKey() const override;
+ std::string GetUserPrivateKey() const override;
+
+ protected:
+ void SetSyncSchedulerForTest(std::unique_ptr<SyncScheduler> sync_scheduler);
+
+ private:
+ // CryptAuthGCMManager::Observer:
+ void OnGCMRegistrationResult(bool success) override;
+ void OnReenrollMessage() override;
+
+ // Callback when a new keypair is generated.
+ void OnKeyPairGenerated(const std::string& public_key,
+ const std::string& private_key);
+
+ // SyncScheduler::Delegate:
+ void OnSyncRequested(
+ std::unique_ptr<SyncScheduler::SyncRequest> sync_request) override;
+
+ // Starts a CryptAuth enrollment attempt, generating a new keypair if one is
+ // not already stored in the user prefs.
+ void DoCryptAuthEnrollment();
+
+ // Starts a CryptAuth enrollment attempt, after a key-pair is stored in the
+ // user prefs.
+ void DoCryptAuthEnrollmentWithKeys();
+
+ // Callback when |cryptauth_enroller_| completes.
+ void OnEnrollmentFinished(bool success);
+
+ // Used to determine the time.
+ base::Clock* clock_;
+
+ // Creates CryptAuthEnroller instances for each enrollment attempt.
+ std::unique_ptr<CryptAuthEnrollerFactory> enroller_factory_;
+
+ // The SecureMessageDelegate used to generate the user's keypair if it does
+ // not already exist.
+ std::unique_ptr<SecureMessageDelegate> secure_message_delegate_;
+
+ // The local device information to upload to CryptAuth.
+ const GcmDeviceInfo device_info_;
+
+ // Used to perform GCM registrations and also notifies when GCM push messages
+ // trigger re-enrollments. Not owned and must outlive this instance.
+ CryptAuthGCMManager* gcm_manager_;
+
+ // Contains perferences that outlive the lifetime of this object and across
+ // process restarts.
+ // Not owned and must outlive this instance.
+ PrefService* pref_service_;
+
+ // Schedules the time between enrollment attempts.
+ std::unique_ptr<SyncScheduler> scheduler_;
+
+ // Contains the SyncRequest that |scheduler_| requests when an enrollment
+ // attempt is made.
+ std::unique_ptr<SyncScheduler::SyncRequest> sync_request_;
+
+ // The CryptAuthEnroller instance for the current enrollment attempt. A new
+ // instance will be created for each individual attempt.
+ std::unique_ptr<CryptAuthEnroller> cryptauth_enroller_;
+
+ base::WeakPtrFactory<CryptAuthEnrollmentManagerImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CryptAuthEnrollmentManagerImpl);
+};
+
+} // namespace cryptauth
+
+#endif // COMPONENTS_CRYPTAUTH_CRYPTAUTH_ENROLLMENT_MANAGER_IMPL_H_
diff --git a/chromium/components/cryptauth/cryptauth_enrollment_manager_unittest.cc b/chromium/components/cryptauth/cryptauth_enrollment_manager_impl_unittest.cc
index 910e92835b0..10fc7bbf82f 100644
--- a/chromium/components/cryptauth/cryptauth_enrollment_manager_unittest.cc
+++ b/chromium/components/cryptauth/cryptauth_enrollment_manager_impl_unittest.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/cryptauth/cryptauth_enrollment_manager.h"
+#include "components/cryptauth/cryptauth_enrollment_manager_impl.h"
+#include <memory>
#include <utility>
#include "base/base64url.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/test/simple_test_clock.h"
#include "base/time/clock.h"
@@ -96,7 +96,7 @@ class MockCryptAuthEnrollerFactory : public CryptAuthEnrollerFactory {
};
// Harness for testing CryptAuthEnrollmentManager.
-class TestCryptAuthEnrollmentManager : public CryptAuthEnrollmentManager {
+class TestCryptAuthEnrollmentManager : public CryptAuthEnrollmentManagerImpl {
public:
TestCryptAuthEnrollmentManager(
base::Clock* clock,
@@ -105,12 +105,12 @@ class TestCryptAuthEnrollmentManager : public CryptAuthEnrollmentManager {
const GcmDeviceInfo& device_info,
CryptAuthGCMManager* gcm_manager,
PrefService* pref_service)
- : CryptAuthEnrollmentManager(clock,
- std::move(enroller_factory),
- std::move(secure_message_delegate),
- device_info,
- gcm_manager,
- pref_service),
+ : CryptAuthEnrollmentManagerImpl(clock,
+ std::move(enroller_factory),
+ std::move(secure_message_delegate),
+ device_info,
+ gcm_manager,
+ pref_service),
scoped_sync_scheduler_(new NiceMock<MockSyncScheduler>()),
weak_sync_scheduler_factory_(scoped_sync_scheduler_) {
SetSyncSchedulerForTest(base::WrapUnique(scoped_sync_scheduler_));
@@ -138,11 +138,11 @@ class TestCryptAuthEnrollmentManager : public CryptAuthEnrollmentManager {
} // namespace
-class CryptAuthEnrollmentManagerTest
+class CryptAuthEnrollmentManagerImplTest
: public testing::Test,
public CryptAuthEnrollmentManager::Observer {
protected:
- CryptAuthEnrollmentManagerTest()
+ CryptAuthEnrollmentManagerImplTest()
: public_key_(kUserPublicKey),
enroller_factory_(new MockCryptAuthEnrollerFactory()),
secure_message_delegate_(new FakeSecureMessageDelegate()),
@@ -166,13 +166,13 @@ class CryptAuthEnrollmentManagerTest
CryptAuthEnrollmentManager::RegisterPrefs(pref_service_.registry());
pref_service_.SetUserPref(
prefs::kCryptAuthEnrollmentIsRecoveringFromFailure,
- base::MakeUnique<base::Value>(false));
+ std::make_unique<base::Value>(false));
pref_service_.SetUserPref(
prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds,
- base::MakeUnique<base::Value>(kLastEnrollmentTimeSeconds));
+ std::make_unique<base::Value>(kLastEnrollmentTimeSeconds));
pref_service_.SetUserPref(
prefs::kCryptAuthEnrollmentReason,
- base::MakeUnique<base::Value>(INVOCATION_REASON_UNKNOWN));
+ std::make_unique<base::Value>(INVOCATION_REASON_UNKNOWN));
std::string public_key_b64, private_key_b64;
base::Base64UrlEncode(public_key_,
@@ -217,7 +217,7 @@ class CryptAuthEnrollmentManagerTest
Enroll(public_key_, private_key_, _, expected_invocation_reason, _))
.WillOnce(SaveArg<4>(&completion_callback));
- auto sync_request = base::MakeUnique<SyncScheduler::SyncRequest>(
+ auto sync_request = std::make_unique<SyncScheduler::SyncRequest>(
enrollment_manager_.GetSyncScheduler());
EXPECT_CALL(*this, OnEnrollmentStartedProxy());
@@ -256,10 +256,10 @@ class CryptAuthEnrollmentManagerTest
TestCryptAuthEnrollmentManager enrollment_manager_;
- DISALLOW_COPY_AND_ASSIGN(CryptAuthEnrollmentManagerTest);
+ DISALLOW_COPY_AND_ASSIGN(CryptAuthEnrollmentManagerImplTest);
};
-TEST_F(CryptAuthEnrollmentManagerTest, RegisterPrefs) {
+TEST_F(CryptAuthEnrollmentManagerImplTest, RegisterPrefs) {
TestingPrefServiceSimple pref_service;
CryptAuthEnrollmentManager::RegisterPrefs(pref_service.registry());
EXPECT_TRUE(pref_service.FindPreference(
@@ -269,7 +269,7 @@ TEST_F(CryptAuthEnrollmentManagerTest, RegisterPrefs) {
EXPECT_TRUE(pref_service.FindPreference(prefs::kCryptAuthEnrollmentReason));
}
-TEST_F(CryptAuthEnrollmentManagerTest, GetEnrollmentState) {
+TEST_F(CryptAuthEnrollmentManagerImplTest, GetEnrollmentState) {
enrollment_manager_.Start();
ON_CALL(*sync_scheduler(), GetStrategy())
@@ -294,7 +294,7 @@ TEST_F(CryptAuthEnrollmentManagerTest, GetEnrollmentState) {
EXPECT_FALSE(enrollment_manager_.IsEnrollmentInProgress());
}
-TEST_F(CryptAuthEnrollmentManagerTest, InitWithDefaultPrefs) {
+TEST_F(CryptAuthEnrollmentManagerImplTest, InitWithDefaultPrefs) {
base::SimpleTestClock clock;
clock.SetNow(base::Time::FromDoubleT(kInitialTimeNowSeconds));
base::TimeDelta elapsed_time = clock.Now() - base::Time::FromDoubleT(0);
@@ -303,8 +303,8 @@ TEST_F(CryptAuthEnrollmentManagerTest, InitWithDefaultPrefs) {
CryptAuthEnrollmentManager::RegisterPrefs(pref_service.registry());
TestCryptAuthEnrollmentManager enrollment_manager(
- &clock, base::MakeUnique<MockCryptAuthEnrollerFactory>(),
- base::MakeUnique<FakeSecureMessageDelegate>(), device_info_,
+ &clock, std::make_unique<MockCryptAuthEnrollerFactory>(),
+ std::make_unique<FakeSecureMessageDelegate>(), device_info_,
&gcm_manager_, &pref_service);
EXPECT_CALL(
@@ -316,7 +316,7 @@ TEST_F(CryptAuthEnrollmentManagerTest, InitWithDefaultPrefs) {
EXPECT_TRUE(enrollment_manager.GetLastEnrollmentTime().is_null());
}
-TEST_F(CryptAuthEnrollmentManagerTest, InitWithExistingPrefs) {
+TEST_F(CryptAuthEnrollmentManagerImplTest, InitWithExistingPrefs) {
EXPECT_CALL(
*sync_scheduler(),
Start(clock_.Now() - base::Time::FromDoubleT(kLastEnrollmentTimeSeconds),
@@ -328,10 +328,10 @@ TEST_F(CryptAuthEnrollmentManagerTest, InitWithExistingPrefs) {
enrollment_manager_.GetLastEnrollmentTime());
}
-TEST_F(CryptAuthEnrollmentManagerTest, InitWithExpiredEnrollment) {
+TEST_F(CryptAuthEnrollmentManagerImplTest, InitWithExpiredEnrollment) {
pref_service_.SetUserPref(
prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds,
- base::MakeUnique<base::Value>(kLastExpiredEnrollmentTimeSeconds));
+ std::make_unique<base::Value>(kLastExpiredEnrollmentTimeSeconds));
EXPECT_CALL(*sync_scheduler(),
Start(clock_.Now() - base::Time::FromDoubleT(
@@ -344,12 +344,11 @@ TEST_F(CryptAuthEnrollmentManagerTest, InitWithExpiredEnrollment) {
enrollment_manager_.GetLastEnrollmentTime());
}
-TEST_F(CryptAuthEnrollmentManagerTest, ForceEnrollment) {
+TEST_F(CryptAuthEnrollmentManagerImplTest, ForceEnrollment) {
enrollment_manager_.Start();
EXPECT_CALL(*sync_scheduler(), ForceSync());
- enrollment_manager_.ForceEnrollmentNow(
- INVOCATION_REASON_SERVER_INITIATED);
+ enrollment_manager_.ForceEnrollmentNow(INVOCATION_REASON_SERVER_INITIATED);
auto completion_callback =
FireSchedulerForEnrollment(INVOCATION_REASON_SERVER_INITIATED);
@@ -360,8 +359,7 @@ TEST_F(CryptAuthEnrollmentManagerTest, ForceEnrollment) {
EXPECT_EQ(clock_.Now(), enrollment_manager_.GetLastEnrollmentTime());
}
-TEST_F(CryptAuthEnrollmentManagerTest,
- EnrollmentFailsThenSucceeds) {
+TEST_F(CryptAuthEnrollmentManagerImplTest, EnrollmentFailsThenSucceeds) {
enrollment_manager_.Start();
base::Time old_enrollment_time = enrollment_manager_.GetLastEnrollmentTime();
@@ -390,8 +388,7 @@ TEST_F(CryptAuthEnrollmentManagerTest,
prefs::kCryptAuthEnrollmentIsRecoveringFromFailure));
}
-TEST_F(CryptAuthEnrollmentManagerTest,
- EnrollmentSucceedsForFirstTime) {
+TEST_F(CryptAuthEnrollmentManagerImplTest, EnrollmentSucceedsForFirstTime) {
// Initialize |enrollment_manager_|.
ON_CALL(*sync_scheduler(), GetStrategy())
.WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH));
@@ -404,16 +401,16 @@ TEST_F(CryptAuthEnrollmentManagerTest,
// Trigger a sync request.
EXPECT_CALL(*this, OnEnrollmentStartedProxy());
- auto sync_request = base::MakeUnique<SyncScheduler::SyncRequest>(
+ auto sync_request = std::make_unique<SyncScheduler::SyncRequest>(
enrollment_manager_.GetSyncScheduler());
static_cast<SyncScheduler::Delegate*>(&enrollment_manager_)
->OnSyncRequested(std::move(sync_request));
// Complete GCM registration successfully, and expect an enrollment.
CryptAuthEnroller::EnrollmentFinishedCallback enrollment_callback;
- EXPECT_CALL(*next_cryptauth_enroller(),
- Enroll(public_key_, private_key_, _,
- INVOCATION_REASON_INITIALIZATION, _))
+ EXPECT_CALL(
+ *next_cryptauth_enroller(),
+ Enroll(public_key_, private_key_, _, INVOCATION_REASON_INITIALIZATION, _))
.WillOnce(SaveArg<4>(&enrollment_callback));
ASSERT_TRUE(gcm_manager_.registration_in_progress());
gcm_manager_.CompleteRegistration(kGCMRegistrationId);
@@ -431,7 +428,7 @@ TEST_F(CryptAuthEnrollmentManagerTest,
EXPECT_EQ(private_key_, enrollment_manager_.GetUserPrivateKey());
}
-TEST_F(CryptAuthEnrollmentManagerTest, GCMRegistrationFails) {
+TEST_F(CryptAuthEnrollmentManagerImplTest, GCMRegistrationFails) {
// Initialize |enrollment_manager_|.
ON_CALL(*sync_scheduler(), GetStrategy())
.WillByDefault(Return(SyncScheduler::Strategy::PERIODIC_REFRESH));
@@ -440,7 +437,7 @@ TEST_F(CryptAuthEnrollmentManagerTest, GCMRegistrationFails) {
// Trigger a sync request.
EXPECT_CALL(*this, OnEnrollmentStartedProxy());
- auto sync_request = base::MakeUnique<SyncScheduler::SyncRequest>(
+ auto sync_request = std::make_unique<SyncScheduler::SyncRequest>(
enrollment_manager_.GetSyncScheduler());
static_cast<SyncScheduler::Delegate*>(&enrollment_manager_)
->OnSyncRequested(std::move(sync_request));
@@ -450,7 +447,7 @@ TEST_F(CryptAuthEnrollmentManagerTest, GCMRegistrationFails) {
gcm_manager_.CompleteRegistration(std::string());
}
-TEST_F(CryptAuthEnrollmentManagerTest, ReenrollOnGCMPushMessage) {
+TEST_F(CryptAuthEnrollmentManagerImplTest, ReenrollOnGCMPushMessage) {
enrollment_manager_.Start();
// Simulate receiving a GCM push message, forcing the device to re-enroll.
diff --git a/chromium/components/cryptauth/device_capability_manager_impl.cc b/chromium/components/cryptauth/device_capability_manager_impl.cc
index e49121a5f62..59b67737090 100644
--- a/chromium/components/cryptauth/device_capability_manager_impl.cc
+++ b/chromium/components/cryptauth/device_capability_manager_impl.cc
@@ -4,6 +4,8 @@
#include "components/cryptauth/device_capability_manager_impl.h"
+#include <memory>
+
#include "base/logging.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
@@ -48,7 +50,7 @@ void DeviceCapabilityManagerImpl::SetCapabilityEnabled(
bool enabled,
const base::Closure& success_callback,
const base::Callback<void(const std::string&)>& error_callback) {
- pending_requests_.emplace(base::MakeUnique<Request>(
+ pending_requests_.emplace(std::make_unique<Request>(
RequestType::SET_CAPABILITY_ENABLED, Capability::CAPABILITY_UNLOCK_KEY,
public_key, enabled, success_callback, error_callback));
ProcessRequestQueue();
@@ -60,7 +62,7 @@ void DeviceCapabilityManagerImpl::FindEligibleDevicesForCapability(
const std::vector<IneligibleDevice>&)>&
success_callback,
const base::Callback<void(const std::string&)>& error_callback) {
- pending_requests_.emplace(base::MakeUnique<Request>(
+ pending_requests_.emplace(std::make_unique<Request>(
RequestType::FIND_ELIGIBLE_DEVICES_FOR_CAPABILITY,
Capability::CAPABILITY_UNLOCK_KEY, success_callback, error_callback));
ProcessRequestQueue();
@@ -71,7 +73,7 @@ void DeviceCapabilityManagerImpl::IsCapabilityPromotable(
Capability capability,
const base::Callback<void(bool)>& success_callback,
const base::Callback<void(const std::string&)>& error_callback) {
- pending_requests_.emplace(base::MakeUnique<Request>(
+ pending_requests_.emplace(std::make_unique<Request>(
RequestType::IS_CAPABILITY_PROMOTABLE, capability, public_key,
success_callback, error_callback));
ProcessRequestQueue();
@@ -239,4 +241,4 @@ void DeviceCapabilityManagerImpl::ProcessRequestQueue() {
}
}
-} // namespace cryptauth \ No newline at end of file
+} // namespace cryptauth
diff --git a/chromium/components/cryptauth/device_capability_manager_impl_unittest.cc b/chromium/components/cryptauth/device_capability_manager_impl_unittest.cc
index f080bf9db4b..5868c6de7b5 100644
--- a/chromium/components/cryptauth/device_capability_manager_impl_unittest.cc
+++ b/chromium/components/cryptauth/device_capability_manager_impl_unittest.cc
@@ -15,7 +15,6 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "components/cryptauth/mock_cryptauth_client.h"
#include "components/cryptauth/remote_device.h"
#include "components/cryptauth/remote_device_test_util.h"
@@ -69,10 +68,10 @@ class DeviceCapabilityManagerImplTest
void SetUp() override {
mock_cryptauth_client_factory_ =
- base::MakeUnique<MockCryptAuthClientFactory>(
+ std::make_unique<MockCryptAuthClientFactory>(
MockCryptAuthClientFactory::MockType::MAKE_NICE_MOCKS);
mock_cryptauth_client_factory_->AddObserver(this);
- device_capability_manager_ = base::MakeUnique<DeviceCapabilityManagerImpl>(
+ device_capability_manager_ = std::make_unique<DeviceCapabilityManagerImpl>(
mock_cryptauth_client_factory_.get());
}
@@ -422,4 +421,4 @@ TEST_F(DeviceCapabilityManagerImplTest, TestOrderViaMultipleErrors) {
EXPECT_EQ(kErrorFindEligibleForPromotion, GetResultAndReset());
}
-} // namespace cryptauth \ No newline at end of file
+} // namespace cryptauth
diff --git a/chromium/components/cryptauth/device_to_device_authenticator.cc b/chromium/components/cryptauth/device_to_device_authenticator.cc
index a8a648b390d..5adab3eebbd 100644
--- a/chromium/components/cryptauth/device_to_device_authenticator.cc
+++ b/chromium/components/cryptauth/device_to_device_authenticator.cc
@@ -4,6 +4,7 @@
#include "components/cryptauth/device_to_device_authenticator.h"
+#include <memory>
#include <utility>
#include "base/memory/ptr_util.h"
@@ -68,7 +69,7 @@ DeviceToDeviceAuthenticator::DeviceToDeviceAuthenticator(
: connection_(connection),
account_id_(account_id),
secure_message_delegate_(std::move(secure_message_delegate)),
- helper_(base::MakeUnique<DeviceToDeviceInitiatorHelper>()),
+ helper_(std::make_unique<DeviceToDeviceInitiatorHelper>()),
state_(State::NOT_STARTED),
weak_ptr_factory_(this) {
DCHECK(connection_);
@@ -122,7 +123,7 @@ void DeviceToDeviceAuthenticator::OnKeyPairGenerated(
}
std::unique_ptr<base::Timer> DeviceToDeviceAuthenticator::CreateTimer() {
- return base::MakeUnique<base::OneShotTimer>();
+ return std::make_unique<base::OneShotTimer>();
}
void DeviceToDeviceAuthenticator::OnHelloMessageCreated(
@@ -145,7 +146,7 @@ void DeviceToDeviceAuthenticator::OnHelloMessageCreated(
// Send the [Initiator Hello] message to the remote device.
state_ = State::SENT_HELLO;
hello_message_ = message;
- connection_->SendMessage(base::MakeUnique<WireMessage>(
+ connection_->SendMessage(std::make_unique<WireMessage>(
hello_message_, std::string(Authenticator::kAuthenticationFeature)));
}
@@ -184,7 +185,7 @@ void DeviceToDeviceAuthenticator::OnInitiatorAuthCreated(
}
state_ = State::SENT_INITIATOR_AUTH;
- connection_->SendMessage(base::MakeUnique<WireMessage>(
+ connection_->SendMessage(std::make_unique<WireMessage>(
message, std::string(Authenticator::kAuthenticationFeature)));
}
@@ -213,7 +214,7 @@ void DeviceToDeviceAuthenticator::Succeed() {
connection_->RemoveObserver(this);
callback_.Run(
Result::SUCCESS,
- base::MakeUnique<DeviceToDeviceSecureContext>(
+ std::make_unique<DeviceToDeviceSecureContext>(
std::move(secure_message_delegate_), session_keys_,
responder_auth_message_, SecureContext::PROTOCOL_VERSION_THREE_ONE));
}
diff --git a/chromium/components/cryptauth/device_to_device_authenticator_unittest.cc b/chromium/components/cryptauth/device_to_device_authenticator_unittest.cc
index 851df649c62..eecec3a0226 100644
--- a/chromium/components/cryptauth/device_to_device_authenticator_unittest.cc
+++ b/chromium/components/cryptauth/device_to_device_authenticator_unittest.cc
@@ -4,6 +4,7 @@
#include "components/cryptauth/device_to_device_authenticator.h"
+#include <memory>
#include <utility>
#include <vector>
@@ -350,10 +351,10 @@ TEST_F(CryptAuthDeviceToDeviceAuthenticatorTest,
// completes.
WireMessage wire_message(base::RandBytesAsString(300u),
Authenticator::kAuthenticationFeature);
- connection_.SendMessage(base::MakeUnique<WireMessage>(
+ connection_.SendMessage(std::make_unique<WireMessage>(
base::RandBytesAsString(300u), Authenticator::kAuthenticationFeature));
connection_.OnBytesReceived(wire_message.Serialize());
- connection_.SendMessage(base::MakeUnique<WireMessage>(
+ connection_.SendMessage(std::make_unique<WireMessage>(
base::RandBytesAsString(300u), Authenticator::kAuthenticationFeature));
connection_.OnBytesReceived(wire_message.Serialize());
}
diff --git a/chromium/components/cryptauth/device_to_device_operations_unittest.cc b/chromium/components/cryptauth/device_to_device_operations_unittest.cc
index 31bba05a155..bc96d5eddb3 100644
--- a/chromium/components/cryptauth/device_to_device_operations_unittest.cc
+++ b/chromium/components/cryptauth/device_to_device_operations_unittest.cc
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
+
#include "base/base64url.h"
#include "base/bind.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "components/cryptauth/device_to_device_initiator_helper.h"
#include "components/cryptauth/device_to_device_responder_operations.h"
#include "components/cryptauth/fake_secure_message_delegate.h"
@@ -94,7 +95,7 @@ class CryptAuthDeviceToDeviceOperationsTest : public testing::Test {
persistent_symmetric_key_ = "persistent symmetric key";
- helper_ = base::MakeUnique<DeviceToDeviceInitiatorHelper>();
+ helper_ = std::make_unique<DeviceToDeviceInitiatorHelper>();
}
// Creates the initator's [Hello] message.
diff --git a/chromium/components/cryptauth/device_to_device_secure_context_unittest.cc b/chromium/components/cryptauth/device_to_device_secure_context_unittest.cc
index f26749264a8..388cea652d4 100644
--- a/chromium/components/cryptauth/device_to_device_secure_context_unittest.cc
+++ b/chromium/components/cryptauth/device_to_device_secure_context_unittest.cc
@@ -7,7 +7,7 @@
#include <memory>
#include "base/bind.h"
-#include "base/memory/ptr_util.h"
+#include "base/callback.h"
#include "components/cryptauth/fake_secure_message_delegate.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
#include "components/cryptauth/proto/securemessage.pb.h"
@@ -52,7 +52,7 @@ class InvertedSessionKeys : public SessionKeys {
class ProximityAuthDeviceToDeviceSecureContextTest : public testing::Test {
protected:
ProximityAuthDeviceToDeviceSecureContextTest()
- : secure_context_(base::MakeUnique<FakeSecureMessageDelegate>(),
+ : secure_context_(std::make_unique<FakeSecureMessageDelegate>(),
SessionKeys(kSymmetricKey),
kResponderAuthMessage,
kProtocolVersion) {}
@@ -95,7 +95,7 @@ TEST_F(ProximityAuthDeviceToDeviceSecureContextTest, EncodeAndDecode) {
// Initialize second secure channel with the same parameters as the first.
InvertedSessionKeys inverted_session_keys(kSymmetricKey);
DeviceToDeviceSecureContext secure_context2(
- base::MakeUnique<FakeSecureMessageDelegate>(), inverted_session_keys,
+ std::make_unique<FakeSecureMessageDelegate>(), inverted_session_keys,
kResponderAuthMessage, kProtocolVersion);
std::string message = "encrypt this message";
@@ -122,7 +122,7 @@ TEST_F(ProximityAuthDeviceToDeviceSecureContextTest,
DecodeInvalidSequenceNumber) {
// Initialize second secure channel with the same parameters as the first.
DeviceToDeviceSecureContext secure_context2(
- base::MakeUnique<FakeSecureMessageDelegate>(),
+ std::make_unique<FakeSecureMessageDelegate>(),
InvertedSessionKeys(kSymmetricKey), kResponderAuthMessage,
kProtocolVersion);
diff --git a/chromium/components/cryptauth/fake_connection.cc b/chromium/components/cryptauth/fake_connection.cc
index 76f5718c2f3..e126787861f 100644
--- a/chromium/components/cryptauth/fake_connection.cc
+++ b/chromium/components/cryptauth/fake_connection.cc
@@ -4,9 +4,9 @@
#include "components/cryptauth/fake_connection.h"
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "components/cryptauth/wire_message.h"
namespace cryptauth {
@@ -90,7 +90,7 @@ void FakeConnection::SendMessageImpl(std::unique_ptr<WireMessage> message) {
std::unique_ptr<WireMessage> FakeConnection::DeserializeWireMessage(
bool* is_incomplete_message) {
*is_incomplete_message = false;
- return base::MakeUnique<WireMessage>(pending_payload_, pending_feature_);
+ return std::make_unique<WireMessage>(pending_payload_, pending_feature_);
}
} // namespace cryptauth
diff --git a/chromium/components/cryptauth/fake_cryptauth_device_manager.cc b/chromium/components/cryptauth/fake_cryptauth_device_manager.cc
new file mode 100644
index 00000000000..0e7b815eb2c
--- /dev/null
+++ b/chromium/components/cryptauth/fake_cryptauth_device_manager.cc
@@ -0,0 +1,83 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cryptauth/fake_cryptauth_device_manager.h"
+
+#include <memory>
+
+namespace cryptauth {
+
+FakeCryptAuthDeviceManager::FakeCryptAuthDeviceManager() = default;
+
+FakeCryptAuthDeviceManager::~FakeCryptAuthDeviceManager() = default;
+
+void FakeCryptAuthDeviceManager::FinishActiveSync(
+ SyncResult sync_result,
+ DeviceChangeResult device_change_result,
+ const base::Time& sync_finish_time) {
+ DCHECK(is_sync_in_progress_);
+ is_sync_in_progress_ = false;
+
+ if (sync_result == CryptAuthDeviceManager::SyncResult::SUCCESS) {
+ last_sync_time_ = sync_finish_time;
+ is_recovering_from_failure_ = false;
+ } else {
+ is_recovering_from_failure_ = true;
+ }
+
+ NotifySyncFinished(sync_result, device_change_result);
+}
+
+void FakeCryptAuthDeviceManager::Start() {
+ has_started_ = true;
+}
+
+void FakeCryptAuthDeviceManager::ForceSyncNow(
+ InvocationReason invocation_reason) {
+ is_sync_in_progress_ = true;
+ NotifySyncStarted();
+}
+
+base::Time FakeCryptAuthDeviceManager::GetLastSyncTime() const {
+ return last_sync_time_;
+}
+
+base::TimeDelta FakeCryptAuthDeviceManager::GetTimeToNextAttempt() const {
+ return time_to_next_attempt_;
+}
+
+bool FakeCryptAuthDeviceManager::IsSyncInProgress() const {
+ return is_sync_in_progress_;
+}
+
+bool FakeCryptAuthDeviceManager::IsRecoveringFromFailure() const {
+ return is_recovering_from_failure_;
+}
+
+std::vector<ExternalDeviceInfo> FakeCryptAuthDeviceManager::GetSyncedDevices()
+ const {
+ return synced_devices_;
+}
+
+std::vector<ExternalDeviceInfo> FakeCryptAuthDeviceManager::GetUnlockKeys()
+ const {
+ return unlock_keys_;
+}
+
+std::vector<ExternalDeviceInfo> FakeCryptAuthDeviceManager::GetPixelUnlockKeys()
+ const {
+ return pixel_unlock_keys_;
+}
+
+std::vector<ExternalDeviceInfo> FakeCryptAuthDeviceManager::GetTetherHosts()
+ const {
+ return tether_hosts_;
+}
+
+std::vector<ExternalDeviceInfo>
+FakeCryptAuthDeviceManager::GetPixelTetherHosts() const {
+ return pixel_tether_hosts_;
+}
+
+} // namespace cryptauth
diff --git a/chromium/components/cryptauth/fake_cryptauth_device_manager.h b/chromium/components/cryptauth/fake_cryptauth_device_manager.h
new file mode 100644
index 00000000000..582883b931c
--- /dev/null
+++ b/chromium/components/cryptauth/fake_cryptauth_device_manager.h
@@ -0,0 +1,106 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CRYPTAUTH_FAKE_CRYPTAUTH_DEVICE_MANAGER_H_
+#define COMPONENTS_CRYPTAUTH_FAKE_CRYPTAUTH_DEVICE_MANAGER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "components/cryptauth/cryptauth_device_manager.h"
+#include "components/cryptauth/proto/cryptauth_api.pb.h"
+
+namespace cryptauth {
+
+// Test double for CryptAuthDeviceManager.
+class FakeCryptAuthDeviceManager : public CryptAuthDeviceManager {
+ public:
+ FakeCryptAuthDeviceManager();
+ ~FakeCryptAuthDeviceManager() override;
+
+ bool has_started() { return has_started_; }
+
+ void set_time_to_next_attempt(base::TimeDelta time_to_next_attempt) {
+ time_to_next_attempt_ = time_to_next_attempt;
+ }
+
+ std::vector<ExternalDeviceInfo>& synced_devices() { return synced_devices_; }
+
+ void set_synced_devices(std::vector<ExternalDeviceInfo> synced_devices) {
+ synced_devices_ = synced_devices;
+ }
+
+ std::vector<ExternalDeviceInfo>& unlock_keys() { return unlock_keys_; }
+
+ void set_unlock_keys(std::vector<ExternalDeviceInfo> unlock_keys) {
+ unlock_keys_ = unlock_keys;
+ }
+
+ std::vector<ExternalDeviceInfo>& pixel_unlock_keys() {
+ return pixel_unlock_keys_;
+ }
+
+ void set_pixel_unlock_keys(
+ std::vector<ExternalDeviceInfo> pixel_unlock_keys) {
+ pixel_unlock_keys_ = pixel_unlock_keys;
+ }
+
+ std::vector<ExternalDeviceInfo>& tether_hosts() { return tether_hosts_; }
+
+ void set_tether_hosts(std::vector<ExternalDeviceInfo> tether_hosts) {
+ tether_hosts_ = tether_hosts;
+ }
+
+ std::vector<ExternalDeviceInfo>& pixel_tether_hosts() {
+ return pixel_tether_hosts_;
+ }
+
+ void set_pixel_tether_hosts(
+ std::vector<ExternalDeviceInfo> pixel_tether_hosts) {
+ pixel_tether_hosts_ = pixel_tether_hosts;
+ }
+
+ // Finishes the active sync; should only be called if a sync is in progress
+ // due to a previous call to ForceSyncNow(). If |sync_result| is SUCCESS,
+ // |sync_finish_time| will be stored as the last sync time and will be
+ // returned by future calls to GetLastSyncTime().
+ void FinishActiveSync(SyncResult sync_result,
+ DeviceChangeResult device_change_result,
+ const base::Time& sync_finish_time = base::Time());
+
+ // Make these functions public for testing.
+ using CryptAuthDeviceManager::NotifySyncStarted;
+ using CryptAuthDeviceManager::NotifySyncFinished;
+
+ // CryptAuthDeviceManager:
+ void Start() override;
+ void ForceSyncNow(InvocationReason invocation_reason) override;
+ base::Time GetLastSyncTime() const override;
+ base::TimeDelta GetTimeToNextAttempt() const override;
+ bool IsSyncInProgress() const override;
+ bool IsRecoveringFromFailure() const override;
+ std::vector<ExternalDeviceInfo> GetSyncedDevices() const override;
+ std::vector<ExternalDeviceInfo> GetUnlockKeys() const override;
+ std::vector<ExternalDeviceInfo> GetPixelUnlockKeys() const override;
+ std::vector<ExternalDeviceInfo> GetTetherHosts() const override;
+ std::vector<ExternalDeviceInfo> GetPixelTetherHosts() const override;
+
+ private:
+ bool has_started_ = false;
+ bool is_sync_in_progress_ = false;
+ bool is_recovering_from_failure_ = false;
+ base::Time last_sync_time_;
+ base::TimeDelta time_to_next_attempt_;
+ std::vector<ExternalDeviceInfo> synced_devices_;
+ std::vector<ExternalDeviceInfo> unlock_keys_;
+ std::vector<ExternalDeviceInfo> pixel_unlock_keys_;
+ std::vector<ExternalDeviceInfo> tether_hosts_;
+ std::vector<ExternalDeviceInfo> pixel_tether_hosts_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeCryptAuthDeviceManager);
+};
+
+} // namespace cryptauth
+
+#endif // COMPONENTS_CRYPTAUTH_FAKE_CRYPTAUTH_DEVICE_MANAGER_H_
diff --git a/chromium/components/cryptauth/fake_cryptauth_enrollment_manager.cc b/chromium/components/cryptauth/fake_cryptauth_enrollment_manager.cc
new file mode 100644
index 00000000000..538478c74c4
--- /dev/null
+++ b/chromium/components/cryptauth/fake_cryptauth_enrollment_manager.cc
@@ -0,0 +1,68 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cryptauth/fake_cryptauth_enrollment_manager.h"
+
+namespace cryptauth {
+
+FakeCryptAuthEnrollmentManager::FakeCryptAuthEnrollmentManager() = default;
+
+FakeCryptAuthEnrollmentManager::~FakeCryptAuthEnrollmentManager() = default;
+
+void FakeCryptAuthEnrollmentManager::Start() {
+ has_started_ = true;
+}
+
+void FakeCryptAuthEnrollmentManager::FinishActiveEnrollment(
+ bool success,
+ const base::Time& enrollment_finish_time) {
+ DCHECK(is_enrollment_in_progress_);
+ is_enrollment_in_progress_ = false;
+
+ if (success) {
+ last_enrollment_time_ = enrollment_finish_time;
+ is_recovering_from_failure_ = false;
+ } else {
+ is_recovering_from_failure_ = true;
+ }
+
+ NotifyEnrollmentFinished(success);
+}
+
+void FakeCryptAuthEnrollmentManager::ForceEnrollmentNow(
+ InvocationReason invocation_reason) {
+ is_enrollment_in_progress_ = true;
+ last_invocation_reason_ = invocation_reason;
+ NotifyEnrollmentStarted();
+}
+
+bool FakeCryptAuthEnrollmentManager::IsEnrollmentValid() const {
+ return is_enrollment_valid_;
+}
+
+base::Time FakeCryptAuthEnrollmentManager::GetLastEnrollmentTime() const {
+ return last_enrollment_time_;
+}
+
+base::TimeDelta FakeCryptAuthEnrollmentManager::GetTimeToNextAttempt() const {
+ return time_to_next_attempt_;
+}
+
+bool FakeCryptAuthEnrollmentManager::IsEnrollmentInProgress() const {
+ return is_enrollment_in_progress_;
+}
+
+bool FakeCryptAuthEnrollmentManager::IsRecoveringFromFailure() const {
+ return is_recovering_from_failure_;
+}
+
+std::string FakeCryptAuthEnrollmentManager::GetUserPublicKey() const {
+ return user_public_key_;
+}
+
+std::string FakeCryptAuthEnrollmentManager::GetUserPrivateKey() const {
+ return user_private_key_;
+}
+
+} // namespace cryptauth
diff --git a/chromium/components/cryptauth/fake_cryptauth_enrollment_manager.h b/chromium/components/cryptauth/fake_cryptauth_enrollment_manager.h
new file mode 100644
index 00000000000..1ffc0482b1f
--- /dev/null
+++ b/chromium/components/cryptauth/fake_cryptauth_enrollment_manager.h
@@ -0,0 +1,85 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CRYPTAUTH_FAKE_CRYPTAUTH_ENROLLMENT_MANAGER_H_
+#define COMPONENTS_CRYPTAUTH_FAKE_CRYPTAUTH_ENROLLMENT_MANAGER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "components/cryptauth/cryptauth_enrollment_manager.h"
+#include "components/cryptauth/proto/cryptauth_api.pb.h"
+
+namespace cryptauth {
+
+// Test double for CryptAuthEnrollmentManager.
+class FakeCryptAuthEnrollmentManager : public CryptAuthEnrollmentManager {
+ public:
+ FakeCryptAuthEnrollmentManager();
+ ~FakeCryptAuthEnrollmentManager() override;
+
+ void set_time_to_next_attempt(const base::TimeDelta& time_to_next_attempt) {
+ time_to_next_attempt_ = time_to_next_attempt;
+ }
+
+ void set_is_enrollment_valid(bool is_enrollment_valid) {
+ is_enrollment_valid_ = is_enrollment_valid;
+ }
+
+ void set_user_public_key(const std::string& user_public_key) {
+ user_public_key_ = user_public_key;
+ }
+
+ void set_user_private_key(const std::string& user_private_key) {
+ user_private_key_ = user_private_key;
+ }
+
+ bool has_started() { return has_started_; }
+
+ base::Optional<InvocationReason> last_invocation_reason() {
+ return last_invocation_reason_;
+ }
+
+ // Finishes the active enrollment; should only be called if enrollment is in
+ // progress due to a previous call to ForceEnrollmentNow(). If |success| is
+ // true, |enrollment_finish_time| will be stored as the last enrollment time
+ // and will be returned by future calls to GetLastEnrollmentTime().
+ void FinishActiveEnrollment(
+ bool success,
+ const base::Time& enrollment_finish_time = base::Time());
+
+ // Make these functions public for testing.
+ using CryptAuthEnrollmentManager::NotifyEnrollmentStarted;
+ using CryptAuthEnrollmentManager::NotifyEnrollmentFinished;
+
+ // CryptAuthEnrollmentManager:
+ void Start() override;
+ void ForceEnrollmentNow(InvocationReason invocation_reason) override;
+ bool IsEnrollmentValid() const override;
+ base::Time GetLastEnrollmentTime() const override;
+ base::TimeDelta GetTimeToNextAttempt() const override;
+ bool IsEnrollmentInProgress() const override;
+ bool IsRecoveringFromFailure() const override;
+ std::string GetUserPublicKey() const override;
+ std::string GetUserPrivateKey() const override;
+
+ private:
+ bool has_started_ = false;
+ bool is_enrollment_in_progress_ = false;
+ bool is_recovering_from_failure_ = false;
+ bool is_enrollment_valid_ = false;
+ base::Optional<InvocationReason> last_invocation_reason_;
+ base::Time last_enrollment_time_;
+ base::TimeDelta time_to_next_attempt_;
+ std::string user_public_key_;
+ std::string user_private_key_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeCryptAuthEnrollmentManager);
+};
+
+} // namespace cryptauth
+
+#endif // COMPONENTS_CRYPTAUTH_FAKE_CRYPTAUTH_ENROLLMENT_MANAGER_H_
diff --git a/chromium/components/cryptauth/fake_cryptauth_service.cc b/chromium/components/cryptauth/fake_cryptauth_service.cc
index 93b9113cc42..4fa3e34e7b7 100644
--- a/chromium/components/cryptauth/fake_cryptauth_service.cc
+++ b/chromium/components/cryptauth/fake_cryptauth_service.cc
@@ -4,8 +4,9 @@
#include "components/cryptauth/fake_cryptauth_service.h"
+#include <memory>
+
#include "base/callback.h"
-#include "base/memory/ptr_util.h"
#include "components/cryptauth/fake_secure_message_delegate.h"
#include "components/cryptauth/mock_cryptauth_client.h"
@@ -34,12 +35,12 @@ std::string FakeCryptAuthService::GetAccountId() {
std::unique_ptr<SecureMessageDelegate>
FakeCryptAuthService::CreateSecureMessageDelegate() {
- return base::MakeUnique<FakeSecureMessageDelegate>();
+ return std::make_unique<FakeSecureMessageDelegate>();
}
std::unique_ptr<CryptAuthClientFactory>
FakeCryptAuthService::CreateCryptAuthClientFactory() {
- return base::MakeUnique<MockCryptAuthClientFactory>(
+ return std::make_unique<MockCryptAuthClientFactory>(
MockCryptAuthClientFactory::MockType::MAKE_NICE_MOCKS);
}
diff --git a/chromium/components/cryptauth/fake_secure_channel.cc b/chromium/components/cryptauth/fake_secure_channel.cc
index fd21916b913..9fbe29c831d 100644
--- a/chromium/components/cryptauth/fake_secure_channel.cc
+++ b/chromium/components/cryptauth/fake_secure_channel.cc
@@ -63,7 +63,13 @@ int FakeSecureChannel::SendMessage(const std::string& feature,
}
void FakeSecureChannel::Disconnect() {
- ChangeStatus(Status::DISCONNECTED);
+ if (status() == Status::DISCONNECTING || status() == Status::DISCONNECTED)
+ return;
+
+ if (status() == Status::CONNECTING)
+ ChangeStatus(Status::DISCONNECTED);
+ else
+ ChangeStatus(Status::DISCONNECTING);
}
void FakeSecureChannel::AddObserver(Observer* observer) {
diff --git a/chromium/components/cryptauth/fake_secure_message_delegate_unittest.cc b/chromium/components/cryptauth/fake_secure_message_delegate_unittest.cc
index 712a5714118..4b8c31e66fd 100644
--- a/chromium/components/cryptauth/fake_secure_message_delegate_unittest.cc
+++ b/chromium/components/cryptauth/fake_secure_message_delegate_unittest.cc
@@ -5,6 +5,7 @@
#include "components/cryptauth/fake_secure_message_delegate.h"
#include "base/bind.h"
+#include "base/callback.h"
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/cryptauth/foreground_eid_generator.cc b/chromium/components/cryptauth/foreground_eid_generator.cc
index d50464c29b6..5f866128c7b 100644
--- a/chromium/components/cryptauth/foreground_eid_generator.cc
+++ b/chromium/components/cryptauth/foreground_eid_generator.cc
@@ -5,6 +5,7 @@
#include "components/cryptauth/foreground_eid_generator.h"
#include <cstring>
+#include <memory>
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
@@ -58,7 +59,7 @@ std::string ForegroundEidGenerator::EidData::DataInHex() const {
}
ForegroundEidGenerator::ForegroundEidGenerator()
- : ForegroundEidGenerator(base::MakeUnique<RawEidGeneratorImpl>(),
+ : ForegroundEidGenerator(std::make_unique<RawEidGeneratorImpl>(),
base::DefaultClock::GetInstance()) {}
ForegroundEidGenerator::ForegroundEidGenerator(
diff --git a/chromium/components/cryptauth/foreground_eid_generator_unittest.cc b/chromium/components/cryptauth/foreground_eid_generator_unittest.cc
index 814cc4c7d20..37f460e9fff 100644
--- a/chromium/components/cryptauth/foreground_eid_generator_unittest.cc
+++ b/chromium/components/cryptauth/foreground_eid_generator_unittest.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
@@ -133,7 +132,7 @@ class CryptAuthForegroundEidGeneratorTest : public testing::Test {
SetTestTime(kDefaultCurrentTime);
eid_generator_.reset(new ForegroundEidGenerator(
- base::MakeUnique<TestRawEidGenerator>(), &test_clock_));
+ std::make_unique<TestRawEidGenerator>(), &test_clock_));
}
// TODO(khorimoto): Is there an easier way to do this?
@@ -335,7 +334,7 @@ TEST_F(CryptAuthForegroundEidGeneratorTest,
// Use real RawEidGenerator implementation instead of test version.
eid_generator_.reset(new ForegroundEidGenerator(
- base::MakeUnique<RawEidGeneratorImpl>(), &test_clock_));
+ std::make_unique<RawEidGeneratorImpl>(), &test_clock_));
std::unique_ptr<ForegroundEidGenerator::EidData> data =
eid_generator_->GenerateBackgroundScanFilter(
diff --git a/chromium/components/cryptauth/local_device_data_provider_unittest.cc b/chromium/components/cryptauth/local_device_data_provider_unittest.cc
index 9259c5d0c54..97d291e4d41 100644
--- a/chromium/components/cryptauth/local_device_data_provider_unittest.cc
+++ b/chromium/components/cryptauth/local_device_data_provider_unittest.cc
@@ -4,14 +4,14 @@
#include "components/cryptauth/local_device_data_provider.h"
+#include <memory>
#include <string>
#include <vector>
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "components/cryptauth/cryptauth_device_manager.h"
#include "components/cryptauth/cryptauth_enroller.h"
-#include "components/cryptauth/cryptauth_enrollment_manager.h"
+#include "components/cryptauth/fake_cryptauth_device_manager.h"
+#include "components/cryptauth/fake_cryptauth_enrollment_manager.h"
#include "components/cryptauth/fake_cryptauth_gcm_manager.h"
#include "components/cryptauth/fake_cryptauth_service.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
@@ -36,29 +36,6 @@ const char kBeaconSeed2Data[] = "beaconSeed2Data";
const int64_t kBeaconSeed2StartMs = 2000L;
const int64_t kBeaconSeed2EndMs = 3000L;
-class MockCryptAuthDeviceManager : public CryptAuthDeviceManager {
- public:
- MockCryptAuthDeviceManager() {}
- ~MockCryptAuthDeviceManager() override {}
-
- MOCK_CONST_METHOD0(GetSyncedDevices, std::vector<ExternalDeviceInfo>());
-};
-
-class MockCryptAuthEnrollmentManager : public CryptAuthEnrollmentManager {
- public:
- explicit MockCryptAuthEnrollmentManager(
- FakeCryptAuthGCMManager* fake_cryptauth_gcm_manager)
- : CryptAuthEnrollmentManager(nullptr /* clock */,
- nullptr /* enroller_factory */,
- nullptr /* secure_message_delegate */,
- GcmDeviceInfo(),
- fake_cryptauth_gcm_manager,
- nullptr /* pref_service */) {}
- ~MockCryptAuthEnrollmentManager() override {}
-
- MOCK_CONST_METHOD0(GetUserPublicKey, std::string());
-};
-
BeaconSeed CreateBeaconSeed(const std::string& data,
int64_t start_ms,
int64_t end_ms) {
@@ -71,9 +48,9 @@ BeaconSeed CreateBeaconSeed(const std::string& data,
} // namespace
-class LocalDeviceDataProviderTest : public testing::Test {
+class CryptAuthLocalDeviceDataProviderTest : public testing::Test {
protected:
- LocalDeviceDataProviderTest() {
+ CryptAuthLocalDeviceDataProviderTest() {
fake_beacon_seeds_.push_back(CreateBeaconSeed(
kBeaconSeed1Data, kBeaconSeed1StartMs, kBeaconSeed1EndMs));
fake_beacon_seeds_.push_back(CreateBeaconSeed(
@@ -121,19 +98,15 @@ class LocalDeviceDataProviderTest : public testing::Test {
}
void SetUp() override {
- mock_device_manager_ =
- base::WrapUnique(new NiceMock<MockCryptAuthDeviceManager>());
- fake_cryptauth_gcm_manager_ =
- base::MakeUnique<FakeCryptAuthGCMManager>("registrationId");
- mock_enrollment_manager_ =
- base::WrapUnique(new NiceMock<MockCryptAuthEnrollmentManager>(
- fake_cryptauth_gcm_manager_.get()));
-
- fake_cryptauth_service_ = base::MakeUnique<FakeCryptAuthService>();
+ fake_device_manager_ = std::make_unique<FakeCryptAuthDeviceManager>();
+ fake_enrollment_manager_ =
+ std::make_unique<FakeCryptAuthEnrollmentManager>();
+
+ fake_cryptauth_service_ = std::make_unique<FakeCryptAuthService>();
fake_cryptauth_service_->set_cryptauth_device_manager(
- mock_device_manager_.get());
+ fake_device_manager_.get());
fake_cryptauth_service_->set_cryptauth_enrollment_manager(
- mock_enrollment_manager_.get());
+ fake_enrollment_manager_.get());
provider_ = base::WrapUnique(
new LocalDeviceDataProvider(fake_cryptauth_service_.get()));
@@ -142,23 +115,20 @@ class LocalDeviceDataProviderTest : public testing::Test {
std::vector<BeaconSeed> fake_beacon_seeds_;
std::vector<ExternalDeviceInfo> fake_synced_devices_;
- std::unique_ptr<FakeCryptAuthGCMManager> fake_cryptauth_gcm_manager_;
- std::unique_ptr<NiceMock<MockCryptAuthDeviceManager>> mock_device_manager_;
- std::unique_ptr<NiceMock<MockCryptAuthEnrollmentManager>>
- mock_enrollment_manager_;
+ std::unique_ptr<FakeCryptAuthDeviceManager> fake_device_manager_;
+ std::unique_ptr<FakeCryptAuthEnrollmentManager> fake_enrollment_manager_;
std::unique_ptr<FakeCryptAuthService> fake_cryptauth_service_;
std::unique_ptr<LocalDeviceDataProvider> provider_;
private:
- DISALLOW_COPY_AND_ASSIGN(LocalDeviceDataProviderTest);
+ DISALLOW_COPY_AND_ASSIGN(CryptAuthLocalDeviceDataProviderTest);
};
-TEST_F(LocalDeviceDataProviderTest, TestGetLocalDeviceData_NoPublicKey) {
- ON_CALL(*mock_enrollment_manager_, GetUserPublicKey())
- .WillByDefault(Return(std::string()));
- ON_CALL(*mock_device_manager_, GetSyncedDevices())
- .WillByDefault(Return(fake_synced_devices_));
+TEST_F(CryptAuthLocalDeviceDataProviderTest,
+ TestGetLocalDeviceData_NoPublicKey) {
+ fake_enrollment_manager_->set_user_public_key(std::string());
+ fake_device_manager_->set_synced_devices(fake_synced_devices_);
std::string public_key;
std::vector<BeaconSeed> beacon_seeds;
@@ -166,11 +136,9 @@ TEST_F(LocalDeviceDataProviderTest, TestGetLocalDeviceData_NoPublicKey) {
EXPECT_FALSE(provider_->GetLocalDeviceData(&public_key, &beacon_seeds));
}
-TEST_F(LocalDeviceDataProviderTest, TestGetLocalDeviceData_NoSyncedDevices) {
- ON_CALL(*mock_enrollment_manager_, GetUserPublicKey())
- .WillByDefault(Return(kDefaultPublicKey));
- ON_CALL(*mock_device_manager_, GetSyncedDevices())
- .WillByDefault(Return(std::vector<ExternalDeviceInfo>()));
+TEST_F(CryptAuthLocalDeviceDataProviderTest,
+ TestGetLocalDeviceData_NoSyncedDevices) {
+ fake_enrollment_manager_->set_user_public_key(kDefaultPublicKey);
std::string public_key;
std::vector<BeaconSeed> beacon_seeds;
@@ -178,14 +146,12 @@ TEST_F(LocalDeviceDataProviderTest, TestGetLocalDeviceData_NoSyncedDevices) {
EXPECT_FALSE(provider_->GetLocalDeviceData(&public_key, &beacon_seeds));
}
-TEST_F(LocalDeviceDataProviderTest,
+TEST_F(CryptAuthLocalDeviceDataProviderTest,
TestGetLocalDeviceData_NoSyncedDeviceMatchingPublicKey) {
- ON_CALL(*mock_enrollment_manager_, GetUserPublicKey())
- .WillByDefault(Return(kDefaultPublicKey));
- ON_CALL(*mock_device_manager_, GetSyncedDevices())
- .WillByDefault(Return(std::vector<ExternalDeviceInfo>{
- fake_synced_devices_[0], fake_synced_devices_[1],
- fake_synced_devices_[2], fake_synced_devices_[3]}));
+ fake_enrollment_manager_->set_user_public_key(kDefaultPublicKey);
+ fake_device_manager_->set_synced_devices(std::vector<ExternalDeviceInfo>{
+ fake_synced_devices_[0], fake_synced_devices_[1], fake_synced_devices_[2],
+ fake_synced_devices_[3]});
std::string public_key;
std::vector<BeaconSeed> beacon_seeds;
@@ -193,14 +159,10 @@ TEST_F(LocalDeviceDataProviderTest,
EXPECT_FALSE(provider_->GetLocalDeviceData(&public_key, &beacon_seeds));
}
-TEST_F(LocalDeviceDataProviderTest,
+TEST_F(CryptAuthLocalDeviceDataProviderTest,
TestGetLocalDeviceData_SyncedDeviceIncludesPublicKeyButNoBeaconSeeds) {
- ON_CALL(*mock_enrollment_manager_, GetUserPublicKey())
- .WillByDefault(Return(kDefaultPublicKey));
- ON_CALL(*mock_device_manager_, GetSyncedDevices())
- .WillByDefault(Return(std::vector<ExternalDeviceInfo>{
- fake_synced_devices_[4],
- }));
+ fake_enrollment_manager_->set_user_public_key(kDefaultPublicKey);
+ fake_device_manager_->synced_devices().push_back(fake_synced_devices_[4]);
std::string public_key;
std::vector<BeaconSeed> beacon_seeds;
@@ -208,11 +170,9 @@ TEST_F(LocalDeviceDataProviderTest,
EXPECT_FALSE(provider_->GetLocalDeviceData(&public_key, &beacon_seeds));
}
-TEST_F(LocalDeviceDataProviderTest, TestGetLocalDeviceData_Success) {
- ON_CALL(*mock_enrollment_manager_, GetUserPublicKey())
- .WillByDefault(Return(kDefaultPublicKey));
- ON_CALL(*mock_device_manager_, GetSyncedDevices())
- .WillByDefault(Return(fake_synced_devices_));
+TEST_F(CryptAuthLocalDeviceDataProviderTest, TestGetLocalDeviceData_Success) {
+ fake_enrollment_manager_->set_user_public_key(kDefaultPublicKey);
+ fake_device_manager_->set_synced_devices(fake_synced_devices_);
std::string public_key;
std::vector<BeaconSeed> beacon_seeds;
diff --git a/chromium/components/cryptauth/mock_foreground_eid_generator.cc b/chromium/components/cryptauth/mock_foreground_eid_generator.cc
index 7964b4e044f..51d21ab62cd 100644
--- a/chromium/components/cryptauth/mock_foreground_eid_generator.cc
+++ b/chromium/components/cryptauth/mock_foreground_eid_generator.cc
@@ -4,7 +4,7 @@
#include "components/cryptauth/mock_foreground_eid_generator.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
namespace cryptauth {
@@ -22,13 +22,13 @@ MockForegroundEidGenerator::GenerateBackgroundScanFilter(
std::unique_ptr<DataWithTimestamp> adjacent_data;
if (background_scan_filter_->adjacent_data) {
- adjacent_data = base::MakeUnique<DataWithTimestamp>(
+ adjacent_data = std::make_unique<DataWithTimestamp>(
background_scan_filter_->adjacent_data->data,
background_scan_filter_->adjacent_data->start_timestamp_ms,
background_scan_filter_->adjacent_data->end_timestamp_ms);
}
- return base::MakeUnique<EidData>(background_scan_filter_->current_data,
+ return std::make_unique<EidData>(background_scan_filter_->current_data,
std::move(adjacent_data));
}
@@ -40,7 +40,7 @@ MockForegroundEidGenerator::GenerateAdvertisement(
return nullptr;
}
- return base::MakeUnique<DataWithTimestamp>(advertisement_->data,
+ return std::make_unique<DataWithTimestamp>(advertisement_->data,
advertisement_->start_timestamp_ms,
advertisement_->end_timestamp_ms);
}
diff --git a/chromium/components/cryptauth/remote_beacon_seed_fetcher_unittest.cc b/chromium/components/cryptauth/remote_beacon_seed_fetcher_unittest.cc
index 31fcaeeeed3..7e4aab88023 100644
--- a/chromium/components/cryptauth/remote_beacon_seed_fetcher_unittest.cc
+++ b/chromium/components/cryptauth/remote_beacon_seed_fetcher_unittest.cc
@@ -4,10 +4,11 @@
#include "components/cryptauth/remote_beacon_seed_fetcher.h"
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "components/cryptauth/cryptauth_client.h"
-#include "components/cryptauth/cryptauth_device_manager.h"
+#include "components/cryptauth/fake_cryptauth_device_manager.h"
#include "components/cryptauth/remote_device.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -38,14 +39,6 @@ const int64_t fake_beacon_seed4_end_ms = 3000L;
const std::string public_key1 = "publicKey1";
const std::string public_key2 = "publicKey2";
-class MockDeviceManager : public CryptAuthDeviceManager {
- public:
- MockDeviceManager() {}
- ~MockDeviceManager() override {}
-
- MOCK_CONST_METHOD0(GetSyncedDevices, std::vector<ExternalDeviceInfo>());
-};
-
ExternalDeviceInfo CreateFakeInfo1() {
BeaconSeed seed1;
seed1.set_data(fake_beacon_seed1_data);
@@ -90,13 +83,13 @@ class CryptAuthRemoteBeaconSeedFetcherTest : public testing::Test {
: fake_info1_(CreateFakeInfo1()), fake_info2_(CreateFakeInfo2()) {}
void SetUp() override {
- mock_device_manager_ = base::MakeUnique<MockDeviceManager>();
- fetcher_ = base::MakeUnique<StrictMock<RemoteBeaconSeedFetcher>>(
- mock_device_manager_.get());
+ fake_device_manager_ = std::make_unique<FakeCryptAuthDeviceManager>();
+ fetcher_ = std::make_unique<StrictMock<RemoteBeaconSeedFetcher>>(
+ fake_device_manager_.get());
}
std::unique_ptr<RemoteBeaconSeedFetcher> fetcher_;
- std::unique_ptr<MockDeviceManager> mock_device_manager_;
+ std::unique_ptr<FakeCryptAuthDeviceManager> fake_device_manager_;
const ExternalDeviceInfo fake_info1_;
const ExternalDeviceInfo fake_info2_;
@@ -111,18 +104,14 @@ TEST_F(CryptAuthRemoteBeaconSeedFetcherTest, TestRemoteDeviceWithNoPublicKey) {
}
TEST_F(CryptAuthRemoteBeaconSeedFetcherTest, TestNoSyncedDevices) {
- EXPECT_CALL(*mock_device_manager_, GetSyncedDevices())
- .WillOnce(Return(std::vector<ExternalDeviceInfo>()));
-
std::vector<BeaconSeed> seeds;
EXPECT_FALSE(fetcher_->FetchSeedsForDeviceId(
RemoteDevice::GenerateDeviceId(public_key1), &seeds));
}
TEST_F(CryptAuthRemoteBeaconSeedFetcherTest, TestDeviceHasDifferentPublicKey) {
- std::vector<ExternalDeviceInfo> device_infos = {fake_info1_, fake_info2_};
- EXPECT_CALL(*mock_device_manager_, GetSyncedDevices())
- .WillOnce(Return(device_infos));
+ fake_device_manager_->set_synced_devices(
+ std::vector<ExternalDeviceInfo>{fake_info1_, fake_info2_});
std::vector<BeaconSeed> seeds;
EXPECT_FALSE(fetcher_->FetchSeedsForDeviceId(
@@ -130,10 +119,8 @@ TEST_F(CryptAuthRemoteBeaconSeedFetcherTest, TestDeviceHasDifferentPublicKey) {
}
TEST_F(CryptAuthRemoteBeaconSeedFetcherTest, TestSuccess) {
- std::vector<ExternalDeviceInfo> device_infos = {fake_info1_, fake_info2_};
- EXPECT_CALL(*mock_device_manager_, GetSyncedDevices())
- .Times(2)
- .WillRepeatedly(Return(device_infos));
+ fake_device_manager_->set_synced_devices(
+ std::vector<ExternalDeviceInfo>{fake_info1_, fake_info2_});
std::vector<BeaconSeed> seeds1;
ASSERT_TRUE(fetcher_->FetchSeedsForDeviceId(
diff --git a/chromium/components/cryptauth/remote_device_loader_unittest.cc b/chromium/components/cryptauth/remote_device_loader_unittest.cc
index 3aa71fb89c4..03599cdd7f0 100644
--- a/chromium/components/cryptauth/remote_device_loader_unittest.cc
+++ b/chromium/components/cryptauth/remote_device_loader_unittest.cc
@@ -11,7 +11,6 @@
#include "base/bind.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "components/cryptauth/fake_secure_message_delegate.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -129,7 +128,7 @@ TEST_F(CryptAuthRemoteDeviceLoaderTest, LoadDevicesWithAndWithoutBeaconSeeds) {
1, CreateDeviceInfo("0"));
RemoteDeviceLoader loader1(device_infos, user_private_key_, kUserId,
- base::MakeUnique<FakeSecureMessageDelegate>());
+ std::make_unique<FakeSecureMessageDelegate>());
EXPECT_CALL(*this, LoadCompleted());
loader1.Load(
false /* should_load_beacon_seeds */,
@@ -138,7 +137,7 @@ TEST_F(CryptAuthRemoteDeviceLoaderTest, LoadDevicesWithAndWithoutBeaconSeeds) {
RemoteDevice remote_device_without_beacon_seed = remote_devices_[0];
RemoteDeviceLoader loader2(device_infos, user_private_key_, kUserId,
- base::MakeUnique<FakeSecureMessageDelegate>());
+ std::make_unique<FakeSecureMessageDelegate>());
EXPECT_CALL(*this, LoadCompleted());
loader2.Load(
true /* should_load_beacon_seeds */,
diff --git a/chromium/components/cryptauth/remote_device_provider_impl_unittest.cc b/chromium/components/cryptauth/remote_device_provider_impl_unittest.cc
index 15479abed33..588b9b83cd4 100644
--- a/chromium/components/cryptauth/remote_device_provider_impl_unittest.cc
+++ b/chromium/components/cryptauth/remote_device_provider_impl_unittest.cc
@@ -11,6 +11,7 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "components/cryptauth/cryptauth_device_manager.h"
+#include "components/cryptauth/fake_cryptauth_device_manager.h"
#include "components/cryptauth/fake_secure_message_delegate.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
#include "components/cryptauth/remote_device_loader.h"
@@ -30,21 +31,6 @@ namespace {
const char kTestUserId[] = "testUserId";
const char kTestUserPrivateKey[] = "kTestUserPrivateKey";
-class MockCryptAuthDeviceManager : public cryptauth::CryptAuthDeviceManager {
- public:
- ~MockCryptAuthDeviceManager() override {}
-
- void NotifySyncFinished(
- CryptAuthDeviceManager::SyncResult sync_result,
- CryptAuthDeviceManager::DeviceChangeResult device_change_result) {
- cryptauth::CryptAuthDeviceManager::NotifySyncFinished(sync_result,
- device_change_result);
- }
-
- MOCK_CONST_METHOD0(GetSyncedDevices,
- std::vector<::cryptauth::ExternalDeviceInfo>());
-};
-
class FakeSecureMessageDelegateFactory
: public cryptauth::SecureMessageDelegate::Factory {
public:
@@ -111,7 +97,7 @@ class FakeDeviceLoader final : public cryptauth::RemoteDeviceLoader {
EXPECT_EQ(std::string(kTestUserId), user_id);
EXPECT_EQ(std::string(kTestUserPrivateKey), user_private_key);
std::unique_ptr<FakeDeviceLoader> device_loader =
- base::MakeUnique<FakeDeviceLoader>();
+ std::make_unique<FakeDeviceLoader>();
device_loader->remote_device_loader_factory_ = this;
return std::move(device_loader);
}
@@ -168,40 +154,35 @@ class RemoteDeviceProviderImplTest : public testing::Test {
RemoteDeviceProviderImplTest() {}
void SetUp() override {
- mock_device_manager_ =
- base::WrapUnique(new NiceMock<MockCryptAuthDeviceManager>());
- ON_CALL(*mock_device_manager_, GetSyncedDevices())
- .WillByDefault(Invoke(
- this,
- &RemoteDeviceProviderImplTest::mock_device_manager_sync_devices));
+ fake_device_manager_ = std::make_unique<FakeCryptAuthDeviceManager>();
fake_secure_message_delegate_factory_ =
- base::MakeUnique<FakeSecureMessageDelegateFactory>();
+ std::make_unique<FakeSecureMessageDelegateFactory>();
test_device_loader_factory_ =
- base::MakeUnique<FakeDeviceLoader::TestRemoteDeviceLoaderFactory>();
+ std::make_unique<FakeDeviceLoader::TestRemoteDeviceLoaderFactory>();
cryptauth::RemoteDeviceLoader::Factory::SetInstanceForTesting(
test_device_loader_factory_.get());
- test_observer_ = base::MakeUnique<TestObserver>();
+ test_observer_ = std::make_unique<TestObserver>();
}
void CreateRemoteDeviceProvider() {
- remote_device_provider_ = base::MakeUnique<RemoteDeviceProviderImpl>(
- mock_device_manager_.get(), kTestUserId, kTestUserPrivateKey,
+ remote_device_provider_ = std::make_unique<RemoteDeviceProviderImpl>(
+ fake_device_manager_.get(), kTestUserId, kTestUserPrivateKey,
fake_secure_message_delegate_factory_.get());
remote_device_provider_->AddObserver(test_observer_.get());
EXPECT_EQ(0u, remote_device_provider_->GetSyncedDevices().size());
test_device_loader_factory_->InvokeLastCallback(
- mock_device_manager_synced_device_infos_);
+ fake_device_manager_->GetSyncedDevices());
VerifySyncedDevicesMatchExpectation(
- mock_device_manager_synced_device_infos_.size());
+ fake_device_manager_->GetSyncedDevices().size());
}
void VerifySyncedDevicesMatchExpectation(size_t expected_size) {
std::vector<cryptauth::RemoteDevice> synced_devices =
remote_device_provider_->GetSyncedDevices();
EXPECT_EQ(expected_size, synced_devices.size());
- EXPECT_EQ(expected_size, mock_device_manager_sync_devices().size());
+ EXPECT_EQ(expected_size, fake_device_manager_->GetSyncedDevices().size());
std::unordered_set<std::string> public_keys;
- for (const auto& device_info : mock_device_manager_synced_device_infos_) {
+ for (const auto& device_info : fake_device_manager_->GetSyncedDevices()) {
public_keys.insert(device_info.public_key());
}
for (const auto& remote_device : synced_devices) {
@@ -210,12 +191,6 @@ class RemoteDeviceProviderImplTest : public testing::Test {
}
}
- // This is the mock implementation of mock_device_manager_'s
- // GetSyncedDevices().
- std::vector<ExternalDeviceInfo> mock_device_manager_sync_devices() {
- return mock_device_manager_synced_device_infos_;
- }
-
std::vector<cryptauth::RemoteDevice> test_devices() {
return test_device_loader_factory_->test_devices_;
}
@@ -224,13 +199,10 @@ class RemoteDeviceProviderImplTest : public testing::Test {
return test_device_loader_factory_->test_device_infos_[val];
}
- std::vector<cryptauth::ExternalDeviceInfo>
- mock_device_manager_synced_device_infos_;
-
std::unique_ptr<FakeSecureMessageDelegateFactory>
fake_secure_message_delegate_factory_;
- std::unique_ptr<NiceMock<MockCryptAuthDeviceManager>> mock_device_manager_;
+ std::unique_ptr<FakeCryptAuthDeviceManager> fake_device_manager_;
std::unique_ptr<FakeDeviceLoader::TestRemoteDeviceLoaderFactory>
test_device_loader_factory_;
@@ -245,78 +217,78 @@ class RemoteDeviceProviderImplTest : public testing::Test {
TEST_F(RemoteDeviceProviderImplTest, TestMultipleSyncs) {
// Initialize with devices 0 and 1.
- mock_device_manager_synced_device_infos_ = std::vector<ExternalDeviceInfo>{
- test_device_infos_(0), test_device_infos_(1)};
+ fake_device_manager_->synced_devices().push_back(test_device_infos_(0));
+ fake_device_manager_->synced_devices().push_back(test_device_infos_(1));
CreateRemoteDeviceProvider();
VerifySyncedDevicesMatchExpectation(2u /* expected_size */);
EXPECT_EQ(1, test_observer_->num_times_device_list_changed());
// Now add device 2 and trigger another sync.
- mock_device_manager_synced_device_infos_.push_back(test_device_infos_(2));
- mock_device_manager_->NotifySyncFinished(
+ fake_device_manager_->synced_devices().push_back(test_device_infos_(2));
+ fake_device_manager_->NotifySyncFinished(
CryptAuthDeviceManager::SyncResult::SUCCESS,
CryptAuthDeviceManager::DeviceChangeResult::CHANGED);
test_device_loader_factory_->InvokeLastCallback(
- mock_device_manager_synced_device_infos_);
+ fake_device_manager_->GetSyncedDevices());
VerifySyncedDevicesMatchExpectation(3u /* expected_size */);
EXPECT_EQ(2, test_observer_->num_times_device_list_changed());
// Now, simulate a sync which shows that device 0 was removed.
- mock_device_manager_synced_device_infos_.erase(
- mock_device_manager_synced_device_infos_.begin());
- mock_device_manager_->NotifySyncFinished(
+ fake_device_manager_->synced_devices().erase(
+ fake_device_manager_->synced_devices().begin());
+ fake_device_manager_->NotifySyncFinished(
CryptAuthDeviceManager::SyncResult::SUCCESS,
CryptAuthDeviceManager::DeviceChangeResult::CHANGED);
test_device_loader_factory_->InvokeLastCallback(
- mock_device_manager_synced_device_infos_);
+ fake_device_manager_->GetSyncedDevices());
VerifySyncedDevicesMatchExpectation(2u /* expected_size */);
EXPECT_EQ(3, test_observer_->num_times_device_list_changed());
}
TEST_F(RemoteDeviceProviderImplTest,
TestNotifySyncFinishedParameterCombinations) {
- mock_device_manager_synced_device_infos_.push_back(test_device_infos_(0));
+ fake_device_manager_->synced_devices().push_back(test_device_infos_(0));
CreateRemoteDeviceProvider();
VerifySyncedDevicesMatchExpectation(1u /* expected_size */);
- mock_device_manager_->NotifySyncFinished(
+ fake_device_manager_->NotifySyncFinished(
CryptAuthDeviceManager::SyncResult::FAILURE,
CryptAuthDeviceManager::DeviceChangeResult::CHANGED);
EXPECT_FALSE(test_device_loader_factory_->HasQueuedCallback());
VerifySyncedDevicesMatchExpectation(1u /* expected_size */);
EXPECT_EQ(1, test_observer_->num_times_device_list_changed());
- mock_device_manager_->NotifySyncFinished(
+ fake_device_manager_->NotifySyncFinished(
CryptAuthDeviceManager::SyncResult::SUCCESS,
CryptAuthDeviceManager::DeviceChangeResult::UNCHANGED);
EXPECT_FALSE(test_device_loader_factory_->HasQueuedCallback());
VerifySyncedDevicesMatchExpectation(1u /* expected_size */);
EXPECT_EQ(1, test_observer_->num_times_device_list_changed());
- mock_device_manager_->NotifySyncFinished(
+ fake_device_manager_->NotifySyncFinished(
CryptAuthDeviceManager::SyncResult::FAILURE,
CryptAuthDeviceManager::DeviceChangeResult::UNCHANGED);
EXPECT_FALSE(test_device_loader_factory_->HasQueuedCallback());
VerifySyncedDevicesMatchExpectation(1u /* expected_size */);
EXPECT_EQ(1, test_observer_->num_times_device_list_changed());
- mock_device_manager_synced_device_infos_.push_back(test_device_infos_(1));
- mock_device_manager_->NotifySyncFinished(
+ fake_device_manager_->synced_devices().push_back(test_device_infos_(1));
+ fake_device_manager_->NotifySyncFinished(
CryptAuthDeviceManager::SyncResult::SUCCESS,
CryptAuthDeviceManager::DeviceChangeResult::CHANGED);
test_device_loader_factory_->InvokeLastCallback(
- mock_device_manager_synced_device_infos_);
+ fake_device_manager_->GetSyncedDevices());
VerifySyncedDevicesMatchExpectation(2u /* expected_size */);
EXPECT_EQ(2, test_observer_->num_times_device_list_changed());
}
TEST_F(RemoteDeviceProviderImplTest, TestNewSyncDuringDeviceRegeneration) {
- mock_device_manager_synced_device_infos_.push_back(test_device_infos_(0));
+ fake_device_manager_->synced_devices().push_back(test_device_infos_(0));
CreateRemoteDeviceProvider();
VerifySyncedDevicesMatchExpectation(1u /* expected_size */);
// Add device 1 and trigger a sync.
- mock_device_manager_synced_device_infos_.push_back(test_device_infos_(1));
- mock_device_manager_->NotifySyncFinished(
+ fake_device_manager_->synced_devices().push_back(test_device_infos_(1));
+ fake_device_manager_->NotifySyncFinished(
CryptAuthDeviceManager::SyncResult::SUCCESS,
CryptAuthDeviceManager::DeviceChangeResult::CHANGED);
EXPECT_EQ(1, test_observer_->num_times_device_list_changed());
@@ -324,12 +296,12 @@ TEST_F(RemoteDeviceProviderImplTest, TestNewSyncDuringDeviceRegeneration) {
// Do not wait for the new devices to be generated (i.e., don't call
// test_device_loader_factory_->InvokeLastCallback() yet). Trigger a new
// sync with device 2 included.
- mock_device_manager_synced_device_infos_.push_back(test_device_infos_(2));
- mock_device_manager_->NotifySyncFinished(
+ fake_device_manager_->synced_devices().push_back(test_device_infos_(2));
+ fake_device_manager_->NotifySyncFinished(
CryptAuthDeviceManager::SyncResult::SUCCESS,
CryptAuthDeviceManager::DeviceChangeResult::CHANGED);
test_device_loader_factory_->InvokeLastCallback(
- mock_device_manager_synced_device_infos_);
+ fake_device_manager_->GetSyncedDevices());
VerifySyncedDevicesMatchExpectation(3u /* expected_size */);
EXPECT_EQ(2, test_observer_->num_times_device_list_changed());
}
@@ -338,7 +310,7 @@ TEST_F(RemoteDeviceProviderImplTest, TestZeroSyncedDevices) {
CreateRemoteDeviceProvider();
VerifySyncedDevicesMatchExpectation(0 /* expected_size */);
EXPECT_EQ(1, test_observer_->num_times_device_list_changed());
- mock_device_manager_->NotifySyncFinished(
+ fake_device_manager_->NotifySyncFinished(
CryptAuthDeviceManager::SyncResult::SUCCESS,
CryptAuthDeviceManager::DeviceChangeResult::UNCHANGED);
EXPECT_FALSE(test_device_loader_factory_->HasQueuedCallback());
diff --git a/chromium/components/cryptauth/secure_channel.cc b/chromium/components/cryptauth/secure_channel.cc
index 8ba55e4c2a3..bcf3d296c19 100644
--- a/chromium/components/cryptauth/secure_channel.cc
+++ b/chromium/components/cryptauth/secure_channel.cc
@@ -4,6 +4,8 @@
#include "components/cryptauth/secure_channel.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "components/cryptauth/cryptauth_service.h"
@@ -51,6 +53,8 @@ std::string SecureChannel::StatusToString(const Status& status) {
return "[authenticating]";
case Status::AUTHENTICATED:
return "[authenticated]";
+ case Status::DISCONNECTING:
+ return "[disconnecting]";
default:
return "[unknown status]";
}
@@ -90,7 +94,7 @@ int SecureChannel::SendMessage(const std::string& feature,
next_sequence_number_++;
queued_messages_.emplace(
- base::MakeUnique<PendingMessage>(feature, payload, sequence_number));
+ std::make_unique<PendingMessage>(feature, payload, sequence_number));
ProcessMessageQueue();
return sequence_number;
@@ -98,6 +102,8 @@ int SecureChannel::SendMessage(const std::string& feature,
void SecureChannel::Disconnect() {
if (connection_->IsConnected()) {
+ TransitionToStatus(Status::DISCONNECTING);
+
// If |connection_| is active, calling Disconnect() will eventually cause
// its status to transition to DISCONNECTED, which will in turn cause this
// class to transition to DISCONNECTED.
@@ -274,7 +280,7 @@ void SecureChannel::ProcessMessageQueue() {
void SecureChannel::OnMessageEncoded(const std::string& feature,
int sequence_number,
const std::string& encoded_message) {
- connection_->SendMessage(base::MakeUnique<cryptauth::WireMessage>(
+ connection_->SendMessage(std::make_unique<cryptauth::WireMessage>(
encoded_message, feature, sequence_number));
}
diff --git a/chromium/components/cryptauth/secure_channel.h b/chromium/components/cryptauth/secure_channel.h
index 913c659d777..a9b941afb15 100644
--- a/chromium/components/cryptauth/secure_channel.h
+++ b/chromium/components/cryptauth/secure_channel.h
@@ -37,12 +37,15 @@ class SecureChannel : public ConnectionObserver {
// process of authenticating via a 3-message authentication handshake.
// AUTHENTICATED: The connection has been authenticated, and arbitrary
// messages can be sent/received to/from the device.
+ // DISCONNECTING: The connection has started disconnecting but has not yet
+ // finished.
enum class Status {
DISCONNECTED,
CONNECTING,
CONNECTED,
AUTHENTICATING,
AUTHENTICATED,
+ DISCONNECTING
};
static std::string StatusToString(const Status& status);
diff --git a/chromium/components/cryptauth/secure_channel_unittest.cc b/chromium/components/cryptauth/secure_channel_unittest.cc
index aceab544f82..bfcdbcc0c0c 100644
--- a/chromium/components/cryptauth/secure_channel_unittest.cc
+++ b/chromium/components/cryptauth/secure_channel_unittest.cc
@@ -4,6 +4,7 @@
#include "components/cryptauth/secure_channel.h"
+#include <memory>
#include <string>
#include "base/bind.h"
@@ -165,13 +166,13 @@ class CryptAuthSecureChannelTest : public testing::Test {
void SetUp() override {
has_verified_gatt_services_event_ = false;
- test_authenticator_factory_ = base::MakeUnique<TestAuthenticatorFactory>();
+ test_authenticator_factory_ = std::make_unique<TestAuthenticatorFactory>();
DeviceToDeviceAuthenticator::Factory::SetInstanceForTesting(
test_authenticator_factory_.get());
fake_secure_context_ = nullptr;
- fake_cryptauth_service_ = base::MakeUnique<FakeCryptAuthService>();
+ fake_cryptauth_service_ = std::make_unique<FakeCryptAuthService>();
fake_connection_ =
new FakeConnection(test_device_, /* should_auto_connect */ false);
@@ -182,7 +183,7 @@ class CryptAuthSecureChannelTest : public testing::Test {
EXPECT_EQ(static_cast<size_t>(1), fake_connection_->observers().size());
EXPECT_EQ(secure_channel_.get(), fake_connection_->observers()[0]);
- test_observer_ = base::MakeUnique<TestObserver>(secure_channel_.get());
+ test_observer_ = std::make_unique<TestObserver>(secure_channel_.get());
secure_channel_->AddObserver(test_observer_.get());
}
@@ -451,12 +452,11 @@ TEST_F(CryptAuthSecureChannelTest, AuthenticationFails_Disconnect) {
});
FailAuthentication(Authenticator::Result::DISCONNECTED);
- VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange> {
- {
- SecureChannel::Status::AUTHENTICATING,
- SecureChannel::Status::DISCONNECTED
- }
- });
+ VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
+ {SecureChannel::Status::AUTHENTICATING,
+ SecureChannel::Status::DISCONNECTING},
+ {SecureChannel::Status::DISCONNECTING,
+ SecureChannel::Status::DISCONNECTED}});
}
TEST_F(CryptAuthSecureChannelTest, AuthenticationFails_Failure) {
@@ -481,12 +481,11 @@ TEST_F(CryptAuthSecureChannelTest, AuthenticationFails_Failure) {
});
FailAuthentication(Authenticator::Result::FAILURE);
- VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange> {
- {
- SecureChannel::Status::AUTHENTICATING,
- SecureChannel::Status::DISCONNECTED
- }
- });
+ VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
+ {SecureChannel::Status::AUTHENTICATING,
+ SecureChannel::Status::DISCONNECTING},
+ {SecureChannel::Status::DISCONNECTING,
+ SecureChannel::Status::DISCONNECTED}});
}
// Regression test for crbug.com/765810. This test ensures that a crash does not
@@ -555,12 +554,11 @@ TEST_F(
TEST_F(CryptAuthSecureChannelTest, SendMessage_Failure) {
ConnectAndAuthenticate();
StartAndFinishSendingMessage("feature", "payload", /* success */ false);
- VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange> {
- {
- SecureChannel::Status::AUTHENTICATED,
- SecureChannel::Status::DISCONNECTED
- }
- });
+ VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
+ {SecureChannel::Status::AUTHENTICATED,
+ SecureChannel::Status::DISCONNECTING},
+ {SecureChannel::Status::DISCONNECTING,
+ SecureChannel::Status::DISCONNECTED}});
}
TEST_F(CryptAuthSecureChannelTest, SendMessage_Success) {
@@ -600,12 +598,11 @@ TEST_F(CryptAuthSecureChannelTest, SendMessage_MultipleMessages_FirstFails) {
FinishSendingMessage(sequence_number1, false);
// The connection should have become disconnected.
- VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange> {
- {
- SecureChannel::Status::AUTHENTICATED,
- SecureChannel::Status::DISCONNECTED
- }
- });
+ VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{
+ {SecureChannel::Status::AUTHENTICATED,
+ SecureChannel::Status::DISCONNECTING},
+ {SecureChannel::Status::DISCONNECTING,
+ SecureChannel::Status::DISCONNECTED}});
// The first message failed, so no other ones should be tried afterward.
VerifyNoMessageBeingSent();
diff --git a/chromium/components/cryptauth/sync_scheduler_impl.cc b/chromium/components/cryptauth/sync_scheduler_impl.cc
index 9bde910ecbf..b8200c06cec 100644
--- a/chromium/components/cryptauth/sync_scheduler_impl.cc
+++ b/chromium/components/cryptauth/sync_scheduler_impl.cc
@@ -7,9 +7,9 @@
#include <algorithm>
#include <cmath>
#include <limits>
+#include <memory>
#include "base/bind.h"
-#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
@@ -113,13 +113,13 @@ void SyncSchedulerImpl::OnTimerFired() {
}
delegate_->OnSyncRequested(
- base::MakeUnique<SyncRequest>(weak_ptr_factory_.GetWeakPtr()));
+ std::make_unique<SyncRequest>(weak_ptr_factory_.GetWeakPtr()));
}
std::unique_ptr<base::Timer> SyncSchedulerImpl::CreateTimer() {
bool retain_user_task = false;
bool is_repeating = false;
- return base::MakeUnique<base::Timer>(retain_user_task, is_repeating);
+ return std::make_unique<base::Timer>(retain_user_task, is_repeating);
}
void SyncSchedulerImpl::ScheduleNextSync(const base::TimeDelta& sync_delta) {
diff --git a/chromium/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc b/chromium/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
index 1f1af66f9a1..ed6203ca38f 100644
--- a/chromium/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
+++ b/chromium/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
@@ -32,8 +32,8 @@
#include "net/base/load_flags.h"
#include "net/base/network_delegate_impl.h"
#include "net/http/http_request_headers.h"
-#include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_retry_info.h"
+#include "net/proxy_resolution/proxy_info.h"
+#include "net/proxy_resolution/proxy_retry_info.h"
#include "net/socket/socket_test_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
diff --git a/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc b/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc
index e943f75b131..61044ce7a27 100644
--- a/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc
+++ b/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc
@@ -16,9 +16,9 @@
#include "base/task_scheduler/task_traits.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
#include "components/variations/net/variations_http_headers.h"
diff --git a/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc b/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc
index f9200eb559a..8966a225548 100644
--- a/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc
+++ b/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc
@@ -21,9 +21,9 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "components/data_reduction_proxy/proto/pageload_metrics.pb.h"
#include "content/public/common/child_process_host.h"
diff --git a/chromium/components/data_reduction_proxy/core/browser/BUILD.gn b/chromium/components/data_reduction_proxy/core/browser/BUILD.gn
index c8d6b739c19..5dd1eca334e 100644
--- a/chromium/components/data_reduction_proxy/core/browser/BUILD.gn
+++ b/chromium/components/data_reduction_proxy/core/browser/BUILD.gn
@@ -41,6 +41,8 @@ browser_sources = [
"data_reduction_proxy_service_observer.h",
"data_reduction_proxy_settings.cc",
"data_reduction_proxy_settings.h",
+ "data_reduction_proxy_util.cc",
+ "data_reduction_proxy_util.h",
"data_store.cc",
"data_store.h",
"data_usage_store.cc",
@@ -178,6 +180,7 @@ source_set("unit_tests") {
"data_reduction_proxy_prefs_unittest.cc",
"data_reduction_proxy_request_options_unittest.cc",
"data_reduction_proxy_settings_unittest.cc",
+ "data_reduction_proxy_util_unittest.cc",
"data_usage_store_unittest.cc",
"network_properties_manager_unittest.cc",
"warmup_url_fetcher_unittest.cc",
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc
index 58e17ba113a..0a51d7e8f9e 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc
@@ -17,14 +17,14 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "net/base/load_flags.h"
+#include "net/base/proxy_server.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
-#include "net/proxy/proxy_config.h"
-#include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_list.h"
-#include "net/proxy/proxy_retry_info.h"
-#include "net/proxy/proxy_server.h"
-#include "net/proxy/proxy_service.h"
+#include "net/proxy_resolution/proxy_config.h"
+#include "net/proxy_resolution/proxy_info.h"
+#include "net/proxy_resolution/proxy_list.h"
+#include "net/proxy_resolution/proxy_retry_info.h"
+#include "net/proxy_resolution/proxy_service.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_status.h"
@@ -60,10 +60,11 @@ void MarkProxiesAsBadUntil(
net::ProxyInfo proxy_info;
proxy_info.UseProxyList(proxy_list);
DCHECK(request->context());
- net::ProxyService* proxy_service = request->context()->proxy_service();
- DCHECK(proxy_service);
+ net::ProxyResolutionService* proxy_resolution_service =
+ request->context()->proxy_resolution_service();
+ DCHECK(proxy_resolution_service);
- proxy_service->MarkProxiesAsBadUntil(
+ proxy_resolution_service->MarkProxiesAsBadUntil(
proxy_info, bypass_duration, additional_bad_proxies, request->net_log());
}
@@ -250,13 +251,13 @@ bool DataReductionProxyBypassProtocol::HandleValidResponseHeadersCase(
return false;
DCHECK(request.context());
- DCHECK(request.context()->proxy_service());
+ DCHECK(request.context()->proxy_resolution_service());
net::ProxyServer proxy_server =
data_reduction_proxy_type_info->proxy_servers.front();
// Only record UMA if the proxy isn't already on the retry list.
if (!config_->IsProxyBypassed(
- request.context()->proxy_service()->proxy_retry_info(), proxy_server,
+ request.context()->proxy_resolution_service()->proxy_retry_info(), proxy_server,
nullptr)) {
DataReductionProxyBypassStats::RecordDataReductionProxyBypassInfo(
data_reduction_proxy_type_info->proxy_index == 0,
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h
index b8e18009a97..40aaf09e5a2 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h
@@ -42,10 +42,11 @@ class DataReductionProxyBypassProtocol {
~DataReductionProxyBypassProtocol();
// Decides whether to mark the data reduction proxy as temporarily bad and
- // put it on the proxy retry map, which is maintained by the ProxyService of
- // the URLRequestContext. Returns true if the request should be retried.
- // Updates the load flags in |request| for some bypass types, e.g.,
- // "block-once". Returns the DataReductionProxyBypassType (if not NULL).
+ // put it on the proxy retry map, which is maintained by the
+ // ProxyResolutionService of the URLRequestContext. Returns true if the
+ // request should be retried. Updates the load flags in |request| for some
+ // bypass types, e.g., "block-once". Returns the DataReductionProxyBypassType
+ // (if not NULL).
bool MaybeBypassProxyAndPrepareToRetry(
net::URLRequest* request,
DataReductionProxyBypassType* proxy_bypass_type,
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
index fa0b804dcfc..2f8e414a0a3 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
@@ -32,11 +32,11 @@
#include "net/base/network_change_notifier.h"
#include "net/base/network_delegate.h"
#include "net/base/proxy_delegate.h"
+#include "net/base/proxy_server.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_transaction_test_util.h"
#include "net/http/http_util.h"
-#include "net/proxy/proxy_server.h"
-#include "net/proxy/proxy_service.h"
+#include "net/proxy_resolution/proxy_service.h"
#include "net/socket/socket_test_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_response.h"
@@ -60,7 +60,7 @@ using net::HttpResponseHeaders;
using net::MockRead;
using net::MockWrite;
using net::ProxyRetryInfoMap;
-using net::ProxyService;
+using net::ProxyResolutionService;
using net::StaticSocketDataProvider;
using net::TestDelegate;
using net::TestURLRequestContext;
@@ -109,13 +109,15 @@ class DataReductionProxyProtocolEmbeddedServerTest : public testing::Test {
test_context_->RunUntilIdle();
}
- // Sets up the |TestURLRequestContext| with the provided |ProxyService|.
- void ConfigureTestDependencies(std::unique_ptr<ProxyService> proxy_service) {
+ // Sets up the |TestURLRequestContext| with the provided
+ // |ProxyResolutionService|.
+ void ConfigureTestDependencies(
+ std::unique_ptr<ProxyResolutionService> proxy_resolution_service) {
// Create a context with delayed initialization.
context_.reset(new TestURLRequestContext(true));
- proxy_service_ = std::move(proxy_service);
- context_->set_proxy_service(proxy_service_.get());
+ proxy_resolution_service_ = std::move(proxy_resolution_service);
+ context_->set_proxy_resolution_service(proxy_resolution_service_.get());
DataReductionProxyInterceptor* interceptor =
new DataReductionProxyInterceptor(
@@ -140,7 +142,7 @@ class DataReductionProxyProtocolEmbeddedServerTest : public testing::Test {
base::MessageLoopForIO message_loop_;
net::EmbeddedTestServer embedded_test_server_;
- std::unique_ptr<ProxyService> proxy_service_;
+ std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
std::unique_ptr<DataReductionProxyTestContext> test_context_;
std::unique_ptr<net::URLRequestInterceptingJobFactory> job_factory_;
@@ -169,7 +171,8 @@ TEST_F(DataReductionProxyProtocolEmbeddedServerTest,
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kDataReductionProxy, proxy_server.host_port_pair().ToString());
test_context_->config()->ResetParamFlagsForTest();
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult("DIRECT"));
+ ConfigureTestDependencies(
+ ProxyResolutionService::CreateFixedFromPacResult("DIRECT"));
test_context_->RunUntilIdle();
base::RunLoop().RunUntilIdle();
@@ -187,11 +190,12 @@ TEST_F(DataReductionProxyProtocolEmbeddedServerTest,
}
EXPECT_FALSE(url_request->proxy_server().is_http());
// The proxy should have been marked as bad.
- ProxyRetryInfoMap retry_info = proxy_service_->proxy_retry_info();
+ ProxyRetryInfoMap retry_info =
+ proxy_resolution_service_->proxy_retry_info();
while (retry_info.size() != 1) {
test_context_->RunUntilIdle();
base::RunLoop().RunUntilIdle();
- retry_info = proxy_service_->proxy_retry_info();
+ retry_info = proxy_resolution_service_->proxy_retry_info();
}
EXPECT_LE(base::TimeDelta::FromMinutes(4),
@@ -217,11 +221,12 @@ TEST_F(DataReductionProxyProtocolEmbeddedServerTest,
EXPECT_TRUE(!url_request->proxy_server().is_valid() ||
url_request->proxy_server().is_direct());
// The proxy should still be marked as bad.
- ProxyRetryInfoMap retry_info = proxy_service_->proxy_retry_info();
+ ProxyRetryInfoMap retry_info =
+ proxy_resolution_service_->proxy_retry_info();
while (retry_info.size() != 1) {
test_context_->RunUntilIdle();
base::RunLoop().RunUntilIdle();
- retry_info = proxy_service_->proxy_retry_info();
+ retry_info = proxy_resolution_service_->proxy_retry_info();
}
EXPECT_LE(base::TimeDelta::FromMinutes(4),
@@ -253,19 +258,21 @@ class DataReductionProxyProtocolTest : public testing::Test {
test_context_->RunUntilIdle();
}
- // Sets up the |TestURLRequestContext| with the provided |ProxyService|.
- void ConfigureTestDependencies(std::unique_ptr<ProxyService> proxy_service,
- bool use_mock_socket_factory,
- bool use_drp_proxy_delegate,
- bool use_test_network_delegate) {
+ // Sets up the |TestURLRequestContext| with the provided
+ // |ProxyResolutionService|.
+ void ConfigureTestDependencies(
+ std::unique_ptr<ProxyResolutionService> proxy_resolution_service,
+ bool use_mock_socket_factory,
+ bool use_drp_proxy_delegate,
+ bool use_test_network_delegate) {
// Create a context with delayed initialization.
context_.reset(new TestURLRequestContext(true));
- proxy_service_ = std::move(proxy_service);
+ proxy_resolution_service_ = std::move(proxy_resolution_service);
if (use_mock_socket_factory) {
context_->set_client_socket_factory(&mock_socket_factory_);
}
- context_->set_proxy_service(proxy_service_.get());
+ context_->set_proxy_resolution_service(proxy_resolution_service_.get());
if (use_test_network_delegate) {
network_delegate_.reset(new net::TestNetworkDelegate());
context_->set_network_delegate(network_delegate_.get());
@@ -465,7 +472,8 @@ class DataReductionProxyProtocolTest : public testing::Test {
int duration_seconds,
const std::string& bad_proxy,
const std::string& bad_proxy2) {
- const ProxyRetryInfoMap& retry_info = proxy_service_->proxy_retry_info();
+ const ProxyRetryInfoMap& retry_info =
+ proxy_resolution_service_->proxy_retry_info();
ASSERT_EQ(expected_num_bad_proxies, retry_info.size());
base::TimeDelta expected_min_duration;
@@ -501,7 +509,7 @@ class DataReductionProxyProtocolTest : public testing::Test {
std::unique_ptr<net::URLRequestInterceptor> simple_interceptor_;
net::MockClientSocketFactory mock_socket_factory_;
std::unique_ptr<net::TestNetworkDelegate> network_delegate_;
- std::unique_ptr<ProxyService> proxy_service_;
+ std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
std::unique_ptr<DataReductionProxyTestContext> test_context_;
std::unique_ptr<DataReductionProxyBypassStats> bypass_stats_;
net::StaticHttpUserAgentSettings http_user_agent_settings_;
@@ -574,7 +582,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassRetryOnPostConnectionErrors) {
base::HistogramTester histogram_tester;
ConfigureTestDependencies(
- ProxyService::CreateFixedFromPacResult(
+ ProxyResolutionService::CreateFixedFromPacResult(
net::ProxyServer::FromURI(primary, net::ProxyServer::SCHEME_HTTP)
.ToPacString() +
"; " +
@@ -594,11 +602,12 @@ TEST_F(DataReductionProxyProtocolTest, BypassRetryOnPostConnectionErrors) {
TestBadProxies(tests[i].expected_bad_proxy_count,
tests[i].expected_duration, primary, fallback);
- ProxyRetryInfoMap retry_info = proxy_service_->proxy_retry_info();
+ ProxyRetryInfoMap retry_info =
+ proxy_resolution_service_->proxy_retry_info();
while (retry_info.size() != 1) {
test_context_->RunUntilIdle();
base::RunLoop().RunUntilIdle();
- retry_info = proxy_service_->proxy_retry_info();
+ retry_info = proxy_resolution_service_->proxy_retry_info();
}
EXPECT_LE(base::TimeDelta::FromMinutes(4),
@@ -1019,7 +1028,7 @@ TEST_F(DataReductionProxyProtocolTest, BypassLogic) {
.ToString();
for (size_t i = 0; i < arraysize(tests); ++i) {
ConfigureTestDependencies(
- ProxyService::CreateFixedFromPacResult(
+ ProxyResolutionService::CreateFixedFromPacResult(
net::ProxyServer::FromURI(primary, net::ProxyServer::SCHEME_HTTP)
.ToPacString() +
"; " +
@@ -1129,8 +1138,8 @@ TEST_F(DataReductionProxyBypassProtocolEndToEndTest,
const std::string kPrimary = "https://unrecognized-drp.net:443";
ResetDependencies();
- storage()->set_proxy_service(
- ProxyService::CreateFixed(kPrimary + ",direct://"));
+ storage()->set_proxy_resolution_service(
+ ProxyResolutionService::CreateFixed(kPrimary + ",direct://"));
AttachToContextAndInit();
// The proxy is an HTTPS proxy, so set up the fake SSL socket data.
@@ -1162,9 +1171,9 @@ TEST_F(DataReductionProxyBypassProtocolEndToEndTest,
EXPECT_EQ(test.expected_bypass_type,
drp_test_context()->io_data()->bypass_stats()->GetBypassType());
// Check the bad proxy list.
- EXPECT_EQ(test.expected_bad_proxy,
- base::ContainsKey(context()->proxy_service()->proxy_retry_info(),
- kPrimary));
+ EXPECT_EQ(test.expected_bad_proxy, base::ContainsKey(
+ context()->proxy_resolution_service()->proxy_retry_info(),
+ kPrimary));
}
}
@@ -1199,8 +1208,8 @@ TEST_F(DataReductionProxyBypassProtocolEndToEndTest,
for (const auto& test : test_cases) {
ResetDependencies();
- storage()->set_proxy_service(
- net::ProxyService::CreateFixed(test.proxy_rules));
+ storage()->set_proxy_resolution_service(
+ net::ProxyResolutionService::CreateFixed(test.proxy_rules));
AttachToContextAndInit();
if (test.enable_data_reduction_proxy) {
drp_test_context()->DisableWarmupURLFetch();
@@ -1232,10 +1241,10 @@ TEST_F(DataReductionProxyProtocolTest,
ProxyBypassIgnoredOnDirectConnection) {
// Verify that a Chrome-Proxy header is ignored when returned from a directly
// connected origin server.
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult("DIRECT"),
- true /* use_mock_socket_factory */,
- false /* use_drp_proxy_delegate */,
- true /* use_test_network_delegate */);
+ ConfigureTestDependencies(
+ ProxyResolutionService::CreateFixedFromPacResult("DIRECT"),
+ true /* use_mock_socket_factory */, false /* use_drp_proxy_delegate */,
+ true /* use_test_network_delegate */);
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc
index 070c52aef33..313c824d1f3 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc
@@ -8,15 +8,15 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/base/proxy_server.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
-#include "net/proxy/proxy_server.h"
-#include "net/proxy/proxy_service.h"
+#include "net/proxy_resolution/proxy_service.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
index f86c341a907..2bd7a912344 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
@@ -35,11 +35,11 @@
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/proxy_delegate.h"
+#include "net/base/proxy_server.h"
#include "net/base/request_priority.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
-#include "net/proxy/proxy_server.h"
#include "net/socket/socket_test_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
@@ -395,8 +395,8 @@ class DataReductionProxyBypassStatsEndToEndTest : public testing::Test {
return request;
}
- void set_proxy_service(net::ProxyService* proxy_service) {
- context_.set_proxy_service(proxy_service);
+ void set_proxy_resolution_service(net::ProxyResolutionService* proxy_resolution_service) {
+ context_.set_proxy_resolution_service(proxy_resolution_service);
}
void set_host_resolver(net::HostResolver* host_resolver) {
@@ -416,7 +416,7 @@ class DataReductionProxyBypassStatsEndToEndTest : public testing::Test {
}
void ClearBadProxies() {
- context_.proxy_service()->ClearBadProxiesCache();
+ context_.proxy_resolution_service()->ClearBadProxiesCache();
}
void InitializeContext() {
@@ -597,9 +597,9 @@ TEST_F(DataReductionProxyBypassStatsEndToEndTest, URLRedirectCycle) {
TEST_F(DataReductionProxyBypassStatsEndToEndTest,
BypassedBytesProxyOverridden) {
- std::unique_ptr<net::ProxyService> proxy_service(
- net::ProxyService::CreateFixed("http://test.com:80"));
- set_proxy_service(proxy_service.get());
+ std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service(
+ net::ProxyResolutionService::CreateFixed("http://test.com:80"));
+ set_proxy_resolution_service(proxy_resolution_service.get());
InitializeContext();
base::HistogramTester histogram_tester;
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
index 3c21d55e360..9b43046be09 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
@@ -24,6 +24,7 @@
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/task_runner_util.h"
#include "base/time/default_tick_clock.h"
#include "build/build_config.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
@@ -39,9 +40,9 @@
#include "net/base/load_flags.h"
#include "net/base/network_change_notifier.h"
#include "net/base/network_interfaces.h"
+#include "net/base/proxy_server.h"
#include "net/log/net_log_source_type.h"
#include "net/nqe/effective_connection_type.h"
-#include "net/proxy/proxy_server.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"
@@ -119,6 +120,52 @@ void RecordWarmupURLFetchAttemptEvent(
WarmupURLFetchAttemptEvent::kCount);
}
+std::string DoGetCurrentNetworkID() {
+ // It is possible that the connection type changed between when
+ // GetConnectionType() was called and when the API to determine the
+ // network name was called. Check if that happened and retry until the
+ // connection type stabilizes. This is an imperfect solution but should
+ // capture majority of cases, and should not significantly affect estimates
+ // (that are approximate to begin with).
+
+ while (true) {
+ net::NetworkChangeNotifier::ConnectionType connection_type =
+ net::NetworkChangeNotifier::GetConnectionType();
+ std::string ssid_mccmnc;
+
+ switch (connection_type) {
+ case net::NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN:
+ case net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE:
+ case net::NetworkChangeNotifier::ConnectionType::CONNECTION_BLUETOOTH:
+ case net::NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET:
+ break;
+ case net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI:
+#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_WIN)
+ ssid_mccmnc = net::GetWifiSSID();
+#endif
+ break;
+ case net::NetworkChangeNotifier::ConnectionType::CONNECTION_2G:
+ case net::NetworkChangeNotifier::ConnectionType::CONNECTION_3G:
+ case net::NetworkChangeNotifier::ConnectionType::CONNECTION_4G:
+#if defined(OS_ANDROID)
+ ssid_mccmnc = net::android::GetTelephonyNetworkOperator();
+#endif
+ break;
+ }
+
+ if (connection_type == net::NetworkChangeNotifier::GetConnectionType()) {
+ if (connection_type >= net::NetworkChangeNotifier::CONNECTION_2G &&
+ connection_type <= net::NetworkChangeNotifier::CONNECTION_4G) {
+ // No need to differentiate cellular connections by the exact
+ // connection type.
+ return "cell," + ssid_mccmnc;
+ }
+ return base::IntToString(connection_type) + "," + ssid_mccmnc;
+ }
+ }
+ NOTREACHED();
+}
+
} // namespace
namespace data_reduction_proxy {
@@ -274,7 +321,7 @@ bool DataReductionProxyConfig::IsBypassedByDataReductionProxyLocalRules(
const net::ProxyConfig& data_reduction_proxy_config) const {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(request.context());
- DCHECK(request.context()->proxy_service());
+ DCHECK(request.context()->proxy_resolution_service());
net::ProxyInfo result;
data_reduction_proxy_config.proxy_rules().Apply(
request.url(), &result);
@@ -291,9 +338,9 @@ bool DataReductionProxyConfig::AreDataReductionProxiesBypassed(
base::TimeDelta* min_retry_delay) const {
DCHECK(thread_checker_.CalledOnValidThread());
if (request.context() != nullptr &&
- request.context()->proxy_service() != nullptr) {
+ request.context()->proxy_resolution_service() != nullptr) {
return AreProxiesBypassed(
- request.context()->proxy_service()->proxy_retry_info(),
+ request.context()->proxy_resolution_service()->proxy_retry_info(),
data_reduction_proxy_config.proxy_rules(),
request.url().SchemeIsCryptographic(), min_retry_delay);
}
@@ -306,8 +353,8 @@ bool DataReductionProxyConfig::AreProxiesBypassed(
const net::ProxyConfig::ProxyRules& proxy_rules,
bool is_https,
base::TimeDelta* min_retry_delay) const {
- // Data reduction proxy config is TYPE_PROXY_PER_SCHEME.
- if (proxy_rules.type != net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME)
+ // Data reduction proxy config is Type::PROXY_LIST_PER_SCHEME.
+ if (proxy_rules.type != net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME)
return false;
if (is_https)
@@ -363,8 +410,8 @@ bool DataReductionProxyConfig::IsProxyBypassed(
bool DataReductionProxyConfig::ContainsDataReductionProxy(
const net::ProxyConfig::ProxyRules& proxy_rules) const {
DCHECK(thread_checker_.CalledOnValidThread());
- // Data Reduction Proxy configurations are always TYPE_PROXY_PER_SCHEME.
- if (proxy_rules.type != net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME)
+ // Data Reduction Proxy configurations are always Type::PROXY_LIST_PER_SCHEME.
+ if (proxy_rules.type != net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME)
return false;
const net::ProxyList* http_proxy_list =
@@ -629,7 +676,22 @@ void DataReductionProxyConfig::OnNetworkChanged(
connection_type_ = type;
RecordNetworkChangeEvent(NETWORK_CHANGED);
- network_properties_manager_->OnChangeInNetworkID(GetCurrentNetworkID());
+
+ if (!get_network_id_task_runner_) {
+ ContinueNetworkChanged(GetCurrentNetworkID());
+ return;
+ }
+
+ base::PostTaskAndReplyWithResult(
+ get_network_id_task_runner_.get(), FROM_HERE,
+ base::BindOnce(&DoGetCurrentNetworkID),
+ base::BindOnce(&DataReductionProxyConfig::ContinueNetworkChanged,
+ weak_factory_.GetWeakPtr()));
+}
+
+void DataReductionProxyConfig::ContinueNetworkChanged(
+ const std::string& network_id) {
+ network_properties_manager_->OnChangeInNetworkID(network_id);
ReloadConfig();
@@ -761,7 +823,8 @@ bool DataReductionProxyConfig::ShouldAcceptServerPreview(
DCHECK((request.load_flags() & net::LOAD_MAIN_FRAME_DEPRECATED) != 0);
DCHECK(!request.url().SchemeIsCryptographic());
- if (!base::FeatureList::IsEnabled(
+ if (!previews::params::ArePreviewsAllowed() ||
+ !base::FeatureList::IsEnabled(
features::kDataReductionProxyDecidesTransform)) {
return false;
}
@@ -805,50 +868,7 @@ DataReductionProxyConfig::GetProxiesForHttp() const {
std::string DataReductionProxyConfig::GetCurrentNetworkID() const {
DCHECK(thread_checker_.CalledOnValidThread());
-
- // It is possible that the connection type changed between when
- // GetConnectionType() was called and when the API to determine the
- // network name was called. Check if that happened and retry until the
- // connection type stabilizes. This is an imperfect solution but should
- // capture majority of cases, and should not significantly affect estimates
- // (that are approximate to begin with).
-
- while (true) {
- net::NetworkChangeNotifier::ConnectionType connection_type =
- net::NetworkChangeNotifier::GetConnectionType();
- std::string ssid_mccmnc;
-
- switch (connection_type) {
- case net::NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN:
- case net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE:
- case net::NetworkChangeNotifier::ConnectionType::CONNECTION_BLUETOOTH:
- case net::NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET:
- break;
- case net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI:
-#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_WIN)
- ssid_mccmnc = net::GetWifiSSID();
-#endif
- break;
- case net::NetworkChangeNotifier::ConnectionType::CONNECTION_2G:
- case net::NetworkChangeNotifier::ConnectionType::CONNECTION_3G:
- case net::NetworkChangeNotifier::ConnectionType::CONNECTION_4G:
-#if defined(OS_ANDROID)
- ssid_mccmnc = net::android::GetTelephonyNetworkOperator();
-#endif
- break;
- }
-
- if (connection_type == net::NetworkChangeNotifier::GetConnectionType()) {
- if (connection_type >= net::NetworkChangeNotifier::CONNECTION_2G &&
- connection_type <= net::NetworkChangeNotifier::CONNECTION_4G) {
- // No need to differentiate cellular connections by the exact
- // connection type.
- return "cell," + ssid_mccmnc;
- }
- return base::IntToString(connection_type) + "," + ssid_mccmnc;
- }
- }
- NOTREACHED();
+ return DoGetCurrentNetworkID();
}
const NetworkPropertiesManager&
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
index 327562e755e..986045b564e 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
@@ -25,8 +25,8 @@
#include "components/previews/core/previews_experiments.h"
#include "net/base/network_change_notifier.h"
#include "net/log/net_log_with_source.h"
-#include "net/proxy/proxy_config.h"
-#include "net/proxy/proxy_retry_info.h"
+#include "net/proxy_resolution/proxy_config.h"
+#include "net/proxy_resolution/proxy_retry_info.h"
namespace base {
class SingleThreadTaskRunner;
@@ -125,7 +125,8 @@ class DataReductionProxyConfig
// contain the names of the Data Reduction Proxy servers that would be used if
// |proxy_info.proxy_servers.front()| is bypassed, if any exist. In addition,
// |proxy_info| will note if the proxy used was a fallback. |proxy_info| can
- // be NULL if the caller isn't interested in its values.
+ // be NULL if the caller isn't interested in its values. Virtualized for
+ // testing.
virtual bool WasDataReductionProxyUsed(
const net::URLRequest* request,
DataReductionProxyTypeInfo* proxy_info) const;
@@ -136,17 +137,14 @@ class DataReductionProxyConfig
// will contain the name of the Data Reduction Proxy servers that would be
// used if |proxy_info.proxy_servers.front()| is bypassed, if any exist. In
// addition, |proxy_info| will note if the proxy was a fallback. |proxy_info|
- // can be NULL if the caller isn't interested in its values. Virtual for
- // testing.
- virtual bool IsDataReductionProxy(
- const net::ProxyServer& proxy_server,
- DataReductionProxyTypeInfo* proxy_info) const;
+ // can be NULL if the caller isn't interested in its values.
+ bool IsDataReductionProxy(const net::ProxyServer& proxy_server,
+ DataReductionProxyTypeInfo* proxy_info) const;
// Returns true if this request would be bypassed by the Data Reduction Proxy
// based on applying the |data_reduction_proxy_config| param rules to the
// request URL.
- // Virtualized for mocking.
- virtual bool IsBypassedByDataReductionProxyLocalRules(
+ bool IsBypassedByDataReductionProxyLocalRules(
const net::URLRequest& request,
const net::ProxyConfig& data_reduction_proxy_config) const;
@@ -157,8 +155,7 @@ class DataReductionProxyConfig
// reduction proxies in min_retry_delay (if not NULL). If there are no
// bypassed data reduction proxies for the request scheme, returns false and
// does not assign min_retry_delay.
- // Virtualized for mocking.
- virtual bool AreDataReductionProxiesBypassed(
+ bool AreDataReductionProxiesBypassed(
const net::URLRequest& request,
const net::ProxyConfig& data_reduction_proxy_config,
base::TimeDelta* min_retry_delay) const;
@@ -204,10 +201,16 @@ class DataReductionProxyConfig
// Returns the details of the proxy to which the warmup URL probe is
// in-flight. Returns base::nullopt if no warmup probe is in-flight.
+ // Virtualized for testing.
virtual base::Optional<
std::pair<bool /* is_secure_proxy */, bool /*is_core_proxy */>>
GetInFlightWarmupProxyDetails() const;
+ void set_get_network_id_task_runner(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ get_network_id_task_runner_ = task_runner;
+ }
+
protected:
virtual base::TimeTicks GetTicksNow() const;
@@ -274,6 +277,13 @@ class DataReductionProxyConfig
void OnNetworkChanged(
net::NetworkChangeNotifier::ConnectionType type) override;
+ // Invoked to continue network changed handling after the network id is
+ // retrieved. If |get_network_id_task_runner_| is set, the network id is
+ // fetched on the worker thread. Otherwise, OnNetworkChanged calls this
+ // directly. This is a workaround for https://crbug.com/821607 where
+ // net::GetWifiSSID() call gets stuck.
+ void ContinueNetworkChanged(const std::string& network_id);
+
// Requests the secure proxy check URL. Upon completion, returns the results
// to the caller via the |fetcher_callback|. Virtualized for unit testing.
virtual void SecureProxyCheck(SecureProxyCheckerCallback fetcher_callback);
@@ -310,8 +320,8 @@ class DataReductionProxyConfig
// the use of secure proxies.
void HandleCaptivePortal();
- // Returns true if the current network has captive portal. Virtualized
- // for testing.
+ // Returns true if the current network has captive portal. Virtualized for
+ // testing.
virtual bool GetIsCaptivePortal() const;
// Fetches the warmup URL.
@@ -337,6 +347,9 @@ class DataReductionProxyConfig
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+ // Optional task runner for GetCurrentNetworkID.
+ scoped_refptr<base::SingleThreadTaskRunner> get_network_id_task_runner_;
+
// The caller must ensure that the |net_log_|, if set, outlives this instance.
// It is used to create new instances of |net_log_with_source_| on secure
// proxy checks. |net_log_with_source_| permits the correlation of the begin
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
index 55ffcb8f473..c8dacb91a9e 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
@@ -25,11 +25,11 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_creator.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
#include "components/variations/net/variations_http_headers.h"
@@ -37,12 +37,12 @@
#include "net/base/load_flags.h"
#include "net/base/load_timing_info.h"
#include "net/base/net_errors.h"
+#include "net/base/proxy_server.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/log/net_log_source_type.h"
-#include "net/proxy/proxy_server.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_status.h"
@@ -99,7 +99,9 @@ std::vector<DataReductionProxyServer> GetProxiesForHTTP(
proxies.push_back(DataReductionProxyServer(
net::ProxyServer(
protobuf_parser::SchemeFromProxyScheme(server.scheme()),
- net::HostPortPair(server.host(), server.port())),
+ net::HostPortPair(server.host(), server.port()),
+ /* HTTPS proxies are marked as trusted. */
+ server.scheme() == ProxyServer_ProxyScheme_HTTPS),
server.type()));
}
}
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
index e4867634593..a3101975743 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
@@ -18,6 +18,7 @@
#include "base/run_loop.h"
#include "base/test/histogram_tester.h"
#include "base/test/mock_entropy_provider.h"
+#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
@@ -32,9 +33,9 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "net/base/network_change_notifier.h"
+#include "net/base/proxy_server.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
-#include "net/proxy/proxy_server.h"
#include "net/socket/socket_test_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_context_storage.h"
@@ -448,10 +449,6 @@ class DataReductionProxyConfigServiceClientTest : public testing::Test {
return half_reporting_fraction_encoded_config_;
}
- bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) const {
- return delegate_->IsTrustedSpdyProxy(proxy_server);
- }
-
const std::string& loaded_config() const { return loaded_config_; }
net::TestURLRequestContext* test_url_request_context() const {
@@ -552,12 +549,12 @@ TEST_F(DataReductionProxyConfigServiceClientTest, RemoteConfigSuccess) {
Init(true);
AddMockSuccess();
SetDataReductionProxyEnabled(true, true);
- EXPECT_FALSE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_TRUE(configurator()->GetProxyConfig().proxy_rules().empty());
EXPECT_EQ(std::vector<net::ProxyServer>(), GetConfiguredProxiesForHttp());
config_client()->RetrieveConfig();
RunUntilIdle();
VerifyRemoteSuccess(true);
- EXPECT_TRUE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_FALSE(configurator()->GetProxyConfig().proxy_rules().empty());
#if defined(OS_ANDROID)
EXPECT_FALSE(config_client()->foreground_fetch_pending());
#endif
@@ -606,7 +603,8 @@ TEST_F(DataReductionProxyConfigServiceClientTest,
// Secure check failed.
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- NetworkPropertiesManager manager(&test_prefs,
+ NetworkPropertiesManager manager(base::DefaultClock::GetInstance(),
+ &test_prefs,
base::ThreadTaskRunnerHandle::Get());
manager.SetIsSecureProxyDisallowedByCarrier(true);
configurator()->Enable(manager, http_proxies);
@@ -745,7 +743,8 @@ TEST_F(DataReductionProxyConfigServiceClientTest,
// Secure check failed.
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- NetworkPropertiesManager manager(&test_prefs,
+ NetworkPropertiesManager manager(base::DefaultClock::GetInstance(),
+ &test_prefs,
base::ThreadTaskRunnerHandle::Get());
manager.SetIsSecureProxyDisallowedByCarrier(true);
configurator()->Enable(manager, http_proxies);
@@ -794,14 +793,14 @@ TEST_F(DataReductionProxyConfigServiceClientTest, AuthFailure) {
AddMockPreviousSuccess();
SetDataReductionProxyEnabled(true, true);
- EXPECT_FALSE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_TRUE(configurator()->GetProxyConfig().proxy_rules().empty());
histogram_tester.ExpectTotalCount(
"DataReductionProxy.ConfigService.AuthExpired", 0);
config_client()->RetrieveConfig();
RunUntilIdle();
// First remote config should be fetched.
VerifyRemoteSuccessWithOldConfig();
- EXPECT_TRUE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_FALSE(configurator()->GetProxyConfig().proxy_rules().empty());
EXPECT_EQ(kOldSuccessSessionKey, request_options()->GetSecureSession());
EXPECT_EQ(0, config_client()->GetBackoffErrorCount());
histogram_tester.ExpectUniqueSample(
@@ -821,7 +820,7 @@ TEST_F(DataReductionProxyConfigServiceClientTest, AuthFailure) {
EXPECT_TRUE(config_client()->ShouldRetryDueToAuthFailure(
request_headers, parsed.get(), origin, load_timing_info));
EXPECT_EQ(1, config_client()->GetBackoffErrorCount());
- EXPECT_FALSE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_TRUE(configurator()->GetProxyConfig().proxy_rules().empty());
// Persisted config on pref should be cleared.
EXPECT_TRUE(persisted_config().empty());
@@ -951,14 +950,14 @@ TEST_F(DataReductionProxyConfigServiceClientTest, MultipleAuthFailures) {
AddMockSuccess();
SetDataReductionProxyEnabled(true, true);
- EXPECT_FALSE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_TRUE(configurator()->GetProxyConfig().proxy_rules().empty());
histogram_tester.ExpectTotalCount(
"DataReductionProxy.ConfigService.AuthExpired", 0);
config_client()->RetrieveConfig();
RunUntilIdle();
// First remote config should be fetched.
VerifyRemoteSuccessWithOldConfig();
- EXPECT_TRUE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_FALSE(configurator()->GetProxyConfig().proxy_rules().empty());
EXPECT_EQ(kOldSuccessSessionKey, request_options()->GetSecureSession());
EXPECT_EQ(0, config_client()->GetBackoffErrorCount());
histogram_tester.ExpectUniqueSample(
@@ -978,7 +977,7 @@ TEST_F(DataReductionProxyConfigServiceClientTest, MultipleAuthFailures) {
EXPECT_TRUE(config_client()->ShouldRetryDueToAuthFailure(
request_headers, parsed.get(), origin, load_timing_info));
EXPECT_EQ(1, config_client()->GetBackoffErrorCount());
- EXPECT_FALSE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_TRUE(configurator()->GetProxyConfig().proxy_rules().empty());
// Persisted config on pref should be cleared.
EXPECT_TRUE(persisted_config().empty());
@@ -1050,7 +1049,7 @@ TEST_F(DataReductionProxyConfigServiceClientTest,
AddMockSuccess();
SetDataReductionProxyEnabled(true, true);
- EXPECT_FALSE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_TRUE(configurator()->GetProxyConfig().proxy_rules().empty());
histogram_tester.ExpectTotalCount(
"DataReductionProxy.ConfigService.AuthExpired", 0);
config_client()->RetrieveConfig();
@@ -1058,7 +1057,7 @@ TEST_F(DataReductionProxyConfigServiceClientTest,
RunUntilIdle();
// First remote config should be fetched.
VerifyRemoteSuccessWithOldConfig();
- EXPECT_TRUE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_FALSE(configurator()->GetProxyConfig().proxy_rules().empty());
EXPECT_EQ(kOldSuccessSessionKey, request_options()->GetSecureSession());
EXPECT_EQ(0, config_client()->GetBackoffErrorCount());
histogram_tester.ExpectUniqueSample(
@@ -1069,7 +1068,7 @@ TEST_F(DataReductionProxyConfigServiceClientTest,
AddMockPreviousSuccess();
SetDataReductionProxyEnabled(true, true);
- EXPECT_TRUE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_FALSE(configurator()->GetProxyConfig().proxy_rules().empty());
config_client()->RetrieveConfig();
// Trigger an auth failure.
@@ -1086,7 +1085,7 @@ TEST_F(DataReductionProxyConfigServiceClientTest,
EXPECT_TRUE(config_client()->ShouldRetryDueToAuthFailure(
request_headers, parsed.get(), origin, load_timing_info));
EXPECT_EQ(1, config_client()->GetBackoffErrorCount());
- EXPECT_FALSE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_TRUE(configurator()->GetProxyConfig().proxy_rules().empty());
// Persisted config on pref should be cleared.
EXPECT_TRUE(persisted_config().empty());
@@ -1095,7 +1094,7 @@ TEST_F(DataReductionProxyConfigServiceClientTest,
histogram_tester.ExpectBucketCount(
"DataReductionProxy.ConfigService.AuthExpired", true, 1);
- EXPECT_FALSE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_TRUE(configurator()->GetProxyConfig().proxy_rules().empty());
// Persisted config on pref should be cleared.
EXPECT_TRUE(persisted_config().empty());
@@ -1103,7 +1102,7 @@ TEST_F(DataReductionProxyConfigServiceClientTest,
RunUntilIdle();
VerifyRemoteSuccess(true);
- EXPECT_TRUE(configurator()->GetProxyConfig().is_valid());
+ EXPECT_FALSE(configurator()->GetProxyConfig().proxy_rules().empty());
// Persisted config on pref should be cleared.
EXPECT_FALSE(persisted_config().empty());
EXPECT_FALSE(persisted_config_retrieval_time().is_null());
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h
index e3142c18d04..84f15f89587 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h
@@ -22,7 +22,6 @@ class TickClock;
namespace net {
class NetLog;
-class ProxyServer;
}
namespace data_reduction_proxy {
@@ -167,29 +166,13 @@ class MockDataReductionProxyConfig : public TestDataReductionProxyConfig {
DataReductionProxyEventCreator* event_creator);
~MockDataReductionProxyConfig();
- MOCK_METHOD2(SetProxyPrefs, void(bool enabled, bool at_startup));
- MOCK_CONST_METHOD2(IsDataReductionProxy,
- bool(const net::ProxyServer& proxy_server,
- DataReductionProxyTypeInfo* proxy_info));
MOCK_CONST_METHOD2(WasDataReductionProxyUsed,
bool(const net::URLRequest*,
DataReductionProxyTypeInfo* proxy_info));
MOCK_CONST_METHOD1(ContainsDataReductionProxy,
bool(const net::ProxyConfig::ProxyRules& proxy_rules));
- MOCK_CONST_METHOD2(IsBypassedByDataReductionProxyLocalRules,
- bool(const net::URLRequest& request,
- const net::ProxyConfig& data_reduction_proxy_config));
- MOCK_CONST_METHOD3(AreDataReductionProxiesBypassed,
- bool(const net::URLRequest& request,
- const net::ProxyConfig& data_reduction_proxy_config,
- base::TimeDelta* min_retry_delay));
MOCK_METHOD1(SecureProxyCheck,
void(SecureProxyCheckerCallback fetcher_callback));
-
- using DataReductionProxyConfig::UpdateConfigForTesting;
-
- // Resets the Lo-Fi status to default state.
- void ResetLoFiStatusForTest();
};
} // namespace data_reduction_proxy
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
index 3e40a190817..ff82e5a53e9 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
@@ -28,6 +28,7 @@
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/platform_thread.h"
+#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
@@ -41,18 +42,17 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
-#include "components/previews/core/previews_decider.h"
#include "components/previews/core/previews_experiments.h"
+#include "components/previews/core/test_previews_decider.h"
#include "components/variations/variations_associated_data.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/network_change_notifier.h"
+#include "net/base/proxy_server.h"
#include "net/http/http_status_code.h"
#include "net/log/test_net_log.h"
#include "net/nqe/effective_connection_type.h"
-#include "net/nqe/external_estimate_provider.h"
#include "net/nqe/network_quality_estimator_test_util.h"
-#include "net/proxy/proxy_server.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/test_url_fetcher_factory.h"
@@ -86,29 +86,6 @@ std::string GetRetryMapKeyFromOrigin(const std::string& origin) {
return origin;
}
-class TestPreviewsDecider : public previews::PreviewsDecider {
- public:
- TestPreviewsDecider(bool allow_previews) : allow_previews_(allow_previews) {}
- ~TestPreviewsDecider() override {}
-
- // previews::PreviewsDecider:
- bool ShouldAllowPreviewAtECT(
- const net::URLRequest& request,
- previews::PreviewsType type,
- net::EffectiveConnectionType effective_connection_type_threshold,
- const std::vector<std::string>& host_blacklist_from_server)
- const override {
- return allow_previews_;
- }
- bool ShouldAllowPreview(const net::URLRequest& request,
- previews::PreviewsType type) const override {
- return allow_previews_;
- }
-
- private:
- bool allow_previews_;
-};
-
} // namespace
class DataReductionProxyConfigTest : public testing::Test {
@@ -458,7 +435,8 @@ TEST_F(DataReductionProxyConfigTest, WarmupURL) {
event_creator());
NetworkPropertiesManager network_properties_manager(
- test_context_->pref_service(), test_context_->task_runner());
+ base::DefaultClock::GetInstance(), test_context_->pref_service(),
+ test_context_->task_runner());
config.InitializeOnIOThread(test_context_->request_context_getter(),
test_context_->request_context_getter(),
&network_properties_manager);
@@ -947,10 +925,12 @@ TEST_F(DataReductionProxyConfigTest, IsDataReductionProxyWithMutableConfig) {
}
}
-TEST_F(DataReductionProxyConfigTest, ShouldEnableServerPreviews) {
+TEST_F(DataReductionProxyConfigTest,
+ ShouldAcceptServerPreviewAllPreviewsDisabled) {
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(
- features::kDataReductionProxyDecidesTransform);
+ scoped_feature_list.InitFromCommandLine(
+ "DataReductionProxyDecidesTransform" /* enable_features */,
+ "Previews" /* disable_features */);
net::TestURLRequestContext context;
net::TestDelegate delegate;
@@ -958,12 +938,27 @@ TEST_F(DataReductionProxyConfigTest, ShouldEnableServerPreviews) {
GURL(), net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
request->SetLoadFlags(request->load_flags() |
net::LOAD_MAIN_FRAME_DEPRECATED);
- std::unique_ptr<TestPreviewsDecider> previews_decider =
- std::make_unique<TestPreviewsDecider>(true);
- EXPECT_TRUE(test_config()->ShouldAcceptServerPreview(
+ std::unique_ptr<previews::TestPreviewsDecider> previews_decider =
+ std::make_unique<previews::TestPreviewsDecider>(true);
+ EXPECT_FALSE(test_config()->ShouldAcceptServerPreview(
*request.get(), *previews_decider.get()));
+}
- previews_decider = std::make_unique<TestPreviewsDecider>(false);
+TEST_F(DataReductionProxyConfigTest,
+ ShouldAcceptServerPreviewServerPreviewsDisabled) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(
+ "Previews" /* enable_features */,
+ "DataReductionProxyDecidesTransform" /* disable_features */);
+
+ net::TestURLRequestContext context;
+ net::TestDelegate delegate;
+ std::unique_ptr<net::URLRequest> request = context.CreateRequest(
+ GURL(), net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
+ request->SetLoadFlags(request->load_flags() |
+ net::LOAD_MAIN_FRAME_DEPRECATED);
+ std::unique_ptr<previews::TestPreviewsDecider> previews_decider =
+ std::make_unique<previews::TestPreviewsDecider>(true);
EXPECT_FALSE(test_config()->ShouldAcceptServerPreview(
*request.get(), *previews_decider.get()));
}
@@ -971,8 +966,9 @@ TEST_F(DataReductionProxyConfigTest, ShouldEnableServerPreviews) {
TEST_F(DataReductionProxyConfigTest, ShouldAcceptServerPreview) {
// Turn on proxy-decides-transform feature to satisfy DCHECK.
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(
- features::kDataReductionProxyDecidesTransform);
+ scoped_feature_list.InitFromCommandLine(
+ "Previews,DataReductionProxyDecidesTransform" /* enable_features */,
+ std::string() /* disable_features */);
base::FieldTrialList field_trial_list(nullptr);
base::FieldTrialList::CreateFieldTrial(
"DataReductionProxyPreviewsBlackListTransition", "Enabled");
@@ -984,8 +980,8 @@ TEST_F(DataReductionProxyConfigTest, ShouldAcceptServerPreview) {
GURL(), net::IDLE, &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
request->SetLoadFlags(request->load_flags() |
net::LOAD_MAIN_FRAME_DEPRECATED);
- std::unique_ptr<TestPreviewsDecider> previews_decider =
- std::make_unique<TestPreviewsDecider>(true);
+ std::unique_ptr<previews::TestPreviewsDecider> previews_decider =
+ std::make_unique<previews::TestPreviewsDecider>(true);
// Verify true for no flags.
EXPECT_TRUE(test_config()->ShouldAcceptServerPreview(
@@ -993,13 +989,13 @@ TEST_F(DataReductionProxyConfigTest, ShouldAcceptServerPreview) {
// Verify PreviewsDecider check.
base::CommandLine::ForCurrentProcess()->InitFromArgv(0, nullptr);
- previews_decider = std::make_unique<TestPreviewsDecider>(false);
+ previews_decider = std::make_unique<previews::TestPreviewsDecider>(false);
EXPECT_FALSE(test_config()->ShouldAcceptServerPreview(
*request.get(), *previews_decider.get()));
histogram_tester.ExpectBucketCount(
"DataReductionProxy.Protocol.NotAcceptingTransform",
1 /* NOT_ACCEPTING_TRANSFORM_BLACKLISTED */, 1);
- previews_decider = std::make_unique<TestPreviewsDecider>(true);
+ previews_decider = std::make_unique<previews::TestPreviewsDecider>(true);
}
TEST_F(DataReductionProxyConfigTest, HandleWarmupFetcherResponse) {
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc
index 474ea797e35..93cd04c2522 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc
@@ -11,10 +11,10 @@
#include "base/strings/string_util.h"
#include "base/values.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/browser/network_properties_manager.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_creator.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
-#include "net/proxy/proxy_config.h"
+#include "net/proxy_resolution/proxy_config.h"
namespace data_reduction_proxy {
@@ -51,9 +51,9 @@ net::ProxyConfig DataReductionProxyConfigurator::CreateProxyConfig(
DCHECK(thread_checker_.CalledOnValidThread());
net::ProxyConfig config;
- DCHECK(!config.is_valid() && config.proxy_rules().proxies_for_http.IsEmpty());
+ DCHECK(config.proxy_rules().proxies_for_http.IsEmpty());
config.proxy_rules().type =
- net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
+ net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME;
for (const auto& http_proxy : proxies_for_http) {
// If the config is being generated for fetching the probe URL, then the
@@ -97,16 +97,11 @@ net::ProxyConfig DataReductionProxyConfigurator::CreateProxyConfig(
}
if (config.proxy_rules().proxies_for_http.IsEmpty()) {
- // Return an invalid net config so that data reduction proxy is not used.
- return config;
+ // Return a DIRECT net config so that data reduction proxy is not used.
+ return net::ProxyConfig::CreateDirect();
}
config.proxy_rules().bypass_rules = bypass_rules_;
- // The ID is set to a bogus value. It cannot be left uninitialized, else the
- // config will return invalid.
- net::ProxyConfig::ID unused_id = 1;
- config.set_id(unused_id);
-
return config;
}
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h
index 8ddf7f77e00..7a1a8dd4837 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h
@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
-#include "net/proxy/proxy_config.h"
+#include "net/proxy_resolution/proxy_config.h"
namespace net {
class NetLog;
@@ -71,8 +71,8 @@ class DataReductionProxyConfigurator {
net::ProxyBypassRules bypass_rules_;
// The Data Reduction Proxy's configuration. This contains the list of
- // acceptable data reduction proxies and bypass rules. It should be accessed
- // only on the IO thread.
+ // acceptable data reduction proxies and bypass rules, or DIRECT if DRP is not
+ // enabled. It should be accessed only on the IO thread.
net::ProxyConfig config_;
// Used for logging of network- and Data Reduction Proxy-related events.
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc
index aff0df53c45..ed03440f2db 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/test/scoped_task_environment.h"
+#include "base/time/default_clock.h"
#include "base/values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
#include "components/data_reduction_proxy/core/browser/network_properties_manager.h"
@@ -17,7 +18,7 @@
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
-#include "net/proxy/proxy_server.h"
+#include "net/base/proxy_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -28,7 +29,8 @@ class DataReductionProxyConfiguratorTest : public testing::Test {
void SetUp() override {
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
manager_.reset(new NetworkPropertiesManager(
- &test_prefs, base::ThreadTaskRunnerHandle::Get()));
+ base::DefaultClock::GetInstance(), &test_prefs,
+ base::ThreadTaskRunnerHandle::Get()));
manager_->OnChangeInNetworkID("test");
test_context_ = DataReductionProxyTestContext::Builder().Build();
@@ -75,7 +77,7 @@ class DataReductionProxyConfiguratorTest : public testing::Test {
const net::ProxyConfig::ProxyRules& rules =
config_->GetProxyConfig().proxy_rules();
ASSERT_EQ(expected_rules_type, rules.type);
- if (net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME ==
+ if (net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME ==
expected_rules_type) {
ASSERT_EQ(expected_http_proxies, rules.proxies_for_http.ToPacString());
ASSERT_EQ(std::string(), rules.proxies_for_https.ToPacString());
@@ -95,7 +97,7 @@ class DataReductionProxyConfiguratorTest : public testing::Test {
->CreateProxyConfig(probe_url_config, *manager_.get(), http_proxies)
.proxy_rules();
ASSERT_EQ(expected_rules_type, rules.type);
- if (net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME ==
+ if (net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME ==
expected_rules_type) {
ASSERT_EQ(expected_http_proxies, rules.proxies_for_http.ToPacString());
ASSERT_EQ(std::string(), rules.proxies_for_https.ToPacString());
@@ -114,7 +116,7 @@ TEST_F(DataReductionProxyConfiguratorTest, TestUnrestricted) {
config_->Enable(*manager_,
BuildProxyList("https://www.foo.com:443", ProxyServer::CORE,
"http://www.bar.com:80", ProxyServer::CORE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"HTTPS www.foo.com:443;PROXY www.bar.com:80;DIRECT",
std::string());
}
@@ -123,7 +125,7 @@ TEST_F(DataReductionProxyConfiguratorTest, TestUnrestrictedQuic) {
config_->Enable(*manager_,
BuildProxyList("quic://www.foo.com:443", ProxyServer::CORE,
"http://www.bar.com:80", ProxyServer::CORE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"QUIC www.foo.com:443;PROXY www.bar.com:80;DIRECT",
std::string());
}
@@ -133,7 +135,7 @@ TEST_F(DataReductionProxyConfiguratorTest, TestUnrestrictedWithBypassRule) {
config_->Enable(*manager_,
BuildProxyList("https://www.foo.com:443", ProxyServer::CORE,
"http://www.bar.com:80", ProxyServer::CORE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"HTTPS www.foo.com:443;PROXY www.bar.com:80;DIRECT",
"<local>;*.goo.com;");
}
@@ -143,7 +145,7 @@ TEST_F(DataReductionProxyConfiguratorTest, TestUnrestrictedWithBypassRuleQuic) {
config_->Enable(*manager_,
BuildProxyList("quic://www.foo.com:443", ProxyServer::CORE,
"http://www.bar.com:80", ProxyServer::CORE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"QUIC www.foo.com:443;PROXY www.bar.com:80;DIRECT",
"<local>;*.goo.com;");
}
@@ -152,7 +154,7 @@ TEST_F(DataReductionProxyConfiguratorTest, TestUnrestrictedWithoutFallback) {
config_->Enable(*manager_,
BuildProxyList("https://www.foo.com:443", ProxyServer::CORE,
std::string(), ProxyServer::CORE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"HTTPS www.foo.com:443;DIRECT", std::string());
}
@@ -161,7 +163,7 @@ TEST_F(DataReductionProxyConfiguratorTest,
config_->Enable(*manager_,
BuildProxyList("quic://www.foo.com:443", ProxyServer::CORE,
std::string(), ProxyServer::CORE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"QUIC www.foo.com:443;DIRECT", std::string());
}
@@ -170,7 +172,7 @@ TEST_F(DataReductionProxyConfiguratorTest, TestSecureRestrictedProxiesAreCore) {
config_->Enable(*manager_,
BuildProxyList("https://www.foo.com:443", ProxyServer::CORE,
"http://www.bar.com:80", ProxyServer::CORE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"PROXY www.bar.com:80;DIRECT", std::string());
}
@@ -179,7 +181,7 @@ TEST_F(DataReductionProxyConfiguratorTest, TestSecureNonCoreRestricted) {
config_->Enable(*manager_,
BuildProxyList("https://www.foo.com:443", ProxyServer::CORE,
"http://www.bar.com:80", ProxyServer::CORE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"HTTPS www.foo.com:443;PROXY www.bar.com:80;DIRECT",
std::string());
}
@@ -191,7 +193,7 @@ TEST_F(DataReductionProxyConfiguratorTest,
*manager_,
BuildProxyList("https://www.foo.com:443", ProxyServer::UNSPECIFIED_TYPE,
"http://www.bar.com:80", ProxyServer::UNSPECIFIED_TYPE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"HTTPS www.foo.com:443;PROXY www.bar.com:80;DIRECT",
std::string());
}
@@ -201,7 +203,7 @@ TEST_F(DataReductionProxyConfiguratorTest, TestInsecureCoreRestricted) {
config_->Enable(*manager_,
BuildProxyList("https://www.foo.com:443", ProxyServer::CORE,
"http://www.bar.com:80", ProxyServer::CORE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"HTTPS www.foo.com:443;DIRECT", std::string());
}
@@ -210,7 +212,7 @@ TEST_F(DataReductionProxyConfiguratorTest, TestInsecureNonCoreRestricted) {
config_->Enable(*manager_,
BuildProxyList("https://www.foo.com:443", ProxyServer::CORE,
"http://www.bar.com:80", ProxyServer::CORE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"HTTPS www.foo.com:443;PROXY www.bar.com:80;DIRECT",
std::string());
}
@@ -221,7 +223,7 @@ TEST_F(DataReductionProxyConfiguratorTest, TestSecureInsecureCoreRestricted) {
config_->Enable(*manager_,
BuildProxyList("https://www.foo.com:443", ProxyServer::CORE,
"http://www.bar.com:80", ProxyServer::CORE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, "",
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::EMPTY, "",
std::string());
}
@@ -230,7 +232,7 @@ TEST_F(DataReductionProxyConfiguratorTest, TestRestrictedQuic) {
config_->Enable(*manager_,
BuildProxyList("quic://www.foo.com:443", ProxyServer::CORE,
"http://www.bar.com:80", ProxyServer::CORE));
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"PROXY www.bar.com:80;DIRECT", std::string());
}
@@ -239,7 +241,7 @@ TEST_F(DataReductionProxyConfiguratorTest, TestDisable) {
BuildProxyList("https://www.foo.com:443", ProxyServer::CORE,
"http://www.bar.com:80", ProxyServer::CORE));
config_->Disable();
- CheckProxyConfig(net::ProxyConfig::ProxyRules::TYPE_NO_RULES, std::string(),
+ CheckProxyConfig(net::ProxyConfig::ProxyRules::Type::EMPTY, std::string(),
std::string());
}
@@ -263,11 +265,11 @@ TEST_F(DataReductionProxyConfiguratorTest,
"http://www.bar.com:80", ProxyServer::CORE);
config_->Enable(*manager_, http_proxies);
CheckProbeProxyConfig(http_proxies, true /* probe_url_config */,
- net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
+ net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
"HTTPS www.foo.com:443;PROXY www.bar.com:80;DIRECT",
std::string());
CheckProbeProxyConfig(http_proxies, false /* probe_url_config */,
- net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, "",
+ net::ProxyConfig::ProxyRules::Type::EMPTY, "",
std::string());
}
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc
index a8a3ff74dfc..53120a1828e 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc
@@ -11,7 +11,7 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/lofi_decider.h"
#include "components/data_use_measurement/core/data_use.h"
#include "components/data_use_measurement/core/data_use_ascriber.h"
@@ -109,15 +109,11 @@ void DataReductionProxyDataUseObserver::OnPageResourceLoad(
return;
int64_t network_bytes = request.GetTotalReceivedBytes();
- DataReductionProxyRequestType request_type = GetDataReductionProxyRequestType(
- request, data_reduction_proxy_io_data_->configurator()->GetProxyConfig(),
- *data_reduction_proxy_io_data_->config());
// Estimate how many bytes would have been used if the DataReductionProxy was
// not used, and record the data usage.
int64_t original_bytes = util::EstimateOriginalReceivedBytes(
- request, request_type == VIA_DATA_REDUCTION_PROXY,
- data_reduction_proxy_io_data_->lofi_decider());
+ request, data_reduction_proxy_io_data_->lofi_decider());
if (data_use->traffic_type() ==
data_use_measurement::DataUse::TrafficType::USER_TRAFFIC &&
@@ -158,19 +154,26 @@ void DataReductionProxyDataUseObserver::OnPageDidFinishLoad(
// Report estimated data savings for NOSCRIPT if applicable.
if (previews_user_data->committed_previews_type() ==
previews::PreviewsType::NOSCRIPT) {
- int inflated_bytes =
- (data_use->total_bytes_received() *
- previews::params::NoScriptPreviewsInflationPercent()) /
- 100 +
- previews::params::NoScriptPreviewsInflationBytes();
+ int inflation_percent =
+ previews::params::NoScriptPreviewsInflationPercent();
+ int inflation_bytes = previews::params::NoScriptPreviewsInflationBytes();
+ if (previews_user_data->data_savings_inflation_percent() != 0) {
+ // Use specific inflation percent rather than default.
+ inflation_percent =
+ previews_user_data->data_savings_inflation_percent();
+ inflation_bytes = 0;
+ }
+ int total_inflated_bytes =
+ (data_use->total_bytes_received() * inflation_percent) / 100 +
+ inflation_bytes;
// Report for overall usage.
DCHECK(data_use->url().SchemeIs(url::kHttpsScheme));
data_reduction_proxy_io_data_->UpdateContentLengths(
- 0, inflated_bytes, data_reduction_proxy_io_data_->IsEnabled(), HTTPS,
- std::string());
+ 0, total_inflated_bytes, data_reduction_proxy_io_data_->IsEnabled(),
+ HTTPS, std::string());
// Report for host usage.
data_reduction_proxy_io_data_->UpdateDataUseForHost(
- 0, inflated_bytes, data_use->url().HostNoBrackets());
+ 0, total_inflated_bytes, data_use->url().HostNoBrackets());
}
}
}
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer_unittest.cc
index df50e87162e..de037438c60 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer_unittest.cc
@@ -132,11 +132,35 @@ TEST_F(DataReductionProxyDataUseObserverTest,
previews_user_data.SetCommittedPreviewsType(previews::PreviewsType::NOSCRIPT);
SetPreviewsUserData(data_use.get(), &previews_user_data);
int inflation_value = 500000 * kInflationPercent / 100 + kInflationBytes;
+ EXPECT_EQ(251000, inflation_value);
EXPECT_CALL(*mock_drp_service(),
UpdateContentLengths(0, inflation_value, true, _, _))
.Times(1);
EXPECT_CALL(*mock_drp_service(),
- UpdateDataUseForHost(0, 251000, "testsite.com"))
+ UpdateDataUseForHost(0, inflation_value, "testsite.com"))
+ .Times(1);
+ DidFinishLoad(data_use.get());
+ RunUntilIdle();
+}
+
+TEST_F(DataReductionProxyDataUseObserverTest,
+ OnPageDidFinishLoadHasCommittedNoScriptPreviewWithInflationPercent) {
+ std::unique_ptr<data_use_measurement::DataUse> data_use =
+ std::make_unique<data_use_measurement::DataUse>(
+ data_use_measurement::DataUse::TrafficType::USER_TRAFFIC);
+ data_use->IncrementTotalBytes(500000, 300);
+ data_use->set_url(GURL("https://testsite.com"));
+ previews::PreviewsUserData previews_user_data(7 /* page_id */);
+ previews_user_data.SetDataSavingsInflationPercent(80);
+ previews_user_data.SetCommittedPreviewsType(previews::PreviewsType::NOSCRIPT);
+ SetPreviewsUserData(data_use.get(), &previews_user_data);
+ int inflation_value = 500000 * 80 / 100;
+ EXPECT_EQ(400000, inflation_value);
+ EXPECT_CALL(*mock_drp_service(),
+ UpdateContentLengths(0, inflation_value, true, _, _))
+ .Times(1);
+ EXPECT_CALL(*mock_drp_service(),
+ UpdateDataUseForHost(0, inflation_value, "testsite.com"))
.Times(1);
DidFinishLoad(data_use.get());
RunUntilIdle();
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
index 9563aba800a..5bb99b80c8f 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
@@ -15,16 +15,16 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_creator.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
#include "net/base/host_port_pair.h"
+#include "net/base/proxy_server.h"
#include "net/base/url_util.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
-#include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_server.h"
+#include "net/proxy_resolution/proxy_info.h"
namespace data_reduction_proxy {
@@ -32,52 +32,6 @@ namespace {
static const char kDataReductionCoreProxy[] = "proxy.googlezip.net";
-// Adds data reduction proxies to |result|, where applicable, if result
-// otherwise uses a direct connection for |url|, and the data reduction proxy is
-// not bypassed. Also, configures |result| to proceed directly to the origin if
-// |result|'s current proxy is the data reduction proxy.
-void OnResolveProxyHandler(
- const GURL& url,
- const std::string& method,
- const net::ProxyConfig& proxy_config,
- const net::ProxyRetryInfoMap& proxy_retry_info,
- const DataReductionProxyConfig& data_reduction_proxy_config,
- DataReductionProxyIOData* io_data,
- net::ProxyInfo* result) {
- DCHECK(result->is_empty() || result->is_direct() ||
- !data_reduction_proxy_config.IsDataReductionProxy(
- result->proxy_server(), nullptr));
-
- if (!util::EligibleForDataReductionProxy(*result, url, method))
- return;
-
- net::ProxyInfo data_reduction_proxy_info;
- bool data_saver_proxy_used = util::ApplyProxyConfigToProxyInfo(
- proxy_config, proxy_retry_info, url, &data_reduction_proxy_info);
- if (data_saver_proxy_used)
- result->OverrideProxyList(data_reduction_proxy_info.proxy_list());
-
- if (io_data && io_data->resource_type_provider()) {
- ResourceTypeProvider::ContentType content_type =
- io_data->resource_type_provider()->GetContentType(url);
- DCHECK_GT(ResourceTypeProvider::CONTENT_TYPE_MAX, content_type);
- UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.ResourceContentType",
- content_type,
- ResourceTypeProvider::CONTENT_TYPE_MAX);
- }
-
- // The |proxy_config| must be valid otherwise the proxy cannot be used.
- DCHECK(proxy_config.is_valid() || !data_saver_proxy_used);
-
- if (data_reduction_proxy_config.enabled_by_user_and_reachable() &&
- url.SchemeIs(url::kHttpScheme) && !net::IsLocalhost(url) &&
- !params::IsIncludedInHoldbackFieldTrial()) {
- UMA_HISTOGRAM_BOOLEAN(
- "DataReductionProxy.ConfigService.HTTPRequests",
- !data_reduction_proxy_config.GetProxiesForHttp().empty());
- }
-}
-
} // namespace
DataReductionProxyDelegate::DataReductionProxyDelegate(
@@ -90,7 +44,6 @@ DataReductionProxyDelegate::DataReductionProxyDelegate(
configurator_(configurator),
event_creator_(event_creator),
bypass_stats_(bypass_stats),
- alternative_proxies_broken_(false),
tick_clock_(base::DefaultTickClock::GetInstance()),
first_data_saver_request_recorded_(false),
io_data_(nullptr),
@@ -122,15 +75,21 @@ void DataReductionProxyDelegate::OnResolveProxy(
const std::string& method,
const net::ProxyRetryInfoMap& proxy_retry_info,
net::ProxyInfo* result) {
- DCHECK(result);
DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(result);
+ DCHECK(result->is_empty() || result->is_direct() ||
+ !config_->IsDataReductionProxy(result->proxy_server(), nullptr));
+
+ if (!params::IsIncludedInQuicFieldTrial())
+ RecordQuicProxyStatus(QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL);
+
+ if (!util::EligibleForDataReductionProxy(*result, url, method))
+ return;
ResourceTypeProvider::ContentType content_type =
ResourceTypeProvider::CONTENT_TYPE_UNKNOWN;
-
- if (io_data_ && io_data_->resource_type_provider()) {
+ if (io_data_ && io_data_->resource_type_provider())
content_type = io_data_->resource_type_provider()->GetContentType(url);
- }
std::vector<DataReductionProxyServer> proxies_for_http =
params::IsIncludedInHoldbackFieldTrial()
@@ -176,21 +135,33 @@ void DataReductionProxyDelegate::OnResolveProxy(
net::ProxyConfig proxy_config = configurator_->CreateProxyConfig(
is_warmup_url, config_->GetNetworkPropertiesManager(), proxies_for_http);
- OnResolveProxyHandler(url, method, proxy_config, proxy_retry_info, *config_,
- io_data_, result);
+ net::ProxyInfo data_reduction_proxy_info;
+ if (util::ApplyProxyConfigToProxyInfo(proxy_config, proxy_retry_info, url,
+ &data_reduction_proxy_info)) {
+ DCHECK(!data_reduction_proxy_info.is_empty() &&
+ !data_reduction_proxy_info.is_direct());
+ result->OverrideProxyList(data_reduction_proxy_info.proxy_list());
+
+ GetAlternativeProxy(url, proxy_retry_info, result);
- if (!result->is_empty()) {
- net::ProxyServer alternative_proxy_server;
- GetAlternativeProxy(url, result->proxy_server(), &alternative_proxy_server);
- result->SetAlternativeProxy(alternative_proxy_server);
+ if (!first_data_saver_request_recorded_) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "DataReductionProxy.TimeToFirstDataSaverRequest",
+ tick_clock_->NowTicks() - last_network_change_time_);
+ first_data_saver_request_recorded_ = true;
+ }
}
- if (!first_data_saver_request_recorded_ && !result->is_empty() &&
- config_->IsDataReductionProxy(result->proxy_server(), nullptr)) {
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "DataReductionProxy.TimeToFirstDataSaverRequest",
- tick_clock_->NowTicks() - last_network_change_time_);
- first_data_saver_request_recorded_ = true;
+ DCHECK_GT(ResourceTypeProvider::CONTENT_TYPE_MAX, content_type);
+ UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.ResourceContentType",
+ content_type,
+ ResourceTypeProvider::CONTENT_TYPE_MAX);
+
+ if (config_->enabled_by_user_and_reachable() &&
+ url.SchemeIs(url::kHttpScheme) && !net::IsLocalhost(url) &&
+ !params::IsIncludedInHoldbackFieldTrial()) {
+ UMA_HISTOGRAM_BOOLEAN("DataReductionProxy.ConfigService.HTTPRequests",
+ !config_->GetProxiesForHttp().empty());
}
}
@@ -207,13 +178,6 @@ void DataReductionProxyDelegate::OnFallback(const net::ProxyServer& bad_proxy,
bypass_stats_->OnProxyFallback(bad_proxy, net_error);
}
-bool DataReductionProxyDelegate::IsTrustedSpdyProxy(
- const net::ProxyServer& proxy_server) {
- DCHECK(thread_checker_.CalledOnValidThread());
- return proxy_server.is_valid() && proxy_server.is_https() && config_ &&
- config_->IsDataReductionProxy(proxy_server, nullptr);
-}
-
void DataReductionProxyDelegate::SetTickClockForTesting(
base::TickClock* tick_clock) {
tick_clock_ = tick_clock;
@@ -224,10 +188,13 @@ void DataReductionProxyDelegate::SetTickClockForTesting(
void DataReductionProxyDelegate::GetAlternativeProxy(
const GURL& url,
- const net::ProxyServer& resolved_proxy_server,
- net::ProxyServer* alternative_proxy_server) const {
+ const net::ProxyRetryInfoMap& proxy_retry_info,
+ net::ProxyInfo* result) const {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!alternative_proxy_server->is_valid());
+
+ net::ProxyServer resolved_proxy_server = result->proxy_server();
+ DCHECK(resolved_proxy_server.is_valid());
+ DCHECK(config_->IsDataReductionProxy(resolved_proxy_server, nullptr));
if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS() ||
url.SchemeIsCryptographic()) {
@@ -235,46 +202,30 @@ void DataReductionProxyDelegate::GetAlternativeProxy(
}
if (!params::IsIncludedInQuicFieldTrial()) {
- RecordQuicProxyStatus(QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL);
+ // RecordQuicProxyStatus already called by OnResolveProxy.
return;
}
- if (!resolved_proxy_server.is_valid() || !resolved_proxy_server.is_https())
+ if (!resolved_proxy_server.is_https())
return;
- if (!config_ ||
- !config_->IsDataReductionProxy(resolved_proxy_server, nullptr)) {
+ if (!SupportsQUIC(resolved_proxy_server)) {
+ RecordQuicProxyStatus(QUIC_PROXY_NOT_SUPPORTED);
return;
}
- if (alternative_proxies_broken_) {
- RecordQuicProxyStatus(QUIC_PROXY_STATUS_MARKED_AS_BROKEN);
- return;
- }
+ net::ProxyInfo alternative_proxy_info;
+ alternative_proxy_info.UseProxyServer(net::ProxyServer(
+ net::ProxyServer::SCHEME_QUIC, resolved_proxy_server.host_port_pair()));
+ alternative_proxy_info.DeprioritizeBadProxies(proxy_retry_info);
- if (!SupportsQUIC(resolved_proxy_server)) {
- RecordQuicProxyStatus(QUIC_PROXY_NOT_SUPPORTED);
+ if (alternative_proxy_info.is_empty()) {
+ RecordQuicProxyStatus(QUIC_PROXY_STATUS_MARKED_AS_BROKEN);
return;
}
- *alternative_proxy_server = net::ProxyServer(
- net::ProxyServer::SCHEME_QUIC, resolved_proxy_server.host_port_pair());
- DCHECK(alternative_proxy_server->is_valid());
RecordQuicProxyStatus(QUIC_PROXY_STATUS_AVAILABLE);
- return;
-}
-
-void DataReductionProxyDelegate::OnAlternativeProxyBroken(
- const net::ProxyServer& alternative_proxy_server) {
- DCHECK(thread_checker_.CalledOnValidThread());
- // TODO(tbansal): Reset this on connection change events.
- // Currently, DataReductionProxyDelegate does not maintain a list of broken
- // proxies. If one alternative proxy is broken, use of all alternative proxies
- // is disabled because it is likely that other QUIC proxies would be
- // broken too.
- alternative_proxies_broken_ = true;
- UMA_HISTOGRAM_COUNTS_100("DataReductionProxy.Quic.OnAlternativeProxyBroken",
- 1);
+ result->SetAlternativeProxy(alternative_proxy_info.proxy_server());
}
bool DataReductionProxyDelegate::SupportsQUIC(
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h
index 78cddc6e9c7..f5adf5c608c 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h
@@ -11,7 +11,7 @@
#include "base/threading/thread_checker.h"
#include "net/base/network_change_notifier.h"
#include "net/base/proxy_delegate.h"
-#include "net/proxy/proxy_retry_info.h"
+#include "net/proxy_resolution/proxy_retry_info.h"
#include "url/gurl.h"
namespace base {
@@ -55,16 +55,10 @@ class DataReductionProxyDelegate
const net::ProxyRetryInfoMap& proxy_retry_info,
net::ProxyInfo* result) override;
void OnFallback(const net::ProxyServer& bad_proxy, int net_error) override;
- bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override;
void SetTickClockForTesting(base::TickClock* tick_clock);
protected:
- // Protected so that this method is accessible for testing.
- // net::ProxyDelegate implementation:
- void OnAlternativeProxyBroken(
- const net::ProxyServer& alternative_proxy_server) override;
-
// Protected so that it can be overridden during testing.
// Returns true if |proxy_server| supports QUIC.
virtual bool SupportsQUIC(const net::ProxyServer& proxy_server) const;
@@ -86,18 +80,17 @@ class DataReductionProxyDelegate
// NetworkChangeNotifier::IPAddressObserver:
void OnIPAddressChanged() override;
+ // Checks if the first proxy server in |result| supports QUIC and if so
+ // adds an alternative proxy configuration to |result|.
void GetAlternativeProxy(const GURL& url,
- const net::ProxyServer& resolved_proxy_server,
- net::ProxyServer* alternative_proxy_server) const;
+ const net::ProxyRetryInfoMap& proxy_retry_info,
+ net::ProxyInfo* result) const;
const DataReductionProxyConfig* config_;
const DataReductionProxyConfigurator* configurator_;
DataReductionProxyEventCreator* event_creator_;
DataReductionProxyBypassStats* bypass_stats_;
- // True if the use of alternate proxies is disabled.
- bool alternative_proxies_broken_;
-
// Tick clock used for obtaining the current time.
base::TickClock* tick_clock_;
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
index dc519c3f744..2b6444db90e 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
@@ -43,11 +43,11 @@
#include "net/base/net_errors.h"
#include "net/base/network_change_notifier.h"
#include "net/base/proxy_delegate.h"
+#include "net/base/proxy_server.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
-#include "net/proxy/proxy_config.h"
-#include "net/proxy/proxy_server.h"
+#include "net/proxy_resolution/proxy_config.h"
#include "net/socket/socket_test_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
@@ -130,7 +130,6 @@ class TestDataReductionProxyDelegate : public DataReductionProxyDelegate {
}
}
- using DataReductionProxyDelegate::OnAlternativeProxyBroken;
using DataReductionProxyDelegate::QuicProxyStatus;
private:
@@ -139,81 +138,6 @@ class TestDataReductionProxyDelegate : public DataReductionProxyDelegate {
DISALLOW_COPY_AND_ASSIGN(TestDataReductionProxyDelegate);
};
-// Tests that the trusted SPDY proxy is verified correctly.
-TEST(DataReductionProxyDelegate, IsTrustedSpdyProxy) {
- base::MessageLoopForIO message_loop_;
- std::unique_ptr<DataReductionProxyTestContext> test_context =
- DataReductionProxyTestContext::Builder()
- .WithConfigClient()
- .WithMockDataReductionProxyService()
- .Build();
-
- const struct {
- net::ProxyServer::Scheme first_proxy_scheme;
- net::ProxyServer::Scheme second_proxy_scheme;
- bool expect_proxy_is_trusted;
- } test_cases[] = {
- {net::ProxyServer::SCHEME_HTTP, net::ProxyServer::SCHEME_INVALID, false},
- {net::ProxyServer::SCHEME_QUIC, net::ProxyServer::SCHEME_INVALID, false},
- {net::ProxyServer::SCHEME_HTTP, net::ProxyServer::SCHEME_HTTP, false},
- {net::ProxyServer::SCHEME_INVALID, net::ProxyServer::SCHEME_INVALID,
- false},
- // First proxy is HTTPS, and second is invalid.
- {net::ProxyServer::SCHEME_HTTPS, net::ProxyServer::SCHEME_INVALID, true},
- // First proxy is invalid, and second proxy is HTTPS.
- {net::ProxyServer::SCHEME_INVALID, net::ProxyServer::SCHEME_HTTPS, true},
- // First proxy is HTTPS, and second is HTTP.
- {net::ProxyServer::SCHEME_HTTPS, net::ProxyServer::SCHEME_HTTPS, true},
- // Second proxy is HTTPS, and first is HTTP.
- {net::ProxyServer::SCHEME_HTTP, net::ProxyServer::SCHEME_HTTPS, true},
- {net::ProxyServer::SCHEME_QUIC, net::ProxyServer::SCHEME_INVALID, false},
- {net::ProxyServer::SCHEME_QUIC, net::ProxyServer::SCHEME_HTTP, false},
- {net::ProxyServer::SCHEME_QUIC, net::ProxyServer::SCHEME_HTTPS, true},
- };
- for (const auto& test : test_cases) {
- ASSERT_EQ(test.expect_proxy_is_trusted,
- (test.first_proxy_scheme == net::ProxyServer::SCHEME_HTTPS ||
- test.second_proxy_scheme == net::ProxyServer::SCHEME_HTTPS))
- << (&test - test_cases);
-
- std::vector<DataReductionProxyServer> proxies_for_http;
- net::ProxyServer first_proxy;
- net::ProxyServer second_proxy;
- if (test.first_proxy_scheme != net::ProxyServer::SCHEME_INVALID) {
- first_proxy = GetProxyWithScheme(test.first_proxy_scheme);
- proxies_for_http.push_back(
- DataReductionProxyServer(first_proxy, ProxyServer::CORE));
- }
- if (test.second_proxy_scheme != net::ProxyServer::SCHEME_INVALID) {
- second_proxy = GetProxyWithScheme(test.second_proxy_scheme);
- proxies_for_http.push_back(DataReductionProxyServer(
- second_proxy, ProxyServer::UNSPECIFIED_TYPE));
- }
-
- std::unique_ptr<DataReductionProxyMutableConfigValues> config_values =
- std::make_unique<DataReductionProxyMutableConfigValues>();
- config_values->UpdateValues(proxies_for_http);
-
- std::unique_ptr<DataReductionProxyConfig> config(
- new DataReductionProxyConfig(
- message_loop_.task_runner(), test_context->net_log(),
- std::move(config_values), test_context->configurator(),
- test_context->event_creator()));
-
- DataReductionProxyDelegate delegate(
- config.get(), test_context->io_data()->configurator(),
- test_context->io_data()->event_creator(),
- test_context->io_data()->bypass_stats(),
- test_context->io_data()->net_log());
-
- base::FieldTrialList field_trial_list(nullptr);
- EXPECT_EQ(test.expect_proxy_is_trusted,
- delegate.IsTrustedSpdyProxy(first_proxy) ||
- delegate.IsTrustedSpdyProxy(second_proxy))
- << (&test - test_cases);
- }
-}
-
#if defined(OS_ANDROID)
const Client kClient = Client::CHROME_ANDROID;
#elif defined(OS_IOS)
@@ -403,21 +327,16 @@ TEST_F(DataReductionProxyDelegateTest, OnResolveProxy) {
// afterwards.
// Another proxy is used. It should be used afterwards.
result.Use(direct_proxy_info);
- net::ProxyConfig::ID prev_id = result.config_id();
proxy_delegate()->OnResolveProxy(url, "GET", empty_proxy_retry_info, &result);
EXPECT_EQ(params()->proxies_for_http().front().proxy_server(),
result.proxy_server());
- // Only the proxy list should be updated, not the proxy info.
- EXPECT_EQ(result.config_id(), prev_id);
// A direct connection is used, but the data reduction proxy is on the retry
// list. A direct connection should be used afterwards.
result.Use(direct_proxy_info);
- prev_id = result.config_id();
proxy_delegate()->OnResolveProxy(GURL("ws://echo.websocket.org/"), "GET",
data_reduction_proxy_retry_info, &result);
EXPECT_TRUE(result.proxy_server().is_direct());
- EXPECT_EQ(result.config_id(), prev_id);
// Test that ws:// and wss:// URLs bypass the data reduction proxy.
result.UseDirect();
@@ -498,7 +417,6 @@ TEST_F(DataReductionProxyDelegateTest, OnResolveProxyWarmupURL) {
// A direct connection is used. The data reduction proxy should be used
// afterwards.
result.Use(direct_proxy_info);
- net::ProxyConfig::ID prev_id = result.config_id();
proxy_delegate()->OnResolveProxy(url, "GET", empty_proxy_retry_info,
&result);
//
@@ -508,8 +426,6 @@ TEST_F(DataReductionProxyDelegateTest, OnResolveProxyWarmupURL) {
} else {
EXPECT_TRUE(result.proxy_server().is_direct());
}
- // Only the proxy list should be updated, not the proxy info.
- EXPECT_EQ(result.config_id(), prev_id);
}
}
@@ -519,30 +435,30 @@ TEST_F(DataReductionProxyDelegateTest, AlternativeProxy) {
const struct {
bool is_in_quic_field_trial;
bool proxy_supports_quic;
- GURL gurl;
net::ProxyServer::Scheme first_proxy_scheme;
net::ProxyServer::Scheme second_proxy_scheme;
- } tests[] = {{false, true, GURL("http://www.example.com"),
- net::ProxyServer::SCHEME_HTTPS, net::ProxyServer::SCHEME_HTTP},
- {true, true, GURL("http://www.example.com"),
- net::ProxyServer::SCHEME_HTTPS, net::ProxyServer::SCHEME_HTTP},
- {true, true, GURL("http://www.example.com"),
- net::ProxyServer::SCHEME_HTTP, net::ProxyServer::SCHEME_HTTPS},
- {true, true, GURL("http://www.example.com"),
- net::ProxyServer::SCHEME_QUIC, net::ProxyServer::SCHEME_HTTP},
- {true, true, GURL("http://www.example.com"),
- net::ProxyServer::SCHEME_QUIC, net::ProxyServer::SCHEME_HTTPS},
- {true, false, GURL("http://www.example.com"),
- net::ProxyServer::SCHEME_HTTPS, net::ProxyServer::SCHEME_HTTP},
- {true, false, GURL("http://www.example.com"),
- net::ProxyServer::SCHEME_HTTP, net::ProxyServer::SCHEME_HTTPS}};
+ } tests[] = {{false, true, net::ProxyServer::SCHEME_HTTPS,
+ net::ProxyServer::SCHEME_HTTP},
+ {true, true, net::ProxyServer::SCHEME_HTTPS,
+ net::ProxyServer::SCHEME_HTTP},
+ {true, true, net::ProxyServer::SCHEME_HTTP,
+ net::ProxyServer::SCHEME_HTTPS},
+ {true, true, net::ProxyServer::SCHEME_QUIC,
+ net::ProxyServer::SCHEME_HTTP},
+ {true, true, net::ProxyServer::SCHEME_QUIC,
+ net::ProxyServer::SCHEME_HTTPS},
+ {true, false, net::ProxyServer::SCHEME_HTTPS,
+ net::ProxyServer::SCHEME_HTTP},
+ {true, false, net::ProxyServer::SCHEME_HTTP,
+ net::ProxyServer::SCHEME_HTTPS}};
+ GURL url("http://www.example.com");
+
for (const auto test : tests) {
// True if there should exist a valid alternative proxy server corresponding
// to the first proxy in the list of proxies available to the data reduction
// proxy.
const bool expect_alternative_proxy_server_to_first_proxy =
test.is_in_quic_field_trial && test.proxy_supports_quic &&
- !test.gurl.SchemeIsCryptographic() &&
test.first_proxy_scheme == net::ProxyServer::SCHEME_HTTPS;
// True if there should exist a valid alternative proxy server corresponding
@@ -550,7 +466,6 @@ TEST_F(DataReductionProxyDelegateTest, AlternativeProxy) {
// reduction proxy.
const bool expect_alternative_proxy_server_to_second_proxy =
test.is_in_quic_field_trial && test.proxy_supports_quic &&
- !test.gurl.SchemeIsCryptographic() &&
test.second_proxy_scheme == net::ProxyServer::SCHEME_HTTPS;
std::vector<DataReductionProxyServer> proxies_for_http;
@@ -587,22 +502,20 @@ TEST_F(DataReductionProxyDelegateTest, AlternativeProxy) {
// Test if the alternative proxy is correctly set if the resolved proxy is
// |first_proxy|.
base::HistogramTester histogram_tester;
- delegate.OnResolveProxy(test.gurl, "GET", empty_proxy_retry_info,
- &proxy_info);
+ delegate.OnResolveProxy(url, "GET", empty_proxy_retry_info, &proxy_info);
ASSERT_EQ(first_proxy, proxy_info.proxy_server());
alternative_proxy_server_to_first_proxy = proxy_info.alternative_proxy();
EXPECT_EQ(expect_alternative_proxy_server_to_first_proxy,
alternative_proxy_server_to_first_proxy.is_valid());
// Verify that the metrics are recorded correctly.
- if (test.is_in_quic_field_trial && !test.gurl.SchemeIsCryptographic() &&
+ if (test.is_in_quic_field_trial &&
test.first_proxy_scheme == net::ProxyServer::SCHEME_HTTPS) {
delegate.VerifyQuicHistogramCounts(
histogram_tester, expect_alternative_proxy_server_to_first_proxy,
test.proxy_supports_quic, false);
} else {
- if (!test.is_in_quic_field_trial &&
- !test.gurl.SchemeIsCryptographic()) {
+ if (!test.is_in_quic_field_trial) {
histogram_tester.ExpectUniqueSample(
"DataReductionProxy.Quic.ProxyStatus",
3 /* QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL */, 1);
@@ -611,8 +524,6 @@ TEST_F(DataReductionProxyDelegateTest, AlternativeProxy) {
"DataReductionProxy.Quic.ProxyStatus", 0);
}
}
- histogram_tester.ExpectTotalCount(
- "DataReductionProxy.Quic.OnAlternativeProxyBroken", 0);
}
{
@@ -626,8 +537,8 @@ TEST_F(DataReductionProxyDelegateTest, AlternativeProxy) {
proxy_retry_info[first_proxy.ToURI()] = bad_proxy_info;
base::HistogramTester histogram_tester;
- delegate.OnResolveProxy(test.gurl, "GET", proxy_retry_info, &proxy_info);
- ASSERT_EQ(second_proxy, proxy_info.proxy_server());
+ delegate.OnResolveProxy(url, "GET", proxy_retry_info, &proxy_info);
+ EXPECT_EQ(second_proxy, proxy_info.proxy_server());
alternative_proxy_server_to_second_proxy = proxy_info.alternative_proxy();
EXPECT_EQ(expect_alternative_proxy_server_to_first_proxy,
alternative_proxy_server_to_first_proxy.is_valid());
@@ -635,14 +546,13 @@ TEST_F(DataReductionProxyDelegateTest, AlternativeProxy) {
alternative_proxy_server_to_second_proxy.is_valid());
// Verify that the metrics are recorded correctly.
- if (test.is_in_quic_field_trial && !test.gurl.SchemeIsCryptographic() &&
+ if (test.is_in_quic_field_trial &&
test.second_proxy_scheme == net::ProxyServer::SCHEME_HTTPS) {
delegate.VerifyQuicHistogramCounts(
histogram_tester, expect_alternative_proxy_server_to_second_proxy,
test.proxy_supports_quic, false);
} else {
- if (!test.is_in_quic_field_trial &&
- !test.gurl.SchemeIsCryptographic()) {
+ if (!test.is_in_quic_field_trial) {
histogram_tester.ExpectUniqueSample(
"DataReductionProxy.Quic.ProxyStatus",
3 /* QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL */, 1);
@@ -651,8 +561,6 @@ TEST_F(DataReductionProxyDelegateTest, AlternativeProxy) {
"DataReductionProxy.Quic.ProxyStatus", 0);
}
}
- histogram_tester.ExpectTotalCount(
- "DataReductionProxy.Quic.OnAlternativeProxyBroken", 0);
}
{
@@ -663,13 +571,12 @@ TEST_F(DataReductionProxyDelegateTest, AlternativeProxy) {
proxy_info.UseProxyServer(non_drp_proxy_server);
base::HistogramTester histogram_tester;
- delegate.OnResolveProxy(test.gurl, "GET", empty_proxy_retry_info,
- &proxy_info);
- ASSERT_EQ(non_drp_proxy_server, proxy_info.proxy_server());
+ delegate.OnResolveProxy(url, "GET", empty_proxy_retry_info, &proxy_info);
+ EXPECT_EQ(non_drp_proxy_server, proxy_info.proxy_server());
EXPECT_FALSE(proxy_info.alternative_proxy().is_valid());
// Verify that the metrics are recorded correctly.
- if (!test.is_in_quic_field_trial && !test.gurl.SchemeIsCryptographic()) {
+ if (!test.is_in_quic_field_trial) {
histogram_tester.ExpectUniqueSample(
"DataReductionProxy.Quic.ProxyStatus",
3 /* QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL */, 1);
@@ -677,38 +584,30 @@ TEST_F(DataReductionProxyDelegateTest, AlternativeProxy) {
histogram_tester.ExpectTotalCount("DataReductionProxy.Quic.ProxyStatus",
0);
}
-
- histogram_tester.ExpectTotalCount(
- "DataReductionProxy.Quic.OnAlternativeProxyBroken", 0);
}
// Test if the alternative proxy is correctly marked as broken.
if (expect_alternative_proxy_server_to_first_proxy) {
+ base::HistogramTester histogram_tester;
proxy_info.UseDirect();
- base::HistogramTester histogram_tester;
// Verify that when the alternative proxy server is reported as broken,
// then it is no longer returned when OnResolveProxy is called.
- EXPECT_EQ(
- first_proxy.host_port_pair().host(),
- alternative_proxy_server_to_first_proxy.host_port_pair().host());
- EXPECT_EQ(
- first_proxy.host_port_pair().port(),
- alternative_proxy_server_to_first_proxy.host_port_pair().port());
- EXPECT_EQ(net::ProxyServer::SCHEME_QUIC,
- alternative_proxy_server_to_first_proxy.scheme());
-
- delegate.OnAlternativeProxyBroken(first_proxy);
- delegate.OnResolveProxy(test.gurl, "GET", empty_proxy_retry_info,
- &proxy_info);
+ net::ProxyRetryInfoMap proxy_retry_info;
+ net::ProxyRetryInfo bad_proxy_info;
+ bad_proxy_info.bad_until = base::TimeTicks() + base::TimeDelta::Max();
+ bad_proxy_info.try_while_bad = false;
+ net::ProxyServer bad_proxy_server(net::ProxyServer::SCHEME_QUIC,
+ first_proxy.host_port_pair());
+ proxy_retry_info[bad_proxy_server.ToURI()] = bad_proxy_info;
+
+ delegate.OnResolveProxy(url, "GET", proxy_retry_info, &proxy_info);
ASSERT_EQ(first_proxy, proxy_info.proxy_server());
+ EXPECT_FALSE(proxy_info.alternative_proxy().is_valid());
delegate.VerifyQuicHistogramCounts(
histogram_tester, expect_alternative_proxy_server_to_first_proxy,
test.proxy_supports_quic, true);
- histogram_tester.ExpectTotalCount(
- "DataReductionProxy.Quic.OnAlternativeProxyBroken", 1);
- EXPECT_FALSE(proxy_info.alternative_proxy().is_valid());
}
}
}
@@ -784,8 +683,7 @@ TEST_F(DataReductionProxyDelegateTest, OnCompletedSizeFor200) {
"Via: 1.1 Chrome-Compression-Proxy-Suffix, 9.9 other-proxy\r\n"
"Via: 2.2 Chrome-Compression-Proxy\r\n"
"Warning: 214 Chrome-Compression-Proxy \"Transformation Applied\"\r\n"
- "X-Original-Content-Length: 10000\r\n"
- "Chrome-Proxy: q=low\r\n"
+ "Chrome-Proxy: q=low,ofcl=10000\r\n"
"Content-Length: 1000\r\n\r\n",
},
{
@@ -915,7 +813,7 @@ TEST_F(DataReductionProxyDelegateTest, OnCompletedSizeFor304) {
} test_cases[] = {{
"HTTP/1.1 304 Not Modified\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "X-Original-Content-Length: 10000\r\n\r\n",
+ "Chrome-Proxy: ofcl=10000\r\n\r\n",
},
{
"HTTP/1.1 304 Not Modified\r\n"
@@ -1002,17 +900,17 @@ TEST_F(DataReductionProxyDelegateTest, PartialRangeSavings) {
{"HTTP/1.1 200 OK\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
"Content-Length: 1000\r\n"
- "X-Original-Content-Length: 3000\r\n\r\n",
+ "Chrome-Proxy: ofcl=3000\r\n\r\n",
100, 300},
{"HTTP/1.1 200 OK\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
"Content-Length: 1000\r\n"
- "X-Original-Content-Length: 1000\r\n\r\n",
+ "Chrome-Proxy: ofcl=1000\r\n\r\n",
100, 100},
{"HTTP/1.1 200 OK\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
"Content-Length: 3000\r\n"
- "X-Original-Content-Length: 1000\r\n\r\n",
+ "Chrome-Proxy: ofcl=1000\r\n\r\n",
300, 100},
{"HTTP/1.1 200 OK\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
@@ -1021,38 +919,38 @@ TEST_F(DataReductionProxyDelegateTest, PartialRangeSavings) {
{"HTTP/1.1 200 OK\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
"Content-Length: 1000\r\n"
- "X-Original-Content-Length: nonsense\r\n\r\n",
+ "Chrome-Proxy: ofcl=nonsense\r\n\r\n",
100, 100},
{"HTTP/1.1 200 OK\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
"Content-Length: 0\r\n"
- "X-Original-Content-Length: 1000\r\n\r\n",
+ "Chrome-Proxy: ofcl=1000\r\n\r\n",
0, 1000},
{"HTTP/1.1 200 OK\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "X-Original-Content-Length: 1000\r\n\r\n",
+ "Chrome-Proxy: ofcl=1000\r\n\r\n",
100, 100},
{"HTTP/1.1 200 OK\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
"Content-Length: nonsense\r\n"
- "X-Original-Content-Length: 3000\r\n\r\n",
+ "Chrome-Proxy: ofcl=3000\r\n\r\n",
100, 100},
{"HTTP/1.1 200 OK\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
"Content-Length: 1000\r\n"
- "X-Original-Content-Length: 0\r\n\r\n",
+ "Chrome-Proxy: ofcl=0\r\n\r\n",
100, 0},
{"HTTP/1.1 200 OK\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
"Content-Length: 1000\r\n"
- "X-Original-Content-Length: 0\r\n\r\n",
+ "Chrome-Proxy: ofcl=0\r\n\r\n",
0, 0},
{"HTTP/1.1 200 OK\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
"Content-Length: " +
base::Int64ToString(static_cast<int64_t>(1) << 60) +
"\r\n"
- "X-Original-Content-Length: " +
+ "Chrome-Proxy: ofcl=" +
base::Int64ToString((static_cast<int64_t>(1) << 60) * 3) +
"\r\n\r\n",
100, 300},
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
index 27520ede0b2..d5b3cd4d5b5 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
@@ -27,10 +27,10 @@
#include "components/prefs/pref_service.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/base/proxy_server.h"
#include "net/base/request_priority.h"
#include "net/http/http_response_headers.h"
#include "net/log/test_net_log.h"
-#include "net/proxy/proxy_server.h"
#include "net/socket/socket_test_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -103,8 +103,8 @@ class TestURLRequestContextWithDataReductionProxy
TestURLRequestContextWithDataReductionProxy(const net::ProxyServer& origin,
net::NetworkDelegate* delegate)
: net::TestURLRequestContext(true) {
- context_storage_.set_proxy_service(
- net::ProxyService::CreateFixed(origin.ToURI()));
+ context_storage_.set_proxy_resolution_service(
+ net::ProxyResolutionService::CreateFixed(origin.ToURI()));
set_network_delegate(delegate);
}
@@ -231,10 +231,11 @@ class DataReductionProxyInterceptorWithServerTest : public testing::Test {
DataReductionProxyServer(origin, ProxyServer::UNSPECIFIED_TYPE));
test_context_->config()->test_params()->SetProxiesForHttp(proxies_for_http);
std::string proxy_name = origin.ToURI();
- proxy_service_ = net::ProxyService::CreateFixedFromPacResult(
- "PROXY " + proxy_name + "; DIRECT");
+ proxy_resolution_service_ =
+ net::ProxyResolutionService::CreateFixedFromPacResult(
+ "PROXY " + proxy_name + "; DIRECT");
- context_.set_proxy_service(proxy_service_.get());
+ context_.set_proxy_resolution_service(proxy_resolution_service_.get());
std::unique_ptr<net::URLRequestJobFactoryImpl> job_factory_impl(
new net::URLRequestJobFactoryImpl());
@@ -260,7 +261,7 @@ class DataReductionProxyInterceptorWithServerTest : public testing::Test {
net::TestURLRequestContext context_;
net::EmbeddedTestServer proxy_;
net::EmbeddedTestServer direct_;
- std::unique_ptr<net::ProxyService> proxy_service_;
+ std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service_;
std::unique_ptr<net::URLRequestJobFactory> job_factory_;
std::unique_ptr<DataReductionProxyTestContext> test_context_;
};
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
index be8242541f3..050f4c86a1d 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h"
@@ -75,7 +76,7 @@ net::URLRequestContext*
BasicHTTPURLRequestContextGetter::GetURLRequestContext() {
if (!url_request_context_) {
net::URLRequestContextBuilder builder;
- builder.set_proxy_service(net::ProxyService::CreateDirect());
+ builder.set_proxy_resolution_service(net::ProxyResolutionService::CreateDirect());
builder.SetSpdyAndQuicEnabled(false, false);
url_request_context_ = builder.Build();
}
@@ -158,8 +159,8 @@ DataReductionProxyIOData::DataReductionProxyIOData(
proxy_delegate_.reset(new DataReductionProxyDelegate(
config_.get(), configurator_.get(), event_creator_.get(),
bypass_stats_.get(), net_log_));
- network_properties_manager_.reset(
- new NetworkPropertiesManager(prefs, ui_task_runner_));
+ network_properties_manager_.reset(new NetworkPropertiesManager(
+ base::DefaultClock::GetInstance(), prefs, ui_task_runner_));
}
DataReductionProxyIOData::DataReductionProxyIOData(
@@ -174,8 +175,8 @@ DataReductionProxyIOData::DataReductionProxyIOData(
weak_factory_(this) {
DCHECK(ui_task_runner_);
DCHECK(io_task_runner_);
- network_properties_manager_.reset(
- new NetworkPropertiesManager(prefs, ui_task_runner_));
+ network_properties_manager_.reset(new NetworkPropertiesManager(
+ base::DefaultClock::GetInstance(), prefs, ui_task_runner_));
}
DataReductionProxyIOData::~DataReductionProxyIOData() {
@@ -247,6 +248,12 @@ void DataReductionProxyIOData::DeleteBrowsingHistory(const base::Time start,
network_properties_manager_->DeleteHistory();
}
+void DataReductionProxyIOData::OnCacheCleared(const base::Time start,
+ const base::Time end) {
+ DCHECK(io_task_runner_->BelongsToCurrentThread());
+ network_properties_manager_->DeleteHistory();
+}
+
std::unique_ptr<net::URLRequestInterceptor>
DataReductionProxyIOData::CreateInterceptor() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
@@ -282,7 +289,7 @@ DataReductionProxyIOData::CreateProxyDelegate() const {
// Bug http://crbug/488190.
void DataReductionProxyIOData::SetProxyPrefs(bool enabled, bool at_startup) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
- DCHECK(url_request_context_getter_->GetURLRequestContext()->proxy_service());
+ DCHECK(url_request_context_getter_->GetURLRequestContext()->proxy_resolution_service());
enabled_ = enabled;
config_->SetProxyConfig(enabled, at_startup);
if (config_client_) {
@@ -293,9 +300,9 @@ void DataReductionProxyIOData::SetProxyPrefs(bool enabled, bool at_startup) {
// If Data Saver is disabled, reset data reduction proxy state.
if (!enabled) {
- net::ProxyService* proxy_service =
- url_request_context_getter_->GetURLRequestContext()->proxy_service();
- proxy_service->ClearBadProxiesCache();
+ net::ProxyResolutionService* proxy_resolution_service =
+ url_request_context_getter_->GetURLRequestContext()->proxy_resolution_service();
+ proxy_resolution_service->ClearBadProxiesCache();
bypass_stats_->ClearRequestCounts();
bypass_stats_->NotifyUnavailabilityIfChanged();
}
@@ -348,8 +355,8 @@ void DataReductionProxyIOData::UpdateContentLengths(
void DataReductionProxyIOData::AddEvent(std::unique_ptr<base::Value> event) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
ui_task_runner_->PostTask(
- FROM_HERE, base::Bind(&DataReductionProxyService::AddEvent, service_,
- base::Passed(&event)));
+ FROM_HERE, base::BindOnce(&DataReductionProxyService::AddEvent, service_,
+ std::move(event)));
}
void DataReductionProxyIOData::AddEnabledEvent(
@@ -357,8 +364,8 @@ void DataReductionProxyIOData::AddEnabledEvent(
bool enabled) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
ui_task_runner_->PostTask(
- FROM_HERE, base::Bind(&DataReductionProxyService::AddEnabledEvent,
- service_, base::Passed(&event), enabled));
+ FROM_HERE, base::BindOnce(&DataReductionProxyService::AddEnabledEvent,
+ service_, std::move(event), enabled));
}
void DataReductionProxyIOData::AddEventAndSecureProxyCheckState(
@@ -367,8 +374,9 @@ void DataReductionProxyIOData::AddEventAndSecureProxyCheckState(
DCHECK(io_task_runner_->BelongsToCurrentThread());
ui_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&DataReductionProxyService::AddEventAndSecureProxyCheckState,
- service_, base::Passed(&event), state));
+ base::BindOnce(
+ &DataReductionProxyService::AddEventAndSecureProxyCheckState,
+ service_, std::move(event), state));
}
void DataReductionProxyIOData::AddAndSetLastBypassEvent(
@@ -377,8 +385,8 @@ void DataReductionProxyIOData::AddAndSetLastBypassEvent(
DCHECK(io_task_runner_->BelongsToCurrentThread());
ui_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&DataReductionProxyService::AddAndSetLastBypassEvent, service_,
- base::Passed(&event), expiration_ticks));
+ base::BindOnce(&DataReductionProxyService::AddAndSetLastBypassEvent,
+ service_, std::move(event), expiration_ticks));
}
void DataReductionProxyIOData::SetUnreachable(bool unreachable) {
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h
index c2f2144af04..ad60792d4d4 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h
@@ -20,8 +20,8 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_storage_delegate.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/lofi_decider.h"
#include "components/data_reduction_proxy/core/common/lofi_ui_service.h"
#include "components/data_reduction_proxy/core/common/resource_type_provider.h"
@@ -141,6 +141,11 @@ class DataReductionProxyIOData : public DataReductionProxyEventStorageDelegate {
// Called when the user clears the browsing history.
void DeleteBrowsingHistory(const base::Time start, const base::Time end);
+ // Notifies |this| that the user has requested to clear the browser
+ // cache. This method is not called if only a subset of site entries are
+ // cleared.
+ void OnCacheCleared(const base::Time start, const base::Time end);
+
// Various accessor methods.
DataReductionProxyConfigurator* configurator() const {
return configurator_.get();
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
index f102d9cd76d..6c8ca4250ca 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
@@ -26,8 +26,8 @@
#include "net/http/http_network_session.h"
#include "net/log/net_log.h"
#include "net/log/net_log_with_source.h"
-#include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_service.h"
+#include "net/proxy_resolution/proxy_info.h"
+#include "net/proxy_resolution/proxy_service.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
@@ -167,17 +167,17 @@ TEST_F(DataReductionProxyIODataTest, TestResetBadProxyListOnDisableDataSaver) {
std::vector<net::ProxyServer> proxies;
proxies.push_back(net::ProxyServer::FromURI("http://foo1.com",
net::ProxyServer::SCHEME_HTTP));
- net::ProxyService* proxy_service =
+ net::ProxyResolutionService* proxy_resolution_service =
io_data->url_request_context_getter_->GetURLRequestContext()
- ->proxy_service();
+ ->proxy_resolution_service();
net::ProxyInfo proxy_info;
proxy_info.UseNamedProxy("http://foo2.com");
net::NetLogWithSource net_log_with_source;
const net::ProxyRetryInfoMap& bad_proxy_list =
- proxy_service->proxy_retry_info();
+ proxy_resolution_service->proxy_retry_info();
// Simulate network error to add proxies to the bad proxy list.
- proxy_service->MarkProxiesAsBadUntil(proxy_info, base::TimeDelta::FromDays(1),
+ proxy_resolution_service->MarkProxiesAsBadUntil(proxy_info, base::TimeDelta::FromDays(1),
proxies, net_log_with_source);
base::RunLoop().RunUntilIdle();
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc
index beff82d857d..edf466aff81 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc
@@ -7,11 +7,11 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "net/base/load_flags.h"
+#include "net/base/proxy_server.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_status_code.h"
-#include "net/proxy/proxy_config.h"
-#include "net/proxy/proxy_server.h"
+#include "net/proxy_resolution/proxy_config.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "url/url_constants.h"
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
index 3eaf9e5bbda..dc715862333 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
@@ -16,10 +16,10 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
#include "net/base/load_flags.h"
+#include "net/base/proxy_server.h"
#include "net/log/net_log_source_type.h"
#include "net/log/net_log_with_source.h"
-#include "net/proxy/proxy_server.h"
-#include "net/proxy/proxy_service.h"
+#include "net/proxy_resolution/proxy_service.h"
#include "net/socket/socket_test_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
@@ -171,11 +171,11 @@ TEST(ChromeNetworkDailyDataSavingMetricsTest,
net::TestURLRequestContext context(true);
net::MockClientSocketFactory mock_socket_factory;
context.set_client_socket_factory(&mock_socket_factory);
- // Set the |proxy_service| to use |test_case.proxy_server| for requests.
- std::unique_ptr<net::ProxyService> proxy_service(
- net::ProxyService::CreateFixedFromPacResult(
+ // Set the |proxy_resolution_service| to use |test_case.proxy_server| for requests.
+ std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service(
+ net::ProxyResolutionService::CreateFixedFromPacResult(
test_case.proxy_server.ToPacString()));
- context.set_proxy_service(proxy_service.get());
+ context.set_proxy_resolution_service(proxy_resolution_service.get());
context.Init();
// Create a fake URLRequest and fill it with the appropriate response
@@ -204,7 +204,7 @@ TEST(ChromeNetworkDailyDataSavingMetricsTest,
net::ProxyInfo proxy_info;
proxy_info.UseProxyList(
data_reduction_proxy_config.proxy_rules().proxies_for_http);
- EXPECT_TRUE(context.proxy_service()->MarkProxiesAsBadUntil(
+ EXPECT_TRUE(context.proxy_resolution_service()->MarkProxiesAsBadUntil(
proxy_info, test_case.bypass_duration,
std::vector<net::ProxyServer>(),
net::NetLogWithSource::Make(context.net_log(),
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h
index a749d00b43e..145db2b19e1 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_config_values.h"
-#include "net/proxy/proxy_server.h"
+#include "net/base/proxy_server.h"
#include "url/gurl.h"
namespace data_reduction_proxy {
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc
index c9b622980a6..bfea492ed7d 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc
@@ -12,7 +12,7 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
-#include "net/proxy/proxy_server.h"
+#include "net/base/proxy_server.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace data_reduction_proxy {
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
index 4e119781830..c26d6dd0c7c 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -21,19 +21,19 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/lofi_decider.h"
#include "net/base/load_flags.h"
#include "net/base/mime_util.h"
+#include "net/base/proxy_server.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/nqe/effective_connection_type.h"
#include "net/nqe/network_quality_estimator.h"
-#include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_server.h"
-#include "net/proxy/proxy_service.h"
+#include "net/proxy_resolution/proxy_info.h"
+#include "net/proxy_resolution/proxy_service.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_status.h"
@@ -590,10 +590,9 @@ void DataReductionProxyNetworkDelegate::CalculateAndRecordDataUsage(
// Estimate how many bytes would have been used if the DataReductionProxy was
// not used, and record the data usage.
int64_t original_size = util::EstimateOriginalReceivedBytes(
- request, request_type == VIA_DATA_REDUCTION_PROXY,
- data_reduction_proxy_io_data_
- ? data_reduction_proxy_io_data_->lofi_decider()
- : nullptr);
+ request, data_reduction_proxy_io_data_
+ ? data_reduction_proxy_io_data_->lofi_decider()
+ : nullptr);
std::string mime_type;
if (request.response_headers())
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
index 68342475af6..cbe18a6957c 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
@@ -17,7 +17,7 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h"
#include "net/base/completion_callback.h"
#include "net/base/layered_network_delegate.h"
-#include "net/proxy/proxy_retry_info.h"
+#include "net/proxy_resolution/proxy_retry_info.h"
class GURL;
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
index 33c20c1e252..672db949a06 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -45,21 +45,22 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/data_reduction_proxy/core/common/lofi_decider.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
-#include "components/previews/core/previews_decider.h"
#include "components/previews/core/previews_experiments.h"
+#include "components/previews/core/previews_features.h"
+#include "components/previews/core/test_previews_decider.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/base/proxy_server.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/nqe/effective_connection_type.h"
#include "net/nqe/network_quality_estimator_test_util.h"
-#include "net/proxy/proxy_config.h"
-#include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_retry_info.h"
-#include "net/proxy/proxy_server.h"
-#include "net/proxy/proxy_service.h"
+#include "net/proxy_resolution/proxy_config.h"
+#include "net/proxy_resolution/proxy_info.h"
+#include "net/proxy_resolution/proxy_retry_info.h"
+#include "net/proxy_resolution/proxy_service.h"
#include "net/socket/socket_test_util.h"
#include "net/test/cert_test_util.h"
#include "net/test/gtest_util.h"
@@ -313,28 +314,6 @@ class TestLoFiUIService : public LoFiUIService {
bool on_lofi_response_;
};
-class TestPreviewsDecider : public previews::PreviewsDecider {
- public:
- TestPreviewsDecider() {}
- ~TestPreviewsDecider() override {}
- // previews::PreviewsDecider:
- bool ShouldAllowPreviewAtECT(
- const net::URLRequest& request,
- previews::PreviewsType type,
- net::EffectiveConnectionType effective_connection_type_threshold,
- const std::vector<std::string>& host_blacklist_from_server)
- const override {
- return true;
- }
-
- // Same as ShouldAllowPreviewAtECT, but uses the previews default
- // EffectiveConnectionType and no blacklisted hosts from the server.
- bool ShouldAllowPreview(const net::URLRequest& request,
- previews::PreviewsType type) const override {
- return true;
- }
-};
-
enum ProxyTestConfig { USE_SECURE_PROXY, USE_INSECURE_PROXY, BYPASS_PROXY };
class DataReductionProxyNetworkDelegateTest : public testing::Test {
@@ -365,9 +344,9 @@ class DataReductionProxyNetworkDelegateTest : public testing::Test {
}
context_.reset(new net::TestURLRequestContext(true));
context_storage_.reset(new net::URLRequestContextStorage(context_.get()));
- proxy_service_ =
- net::ProxyService::CreateFixedFromPacResult(proxy_server.ToPacString());
- context_->set_proxy_service(proxy_service_.get());
+ proxy_resolution_service_ = net::ProxyResolutionService::CreateFixedFromPacResult(
+ proxy_server.ToPacString());
+ context_->set_proxy_resolution_service(proxy_resolution_service_.get());
context_->set_network_quality_estimator(&test_network_quality_estimator_);
mock_socket_factory_.reset(new net::MockClientSocketFactory());
@@ -692,7 +671,7 @@ class DataReductionProxyNetworkDelegateTest : public testing::Test {
"HTTP/1.1 200 OK\r\n"
"Content-Length: 140\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: 200\r\n"
+ "Chrome-Proxy: ofcl=200\r\n"
"Cache-Control: max-age=1200\r\n"
"Vary: accept-encoding\r\n\r\n";
@@ -868,7 +847,7 @@ class DataReductionProxyNetworkDelegateTest : public testing::Test {
private:
base::MessageLoopForIO message_loop_;
std::unique_ptr<net::MockClientSocketFactory> mock_socket_factory_;
- std::unique_ptr<net::ProxyService> proxy_service_;
+ std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service_;
std::unique_ptr<net::TestURLRequestContext> context_;
std::unique_ptr<net::URLRequestContextStorage> context_storage_;
@@ -918,8 +897,10 @@ TEST_F(DataReductionProxyNetworkDelegateTest, AuthenticationTest) {
TEST_F(DataReductionProxyNetworkDelegateTest, LoFiTransitions) {
Init(USE_INSECURE_PROXY, false);
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(
- features::kDataReductionProxyDecidesTransform);
+ scoped_feature_list.InitWithFeatures(
+ {previews::features::kPreviews,
+ features::kDataReductionProxyDecidesTransform},
+ {});
// Enable Lo-Fi.
bool is_data_reduction_proxy_enabled[] = {false, true};
@@ -936,7 +917,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest, LoFiTransitions) {
}
// Needed as a parameter, but functionality is not tested.
- TestPreviewsDecider test_previews_decider;
+ previews::TestPreviewsDecider test_previews_decider(true);
{
// Main frame loaded. Lo-Fi should be used.
@@ -1246,6 +1227,11 @@ TEST_F(DataReductionProxyNetworkDelegateTest, RedirectRequestDataCleared) {
TEST_F(DataReductionProxyNetworkDelegateTest, NetHistograms) {
Init(USE_INSECURE_PROXY, false);
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {previews::features::kPreviews,
+ features::kDataReductionProxyDecidesTransform},
+ {});
base::HistogramTester histogram_tester;
@@ -1254,7 +1240,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest, NetHistograms) {
"Date: Wed, 28 Nov 2007 09:40:09 GMT\r\n"
"Expires: Mon, 24 Nov 2014 12:45:26 GMT\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: " +
+ "Chrome-Proxy: ofcl=" +
base::Int64ToString(kOriginalContentLength) + "\r\n\r\n";
std::unique_ptr<net::URLRequest> fake_request(FetchURLRequest(
@@ -1326,7 +1312,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest, NetHistograms) {
}
// Needed as a parameter, but functionality is not tested.
- TestPreviewsDecider test_previews_decider;
+ previews::TestPreviewsDecider test_previews_decider(true);
lofi_decider()->SetIsUsingLoFi(config()->ShouldAcceptServerPreview(
*fake_request.get(), test_previews_decider));
@@ -1373,7 +1359,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest, NetVideoHistograms) {
"Expires: Mon, 24 Nov 2014 12:45:26 GMT\r\n"
"Content-Type: video/mp4\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: " +
+ "Chrome-Proxy: ofcl=" +
base::Int64ToString(kOriginalContentLength) + "\r\n\r\n";
FetchURLRequest(GURL(kTestURL), nullptr, video_response_headers,
@@ -1553,7 +1539,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest, DetailedNetHistograms) {
if (test.proxy_config == USE_INSECURE_PROXY) {
via_header = "Via: 1.1 Chrome-Compression-Proxy\r\n";
- ocl_header = "x-original-content-length: " +
+ ocl_header = "Chrome-Proxy: ofcl=" +
base::Int64ToString(kOriginalContentLength) + "\r\n";
}
if (test.is_video) {
@@ -1602,7 +1588,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest,
"Date: Wed, 28 Nov 2007 09:40:09 GMT\r\n"
"Expires: Mon, 24 Nov 2014 12:45:26 GMT\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: 200\r\n\r\n";
+ "Chrome-Proxy: ofcl=200\r\n\r\n";
auto request =
FetchURLRequest(GURL(kTestURL), nullptr, response_headers, 140, 0);
@@ -1622,7 +1608,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest,
"Date: Wed, 28 Nov 2007 09:40:09 GMT\r\n"
"Expires: Mon, 24 Nov 2014 12:45:26 GMT\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: 200\r\n"
+ "Chrome-Proxy: ofcl=200\r\n"
"Chrome-Proxy-Content-Transform: empty-image\r\n\r\n";
auto request =
@@ -1717,7 +1703,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest,
"HTTP/1.1 200 OK\r\n"
"Content-Length: 140\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: 200\r\n"
+ "Chrome-Proxy: ofcl=200\r\n"
"Cache-Control: max-age=0\r\n"
"Vary: accept-encoding\r\n\r\n";
@@ -1740,7 +1726,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest,
"Date: Wed, 28 Nov 2007 09:40:09 GMT\r\n"
"Expires: Mon, 24 Nov 2014 12:45:26 GMT\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: 200\r\n";
+ "Chrome-Proxy: ofcl=200\r\n";
response_headers += "\r\n";
auto request =
@@ -1763,7 +1749,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest,
"HTTP/1.1 200 OK\r\n"
"Content-Length: 140\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: 200\r\n"
+ "Chrome-Proxy: ofcl=200\r\n"
"Cache-Control: max-age=1200\r\n"
"Vary: accept-encoding\r\n";
response_headers += "\r\n";
@@ -1782,7 +1768,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest,
"HTTP/1.1 200 OK\r\n"
"Content-Length: 140\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: 200\r\n"
+ "Chrome-Proxy: ofcl=200\r\n"
"Cache-Control: max-age=1200\r\n"
"Vary: accept-encoding\r\n";
response_headers += "\r\n";
@@ -1813,7 +1799,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest,
"HTTP/1.1 200 OK\r\n"
"Content-Length: 140\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: 200\r\n"
+ "Chrome-Proxy: ofcl=200\r\n"
"Cache-Control: max-age=1200\r\n"
"Vary: accept-encoding\r\n";
response_headers += "\r\n";
@@ -1830,7 +1816,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest, BrotliAdvertisement) {
std::string response_headers =
"HTTP/1.1 200 OK\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: 200\r\n"
+ "Chrome-Proxy: ofcl=200\r\n"
"Cache-Control: max-age=1200\r\n"
"Content-Encoding: br\r\n"
"Vary: accept-encoding\r\n";
@@ -1965,7 +1951,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest, ECTHeaderEnabledWithVary) {
"Via: 1.1 Chrome-Compression-Proxy\r\n"
"Cache-Control: max-age=1200\r\n"
"Vary: chrome-proxy-ect\r\n"
- "x-original-content-length: 200\r\n\r\n";
+ "Chrome-Proxy: ofcl=200\r\n\r\n";
int response_body_size = 140;
std::string response_body(base::checked_cast<size_t>(response_body_size),
@@ -2006,7 +1992,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest, ECTHeaderEnabledWithoutVary) {
"Content-Length: 140\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
"Cache-Control: max-age=1200\r\n"
- "x-original-content-length: 200\r\n\r\n";
+ "Chrome-Proxy: ofcl=200\r\n\r\n";
int response_body_size = 140;
std::string response_body(base::checked_cast<size_t>(response_body_size),
@@ -2051,10 +2037,20 @@ class DataReductionProxyNetworkDelegateClientLoFiTest : public testing::Test {
mock_socket_factory_.reset(new net::MockClientSocketFactory());
context_->set_client_socket_factory(mock_socket_factory_.get());
+ net::ProxyServer proxy_server = net::ProxyServer::FromURI(
+ "http://origin.net:80", net::ProxyServer::SCHEME_HTTP);
+
+ proxy_resolution_service_ =
+ net::ProxyResolutionService::CreateFixedFromPacResult(
+ proxy_server.ToPacString());
+ context_->set_proxy_resolution_service(proxy_resolution_service_.get());
+
drp_test_context_ =
DataReductionProxyTestContext::Builder()
.WithURLRequestContext(context_.get())
.WithMockClientSocketFactory(mock_socket_factory_.get())
+ .WithProxiesForHttp({DataReductionProxyServer(
+ proxy_server, ProxyServer::UNSPECIFIED_TYPE)})
.Build();
drp_test_context_->AttachToURLRequestContext(context_storage_.get());
@@ -2092,6 +2088,7 @@ class DataReductionProxyNetworkDelegateClientLoFiTest : public testing::Test {
std::unique_ptr<net::TestURLRequestContext> context_;
std::unique_ptr<net::URLRequestContextStorage> context_storage_;
std::unique_ptr<net::MockClientSocketFactory> mock_socket_factory_;
+ std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service_;
std::unique_ptr<DataReductionProxyTestContext> drp_test_context_;
int64_t baseline_savings_;
};
@@ -2175,6 +2172,8 @@ TEST_F(DataReductionProxyNetworkDelegateClientLoFiTest, DataSavingsNonDRP) {
GURL("http://example.com"), net::RequestPriority::IDLE, &test_delegate,
TRAFFIC_ANNOTATION_FOR_TESTS);
+ request->SetLoadFlags(request->load_flags() | net::LOAD_BYPASS_PROXY);
+
request->Start();
base::RunLoop().RunUntilIdle();
@@ -2193,7 +2192,7 @@ TEST_F(DataReductionProxyNetworkDelegateClientLoFiTest, DataSavingsThroughDRP) {
"Content-Range: bytes 0-2047/10000\r\n"
"Content-Length: 2048\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "X-Original-Content-Length: 3000\r\n\r\n";
+ "Chrome-Proxy: ofcl=3000\r\n\r\n";
std::string response_body(2048, 'a');
net::MockRead reads[] = {net::MockRead(kHeaders),
@@ -2227,7 +2226,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest, TestAcceptTransformHistogram) {
"HTTP/1.1 200 OK\r\n"
"Content-Length: 140\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: 200\r\n"
+ "Chrome-Proxy: ofcl=200\r\n"
"Cache-Control: max-age=0\r\n"
"Vary: accept-encoding\r\n\r\n";
@@ -2237,7 +2236,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest, TestAcceptTransformHistogram) {
"Date: Wed, 28 Nov 2007 09:40:09 GMT\r\n"
"Expires: Mon, 24 Nov 2014 12:45:26 GMT\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: 200\r\n"
+ "Chrome-Proxy: ofcl=200\r\n"
"\r\n";
// Verify lite page request.
@@ -2286,7 +2285,7 @@ TEST_F(DataReductionProxyNetworkDelegateTest, TestAcceptTransformHistogram) {
"Date: Wed, 28 Nov 2007 09:40:09 GMT\r\n"
"Expires: Mon, 24 Nov 2014 12:45:26 GMT\r\n"
"Via: 1.1 Chrome-Compression-Proxy\r\n"
- "x-original-content-length: 200\r\n"
+ "Chrome-Proxy: ofcl=200\r\n"
"\r\n";
request = FetchURLRequest(GURL(kTestURL), nullptr, response_headers, 140, 0);
EXPECT_FALSE(DataReductionProxyData::GetData(*request)->lite_page_received());
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 da23635c84f..fc20bdcdcd4 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
@@ -29,7 +29,7 @@
#include "crypto/random.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
-#include "net/proxy/proxy_server.h"
+#include "net/base/proxy_server.h"
#include "net/url_request/url_request.h"
#if defined(USE_GOOGLE_API_KEYS_FOR_AUTH_KEY)
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h
index 08700fd2d18..e0b356166bf 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
@@ -18,7 +18,7 @@
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
namespace net {
class HttpRequestHeaders;
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 1a4883c17b2..dcf0efb4ff7 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
@@ -25,7 +25,7 @@
#include "net/base/auth.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
-#include "net/proxy/proxy_server.h"
+#include "net/base/proxy_server.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "testing/gmock/include/gmock/gmock.h"
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 c37b386150d..2002ef1991f 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
@@ -205,16 +205,25 @@ void DataReductionProxyService::SetPingbackReportingFraction(
pingback_client_->SetPingbackReportingFraction(pingback_reporting_fraction);
}
+void DataReductionProxyService::OnCacheCleared(const base::Time start,
+ const base::Time end) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ io_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&DataReductionProxyIOData::OnCacheCleared,
+ io_data_, start, end));
+}
+
void DataReductionProxyService::LoadHistoricalDataUsage(
const HistoricalDataUsageCallback& load_data_usage_callback) {
std::unique_ptr<std::vector<DataUsageBucket>> data_usage(
new std::vector<DataUsageBucket>());
std::vector<DataUsageBucket>* data_usage_ptr = data_usage.get();
db_task_runner_->PostTaskAndReply(
- FROM_HERE, base::Bind(&DBDataOwner::LoadHistoricalDataUsage,
- db_data_owner_->GetWeakPtr(),
- base::Unretained(data_usage_ptr)),
- base::Bind(load_data_usage_callback, base::Passed(&data_usage)));
+ FROM_HERE,
+ base::BindOnce(&DBDataOwner::LoadHistoricalDataUsage,
+ db_data_owner_->GetWeakPtr(),
+ base::Unretained(data_usage_ptr)),
+ base::BindOnce(load_data_usage_callback, std::move(data_usage)));
}
void DataReductionProxyService::LoadCurrentDataUsageBucket(
@@ -223,17 +232,18 @@ void DataReductionProxyService::LoadCurrentDataUsageBucket(
DataUsageBucket* bucket_ptr = bucket.get();
db_task_runner_->PostTaskAndReply(
FROM_HERE,
- base::Bind(&DBDataOwner::LoadCurrentDataUsageBucket,
- db_data_owner_->GetWeakPtr(), base::Unretained(bucket_ptr)),
- base::Bind(load_current_data_usage_callback, base::Passed(&bucket)));
+ base::BindOnce(&DBDataOwner::LoadCurrentDataUsageBucket,
+ db_data_owner_->GetWeakPtr(),
+ base::Unretained(bucket_ptr)),
+ base::BindOnce(load_current_data_usage_callback, std::move(bucket)));
}
void DataReductionProxyService::StoreCurrentDataUsageBucket(
std::unique_ptr<DataUsageBucket> current) {
db_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&DBDataOwner::StoreCurrentDataUsageBucket,
- db_data_owner_->GetWeakPtr(), base::Passed(&current)));
+ base::BindOnce(&DBDataOwner::StoreCurrentDataUsageBucket,
+ db_data_owner_->GetWeakPtr(), std::move(current)));
}
void DataReductionProxyService::DeleteHistoricalDataUsage() {
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 563fe87b29f..c93dab6e9c9 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
@@ -127,6 +127,11 @@ class DataReductionProxyService
// Sets the reporting fraction in the pingback client.
void SetPingbackReportingFraction(float pingback_reporting_fraction);
+ // Notifies |this| that the user has requested to clear the browser
+ // cache. This method is not called if only a subset of site entries are
+ // cleared.
+ void OnCacheCleared(const base::Time start, const base::Time end);
+
// Accessor methods.
DataReductionProxyCompressionStats* compression_stats() const {
return compression_stats_.get();
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
index 85070409016..614cb7a0868 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
@@ -281,6 +281,7 @@ void DataReductionProxySettings::RecordDataReductionInit() const {
DCHECK(thread_checker_.CalledOnValidThread());
RecordStartupState(IsDataReductionProxyEnabled() ? PROXY_ENABLED
: PROXY_DISABLED);
+ RecordStartupSavings();
}
void DataReductionProxySettings::RecordStartupState(
@@ -290,6 +291,38 @@ void DataReductionProxySettings::RecordStartupState(
PROXY_STARTUP_STATE_COUNT);
}
+void DataReductionProxySettings::RecordStartupSavings() const {
+ // Minimum bytes the user should have browsed, for the data savings percent
+ // UMA to be recorded at startup.
+ const unsigned int kMinOriginalContentLengthBytes =
+ 10 * 1024 * 1024; // 10 MB.
+
+ if (!IsDataReductionProxyEnabled())
+ return;
+
+ DCHECK(data_reduction_proxy_service_->compression_stats());
+ int64_t original_content_length =
+ data_reduction_proxy_service_->compression_stats()
+ ->GetHttpOriginalContentLength();
+ int64_t received_content_length =
+ data_reduction_proxy_service_->compression_stats()
+ ->GetHttpReceivedContentLength();
+ if (original_content_length < kMinOriginalContentLengthBytes)
+ return;
+ int savings_percent =
+ static_cast<int>(((original_content_length - received_content_length) /
+ (float)original_content_length) *
+ 100.0);
+ if (savings_percent >= 0) {
+ UMA_HISTOGRAM_PERCENTAGE("DataReductionProxy.StartupSavingsPercent",
+ savings_percent > 0 ? savings_percent : 0);
+ }
+ if (savings_percent < 0) {
+ UMA_HISTOGRAM_PERCENTAGE("DataReductionProxy.StartupNegativeSavingsPercent",
+ -savings_percent);
+ }
+}
+
ContentLengthList
DataReductionProxySettings::GetDailyContentLengths(const char* pref_name) {
DCHECK(thread_checker_.CalledOnValidThread());
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 2e2005caf4b..faac818678f 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
@@ -218,6 +218,11 @@ class DataReductionProxySettings : public DataReductionProxyServiceObserver {
void OnProxyEnabledPrefChange();
+ // Records data savings percentage histogram at chrome startup, for users who
+ // have browsed a reasonable amount. Positive and negative savings are
+ // recorded in a separate histogram.
+ void RecordStartupSavings() const;
+
void ResetDataReductionStatistics();
// Update IO thread objects in response to UI thread changes.
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
index 5b072d50582..2561b739fb5 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
@@ -19,6 +19,7 @@
#include "base/test/mock_entropy_provider.h"
#include "base/test/simple_test_clock.h"
#include "base/time/clock.h"
+#include "base/time/default_clock.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
@@ -30,7 +31,7 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/prefs/pref_registry_simple.h"
-#include "net/proxy/proxy_server.h"
+#include "net/base/proxy_server.h"
#include "net/socket/socket_test_util.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -65,7 +66,8 @@ class DataReductionProxySettingsTest
TEST_F(DataReductionProxySettingsTest, TestIsProxyEnabledOrManaged) {
InitPrefMembers();
NetworkPropertiesManager network_properties_manager(
- test_context_->pref_service(), test_context_->task_runner());
+ base::DefaultClock::GetInstance(), test_context_->pref_service(),
+ test_context_->task_runner());
test_context_->config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
@@ -89,7 +91,8 @@ TEST_F(DataReductionProxySettingsTest, TestIsProxyEnabledOrManaged) {
TEST_F(DataReductionProxySettingsTest, TestCanUseDataReductionProxy) {
InitPrefMembers();
NetworkPropertiesManager network_properties_manager(
- test_context_->pref_service(), test_context_->task_runner());
+ base::DefaultClock::GetInstance(), test_context_->pref_service(),
+ test_context_->task_runner());
test_context_->config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
@@ -260,7 +263,8 @@ TEST(DataReductionProxySettingsStandaloneTest, TestOnProxyEnabledPrefChange) {
.Build();
NetworkPropertiesManager network_properties_manager(
- drp_test_context->pref_service(), drp_test_context->task_runner());
+ base::DefaultClock::GetInstance(), drp_test_context->pref_service(),
+ drp_test_context->task_runner());
drp_test_context->config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
@@ -286,7 +290,8 @@ TEST_F(DataReductionProxySettingsTest, TestMaybeActivateDataReductionProxy) {
// so it won't trigger MaybeActivateDataReductionProxy when the pref value
// is set.
NetworkPropertiesManager network_properties_manager(
- test_context_->pref_service(), test_context_->task_runner());
+ base::DefaultClock::GetInstance(), test_context_->pref_service(),
+ test_context_->task_runner());
test_context_->config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
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 7f8d401ca40..f3a2bebdd94 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
@@ -36,9 +36,9 @@
#include "components/prefs/testing_pref_service.h"
#include "net/base/network_delegate_impl.h"
#include "net/nqe/network_quality_estimator_test_util.h"
-#include "net/proxy/proxy_config.h"
-#include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_list.h"
+#include "net/proxy_resolution/proxy_config.h"
+#include "net/proxy_resolution/proxy_info.h"
+#include "net/proxy_resolution/proxy_list.h"
#include "net/socket/socket_test_util.h"
#include "net/url_request/url_request_context_storage.h"
#include "net/url_request/url_request_intercepting_job_factory.h"
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 f5866069407..5a63e583fc3 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
@@ -28,8 +28,8 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h"
#include "components/data_reduction_proxy/core/browser/data_store.h"
#include "net/base/backoff_entry.h"
+#include "net/base/proxy_server.h"
#include "net/log/test_net_log.h"
-#include "net/proxy/proxy_server.h"
#include "net/url_request/url_request_context_getter.h"
#include "testing/gmock/include/gmock/gmock.h"
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_util.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.cc
index 1dee69fa158..d4010a64059 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_util.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.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/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include <stdint.h>
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "base/version.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "components/data_reduction_proxy/core/common/lofi_decider.h"
#include "components/data_reduction_proxy/core/common/version.h"
@@ -17,8 +18,8 @@
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
-#include "net/proxy/proxy_config.h"
-#include "net/proxy/proxy_info.h"
+#include "net/proxy_resolution/proxy_config.h"
+#include "net/proxy_resolution/proxy_info.h"
#include "net/url_request/url_request.h"
#if defined(USE_GOOGLE_API_KEYS)
@@ -67,8 +68,14 @@ int64_t ScaleByteCountByRatio(int64_t byte_count,
// protocol as |request| did. This is to account for stuff like HTTP/2 header
// compression.
int64_t EstimateOriginalHeaderBytes(const net::URLRequest& request,
- bool used_drp) {
- if (used_drp) {
+ const LoFiDecider* lofi_decider) {
+ // If this is an auto-reload of an image, then this request would ordinarily
+ // not be issued, so return 0.
+ if (lofi_decider && lofi_decider->IsClientLoFiAutoReloadRequest(request))
+ return 0;
+ data_reduction_proxy::DataReductionProxyData* data =
+ data_reduction_proxy::DataReductionProxyData::GetData(request);
+ if (data && data->used_data_reduction_proxy()) {
// TODO(sclittle): Remove headers added by Data Reduction Proxy when
// computing original size. https://crbug.com/535701.
return request.response_headers()->raw_headers().size();
@@ -174,7 +181,7 @@ bool ApplyProxyConfigToProxyInfo(const net::ProxyConfig& proxy_config,
const GURL& url,
net::ProxyInfo* data_reduction_proxy_info) {
DCHECK(data_reduction_proxy_info);
- if (!proxy_config.is_valid())
+ if (proxy_config.proxy_rules().empty())
return false;
proxy_config.proxy_rules().Apply(url, data_reduction_proxy_info);
data_reduction_proxy_info->DeprioritizeBadProxies(proxy_retry_info);
@@ -201,19 +208,36 @@ int64_t CalculateOCLFromOFCL(const net::URLRequest& request) {
original_content_length, range_content_length);
}
}
- if (original_content_length < 0) {
- // Fallback to using XOCL if getting from OFCL header fails.
- // TODO(rajendrant): Remove the usage of OFCL, after integration tests are
- // changed.
- original_content_length =
- response_headers->GetInt64HeaderValue("x-original-content-length");
- }
return original_content_length;
}
-int64_t CalculateEffectiveOCL(const net::URLRequest& request) {
- if (request.was_cached() || !request.response_headers())
- return request.received_response_content_length();
+int64_t EstimateOriginalBodySize(const net::URLRequest& request,
+ const LoFiDecider* lofi_decider) {
+ if (lofi_decider) {
+ // If this is an auto-reload of an image, then this request would ordinarily
+ // not be issued, so return 0.
+ if (lofi_decider->IsClientLoFiAutoReloadRequest(request))
+ return 0;
+
+ int64_t first, last, length;
+ if (!request.was_cached() &&
+ lofi_decider->IsClientLoFiImageRequest(request) &&
+ request.response_headers() &&
+ request.response_headers()->GetContentRangeFor206(&first, &last,
+ &length) &&
+ length > request.received_response_content_length()) {
+ return length;
+ }
+ }
+
+ data_reduction_proxy::DataReductionProxyData* data =
+ data_reduction_proxy::DataReductionProxyData::GetData(request);
+ if (!data || !data->used_data_reduction_proxy() || request.was_cached() ||
+ !request.response_headers()) {
+ return std::min<int64_t>(request.GetTotalReceivedBytes(),
+ request.received_response_content_length());
+ }
+
int64_t original_content_length_from_header = CalculateOCLFromOFCL(request);
if (original_content_length_from_header < 0)
@@ -235,27 +259,12 @@ int64_t CalculateEffectiveOCL(const net::URLRequest& request) {
}
int64_t EstimateOriginalReceivedBytes(const net::URLRequest& request,
- bool used_drp,
const LoFiDecider* lofi_decider) {
if (request.was_cached() || !request.response_headers())
return request.GetTotalReceivedBytes();
- if (lofi_decider) {
- if (lofi_decider->IsClientLoFiAutoReloadRequest(request))
- return 0;
-
- int64_t first, last, length;
- if (lofi_decider->IsClientLoFiImageRequest(request) &&
- request.response_headers()->GetContentRangeFor206(&first, &last,
- &length) &&
- length > request.received_response_content_length()) {
- return EstimateOriginalHeaderBytes(request, used_drp) + length;
- }
- }
-
- return used_drp ? EstimateOriginalHeaderBytes(request, used_drp) +
- util::CalculateEffectiveOCL(request)
- : request.GetTotalReceivedBytes();
+ return EstimateOriginalHeaderBytes(request, lofi_decider) +
+ EstimateOriginalBodySize(request, lofi_decider);
}
ProxyScheme ConvertNetProxySchemeToProxyScheme(
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_util.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h
index a40f35890d6..98f4f52f315 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_util.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h
@@ -2,29 +2,29 @@
// 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_COMMON_DATA_REDUCTION_PROXY_UTIL_H_
-#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_UTIL_H_
+#ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_UTIL_H_
+#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_UTIL_H_
#include <memory>
#include <string>
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "components/data_reduction_proxy/proto/pageload_metrics.pb.h"
+#include "net/base/proxy_server.h"
#include "net/nqe/effective_connection_type.h"
-#include "net/proxy/proxy_retry_info.h"
-#include "net/proxy/proxy_server.h"
+#include "net/proxy_resolution/proxy_retry_info.h"
#include "url/gurl.h"
namespace base {
class Time;
class TimeDelta;
-}
+} // namespace base
namespace net {
class ProxyConfig;
class ProxyInfo;
class URLRequest;
-}
+} // namespace net
namespace data_reduction_proxy {
@@ -88,10 +88,11 @@ bool EligibleForDataReductionProxy(const net::ProxyInfo& proxy_info,
const std::string& method);
// Determines if |proxy_config| would override a direct. |proxy_config| should
-// be a data reduction proxy config with proxy servers mapped in the rules.
-// |proxy_retry_info| contains the list of bad proxies. |url| is used to
-// determine whether it is HTTP or HTTPS. |data_reduction_proxy_info| is an out
-// param that will contain the proxies that should be used.
+// be a data reduction proxy config with proxy servers mapped in the
+// rules, or DIRECT to indicate DRP is not to be used. |proxy_retry_info|
+// contains the list of bad proxies. |url| is used to determine whether it is
+// HTTP or HTTPS. |data_reduction_proxy_info| is an out param that will contain
+// the proxies that should be used.
bool ApplyProxyConfigToProxyInfo(const net::ProxyConfig& proxy_config,
const net::ProxyRetryInfoMap& proxy_retry_info,
const GURL& url,
@@ -107,14 +108,13 @@ int64_t CalculateOCLFromOFCL(const net::URLRequest& request);
// received response length. For partial failed responses an estimate is
// provided by scaling received response length based on OFCL and Content-Length
// header.
-int64_t CalculateEffectiveOCL(const net::URLRequest& request);
+int64_t EstimateOriginalBodySize(const net::URLRequest& request,
+ const LoFiDecider* lofi_decider);
-// Given a |request| that went through the Data Reduction Proxy if |used_drp| is
-// true, this function estimates how many bytes would have been received if the
-// response had been received directly from the origin without any data saver
-// optimizations.
+// Given a |request| that went through the Data Reduction Proxy; this function
+// estimates how many bytes would have been received if the response had been
+// received directly from the origin without any data saver optimizations.
int64_t EstimateOriginalReceivedBytes(const net::URLRequest& request,
- bool used_drp,
const LoFiDecider* lofi_decider);
// Converts net::ProxyServer::Scheme to type ProxyScheme.
@@ -166,4 +166,4 @@ std::unique_ptr<Timestamp> CreateTimestampFromTime(const base::Time& time);
} // namespace data_reduction_proxy
-#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_UTIL_H_
+#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_UTIL_H_
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_util_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_util_unittest.cc
index a08273f71e8..9f4c680b3dd 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_util_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_util_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include <stdint.h>
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_usage_store.cc b/chromium/components/data_reduction_proxy/core/browser/data_usage_store.cc
index 41f5fb65332..2c4db6767cf 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_usage_store.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_usage_store.cc
@@ -18,7 +18,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
-#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/proto/data_store.pb.h"
diff --git a/chromium/components/data_reduction_proxy/core/browser/db_data_owner.cc b/chromium/components/data_reduction_proxy/core/browser/db_data_owner.cc
index d416992a93d..1273720c38f 100644
--- a/chromium/components/data_reduction_proxy/core/browser/db_data_owner.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/db_data_owner.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "base/logging.h"
-#include "base/threading/sequenced_worker_pool.h"
#include "components/data_reduction_proxy/core/browser/data_store.h"
#include "components/data_reduction_proxy/core/browser/data_usage_store.h"
#include "components/data_reduction_proxy/proto/data_store.pb.h"
diff --git a/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.cc b/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.cc
index 693b2e7b8f7..a217e23f3bd 100644
--- a/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.cc
@@ -4,12 +4,15 @@
#include "components/data_reduction_proxy/core/browser/network_properties_manager.h"
+#include <vector>
+
#include "base/base64.h"
#include "base/bind.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/clock.h"
#include "base/values.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
#include "components/prefs/scoped_user_pref_update.h"
@@ -46,8 +49,14 @@ base::Optional<NetworkProperties> GetParsedNetworkProperty(
class NetworkPropertiesManager::PrefManager {
public:
- explicit PrefManager(PrefService* pref_service)
- : pref_service_(pref_service), ui_weak_ptr_factory_(this) {}
+ PrefManager(base::Clock* clock, PrefService* pref_service)
+ : clock_(clock), pref_service_(pref_service), ui_weak_ptr_factory_(this) {
+ DCHECK(clock_);
+ DictionaryPrefUpdate update(pref_service_, prefs::kNetworkProperties);
+ base::DictionaryValue* properties_dict = update.Get();
+
+ CleanupOldOrInvalidValues(properties_dict);
+ }
~PrefManager() {}
@@ -111,11 +120,6 @@ class NetworkPropertiesManager::PrefManager {
int64_t timestamp = network_properties.value().last_modified();
- // TODO(tbansal): crbug.com/779219: Consider handling the case when the
- // device clock is moved back. For example, if the clock is moved back
- // by a year, then for the next year, those older entries will have
- // timestamps that are later than any new entries from networks that the
- // user browses.
if (timestamp < earliest_timestamp) {
earliest_timestamp = timestamp;
key_to_delete = &it.first;
@@ -126,6 +130,44 @@ class NetworkPropertiesManager::PrefManager {
properties_dict->RemoveKey(*key_to_delete);
}
+ // Removes all old or invalid values from the dictionary.
+ void CleanupOldOrInvalidValues(base::DictionaryValue* properties_dict) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // Entries that have not been modified during last |kMaxEntryAge| would be
+ // deleted.
+ static constexpr base::TimeDelta kMaxEntryAge =
+ base::TimeDelta::FromDays(30);
+ const base::Time now = clock_->Now();
+
+ std::vector<std::string> keys_to_delete;
+
+ for (const auto& it : properties_dict->DictItems()) {
+ // At most one entry is deleted within this loop since |it| may not
+ // be valid once an entry is deleted from the dictionary.
+ base::Optional<NetworkProperties> network_properties =
+ GetParsedNetworkProperty(it.second);
+ if (!network_properties) {
+ // Delete the corrupted entry.
+ keys_to_delete.push_back(it.first);
+ continue;
+ }
+
+ base::Time timestamp_entry =
+ base::Time::FromJavaTime(network_properties.value().last_modified());
+ base::TimeDelta entry_age = now - timestamp_entry;
+ if (entry_age < base::TimeDelta() || entry_age > kMaxEntryAge) {
+ keys_to_delete.push_back(it.first);
+ continue;
+ }
+ }
+
+ for (const auto& key : keys_to_delete)
+ properties_dict->RemoveKey(key);
+ }
+
+ base::Clock* clock_;
+
// Guaranteed to be non-null during the lifetime of |this|.
PrefService* pref_service_;
@@ -138,15 +180,18 @@ class NetworkPropertiesManager::PrefManager {
};
NetworkPropertiesManager::NetworkPropertiesManager(
+ base::Clock* clock,
PrefService* pref_service,
scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
- : ui_task_runner_(ui_task_runner),
+ : clock_(clock),
+ ui_task_runner_(ui_task_runner),
network_properties_container_(ConvertDictionaryValueToParsedPrefs(
pref_service->GetDictionary(prefs::kNetworkProperties))) {
DCHECK(ui_task_runner_);
DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(clock_);
- pref_manager_.reset(new PrefManager(pref_service));
+ pref_manager_.reset(new PrefManager(clock_, pref_service));
pref_manager_weak_ptr_ = pref_manager_->GetWeakPtr();
ResetWarmupURLFetchMetrics();
@@ -217,7 +262,7 @@ void NetworkPropertiesManager::ResetWarmupURLFetchMetrics() {
void NetworkPropertiesManager::OnChangeInNetworkPropertyOnIOThread() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- network_properties_.set_last_modified(base::Time::Now().ToJavaTime());
+ network_properties_.set_last_modified(clock_->Now().ToJavaTime());
// Remove the entry from the map, if it is already present.
network_properties_container_.erase(network_id_);
network_properties_container_.emplace(
@@ -405,4 +450,4 @@ size_t NetworkPropertiesManager::GetWarmupURLFetchAttemptCounts(
}
}
-} // namespace data_reduction_proxy \ No newline at end of file
+} // namespace data_reduction_proxy
diff --git a/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.h b/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.h
index 550272b1943..b03c1e2f8c9 100644
--- a/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.h
+++ b/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.h
@@ -16,6 +16,7 @@
#include "components/prefs/pref_service.h"
namespace base {
+class Clock;
class Value;
}
@@ -28,6 +29,7 @@ namespace data_reduction_proxy {
class NetworkPropertiesManager {
public:
NetworkPropertiesManager(
+ base::Clock* clock,
PrefService* pref_service,
scoped_refptr<base::SequencedTaskRunner> ui_task_runner);
@@ -109,6 +111,9 @@ class NetworkPropertiesManager {
static NetworkPropertiesContainer ConvertDictionaryValueToParsedPrefs(
const base::Value* value);
+ // Clock used for querying current time. Guaranteed to be non-null.
+ base::Clock* clock_;
+
// Task runner on which prefs should be accessed.
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
diff --git a/chromium/components/data_reduction_proxy/core/browser/network_properties_manager_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/network_properties_manager_unittest.cc
index 723c20f230a..8c369fd3c8e 100644
--- a/chromium/components/data_reduction_proxy/core/browser/network_properties_manager_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/network_properties_manager_unittest.cc
@@ -8,7 +8,9 @@
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/histogram_tester.h"
+#include "base/test/simple_test_clock.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/default_clock.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
@@ -23,7 +25,14 @@ class TestNetworkPropertiesManager : public NetworkPropertiesManager {
TestNetworkPropertiesManager(
PrefService* pref_service,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
- : NetworkPropertiesManager(pref_service, ui_task_runner) {}
+ : TestNetworkPropertiesManager(base::DefaultClock::GetInstance(),
+ pref_service,
+ ui_task_runner) {}
+ TestNetworkPropertiesManager(
+ base::Clock* clock,
+ PrefService* pref_service,
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
+ : NetworkPropertiesManager(clock, pref_service, ui_task_runner) {}
~TestNetworkPropertiesManager() override {}
};
@@ -421,6 +430,66 @@ TEST(NetworkPropertyTest, TestDeleteHistory) {
}
}
+TEST(NetworkPropertyTest, TestDeleteOldValues) {
+ base::HistogramTester histogram_tester;
+ base::SimpleTestClock test_clock;
+ test_clock.SetNow(base::DefaultClock::GetInstance()->Now());
+
+ TestingPrefServiceSimple test_prefs;
+ test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
+ base::MessageLoopForIO loop;
+ TestNetworkPropertiesManager network_properties_manager(
+ &test_clock, &test_prefs, base::ThreadTaskRunnerHandle::Get());
+
+ for (size_t i = 0; i < 5; ++i) {
+ std::string network_id("test" + base::IntToString(i));
+ network_properties_manager.OnChangeInNetworkID(network_id);
+ network_properties_manager.SetIsCaptivePortal(true);
+ }
+
+ test_clock.Advance(base::TimeDelta::FromDays(20));
+
+ for (size_t i = 5; i < 10; ++i) {
+ std::string network_id("test" + base::IntToString(i));
+ network_properties_manager.OnChangeInNetworkID(network_id);
+ network_properties_manager.SetIsCaptivePortal(true);
+ }
+
+ base::RunLoop().RunUntilIdle();
+
+ // Verify the prefs.
+ EXPECT_EQ(10u, test_prefs.GetDictionary(prefs::kNetworkProperties)->size());
+ for (size_t i = 0; i < 10; ++i) {
+ std::string network_id("test" + base::IntToString(i));
+ EXPECT_TRUE(test_prefs.GetDictionary(prefs::kNetworkProperties)
+ ->HasKey(network_id));
+ }
+
+ // Entries should not be cleared since all values are less than 30 days old.
+ {
+ TestNetworkPropertiesManager network_properties_manager_2(
+ &test_clock, &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ for (size_t i = 0; i < 10; ++i) {
+ std::string network_id("test" + base::IntToString(i));
+
+ EXPECT_TRUE(test_prefs.GetDictionary(prefs::kNetworkProperties)
+ ->HasKey(network_id));
+ }
+ }
+
+ // Only the entries from 5 to 9 should be cleared since they are 40 days old.
+ test_clock.Advance(base::TimeDelta::FromDays(20));
+ {
+ TestNetworkPropertiesManager network_properties_manager_3(
+ &test_clock, &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ for (size_t i = 0; i < 10; ++i) {
+ std::string network_id("test" + base::IntToString(i));
+ EXPECT_EQ(i >= 5, test_prefs.GetDictionary(prefs::kNetworkProperties)
+ ->HasKey(network_id));
+ }
+ }
+}
+
} // namespace
} // namespace data_reduction_proxy \ No newline at end of file
diff --git a/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc b/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
index 7c1a58cd1db..a5832ab600d 100644
--- a/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
@@ -9,10 +9,10 @@
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
#include "net/base/load_flags.h"
#include "net/http/http_status_code.h"
diff --git a/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
index 87079356545..494665ade94 100644
--- a/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
@@ -16,11 +16,11 @@
#include "base/test/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/platform_thread.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
+#include "net/base/proxy_server.h"
#include "net/http/http_status_code.h"
#include "net/nqe/network_quality_estimator_test_util.h"
-#include "net/proxy/proxy_server.h"
#include "net/socket/socket_test_util.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_context_getter.h"
@@ -401,7 +401,7 @@ TEST(WarmupURLFetcherTest, TestFetchTimesout) {
success_reads[2] = net::MockRead(net::SYNCHRONOUS, net::OK);
socket_data_providers.push_back(
- (base::MakeUnique<net::StaticSocketDataProvider>(
+ (std::make_unique<net::StaticSocketDataProvider>(
success_reads, arraysize(success_reads), nullptr, 0)));
mock_socket_factory.AddSocketDataProvider(socket_data_providers.back().get());
@@ -461,7 +461,7 @@ TEST(WarmupURLFetcherTest, TestSuccessfulFetchWarmupURLWithDelay) {
success_reads[2] = net::MockRead(net::SYNCHRONOUS, net::OK);
socket_data_providers.push_back(
- (base::MakeUnique<net::StaticSocketDataProvider>(
+ (std::make_unique<net::StaticSocketDataProvider>(
success_reads, arraysize(success_reads), nullptr, 0)));
mock_socket_factory.AddSocketDataProvider(socket_data_providers.back().get());
diff --git a/chromium/components/data_reduction_proxy/core/common/BUILD.gn b/chromium/components/data_reduction_proxy/core/common/BUILD.gn
index 92bcdb0359a..d7930835fe6 100644
--- a/chromium/components/data_reduction_proxy/core/common/BUILD.gn
+++ b/chromium/components/data_reduction_proxy/core/common/BUILD.gn
@@ -31,8 +31,6 @@ template("common_tmpl") {
"data_reduction_proxy_server.h",
"data_reduction_proxy_switches.cc",
"data_reduction_proxy_switches.h",
- "data_reduction_proxy_util.cc",
- "data_reduction_proxy_util.h",
"lofi_decider.h",
"lofi_ui_service.h",
"resource_type_provider.h",
@@ -94,7 +92,6 @@ source_set("unit_tests") {
"data_reduction_proxy_event_store_unittest.cc",
"data_reduction_proxy_headers_unittest.cc",
"data_reduction_proxy_params_unittest.cc",
- "data_reduction_proxy_util_unittest.cc",
]
deps = [
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_event_creator.cc b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_event_creator.cc
index f915a6bfd4f..08fe674a10a 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_event_creator.cc
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_event_creator.cc
@@ -11,11 +11,11 @@
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
+#include "net/base/proxy_server.h"
#include "net/log/net_log.h"
#include "net/log/net_log_entry.h"
#include "net/log/net_log_source.h"
#include "net/log/net_log_with_source.h"
-#include "net/proxy/proxy_server.h"
namespace data_reduction_proxy {
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc
index c5c81780ac7..aede1168105 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc
@@ -15,6 +15,7 @@
#include "base/json/json_writer.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
@@ -27,6 +28,7 @@
#include "components/prefs/testing_pref_service.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
+#include "net/base/proxy_server.h"
#include "net/http/http_status_code.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
@@ -34,7 +36,6 @@
#include "net/log/net_log_with_source.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_entry.h"
-#include "net/proxy/proxy_server.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace data_reduction_proxy {
@@ -225,7 +226,8 @@ TEST_F(DataReductionProxyEventStoreTest, TestFeedbackMethods) {
base::MessageLoopForIO loop;
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- NetworkPropertiesManager manager(&test_prefs,
+ NetworkPropertiesManager manager(base::DefaultClock::GetInstance(),
+ &test_prefs,
base::ThreadTaskRunnerHandle::Get());
DataReductionProxyConfigurator configurator(net_log(), event_creator());
EXPECT_EQ(std::string(), event_store()->GetHttpProxyList());
@@ -252,7 +254,8 @@ TEST_F(DataReductionProxyEventStoreTest, TestFeedbackLastBypassEventFullURL) {
base::MessageLoopForIO loop;
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- NetworkPropertiesManager manager(&test_prefs,
+ NetworkPropertiesManager manager(base::DefaultClock::GetInstance(),
+ &test_prefs,
base::ThreadTaskRunnerHandle::Get());
DataReductionProxyConfigurator configurator(net_log(), event_creator());
std::vector<DataReductionProxyServer> http_proxies;
@@ -290,7 +293,8 @@ TEST_F(DataReductionProxyEventStoreTest, TestFeedbackLastBypassEventHostOnly) {
base::MessageLoopForIO loop;
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- NetworkPropertiesManager manager(&test_prefs,
+ NetworkPropertiesManager manager(base::DefaultClock::GetInstance(),
+ &test_prefs,
base::ThreadTaskRunnerHandle::Get());
DataReductionProxyConfigurator configurator(net_log(), event_creator());
std::vector<DataReductionProxyServer> http_proxies;
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 00c2d361740..29865459826 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
@@ -13,7 +13,7 @@
#include "base/time/time.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
-#include "net/proxy/proxy_service.h"
+#include "net/proxy_resolution/proxy_service.h"
class GURL;
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_headers_unittest.cc b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_headers_unittest.cc
index b3d602f2a6e..28d104f6051 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_headers_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_headers_unittest.cc
@@ -19,7 +19,7 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers_test_utils.h"
#include "net/http/http_response_headers.h"
-#include "net/proxy/proxy_service.h"
+#include "net/proxy_resolution/proxy_service.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
index 5976cbd1efd..0232a10228f 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -18,7 +18,7 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/variations/variations_associated_data.h"
-#include "net/proxy/proxy_server.h"
+#include "net/base/proxy_server.h"
#include "url/url_constants.h"
#if defined(OS_ANDROID)
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 0e2a200dcbf..83b920e41c3 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
@@ -20,7 +20,7 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "components/variations/variations_associated_data.h"
-#include "net/proxy/proxy_server.h"
+#include "net/base/proxy_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_server.h b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_server.h
index 7712db2de21..629b61c3538 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_server.h
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_server.h
@@ -9,7 +9,7 @@
#include "components/data_reduction_proxy/core/common/resource_type_provider.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
-#include "net/proxy/proxy_server.h"
+#include "net/base/proxy_server.h"
namespace data_reduction_proxy {
diff --git a/chromium/components/data_use_measurement/core/data_use_ascriber.cc b/chromium/components/data_use_measurement/core/data_use_ascriber.cc
index f508dd868f4..2f1b66485aa 100644
--- a/chromium/components/data_use_measurement/core/data_use_ascriber.cc
+++ b/chromium/components/data_use_measurement/core/data_use_ascriber.cc
@@ -4,9 +4,9 @@
#include "components/data_use_measurement/core/data_use_ascriber.h"
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "components/data_use_measurement/core/data_use_network_delegate.h"
#include "components/data_use_measurement/core/data_use_recorder.h"
#include "components/data_use_measurement/core/url_request_classifier.h"
@@ -20,7 +20,7 @@ DataUseAscriber::~DataUseAscriber() {}
std::unique_ptr<net::NetworkDelegate> DataUseAscriber::CreateNetworkDelegate(
std::unique_ptr<net::NetworkDelegate> wrapped_network_delegate,
const metrics::UpdateUsagePrefCallbackType& metrics_data_use_forwarder) {
- return base::MakeUnique<data_use_measurement::DataUseNetworkDelegate>(
+ return std::make_unique<data_use_measurement::DataUseNetworkDelegate>(
std::move(wrapped_network_delegate), this, CreateURLRequestClassifier(),
metrics_data_use_forwarder);
}
diff --git a/chromium/components/data_use_measurement/core/data_use_measurement.cc b/chromium/components/data_use_measurement/core/data_use_measurement.cc
index 829f57718a8..da3b36e9299 100644
--- a/chromium/components/data_use_measurement/core/data_use_measurement.cc
+++ b/chromium/components/data_use_measurement/core/data_use_measurement.cc
@@ -7,7 +7,6 @@
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
-#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "components/data_use_measurement/core/data_use_ascriber.h"
@@ -49,19 +48,9 @@ void RecordUMAHistogramCount(const std::string& name, int64_t sample) {
void IncreaseSparseHistogramByValue(const std::string& name,
int64_t sample,
int64_t value) {
- // Convert raw value to KiB and probabilistically round up/down if the
- // remainder is more than a random number [0, 1KiB). This gives a more
- // accurate count when there are a large number of records. RandInt is
- // "inclusive", hence the -1 for the max value.
- int64_t value_kb = value >> 10;
- if (value - (value_kb << 10) > base::RandInt(0, (1 << 10) - 1))
- value_kb += 1;
- if (value_kb == 0)
- return;
-
base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
name + "KB", base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->AddCount(sample, value_kb);
+ histogram->AddKiB(sample, value);
}
#if defined(OS_ANDROID)
@@ -405,9 +394,6 @@ void DataUseMeasurement::ReportDataUsageServices(
DataUseUserData::AppState app_state,
bool is_connection_cellular,
int64_t message_size) const {
- RecordUMAHistogramCount(
- "DataUse.MessageSize." + DataUseUserData::GetServiceNameAsString(service),
- message_size);
if (message_size > 0) {
IncreaseSparseHistogramByValue(
GetHistogramName("DataUse.MessageSize.AllServices", dir, app_state,
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 d0e37c1ffb7..f4538382151 100644
--- a/chromium/components/data_use_measurement/core/data_use_measurement.h
+++ b/chromium/components/data_use_measurement/core/data_use_measurement.h
@@ -123,9 +123,8 @@ class DataUseMeasurement {
void ReportServicesMessageSizeUMA(const net::URLRequest& request);
// Records data use histograms of services. It gets the size of exchanged
- // message, its direction (which is upstream or downstream) and reports to two
- // histogram groups. DataUse.MessageSize.ServiceName and
- // DataUse.Services.{Dimensions}. In the second one, services are buckets.
+ // message, its direction (which is upstream or downstream) and reports to the
+ // histogram DataUse.Services.{Dimensions} with, services as the buckets.
// |app_state| indicates the app state which can be foreground, background, or
// unknown.
void ReportDataUsageServices(
diff --git a/chromium/components/data_use_measurement/core/data_use_measurement_unittest.cc b/chromium/components/data_use_measurement/core/data_use_measurement_unittest.cc
index c2aed267010..a91c363b7ff 100644
--- a/chromium/components/data_use_measurement/core/data_use_measurement_unittest.cc
+++ b/chromium/components/data_use_measurement/core/data_use_measurement_unittest.cc
@@ -8,7 +8,6 @@
#include <string>
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/test/histogram_tester.h"
@@ -44,7 +43,7 @@ class TestURLRequestClassifier : public base::SupportsUserData::Data,
static void MarkAsUserRequest(net::URLRequest* request) {
request->SetUserData(kUserDataKey,
- base::MakeUnique<TestURLRequestClassifier>());
+ std::make_unique<TestURLRequestClassifier>());
}
DataUseUserData::DataUseContentType GetContentType(
@@ -143,7 +142,7 @@ class DataUseMeasurementTest : public testing::Test {
} else {
request->SetUserData(
data_use_measurement::DataUseUserData::kUserDataKey,
- base::MakeUnique<data_use_measurement::DataUseUserData>(
+ std::make_unique<data_use_measurement::DataUseUserData>(
data_use_measurement::DataUseUserData::SUGGESTIONS,
data_use_measurement_.CurrentAppState()));
}
@@ -196,8 +195,6 @@ class DataUseMeasurementTest : public testing::Test {
histogram_tester.ExpectTotalCount("DataUse.TrafficSize.System.Upstream." +
target_dimension + kConnectionType,
1);
- // One upload and one download message, so total count should be 2.
- histogram_tester.ExpectTotalCount("DataUse.MessageSize.Suggestions", 2);
}
DataUseMeasurement* data_use_measurement() { return &data_use_measurement_; }
diff --git a/chromium/components/data_use_measurement/core/data_use_network_delegate_unittest.cc b/chromium/components/data_use_measurement/core/data_use_network_delegate_unittest.cc
index fda5be088d1..6423e459861 100644
--- a/chromium/components/data_use_measurement/core/data_use_network_delegate_unittest.cc
+++ b/chromium/components/data_use_measurement/core/data_use_network_delegate_unittest.cc
@@ -4,7 +4,8 @@
#include "components/data_use_measurement/core/data_use_network_delegate.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/test/histogram_tester.h"
@@ -33,7 +34,7 @@ class TestURLRequestClassifier : public base::SupportsUserData::Data,
static void MarkAsUserRequest(net::URLRequest* request) {
request->SetUserData(kUserDataKey,
- base::MakeUnique<TestURLRequestClassifier>());
+ std::make_unique<TestURLRequestClassifier>());
}
DataUseUserData::DataUseContentType GetContentType(
@@ -112,7 +113,7 @@ std::unique_ptr<net::URLRequest> RequestURL(
} else {
request->SetUserData(
data_use_measurement::DataUseUserData::kUserDataKey,
- base::MakeUnique<data_use_measurement::DataUseUserData>(
+ std::make_unique<data_use_measurement::DataUseUserData>(
data_use_measurement::DataUseUserData::SUGGESTIONS,
data_use_measurement::DataUseUserData::FOREGROUND));
}
@@ -125,9 +126,9 @@ class DataUseNetworkDelegateTest : public testing::Test {
public:
DataUseNetworkDelegateTest()
: context_(true),
- data_use_network_delegate_(base::MakeUnique<net::TestNetworkDelegate>(),
+ data_use_network_delegate_(std::make_unique<net::TestNetworkDelegate>(),
&test_data_use_ascriber_,
- base::MakeUnique<TestURLRequestClassifier>(),
+ std::make_unique<TestURLRequestClassifier>(),
metrics::UpdateUsagePrefCallbackType()) {
context_.set_client_socket_factory(&mock_socket_factory_);
context_.set_network_delegate(&data_use_network_delegate_);
@@ -149,9 +150,8 @@ class DataUseNetworkDelegateTest : public testing::Test {
// This function tests data use measurement for requests by services. it makes a
// query which is similar to a query of a service, so it should affect
-// DataUse.TrafficSize.System.Dimensions and DataUse.MessageSize.ServiceName
-// histograms. AppState and ConnectionType dimensions are always Foreground and
-// NotCellular respectively.
+// DataUse.TrafficSize.System.Dimensions histogram. AppState and ConnectionType
+// dimensions are always Foreground and NotCellular respectively.
TEST_F(DataUseNetworkDelegateTest, DataUseMeasurementServiceTest) {
base::HistogramTester histogram_tester;
@@ -164,9 +164,6 @@ TEST_F(DataUseNetworkDelegateTest, DataUseMeasurementServiceTest) {
.empty());
histogram_tester.ExpectTotalCount(
"DataUse.TrafficSize.System.Upstream.Foreground.NotCellular", 1);
- EXPECT_FALSE(histogram_tester
- .GetTotalCountsForPrefix("DataUse.MessageSize.Suggestions")
- .empty());
histogram_tester.ExpectTotalCount(
"DataUse.TrafficSize.User.Downstream.Foreground.NotCellular", 0);
histogram_tester.ExpectTotalCount(
@@ -193,14 +190,13 @@ TEST_F(DataUseNetworkDelegateTest, DataUseMeasurementUserTest) {
"DataUse.TrafficSize.System.Downstream.Foreground.NotCellular", 0);
histogram_tester.ExpectTotalCount(
"DataUse.TrafficSize.System.Upstream.Foreground.NotCellular", 0);
- histogram_tester.ExpectTotalCount("DataUse.MessageSize.Suggestions", 0);
}
// This function tests data use measurement for requests by services in case the
// request is redirected once. it makes a query which is similar to a query of a
// service, so it should affect DataUse.TrafficSize.System.Dimensions and
-// DataUse.MessageSize.ServiceName histograms. AppState and ConnectionType
-// dimensions are always Foreground and NotCellular respectively.
+// histogram. AppState and ConnectionType dimensions are always Foreground and
+// NotCellular respectively.
TEST_F(DataUseNetworkDelegateTest, DataUseMeasurementServiceTestWithRedirect) {
base::HistogramTester histogram_tester;
@@ -214,9 +210,6 @@ TEST_F(DataUseNetworkDelegateTest, DataUseMeasurementServiceTestWithRedirect) {
histogram_tester.ExpectTotalCount(
"DataUse.TrafficSize.System.Upstream.Foreground.NotCellular", 2);
// Two uploads and two downloads message, so totalCount should be 4.
- EXPECT_FALSE(histogram_tester
- .GetTotalCountsForPrefix("DataUse.MessageSize.Suggestions")
- .empty());
histogram_tester.ExpectTotalCount(
"DataUse.TrafficSize.User.Downstream.Foreground.NotCellular", 0);
histogram_tester.ExpectTotalCount(
@@ -244,7 +237,6 @@ TEST_F(DataUseNetworkDelegateTest, DataUseMeasurementUserTestWithRedirect) {
"DataUse.TrafficSize.System.Downstream.Foreground.NotCellular", 0);
histogram_tester.ExpectTotalCount(
"DataUse.TrafficSize.System.Upstream.Foreground.NotCellular", 0);
- histogram_tester.ExpectTotalCount("DataUse.MessageSize.Suggestions", 0);
}
} // namespace
diff --git a/chromium/components/data_use_measurement/core/data_use_user_data.cc b/chromium/components/data_use_measurement/core/data_use_user_data.cc
index d164110ee36..ca3bb4f0c67 100644
--- a/chromium/components/data_use_measurement/core/data_use_user_data.cc
+++ b/chromium/components/data_use_measurement/core/data_use_user_data.cc
@@ -4,11 +4,12 @@
#include "components/data_use_measurement/core/data_use_user_data.h"
+#include <memory>
+
#if defined(OS_ANDROID)
#include "base/android/application_status_listener.h"
#endif
-#include "base/memory/ptr_util.h"
#include "net/url_request/url_fetcher.h"
namespace data_use_measurement {
@@ -43,7 +44,7 @@ const void* const DataUseUserData::kUserDataKey =
// static
std::unique_ptr<base::SupportsUserData::Data> DataUseUserData::Create(
ServiceName service_name) {
- return base::MakeUnique<DataUseUserData>(service_name, GetCurrentAppState());
+ return std::make_unique<DataUseUserData>(service_name, GetCurrentAppState());
}
// static
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 e97180e53af..337e1eb9e13 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
@@ -7,6 +7,7 @@
#include <inttypes.h>
#include <algorithm>
+#include <memory>
#include <utility>
#include "base/atomic_sequence_num.h"
@@ -14,7 +15,6 @@
#include "base/macros.h"
#include "base/memory/discardable_memory.h"
#include "base/memory/discardable_shared_memory.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/memory.h"
#include "base/process/process_metrics.h"
@@ -108,8 +108,8 @@ ClientDiscardableSharedMemoryManager::ClientDiscardableSharedMemoryManager(
base::ThreadTaskRunnerHandle::Get());
mojom::DiscardableSharedMemoryManagerPtrInfo info = manager.PassInterface();
io_task_runner_->PostTask(
- FROM_HERE, base::Bind(&InitManagerMojoOnIO, manager_mojo_.get(),
- base::Passed(&info)));
+ FROM_HERE, base::BindOnce(&InitManagerMojoOnIO, manager_mojo_.get(),
+ std::move(info)));
}
ClientDiscardableSharedMemoryManager::~ClientDiscardableSharedMemoryManager() {
@@ -191,7 +191,7 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
// at least one span from the free lists.
MemoryUsageChanged(heap_->GetSize(), heap_->GetSizeOfFreeLists());
- return base::MakeUnique<DiscardableMemoryImpl>(this, std::move(free_span));
+ return std::make_unique<DiscardableMemoryImpl>(this, std::move(free_span));
}
// Release purged memory to free up the address space before we attempt to
@@ -237,7 +237,7 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
MemoryUsageChanged(heap_->GetSize(), heap_->GetSizeOfFreeLists());
- return base::MakeUnique<DiscardableMemoryImpl>(this, std::move(new_span));
+ return std::make_unique<DiscardableMemoryImpl>(this, std::move(new_span));
}
bool ClientDiscardableSharedMemoryManager::OnMemoryDump(
@@ -363,12 +363,13 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
base::ScopedClosureRunner event_signal_runner(
base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
io_task_runner_->PostTask(
- FROM_HERE, base::Bind(&ClientDiscardableSharedMemoryManager::AllocateOnIO,
- base::Unretained(this), size, id, &handle,
- base::Passed(&event_signal_runner)));
+ FROM_HERE,
+ base::BindOnce(&ClientDiscardableSharedMemoryManager::AllocateOnIO,
+ base::Unretained(this), size, id, &handle,
+ std::move(event_signal_runner)));
// Waiting until IPC has finished on the IO thread.
event.Wait();
- auto memory = base::MakeUnique<base::DiscardableSharedMemory>(handle);
+ auto memory = std::make_unique<base::DiscardableSharedMemory>(handle);
if (!memory->Map(size))
base::TerminateBecauseOutOfMemory(size);
return memory;
@@ -382,9 +383,9 @@ void ClientDiscardableSharedMemoryManager::AllocateOnIO(
(*manager_mojo_)
->AllocateLockedDiscardableSharedMemory(
static_cast<uint32_t>(size), id,
- base::Bind(
+ base::BindOnce(
&ClientDiscardableSharedMemoryManager::AllocateCompletedOnIO,
- base::Unretained(this), handle, base::Passed(&closure_runner)));
+ base::Unretained(this), handle, std::move(closure_runner)));
}
void ClientDiscardableSharedMemoryManager::AllocateCompletedOnIO(
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 b8f2b0d0c90..b650e58a615 100644
--- a/chromium/components/discardable_memory/common/discardable_shared_memory_heap.cc
+++ b/chromium/components/discardable_memory/common/discardable_shared_memory_heap.cc
@@ -5,6 +5,7 @@
#include "components/discardable_memory/common/discardable_shared_memory_heap.h"
#include <algorithm>
+#include <memory>
#include <utility>
#include "base/format_macros.h"
@@ -131,7 +132,7 @@ DiscardableSharedMemoryHeap::Grow(
num_blocks_ += span->length_;
// Start tracking if segment is resident by adding it to |memory_segments_|.
- memory_segments_.push_back(base::MakeUnique<ScopedMemorySegment>(
+ memory_segments_.push_back(std::make_unique<ScopedMemorySegment>(
this, std::move(shared_memory), size, id, deleted_callback));
return span;
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 4306a3a56ec..7ddb4263261 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
@@ -8,12 +8,12 @@
#include <algorithm>
#include <cmath>
#include <cstdlib>
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/memory/discardable_shared_memory.h"
-#include "base/memory/ptr_util.h"
#include "base/process/process_metrics.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"
@@ -73,9 +73,9 @@ TEST(DiscardableSharedMemoryHeapTest, SearchFreeLists) {
std::unique_ptr<DiscardableSharedMemoryHeap::Span> span =
heap.SearchFreeLists(random_blocks[i], slack);
if (span) {
- spans.push_back(base::MakeUnique<base::ScopedClosureRunner>(
- base::Bind(&DiscardableSharedMemoryHeap::MergeIntoFreeLists,
- base::Unretained(&heap), base::Passed(&span))));
+ spans.push_back(std::make_unique<base::ScopedClosureRunner>(
+ base::BindOnce(&DiscardableSharedMemoryHeap::MergeIntoFreeLists,
+ base::Unretained(&heap), std::move(span))));
} else if (!spans.empty()) {
// Merge a random span back into the free list.
std::swap(spans[random_span[i] % spans.size()], spans.back());
diff --git a/chromium/components/dom_distiller/content/browser/distillability_driver.cc b/chromium/components/dom_distiller/content/browser/distillability_driver.cc
index 0ec73fb632a..37f9d5c1266 100644
--- a/chromium/components/dom_distiller/content/browser/distillability_driver.cc
+++ b/chromium/components/dom_distiller/content/browser/distillability_driver.cc
@@ -4,7 +4,8 @@
#include "components/dom_distiller/content/browser/distillability_driver.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
@@ -57,7 +58,7 @@ DistillabilityDriver::~DistillabilityDriver() {
void DistillabilityDriver::CreateDistillabilityService(
mojom::DistillabilityServiceRequest request) {
mojo::MakeStrongBinding(
- base::MakeUnique<DistillabilityServiceImpl>(weak_factory_.GetWeakPtr()),
+ std::make_unique<DistillabilityServiceImpl>(weak_factory_.GetWeakPtr()),
std::move(request));
}
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 8ef96066657..80c03518e77 100644
--- a/chromium/components/dom_distiller/content/browser/distillable_page_utils.cc
+++ b/chromium/components/dom_distiller/content/browser/distillable_page_utils.cc
@@ -21,15 +21,6 @@
namespace dom_distiller {
namespace {
-void OnOGArticleJsResult(base::Callback<void(bool)> callback,
- const base::Value* result) {
- bool success = false;
- if (result) {
- result->GetAsBoolean(&success);
- }
- callback.Run(success);
-}
-
void OnExtractFeaturesJsResult(const DistillablePageDetector* detector,
base::Callback<void(bool)> callback,
const base::Value* result) {
@@ -37,50 +28,6 @@ void OnExtractFeaturesJsResult(const DistillablePageDetector* detector,
}
} // namespace
-void IsOpenGraphArticle(content::WebContents* web_contents,
- base::Callback<void(bool)> callback) {
- content::RenderFrameHost* main_frame = web_contents->GetMainFrame();
- if (!main_frame) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::Bind(callback, false));
- return;
- }
- std::string og_article_js = ui::ResourceBundle::GetSharedInstance()
- .GetRawDataResource(IDR_IS_DISTILLABLE_JS)
- .as_string();
- RunIsolatedJavaScript(main_frame, og_article_js,
- base::Bind(OnOGArticleJsResult, callback));
-}
-
-void IsDistillablePage(content::WebContents* web_contents,
- bool is_mobile_optimized,
- base::Callback<void(bool)> callback) {
- switch (GetDistillerHeuristicsType()) {
- case DistillerHeuristicsType::ALWAYS_TRUE:
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::Bind(callback, true));
- return;
- case DistillerHeuristicsType::OG_ARTICLE:
- IsOpenGraphArticle(web_contents, callback);
- return;
- case DistillerHeuristicsType::ADABOOST_MODEL:
- // The adaboost model is only applied to non-mobile pages.
- if (is_mobile_optimized) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, false));
- return;
- }
- IsDistillablePageForDetector(
- web_contents, DistillablePageDetector::GetDefault(), callback);
- return;
- case DistillerHeuristicsType::NONE:
- default:
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, false));
- return;
- }
-}
-
void IsDistillablePageForDetector(content::WebContents* web_contents,
const DistillablePageDetector* detector,
base::Callback<void(bool)> callback) {
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 d2805d60dd8..e6f31c559c5 100644
--- a/chromium/components/dom_distiller/content/browser/distillable_page_utils.h
+++ b/chromium/components/dom_distiller/content/browser/distillable_page_utils.h
@@ -12,16 +12,6 @@ namespace dom_distiller {
class DistillablePageDetector;
-// Checks if the page appears to be distillable based on whichever heuristics
-// are configured to be used (see dom_distiller::GetDistillerHeuristicsType).
-void IsDistillablePage(content::WebContents* web_contents,
- bool is_mobile_optimized,
- base::Callback<void(bool)> callback);
-
-// Checks if the web_contents is has opengraph type=article markup.
-void IsOpenGraphArticle(content::WebContents* web_contents,
- base::Callback<void(bool)> callback);
-
// Uses the provided DistillablePageDetector to detect if the page is
// distillable. The passed detector must be alive until after the callback is
// called.
diff --git a/chromium/components/dom_distiller/content/browser/distillable_page_utils_android.cc b/chromium/components/dom_distiller/content/browser/distillable_page_utils_android.cc
index 69a880e1ddd..b998842bd45 100644
--- a/chromium/components/dom_distiller/content/browser/distillable_page_utils_android.cc
+++ b/chromium/components/dom_distiller/content/browser/distillable_page_utils_android.cc
@@ -19,12 +19,6 @@ using base::android::ScopedJavaGlobalRef;
namespace dom_distiller {
namespace android {
namespace {
-void OnIsPageDistillableResult(const JavaRef<jobject>& callback,
- bool isDistillable) {
- Java_DistillablePageUtils_callOnIsPageDistillableResult(
- base::android::AttachCurrentThread(), callback, isDistillable);
-}
-
void OnIsPageDistillableUpdate(const JavaRef<jobject>& callback,
bool isDistillable,
bool isLast,
@@ -35,27 +29,6 @@ void OnIsPageDistillableUpdate(const JavaRef<jobject>& callback,
}
} // namespace
-static void JNI_DistillablePageUtils_IsPageDistillable(
- JNIEnv* env,
- const JavaParamRef<jclass>& jcaller,
- const JavaParamRef<jobject>& webContents,
- jboolean is_mobile_optimized,
- const JavaParamRef<jobject>& callback) {
- content::WebContents* web_contents(
- content::WebContents::FromJavaWebContents(webContents));
-
- if (!web_contents) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(OnIsPageDistillableResult,
- ScopedJavaGlobalRef<jobject>(env, callback), false));
- return;
- }
- IsDistillablePage(web_contents, is_mobile_optimized,
- base::Bind(OnIsPageDistillableResult,
- ScopedJavaGlobalRef<jobject>(env, callback)));
-}
-
static void JNI_DistillablePageUtils_SetDelegate(
JNIEnv* env,
const JavaParamRef<jclass>& jcaller,
diff --git a/chromium/components/dom_distiller/content/browser/distillable_page_utils_browsertest.cc b/chromium/components/dom_distiller/content/browser/distillable_page_utils_browsertest.cc
index 99cee028959..43a6f040035 100644
--- a/chromium/components/dom_distiller/content/browser/distillable_page_utils_browsertest.cc
+++ b/chromium/components/dom_distiller/content/browser/distillable_page_utils_browsertest.cc
@@ -26,7 +26,6 @@ namespace dom_distiller {
namespace {
const char* kArticlePath = "/og_article.html";
-const char* kNonArticlePath = "/non_og_article.html";
class DomDistillerDistillablePageUtilsTest : public content::ContentBrowserTest,
content::WebContentsObserver {
@@ -112,25 +111,6 @@ class ResultHolder {
} // namespace
-IN_PROC_BROWSER_TEST_F(DomDistillerDistillablePageUtilsTest, TestIsOGArticle) {
- LoadURL(kArticlePath);
- base::RunLoop run_loop_;
- ResultHolder holder(run_loop_.QuitClosure());
- IsOpenGraphArticle(shell()->web_contents(), holder.GetCallback());
- run_loop_.Run();
- ASSERT_TRUE(holder.GetResult());
-}
-
-IN_PROC_BROWSER_TEST_F(DomDistillerDistillablePageUtilsTest,
- TestIsNotOGArticle) {
- LoadURL(kNonArticlePath);
- base::RunLoop run_loop_;
- ResultHolder holder(run_loop_.QuitClosure());
- IsOpenGraphArticle(shell()->web_contents(), holder.GetCallback());
- run_loop_.Run();
- ASSERT_FALSE(holder.GetResult());
-}
-
IN_PROC_BROWSER_TEST_F(DomDistillerDistillablePageUtilsTest,
TestIsDistillablePage) {
std::unique_ptr<AdaBoostProto> proto(new AdaBoostProto);
diff --git a/chromium/components/dom_distiller/content/browser/distiller_javascript_service_impl.cc b/chromium/components/dom_distiller/content/browser/distiller_javascript_service_impl.cc
index 847a63b7159..304bf7146d3 100644
--- a/chromium/components/dom_distiller/content/browser/distiller_javascript_service_impl.cc
+++ b/chromium/components/dom_distiller/content/browser/distiller_javascript_service_impl.cc
@@ -4,9 +4,9 @@
#include "components/dom_distiller/content/browser/distiller_javascript_service_impl.h"
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "base/metrics/user_metrics.h"
#include "components/dom_distiller/content/browser/distiller_ui_handle.h"
#include "components/dom_distiller/core/feedback_reporter.h"
@@ -35,7 +35,7 @@ void CreateDistillerJavaScriptService(
DistillerUIHandle* distiller_ui_handle,
mojom::DistillerJavaScriptServiceRequest request,
content::RenderFrameHost* render_frame_host) {
- mojo::MakeStrongBinding(base::MakeUnique<DistillerJavaScriptServiceImpl>(
+ mojo::MakeStrongBinding(std::make_unique<DistillerJavaScriptServiceImpl>(
render_frame_host, distiller_ui_handle),
std::move(request));
}
diff --git a/chromium/components/dom_distiller/content/browser/distiller_page_web_contents.cc b/chromium/components/dom_distiller/content/browser/distiller_page_web_contents.cc
index 3c92a8c6737..9c821be249e 100644
--- a/chromium/components/dom_distiller/content/browser/distiller_page_web_contents.cc
+++ b/chromium/components/dom_distiller/content/browser/distiller_page_web_contents.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "base/callback.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "components/dom_distiller/content/browser/distiller_javascript_utils.h"
@@ -168,7 +167,7 @@ void DistillerPageWebContents::DidFailLoad(
content::WebContentsObserver::Observe(nullptr);
DCHECK(state_ == LOADING_PAGE || state_ == EXECUTING_JAVASCRIPT);
state_ = PAGELOAD_FAILED;
- auto empty = base::MakeUnique<base::Value>();
+ auto empty = std::make_unique<base::Value>();
OnWebContentsDistillationDone(GURL(), base::TimeTicks(), empty.get());
}
}
diff --git a/chromium/components/dom_distiller/content/browser/web_contents_main_frame_observer_unittest.cc b/chromium/components/dom_distiller/content/browser/web_contents_main_frame_observer_unittest.cc
index 91eef8f122f..2d76ff736e8 100644
--- a/chromium/components/dom_distiller/content/browser/web_contents_main_frame_observer_unittest.cc
+++ b/chromium/components/dom_distiller/content/browser/web_contents_main_frame_observer_unittest.cc
@@ -28,7 +28,7 @@ class WebContentsMainFrameObserverTest
ASSERT_FALSE(main_frame_observer_->is_document_loaded_in_main_frame());
}
- void Navigate(bool main_frame, bool in_page) {
+ void Navigate(bool main_frame, bool same_document) {
content::RenderFrameHost* rfh = main_rfh();
content::RenderFrameHostTester* rfh_tester =
content::RenderFrameHostTester::For(rfh);
@@ -36,7 +36,7 @@ class WebContentsMainFrameObserverTest
rfh = rfh_tester->AppendChild("subframe");
std::unique_ptr<content::NavigationHandle> navigation_handle =
content::NavigationHandle::CreateNavigationHandleForTesting(
- GURL(), rfh, true, net::OK, in_page);
+ GURL(), rfh, true, net::OK, same_document);
// Destructor calls DidFinishNavigation.
}
@@ -59,20 +59,20 @@ TEST_F(WebContentsMainFrameObserverTest, IgnoresChildFrameNavigation) {
ASSERT_FALSE(main_frame_observer_->is_document_loaded_in_main_frame());
}
-TEST_F(WebContentsMainFrameObserverTest, IgnoresInPageNavigation) {
+TEST_F(WebContentsMainFrameObserverTest, IgnoresSameDocumentNavigation) {
Navigate(true, true);
ASSERT_FALSE(main_frame_observer_->is_initialized());
ASSERT_FALSE(main_frame_observer_->is_document_loaded_in_main_frame());
}
TEST_F(WebContentsMainFrameObserverTest,
- IgnoresInPageNavigationUnlessMainFrameLoads) {
+ IgnoresSameDocumentavigationUnlessMainFrameLoads) {
Navigate(true, true);
ASSERT_FALSE(main_frame_observer_->is_initialized());
ASSERT_FALSE(main_frame_observer_->is_document_loaded_in_main_frame());
- // Even if we didn't acknowledge an in_page navigation, if the main frame
- // loads, consider a load complete.
+ // Even if we didn't acknowledge a same-document navigation, if the main
+ // frame loads, consider a load complete.
main_frame_observer_->DocumentLoadedInFrame(main_rfh());
ASSERT_TRUE(main_frame_observer_->is_document_loaded_in_main_frame());
}
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 1e42153998c..a855560dbd5 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
@@ -4,10 +4,10 @@
#include "components/dom_distiller/content/renderer/distiller_js_render_frame_observer.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
-#include "base/memory/ptr_util.h"
#include "components/dom_distiller/content/common/distiller_page_notifier_service.mojom.h"
#include "components/dom_distiller/content/renderer/distiller_page_notifier_service_impl.h"
#include "content/public/renderer/render_frame.h"
@@ -61,7 +61,7 @@ void DistillerJsRenderFrameObserver::CreateDistillerPageNotifierService(
if (!load_active_)
return;
mojo::MakeStrongBinding(
- base::MakeUnique<DistillerPageNotifierServiceImpl>(this),
+ std::make_unique<DistillerPageNotifierServiceImpl>(this),
std::move(request));
}
diff --git a/chromium/components/dom_distiller/content/renderer/distiller_native_javascript.cc b/chromium/components/dom_distiller/content/renderer/distiller_native_javascript.cc
index ae6959a7074..0af444efd24 100644
--- a/chromium/components/dom_distiller/content/renderer/distiller_native_javascript.cc
+++ b/chromium/components/dom_distiller/content/renderer/distiller_native_javascript.cc
@@ -42,19 +42,19 @@ void DistillerNativeJavaScript::AddJavaScriptObjectToFrame(
// wrapper function for binding. Note that calling distiller_js_service.get()
// does not transfer ownership of the interface.
BindFunctionToObject(
- distiller_obj, "openSettings",
+ isolate, distiller_obj, "openSettings",
base::Bind(
&mojom::DistillerJavaScriptService::HandleDistillerOpenSettingsCall,
base::Unretained(distiller_js_service_.get())));
}
-template<typename Sig>
+template <typename Sig>
void DistillerNativeJavaScript::BindFunctionToObject(
+ v8::Isolate* isolate,
v8::Local<v8::Object> javascript_object,
const std::string& name,
const base::Callback<Sig> callback) {
// Get the isolate associated with this object.
- v8::Isolate* isolate = javascript_object->GetIsolate();
javascript_object->Set(
gin::StringToSymbol(isolate, name),
gin::CreateFunctionTemplate(isolate, callback)->GetFunction());
diff --git a/chromium/components/dom_distiller/content/renderer/distiller_native_javascript.h b/chromium/components/dom_distiller/content/renderer/distiller_native_javascript.h
index 28078f09639..ecea4776ecd 100644
--- a/chromium/components/dom_distiller/content/renderer/distiller_native_javascript.h
+++ b/chromium/components/dom_distiller/content/renderer/distiller_native_javascript.h
@@ -26,8 +26,9 @@ class DistillerNativeJavaScript {
private:
// Add a function to the provided object.
- template<typename Sig>
- void BindFunctionToObject(v8::Local<v8::Object> javascript_object,
+ template <typename Sig>
+ void BindFunctionToObject(v8::Isolate* isolate,
+ v8::Local<v8::Object> javascript_object,
const std::string& name,
const base::Callback<Sig> callback);
// Make sure the mojo service is connected.
diff --git a/chromium/components/dom_distiller/core/BUILD.gn b/chromium/components/dom_distiller/core/BUILD.gn
index f190917d3eb..63fe88e0519 100644
--- a/chromium/components/dom_distiller/core/BUILD.gn
+++ b/chromium/components/dom_distiller/core/BUILD.gn
@@ -4,8 +4,6 @@
static_library("core") {
sources = [
- "article_attachments_data.cc",
- "article_attachments_data.h",
"article_distillation_update.cc",
"article_distillation_update.h",
"article_entry.cc",
diff --git a/chromium/components/dom_distiller/core/article_attachments_data.cc b/chromium/components/dom_distiller/core/article_attachments_data.cc
deleted file mode 100644
index c888c00271b..00000000000
--- a/chromium/components/dom_distiller/core/article_attachments_data.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/dom_distiller/core/article_attachments_data.h"
-
-#include "base/logging.h"
-
-namespace dom_distiller {
-
-syncer::AttachmentIdList GetAttachmentIds(
- const sync_pb::ArticleAttachments& attachments) {
- syncer::AttachmentIdList ids;
- ids.push_back(
- syncer::AttachmentId::CreateFromProto(attachments.distilled_article()));
- return ids;
-}
-
-std::unique_ptr<ArticleAttachmentsData>
-ArticleAttachmentsData::GetFromAttachmentMap(
- const sync_pb::ArticleAttachments& attachments_key,
- const syncer::AttachmentMap& attachment_map) {
- std::unique_ptr<ArticleAttachmentsData> data(new ArticleAttachmentsData);
- syncer::AttachmentMap::const_iterator iter =
- attachment_map.find(syncer::AttachmentId::CreateFromProto(
- attachments_key.distilled_article()));
- CHECK(iter != attachment_map.end());
- scoped_refptr<base::RefCountedMemory> attachment_bytes =
- iter->second.GetData();
- data->distilled_article_.ParseFromArray(attachment_bytes->front(),
- attachment_bytes->size());
- return data;
-}
-
-void ArticleAttachmentsData::CreateSyncAttachments(
- syncer::AttachmentList* attachment_list,
- sync_pb::ArticleAttachments* attachments_key) const {
- CHECK(attachment_list);
- CHECK(attachments_key);
- std::string serialized_article(distilled_article_.SerializeAsString());
- syncer::Attachment attachment(
- syncer::Attachment::Create(
- base::RefCountedString::TakeString(&serialized_article)));
- *attachments_key->mutable_distilled_article() =
- attachment.GetId().GetProto();
- attachment_list->push_back(attachment);
-}
-
-std::string ArticleAttachmentsData::ToString() const {
- return distilled_article_.SerializeAsString();
-}
-
-} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/core/article_attachments_data.h b/chromium/components/dom_distiller/core/article_attachments_data.h
deleted file mode 100644
index fc21cd51a0d..00000000000
--- a/chromium/components/dom_distiller/core/article_attachments_data.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_DOM_DISTILLER_CORE_ARTICLE_ATTACHMENTS_DATA_H_
-#define COMPONENTS_DOM_DISTILLER_CORE_ARTICLE_ATTACHMENTS_DATA_H_
-
-#include <memory>
-#include <string>
-
-#include "components/dom_distiller/core/proto/distilled_article.pb.h"
-#include "components/sync/model/attachments/attachment.h"
-#include "components/sync/protocol/article_specifics.pb.h"
-
-namespace dom_distiller {
-
-// When stored, article attachments are split into two pieces, the actual data
-// is stored by a set of ids in some attachment storage. The mapping of what
-// each id corresponds to is stored in the ArticleEntry's
-// sync_pb::ArticleAttachments. This class handles splitting into those two
-// pieces (::CreateSyncAttachments) and reconstructing the data from the two
-// pieces (::GetFromAttachmentMap and ::GetAttachmentIds). Outside of this
-// class, the structure of sync_pb::ArticleAttachments (the id mapping) should
-// be rather opaque.
-class ArticleAttachmentsData {
- public:
- static std::unique_ptr<ArticleAttachmentsData> GetFromAttachmentMap(
- const sync_pb::ArticleAttachments& attachments_key,
- const syncer::AttachmentMap& attachment_map);
-
- // Creates sync attachments and the sync_pb::ArticleAttachments id map.
- void CreateSyncAttachments(
- syncer::AttachmentList* attachment_list,
- sync_pb::ArticleAttachments* attachments_key) const;
-
- const DistilledArticleProto& distilled_article() const {
- return distilled_article_;
- }
- void set_distilled_article(const DistilledArticleProto& article) {
- distilled_article_ = article;
- }
-
- std::string ToString() const;
- private:
- DistilledArticleProto distilled_article_;
-};
-
-syncer::AttachmentIdList GetAttachmentIds(
- const sync_pb::ArticleAttachments& attachments);
-
-} // namespace dom_distiller
-
-#endif // COMPONENTS_DOM_DISTILLER_CORE_ARTICLE_ATTACHMENTS_DATA_H_
diff --git a/chromium/components/dom_distiller/core/article_entry.cc b/chromium/components/dom_distiller/core/article_entry.cc
index 750017c2c4f..076f5190941 100644
--- a/chromium/components/dom_distiller/core/article_entry.cc
+++ b/chromium/components/dom_distiller/core/article_entry.cc
@@ -5,7 +5,6 @@
#include "components/dom_distiller/core/article_entry.h"
#include "base/logging.h"
-#include "components/dom_distiller/core/article_attachments_data.h"
#include "components/sync/model/sync_change.h"
using sync_pb::EntitySpecifics;
@@ -64,8 +63,7 @@ std::string GetEntryIdFromSyncData(const syncer::SyncData& data) {
syncer::SyncData CreateLocalData(const ArticleEntry& entry) {
EntitySpecifics specifics = SpecificsFromEntry(entry);
const std::string& entry_id = entry.entry_id();
- return syncer::SyncData::CreateLocalDataWithAttachments(
- entry_id, entry_id, specifics, GetAttachmentIds(entry.attachments()));
+ return syncer::SyncData::CreateLocalData(entry_id, entry_id, specifics);
}
} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/core/data/distillable_page_model.bin b/chromium/components/dom_distiller/core/data/distillable_page_model.bin
deleted file mode 100644
index 39d02eb44de..00000000000
--- a/chromium/components/dom_distiller/core/data/distillable_page_model.bin
+++ /dev/null
Binary files differ
diff --git a/chromium/components/dom_distiller/core/distillable_page_detector.cc b/chromium/components/dom_distiller/core/distillable_page_detector.cc
index 4467a0a44e8..1a9e5777f02 100644
--- a/chromium/components/dom_distiller/core/distillable_page_detector.cc
+++ b/chromium/components/dom_distiller/core/distillable_page_detector.cc
@@ -13,20 +13,6 @@
namespace dom_distiller {
-const DistillablePageDetector* DistillablePageDetector::GetDefault() {
- static DistillablePageDetector* detector = nullptr;
- if (!detector) {
- std::string serialized_proto =
- ui::ResourceBundle::GetSharedInstance()
- .GetRawDataResource(IDR_DISTILLABLE_PAGE_SERIALIZED_MODEL)
- .as_string();
- std::unique_ptr<AdaBoostProto> proto(new AdaBoostProto);
- CHECK(proto->ParseFromString(serialized_proto));
- detector = new DistillablePageDetector(std::move(proto));
- }
- return detector;
-}
-
const DistillablePageDetector* DistillablePageDetector::GetNewModel() {
static DistillablePageDetector* detector = nullptr;
if (!detector) {
diff --git a/chromium/components/dom_distiller/core/distillable_page_detector.h b/chromium/components/dom_distiller/core/distillable_page_detector.h
index 78efdd56e2b..6fe2360440d 100644
--- a/chromium/components/dom_distiller/core/distillable_page_detector.h
+++ b/chromium/components/dom_distiller/core/distillable_page_detector.h
@@ -19,7 +19,6 @@ namespace dom_distiller {
// model.
class DistillablePageDetector {
public:
- static const DistillablePageDetector* GetDefault();
static const DistillablePageDetector* GetNewModel();
static const DistillablePageDetector* GetLongPageModel();
explicit DistillablePageDetector(std::unique_ptr<AdaBoostProto> proto);
diff --git a/chromium/components/dom_distiller/core/distillable_page_detector_unittest.cc b/chromium/components/dom_distiller/core/distillable_page_detector_unittest.cc
index d56be15d249..b5afbd19c1c 100644
--- a/chromium/components/dom_distiller/core/distillable_page_detector_unittest.cc
+++ b/chromium/components/dom_distiller/core/distillable_page_detector_unittest.cc
@@ -4,6 +4,8 @@
#include "components/dom_distiller/core/distillable_page_detector.h"
+#include <memory>
+
#include "base/memory/ptr_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -30,7 +32,7 @@ class Builder {
}
proto_.set_num_features(num_features);
proto_.set_num_stumps(proto_.stump_size());
- return base::MakeUnique<DistillablePageDetector>(
+ return std::make_unique<DistillablePageDetector>(
base::WrapUnique(new AdaBoostProto(proto_)));
}
diff --git a/chromium/components/dom_distiller/core/distilled_content_store.cc b/chromium/components/dom_distiller/core/distilled_content_store.cc
index a2ae21ea3a5..ffe6944a9c6 100644
--- a/chromium/components/dom_distiller/core/distilled_content_store.cc
+++ b/chromium/components/dom_distiller/core/distilled_content_store.cc
@@ -4,6 +4,8 @@
#include "components/dom_distiller/core/distilled_content_store.h"
+#include <utility>
+
#include "base/threading/thread_task_runner_handle.h"
namespace dom_distiller {
@@ -57,7 +59,7 @@ void InMemoryContentStore::LoadContent(
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(callback, success, base::Passed(&distilled_article)));
+ base::BindOnce(callback, success, std::move(distilled_article)));
}
void InMemoryContentStore::InjectContent(const ArticleEntry& entry,
diff --git a/chromium/components/dom_distiller/core/distiller.cc b/chromium/components/dom_distiller/core/distiller.cc
index 7140753209e..f3ebbd8f66c 100644
--- a/chromium/components/dom_distiller/core/distiller.cc
+++ b/chromium/components/dom_distiller/core/distiller.cc
@@ -5,6 +5,7 @@
#include "components/dom_distiller/core/distiller.h"
#include <map>
+#include <memory>
#include <utility>
#include <vector>
@@ -125,7 +126,7 @@ void DistillerImpl::DistillNextPage() {
DCHECK(started_pages_index_.find(page_num) == started_pages_index_.end());
DCHECK(finished_pages_index_.find(page_num) == finished_pages_index_.end());
seen_urls_.insert(url.spec());
- pages_.push_back(base::MakeUnique<DistilledPageData>());
+ pages_.push_back(std::make_unique<DistilledPageData>());
started_pages_index_[page_num] = pages_.size() - 1;
distiller_page_->DistillPage(
url,
diff --git a/chromium/components/dom_distiller/core/distiller_page.cc b/chromium/components/dom_distiller/core/distiller_page.cc
index ad37b5f4f28..36eafa93891 100644
--- a/chromium/components/dom_distiller/core/distiller_page.cc
+++ b/chromium/components/dom_distiller/core/distiller_page.cc
@@ -6,6 +6,8 @@
#include <stddef.h>
+#include <utility>
+
#include "base/bind.h"
#include "base/json/json_writer.h"
#include "base/location.h"
@@ -155,8 +157,8 @@ void DistillerPage::OnDistillationDone(const GURL& page_url,
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(distiller_page_callback_,
- base::Passed(&distiller_result), found_content));
+ FROM_HERE, base::BindOnce(distiller_page_callback_,
+ std::move(distiller_result), found_content));
}
} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/core/distiller_unittest.cc b/chromium/components/dom_distiller/core/distiller_unittest.cc
index 83fc3267ecf..d64a86234e3 100644
--- a/chromium/components/dom_distiller/core/distiller_unittest.cc
+++ b/chromium/components/dom_distiller/core/distiller_unittest.cc
@@ -17,7 +17,6 @@
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
@@ -535,7 +534,7 @@ TEST_F(DistillerTest, CheckMaxPageLimitExactLimit) {
TEST_F(DistillerTest, SinglePageDistillationFailure) {
base::MessageLoopForUI loop;
// To simulate failure return a null value.
- auto null_value = base::MakeUnique<base::Value>();
+ auto null_value = std::make_unique<base::Value>();
distiller_.reset(
new DistillerImpl(url_fetcher_factory_, DomDistillerOptions()));
DistillPage(kURL, CreateMockDistillerPage(null_value.get(), GURL(kURL)));
@@ -557,7 +556,7 @@ TEST_F(DistillerTest, MultiplePagesDistillationFailure) {
distiller_data->distilled_values.begin() + failed_page_num);
distiller_data->distilled_values.insert(
distiller_data->distilled_values.begin() + failed_page_num,
- base::MakeUnique<base::Value>());
+ std::make_unique<base::Value>());
// Expect only calls till the failed page number.
distiller_.reset(
new DistillerImpl(url_fetcher_factory_, DomDistillerOptions()));
diff --git a/chromium/components/dom_distiller/core/dom_distiller_service.cc b/chromium/components/dom_distiller/core/dom_distiller_service.cc
index 6684f57d15d..06443b5896d 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_service.cc
+++ b/chromium/components/dom_distiller/core/dom_distiller_service.cc
@@ -4,11 +4,11 @@
#include "components/dom_distiller/core/dom_distiller_service.h"
+#include <memory>
#include <utility>
#include "base/guid.h"
#include "base/location.h"
-#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/dom_distiller/core/distilled_content_store.h"
@@ -249,7 +249,7 @@ bool DomDistillerService::GetOrCreateTaskTrackerForEntry(
TaskTracker* DomDistillerService::CreateTaskTracker(const ArticleEntry& entry) {
TaskTracker::CancelCallback cancel_callback =
base::Bind(&DomDistillerService::CancelTask, base::Unretained(this));
- tasks_.push_back(base::MakeUnique<TaskTracker>(entry, cancel_callback,
+ tasks_.push_back(std::make_unique<TaskTracker>(entry, cancel_callback,
content_store_.get()));
return tasks_.back().get();
}
diff --git a/chromium/components/dom_distiller/core/dom_distiller_store.cc b/chromium/components/dom_distiller/core/dom_distiller_store.cc
index 2c5b324db71..a3e7d1c690b 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_store.cc
+++ b/chromium/components/dom_distiller/core/dom_distiller_store.cc
@@ -44,7 +44,6 @@ DomDistillerStore::DomDistillerStore(
const base::FilePath& database_dir)
: database_(std::move(database)),
database_loaded_(false),
- attachment_store_(syncer::AttachmentStore::CreateInMemoryStore()),
weak_ptr_factory_(this) {
database_->Init(kDatabaseUMAClientName, database_dir,
leveldb_proto::CreateSimpleOptions(),
@@ -58,7 +57,6 @@ DomDistillerStore::DomDistillerStore(
const base::FilePath& database_dir)
: database_(std::move(database)),
database_loaded_(false),
- attachment_store_(syncer::AttachmentStore::CreateInMemoryStore()),
model_(initial_data),
weak_ptr_factory_(this) {
database_->Init(kDatabaseUMAClientName, database_dir,
@@ -83,122 +81,6 @@ bool DomDistillerStore::GetEntryByUrl(const GURL& url, ArticleEntry* entry) {
return model_.GetEntryByUrl(url, entry);
}
-void DomDistillerStore::UpdateAttachments(
- const std::string& entry_id,
- std::unique_ptr<ArticleAttachmentsData> attachments_data,
- const UpdateAttachmentsCallback& callback) {
- if (!GetEntryById(entry_id, nullptr)) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::Bind(callback, false));
- }
-
- std::unique_ptr<sync_pb::ArticleAttachments> article_attachments(
- new sync_pb::ArticleAttachments());
- syncer::AttachmentList attachment_list;
- attachments_data->CreateSyncAttachments(&attachment_list,
- article_attachments.get());
-
- attachment_store_->Write(
- attachment_list,
- base::Bind(&DomDistillerStore::OnAttachmentsWrite,
- weak_ptr_factory_.GetWeakPtr(), entry_id,
- base::Passed(&article_attachments), callback));
-}
-
-void DomDistillerStore::OnAttachmentsWrite(
- const std::string& entry_id,
- std::unique_ptr<sync_pb::ArticleAttachments> article_attachments,
- const UpdateAttachmentsCallback& callback,
- const syncer::AttachmentStore::Result& result) {
- bool success = false;
- switch (result) {
- case syncer::AttachmentStore::UNSPECIFIED_ERROR:
- case syncer::AttachmentStore::STORE_INITIALIZATION_FAILED:
- break;
- case syncer::AttachmentStore::SUCCESS:
- success = true;
- break;
- }
-
- if (success) {
- ArticleEntry entry;
- bool has_entry = GetEntryById(entry_id, &entry);
- if (!has_entry) {
- success = false;
- attachment_store_->Drop(GetAttachmentIds(*article_attachments),
- syncer::AttachmentStore::DropCallback());
- } else {
- if (entry.has_attachments()) {
- attachment_store_->Drop(GetAttachmentIds(entry.attachments()),
- syncer::AttachmentStore::DropCallback());
- }
- entry.set_allocated_attachments(article_attachments.release());
-
- SyncChangeList changes_to_apply;
- changes_to_apply.push_back(SyncChange(
- FROM_HERE, SyncChange::ACTION_UPDATE, CreateLocalData(entry)));
-
- SyncChangeList changes_applied;
- SyncChangeList changes_missing;
-
- ApplyChangesToModel(changes_to_apply, &changes_applied, &changes_missing);
-
- DCHECK_EQ(size_t(0), changes_missing.size());
- DCHECK_EQ(size_t(1), changes_applied.size());
-
- ApplyChangesToSync(FROM_HERE, changes_applied);
- ApplyChangesToDatabase(changes_applied);
- }
- }
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::Bind(callback, success));
-}
-
-void DomDistillerStore::GetAttachments(
- const std::string& entry_id,
- const GetAttachmentsCallback& callback) {
- ArticleEntry entry;
- if (!model_.GetEntryById(entry_id, &entry)
- || !entry.has_attachments()) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, false, nullptr));
- return;
- }
-
- // TODO(cjhopman): This should use GetOrDownloadAttachments() once there is a
- // feasible way to use that.
- attachment_store_->Read(GetAttachmentIds(entry.attachments()),
- base::Bind(&DomDistillerStore::OnAttachmentsRead,
- weak_ptr_factory_.GetWeakPtr(),
- entry.attachments(), callback));
-}
-
-void DomDistillerStore::OnAttachmentsRead(
- const sync_pb::ArticleAttachments& attachments_proto,
- const GetAttachmentsCallback& callback,
- const syncer::AttachmentStore::Result& result,
- std::unique_ptr<syncer::AttachmentMap> attachments,
- std::unique_ptr<syncer::AttachmentIdList> missing) {
- bool success = false;
- switch (result) {
- case syncer::AttachmentStore::UNSPECIFIED_ERROR:
- case syncer::AttachmentStore::STORE_INITIALIZATION_FAILED:
- break;
- case syncer::AttachmentStore::SUCCESS:
- DCHECK(missing->empty());
- success = true;
- break;
- }
- std::unique_ptr<ArticleAttachmentsData> attachments_data;
- if (success) {
- attachments_data = ArticleAttachmentsData::GetFromAttachmentMap(
- attachments_proto, *attachments);
- }
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(callback, success, base::Passed(&attachments_data)));
-}
-
bool DomDistillerStore::AddEntry(const ArticleEntry& entry) {
return ChangeEntry(entry, SyncChange::ACTION_ADD);
}
@@ -211,22 +93,6 @@ bool DomDistillerStore::RemoveEntry(const ArticleEntry& entry) {
return ChangeEntry(entry, SyncChange::ACTION_DELETE);
}
-namespace {
-
-bool VerifyAttachmentsUnchanged(const ArticleEntry& entry,
- const DomDistillerModel& model) {
- ArticleEntry currentEntry;
- model.GetEntryById(entry.entry_id(), &currentEntry);
- DCHECK_EQ(currentEntry.has_attachments(), entry.has_attachments());
- if (currentEntry.has_attachments()) {
- DCHECK_EQ(currentEntry.attachments().SerializeAsString(),
- entry.attachments().SerializeAsString());
- }
- return true;
-}
-
-} // namespace
-
bool DomDistillerStore::ChangeEntry(const ArticleEntry& entry,
SyncChange::SyncChangeType changeType) {
if (!database_loaded_) {
@@ -239,7 +105,6 @@ bool DomDistillerStore::ChangeEntry(const ArticleEntry& entry,
DVLOG(1) << "Already have entry with id " << entry.entry_id() << ".";
return false;
}
- DCHECK(VerifyAttachmentsUnchanged(entry, model_));
} else if (changeType != SyncChange::ACTION_ADD) {
DVLOG(1) << "No entry with id " << entry.entry_id() << " found.";
return false;
diff --git a/chromium/components/dom_distiller/core/dom_distiller_store.h b/chromium/components/dom_distiller/core/dom_distiller_store.h
index 26aefddab64..a42140ba1f3 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_store.h
+++ b/chromium/components/dom_distiller/core/dom_distiller_store.h
@@ -12,7 +12,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "components/dom_distiller/core/article_attachments_data.h"
#include "components/dom_distiller/core/article_entry.h"
#include "components/dom_distiller/core/dom_distiller_model.h"
#include "components/dom_distiller/core/dom_distiller_observer.h"
@@ -29,10 +28,6 @@ namespace base {
class FilePath;
}
-namespace syncer {
-class AttachmentStore;
-}
-
namespace dom_distiller {
// Interface for accessing the stored/synced DomDistiller entries.
@@ -48,28 +43,6 @@ class DomDistillerStoreInterface {
virtual bool UpdateEntry(const ArticleEntry& entry) = 0;
virtual bool RemoveEntry(const ArticleEntry& entry) = 0;
- typedef base::Callback<void(bool success)> UpdateAttachmentsCallback;
- typedef base::Callback<
- void(bool success, std::unique_ptr<ArticleAttachmentsData> attachments)>
- GetAttachmentsCallback;
-
- // Updates the attachments for an entry. The callback will be called with
- // success==true once the new attachments have been stored locally and the
- // entry has been updated. It will be called with success==false if that
- // failed (e.g. storing the attachment failed, the entry couldn't be found,
- // etc.).
- virtual void UpdateAttachments(
- const std::string& entry_id,
- std::unique_ptr<ArticleAttachmentsData> attachments,
- const UpdateAttachmentsCallback& callback) = 0;
-
- // Gets the attachments for an entry. If the attachments are available (either
- // locally or from sync), the callback will be called with success==true and
- // a pointer to the attachments. Otherwise it will be called with
- // success==false.
- virtual void GetAttachments(const std::string& entry_id,
- const GetAttachmentsCallback& callback) = 0;
-
// Lookup an ArticleEntry by ID or URL. Returns whether a corresponding entry
// was found. On success, if |entry| is not null, it will contain the entry.
virtual bool GetEntryById(const std::string& entry_id,
@@ -127,13 +100,6 @@ class DomDistillerStore : public syncer::SyncableService,
bool UpdateEntry(const ArticleEntry& entry) override;
bool RemoveEntry(const ArticleEntry& entry) override;
- void UpdateAttachments(
- const std::string& entry_id,
- std::unique_ptr<ArticleAttachmentsData> attachments_data,
- const UpdateAttachmentsCallback& callback) override;
- void GetAttachments(const std::string& entry_id,
- const GetAttachmentsCallback& callback) override;
-
bool GetEntryById(const std::string& entry_id, ArticleEntry* entry) override;
bool GetEntryByUrl(const GURL& url, ArticleEntry* entry) override;
std::vector<ArticleEntry> GetEntries() const override;
@@ -162,18 +128,6 @@ class DomDistillerStore : public syncer::SyncableService,
bool ChangeEntry(const ArticleEntry& entry,
syncer::SyncChange::SyncChangeType changeType);
- void OnAttachmentsWrite(
- const std::string& entry_id,
- std::unique_ptr<sync_pb::ArticleAttachments> article_attachments,
- const UpdateAttachmentsCallback& callback,
- const syncer::AttachmentStore::Result& result);
-
- void OnAttachmentsRead(const sync_pb::ArticleAttachments& attachments_proto,
- const GetAttachmentsCallback& callback,
- const syncer::AttachmentStore::Result& result,
- std::unique_ptr<syncer::AttachmentMap> attachments,
- std::unique_ptr<syncer::AttachmentIdList> missing);
-
syncer::SyncMergeResult MergeDataWithModel(
const syncer::SyncDataList& data, syncer::SyncChangeList* changes_applied,
syncer::SyncChangeList* changes_missing);
@@ -201,7 +155,6 @@ class DomDistillerStore : public syncer::SyncableService,
std::unique_ptr<syncer::SyncErrorFactory> error_factory_;
std::unique_ptr<leveldb_proto::ProtoDatabase<ArticleEntry>> database_;
bool database_loaded_;
- std::unique_ptr<syncer::AttachmentStore> attachment_store_;
base::ObserverList<DomDistillerObserver> observers_;
DomDistillerModel model_;
diff --git a/chromium/components/dom_distiller/core/dom_distiller_store_unittest.cc b/chromium/components/dom_distiller/core/dom_distiller_store_unittest.cc
index 7940f6e1e11..09cb30ee9ca 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_store_unittest.cc
+++ b/chromium/components/dom_distiller/core/dom_distiller_store_unittest.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -18,8 +19,6 @@
#include "components/dom_distiller/core/article_entry.h"
#include "components/dom_distiller/core/dom_distiller_test_util.h"
#include "components/leveldb_proto/testing/fake_db.h"
-#include "components/sync/model/attachments/attachment_id.h"
-#include "components/sync/model/attachments/attachment_service_proxy_for_test.h"
#include "components/sync/protocol/sync.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -162,10 +161,8 @@ class DomDistillerStoreTest : public testing::Test {
protected:
SyncData CreateSyncData(const ArticleEntry& entry) {
EntitySpecifics specifics = SpecificsFromEntry(entry);
- return SyncData::CreateRemoteData(
- next_sync_id_++, specifics, Time::UnixEpoch(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create());
+ return SyncData::CreateRemoteData(next_sync_id_++, specifics,
+ Time::UnixEpoch());
}
SyncDataList SyncDataFromEntryMap(const EntryMap& model) {
@@ -312,60 +309,6 @@ TEST_F(DomDistillerStoreTest, TestAddAndUpdateEntry) {
EXPECT_FALSE(store_->UpdateEntry(GetSampleEntry(0)));
}
-class MockAttachmentsCallbacks {
- public:
- MOCK_METHOD2(Get, void(bool, ArticleAttachmentsData*));
- MOCK_METHOD1(Update, void(bool));
-
- void GetImpl(bool success,
- std::unique_ptr<ArticleAttachmentsData> attachments) {
- Get(success, attachments.get());
- }
-
- DomDistillerStore::UpdateAttachmentsCallback UpdateCallback() {
- return base::Bind(&MockAttachmentsCallbacks::Update,
- base::Unretained(this));
- }
-
- DomDistillerStore::GetAttachmentsCallback GetCallback() {
- return base::Bind(&MockAttachmentsCallbacks::GetImpl,
- base::Unretained(this));
- }
-};
-
-TEST_F(DomDistillerStoreTest, TestAttachments) {
- ArticleEntry entry(GetSampleEntry(0));
- AddEntry(entry, &db_model_);
- CreateStore();
- fake_db_->InitCallback(true);
- fake_db_->LoadCallback(true);
- ASSERT_TRUE(AreEntriesEqual(store_->GetEntries(), db_model_));
-
- MockAttachmentsCallbacks callbacks;
-
- store_->GetAttachments(entry.entry_id(), callbacks.GetCallback());
- EXPECT_CALL(callbacks, Get(false, _));
- base::RunLoop().RunUntilIdle();
-
- ArticleAttachmentsData attachments, got_attachments;
- DistilledArticleProto article_proto;
- article_proto.set_title("A title");
- attachments.set_distilled_article(article_proto);
- store_->UpdateAttachments(
- entry.entry_id(), base::MakeUnique<ArticleAttachmentsData>(attachments),
- callbacks.UpdateCallback());
- EXPECT_CALL(callbacks, Update(true));
- base::RunLoop().RunUntilIdle();
-
- store_->GetAttachments(entry.entry_id(), callbacks.GetCallback());
- EXPECT_CALL(callbacks, Get(true, _))
- .WillOnce(SaveArgPointee<1>(&got_attachments));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_EQ(attachments.ToString(),
- got_attachments.ToString());
-}
-
TEST_F(DomDistillerStoreTest, TestSyncMergeWithEmptyDatabase) {
AddEntry(GetSampleEntry(0), &sync_model_);
AddEntry(GetSampleEntry(1), &sync_model_);
diff --git a/chromium/components/dom_distiller/core/fake_distiller.cc b/chromium/components/dom_distiller/core/fake_distiller.cc
index ab64ce6e39e..6b046b1adc4 100644
--- a/chromium/components/dom_distiller/core/fake_distiller.cc
+++ b/chromium/components/dom_distiller/core/fake_distiller.cc
@@ -74,8 +74,8 @@ void FakeDistiller::RunDistillerUpdateCallback(
void FakeDistiller::PostDistillerCallback(
std::unique_ptr<DistilledArticleProto> proto) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&FakeDistiller::RunDistillerCallbackInternal,
- base::Unretained(this), base::Passed(&proto)));
+ FROM_HERE, base::BindOnce(&FakeDistiller::RunDistillerCallbackInternal,
+ base::Unretained(this), std::move(proto)));
}
void FakeDistiller::RunDistillerCallbackInternal(
diff --git a/chromium/components/dom_distiller/core/javascript/is_distillable_trigger.js b/chromium/components/dom_distiller/core/javascript/is_distillable_trigger.js
deleted file mode 100644
index b09aad48d88..00000000000
--- a/chromium/components/dom_distiller/core/javascript/is_distillable_trigger.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(function() {
- var elems = document.querySelectorAll(
- 'meta[property="og:type"],meta[name="og:type"]');
- for (var i in elems) {
- if (elems[i].content && elems[i].content.toUpperCase() == 'ARTICLE') {
- return true;
- }
- }
- var elems = document.querySelectorAll(
- '*[itemtype="http://schema.org/Article"]');
- for (var i in elems) {
- if (elems[i].itemscope) {
- return true;
- }
- }
- return false;
-})()
diff --git a/chromium/components/dom_distiller/core/url_utils.cc b/chromium/components/dom_distiller/core/url_utils.cc
index bb4ba5aacab..c34ec2932c3 100644
--- a/chromium/components/dom_distiller/core/url_utils.cc
+++ b/chromium/components/dom_distiller/core/url_utils.cc
@@ -92,11 +92,6 @@ bool IsDistilledPage(const GURL& url) {
return url.is_valid() && url.scheme() == kDomDistillerScheme;
}
-base::StringPiece GetIsDistillableJs() {
- return ui::ResourceBundle::GetSharedInstance().GetRawDataResource(
- IDR_IS_DISTILLABLE_JS);
-}
-
} // namespace url_utils
} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/core/url_utils.h b/chromium/components/dom_distiller/core/url_utils.h
index 4255a5b68df..d0beeb8a127 100644
--- a/chromium/components/dom_distiller/core/url_utils.h
+++ b/chromium/components/dom_distiller/core/url_utils.h
@@ -48,10 +48,6 @@ bool IsUrlDistillable(const GURL& url);
// Returns whether the given |url| is for a distilled page.
bool IsDistilledPage(const GURL& url);
-// Returns a JavaScript snippet that returns whether or not a page should be
-// used with DomDistillerService and can be executed in a live page.
-base::StringPiece GetIsDistillableJs();
-
} // namespace url_utils
} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/core/url_utils_android.cc b/chromium/components/dom_distiller/core/url_utils_android.cc
index db431e37b43..990b2cad4bc 100644
--- a/chromium/components/dom_distiller/core/url_utils_android.cc
+++ b/chromium/components/dom_distiller/core/url_utils_android.cc
@@ -63,21 +63,6 @@ jboolean JNI_DomDistillerUrlUtils_IsDistilledPage(
return dom_distiller::url_utils::IsDistilledPage(url);
}
-jboolean JNI_DomDistillerUrlUtils_IsUrlDistillable(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& j_url) {
- GURL url(base::android::ConvertJavaStringToUTF8(env, j_url));
- return dom_distiller::url_utils::IsUrlDistillable(url);
-}
-
-ScopedJavaLocalRef<jstring> JNI_DomDistillerUrlUtils_GetIsDistillableJs(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz) {
- return base::android::ConvertUTF8ToJavaString(
- env, dom_distiller::url_utils::GetIsDistillableJs());
-}
-
ScopedJavaLocalRef<jstring> JNI_DomDistillerUrlUtils_GetValueForKeyInUrl(
JNIEnv* env,
const JavaParamRef<jclass>& clazz,
diff --git a/chromium/components/dom_distiller/ios/distiller_page_factory_ios.mm b/chromium/components/dom_distiller/ios/distiller_page_factory_ios.mm
index 65fb78f8aab..9dafaa8e448 100644
--- a/chromium/components/dom_distiller/ios/distiller_page_factory_ios.mm
+++ b/chromium/components/dom_distiller/ios/distiller_page_factory_ios.mm
@@ -4,7 +4,8 @@
#include "components/dom_distiller/ios/distiller_page_factory_ios.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "components/dom_distiller/ios/distiller_page_ios.h"
#include "ios/web/public/browser_state.h"
@@ -22,13 +23,13 @@ DistillerPageFactoryIOS::~DistillerPageFactoryIOS() {}
std::unique_ptr<DistillerPage> DistillerPageFactoryIOS::CreateDistillerPage(
const gfx::Size& view_size) const {
- return base::MakeUnique<DistillerPageIOS>(browser_state_);
+ return std::make_unique<DistillerPageIOS>(browser_state_);
}
std::unique_ptr<DistillerPage>
DistillerPageFactoryIOS::CreateDistillerPageWithHandle(
std::unique_ptr<SourcePageHandle> handle) const {
- return base::MakeUnique<DistillerPageIOS>(browser_state_);
+ return std::make_unique<DistillerPageIOS>(browser_state_);
}
} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/webui/dom_distiller_ui.cc b/chromium/components/dom_distiller/webui/dom_distiller_ui.cc
index 36b1523be1b..09701535380 100644
--- a/chromium/components/dom_distiller/webui/dom_distiller_ui.cc
+++ b/chromium/components/dom_distiller/webui/dom_distiller_ui.cc
@@ -4,7 +4,8 @@
#include "components/dom_distiller/webui/dom_distiller_ui.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "components/dom_distiller/core/dom_distiller_constants.h"
#include "components/dom_distiller/core/dom_distiller_service.h"
#include "components/dom_distiller/webui/dom_distiller_handler.h"
@@ -53,7 +54,7 @@ DomDistillerUi::DomDistillerUi(content::WebUI* web_ui,
// Add message handler.
web_ui->AddMessageHandler(
- base::MakeUnique<DomDistillerHandler>(service, scheme));
+ std::make_unique<DomDistillerHandler>(service, scheme));
}
DomDistillerUi::~DomDistillerUi() {}
diff --git a/chromium/components/domain_reliability/beacon.cc b/chromium/components/domain_reliability/beacon.cc
index 590a666eaad..bcee54997fb 100644
--- a/chromium/components/domain_reliability/beacon.cc
+++ b/chromium/components/domain_reliability/beacon.cc
@@ -4,9 +4,9 @@
#include "components/domain_reliability/beacon.h"
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "components/domain_reliability/util.h"
#include "net/base/net_errors.h"
@@ -26,7 +26,7 @@ std::unique_ptr<Value> DomainReliabilityBeacon::ToValue(
base::TimeTicks last_network_change_time,
const GURL& collector_url,
const std::vector<std::unique_ptr<std::string>>& path_prefixes) const {
- auto beacon_value = base::MakeUnique<DictionaryValue>();
+ auto beacon_value = std::make_unique<DictionaryValue>();
DCHECK(url.is_valid());
GURL sanitized_url = SanitizeURLForReport(url, collector_url, path_prefixes);
beacon_value->SetString("url", sanitized_url.spec());
@@ -34,7 +34,7 @@ std::unique_ptr<Value> DomainReliabilityBeacon::ToValue(
if (!quic_error.empty())
beacon_value->SetString("quic_error", quic_error);
if (chrome_error != net::OK) {
- auto failure_value = base::MakeUnique<DictionaryValue>();
+ auto failure_value = std::make_unique<DictionaryValue>();
failure_value->SetString("custom_error",
net::ErrorToString(chrome_error));
beacon_value->Set("failure_data", std::move(failure_value));
diff --git a/chromium/components/domain_reliability/config_unittest.cc b/chromium/components/domain_reliability/config_unittest.cc
index be701b0998a..f434bb9af59 100644
--- a/chromium/components/domain_reliability/config_unittest.cc
+++ b/chromium/components/domain_reliability/config_unittest.cc
@@ -7,7 +7,6 @@
#include <memory>
#include <string>
-#include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -19,7 +18,7 @@ std::unique_ptr<DomainReliabilityConfig> MakeBaseConfig() {
config->origin = GURL("https://example/");
config->include_subdomains = false;
config->collectors.push_back(
- base::MakeUnique<GURL>("https://example/upload"));
+ std::make_unique<GURL>("https://example/upload"));
config->failure_sample_rate = 1.0;
config->success_sample_rate = 0.0;
EXPECT_TRUE(config->IsValid());
@@ -28,8 +27,8 @@ std::unique_ptr<DomainReliabilityConfig> MakeBaseConfig() {
std::unique_ptr<DomainReliabilityConfig> MakeSampleConfig() {
std::unique_ptr<DomainReliabilityConfig> config(MakeBaseConfig());
- config->path_prefixes.push_back(base::MakeUnique<std::string>("/css/"));
- config->path_prefixes.push_back(base::MakeUnique<std::string>("/js/"));
+ config->path_prefixes.push_back(std::make_unique<std::string>("/css/"));
+ config->path_prefixes.push_back(std::make_unique<std::string>("/js/"));
EXPECT_TRUE(config->IsValid());
return config;
}
@@ -51,7 +50,7 @@ TEST_F(DomainReliabilityConfigTest, IsValid) {
EXPECT_FALSE(config->IsValid());
config = MakeSampleConfig();
- config->collectors[0] = base::MakeUnique<GURL>();
+ config->collectors[0] = std::make_unique<GURL>();
EXPECT_FALSE(config->IsValid());
config = MakeSampleConfig();
diff --git a/chromium/components/domain_reliability/dispatcher.cc b/chromium/components/domain_reliability/dispatcher.cc
index c4efdd00dcc..00166e62201 100644
--- a/chromium/components/domain_reliability/dispatcher.cc
+++ b/chromium/components/domain_reliability/dispatcher.cc
@@ -5,11 +5,11 @@
#include "components/domain_reliability/dispatcher.h"
#include <algorithm>
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/timer/timer.h"
#include "components/domain_reliability/util.h"
@@ -56,7 +56,7 @@ void DomainReliabilityDispatcher::ScheduleTask(
// Would be DCHECK_LE, but you can't << a TimeDelta.
DCHECK(min_delay <= max_delay);
- std::unique_ptr<Task> owned_task = base::MakeUnique<Task>(
+ std::unique_ptr<Task> owned_task = std::make_unique<Task>(
closure, time_->CreateTimer(), min_delay, max_delay);
Task* task = owned_task.get();
tasks_.insert(std::move(owned_task));
diff --git a/chromium/components/domain_reliability/google_configs.cc b/chromium/components/domain_reliability/google_configs.cc
index ec0335a8e00..5dd88eec0c2 100644
--- a/chromium/components/domain_reliability/google_configs.cc
+++ b/chromium/components/domain_reliability/google_configs.cc
@@ -308,6 +308,7 @@ const GoogleConfigParams kGoogleConfigs[] = {
{"chromeexperiments.com", true, false, false},
{"chromestatus.com", true, false, false},
{"chromium.org", true, false, false},
+ {"clients6.google.com", true, false, false},
{"cloudendpointsapis.com", true, false, false},
{"dartmotif.com", true, false, false},
{"dartsearch.net", true, false, false},
@@ -523,39 +524,6 @@ const GoogleConfigParams kGoogleConfigs[] = {
{"ad.doubleclick.net", false, false, false},
{"drive.google.com", false, false, false},
{"redirector.googlevideo.com", false, false, false},
-
- // Third-party domains that have been approved for use within Google's
- // server-side Domain Reliablity infrastructure.
- //
- // DO NOT ADD TO THIS WITHOUT APPROVAL FROM juliatuttle@.
- //
- // This is intended as a short-term stopgap to assess server-side data
- // handling for domains that may one day use Network Error Logging with a
- // third-party collector.
- //
- // To prevent this from being used too heavily, this list is limited to the
- // initial 16 origins, and will be removed in January 2018, around three
- // months after it was added.
- //
- // include_origin_specific_collector is set so that Domain Reliability will
- // provide full URLs in at least some report uploads, which will be
- // redirected from the same origin to Google's servers.
- {"wistia.com", true, true, false},
- {"wistia.net", true, true, false},
- {"wistia.land", true, true, false},
- {"embedwistia-a.akamaihd.net", true, true, false},
- {"wayfair.co.uk", true, true, false},
- {"dwellstudio.com", true, true, false},
- {"csnstores.com", true, true, false},
- {"jossandmain.com", true, true, false},
- {"secure.img2.wfcdn.com", true, true, false},
- {"secure.img3.wfcdn.com", true, true, false},
- {"birchlane.com", true, true, false},
- {"allmodern.com", true, true, false},
- {"perigold.com", true, true, false},
- {"wayfairsupply.com", true, true, false},
- {"wayfair.ca", true, true, false},
- {"wayfair.de", true, true, false},
};
const char* const kGoogleStandardCollectors[] = {
@@ -590,11 +558,11 @@ static std::unique_ptr<DomainReliabilityConfig> CreateGoogleConfig(
GURL::Replacements replacements;
replacements.SetPathStr(kGoogleOriginSpecificCollectorPathString);
config->collectors.push_back(
- base::MakeUnique<GURL>(config->origin.ReplaceComponents(replacements)));
+ std::make_unique<GURL>(config->origin.ReplaceComponents(replacements)));
}
for (size_t i = 0; i < arraysize(kGoogleStandardCollectors); i++)
config->collectors.push_back(
- base::MakeUnique<GURL>(kGoogleStandardCollectors[i]));
+ std::make_unique<GURL>(kGoogleStandardCollectors[i]));
config->success_sample_rate = 0.05;
config->failure_sample_rate = 1.00;
config->path_prefixes.clear();
diff --git a/chromium/components/domain_reliability/header.cc b/chromium/components/domain_reliability/header.cc
index 05a637961e7..0d2136d8a12 100644
--- a/chromium/components/domain_reliability/header.cc
+++ b/chromium/components/domain_reliability/header.cc
@@ -6,7 +6,9 @@
#include <stdint.h>
+#include <memory>
#include <string>
+
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_tokenizer.h"
@@ -169,7 +171,7 @@ bool ParseReportUri(const std::vector<base::StringPiece> in,
GURL url(unquoted);
if (!url.is_valid() || !content::IsOriginSecure(url))
return false;
- out->push_back(base::MakeUnique<GURL>(url));
+ out->push_back(std::make_unique<GURL>(url));
}
return true;
diff --git a/chromium/components/domain_reliability/monitor.cc b/chromium/components/domain_reliability/monitor.cc
index 87c969d9202..a5cf89e8aca 100644
--- a/chromium/components/domain_reliability/monitor.cc
+++ b/chromium/components/domain_reliability/monitor.cc
@@ -4,12 +4,12 @@
#include "components/domain_reliability/monitor.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner.h"
#include "components/domain_reliability/baked_in_configs.h"
@@ -273,7 +273,7 @@ DomainReliabilityMonitor::CreateContextForConfig(
DCHECK(config);
DCHECK(config->IsValid());
- return base::MakeUnique<DomainReliabilityContext>(
+ return std::make_unique<DomainReliabilityContext>(
time_.get(), scheduler_params_, upload_reporter_string_,
&last_network_change_time_, upload_allowed_callback_, &dispatcher_,
uploader_.get(), std::move(config));
diff --git a/chromium/components/domain_reliability/quic_error_mapping.cc b/chromium/components/domain_reliability/quic_error_mapping.cc
index f322b47248e..f7d54f6afaf 100644
--- a/chromium/components/domain_reliability/quic_error_mapping.cc
+++ b/chromium/components/domain_reliability/quic_error_mapping.cc
@@ -232,6 +232,13 @@ const struct QuicErrorMapping {
// Network changed, but connection had one or more non-migratable streams.
{net::QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM,
"quic.connection_migration_non_migratable_stream"},
+ // Network changed, but connection migration was disabled by config.
+ {net::QUIC_CONNECTION_MIGRATION_DISABLED_BY_CONFIG,
+ "quic.connection_migration_disabled_by_config"},
+ // Network changed, but error was encountered on the alternative network.
+ {net::QUIC_CONNECTION_MIGRATION_INTERNAL_ERROR,
+ "quic.connection_migration_internal_error"},
+
// Stream frame overlaps with buffered data.
{net::QUIC_OVERLAPPING_STREAM_DATA, "quic.overlapping_stream_data"},
// Stream frames arrived too discontiguously so that stream sequencer buffer
diff --git a/chromium/components/domain_reliability/scheduler.cc b/chromium/components/domain_reliability/scheduler.cc
index 5f431e4f268..22945f991b6 100644
--- a/chromium/components/domain_reliability/scheduler.cc
+++ b/chromium/components/domain_reliability/scheduler.cc
@@ -6,9 +6,9 @@
#include <stdint.h>
#include <algorithm>
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
@@ -96,7 +96,7 @@ DomainReliabilityScheduler::DomainReliabilityScheduler(
for (size_t i = 0; i < num_collectors; ++i) {
collectors_.push_back(
- base::MakeUnique<net::BackoffEntry>(&backoff_policy_, time_));
+ std::make_unique<net::BackoffEntry>(&backoff_policy_, time_));
}
}
diff --git a/chromium/components/domain_reliability/service.cc b/chromium/components/domain_reliability/service.cc
index d11adad5176..c1bce2654d3 100644
--- a/chromium/components/domain_reliability/service.cc
+++ b/chromium/components/domain_reliability/service.cc
@@ -4,6 +4,8 @@
#include "components/domain_reliability/service.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
@@ -118,10 +120,8 @@ class DomainReliabilityServiceImpl : public DomainReliabilityService {
DCHECK(network_task_runner_.get());
network_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&AddContextForTestingOnNetworkTaskRunner,
- monitor_,
- base::Passed(&config)));
+ FROM_HERE, base::BindOnce(&AddContextForTestingOnNetworkTaskRunner,
+ monitor_, std::move(config)));
}
void ForceUploadsForTesting() override {
@@ -145,7 +145,7 @@ class DomainReliabilityServiceImpl : public DomainReliabilityService {
base::BindOnce(
&DomainReliabilityServiceImpl::CheckUploadAllowedOnUIThread,
service, base::RetainedRef(network_task_runner), origin,
- base::Passed(&callback)));
+ std::move(callback)));
}
void CheckUploadAllowedOnUIThread(
diff --git a/chromium/components/domain_reliability/service_unittest.cc b/chromium/components/domain_reliability/service_unittest.cc
index eef6588ca0f..2491253c754 100644
--- a/chromium/components/domain_reliability/service_unittest.cc
+++ b/chromium/components/domain_reliability/service_unittest.cc
@@ -78,8 +78,6 @@ class TestPermissionManager : public content::PermissionManager {
return kNoPendingOperation;
}
- void CancelPermissionRequest(int request_id) override { NOTIMPLEMENTED(); }
-
void ResetPermission(content::PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin) override {
diff --git a/chromium/components/domain_reliability/test_util.cc b/chromium/components/domain_reliability/test_util.cc
index a121c5c2f9b..7793784fbb1 100644
--- a/chromium/components/domain_reliability/test_util.cc
+++ b/chromium/components/domain_reliability/test_util.cc
@@ -4,9 +4,10 @@
#include "components/domain_reliability/test_util.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/callback.h"
-#include "base/memory/ptr_util.h"
#include "components/domain_reliability/scheduler.h"
#include "net/url_request/url_request_status.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -175,7 +176,7 @@ std::unique_ptr<DomainReliabilityConfig> MakeTestConfigWithOrigin(
DomainReliabilityConfig* config = new DomainReliabilityConfig();
config->origin = origin;
config->collectors.push_back(
- base::MakeUnique<GURL>("https://exampleuploader/upload"));
+ std::make_unique<GURL>("https://exampleuploader/upload"));
config->failure_sample_rate = 1.0;
config->success_sample_rate = 0.0;
diff --git a/chromium/components/domain_reliability/util.cc b/chromium/components/domain_reliability/util.cc
index 18764300e2a..4fb78944502 100644
--- a/chromium/components/domain_reliability/util.cc
+++ b/chromium/components/domain_reliability/util.cc
@@ -131,6 +131,7 @@ std::string GetDomainReliabilityProtocol(
case net::HttpResponseInfo::CONNECTION_INFO_QUIC_41:
case net::HttpResponseInfo::CONNECTION_INFO_QUIC_42:
case net::HttpResponseInfo::CONNECTION_INFO_QUIC_43:
+ case net::HttpResponseInfo::CONNECTION_INFO_QUIC_99:
return "QUIC";
case net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS:
NOTREACHED();
diff --git a/chromium/components/download/BUILD.gn b/chromium/components/download/BUILD.gn
index 4750fd24e0e..668f4e62b73 100644
--- a/chromium/components/download/BUILD.gn
+++ b/chromium/components/download/BUILD.gn
@@ -10,7 +10,9 @@ group("unit_tests") {
"//components/download/content/internal:unit_tests",
"//components/download/content/public:unit_tests",
"//components/download/downloader/in_progress:unit_tests",
- "//components/download/internal:unit_tests",
+ "//components/download/internal/background_service:unit_tests",
+ "//components/download/internal/common:unit_tests",
+ "//components/download/quarantine:unit_tests",
]
}
diff --git a/chromium/components/download/components_unittests.filter b/chromium/components/download/components_unittests.filter
index 9d1d8bdae5d..6e373295ada 100644
--- a/chromium/components/download/components_unittests.filter
+++ b/chromium/components/download/components_unittests.filter
@@ -10,6 +10,7 @@ DownloadServiceModelImplTest.*
DownloadStoreTest.*
FileMonitorTest.*
InProgressConversionsTest.*
+InMemoryDownloadDriverTest.*
InMemoryDownloadTest.*
NavigationMonitorImplTest.*
NetworkListenerTest.*
diff --git a/chromium/components/download/content/factory/BUILD.gn b/chromium/components/download/content/factory/BUILD.gn
index 96ccec7be4e..a57cd73b2e8 100644
--- a/chromium/components/download/content/factory/BUILD.gn
+++ b/chromium/components/download/content/factory/BUILD.gn
@@ -11,14 +11,14 @@ source_set("factory") {
]
public_deps = [
- "//components/download/public",
+ "//components/download/public/background_service:public",
]
deps = [
"//base",
"//components/download/content/internal",
- "//components/download/internal",
- "//components/download/internal/proto",
+ "//components/download/internal/background_service:internal",
+ "//components/download/internal/background_service/proto",
"//components/keyed_service/content",
"//components/leveldb_proto",
"//content/public/browser",
diff --git a/chromium/components/download/content/factory/download_service_factory.cc b/chromium/components/download/content/factory/download_service_factory.cc
index cfa39be5caa..26686cbb093 100644
--- a/chromium/components/download/content/factory/download_service_factory.cc
+++ b/chromium/components/download/content/factory/download_service_factory.cc
@@ -2,24 +2,31 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "components/download/content/factory/download_service_factory.h"
+
#include "base/files/file_path.h"
#include "build/build_config.h"
#include "components/download/content/factory/navigation_monitor_factory.h"
#include "components/download/content/internal/download_driver_impl.h"
-#include "components/download/internal/client_set.h"
-#include "components/download/internal/config.h"
-#include "components/download/internal/controller_impl.h"
-#include "components/download/internal/download_service_impl.h"
-#include "components/download/internal/download_store.h"
-#include "components/download/internal/file_monitor_impl.h"
-#include "components/download/internal/logger_impl.h"
-#include "components/download/internal/model_impl.h"
-#include "components/download/internal/proto/entry.pb.h"
-#include "components/download/internal/scheduler/scheduler_impl.h"
+#include "components/download/internal/background_service/client_set.h"
+#include "components/download/internal/background_service/config.h"
+#include "components/download/internal/background_service/controller_impl.h"
+#include "components/download/internal/background_service/download_service_impl.h"
+#include "components/download/internal/background_service/download_store.h"
+#include "components/download/internal/background_service/empty_file_monitor.h"
+#include "components/download/internal/background_service/empty_task_scheduler.h"
+#include "components/download/internal/background_service/file_monitor_impl.h"
+#include "components/download/internal/background_service/in_memory_download_driver.h"
+#include "components/download/internal/background_service/logger_impl.h"
+#include "components/download/internal/background_service/model_impl.h"
+#include "components/download/internal/background_service/noop_store.h"
+#include "components/download/internal/background_service/proto/entry.pb.h"
+#include "components/download/internal/background_service/scheduler/scheduler_impl.h"
#include "components/leveldb_proto/proto_database_impl.h"
+#include "net/url_request/url_request_context_getter.h"
#if defined(OS_ANDROID)
-#include "components/download/internal/android/battery_status_listener_android.h"
+#include "components/download/internal/background_service/android/battery_status_listener_android.h"
#endif
namespace download {
@@ -29,24 +36,18 @@ const base::FilePath::CharType kEntryDBStorageDir[] =
const base::FilePath::CharType kFilesStorageDir[] = FILE_PATH_LITERAL("Files");
} // namespace
-DownloadService* CreateDownloadService(
+// Helper function to create download service with different implementation
+// details.
+DownloadService* CreateDownloadServiceInternal(
+ content::BrowserContext* browser_context,
std::unique_ptr<DownloadClientMap> clients,
- content::DownloadManager* download_manager,
- const base::FilePath& storage_dir,
- const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
- std::unique_ptr<TaskScheduler> task_scheduler) {
+ std::unique_ptr<Configuration> config,
+ std::unique_ptr<DownloadDriver> driver,
+ std::unique_ptr<Store> store,
+ std::unique_ptr<TaskScheduler> task_scheduler,
+ std::unique_ptr<FileMonitor> file_monitor,
+ const base::FilePath& files_storage_dir) {
auto client_set = std::make_unique<ClientSet>(std::move(clients));
- auto config = Configuration::CreateFromFinch();
-
- auto files_storage_dir = storage_dir.Append(kFilesStorageDir);
- auto driver = std::make_unique<DownloadDriverImpl>(download_manager);
-
- auto entry_db_storage_dir = storage_dir.Append(kEntryDBStorageDir);
- auto entry_db =
- std::make_unique<leveldb_proto::ProtoDatabaseImpl<protodb::Entry>>(
- background_task_runner);
- auto store = std::make_unique<DownloadStore>(entry_db_storage_dir,
- std::move(entry_db));
auto model = std::make_unique<ModelImpl>(std::move(store));
#if defined(OS_ANDROID)
@@ -61,12 +62,9 @@ DownloadService* CreateDownloadService(
config->network_startup_delay, config->network_change_delay,
std::move(battery_listener));
NavigationMonitor* navigation_monitor =
- NavigationMonitorFactory::GetForBrowserContext(
- download_manager->GetBrowserContext());
+ NavigationMonitorFactory::GetForBrowserContext(browser_context);
auto scheduler = std::make_unique<SchedulerImpl>(
task_scheduler.get(), config.get(), client_set.get());
- auto file_monitor = std::make_unique<FileMonitorImpl>(
- files_storage_dir, background_task_runner, config->file_keep_alive_time);
auto logger = std::make_unique<LoggerImpl>();
auto controller = std::make_unique<ControllerImpl>(
config.get(), logger.get(), std::move(client_set), std::move(driver),
@@ -79,4 +77,60 @@ DownloadService* CreateDownloadService(
std::move(controller));
}
+// Create download service for normal profile.
+DownloadService* BuildDownloadService(
+ content::BrowserContext* browser_context,
+ std::unique_ptr<DownloadClientMap> clients,
+ const base::FilePath& storage_dir,
+ const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+ std::unique_ptr<TaskScheduler> task_scheduler) {
+ auto config = Configuration::CreateFromFinch();
+
+ auto driver = std::make_unique<DownloadDriverImpl>(
+ content::BrowserContext::GetDownloadManager(browser_context));
+
+ auto entry_db_storage_dir = storage_dir.Append(kEntryDBStorageDir);
+ auto entry_db =
+ std::make_unique<leveldb_proto::ProtoDatabaseImpl<protodb::Entry>>(
+ background_task_runner);
+ auto store = std::make_unique<DownloadStore>(entry_db_storage_dir,
+ std::move(entry_db));
+
+ auto files_storage_dir = storage_dir.Append(kFilesStorageDir);
+ auto file_monitor = std::make_unique<FileMonitorImpl>(
+ files_storage_dir, background_task_runner, config->file_keep_alive_time);
+
+ return CreateDownloadServiceInternal(
+ browser_context, std::move(clients), std::move(config), std::move(driver),
+ std::move(store), std::move(task_scheduler), std::move(file_monitor),
+ files_storage_dir);
+}
+
+// Create download service for incognito mode without any database or file IO.
+DownloadService* BuildInMemoryDownloadService(
+ content::BrowserContext* browser_context,
+ std::unique_ptr<DownloadClientMap> clients,
+ const base::FilePath& storage_dir,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ BlobTaskProxy::BlobContextGetter blob_context_getter,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
+ auto config = Configuration::CreateFromFinch();
+ auto download_factory = std::make_unique<InMemoryDownloadFactory>(
+ request_context_getter, blob_context_getter, io_task_runner);
+ auto driver =
+ std::make_unique<InMemoryDownloadDriver>(std::move(download_factory));
+ auto store = std::make_unique<NoopStore>();
+ auto task_scheduler = std::make_unique<EmptyTaskScheduler>();
+
+ // TODO(xingliu): Remove |files_storage_dir| and |storage_dir| for incognito
+ // mode. See https://crbug.com/810202.
+ auto files_storage_dir = storage_dir.Append(kFilesStorageDir);
+ auto file_monitor = std::make_unique<EmptyFileMonitor>();
+
+ return CreateDownloadServiceInternal(
+ browser_context, std::move(clients), std::move(config), std::move(driver),
+ std::move(store), std::move(task_scheduler), std::move(file_monitor),
+ files_storage_dir);
+}
+
} // namespace download
diff --git a/chromium/components/download/content/factory/download_service_factory.h b/chromium/components/download/content/factory/download_service_factory.h
index 8df6dfe7da5..9dbb7da6a78 100644
--- a/chromium/components/download/content/factory/download_service_factory.h
+++ b/chromium/components/download/content/factory/download_service_factory.h
@@ -10,12 +10,17 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
-#include "components/download/public/clients.h"
+#include "components/download/internal/background_service/blob_task_proxy.h"
+#include "components/download/public/background_service/clients.h"
namespace content {
-class DownloadManager;
+class BrowserContext;
} // namespace content
+namespace net {
+class URLRequestContextGetter;
+} // namespace net
+
namespace download {
class DownloadService;
@@ -31,13 +36,23 @@ class TaskScheduler;
// will act as an in-memory only service (this means no auto-retries after
// restarts, no files written on completion, etc.).
// |background_task_runner| will be used for all disk reads and writes.
-DownloadService* CreateDownloadService(
+DownloadService* BuildDownloadService(
+ content::BrowserContext* browser_context,
std::unique_ptr<DownloadClientMap> clients,
- content::DownloadManager* download_manager,
const base::FilePath& storage_dir,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
std::unique_ptr<TaskScheduler> task_scheduler);
+// Create download service used in incognito mode, without any database or
+// download file IO.
+DownloadService* BuildInMemoryDownloadService(
+ content::BrowserContext* browser_context,
+ std::unique_ptr<DownloadClientMap> clients,
+ const base::FilePath& storage_dir,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ BlobTaskProxy::BlobContextGetter blob_context_getter,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+
} // namespace download
#endif // COMPONENTS_DOWNLOAD_CONTENT_FACTORY_DOWNLOAD_SERVICE_FACTORY_H_
diff --git a/chromium/components/download/content/factory/navigation_monitor_factory.cc b/chromium/components/download/content/factory/navigation_monitor_factory.cc
index c4b408a10bf..8459b60bfc5 100644
--- a/chromium/components/download/content/factory/navigation_monitor_factory.cc
+++ b/chromium/components/download/content/factory/navigation_monitor_factory.cc
@@ -4,7 +4,7 @@
#include "components/download/content/factory/navigation_monitor_factory.h"
-#include "components/download/internal/navigation_monitor_impl.h"
+#include "components/download/internal/background_service/navigation_monitor_impl.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
namespace download {
diff --git a/chromium/components/download/content/internal/BUILD.gn b/chromium/components/download/content/internal/BUILD.gn
index 77025b91da8..adef5b62d3e 100644
--- a/chromium/components/download/content/internal/BUILD.gn
+++ b/chromium/components/download/content/internal/BUILD.gn
@@ -15,8 +15,8 @@ source_set("internal") {
public_deps = [
"//components/download/content/public",
- "//components/download/internal",
- "//components/download/public",
+ "//components/download/internal/background_service:internal",
+ "//components/download/public/background_service:public",
]
deps = [
@@ -38,6 +38,7 @@ source_set("unit_tests") {
":internal",
"//base/test:test_support",
"//components/download/content/public",
+ "//components/download/internal/background_service/test:test_support",
"//content/test:test_support",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/components/download/content/internal/download_driver_impl.cc b/chromium/components/download/content/internal/download_driver_impl.cc
index 5e9037dbfdf..47a9e6b7a25 100644
--- a/chromium/components/download/content/internal/download_driver_impl.cc
+++ b/chromium/components/download/content/internal/download_driver_impl.cc
@@ -10,9 +10,9 @@
#include "base/metrics/histogram_functions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_usage_estimator.h"
-#include "components/download/internal/driver_entry.h"
-#include "content/public/browser/download_interrupt_reasons.h"
-#include "content/public/browser/download_url_parameters.h"
+#include "components/download/internal/background_service/driver_entry.h"
+#include "components/download/public/common/download_interrupt_reasons.h"
+#include "components/download/public/common/download_url_parameters.h"
#include "content/public/browser/storage_partition.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
@@ -21,19 +21,19 @@ namespace download {
namespace {
-// Converts a content::DownloadItem::DownloadState to DriverEntry::State.
+// Converts a DownloadItem::DownloadState to DriverEntry::State.
DriverEntry::State ToDriverEntryState(
- content::DownloadItem::DownloadState state) {
+ DownloadItem::DownloadState state) {
switch (state) {
- case content::DownloadItem::IN_PROGRESS:
+ case DownloadItem::IN_PROGRESS:
return DriverEntry::State::IN_PROGRESS;
- case content::DownloadItem::COMPLETE:
+ case DownloadItem::COMPLETE:
return DriverEntry::State::COMPLETE;
- case content::DownloadItem::CANCELLED:
+ case DownloadItem::CANCELLED:
return DriverEntry::State::CANCELLED;
- case content::DownloadItem::INTERRUPTED:
+ case DownloadItem::INTERRUPTED:
return DriverEntry::State::INTERRUPTED;
- case content::DownloadItem::MAX_DOWNLOAD_STATE:
+ case DownloadItem::MAX_DOWNLOAD_STATE:
return DriverEntry::State::UNKNOWN;
default:
NOTREACHED();
@@ -41,20 +41,19 @@ DriverEntry::State ToDriverEntryState(
}
}
-FailureType FailureTypeFromInterruptReason(
- content::DownloadInterruptReason reason) {
+FailureType FailureTypeFromInterruptReason(DownloadInterruptReason reason) {
switch (reason) {
- case content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
- case content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
- case content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG:
- case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
- case content::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED:
- case content::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED:
- case content::DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED:
- case content::DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED:
- case content::DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM:
- case content::DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN:
- case content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
+ case DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
+ case DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
+ case DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG:
+ case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
+ case DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED:
+ case DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED:
+ case DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED:
+ case DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED:
+ case DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM:
+ case DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN:
+ case DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
return FailureType::NOT_RECOVERABLE;
default:
return FailureType::RECOVERABLE;
@@ -62,7 +61,7 @@ FailureType FailureTypeFromInterruptReason(
}
// Logs interrupt reason when download fails.
-void LogDownloadInterruptReason(content::DownloadInterruptReason reason) {
+void LogDownloadInterruptReason(download::DownloadInterruptReason reason) {
base::UmaHistogramSparse("Download.Service.Driver.InterruptReason", reason);
}
@@ -70,7 +69,7 @@ void LogDownloadInterruptReason(content::DownloadInterruptReason reason) {
// static
DriverEntry DownloadDriverImpl::CreateDriverEntry(
- const content::DownloadItem* item) {
+ const DownloadItem* item) {
DCHECK(item);
DriverEntry entry;
entry.guid = item->GetGuid();
@@ -80,7 +79,7 @@ DriverEntry DownloadDriverImpl::CreateDriverEntry(
entry.bytes_downloaded = item->GetReceivedBytes();
entry.expected_total_size = item->GetTotalBytes();
entry.current_file_path =
- item->GetState() == content::DownloadItem::DownloadState::COMPLETE
+ item->GetState() == DownloadItem::DownloadState::COMPLETE
? item->GetTargetFilePath()
: item->GetFullPath();
entry.completion_time = item->GetEndTime();
@@ -150,10 +149,10 @@ void DownloadDriverImpl::Start(
download_manager_->GetBrowserContext(), request_params.url);
DCHECK(storage_partition);
- std::unique_ptr<content::DownloadUrlParameters> download_url_params(
- new content::DownloadUrlParameters(
- request_params.url, storage_partition->GetURLRequestContext(),
- traffic_annotation));
+ std::unique_ptr<DownloadUrlParameters> download_url_params(
+ new DownloadUrlParameters(request_params.url,
+ storage_partition->GetURLRequestContext(),
+ traffic_annotation));
// TODO(xingliu): Make content::DownloadManager handle potential guid
// collision and return an error to fail the download cleanly.
@@ -168,9 +167,9 @@ void DownloadDriverImpl::Start(
if (request_params.fetch_error_body)
download_url_params->set_fetch_error_body(true);
download_url_params->set_download_source(
- content::DownloadSource::INTERNAL_API);
+ download::DownloadSource::INTERNAL_API);
- download_manager_->DownloadUrl(std::move(download_url_params));
+ download_manager_->DownloadUrl(std::move(download_url_params), nullptr);
}
void DownloadDriverImpl::Remove(const std::string& guid) {
@@ -186,7 +185,7 @@ void DownloadDriverImpl::Remove(const std::string& guid) {
void DownloadDriverImpl::DoRemoveDownload(const std::string& guid) {
if (!download_manager_)
return;
- content::DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
+ DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
// Cancels the download and removes the persisted records in content layer.
if (item) {
item->Remove();
@@ -196,7 +195,7 @@ void DownloadDriverImpl::DoRemoveDownload(const std::string& guid) {
void DownloadDriverImpl::Pause(const std::string& guid) {
if (!download_manager_)
return;
- content::DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
+ DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
if (item)
item->Pause();
}
@@ -204,7 +203,7 @@ void DownloadDriverImpl::Pause(const std::string& guid) {
void DownloadDriverImpl::Resume(const std::string& guid) {
if (!download_manager_)
return;
- content::DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
+ DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
if (item)
item->Resume();
}
@@ -212,7 +211,7 @@ void DownloadDriverImpl::Resume(const std::string& guid) {
base::Optional<DriverEntry> DownloadDriverImpl::Find(const std::string& guid) {
if (!download_manager_)
return base::nullopt;
- content::DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
+ DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
if (item)
return CreateDriverEntry(item);
return base::nullopt;
@@ -223,7 +222,7 @@ std::set<std::string> DownloadDriverImpl::GetActiveDownloads() {
if (!download_manager_)
return guids;
- std::vector<content::DownloadItem*> items;
+ std::vector<DownloadItem*> items;
download_manager_->GetAllDownloads(&items);
for (auto* item : items) {
@@ -241,23 +240,22 @@ size_t DownloadDriverImpl::EstimateMemoryUsage() const {
}
void DownloadDriverImpl::OnDownloadUpdated(content::DownloadManager* manager,
- content::DownloadItem* item) {
+ DownloadItem* item) {
DCHECK(client_);
// Blocks the observer call if we asked to remove the download.
if (guid_to_remove_.find(item->GetGuid()) != guid_to_remove_.end())
return;
- using DownloadState = content::DownloadItem::DownloadState;
+ using DownloadState = DownloadItem::DownloadState;
DownloadState state = item->GetState();
- content::DownloadInterruptReason reason = item->GetLastReason();
+ download::DownloadInterruptReason reason = item->GetLastReason();
DriverEntry entry = CreateDriverEntry(item);
if (state == DownloadState::COMPLETE) {
client_->OnDownloadSucceeded(entry);
} else if (state == DownloadState::IN_PROGRESS) {
client_->OnDownloadUpdated(entry);
- } else if (reason !=
- content::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE) {
+ } else if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
if (client_->IsTrackingDownload(item->GetGuid()))
LogDownloadInterruptReason(reason);
client_->OnDownloadFailed(entry, FailureTypeFromInterruptReason(reason));
@@ -265,13 +263,13 @@ void DownloadDriverImpl::OnDownloadUpdated(content::DownloadManager* manager,
}
void DownloadDriverImpl::OnDownloadRemoved(content::DownloadManager* manager,
- content::DownloadItem* download) {
+ DownloadItem* download) {
guid_to_remove_.erase(download->GetGuid());
// |download| is about to be deleted.
}
void DownloadDriverImpl::OnDownloadCreated(content::DownloadManager* manager,
- content::DownloadItem* item) {
+ DownloadItem* item) {
if (guid_to_remove_.find(item->GetGuid()) != guid_to_remove_.end()) {
// Client has removed the download before content persistence layer created
// the record, remove the download immediately.
diff --git a/chromium/components/download/content/internal/download_driver_impl.h b/chromium/components/download/content/internal/download_driver_impl.h
index 6d9d8010ad7..bc3a06e2d29 100644
--- a/chromium/components/download/content/internal/download_driver_impl.h
+++ b/chromium/components/download/content/internal/download_driver_impl.h
@@ -12,8 +12,8 @@
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "components/download/content/public/all_download_item_notifier.h"
-#include "components/download/internal/download_driver.h"
-#include "components/download/public/download_params.h"
+#include "components/download/internal/background_service/download_driver.h"
+#include "components/download/public/background_service/download_params.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/download_manager.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
@@ -28,7 +28,7 @@ class DownloadDriverImpl : public DownloadDriver,
public AllDownloadItemNotifier::Observer {
public:
// Creates a driver entry based on a download item.
- static DriverEntry CreateDriverEntry(const content::DownloadItem* item);
+ static DriverEntry CreateDriverEntry(const download::DownloadItem* item);
// Create the driver.
DownloadDriverImpl(content::DownloadManager* manager);
@@ -55,11 +55,11 @@ class DownloadDriverImpl : public DownloadDriver,
void OnManagerInitialized(content::DownloadManager* manager) override;
void OnManagerGoingDown(content::DownloadManager* manager) override;
void OnDownloadCreated(content::DownloadManager* manager,
- content::DownloadItem* item) override;
+ download::DownloadItem* item) override;
void OnDownloadUpdated(content::DownloadManager* manager,
- content::DownloadItem* item) override;
+ download::DownloadItem* item) override;
void OnDownloadRemoved(content::DownloadManager* manager,
- content::DownloadItem* item) override;
+ download::DownloadItem* item) override;
void OnHardRecoverComplete(bool success);
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 438daadb58f..30ebc598ad3 100644
--- a/chromium/components/download/content/internal/download_driver_impl_unittest.cc
+++ b/chromium/components/download/content/internal/download_driver_impl_unittest.cc
@@ -11,6 +11,7 @@
#include "base/test/test_simple_task_runner.h"
#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 "content/public/test/fake_download_item.h"
#include "content/public/test/mock_download_manager.h"
#include "net/http/http_response_headers.h"
@@ -45,17 +46,6 @@ MATCHER_P(DriverEntryEqual, entry, "") {
} // namespace
-class MockDriverClient : public DownloadDriver::Client {
- public:
- MOCK_METHOD1(OnDriverReady, void(bool));
- MOCK_METHOD1(OnDriverHardRecoverComplete, void(bool));
- MOCK_METHOD1(OnDownloadCreated, void(const DriverEntry&));
- MOCK_METHOD2(OnDownloadFailed, void(const DriverEntry&, FailureType));
- MOCK_METHOD1(OnDownloadSucceeded, void(const DriverEntry&));
- MOCK_METHOD1(OnDownloadUpdated, void(const DriverEntry&));
- MOCK_CONST_METHOD1(IsTrackingDownload, bool(const std::string&));
-};
-
class DownloadDriverImplTest : public testing::Test {
public:
DownloadDriverImplTest()
@@ -107,7 +97,7 @@ TEST_F(DownloadDriverImplTest, TestHardRecover) {
// Ensure driver remove call before download created will result in content
// layer remove call and not propagating the event to driver's client.
TEST_F(DownloadDriverImplTest, RemoveBeforeCreated) {
- using DownloadState = content::DownloadItem::DownloadState;
+ using DownloadState = download::DownloadItem::DownloadState;
EXPECT_CALL(mock_manager_, IsManagerInitialized())
.Times(1)
@@ -143,8 +133,8 @@ TEST_F(DownloadDriverImplTest, RemoveBeforeCreated) {
// Ensures download updates from download items are propagated correctly.
TEST_F(DownloadDriverImplTest, DownloadItemUpdateEvents) {
- using DownloadState = content::DownloadItem::DownloadState;
- using DownloadInterruptReason = content::DownloadInterruptReason;
+ using DownloadState = download::DownloadItem::DownloadState;
+ using DownloadInterruptReason = download::DownloadInterruptReason;
EXPECT_CALL(mock_manager_, IsManagerInitialized())
.Times(1)
@@ -192,7 +182,7 @@ TEST_F(DownloadDriverImplTest, DownloadItemUpdateEvents) {
}
TEST_F(DownloadDriverImplTest, TestGetActiveDownloadsCall) {
- using DownloadState = content::DownloadItem::DownloadState;
+ using DownloadState = download::DownloadItem::DownloadState;
content::FakeDownloadItem item1;
item1.SetState(DownloadState::IN_PROGRESS);
item1.SetGuid(base::GenerateGUID());
@@ -209,7 +199,7 @@ TEST_F(DownloadDriverImplTest, TestGetActiveDownloadsCall) {
item4.SetState(DownloadState::INTERRUPTED);
item4.SetGuid(base::GenerateGUID());
- std::vector<content::DownloadItem*> items{&item1, &item2, &item3, &item4};
+ std::vector<download::DownloadItem*> items{&item1, &item2, &item3, &item4};
ON_CALL(mock_manager_, GetAllDownloads(_))
.WillByDefault(PopulateVector(items));
@@ -227,7 +217,7 @@ TEST_F(DownloadDriverImplTest, TestGetActiveDownloadsCall) {
}
TEST_F(DownloadDriverImplTest, TestCreateDriverEntry) {
- using DownloadState = content::DownloadItem::DownloadState;
+ using DownloadState = download::DownloadItem::DownloadState;
content::FakeDownloadItem item;
const std::string kGuid("dummy guid");
const std::vector<GURL> kUrls = {GURL("http://www.example.com/foo.html"),
diff --git a/chromium/components/download/content/public/BUILD.gn b/chromium/components/download/content/public/BUILD.gn
index 3bbc9b663be..8512700f1a6 100644
--- a/chromium/components/download/content/public/BUILD.gn
+++ b/chromium/components/download/content/public/BUILD.gn
@@ -20,7 +20,7 @@ source_set("public") {
]
deps = [
- "//components/download/public",
+ "//components/download/public/background_service:public",
"//content/public/browser",
]
}
diff --git a/chromium/components/download/content/public/all_download_item_notifier.cc b/chromium/components/download/content/public/all_download_item_notifier.cc
index f8c3e26a1f0..f5f1c58b82b 100644
--- a/chromium/components/download/content/public/all_download_item_notifier.cc
+++ b/chromium/components/download/content/public/all_download_item_notifier.cc
@@ -30,7 +30,7 @@ AllDownloadItemNotifier::AllDownloadItemNotifier(
AllDownloadItemNotifier::~AllDownloadItemNotifier() {
if (manager_)
manager_->RemoveObserver(this);
- for (std::set<content::DownloadItem*>::const_iterator it = observing_.begin();
+ for (std::set<DownloadItem*>::const_iterator it = observing_.begin();
it != observing_.end(); ++it) {
(*it)->RemoveObserver(this);
}
@@ -55,25 +55,25 @@ void AllDownloadItemNotifier::ManagerGoingDown(
void AllDownloadItemNotifier::OnDownloadCreated(
content::DownloadManager* manager,
- content::DownloadItem* item) {
+ DownloadItem* item) {
item->AddObserver(this);
observing_.insert(item);
observer_->OnDownloadCreated(manager, item);
}
-void AllDownloadItemNotifier::OnDownloadUpdated(content::DownloadItem* item) {
+void AllDownloadItemNotifier::OnDownloadUpdated(DownloadItem* item) {
observer_->OnDownloadUpdated(manager_, item);
}
-void AllDownloadItemNotifier::OnDownloadOpened(content::DownloadItem* item) {
+void AllDownloadItemNotifier::OnDownloadOpened(DownloadItem* item) {
observer_->OnDownloadOpened(manager_, item);
}
-void AllDownloadItemNotifier::OnDownloadRemoved(content::DownloadItem* item) {
+void AllDownloadItemNotifier::OnDownloadRemoved(DownloadItem* item) {
observer_->OnDownloadRemoved(manager_, item);
}
-void AllDownloadItemNotifier::OnDownloadDestroyed(content::DownloadItem* item) {
+void AllDownloadItemNotifier::OnDownloadDestroyed(DownloadItem* item) {
item->RemoveObserver(this);
observing_.erase(item);
}
diff --git a/chromium/components/download/content/public/all_download_item_notifier.h b/chromium/components/download/content/public/all_download_item_notifier.h
index e803b30f23a..ddfebf8b5c7 100644
--- a/chromium/components/download/content/public/all_download_item_notifier.h
+++ b/chromium/components/download/content/public/all_download_item_notifier.h
@@ -8,7 +8,7 @@
#include <set>
#include "base/macros.h"
-#include "content/public/browser/download_item.h"
+#include "components/download/public/common/download_item.h"
#include "content/public/browser/download_manager.h"
// AllDownloadItemNotifier observes ALL the DownloadItems on a given
@@ -36,7 +36,7 @@
namespace download {
class AllDownloadItemNotifier : public content::DownloadManager::Observer,
- public content::DownloadItem::Observer {
+ public DownloadItem::Observer {
public:
// All of the methods take the DownloadManager so that subclasses can observe
// multiple managers at once and easily distinguish which manager a given item
@@ -49,13 +49,13 @@ class AllDownloadItemNotifier : public content::DownloadManager::Observer,
virtual void OnManagerInitialized(content::DownloadManager* manager) {}
virtual void OnManagerGoingDown(content::DownloadManager* manager) {}
virtual void OnDownloadCreated(content::DownloadManager* manager,
- content::DownloadItem* item) {}
+ download::DownloadItem* item) {}
virtual void OnDownloadUpdated(content::DownloadManager* manager,
- content::DownloadItem* item) {}
+ download::DownloadItem* item) {}
virtual void OnDownloadOpened(content::DownloadManager* manager,
- content::DownloadItem* item) {}
+ download::DownloadItem* item) {}
virtual void OnDownloadRemoved(content::DownloadManager* manager,
- content::DownloadItem* item) {}
+ download::DownloadItem* item) {}
private:
DISALLOW_COPY_AND_ASSIGN(Observer);
@@ -77,17 +77,17 @@ class AllDownloadItemNotifier : public content::DownloadManager::Observer,
void OnManagerInitialized() override;
void ManagerGoingDown(content::DownloadManager* manager) override;
void OnDownloadCreated(content::DownloadManager* manager,
- content::DownloadItem* item) override;
+ download::DownloadItem* item) override;
// DownloadItem::Observer
- void OnDownloadUpdated(content::DownloadItem* item) override;
- void OnDownloadOpened(content::DownloadItem* item) override;
- void OnDownloadRemoved(content::DownloadItem* item) override;
- void OnDownloadDestroyed(content::DownloadItem* item) override;
+ void OnDownloadUpdated(DownloadItem* item) override;
+ void OnDownloadOpened(DownloadItem* item) override;
+ void OnDownloadRemoved(DownloadItem* item) override;
+ void OnDownloadDestroyed(DownloadItem* item) override;
content::DownloadManager* manager_;
AllDownloadItemNotifier::Observer* observer_;
- std::set<content::DownloadItem*> observing_;
+ std::set<DownloadItem*> observing_;
DISALLOW_COPY_AND_ASSIGN(AllDownloadItemNotifier);
};
diff --git a/chromium/components/download/content/public/all_download_item_notifier_unittest.cc b/chromium/components/download/content/public/all_download_item_notifier_unittest.cc
index 271fed869f7..97039f696e8 100644
--- a/chromium/components/download/content/public/all_download_item_notifier_unittest.cc
+++ b/chromium/components/download/content/public/all_download_item_notifier_unittest.cc
@@ -23,17 +23,13 @@ class MockNotifierObserver : public AllDownloadItemNotifier::Observer {
virtual ~MockNotifierObserver() {}
MOCK_METHOD2(OnDownloadCreated,
- void(content::DownloadManager* manager,
- content::DownloadItem* item));
+ void(content::DownloadManager* manager, DownloadItem* item));
MOCK_METHOD2(OnDownloadUpdated,
- void(content::DownloadManager* manager,
- content::DownloadItem* item));
+ void(content::DownloadManager* manager, DownloadItem* item));
MOCK_METHOD2(OnDownloadOpened,
- void(content::DownloadManager* manager,
- content::DownloadItem* item));
+ void(content::DownloadManager* manager, DownloadItem* item));
MOCK_METHOD2(OnDownloadRemoved,
- void(content::DownloadManager* manager,
- content::DownloadItem* item));
+ void(content::DownloadManager* manager, DownloadItem* item));
private:
DISALLOW_COPY_AND_ASSIGN(MockNotifierObserver);
@@ -50,7 +46,7 @@ class AllDownloadItemNotifierTest : public testing::Test {
content::MockDownloadItem& item() { return item_; }
- content::DownloadItem::Observer* NotifierAsItemObserver() const {
+ DownloadItem::Observer* NotifierAsItemObserver() const {
return notifier_.get();
}
diff --git a/chromium/components/download/content/public/download_navigation_observer.h b/chromium/components/download/content/public/download_navigation_observer.h
index a817953c73c..8f3aea1272f 100644
--- a/chromium/components/download/content/public/download_navigation_observer.h
+++ b/chromium/components/download/content/public/download_navigation_observer.h
@@ -6,7 +6,7 @@
#define COMPONENTS_DOWNLOAD_CONTENT_PUBLIC_DOWNLOAD_NAVIGATION_OBSERVER_H_
#include "base/macros.h"
-#include "components/download/public/navigation_monitor.h"
+#include "components/download/public/background_service/navigation_monitor.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
diff --git a/chromium/components/download/downloader/in_progress/BUILD.gn b/chromium/components/download/downloader/in_progress/BUILD.gn
index 5b7a1b15708..e29d519e73c 100644
--- a/chromium/components/download/downloader/in_progress/BUILD.gn
+++ b/chromium/components/download/downloader/in_progress/BUILD.gn
@@ -11,7 +11,6 @@ static_library("in_progress") {
sources = [
"download_entry.cc",
"download_entry.h",
- "download_source.h",
"in_progress_cache.h",
"in_progress_cache_impl.cc",
"in_progress_cache_impl.h",
@@ -22,6 +21,7 @@ static_library("in_progress") {
deps = [
"//base",
"//components/download/downloader/in_progress/proto",
+ "//components/download/public/common:public",
"//services/metrics/public/cpp:metrics_cpp",
]
}
diff --git a/chromium/components/download/downloader/in_progress/DEPS b/chromium/components/download/downloader/in_progress/DEPS
index 18f63456a20..74bead6e775 100644
--- a/chromium/components/download/downloader/in_progress/DEPS
+++ b/chromium/components/download/downloader/in_progress/DEPS
@@ -1,3 +1,4 @@
include_rules = [
+ "+components/download/public/common",
"+services/metrics/public"
]
diff --git a/chromium/components/download/downloader/in_progress/download_entry.h b/chromium/components/download/downloader/in_progress/download_entry.h
index e2671827ad0..449d29efb35 100644
--- a/chromium/components/download/downloader/in_progress/download_entry.h
+++ b/chromium/components/download/downloader/in_progress/download_entry.h
@@ -7,7 +7,7 @@
#include <string>
-#include "components/download/downloader/in_progress/download_source.h"
+#include "components/download/public/common/download_source.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
namespace download {
diff --git a/chromium/components/download/downloader/in_progress/download_source.h b/chromium/components/download/downloader/in_progress/download_source.h
deleted file mode 100644
index 71a9a06a222..00000000000
--- a/chromium/components/download/downloader/in_progress/download_source.h
+++ /dev/null
@@ -1,30 +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_DOWNLOAD_DOWNLOADER_IN_PROGRESS_DOWNLOAD_SOURCE_H_
-#define COMPONENTS_DOWNLOAD_DOWNLOADER_IN_PROGRESS_DOWNLOAD_SOURCE_H_
-
-#include <string>
-
-namespace download {
-// The source of download.
-// This enum should match content::DownloadSource in
-// content/public/browser/download_source.h.
-// Any changes here should also apply to download_source.proto.
-enum class DownloadSource {
- UNKNOWN = 0,
- NAVIGATION = 1,
- DRAG_AND_DROP = 2,
- FROM_RENDERER = 3,
- EXTENSION_API = 4,
- EXTENSION_INSTALLER = 5,
- INTERNAL_API = 6,
- WEB_CONTENTS_API = 7,
- OFFLINE_PAGE = 8,
- CONTEXT_MENU = 9,
-};
-
-} // namespace download
-
-#endif // COMPONENTS_DOWNLOAD_DOWNLOADER_IN_PROGRESS_DOWNLOAD_SOURCE_H_
diff --git a/chromium/components/download/downloader/in_progress/proto/download_source.proto b/chromium/components/download/downloader/in_progress/proto/download_source.proto
index 2405b948fcd..375b059f639 100644
--- a/chromium/components/download/downloader/in_progress/proto/download_source.proto
+++ b/chromium/components/download/downloader/in_progress/proto/download_source.proto
@@ -9,7 +9,7 @@ option optimize_for = LITE_RUNTIME;
package metadata_pb;
// This should stay in sync with the download::DownloadSource enum in
-// components/download/downloader/in_progress/download_source.h.
+// components/download/public/core/download_source.h.
enum DownloadSource {
UNKNOWN = 0;
NAVIGATION = 1;
diff --git a/chromium/components/download/internal/BUILD.gn b/chromium/components/download/internal/background_service/BUILD.gn
index de298e9294d..3f0a725ab6a 100644
--- a/chromium/components/download/internal/BUILD.gn
+++ b/chromium/components/download/internal/background_service/BUILD.gn
@@ -12,7 +12,7 @@ static_library("internal") {
":*",
"//components/download/content/factory",
"//components/download/content/internal",
- "//components/download/internal/test:test_support",
+ "//components/download/internal/background_service/test:test_support",
]
sources = [
@@ -34,6 +34,10 @@ static_library("internal") {
"download_store.h",
"driver_entry.cc",
"driver_entry.h",
+ "empty_file_monitor.cc",
+ "empty_file_monitor.h",
+ "empty_task_scheduler.cc",
+ "empty_task_scheduler.h",
"entry.cc",
"entry.h",
"entry_utils.cc",
@@ -43,6 +47,8 @@ static_library("internal") {
"file_monitor_impl.h",
"in_memory_download.cc",
"in_memory_download.h",
+ "in_memory_download_driver.cc",
+ "in_memory_download_driver.h",
"log_sink.h",
"log_source.h",
"logger_impl.cc",
@@ -53,6 +59,8 @@ static_library("internal") {
"model_impl.h",
"navigation_monitor_impl.cc",
"navigation_monitor_impl.h",
+ "noop_store.cc",
+ "noop_store.h",
"proto_conversions.cc",
"proto_conversions.h",
"scheduler/device_status.cc",
@@ -75,8 +83,8 @@ static_library("internal") {
deps = [
"//base",
- "//components/download/internal/proto",
- "//components/download/public",
+ "//components/download/internal/background_service/proto",
+ "//components/download/public/background_service:public",
"//components/leveldb_proto",
"//net",
"//storage/browser",
@@ -113,7 +121,7 @@ if (is_android) {
"android/java/src/org/chromium/components/download/internal/BatteryStatusListenerAndroid.java",
"android/java/src/org/chromium/components/download/internal/NetworkStatusListenerAndroid.java",
]
- jni_package = "components/download/internal"
+ jni_package = "components/download/internal/background_service"
}
}
@@ -127,6 +135,7 @@ source_set("unit_tests") {
"download_store_unittest.cc",
"entry_utils_unittest.cc",
"file_monitor_unittest.cc",
+ "in_memory_download_driver_unittest.cc",
"in_memory_download_unittest.cc",
"model_impl_unittest.cc",
"navigation_monitor_impl_unittests.cc",
@@ -139,9 +148,9 @@ source_set("unit_tests") {
deps = [
":internal",
"//base/test:test_support",
- "//components/download/internal/proto",
- "//components/download/internal/test:test_support",
- "//components/download/public/test:test_support",
+ "//components/download/internal/background_service/proto",
+ "//components/download/internal/background_service/test:test_support",
+ "//components/download/public/background_service/test:test_support",
"//components/leveldb_proto:test_support",
"//net:test_support",
"//storage/browser",
diff --git a/chromium/components/download/internal/DEPS b/chromium/components/download/internal/background_service/DEPS
index ed5bc8cbaac..ed5bc8cbaac 100644
--- a/chromium/components/download/internal/DEPS
+++ b/chromium/components/download/internal/background_service/DEPS
diff --git a/chromium/components/download/internal/android/battery_status_listener_android.cc b/chromium/components/download/internal/background_service/android/battery_status_listener_android.cc
index 454cd08acc0..070ffe9e738 100644
--- a/chromium/components/download/internal/android/battery_status_listener_android.cc
+++ b/chromium/components/download/internal/background_service/android/battery_status_listener_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/download/internal/android/battery_status_listener_android.h"
+#include "components/download/internal/background_service/android/battery_status_listener_android.h"
#include "base/android/jni_android.h"
#include "jni/BatteryStatusListenerAndroid_jni.h"
diff --git a/chromium/components/download/internal/android/battery_status_listener_android.h b/chromium/components/download/internal/background_service/android/battery_status_listener_android.h
index cd2420bba3a..ac3bcf36cd9 100644
--- a/chromium/components/download/internal/android/battery_status_listener_android.h
+++ b/chromium/components/download/internal/background_service/android/battery_status_listener_android.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_ANDROID_BATTERY_STATUS_LISTENER_ANDROID_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_ANDROID_BATTERY_STATUS_LISTENER_ANDROID_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_ANDROID_BATTERY_STATUS_LISTENER_ANDROID_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_ANDROID_BATTERY_STATUS_LISTENER_ANDROID_H_
-#include "components/download/internal/scheduler/device_status_listener.h"
+#include "components/download/internal/background_service/scheduler/device_status_listener.h"
#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
@@ -27,4 +27,4 @@ class BatteryStatusListenerAndroid : public BatteryStatusListener {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_ANDROID_BATTERY_STATUS_LISTENER_ANDROID_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_ANDROID_BATTERY_STATUS_LISTENER_ANDROID_H_
diff --git a/chromium/components/download/internal/android/network_status_listener_android.cc b/chromium/components/download/internal/background_service/android/network_status_listener_android.cc
index 0817e936571..0de9b90b236 100644
--- a/chromium/components/download/internal/android/network_status_listener_android.cc
+++ b/chromium/components/download/internal/background_service/android/network_status_listener_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/download/internal/android/network_status_listener_android.h"
+#include "components/download/internal/background_service/android/network_status_listener_android.h"
#include "base/android/jni_android.h"
#include "jni/NetworkStatusListenerAndroid_jni.h"
diff --git a/chromium/components/download/internal/android/network_status_listener_android.h b/chromium/components/download/internal/background_service/android/network_status_listener_android.h
index 13bda6618b2..036223120e3 100644
--- a/chromium/components/download/internal/android/network_status_listener_android.h
+++ b/chromium/components/download/internal/background_service/android/network_status_listener_android.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_ANDROID_NETWORK_STATUS_LISTENER_ANDROID_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_ANDROID_NETWORK_STATUS_LISTENER_ANDROID_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_ANDROID_NETWORK_STATUS_LISTENER_ANDROID_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_ANDROID_NETWORK_STATUS_LISTENER_ANDROID_H_
-#include "components/download/internal/scheduler/network_status_listener.h"
+#include "components/download/internal/background_service/scheduler/network_status_listener.h"
#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
@@ -40,4 +40,4 @@ class NetworkStatusListenerAndroid : public NetworkStatusListener {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_ANDROID_NETWORK_STATUS_LISTENER_ANDROID_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_ANDROID_NETWORK_STATUS_LISTENER_ANDROID_H_
diff --git a/chromium/components/download/internal/blob_task_proxy.cc b/chromium/components/download/internal/background_service/blob_task_proxy.cc
index 1348f13ba2d..ab525937720 100644
--- a/chromium/components/download/internal/blob_task_proxy.cc
+++ b/chromium/components/download/internal/background_service/blob_task_proxy.cc
@@ -2,10 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/blob_task_proxy.h"
+#include "components/download/internal/background_service/blob_task_proxy.h"
+
+#include <utility>
#include "base/guid.h"
#include "base/task_runner_util.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_storage_context.h"
@@ -16,8 +19,7 @@ namespace download {
std::unique_ptr<BlobTaskProxy> BlobTaskProxy::Create(
BlobContextGetter blob_context_getter,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
- return std::make_unique<BlobTaskProxy>(std::move(blob_context_getter),
- io_task_runner);
+ return std::make_unique<BlobTaskProxy>(blob_context_getter, io_task_runner);
}
BlobTaskProxy::BlobTaskProxy(
@@ -29,9 +31,8 @@ BlobTaskProxy::BlobTaskProxy(
// Unretained the raw pointer because owner on UI thread should destroy this
// object on IO thread.
io_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&BlobTaskProxy::InitializeOnIO, base::Unretained(this),
- std::move(blob_context_getter)));
+ FROM_HERE, base::BindOnce(&BlobTaskProxy::InitializeOnIO,
+ base::Unretained(this), blob_context_getter));
}
BlobTaskProxy::~BlobTaskProxy() {
@@ -40,7 +41,7 @@ BlobTaskProxy::~BlobTaskProxy() {
void BlobTaskProxy::InitializeOnIO(BlobContextGetter blob_context_getter) {
io_task_runner_->BelongsToCurrentThread();
- blob_storage_context_ = std::move(blob_context_getter).Run();
+ blob_storage_context_ = blob_context_getter.Run();
}
void BlobTaskProxy::SaveAsBlob(std::unique_ptr<std::string> data,
@@ -57,17 +58,17 @@ void BlobTaskProxy::SaveAsBlobOnIO(std::unique_ptr<std::string> data,
BlobDataHandleCallback callback) {
io_task_runner_->BelongsToCurrentThread();
- // Build blob data.
+ // Build blob data. This has to do a copy into blob's internal storage.
std::string blob_uuid = base::GenerateGUID();
- storage::BlobDataBuilder builder(blob_uuid);
- builder.AppendData(*data.get());
- blob_data_handle_ = blob_storage_context_->AddFinishedBlob(builder);
+ auto builder = std::make_unique<storage::BlobDataBuilder>(blob_uuid);
+ builder->AppendData(*data.get());
+ blob_data_handle_ =
+ blob_storage_context_->AddFinishedBlob(std::move(builder));
// Wait for blob data construction complete.
- auto cb = base::BindRepeating(&BlobTaskProxy::BlobSavedOnIO,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(std::move(callback)));
- blob_data_handle_->RunOnConstructionComplete(cb);
+ auto cb = base::BindOnce(&BlobTaskProxy::BlobSavedOnIO,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback));
+ blob_data_handle_->RunOnConstructionComplete(std::move(cb));
}
void BlobTaskProxy::BlobSavedOnIO(BlobDataHandleCallback callback,
@@ -75,8 +76,8 @@ void BlobTaskProxy::BlobSavedOnIO(BlobDataHandleCallback callback,
io_task_runner_->BelongsToCurrentThread();
// Relay BlobDataHandle and |status| back to main thread.
- auto cb = base::BindOnce(std::move(callback),
- base::Passed(std::move(blob_data_handle_)), status);
+ auto cb =
+ base::BindOnce(std::move(callback), std::move(blob_data_handle_), status);
main_task_runner_->PostTask(FROM_HERE, std::move(cb));
}
diff --git a/chromium/components/download/internal/blob_task_proxy.h b/chromium/components/download/internal/background_service/blob_task_proxy.h
index e757554f9f6..d7fc6113441 100644
--- a/chromium/components/download/internal/blob_task_proxy.h
+++ b/chromium/components/download/internal/background_service/blob_task_proxy.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_INTERNAL_BLOB_TASK_PROXY_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_BLOB_TASK_PROXY_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_BLOB_TASK_PROXY_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_BLOB_TASK_PROXY_H_
#include <memory>
#include <string>
@@ -26,7 +26,7 @@ namespace download {
class BlobTaskProxy {
public:
using BlobContextGetter =
- base::OnceCallback<base::WeakPtr<storage::BlobStorageContext>()>;
+ base::RepeatingCallback<base::WeakPtr<storage::BlobStorageContext>()>;
using BlobDataHandleCallback =
base::OnceCallback<void(std::unique_ptr<storage::BlobDataHandle>,
storage::BlobStatus status)>;
@@ -72,4 +72,4 @@ class BlobTaskProxy {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_BLOB_TASK_PROXY_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_BLOB_TASK_PROXY_H_
diff --git a/chromium/components/download/internal/client_set.cc b/chromium/components/download/internal/background_service/client_set.cc
index c05a1f1d95e..78399df2047 100644
--- a/chromium/components/download/internal/client_set.cc
+++ b/chromium/components/download/internal/background_service/client_set.cc
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/client_set.h"
-#include "components/download/internal/debugging_client.h"
+#include "components/download/internal/background_service/client_set.h"
+#include "components/download/internal/background_service/debugging_client.h"
namespace download {
diff --git a/chromium/components/download/internal/client_set.h b/chromium/components/download/internal/background_service/client_set.h
index 2daa5206782..4bfd49a1072 100644
--- a/chromium/components/download/internal/client_set.h
+++ b/chromium/components/download/internal/background_service/client_set.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_DOWNLOAD_INTERNAL_CLIENT_SET_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_CLIENT_SET_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_CLIENT_SET_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_CLIENT_SET_H_
#include <map>
#include <memory>
#include <set>
#include "base/macros.h"
-#include "components/download/public/clients.h"
+#include "components/download/public/background_service/clients.h"
namespace download {
@@ -32,4 +32,4 @@ class ClientSet {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_CLIENT_SET_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_CLIENT_SET_H_
diff --git a/chromium/components/download/internal/client_set_unittest.cc b/chromium/components/download/internal/background_service/client_set_unittest.cc
index c128ae70e81..a75c5b4971e 100644
--- a/chromium/components/download/internal/client_set_unittest.cc
+++ b/chromium/components/download/internal/background_service/client_set_unittest.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/client_set.h"
+#include "components/download/internal/background_service/client_set.h"
#include <algorithm>
-#include "components/download/public/clients.h"
-#include "components/download/public/test/empty_client.h"
+#include "components/download/public/background_service/clients.h"
+#include "components/download/public/background_service/test/empty_client.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace download {
diff --git a/chromium/components/download/internal/config.cc b/chromium/components/download/internal/background_service/config.cc
index f42683b89ad..81aaaaa7ece 100644
--- a/chromium/components/download/internal/config.cc
+++ b/chromium/components/download/internal/background_service/config.cc
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/config.h"
+#include "components/download/internal/background_service/config.h"
#include <string>
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_number_conversions.h"
-#include "components/download/public/features.h"
+#include "components/download/public/background_service/features.h"
namespace download {
diff --git a/chromium/components/download/internal/config.h b/chromium/components/download/internal/background_service/config.h
index a66af7f7407..6727661372a 100644
--- a/chromium/components/download/internal/config.h
+++ b/chromium/components/download/internal/background_service/config.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_INTERNAL_CONFIG_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_CONFIG_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_CONFIG_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_CONFIG_H_
#include <memory>
@@ -151,4 +151,4 @@ struct Configuration {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_CONFIG_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_CONFIG_H_
diff --git a/chromium/components/download/internal/controller.h b/chromium/components/download/internal/background_service/controller.h
index c16c9ff377c..6ea581c0098 100644
--- a/chromium/components/download/internal/controller.h
+++ b/chromium/components/download/internal/background_service/controller.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_DOWNLOAD_INTERNAL_CONTROLLER_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_CONTROLLER_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_CONTROLLER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_CONTROLLER_H_
#include <string>
#include "base/macros.h"
-#include "components/download/public/clients.h"
-#include "components/download/public/download_service.h"
-#include "components/download/public/download_task_types.h"
+#include "components/download/public/background_service/clients.h"
+#include "components/download/public/background_service/download_service.h"
+#include "components/download/public/background_service/download_task_types.h"
namespace download {
@@ -111,4 +111,4 @@ class Controller {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_CONTROLLER_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_CONTROLLER_H_
diff --git a/chromium/components/download/internal/controller_impl.cc b/chromium/components/download/internal/background_service/controller_impl.cc
index 5a29e136125..ec17c3abaef 100644
--- a/chromium/components/download/internal/controller_impl.cc
+++ b/chromium/components/download/internal/background_service/controller_impl.cc
@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/controller_impl.h"
+#include "components/download/internal/background_service/controller_impl.h"
+
+#include <inttypes.h>
#include <string>
#include <vector>
@@ -11,23 +13,24 @@
#include "base/callback_helpers.h"
#include "base/memory/ptr_util.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"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_usage_estimator.h"
#include "base/trace_event/process_memory_dump.h"
-#include "components/download/internal/client_set.h"
-#include "components/download/internal/config.h"
-#include "components/download/internal/entry.h"
-#include "components/download/internal/entry_utils.h"
-#include "components/download/internal/file_monitor.h"
-#include "components/download/internal/log_sink.h"
-#include "components/download/internal/model.h"
-#include "components/download/internal/scheduler/scheduler.h"
-#include "components/download/internal/stats.h"
-#include "components/download/public/client.h"
-#include "components/download/public/download_metadata.h"
-#include "components/download/public/navigation_monitor.h"
+#include "components/download/internal/background_service/client_set.h"
+#include "components/download/internal/background_service/config.h"
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/internal/background_service/entry_utils.h"
+#include "components/download/internal/background_service/file_monitor.h"
+#include "components/download/internal/background_service/log_sink.h"
+#include "components/download/internal/background_service/model.h"
+#include "components/download/internal/background_service/scheduler/scheduler.h"
+#include "components/download/internal/background_service/stats.h"
+#include "components/download/public/background_service/client.h"
+#include "components/download/public/background_service/download_metadata.h"
+#include "components/download/public/background_service/navigation_monitor.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
namespace download {
@@ -597,7 +600,9 @@ base::Optional<LogSource::EntryDetails> ControllerImpl::GetServiceDownload(
bool ControllerImpl::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) {
- auto* dump = pmd->GetOrCreateAllocatorDump("components/download");
+ auto* dump = pmd->CreateAllocatorDump(
+ base::StringPrintf("components/download/controller_0x%" PRIXPTR,
+ reinterpret_cast<uintptr_t>(this)));
size_t memory_cost =
base::trace_event::EstimateMemoryUsage(externally_active_downloads_);
diff --git a/chromium/components/download/internal/controller_impl.h b/chromium/components/download/internal/background_service/controller_impl.h
index 3e83ef6badc..52365f310ac 100644
--- a/chromium/components/download/internal/controller_impl.h
+++ b/chromium/components/download/internal/background_service/controller_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_DOWNLOAD_INTERNAL_CONTROLLER_IMPL_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_CONTROLLER_IMPL_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_CONTROLLER_IMPL_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_CONTROLLER_IMPL_H_
#include <map>
#include <memory>
@@ -14,18 +14,18 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/trace_event/memory_dump_provider.h"
-#include "components/download/internal/controller.h"
-#include "components/download/internal/download_driver.h"
-#include "components/download/internal/entry.h"
-#include "components/download/internal/log_source.h"
-#include "components/download/internal/model.h"
-#include "components/download/internal/scheduler/device_status_listener.h"
-#include "components/download/internal/startup_status.h"
-#include "components/download/internal/stats.h"
-#include "components/download/public/client.h"
-#include "components/download/public/download_params.h"
-#include "components/download/public/navigation_monitor.h"
-#include "components/download/public/task_scheduler.h"
+#include "components/download/internal/background_service/controller.h"
+#include "components/download/internal/background_service/download_driver.h"
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/internal/background_service/log_source.h"
+#include "components/download/internal/background_service/model.h"
+#include "components/download/internal/background_service/scheduler/device_status_listener.h"
+#include "components/download/internal/background_service/startup_status.h"
+#include "components/download/internal/background_service/stats.h"
+#include "components/download/public/background_service/client.h"
+#include "components/download/public/background_service/download_params.h"
+#include "components/download/public/background_service/navigation_monitor.h"
+#include "components/download/public/background_service/task_scheduler.h"
namespace download {
@@ -263,4 +263,4 @@ class ControllerImpl : public Controller,
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_CONTROLLER_IMPL_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_CONTROLLER_IMPL_H_
diff --git a/chromium/components/download/internal/controller_impl_unittest.cc b/chromium/components/download/internal/background_service/controller_impl_unittest.cc
index 8d8e907e7e7..d98af57a28e 100644
--- a/chromium/components/download/internal/controller_impl_unittest.cc
+++ b/chromium/components/download/internal/background_service/controller_impl_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/download/internal/controller_impl.h"
+#include "components/download/internal/background_service/controller_impl.h"
#include <algorithm>
#include <memory>
@@ -14,22 +14,22 @@
#include "base/test/histogram_tester.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "components/download/internal/client_set.h"
-#include "components/download/internal/config.h"
-#include "components/download/internal/entry.h"
-#include "components/download/internal/entry_utils.h"
-#include "components/download/internal/file_monitor.h"
-#include "components/download/internal/model_impl.h"
-#include "components/download/internal/navigation_monitor_impl.h"
-#include "components/download/internal/scheduler/scheduler.h"
-#include "components/download/internal/stats.h"
-#include "components/download/internal/test/black_hole_log_sink.h"
-#include "components/download/internal/test/entry_utils.h"
-#include "components/download/internal/test/test_device_status_listener.h"
-#include "components/download/internal/test/test_download_driver.h"
-#include "components/download/internal/test/test_store.h"
-#include "components/download/public/test/empty_client.h"
-#include "components/download/public/test/mock_client.h"
+#include "components/download/internal/background_service/client_set.h"
+#include "components/download/internal/background_service/config.h"
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/internal/background_service/entry_utils.h"
+#include "components/download/internal/background_service/file_monitor.h"
+#include "components/download/internal/background_service/model_impl.h"
+#include "components/download/internal/background_service/navigation_monitor_impl.h"
+#include "components/download/internal/background_service/scheduler/scheduler.h"
+#include "components/download/internal/background_service/stats.h"
+#include "components/download/internal/background_service/test/black_hole_log_sink.h"
+#include "components/download/internal/background_service/test/entry_utils.h"
+#include "components/download/internal/background_service/test/test_device_status_listener.h"
+#include "components/download/internal/background_service/test/test_download_driver.h"
+#include "components/download/internal/background_service/test/test_store.h"
+#include "components/download/public/background_service/test/empty_client.h"
+#include "components/download/public/background_service/test/mock_client.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/download/internal/debugging_client.cc b/chromium/components/download/internal/background_service/debugging_client.cc
index c4b06ef4ebd..dedf1c1cb12 100644
--- a/chromium/components/download/internal/debugging_client.cc
+++ b/chromium/components/download/internal/background_service/debugging_client.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/download/internal/debugging_client.h"
+#include "components/download/internal/background_service/debugging_client.h"
namespace download {
diff --git a/chromium/components/download/internal/debugging_client.h b/chromium/components/download/internal/background_service/debugging_client.h
index 8e7694763ca..bd249f334b8 100644
--- a/chromium/components/download/internal/debugging_client.h
+++ b/chromium/components/download/internal/background_service/debugging_client.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_DEBUGGING_CLIENT_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_DEBUGGING_CLIENT_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DEBUGGING_CLIENT_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DEBUGGING_CLIENT_H_
#include "base/macros.h"
-#include "components/download/public/client.h"
+#include "components/download/public/background_service/client.h"
namespace download {
@@ -40,4 +40,4 @@ class DebuggingClient : public Client {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_DEBUGGING_CLIENT_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DEBUGGING_CLIENT_H_
diff --git a/chromium/components/download/internal/download_driver.h b/chromium/components/download/internal/background_service/download_driver.h
index 50265e25a85..476fa7660f0 100644
--- a/chromium/components/download/internal/download_driver.h
+++ b/chromium/components/download/internal/background_service/download_driver.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_DOWNLOAD_INTERNAL_DOWNLOAD_DRIVER_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_DRIVER_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DOWNLOAD_DRIVER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DOWNLOAD_DRIVER_H_
#include <set>
#include <string>
#include "base/optional.h"
-#include "components/download/internal/driver_entry.h"
-#include "components/download/internal/memory_tracker.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"
namespace base {
@@ -106,4 +106,4 @@ class DownloadDriver : public MemoryTracker {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_DRIVER_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DOWNLOAD_DRIVER_H_
diff --git a/chromium/components/download/internal/download_service_impl.cc b/chromium/components/download/internal/background_service/download_service_impl.cc
index 3f1d22ec4ff..3ed181bb6fb 100644
--- a/chromium/components/download/internal/download_service_impl.cc
+++ b/chromium/components/download/internal/background_service/download_service_impl.cc
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/download_service_impl.h"
+#include "components/download/internal/background_service/download_service_impl.h"
#include "base/bind.h"
#include "base/strings/string_util.h"
-#include "components/download/internal/controller.h"
-#include "components/download/internal/logger_impl.h"
-#include "components/download/internal/startup_status.h"
-#include "components/download/internal/stats.h"
+#include "components/download/internal/background_service/controller.h"
+#include "components/download/internal/background_service/logger_impl.h"
+#include "components/download/internal/background_service/startup_status.h"
+#include "components/download/internal/background_service/stats.h"
namespace download {
diff --git a/chromium/components/download/internal/download_service_impl.h b/chromium/components/download/internal/background_service/download_service_impl.h
index 913788feccd..888bcd93ff2 100644
--- a/chromium/components/download/internal/download_service_impl.h
+++ b/chromium/components/download/internal/background_service/download_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_DOWNLOAD_INTERNAL_DOWNLOAD_SERVICE_IMPL_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_SERVICE_IMPL_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DOWNLOAD_SERVICE_IMPL_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DOWNLOAD_SERVICE_IMPL_H_
#include <map>
#include <memory>
@@ -11,9 +11,9 @@
#include "base/containers/circular_deque.h"
#include "base/macros.h"
-#include "components/download/internal/config.h"
-#include "components/download/internal/service_config_impl.h"
-#include "components/download/public/download_service.h"
+#include "components/download/internal/background_service/config.h"
+#include "components/download/internal/background_service/service_config_impl.h"
+#include "components/download/public/background_service/download_service.h"
namespace download {
@@ -65,4 +65,4 @@ class DownloadServiceImpl : public DownloadService {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_SERVICE_IMPL_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DOWNLOAD_SERVICE_IMPL_H_
diff --git a/chromium/components/download/internal/download_service_impl_unittest.cc b/chromium/components/download/internal/background_service/download_service_impl_unittest.cc
index b02db493296..796d3ddc492 100644
--- a/chromium/components/download/internal/download_service_impl_unittest.cc
+++ b/chromium/components/download/internal/background_service/download_service_impl_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/download/internal/download_service_impl.h"
+#include "components/download/internal/background_service/download_service_impl.h"
#include <memory>
@@ -11,11 +11,11 @@
#include "base/test/histogram_tester.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "components/download/internal/startup_status.h"
-#include "components/download/internal/stats.h"
-#include "components/download/internal/test/download_params_utils.h"
-#include "components/download/internal/test/mock_controller.h"
-#include "components/download/public/test/empty_logger.h"
+#include "components/download/internal/background_service/startup_status.h"
+#include "components/download/internal/background_service/stats.h"
+#include "components/download/internal/background_service/test/download_params_utils.h"
+#include "components/download/internal/background_service/test/mock_controller.h"
+#include "components/download/public/background_service/test/empty_logger.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/download/internal/download_store.cc b/chromium/components/download/internal/background_service/download_store.cc
index b2398ef4403..ab1ffac3417 100644
--- a/chromium/components/download/internal/download_store.cc
+++ b/chromium/components/download/internal/background_service/download_store.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/download/internal/download_store.h"
+#include "components/download/internal/background_service/download_store.h"
#include <memory>
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "components/download/internal/entry.h"
-#include "components/download/internal/proto/entry.pb.h"
-#include "components/download/internal/proto_conversions.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"
#include "components/leveldb_proto/proto_database_impl.h"
namespace download {
diff --git a/chromium/components/download/internal/download_store.h b/chromium/components/download/internal/background_service/download_store.h
index adb397b6b3c..953b29854a4 100644
--- a/chromium/components/download/internal/download_store.h
+++ b/chromium/components/download/internal/background_service/download_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_DOWNLOAD_INTERNAL_DOWNLOAD_STORE_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_STORE_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DOWNLOAD_STORE_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DOWNLOAD_STORE_H_
#include <string>
#include <vector>
@@ -11,7 +11,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "components/download/internal/store.h"
+#include "components/download/internal/background_service/store.h"
#include "components/leveldb_proto/proto_database.h"
namespace protodb {
@@ -57,4 +57,4 @@ class DownloadStore : public Store {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_STORE_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DOWNLOAD_STORE_H_
diff --git a/chromium/components/download/internal/download_store_unittest.cc b/chromium/components/download/internal/background_service/download_store_unittest.cc
index 40f61bb3731..f008e113049 100644
--- a/chromium/components/download/internal/download_store_unittest.cc
+++ b/chromium/components/download/internal/background_service/download_store_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/download/internal/download_store.h"
+#include "components/download/internal/background_service/download_store.h"
#include <algorithm>
#include <memory>
@@ -11,10 +11,10 @@
#include "base/callback.h"
#include "base/guid.h"
#include "base/optional.h"
-#include "components/download/internal/entry.h"
-#include "components/download/internal/proto/entry.pb.h"
-#include "components/download/internal/proto_conversions.h"
-#include "components/download/internal/test/entry_utils.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"
+#include "components/download/internal/background_service/test/entry_utils.h"
#include "components/leveldb_proto/testing/fake_db.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/download/internal/driver_entry.cc b/chromium/components/download/internal/background_service/driver_entry.cc
index 04d2c72befd..68f0be7cd1f 100644
--- a/chromium/components/download/internal/driver_entry.cc
+++ b/chromium/components/download/internal/background_service/driver_entry.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/driver_entry.h"
+#include "components/download/internal/background_service/driver_entry.h"
#include "net/http/http_response_headers.h"
diff --git a/chromium/components/download/internal/driver_entry.h b/chromium/components/download/internal/background_service/driver_entry.h
index 14e396ade8a..148308e6c4e 100644
--- a/chromium/components/download/internal/driver_entry.h
+++ b/chromium/components/download/internal/background_service/driver_entry.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_DRIVER_ENTRY_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_DRIVER_ENTRY_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DRIVER_ENTRY_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DRIVER_ENTRY_H_
#include <string>
#include <vector>
@@ -16,17 +16,13 @@ namespace net {
class HttpResponseHeaders;
} // namespace net
-namespace content {
-class DownloadItem;
-} // namespace content
-
namespace download {
// A snapshot of the states of a download. It's preferred to use the data on the
// fly and query new ones from download driver, instead of caching the states.
struct DriverEntry {
// States of the download. Mostly maps to
- // content::DownloadItem::DownloadState.
+ // download::DownloadItem::DownloadState.
enum class State {
IN_PROGRESS = 0,
COMPLETE = 1,
@@ -83,4 +79,4 @@ struct DriverEntry {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_DRIVER_ENTRY_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DRIVER_ENTRY_H_
diff --git a/chromium/components/download/internal/background_service/empty_file_monitor.cc b/chromium/components/download/internal/background_service/empty_file_monitor.cc
new file mode 100644
index 00000000000..185931f4e6c
--- /dev/null
+++ b/chromium/components/download/internal/background_service/empty_file_monitor.cc
@@ -0,0 +1,40 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/internal/background_service/empty_file_monitor.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+
+namespace download {
+
+EmptyFileMonitor::EmptyFileMonitor() : weak_ptr_factory_(this) {}
+
+EmptyFileMonitor::~EmptyFileMonitor() = default;
+
+void EmptyFileMonitor::Initialize(const InitCallback& callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindRepeating(callback, true /* success */));
+}
+
+void EmptyFileMonitor::DeleteUnknownFiles(
+ const Model::EntryList& known_entries,
+ const std::vector<DriverEntry>& known_driver_entries) {}
+
+void EmptyFileMonitor::CleanupFilesForCompletedEntries(
+ const Model::EntryList& entries,
+ const base::RepeatingClosure& completion_callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindRepeating(completion_callback));
+}
+
+void EmptyFileMonitor::DeleteFiles(
+ const std::set<base::FilePath>& files_to_remove,
+ stats::FileCleanupReason reason) {}
+
+void EmptyFileMonitor::HardRecover(const InitCallback& callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindRepeating(callback, true /* success */));
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/background_service/empty_file_monitor.h b/chromium/components/download/internal/background_service/empty_file_monitor.h
new file mode 100644
index 00000000000..715fb1b5479
--- /dev/null
+++ b/chromium/components/download/internal/background_service/empty_file_monitor.h
@@ -0,0 +1,42 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_EMPTY_FILE_MONITOR_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_EMPTY_FILE_MONITOR_H_
+
+#include "components/download/internal/background_service/file_monitor.h"
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+
+namespace download {
+
+// File monitor implementation that does nothing, used in incognito mode without
+// any file persisted to disk.
+class EmptyFileMonitor : public FileMonitor {
+ public:
+ EmptyFileMonitor();
+ ~EmptyFileMonitor() override;
+
+ private:
+ // FileMonitor implementation.
+ void Initialize(const InitCallback& callback) override;
+ void DeleteUnknownFiles(
+ const Model::EntryList& known_entries,
+ const std::vector<DriverEntry>& known_driver_entries) override;
+ void CleanupFilesForCompletedEntries(
+ const Model::EntryList& entries,
+ const base::RepeatingClosure& completion_callback) override;
+ void DeleteFiles(const std::set<base::FilePath>& files_to_remove,
+ stats::FileCleanupReason reason) override;
+ void HardRecover(const InitCallback& callback) override;
+
+ base::WeakPtrFactory<EmptyFileMonitor> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(EmptyFileMonitor);
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_EMPTY_FILE_MONITOR_H_
diff --git a/chromium/components/download/internal/background_service/empty_task_scheduler.cc b/chromium/components/download/internal/background_service/empty_task_scheduler.cc
new file mode 100644
index 00000000000..79faee51fb5
--- /dev/null
+++ b/chromium/components/download/internal/background_service/empty_task_scheduler.cc
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/internal/background_service/empty_task_scheduler.h"
+
+namespace download {
+
+EmptyTaskScheduler::EmptyTaskScheduler() = default;
+
+EmptyTaskScheduler::~EmptyTaskScheduler() = default;
+
+void EmptyTaskScheduler::ScheduleTask(DownloadTaskType task_type,
+ bool require_unmetered_network,
+ bool require_charging,
+ int optimal_battery_percentage,
+ long window_start_time_seconds,
+ long window_end_time_seconds) {}
+
+void EmptyTaskScheduler::CancelTask(DownloadTaskType task_type) {}
+
+} // namespace download
diff --git a/chromium/components/download/internal/background_service/empty_task_scheduler.h b/chromium/components/download/internal/background_service/empty_task_scheduler.h
new file mode 100644
index 00000000000..df32d19b458
--- /dev/null
+++ b/chromium/components/download/internal/background_service/empty_task_scheduler.h
@@ -0,0 +1,35 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_EMPTY_TASK_SCHEDULER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_EMPTY_TASK_SCHEDULER_H_
+
+#include "components/download/public/background_service/task_scheduler.h"
+
+#include "base/macros.h"
+
+namespace download {
+
+// Task scheduler that does nothing for incognito mode.
+class EmptyTaskScheduler : public TaskScheduler {
+ public:
+ EmptyTaskScheduler();
+ ~EmptyTaskScheduler() override;
+
+ private:
+ // TaskScheduler implementation.
+ void ScheduleTask(DownloadTaskType task_type,
+ bool require_unmetered_network,
+ bool require_charging,
+ int optimal_battery_percentage,
+ long window_start_time_seconds,
+ long window_end_time_seconds) override;
+ void CancelTask(DownloadTaskType task_type) override;
+
+ DISALLOW_COPY_AND_ASSIGN(EmptyTaskScheduler);
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_EMPTY_TASK_SCHEDULER_H_
diff --git a/chromium/components/download/internal/entry.cc b/chromium/components/download/internal/background_service/entry.cc
index c04fbd0038a..137b390152a 100644
--- a/chromium/components/download/internal/entry.cc
+++ b/chromium/components/download/internal/background_service/entry.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/entry.h"
+#include "components/download/internal/background_service/entry.h"
#include "base/trace_event/memory_usage_estimator.h"
diff --git a/chromium/components/download/internal/entry.h b/chromium/components/download/internal/background_service/entry.h
index 1cd503cb852..f3efe2b22ec 100644
--- a/chromium/components/download/internal/entry.h
+++ b/chromium/components/download/internal/background_service/entry.h
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_ENTRY_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_ENTRY_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_ENTRY_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_ENTRY_H_
#include "base/time/time.h"
-#include "components/download/public/client.h"
-#include "components/download/public/clients.h"
-#include "components/download/public/download_params.h"
+#include "components/download/public/background_service/client.h"
+#include "components/download/public/background_service/clients.h"
+#include "components/download/public/background_service/download_params.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
namespace download {
@@ -102,4 +102,4 @@ struct Entry {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_ENTRY_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_ENTRY_H_
diff --git a/chromium/components/download/internal/entry_utils.cc b/chromium/components/download/internal/background_service/entry_utils.cc
index 1601e21b0d9..8738cb02350 100644
--- a/chromium/components/download/internal/entry_utils.cc
+++ b/chromium/components/download/internal/background_service/entry_utils.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/entry_utils.h"
+#include "components/download/internal/background_service/entry_utils.h"
#include <algorithm>
-#include "components/download/internal/entry.h"
-#include "components/download/public/download_metadata.h"
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/public/background_service/download_metadata.h"
namespace download {
namespace util {
diff --git a/chromium/components/download/internal/entry_utils.h b/chromium/components/download/internal/background_service/entry_utils.h
index 22a03fd6ae4..410383c50b6 100644
--- a/chromium/components/download/internal/entry_utils.h
+++ b/chromium/components/download/internal/background_service/entry_utils.h
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_ENTRY_UTILS_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_ENTRY_UTILS_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_ENTRY_UTILS_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_ENTRY_UTILS_H_
#include <map>
#include <set>
#include <string>
#include <vector>
-#include "components/download/internal/model.h"
-#include "components/download/internal/scheduler/device_status.h"
-#include "components/download/public/clients.h"
-#include "components/download/public/download_metadata.h"
+#include "components/download/internal/background_service/model.h"
+#include "components/download/internal/background_service/scheduler/device_status.h"
+#include "components/download/public/background_service/clients.h"
+#include "components/download/public/background_service/download_metadata.h"
namespace download {
@@ -52,4 +52,4 @@ DownloadMetaData BuildDownloadMetaData(Entry* entry);
} // namespace util
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_ENTRY_UTILS_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_ENTRY_UTILS_H_
diff --git a/chromium/components/download/internal/entry_utils_unittest.cc b/chromium/components/download/internal/background_service/entry_utils_unittest.cc
index 0a0e7419aba..3730fb535ca 100644
--- a/chromium/components/download/internal/entry_utils_unittest.cc
+++ b/chromium/components/download/internal/background_service/entry_utils_unittest.cc
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/entry_utils.h"
+#include "components/download/internal/background_service/entry_utils.h"
#include <algorithm>
#include "base/memory/ptr_util.h"
-#include "components/download/internal/test/entry_utils.h"
-#include "components/download/public/clients.h"
-#include "components/download/public/download_metadata.h"
+#include "components/download/internal/background_service/test/entry_utils.h"
+#include "components/download/public/background_service/clients.h"
+#include "components/download/public/background_service/download_metadata.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace download {
diff --git a/chromium/components/download/internal/file_monitor.h b/chromium/components/download/internal/background_service/file_monitor.h
index 1174b2ef7d1..9d5447adf40 100644
--- a/chromium/components/download/internal/file_monitor.h
+++ b/chromium/components/download/internal/background_service/file_monitor.h
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_FILE_MONITOR_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_FILE_MONITOR_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_FILE_MONITOR_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_FILE_MONITOR_H_
#include <memory>
#include <set>
#include <string>
#include <vector>
-#include "components/download/internal/model.h"
-#include "components/download/internal/stats.h"
+#include "components/download/internal/background_service/model.h"
+#include "components/download/internal/background_service/stats.h"
namespace base {
class FilePath;
@@ -53,4 +53,4 @@ class FileMonitor {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_FILE_MONITOR_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_FILE_MONITOR_H_
diff --git a/chromium/components/download/internal/file_monitor_impl.cc b/chromium/components/download/internal/background_service/file_monitor_impl.cc
index aaeb6adeec3..9bb4e68b009 100644
--- a/chromium/components/download/internal/file_monitor_impl.cc
+++ b/chromium/components/download/internal/background_service/file_monitor_impl.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/download/internal/file_monitor_impl.h"
+#include "components/download/internal/background_service/file_monitor_impl.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
diff --git a/chromium/components/download/internal/file_monitor_impl.h b/chromium/components/download/internal/background_service/file_monitor_impl.h
index 8b8635319c2..723843f3785 100644
--- a/chromium/components/download/internal/file_monitor_impl.h
+++ b/chromium/components/download/internal/background_service/file_monitor_impl.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_FILE_MONITOR_IMPL_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_FILE_MONITOR_IMPL_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_FILE_MONITOR_IMPL_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_FILE_MONITOR_IMPL_H_
-#include "components/download/internal/file_monitor.h"
+#include "components/download/internal/background_service/file_monitor.h"
#include <memory>
#include <set>
@@ -17,9 +17,9 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
-#include "components/download/internal/driver_entry.h"
-#include "components/download/internal/model.h"
-#include "components/download/internal/stats.h"
+#include "components/download/internal/background_service/driver_entry.h"
+#include "components/download/internal/background_service/model.h"
+#include "components/download/internal/background_service/stats.h"
namespace download {
@@ -56,4 +56,4 @@ class FileMonitorImpl : public FileMonitor {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_FILE_MONITOR_IMPL_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_FILE_MONITOR_IMPL_H_
diff --git a/chromium/components/download/internal/file_monitor_unittest.cc b/chromium/components/download/internal/background_service/file_monitor_unittest.cc
index 347d2d5b468..f2aafe07e54 100644
--- a/chromium/components/download/internal/file_monitor_unittest.cc
+++ b/chromium/components/download/internal/background_service/file_monitor_unittest.cc
@@ -12,10 +12,10 @@
#include "base/optional.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "components/download/internal/driver_entry.h"
-#include "components/download/internal/entry.h"
-#include "components/download/internal/file_monitor_impl.h"
-#include "components/download/internal/test/entry_utils.h"
+#include "components/download/internal/background_service/driver_entry.h"
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/internal/background_service/file_monitor_impl.h"
+#include "components/download/internal/background_service/test/entry_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/download/internal/background_service/in_memory_download.cc b/chromium/components/download/internal/background_service/in_memory_download.cc
new file mode 100644
index 00000000000..091f0e19bf8
--- /dev/null
+++ b/chromium/components/download/internal/background_service/in_memory_download.cc
@@ -0,0 +1,312 @@
+// 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/download/internal/background_service/in_memory_download.h"
+
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/strings/string_util.h"
+#include "components/download/internal/background_service/blob_task_proxy.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_status_code.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "net/url_request/url_fetcher.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
+
+namespace download {
+
+namespace {
+
+// Converts a string to HTTP method used by URLFetcher.
+net::URLFetcher::RequestType ToRequestType(const std::string& method) {
+ // Only supports GET and POST.
+ if (base::EqualsCaseInsensitiveASCII(method, "GET"))
+ return net::URLFetcher::RequestType::GET;
+ if (base::EqualsCaseInsensitiveASCII(method, "POST"))
+ return net::URLFetcher::RequestType::POST;
+
+ NOTREACHED();
+ return net::URLFetcher::RequestType::GET;
+}
+
+} // namespace
+
+InMemoryDownloadImpl::ResponseWriter::ResponseWriter(
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
+ : paused_on_io_(false), io_task_runner_(io_task_runner) {}
+
+InMemoryDownloadImpl::ResponseWriter::~ResponseWriter() = default;
+
+void InMemoryDownloadImpl::ResponseWriter::Pause() {
+ io_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ResponseWriter::PauseOnIO, base::Unretained(this)));
+}
+
+void InMemoryDownloadImpl::ResponseWriter::PauseOnIO() {
+ io_task_runner_->BelongsToCurrentThread();
+ paused_on_io_ = true;
+}
+
+void InMemoryDownloadImpl::ResponseWriter::Resume() {
+ io_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ResponseWriter::ResumeOnIO, base::Unretained(this)));
+}
+
+void InMemoryDownloadImpl::ResponseWriter::ResumeOnIO() {
+ io_task_runner_->BelongsToCurrentThread();
+ paused_on_io_ = false;
+
+ // Continue read from network layer. Since we didn't write on pause, report
+ // 0 byte to network layer.
+ if (!write_callback_.is_null()) {
+ base::ResetAndReturn(&write_callback_).Run(0u);
+ }
+}
+
+std::unique_ptr<std::string> InMemoryDownloadImpl::ResponseWriter::TakeData() {
+ return std::move(data_);
+}
+
+int InMemoryDownloadImpl::ResponseWriter::Initialize(
+ const net::CompletionCallback& callback) {
+ data_ = std::make_unique<std::string>();
+ return net::OK;
+}
+
+int InMemoryDownloadImpl::ResponseWriter::Write(
+ net::IOBuffer* buffer,
+ int num_bytes,
+ const net::CompletionCallback& callback) {
+ io_task_runner_->BelongsToCurrentThread();
+
+ if (paused_on_io_) {
+ write_callback_ = callback;
+ return net::ERR_IO_PENDING;
+ }
+
+ DCHECK(data_);
+ data_->append(buffer->data(), num_bytes);
+ return num_bytes;
+}
+
+int InMemoryDownloadImpl::ResponseWriter::Finish(
+ int net_error,
+ const net::CompletionCallback& callback) {
+ io_task_runner_->BelongsToCurrentThread();
+ return net::OK;
+}
+
+InMemoryDownload::InMemoryDownload(const std::string& guid)
+ : guid_(guid), state_(State::INITIAL), bytes_downloaded_(0u) {}
+
+InMemoryDownload::~InMemoryDownload() = default;
+
+InMemoryDownloadImpl::InMemoryDownloadImpl(
+ const std::string& guid,
+ const RequestParams& request_params,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ Delegate* delegate,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ BlobTaskProxy::BlobContextGetter blob_context_getter,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
+ : InMemoryDownload(guid),
+ request_params_(request_params),
+ traffic_annotation_(traffic_annotation),
+ request_context_getter_(request_context_getter),
+ blob_task_proxy_(
+ BlobTaskProxy::Create(blob_context_getter, io_task_runner)),
+ io_task_runner_(io_task_runner),
+ delegate_(delegate),
+ paused_(false),
+ completion_notified_(false),
+ weak_ptr_factory_(this) {
+ DCHECK(!guid_.empty());
+}
+
+InMemoryDownloadImpl::~InMemoryDownloadImpl() {
+ io_task_runner_->DeleteSoon(FROM_HERE, blob_task_proxy_.release());
+}
+
+void InMemoryDownloadImpl::Start() {
+ DCHECK(state_ == State::INITIAL) << "Only call Start() for new download.";
+ SendRequest();
+ state_ = State::IN_PROGRESS;
+}
+
+void InMemoryDownloadImpl::Pause() {
+ if (paused_)
+ return;
+ paused_ = true;
+
+ switch (state_) {
+ case State::INITIAL:
+ // Do nothing.
+ return;
+ case State::IN_PROGRESS:
+ // Do nothing if network operation is done.
+ DCHECK(response_writer_);
+ response_writer_->Pause();
+ return;
+ case State::FAILED:
+ return;
+ case State::COMPLETE:
+ // Do nothing.
+ return;
+ }
+}
+
+void InMemoryDownloadImpl::Resume() {
+ if (!paused_)
+ return;
+ paused_ = false;
+
+ switch (state_) {
+ case State::INITIAL:
+ NOTREACHED();
+ return;
+ case State::IN_PROGRESS:
+ // Do nothing if network operation is done.
+ DCHECK(response_writer_);
+ response_writer_->Resume();
+ return;
+ case State::FAILED:
+ // Restart the network layer. No ongoing blob task should exist.
+ SendRequest();
+ state_ = State::IN_PROGRESS;
+ return;
+ case State::COMPLETE:
+ NotifyDelegateDownloadComplete();
+ return;
+ }
+}
+
+std::unique_ptr<storage::BlobDataHandle> InMemoryDownloadImpl::ResultAsBlob() {
+ DCHECK(state_ == State::COMPLETE || state_ == State::FAILED);
+ // Return a copy, we keep one reference of the underlying data to avoid
+ // unexpected deletion.
+ return std::make_unique<storage::BlobDataHandle>(*blob_data_handle_);
+}
+
+size_t InMemoryDownloadImpl::EstimateMemoryUsage() const {
+ return bytes_downloaded_;
+}
+
+void InMemoryDownloadImpl::OnURLFetchDownloadProgress(
+ const net::URLFetcher* source,
+ int64_t current,
+ int64_t total,
+ int64_t current_network_bytes) {
+ bytes_downloaded_ = current;
+
+ // TODO(xingliu): Throttle the update frequency. See https://crbug.com/809674.
+ if (delegate_)
+ delegate_->OnDownloadProgress(this);
+}
+
+void InMemoryDownloadImpl::OnURLFetchComplete(const net::URLFetcher* source) {
+ DCHECK(source);
+ response_headers_ = source->GetResponseHeaders();
+
+ switch (source->GetStatus().status()) {
+ case net::URLRequestStatus::Status::SUCCESS:
+ if (HandleResponseCode(source->GetResponseCode())) {
+ SaveAsBlob();
+ return;
+ }
+
+ state_ = State::FAILED;
+ NotifyDelegateDownloadComplete();
+ return;
+ case net::URLRequestStatus::Status::IO_PENDING:
+ return;
+ case net::URLRequestStatus::Status::CANCELED:
+ case net::URLRequestStatus::Status::FAILED:
+ state_ = State::FAILED;
+ NotifyDelegateDownloadComplete();
+ return;
+ }
+}
+
+bool InMemoryDownloadImpl::HandleResponseCode(int response_code) {
+ switch (response_code) {
+ case -1: // Non-HTTP request.
+ case net::HTTP_OK:
+ case net::HTTP_NON_AUTHORITATIVE_INFORMATION:
+ case net::HTTP_PARTIAL_CONTENT:
+ case net::HTTP_CREATED:
+ case net::HTTP_ACCEPTED:
+ case net::HTTP_NO_CONTENT:
+ case net::HTTP_RESET_CONTENT:
+ return true;
+ // All other codes are considered as failed.
+ default:
+ return false;
+ }
+}
+
+void InMemoryDownloadImpl::SaveAsBlob() {
+ DCHECK(url_fetcher_);
+ std::unique_ptr<std::string> data = response_writer_->TakeData();
+ auto callback = base::BindOnce(&InMemoryDownloadImpl::OnSaveBlobDone,
+ weak_ptr_factory_.GetWeakPtr());
+ blob_task_proxy_->SaveAsBlob(std::move(data), std::move(callback));
+}
+
+void InMemoryDownloadImpl::OnSaveBlobDone(
+ std::unique_ptr<storage::BlobDataHandle> blob_handle,
+ storage::BlobStatus status) {
+ // |status| is valid on IO thread, consumer of |blob_handle| should validate
+ // the data when using the blob data.
+ state_ =
+ (status == storage::BlobStatus::DONE) ? State::COMPLETE : State::FAILED;
+
+ // TODO(xingliu): Add metric for blob status code. If failed, consider remove
+ // |blob_data_handle_|. See https://crbug.com/809674.
+ blob_data_handle_ = std::move(blob_handle);
+ completion_time_ = base::Time::Now();
+
+ // Resets network backend.
+ response_writer_ = nullptr;
+ url_fetcher_.reset();
+
+ // Not considering |paused_| here, if pause after starting a blob operation,
+ // just let it finish.
+ NotifyDelegateDownloadComplete();
+}
+
+void InMemoryDownloadImpl::NotifyDelegateDownloadComplete() {
+ if (completion_notified_)
+ return;
+ completion_notified_ = true;
+
+ if (delegate_)
+ delegate_->OnDownloadComplete(this);
+}
+
+void InMemoryDownloadImpl::SendRequest() {
+ url_fetcher_ = net::URLFetcher::Create(request_params_.url,
+ ToRequestType(request_params_.method),
+ this, traffic_annotation_);
+ url_fetcher_->SetRequestContext(request_context_getter_.get());
+ url_fetcher_->SetExtraRequestHeaders(
+ request_params_.request_headers.ToString());
+ response_writer_ =
+ new ResponseWriter(request_context_getter_->GetNetworkTaskRunner());
+ url_fetcher_->SaveResponseWithWriter(
+ std::unique_ptr<ResponseWriter>(response_writer_));
+ url_fetcher_->Start();
+
+ // Pause on network thread if needed.
+ if (paused_)
+ response_writer_->Pause();
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/in_memory_download.h b/chromium/components/download/internal/background_service/in_memory_download.h
index f499758ee61..8f97c9ea4c8 100644
--- a/chromium/components/download/internal/in_memory_download.h
+++ b/chromium/components/download/internal/background_service/in_memory_download.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_INTERNAL_IN_MEMORY_DOWNLOAD_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_IN_MEMORY_DOWNLOAD_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_IN_MEMORY_DOWNLOAD_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_IN_MEMORY_DOWNLOAD_H_
#include <memory>
#include <string>
@@ -12,10 +12,11 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
-#include "components/download/internal/blob_task_proxy.h"
-#include "components/download/public/download_params.h"
+#include "components/download/internal/background_service/blob_task_proxy.h"
+#include "components/download/public/background_service/download_params.h"
#include "net/base/completion_callback.h"
#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_fetcher_response_writer.h"
#include "net/url_request/url_request_context_getter.h"
namespace net {
@@ -31,21 +32,13 @@ namespace download {
struct RequestParams;
-// Object to start a single download and hold in-memory download data.
+// Class to start a single download and hold in-memory download data.
// Used by download service in Incognito mode, where download files shouldn't
// be persisted to disk.
//
// Life cycle: The object is created before creating the network request.
// Call Start() to send the network request.
-//
-// Threading contract:
-// 1. This object lives on the main thread.
-// 2. Reading/writing IO buffer from network is done on another thread,
-// based on |request_context_getter_|. When complete, main thread is notified.
-// 3. After network IO is done, Blob related work is done on IO thread with
-// |blob_task_proxy_|, then notify the result to main thread.
-
-class InMemoryDownload : public net::URLFetcherDelegate {
+class InMemoryDownload {
public:
// Report download progress with in-memory download backend.
class Delegate {
@@ -57,6 +50,18 @@ class InMemoryDownload : public net::URLFetcherDelegate {
virtual ~Delegate() = default;
};
+ // Factory to create in memory download.
+ class Factory {
+ public:
+ virtual std::unique_ptr<InMemoryDownload> Create(
+ const std::string& guid,
+ const RequestParams& request_params,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ Delegate* delegate) = 0;
+
+ virtual ~Factory() = default;
+ };
+
// States of the download.
enum class State {
// The object is created but network request has not been sent.
@@ -79,7 +84,62 @@ class InMemoryDownload : public net::URLFetcherDelegate {
COMPLETE,
};
- InMemoryDownload(
+ virtual ~InMemoryDownload();
+
+ // Send the download request.
+ virtual void Start() = 0;
+
+ // Pause the download request.
+ virtual void Pause() = 0;
+
+ // Resume the download request.
+ virtual void Resume() = 0;
+
+ // Get a copy of blob data handle.
+ virtual std::unique_ptr<storage::BlobDataHandle> ResultAsBlob() = 0;
+
+ // Returns the estimate of dynamically allocated memory in bytes.
+ virtual size_t EstimateMemoryUsage() const = 0;
+
+ const std::string& guid() const { return guid_; }
+ uint64_t bytes_downloaded() const { return bytes_downloaded_; }
+ State state() const { return state_; }
+ const base::Time& completion_time() const { return completion_time_; }
+ scoped_refptr<const net::HttpResponseHeaders> response_headers() const {
+ return response_headers_;
+ }
+
+ protected:
+ InMemoryDownload(const std::string& guid);
+
+ // GUID of the download.
+ const std::string guid_;
+
+ State state_;
+
+ // Completion time of download when data is saved as blob.
+ base::Time completion_time_;
+
+ // HTTP response headers.
+ scoped_refptr<const net::HttpResponseHeaders> response_headers_;
+
+ uint64_t bytes_downloaded_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InMemoryDownload);
+};
+
+// Implementation of InMemoryDownload and uses URLFetcher as network backend.
+// Threading contract:
+// 1. This object lives on the main thread.
+// 2. Reading/writing IO buffer from network is done on another thread,
+// based on |request_context_getter_|. When complete, main thread is notified.
+// 3. After network IO is done, Blob related work is done on IO thread with
+// |blob_task_proxy_|, then notify the result to main thread.
+class InMemoryDownloadImpl : public net::URLFetcherDelegate,
+ public InMemoryDownload {
+ public:
+ InMemoryDownloadImpl(
const std::string& guid,
const RequestParams& request_params,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
@@ -87,19 +147,56 @@ class InMemoryDownload : public net::URLFetcherDelegate {
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
BlobTaskProxy::BlobContextGetter blob_context_getter,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
- ~InMemoryDownload() override;
+ ~InMemoryDownloadImpl() override;
- // Send the download request.
- void Start();
+ private:
+ // Response writer that supports pause and resume operations.
+ class ResponseWriter : public net::URLFetcherResponseWriter {
+ public:
+ ResponseWriter(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+ ~ResponseWriter() override;
- // Get a copy of blob data handle.
- std::unique_ptr<storage::BlobDataHandle> ResultAsBlob();
+ // Pause writing data from pipe into |data_|.
+ void Pause();
- const std::string& guid() const { return guid_; }
- uint64_t bytes_downloaded() const { return bytes_downloaded_; }
- State state() const { return state_; }
+ // Resume writing data from the pipe into |data_|.
+ void Resume();
+
+ // Take the data, must be called after the network layer completes its job.
+ std::unique_ptr<std::string> TakeData();
+
+ private:
+ // net::URLFetcherResponseWriter implementation.
+ int Initialize(const net::CompletionCallback& callback) override;
+ int Write(net::IOBuffer* buffer,
+ int num_bytes,
+ const net::CompletionCallback& callback) override;
+ int Finish(int net_error, const net::CompletionCallback& callback) override;
+
+ void PauseOnIO();
+ void ResumeOnIO();
+
+ // Download data, should be moved to avoid extra copy.
+ std::unique_ptr<std::string> data_;
+
+ bool paused_on_io_;
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+
+ // When paused, cached callback to trigger the next read. Must be set and
+ // called on fetcher's IO thread.
+ net::CompletionCallback write_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResponseWriter);
+ };
+
+ // InMemoryDownload implementation.
+ void Start() override;
+ void Pause() override;
+ void Resume() override;
+
+ std::unique_ptr<storage::BlobDataHandle> ResultAsBlob() override;
+ size_t EstimateMemoryUsage() const override;
- private:
// net::URLFetcherDelegate implementation.
void OnURLFetchDownloadProgress(const net::URLFetcher* source,
int64_t current,
@@ -116,11 +213,13 @@ class InMemoryDownload : public net::URLFetcherDelegate {
void OnSaveBlobDone(std::unique_ptr<storage::BlobDataHandle> blob_handle,
storage::BlobStatus status);
- // Notifies the delegate about completion.
+ // Notifies the delegate about completion. Can be called multiple times and
+ // |completion_notified_| will ensure the delegate only receive one completion
+ // call.
void NotifyDelegateDownloadComplete();
- // GUID of the download.
- const std::string guid_;
+ // Sends the network request.
+ void SendRequest();
// Request parameters of the download.
const RequestParams request_params_;
@@ -133,6 +232,10 @@ class InMemoryDownload : public net::URLFetcherDelegate {
// memory when needed.
std::unique_ptr<net::URLFetcher> url_fetcher_;
+ // Owned by |url_fetcher_|. Lives on fetcher's delegate thread, perform
+ // network IO on fetcher's IO thread.
+ ResponseWriter* response_writer_;
+
// Request context getter used by |url_fetcher_|.
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
@@ -146,18 +249,19 @@ class InMemoryDownload : public net::URLFetcherDelegate {
// Used to access blob storage context.
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
- State state_;
-
Delegate* delegate_;
- uint64_t bytes_downloaded_;
+ bool paused_;
+
+ // Ensures Delegate::OnDownloadComplete is only called once.
+ bool completion_notified_;
// Bounded to main thread task runner.
- base::WeakPtrFactory<InMemoryDownload> weak_ptr_factory_;
+ base::WeakPtrFactory<InMemoryDownloadImpl> weak_ptr_factory_;
- DISALLOW_COPY_AND_ASSIGN(InMemoryDownload);
+ DISALLOW_COPY_AND_ASSIGN(InMemoryDownloadImpl);
};
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_IN_MEMORY_DOWNLOAD_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_IN_MEMORY_DOWNLOAD_H_
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
new file mode 100644
index 00000000000..186fda2fd6b
--- /dev/null
+++ b/chromium/components/download/internal/background_service/in_memory_download_driver.cc
@@ -0,0 +1,177 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/internal/background_service/in_memory_download_driver.h"
+
+namespace download {
+
+namespace {
+
+DriverEntry::State ToDriverEntryState(InMemoryDownload::State state) {
+ switch (state) {
+ case InMemoryDownload::State::INITIAL:
+ return DriverEntry::State::IN_PROGRESS;
+ case InMemoryDownload::State::IN_PROGRESS:
+ return DriverEntry::State::IN_PROGRESS;
+ case InMemoryDownload::State::FAILED:
+ return DriverEntry::State::INTERRUPTED;
+ case InMemoryDownload::State::COMPLETE:
+ return DriverEntry::State::COMPLETE;
+ }
+ NOTREACHED();
+ return DriverEntry::State::UNKNOWN;
+}
+
+// Helper function to create download driver entry based on in memory download.
+DriverEntry CreateDriverEntry(const InMemoryDownload& download) {
+ DriverEntry entry;
+ entry.guid = download.guid();
+ entry.state = ToDriverEntryState(download.state());
+ // TODO(xingliu): Support pause. See https://crbug.com/809674.
+ entry.paused = false;
+ entry.done = entry.state == DriverEntry::State::INTERRUPTED ||
+ entry.state == DriverEntry::State::COMPLETE ||
+ entry.state == DriverEntry::State::CANCELLED;
+ entry.bytes_downloaded = download.bytes_downloaded();
+ entry.response_headers = download.response_headers();
+ if (entry.response_headers) {
+ entry.expected_total_size = entry.response_headers->GetContentLength();
+ }
+ // TODO(xingliu): Support resumption. UrlFetcher doesn't expose url chain.
+ // Figure out if empty url chain is OK and how url chain is used.
+ entry.can_resume = false;
+ return entry;
+}
+
+} // namespace
+
+InMemoryDownloadFactory::InMemoryDownloadFactory(
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ BlobTaskProxy::BlobContextGetter blob_context_getter,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
+ : request_context_getter_(request_context_getter),
+ blob_context_getter_(blob_context_getter),
+ io_task_runner_(io_task_runner) {}
+
+InMemoryDownloadFactory::~InMemoryDownloadFactory() = default;
+
+std::unique_ptr<InMemoryDownload> InMemoryDownloadFactory::Create(
+ const std::string& guid,
+ const RequestParams& request_params,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ InMemoryDownload::Delegate* delegate) {
+ return std::make_unique<InMemoryDownloadImpl>(
+ guid, request_params, traffic_annotation, delegate,
+ request_context_getter_, blob_context_getter_, io_task_runner_);
+}
+
+InMemoryDownloadDriver::InMemoryDownloadDriver(
+ std::unique_ptr<InMemoryDownload::Factory> download_factory)
+ : client_(nullptr), download_factory_(std::move(download_factory)) {}
+
+InMemoryDownloadDriver::~InMemoryDownloadDriver() = default;
+
+void InMemoryDownloadDriver::Initialize(DownloadDriver::Client* client) {
+ DCHECK(!client_) << "Initialize can be called only once.";
+ client_ = client;
+ DCHECK(client_);
+ client_->OnDriverReady(true);
+}
+
+void InMemoryDownloadDriver::HardRecover() {
+ client_->OnDriverHardRecoverComplete(true);
+}
+
+bool InMemoryDownloadDriver::IsReady() const {
+ return true;
+}
+
+void InMemoryDownloadDriver::Start(
+ const RequestParams& request_params,
+ const std::string& guid,
+ const base::FilePath& file_path,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation) {
+ std::unique_ptr<InMemoryDownload> download =
+ download_factory_->Create(guid, request_params, traffic_annotation, this);
+ InMemoryDownload* download_ptr = download.get();
+ DCHECK(downloads_.find(guid) == downloads_.end()) << "Existing GUID found.";
+ downloads_.emplace(guid, std::move(download));
+
+ download_ptr->Start();
+ client_->OnDownloadCreated(CreateDriverEntry(*download_ptr));
+}
+
+void InMemoryDownloadDriver::Remove(const std::string& guid) {
+ downloads_.erase(guid);
+}
+
+void InMemoryDownloadDriver::Pause(const std::string& guid) {
+ auto it = downloads_.find(guid);
+ if (it != downloads_.end())
+ it->second->Pause();
+}
+
+void InMemoryDownloadDriver::Resume(const std::string& guid) {
+ auto it = downloads_.find(guid);
+ if (it != downloads_.end())
+ it->second->Resume();
+}
+
+base::Optional<DriverEntry> InMemoryDownloadDriver::Find(
+ const std::string& guid) {
+ base::Optional<DriverEntry> entry;
+ auto it = downloads_.find(guid);
+ if (it != downloads_.end())
+ entry = CreateDriverEntry(*it->second.get());
+ return entry;
+}
+
+std::set<std::string> InMemoryDownloadDriver::GetActiveDownloads() {
+ std::set<std::string> downloads;
+ for (const auto& it : downloads_) {
+ if (it.second->state() == InMemoryDownload::State::INITIAL ||
+ it.second->state() == InMemoryDownload::State::IN_PROGRESS) {
+ downloads.emplace(it.first);
+ }
+ }
+ return downloads;
+}
+
+size_t InMemoryDownloadDriver::EstimateMemoryUsage() const {
+ size_t memory_usage = 0u;
+ for (const auto& it : downloads_) {
+ memory_usage += it.second->EstimateMemoryUsage();
+ }
+ return memory_usage;
+}
+
+void InMemoryDownloadDriver::OnDownloadProgress(InMemoryDownload* download) {
+ DCHECK(client_);
+ client_->OnDownloadUpdated(CreateDriverEntry(*download));
+}
+
+void InMemoryDownloadDriver::OnDownloadComplete(InMemoryDownload* download) {
+ DCHECK(download);
+ DCHECK(client_);
+ DriverEntry entry = CreateDriverEntry(*download);
+ switch (download->state()) {
+ case InMemoryDownload::State::FAILED:
+ // URLFetcher retries for network failures.
+ client_->OnDownloadFailed(entry, FailureType::NOT_RECOVERABLE);
+ // Should immediately return in case |client_| removes |download| in
+ // OnDownloadFailed.
+ return;
+ case InMemoryDownload::State::COMPLETE:
+ client_->OnDownloadSucceeded(entry);
+ // Should immediately return in case |client_| removes |download| in
+ // OnDownloadSucceeded.
+ return;
+ case InMemoryDownload::State::INITIAL:
+ case InMemoryDownload::State::IN_PROGRESS:
+ NOTREACHED();
+ return;
+ }
+}
+
+} // namespace download
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
new file mode 100644
index 00000000000..019f7577b05
--- /dev/null
+++ b/chromium/components/download/internal/background_service/in_memory_download_driver.h
@@ -0,0 +1,88 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_IN_MEMORY_DOWNLOAD_DRIVER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_IN_MEMORY_DOWNLOAD_DRIVER_H_
+
+#include "components/download/internal/background_service/download_driver.h"
+
+#include <map>
+#include <memory>
+
+#include "base/macros.h"
+#include "components/download/internal/background_service/in_memory_download.h"
+
+namespace download {
+
+class InMemoryDownload;
+
+// Factory to create in memory download object.
+class InMemoryDownloadFactory : public InMemoryDownload::Factory {
+ public:
+ InMemoryDownloadFactory(
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ BlobTaskProxy::BlobContextGetter blob_context_getter,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+ ~InMemoryDownloadFactory() override;
+
+ private:
+ // InMemoryDownload::Factory implementation.
+ std::unique_ptr<InMemoryDownload> Create(
+ const std::string& guid,
+ const RequestParams& request_params,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ InMemoryDownload::Delegate* delegate) override;
+
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
+ BlobTaskProxy::BlobContextGetter blob_context_getter_;
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(InMemoryDownloadFactory);
+};
+
+// Download backend that owns the list of in memory downloads and propagate
+// notification to its client.
+class InMemoryDownloadDriver : public DownloadDriver,
+ public InMemoryDownload::Delegate {
+ public:
+ explicit InMemoryDownloadDriver(
+ std::unique_ptr<InMemoryDownload::Factory> download_factory);
+ ~InMemoryDownloadDriver() override;
+
+ private:
+ // DownloadDriver implementation.
+ void Initialize(DownloadDriver::Client* client) override;
+ void HardRecover() override;
+ bool IsReady() const override;
+ void Start(
+ const RequestParams& request_params,
+ const std::string& guid,
+ const base::FilePath& file_path,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation) override;
+ void Remove(const std::string& guid) override;
+ void Pause(const std::string& guid) override;
+ void Resume(const std::string& guid) override;
+ base::Optional<DriverEntry> Find(const std::string& guid) override;
+ std::set<std::string> GetActiveDownloads() override;
+ size_t EstimateMemoryUsage() const override;
+
+ // InMemoryDownload::Delegate implementation.
+ void OnDownloadProgress(InMemoryDownload* download) override;
+ void OnDownloadComplete(InMemoryDownload* download) override;
+
+ // The client that receives updates from low level download logic.
+ DownloadDriver::Client* client_;
+
+ // The factory used to create in memory download objects.
+ std::unique_ptr<InMemoryDownload::Factory> download_factory_;
+
+ // A map of GUID and in memory download, which holds download data.
+ std::map<std::string, std::unique_ptr<InMemoryDownload>> downloads_;
+
+ DISALLOW_COPY_AND_ASSIGN(InMemoryDownloadDriver);
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_IN_MEMORY_DOWNLOAD_DRIVER_H_
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
new file mode 100644
index 00000000000..7199e1c04ae
--- /dev/null
+++ b/chromium/components/download/internal/background_service/in_memory_download_driver_unittest.cc
@@ -0,0 +1,193 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/internal/background_service/in_memory_download_driver.h"
+
+#include <memory>
+
+#include "components/download/internal/background_service/test/mock_download_driver_client.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+
+namespace download {
+namespace {
+
+MATCHER_P(DriverEntryEqual, entry, "") {
+ return entry.guid == arg.guid && entry.state == arg.state &&
+ entry.bytes_downloaded == arg.bytes_downloaded;
+}
+
+// Test in memory download that doesn't do complex IO.
+class TestInMemoryDownload : public InMemoryDownload {
+ public:
+ TestInMemoryDownload(const std::string& guid,
+ InMemoryDownload::Delegate* delegate)
+ : InMemoryDownload(guid), delegate_(delegate) {
+ DCHECK(delegate_) << "Delegate can't be nullptr.";
+ }
+
+ void SimulateDownloadProgress() {
+ state_ = InMemoryDownload::State::IN_PROGRESS;
+ delegate_->OnDownloadProgress(this);
+ }
+
+ void SimulateDownloadComplete(bool success) {
+ state_ = success ? InMemoryDownload::State::COMPLETE
+ : InMemoryDownload::State::FAILED;
+ delegate_->OnDownloadComplete(this);
+ }
+
+ // InMemoryDownload implementation.
+ void Start() override {}
+ void Pause() override {}
+ void Resume() override {}
+ std::unique_ptr<storage::BlobDataHandle> ResultAsBlob() override {
+ return nullptr;
+ }
+ size_t EstimateMemoryUsage() const override { return 0u; }
+
+ private:
+ InMemoryDownload::Delegate* delegate_;
+ DISALLOW_COPY_AND_ASSIGN(TestInMemoryDownload);
+};
+
+// Factory that injects to InMemoryDownloadDriver and only creates fake objects.
+class TestInMemoryDownloadFactory : public InMemoryDownload::Factory {
+ public:
+ TestInMemoryDownloadFactory() = default;
+ ~TestInMemoryDownloadFactory() override = default;
+
+ // InMemoryDownload::Factory implementation.
+ std::unique_ptr<InMemoryDownload> Create(
+ const std::string& guid,
+ const RequestParams& request_params,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation,
+ InMemoryDownload::Delegate* delegate) override {
+ auto download = std::make_unique<TestInMemoryDownload>(guid, delegate);
+ download_ = download.get();
+ return download;
+ }
+
+ // Returns the last created download, if the driver remove the object, this
+ // can be invalid memory, so need to use with caution.
+ TestInMemoryDownload* last_created_download() { return download_; }
+
+ private:
+ TestInMemoryDownload* download_ = nullptr;
+ DISALLOW_COPY_AND_ASSIGN(TestInMemoryDownloadFactory);
+};
+
+class InMemoryDownloadDriverTest : public testing::Test {
+ public:
+ InMemoryDownloadDriverTest() = default;
+ ~InMemoryDownloadDriverTest() override = default;
+
+ // Helper method to call public method on |driver_|.
+ DownloadDriver* driver() {
+ return static_cast<DownloadDriver*>(driver_.get());
+ }
+
+ MockDriverClient* driver_client() { return &driver_client_; }
+
+ TestInMemoryDownloadFactory* factory() { return factory_; }
+
+ void SetUp() override {
+ auto factory = std::make_unique<TestInMemoryDownloadFactory>();
+ factory_ = factory.get();
+ driver_ = std::make_unique<InMemoryDownloadDriver>(std::move(factory));
+ driver()->Initialize(&driver_client_);
+ }
+
+ void TearDown() override {
+ // Driver should be teared down before its owner.
+ driver_.reset();
+ }
+
+ void Start(const std::string& guid) {
+ RequestParams params;
+ base::FilePath path;
+ driver()->Start(params, guid, path, TRAFFIC_ANNOTATION_FOR_TESTS);
+ }
+
+ private:
+ testing::NiceMock<MockDriverClient> driver_client_;
+ std::unique_ptr<InMemoryDownloadDriver> driver_;
+ TestInMemoryDownloadFactory* factory_;
+ DISALLOW_COPY_AND_ASSIGN(InMemoryDownloadDriverTest);
+};
+
+// Verifies in memory download success and remove API.
+TEST_F(InMemoryDownloadDriverTest, DownloadSuccessAndRemove) {
+ // General states check.
+ EXPECT_TRUE(driver()->IsReady());
+
+ const std::string guid = "1234";
+ EXPECT_CALL(*driver_client(), OnDownloadCreated(_)).Times(1);
+ Start(guid);
+
+ // After starting a download, we should be able to find a record in the
+ // driver.
+ base::Optional<DriverEntry> entry = driver()->Find(guid);
+ EXPECT_TRUE(entry.has_value());
+ EXPECT_EQ(guid, entry->guid);
+ EXPECT_EQ(DriverEntry::State::IN_PROGRESS, entry->state);
+
+ EXPECT_CALL(*driver_client(), OnDownloadUpdated(_));
+ factory()->last_created_download()->SimulateDownloadProgress();
+
+ DriverEntry match_entry;
+ match_entry.state = DriverEntry::State::COMPLETE;
+ match_entry.guid = guid;
+ EXPECT_CALL(*driver_client(),
+ OnDownloadSucceeded(DriverEntryEqual(match_entry)))
+ .Times(1);
+ EXPECT_CALL(*driver_client(), OnDownloadFailed(_, _)).Times(0);
+
+ // Trigger download complete.
+ factory()->last_created_download()->SimulateDownloadComplete(
+ true /* success*/);
+ EXPECT_TRUE(entry.has_value());
+ entry = driver()->Find(guid);
+ EXPECT_EQ(guid, entry->guid);
+ EXPECT_EQ(DriverEntry::State::COMPLETE, entry->state);
+
+ driver()->Remove(guid);
+ entry = driver()->Find(guid);
+ EXPECT_FALSE(entry.has_value());
+}
+
+// Verifies in memory download failure.
+TEST_F(InMemoryDownloadDriverTest, DownloadFailure) {
+ // General states check.
+ EXPECT_TRUE(driver()->IsReady());
+
+ EXPECT_CALL(*driver_client(), OnDownloadCreated(_)).Times(1);
+ EXPECT_CALL(*driver_client(), OnDownloadUpdated(_)).Times(0);
+
+ const std::string guid = "1234";
+ Start(guid);
+
+ DriverEntry match_entry;
+ match_entry.state = DriverEntry::State::INTERRUPTED;
+ match_entry.guid = guid;
+ EXPECT_CALL(*driver_client(),
+ OnDownloadFailed(DriverEntryEqual(match_entry), _))
+ .Times(1);
+ EXPECT_CALL(*driver_client(), OnDownloadSucceeded(_)).Times(0);
+
+ // Trigger download complete.
+ factory()->last_created_download()->SimulateDownloadComplete(
+ false /* success*/);
+ base::Optional<DriverEntry> entry = driver()->Find(guid);
+ EXPECT_TRUE(entry.has_value());
+ EXPECT_EQ(guid, entry->guid);
+ EXPECT_EQ(DriverEntry::State::INTERRUPTED, entry->state);
+}
+
+} // namespace
+} // namespace download
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
new file mode 100644
index 00000000000..145f697358c
--- /dev/null
+++ b/chromium/components/download/internal/background_service/in_memory_download_unittest.cc
@@ -0,0 +1,231 @@
+// 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/download/internal/background_service/in_memory_download.h"
+
+#include "base/files/file_util.h"
+#include "base/guid.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/url_request_test_util.h"
+#include "storage/browser/blob/blob_reader.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace download {
+namespace {
+
+// Posts a dummy task on |task_runner| and wait for its callback, to drain all
+// previous tasks on |task_runner|.
+void DrainPreviousTasks(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ base::RunLoop run_loop;
+
+ auto dummy_task = []() {};
+ task_runner->PostTaskAndReply(FROM_HERE, base::BindRepeating(dummy_task),
+ run_loop.QuitClosure());
+
+ run_loop.Run();
+}
+
+// Dummy callback used for IO_PENDING state in blob operations, this is not
+// called when the blob operation is done, but called when chained with other
+// IO operations that might return IO_PENDING.
+template <typename T>
+void SetValue(T* address, T value) {
+ *address = value;
+}
+
+class MockDelegate : public InMemoryDownload::Delegate {
+ public:
+ MockDelegate() = default;
+
+ void WaitForCompletion() {
+ DCHECK(!run_loop_.running());
+ run_loop_.Run();
+ }
+
+ // InMemoryDownload::Delegate implementation.
+ MOCK_METHOD1(OnDownloadProgress, void(InMemoryDownload*));
+ void OnDownloadComplete(InMemoryDownload* download) {
+ if (run_loop_.running())
+ run_loop_.Quit();
+ }
+
+ private:
+ base::RunLoop run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockDelegate);
+};
+
+// Must run on IO thread task runner.
+base::WeakPtr<storage::BlobStorageContext> BlobStorageContextGetter(
+ storage::BlobStorageContext* blob_context) {
+ DCHECK(blob_context);
+ return blob_context->AsWeakPtr();
+}
+
+class InMemoryDownloadTest : public testing::Test {
+ public:
+ InMemoryDownloadTest() = default;
+ ~InMemoryDownloadTest() override = default;
+
+ void SetUp() override {
+ test_server_.ServeFilesFromDirectory(GetTestDataDirectory());
+ ASSERT_TRUE(test_server_.Start());
+
+ io_thread_.reset(new base::Thread("Network and Blob IO thread"));
+ base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
+ io_thread_->StartWithOptions(options);
+ request_context_getter_ =
+ new net::TestURLRequestContextGetter(io_thread_->task_runner());
+ base::RunLoop loop;
+ io_thread_->task_runner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting([&]() {
+ blob_storage_context_ =
+ std::make_unique<storage::BlobStorageContext>();
+ loop.Quit();
+ }));
+ loop.Run();
+ }
+
+ void TearDown() override {
+ // Say goodbye to |blob_storage_context_| on IO thread.
+ io_thread_->task_runner()->DeleteSoon(FROM_HERE,
+ blob_storage_context_.release());
+ }
+
+ protected:
+ base::FilePath GetTestDataDirectory() {
+ base::FilePath test_data_dir;
+ EXPECT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir));
+ return test_data_dir.AppendASCII("components/test/data/download");
+ }
+
+ // Helper method to create a download with request_params.
+ void CreateDownload(const RequestParams& request_params) {
+ download_ = std::make_unique<InMemoryDownloadImpl>(
+ base::GenerateGUID(), request_params, TRAFFIC_ANNOTATION_FOR_TESTS,
+ delegate(), request_context_getter_,
+ base::BindRepeating(&BlobStorageContextGetter,
+ blob_storage_context_.get()),
+ io_thread_->task_runner());
+ }
+
+ InMemoryDownload* download() { return download_.get(); }
+ MockDelegate* delegate() { return &mock_delegate_; }
+ net::EmbeddedTestServer* test_server() { return &test_server_; }
+ scoped_refptr<net::TestURLRequestContextGetter> request_context_getter() {
+ return request_context_getter_;
+ }
+
+ // Verifies if data read from |blob| is identical as |expected|.
+ void VerifyBlobData(const std::string& expected,
+ storage::BlobDataHandle* blob) {
+ base::RunLoop run_loop;
+ // BlobReader needs to work on IO thread of BlobStorageContext.
+ io_thread_->task_runner()->PostTaskAndReply(
+ FROM_HERE,
+ base::BindOnce(&InMemoryDownloadTest::VerifyBlobDataOnIO,
+ base::Unretained(this), expected, blob),
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ private:
+ void VerifyBlobDataOnIO(const std::string& expected,
+ storage::BlobDataHandle* blob) {
+ DCHECK(blob);
+ int bytes_read = 0;
+ int async_bytes_read = 0;
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(expected.size()));
+
+ auto blob_reader = blob->CreateReader();
+
+ int blob_size = 0;
+ blob_reader->CalculateSize(base::BindRepeating(&SetValue<int>, &blob_size));
+ EXPECT_EQ(blob_size, 0) << "In memory blob read data synchronously.";
+ EXPECT_FALSE(blob->IsBeingBuilt())
+ << "InMemoryDownload ensures blob construction completed.";
+ storage::BlobReader::Status status = blob_reader->Read(
+ buffer.get(), expected.size(), &bytes_read,
+ base::BindRepeating(&SetValue<int>, &async_bytes_read));
+ EXPECT_EQ(storage::BlobReader::Status::DONE, status);
+ EXPECT_EQ(bytes_read, static_cast<int>(expected.size()));
+ EXPECT_EQ(async_bytes_read, 0);
+ for (size_t i = 0; i < expected.size(); i++) {
+ EXPECT_EQ(expected[i], buffer->data()[i]);
+ }
+ }
+
+ // IO thread used by network and blob IO tasks.
+ std::unique_ptr<base::Thread> io_thread_;
+
+ // Created before other objects to provide test environment.
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ std::unique_ptr<InMemoryDownloadImpl> download_;
+ MockDelegate mock_delegate_;
+
+ // Used by URLFetcher network backend.
+ scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
+
+ // Memory backed blob storage that can never page to disk.
+ std::unique_ptr<storage::BlobStorageContext> blob_storage_context_;
+
+ net::EmbeddedTestServer test_server_;
+
+ DISALLOW_COPY_AND_ASSIGN(InMemoryDownloadTest);
+};
+
+TEST_F(InMemoryDownloadTest, DownloadTest) {
+ RequestParams request_params;
+ request_params.url = test_server()->GetURL("/text_data.json");
+ CreateDownload(request_params);
+ download()->Start();
+ delegate()->WaitForCompletion();
+
+ EXPECT_EQ(InMemoryDownload::State::COMPLETE, download()->state());
+ auto blob = download()->ResultAsBlob();
+
+ std::string expected;
+ EXPECT_TRUE(ReadFileToString(
+ GetTestDataDirectory().AppendASCII("text_data.json"), &expected));
+ VerifyBlobData(expected, blob.get());
+}
+
+TEST_F(InMemoryDownloadTest, PauseResume) {
+ RequestParams request_params;
+ request_params.url = test_server()->GetURL("/text_data.json");
+ CreateDownload(request_params);
+
+ // Pause before sending request.
+ download()->Pause();
+ download()->Start();
+
+ // Force to return ERR_IO_PENDING on network thread in
+ // InMemoryDownloadImpl::ResponseWriter::Write.
+ DrainPreviousTasks(request_context_getter()->GetNetworkTaskRunner());
+
+ download()->Resume();
+ delegate()->WaitForCompletion();
+
+ EXPECT_EQ(InMemoryDownload::State::COMPLETE, download()->state());
+ auto blob = download()->ResultAsBlob();
+
+ std::string expected;
+ EXPECT_TRUE(ReadFileToString(
+ GetTestDataDirectory().AppendASCII("text_data.json"), &expected));
+ VerifyBlobData(expected, blob.get());
+}
+
+} // namespace
+
+} // namespace download
diff --git a/chromium/components/download/internal/log_sink.h b/chromium/components/download/internal/background_service/log_sink.h
index b663128747a..a773e217b1b 100644
--- a/chromium/components/download/internal/log_sink.h
+++ b/chromium/components/download/internal/background_service/log_sink.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_DOWNLOAD_INTERNAL_LOG_SINK_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_LOG_SINK_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_LOG_SINK_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_LOG_SINK_H_
-#include "components/download/internal/controller.h"
-#include "components/download/internal/startup_status.h"
-#include "components/download/public/download_params.h"
+#include "components/download/internal/background_service/controller.h"
+#include "components/download/internal/background_service/startup_status.h"
+#include "components/download/public/background_service/download_params.h"
namespace download {
@@ -41,4 +41,4 @@ class LogSink {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_LOG_SINK_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_LOG_SINK_H_
diff --git a/chromium/components/download/internal/log_source.h b/chromium/components/download/internal/background_service/log_source.h
index 546b027aa08..930cb9f28f7 100644
--- a/chromium/components/download/internal/log_source.h
+++ b/chromium/components/download/internal/background_service/log_source.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_DOWNLOAD_INTERNAL_LOG_SOURCE_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_LOG_SOURCE_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_LOG_SOURCE_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_LOG_SOURCE_H_
#include <utility>
#include <vector>
#include "base/optional.h"
-#include "components/download/internal/controller.h"
+#include "components/download/internal/background_service/controller.h"
namespace download {
@@ -42,4 +42,4 @@ class LogSource {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_LOG_SOURCE_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_LOG_SOURCE_H_
diff --git a/chromium/components/download/internal/logger_impl.cc b/chromium/components/download/internal/background_service/logger_impl.cc
index 83c9d8e5481..bd2fe130e80 100644
--- a/chromium/components/download/internal/logger_impl.cc
+++ b/chromium/components/download/internal/background_service/logger_impl.cc
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/logger_impl.h"
+#include "components/download/internal/background_service/logger_impl.h"
#include <memory>
#include "base/memory/ptr_util.h"
#include "base/values.h"
-#include "components/download/internal/driver_entry.h"
-#include "components/download/internal/entry.h"
-#include "components/download/internal/log_source.h"
-#include "components/download/public/clients.h"
-#include "components/download/public/download_params.h"
+#include "components/download/internal/background_service/driver_entry.h"
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/internal/background_service/log_source.h"
+#include "components/download/public/background_service/clients.h"
+#include "components/download/public/background_service/download_params.h"
namespace download {
namespace {
diff --git a/chromium/components/download/internal/logger_impl.h b/chromium/components/download/internal/background_service/logger_impl.h
index 5f449884b27..1da4b05aced 100644
--- a/chromium/components/download/internal/logger_impl.h
+++ b/chromium/components/download/internal/background_service/logger_impl.h
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_LOGGER_IMPL_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_LOGGER_IMPL_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_LOGGER_IMPL_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_LOGGER_IMPL_H_
#include <memory>
#include "base/macros.h"
#include "base/observer_list.h"
-#include "components/download/internal/log_sink.h"
-#include "components/download/public/download_params.h"
-#include "components/download/public/logger.h"
+#include "components/download/internal/background_service/log_sink.h"
+#include "components/download/public/background_service/download_params.h"
+#include "components/download/public/background_service/logger.h"
namespace base {
class Value;
@@ -57,4 +57,4 @@ class LoggerImpl : public Logger, public LogSink {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_LOGGER_IMPL_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_LOGGER_IMPL_H_
diff --git a/chromium/components/download/internal/memory_tracker.h b/chromium/components/download/internal/background_service/memory_tracker.h
index d7023549e7e..2e0d37ad175 100644
--- a/chromium/components/download/internal/memory_tracker.h
+++ b/chromium/components/download/internal/background_service/memory_tracker.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_INTERNAL_MEMORY_TRACKER_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_MEMORY_TRACKER_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_MEMORY_TRACKER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_MEMORY_TRACKER_H_
#include <stddef.h>
@@ -20,4 +20,4 @@ class MemoryTracker {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_MEMORY_TRACKER_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_MEMORY_TRACKER_H_
diff --git a/chromium/components/download/internal/model.h b/chromium/components/download/internal/background_service/model.h
index e7a88e7dd4a..4f48499dd5b 100644
--- a/chromium/components/download/internal/model.h
+++ b/chromium/components/download/internal/background_service/model.h
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_MODEL_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_MODEL_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_MODEL_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_MODEL_H_
#include <memory>
#include <string>
#include <vector>
-#include "components/download/internal/entry.h"
-#include "components/download/internal/memory_tracker.h"
-#include "components/download/public/clients.h"
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/internal/background_service/memory_tracker.h"
+#include "components/download/public/background_service/clients.h"
namespace download {
@@ -97,4 +97,4 @@ class Model : public MemoryTracker {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_MODEL_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_MODEL_H_
diff --git a/chromium/components/download/internal/model_impl.cc b/chromium/components/download/internal/background_service/model_impl.cc
index 2a36b259cf5..d8f8ce6c37c 100644
--- a/chromium/components/download/internal/model_impl.cc
+++ b/chromium/components/download/internal/background_service/model_impl.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/download/internal/model_impl.h"
+#include "components/download/internal/background_service/model_impl.h"
#include <map>
#include <memory>
#include "base/bind.h"
#include "base/trace_event/memory_usage_estimator.h"
-#include "components/download/internal/entry.h"
-#include "components/download/internal/stats.h"
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/internal/background_service/stats.h"
namespace download {
diff --git a/chromium/components/download/internal/model_impl.h b/chromium/components/download/internal/background_service/model_impl.h
index 12a62a431ff..8ec5f0acd0a 100644
--- a/chromium/components/download/internal/model_impl.h
+++ b/chromium/components/download/internal/background_service/model_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_DOWNLOAD_INTERNAL_MODEL_IMPL_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_MODEL_IMPL_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_MODEL_IMPL_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_MODEL_IMPL_H_
#include <map>
#include <string>
@@ -12,9 +12,9 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "components/download/internal/model.h"
-#include "components/download/internal/store.h"
-#include "components/download/public/clients.h"
+#include "components/download/internal/background_service/model.h"
+#include "components/download/internal/background_service/store.h"
+#include "components/download/public/background_service/clients.h"
namespace download {
@@ -71,4 +71,4 @@ class ModelImpl : public Model {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_MODEL_IMPL_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_MODEL_IMPL_H_
diff --git a/chromium/components/download/internal/model_impl_unittest.cc b/chromium/components/download/internal/background_service/model_impl_unittest.cc
index 3415869b6fe..63b91e24e39 100644
--- a/chromium/components/download/internal/model_impl_unittest.cc
+++ b/chromium/components/download/internal/background_service/model_impl_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/download/internal/model_impl.h"
+#include "components/download/internal/background_service/model_impl.h"
#include <algorithm>
#include <memory>
@@ -11,11 +11,11 @@
#include "base/guid.h"
#include "base/macros.h"
#include "base/test/histogram_tester.h"
-#include "components/download/internal/entry.h"
-#include "components/download/internal/stats.h"
-#include "components/download/internal/test/entry_utils.h"
-#include "components/download/internal/test/mock_model_client.h"
-#include "components/download/internal/test/test_store.h"
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/internal/background_service/stats.h"
+#include "components/download/internal/background_service/test/entry_utils.h"
+#include "components/download/internal/background_service/test/mock_model_client.h"
+#include "components/download/internal/background_service/test/test_store.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/download/internal/navigation_monitor_impl.cc b/chromium/components/download/internal/background_service/navigation_monitor_impl.cc
index ade7166425d..52cf9c82284 100644
--- a/chromium/components/download/internal/navigation_monitor_impl.cc
+++ b/chromium/components/download/internal/background_service/navigation_monitor_impl.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/download/internal/navigation_monitor_impl.h"
+#include "components/download/internal/background_service/navigation_monitor_impl.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
diff --git a/chromium/components/download/internal/navigation_monitor_impl.h b/chromium/components/download/internal/background_service/navigation_monitor_impl.h
index a70f1bef08c..a972de39493 100644
--- a/chromium/components/download/internal/navigation_monitor_impl.h
+++ b/chromium/components/download/internal/background_service/navigation_monitor_impl.h
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_NAVIGATION_MONITOR_IMPL_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_NAVIGATION_MONITOR_IMPL_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_NAVIGATION_MONITOR_IMPL_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_NAVIGATION_MONITOR_IMPL_H_
#include "base/cancelable_callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "components/download/public/navigation_monitor.h"
+#include "components/download/public/background_service/navigation_monitor.h"
namespace download {
@@ -47,4 +47,4 @@ class NavigationMonitorImpl : public NavigationMonitor {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_NAVIGATION_MONITOR_IMPL_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_NAVIGATION_MONITOR_IMPL_H_
diff --git a/chromium/components/download/internal/navigation_monitor_impl_unittests.cc b/chromium/components/download/internal/background_service/navigation_monitor_impl_unittests.cc
index f007f5ca817..dbd8ff6f089 100644
--- a/chromium/components/download/internal/navigation_monitor_impl_unittests.cc
+++ b/chromium/components/download/internal/background_service/navigation_monitor_impl_unittests.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/download/internal/navigation_monitor_impl.h"
+#include "components/download/internal/background_service/navigation_monitor_impl.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
diff --git a/chromium/components/download/internal/background_service/noop_store.cc b/chromium/components/download/internal/background_service/noop_store.cc
new file mode 100644
index 00000000000..7eeab1d60b0
--- /dev/null
+++ b/chromium/components/download/internal/background_service/noop_store.cc
@@ -0,0 +1,56 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/internal/background_service/noop_store.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/download/internal/background_service/entry.h"
+
+namespace download {
+
+NoopStore::NoopStore() : initialized_(false), weak_ptr_factory_(this) {}
+
+NoopStore::~NoopStore() = default;
+
+bool NoopStore::IsInitialized() {
+ return initialized_;
+}
+
+void NoopStore::Initialize(InitCallback callback) {
+ DCHECK(!IsInitialized());
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&NoopStore::OnInitFinished, weak_ptr_factory_.GetWeakPtr(),
+ std::move(callback)));
+}
+
+void NoopStore::HardRecover(StoreCallback callback) {
+ initialized_ = true;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), true));
+}
+
+void NoopStore::Update(const Entry& entry, StoreCallback callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), true /** success */));
+}
+
+void NoopStore::Remove(const std::string& guid, StoreCallback callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), true /** success */));
+}
+
+void NoopStore::OnInitFinished(InitCallback callback) {
+ initialized_ = true;
+
+ std::unique_ptr<std::vector<Entry>> entries =
+ std::make_unique<std::vector<Entry>>();
+ std::move(callback).Run(true /** success */, std::move(entries));
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/background_service/noop_store.h b/chromium/components/download/internal/background_service/noop_store.h
new file mode 100644
index 00000000000..643dfc119f1
--- /dev/null
+++ b/chromium/components/download/internal/background_service/noop_store.h
@@ -0,0 +1,44 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_NOOP_STORE_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_NOOP_STORE_H_
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/download/internal/background_service/store.h"
+
+namespace download {
+
+struct Entry;
+
+// A Store implementation that doesn't do anything but honors the interface
+// requirements. Used in incognito mode without any database IO.
+class NoopStore : public Store {
+ public:
+ NoopStore();
+ ~NoopStore() override;
+
+ // Store implementation.
+ bool IsInitialized() override;
+ void Initialize(InitCallback callback) override;
+ void HardRecover(StoreCallback callback) override;
+ void Update(const Entry& entry, StoreCallback callback) override;
+ void Remove(const std::string& guid, StoreCallback callback) override;
+
+ private:
+ void OnInitFinished(InitCallback callback);
+
+ // Whether or not this Store is 'initialized.' Just gets set to |true| once
+ // Initialize() is called.
+ bool initialized_;
+
+ base::WeakPtrFactory<NoopStore> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(NoopStore);
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_NOOP_STORE_H_
diff --git a/chromium/components/download/internal/proto/BUILD.gn b/chromium/components/download/internal/background_service/proto/BUILD.gn
index 9d6c33e751f..1a5ab7249d0 100644
--- a/chromium/components/download/internal/proto/BUILD.gn
+++ b/chromium/components/download/internal/background_service/proto/BUILD.gn
@@ -7,7 +7,7 @@ import("//third_party/protobuf/proto_library.gni")
proto_library("proto") {
visibility = [
"//components/download/content/factory",
- "//components/download/internal:*",
+ "//components/download/internal/background_service/:*",
]
sources = [
diff --git a/chromium/components/download/internal/proto/entry.proto b/chromium/components/download/internal/background_service/proto/entry.proto
index 528795a0f37..2e7cfbbb28d 100644
--- a/chromium/components/download/internal/proto/entry.proto
+++ b/chromium/components/download/internal/background_service/proto/entry.proto
@@ -12,7 +12,7 @@ import "request.proto";
import "scheduling.proto";
// This should stay in sync with the DownloadClient enum
-// (components/download/public/clients.h).
+// (components/download/public/background_service/clients.h).
enum DownloadClient {
INVALID = 0;
TEST = 1;
@@ -28,7 +28,7 @@ enum DownloadClient {
// with a download request.
message Entry {
// This should stay in sync with the State enum
- // (components/download/internal/entry.h).
+ // (components/download/internal/background_service/entry.h).
enum State {
NEW = 0;
AVAILABLE = 1;
diff --git a/chromium/components/download/internal/proto/request.proto b/chromium/components/download/internal/background_service/proto/request.proto
index ae2b7bed13d..ae2b7bed13d 100644
--- a/chromium/components/download/internal/proto/request.proto
+++ b/chromium/components/download/internal/background_service/proto/request.proto
diff --git a/chromium/components/download/internal/proto/scheduling.proto b/chromium/components/download/internal/background_service/proto/scheduling.proto
index ef6a0ca497a..052a458d0fb 100644
--- a/chromium/components/download/internal/proto/scheduling.proto
+++ b/chromium/components/download/internal/background_service/proto/scheduling.proto
@@ -11,7 +11,7 @@ package protodb;
// Stores the scheduling params associated with a download request.
message SchedulingParams {
// This should stay in sync with the NetworkRequirements enum
- // (components/download/public/download_params.h).
+ // (components/download/public/background_service/download_params.h).
enum NetworkRequirements {
NONE = 0;
OPTIMISTIC = 1;
@@ -19,7 +19,7 @@ message SchedulingParams {
}
// This should stay in sync with the BatteryRequirements enum
- // (components/download/public/download_params.h).
+ // (components/download/public/background_service/download_params.h).
enum BatteryRequirements {
BATTERY_INSENSITIVE = 0;
BATTERY_SENSITIVE = 1;
@@ -27,7 +27,7 @@ message SchedulingParams {
}
// This should stay in sync with the Priority enum
- // (components/download/public/download_params.h).
+ // (components/download/public/background_service/download_params.h).
enum Priority {
LOW = 0;
NORMAL = 1;
diff --git a/chromium/components/download/internal/proto_conversions.cc b/chromium/components/download/internal/background_service/proto_conversions.cc
index 30974748edc..ef1398eb058 100644
--- a/chromium/components/download/internal/proto_conversions.cc
+++ b/chromium/components/download/internal/background_service/proto_conversions.cc
@@ -6,7 +6,7 @@
#include <utility>
#include "base/time/time.h"
-#include "components/download/internal/proto_conversions.h"
+#include "components/download/internal/background_service/proto_conversions.h"
#include "net/http/http_request_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
diff --git a/chromium/components/download/internal/proto_conversions.h b/chromium/components/download/internal/background_service/proto_conversions.h
index 4d2e4e53661..6eab96b41c6 100644
--- a/chromium/components/download/internal/proto_conversions.h
+++ b/chromium/components/download/internal/background_service/proto_conversions.h
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_PROTO_CONVERSIONS_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_PROTO_CONVERSIONS_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_PROTO_CONVERSIONS_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_PROTO_CONVERSIONS_H_
-#include "components/download/internal/entry.h"
-#include "components/download/internal/proto/entry.pb.h"
-#include "components/download/internal/proto/request.pb.h"
-#include "components/download/internal/proto/scheduling.pb.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/request.pb.h"
+#include "components/download/internal/background_service/proto/scheduling.pb.h"
namespace download {
@@ -61,4 +61,4 @@ class ProtoConversions {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_PROTO_CONVERSIONS_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_PROTO_CONVERSIONS_H_
diff --git a/chromium/components/download/internal/proto_conversions_unittest.cc b/chromium/components/download/internal/background_service/proto_conversions_unittest.cc
index de3c6c31624..46e9bdc5c92 100644
--- a/chromium/components/download/internal/proto_conversions_unittest.cc
+++ b/chromium/components/download/internal/background_service/proto_conversions_unittest.cc
@@ -6,9 +6,9 @@
#include <utility>
#include "base/guid.h"
-#include "components/download/internal/entry.h"
-#include "components/download/internal/proto_conversions.h"
-#include "components/download/internal/test/entry_utils.h"
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/internal/background_service/proto_conversions.h"
+#include "components/download/internal/background_service/test/entry_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
diff --git a/chromium/components/download/internal/scheduler/device_status.cc b/chromium/components/download/internal/background_service/scheduler/device_status.cc
index 7f3c69f0064..75cf548343d 100644
--- a/chromium/components/download/internal/scheduler/device_status.cc
+++ b/chromium/components/download/internal/background_service/scheduler/device_status.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/download/internal/scheduler/device_status.h"
+#include "components/download/internal/background_service/scheduler/device_status.h"
namespace download {
diff --git a/chromium/components/download/internal/scheduler/device_status.h b/chromium/components/download/internal/background_service/scheduler/device_status.h
index 2397a0cee7d..8d5b3644312 100644
--- a/chromium/components/download/internal/scheduler/device_status.h
+++ b/chromium/components/download/internal/background_service/scheduler/device_status.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_DEVICE_STATUS_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_DEVICE_STATUS_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_DEVICE_STATUS_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_DEVICE_STATUS_H_
-#include "components/download/public/download_params.h"
+#include "components/download/public/background_service/download_params.h"
namespace download {
@@ -72,4 +72,4 @@ struct Criteria {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_DEVICE_STATUS_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_DEVICE_STATUS_H_
diff --git a/chromium/components/download/internal/scheduler/device_status_listener.cc b/chromium/components/download/internal/background_service/scheduler/device_status_listener.cc
index bc40f1b4def..b277fd01a58 100644
--- a/chromium/components/download/internal/scheduler/device_status_listener.cc
+++ b/chromium/components/download/internal/background_service/scheduler/device_status_listener.cc
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/scheduler/device_status_listener.h"
+#include "components/download/internal/background_service/scheduler/device_status_listener.h"
#include "base/power_monitor/power_monitor.h"
#include "build/build_config.h"
-#include "components/download/internal/scheduler/network_status_listener.h"
+#include "components/download/internal/background_service/scheduler/network_status_listener.h"
#if defined(OS_ANDROID)
-#include "components/download/internal/android/network_status_listener_android.h"
+#include "components/download/internal/background_service/android/network_status_listener_android.h"
#endif
namespace download {
diff --git a/chromium/components/download/internal/scheduler/device_status_listener.h b/chromium/components/download/internal/background_service/scheduler/device_status_listener.h
index 29ab639a4a3..715f2e31c1c 100644
--- a/chromium/components/download/internal/scheduler/device_status_listener.h
+++ b/chromium/components/download/internal/background_service/scheduler/device_status_listener.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_DOWNLOAD_INTERNAL_SCHEDULER_DEVICE_STATUS_LISTENER_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_DEVICE_STATUS_LISTENER_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_DEVICE_STATUS_LISTENER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_DEVICE_STATUS_LISTENER_H_
#include <memory>
#include "base/power_monitor/power_observer.h"
#include "base/timer/timer.h"
-#include "components/download/internal/scheduler/device_status.h"
-#include "components/download/internal/scheduler/network_status_listener.h"
+#include "components/download/internal/background_service/scheduler/device_status.h"
+#include "components/download/internal/background_service/scheduler/network_status_listener.h"
#include "net/base/network_change_notifier.h"
namespace download {
@@ -145,4 +145,4 @@ class DeviceStatusListener : public NetworkStatusListener::Observer,
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_DEVICE_STATUS_LISTENER_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_DEVICE_STATUS_LISTENER_H_
diff --git a/chromium/components/download/internal/scheduler/device_status_listener_unittest.cc b/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
index e0b6ce875c5..18ab129af56 100644
--- a/chromium/components/download/internal/scheduler/device_status_listener_unittest.cc
+++ b/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/scheduler/device_status_listener.h"
+#include "components/download/internal/background_service/scheduler/device_status_listener.h"
#include <memory>
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/test/power_monitor_test_base.h"
-#include "components/download/internal/scheduler/network_status_listener.h"
+#include "components/download/internal/background_service/scheduler/network_status_listener.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/download/internal/scheduler/network_status_listener.cc b/chromium/components/download/internal/background_service/scheduler/network_status_listener.cc
index c5e406aa9d1..fd3389cac7b 100644
--- a/chromium/components/download/internal/scheduler/network_status_listener.cc
+++ b/chromium/components/download/internal/background_service/scheduler/network_status_listener.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/download/internal/scheduler/network_status_listener.h"
+#include "components/download/internal/background_service/scheduler/network_status_listener.h"
namespace download {
diff --git a/chromium/components/download/internal/scheduler/network_status_listener.h b/chromium/components/download/internal/background_service/scheduler/network_status_listener.h
index e769c800d9c..4e68380eb8a 100644
--- a/chromium/components/download/internal/scheduler/network_status_listener.h
+++ b/chromium/components/download/internal/background_service/scheduler/network_status_listener.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_INTERNAL_SCHEDULER_NETWORK_STATUS_LISTENER_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_NETWORK_STATUS_LISTENER_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_NETWORK_STATUS_LISTENER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_NETWORK_STATUS_LISTENER_H_
#include "net/base/network_change_notifier.h"
@@ -74,4 +74,4 @@ class NetworkStatusListenerImpl
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_NETWORK_STATUS_LISTENER_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_NETWORK_STATUS_LISTENER_H_
diff --git a/chromium/components/download/internal/scheduler/scheduler.h b/chromium/components/download/internal/background_service/scheduler/scheduler.h
index 58d835a3ab3..5a0ab275745 100644
--- a/chromium/components/download/internal/scheduler/scheduler.h
+++ b/chromium/components/download/internal/background_service/scheduler/scheduler.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_DOWNLOAD_INTERNAL_SCHEDULER_SCHEDULER_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_SCHEDULER_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_SCHEDULER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_SCHEDULER_H_
-#include "components/download/internal/model.h"
-#include "components/download/internal/scheduler/device_status.h"
-#include "components/download/public/download_params.h"
+#include "components/download/internal/background_service/model.h"
+#include "components/download/internal/background_service/scheduler/device_status.h"
+#include "components/download/public/background_service/download_params.h"
namespace download {
@@ -33,4 +33,4 @@ class Scheduler {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_CORE_SCHEDULER_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_SCHEDULER_H_
diff --git a/chromium/components/download/internal/scheduler/scheduler_impl.cc b/chromium/components/download/internal/background_service/scheduler/scheduler_impl.cc
index 4f827281862..a47fe63891b 100644
--- a/chromium/components/download/internal/scheduler/scheduler_impl.cc
+++ b/chromium/components/download/internal/background_service/scheduler/scheduler_impl.cc
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/scheduler/scheduler_impl.h"
-
-#include "components/download/internal/client_set.h"
-#include "components/download/internal/config.h"
-#include "components/download/internal/entry_utils.h"
-#include "components/download/internal/scheduler/device_status.h"
-#include "components/download/public/download_params.h"
-#include "components/download/public/task_scheduler.h"
+#include "components/download/internal/background_service/scheduler/scheduler_impl.h"
+
+#include "components/download/internal/background_service/client_set.h"
+#include "components/download/internal/background_service/config.h"
+#include "components/download/internal/background_service/entry_utils.h"
+#include "components/download/internal/background_service/scheduler/device_status.h"
+#include "components/download/public/background_service/download_params.h"
+#include "components/download/public/background_service/task_scheduler.h"
namespace download {
diff --git a/chromium/components/download/internal/scheduler/scheduler_impl.h b/chromium/components/download/internal/background_service/scheduler/scheduler_impl.h
index 1284d38fe0b..2d53b33ce90 100644
--- a/chromium/components/download/internal/scheduler/scheduler_impl.h
+++ b/chromium/components/download/internal/background_service/scheduler/scheduler_impl.h
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_SCHEDULER_IMPL_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_SCHEDULER_IMPL_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_SCHEDULER_IMPL_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_SCHEDULER_IMPL_H_
-#include "components/download/internal/scheduler/scheduler.h"
+#include "components/download/internal/background_service/scheduler/scheduler.h"
#include <map>
#include <vector>
#include "base/macros.h"
-#include "components/download/internal/entry.h"
+#include "components/download/internal/background_service/entry.h"
namespace download {
@@ -69,4 +69,4 @@ class SchedulerImpl : public Scheduler {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_SCHEDULER_IMPL_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_SCHEDULER_IMPL_H_
diff --git a/chromium/components/download/internal/scheduler/scheduler_impl_unittest.cc b/chromium/components/download/internal/background_service/scheduler/scheduler_impl_unittest.cc
index e564412e02b..d39cfc36551 100644
--- a/chromium/components/download/internal/scheduler/scheduler_impl_unittest.cc
+++ b/chromium/components/download/internal/background_service/scheduler/scheduler_impl_unittest.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/download/internal/scheduler/scheduler_impl.h"
+#include "components/download/internal/background_service/scheduler/scheduler_impl.h"
#include <memory>
#include "base/strings/string_number_conversions.h"
-#include "components/download/internal/config.h"
-#include "components/download/internal/entry.h"
-#include "components/download/internal/scheduler/device_status.h"
-#include "components/download/public/task_scheduler.h"
+#include "components/download/internal/background_service/config.h"
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/internal/background_service/scheduler/device_status.h"
+#include "components/download/public/background_service/task_scheduler.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/download/internal/service_config_impl.cc b/chromium/components/download/internal/background_service/service_config_impl.cc
index 36775bee798..8654ba2da38 100644
--- a/chromium/components/download/internal/service_config_impl.cc
+++ b/chromium/components/download/internal/background_service/service_config_impl.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/service_config_impl.h"
+#include "components/download/internal/background_service/service_config_impl.h"
#include "base/time/time.h"
-#include "components/download/internal/config.h"
+#include "components/download/internal/background_service/config.h"
namespace download {
diff --git a/chromium/components/download/internal/service_config_impl.h b/chromium/components/download/internal/background_service/service_config_impl.h
index a61b3eca270..0444791f1ad 100644
--- a/chromium/components/download/internal/service_config_impl.h
+++ b/chromium/components/download/internal/background_service/service_config_impl.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_INTERNAL_SERVICE_CONFIG_IMPL_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_SERVICE_CONFIG_IMPL_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SERVICE_CONFIG_IMPL_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SERVICE_CONFIG_IMPL_H_
#include "base/macros.h"
-#include "components/download/public/service_config.h"
+#include "components/download/public/background_service/service_config.h"
namespace download {
@@ -30,4 +30,4 @@ class ServiceConfigImpl : public ServiceConfig {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_SERVICE_CONFIG_IMPL_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SERVICE_CONFIG_IMPL_H_
diff --git a/chromium/components/download/internal/service_config_impl_unittest.cc b/chromium/components/download/internal/background_service/service_config_impl_unittest.cc
index 9b14c79a057..b3106669b1f 100644
--- a/chromium/components/download/internal/service_config_impl_unittest.cc
+++ b/chromium/components/download/internal/background_service/service_config_impl_unittest.cc
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/internal/service_config_impl.h"
-#include "components/download/internal/config.h"
+#include "components/download/internal/background_service/service_config_impl.h"
+#include "components/download/internal/background_service/config.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace download {
diff --git a/chromium/components/download/internal/startup_status.cc b/chromium/components/download/internal/background_service/startup_status.cc
index 393e289a6a3..a82c0223392 100644
--- a/chromium/components/download/internal/startup_status.cc
+++ b/chromium/components/download/internal/background_service/startup_status.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/download/internal/startup_status.h"
+#include "components/download/internal/background_service/startup_status.h"
namespace download {
diff --git a/chromium/components/download/internal/startup_status.h b/chromium/components/download/internal/background_service/startup_status.h
index 754428afad9..f9814535280 100644
--- a/chromium/components/download/internal/startup_status.h
+++ b/chromium/components/download/internal/background_service/startup_status.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_STARTUP_STATUS_H_
-#define COMPONENTS_DOWNLOAD_STARTUP_STATUS_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_STARTUP_STATUS_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_STARTUP_STATUS_H_
#include "base/macros.h"
#include "base/optional.h"
@@ -37,4 +37,4 @@ struct StartupStatus {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_STARTUP_STATUS_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_STARTUP_STATUS_H_
diff --git a/chromium/components/download/internal/stats.cc b/chromium/components/download/internal/background_service/stats.cc
index c32ad80ee28..720a87f57e8 100644
--- a/chromium/components/download/internal/stats.cc
+++ b/chromium/components/download/internal/background_service/stats.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/download/internal/stats.h"
+#include "components/download/internal/background_service/stats.h"
#include <map>
@@ -10,7 +10,7 @@
#include "base/files/file_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
-#include "components/download/internal/startup_status.h"
+#include "components/download/internal/background_service/startup_status.h"
namespace download {
namespace stats {
@@ -241,8 +241,7 @@ void LogRecoveryOperation(Entry::State to_state) {
Entry::State::COUNT);
}
-void LogDownloadCompletion(CompletionType type,
- uint64_t file_size_bytes) {
+void LogDownloadCompletion(CompletionType type, uint64_t file_size_bytes) {
// Records completion type.
UMA_HISTOGRAM_ENUMERATION("Download.Service.Finish.Type", type,
CompletionType::COUNT);
diff --git a/chromium/components/download/internal/stats.h b/chromium/components/download/internal/background_service/stats.h
index e68ecdde1c0..ab9d2b530f7 100644
--- a/chromium/components/download/internal/stats.h
+++ b/chromium/components/download/internal/background_service/stats.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_DOWNLOAD_INTERNAL_STATS_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_STATS_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_STATS_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_STATS_H_
#include "base/files/file.h"
#include "base/optional.h"
-#include "components/download/internal/controller.h"
-#include "components/download/internal/driver_entry.h"
-#include "components/download/internal/entry.h"
-#include "components/download/public/clients.h"
-#include "components/download/public/download_params.h"
-#include "components/download/public/download_task_types.h"
+#include "components/download/internal/background_service/controller.h"
+#include "components/download/internal/background_service/driver_entry.h"
+#include "components/download/internal/background_service/entry.h"
+#include "components/download/public/background_service/clients.h"
+#include "components/download/public/background_service/download_params.h"
+#include "components/download/public/background_service/download_task_types.h"
namespace download {
@@ -170,8 +170,7 @@ void LogDownloadParams(const DownloadParams& params);
void LogRecoveryOperation(Entry::State to_state);
// Logs download completion event, download time, and the file size.
-void LogDownloadCompletion(CompletionType type,
- uint64_t file_size_bytes);
+void LogDownloadCompletion(CompletionType type, uint64_t file_size_bytes);
// Logs various pause reasons for download. The reasons are not mutually
// exclusive.
@@ -228,4 +227,4 @@ void LogEntryRetryCount(uint32_t retry_count);
} // namespace stats
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_STATS_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_STATS_H_
diff --git a/chromium/components/download/internal/store.h b/chromium/components/download/internal/background_service/store.h
index 1d1e5686687..c810af38a1e 100644
--- a/chromium/components/download/internal/store.h
+++ b/chromium/components/download/internal/background_service/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_DOWNLOAD_INTERNAL_STORE_H_
-#define COMPONENTS_DOWNLOAD_INTERNAL_STORE_H_
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_STORE_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_STORE_H_
#include <memory>
#include <string>
@@ -48,4 +48,4 @@ class Store {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_INTERNAL_STORE_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_STORE_H_
diff --git a/chromium/components/download/internal/test/BUILD.gn b/chromium/components/download/internal/background_service/test/BUILD.gn
index 3d3648a56bb..6dc81dd7605 100644
--- a/chromium/components/download/internal/test/BUILD.gn
+++ b/chromium/components/download/internal/background_service/test/BUILD.gn
@@ -4,7 +4,10 @@
# Test target for download internal tests to depend on.
source_set("test_support") {
- visibility = [ "//components/download/internal:unit_tests" ]
+ visibility = [
+ "//components/download/content/internal:unit_tests",
+ "//components/download/internal/background_service:unit_tests",
+ ]
testonly = true
@@ -17,12 +20,12 @@ source_set("test_support") {
"entry_utils.h",
"mock_controller.cc",
"mock_controller.h",
+ "mock_download_driver_client.cc",
+ "mock_download_driver_client.h",
"mock_log_sink.cc",
"mock_log_sink.h",
"mock_model_client.cc",
"mock_model_client.h",
- "noop_store.cc",
- "noop_store.h",
"test_device_status_listener.cc",
"test_device_status_listener.h",
"test_download_driver.cc",
@@ -33,12 +36,12 @@ source_set("test_support") {
public_deps = [
"//base",
- "//components/download/public",
+ "//components/download/public/background_service:public",
"//net:test_support",
"//testing/gmock",
]
deps = [
- "//components/download/internal",
+ "//components/download/internal/background_service:internal",
]
}
diff --git a/chromium/components/download/internal/common/BUILD.gn b/chromium/components/download/internal/common/BUILD.gn
new file mode 100644
index 00000000000..98de310f8c9
--- /dev/null
+++ b/chromium/components/download/internal/common/BUILD.gn
@@ -0,0 +1,46 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("internal") {
+ visibility = [ "//components/download/public/common:public" ]
+
+ configs += [
+ "//components/download/public/common:components_download_implementation",
+ ]
+
+ sources = [
+ "download_create_info.cc",
+ "download_interrupt_reasons_impl.cc",
+ "download_stats.cc",
+ "download_task_runner.cc",
+ "download_ukm_helper.cc",
+ "download_utils.cc",
+ "rate_estimator.cc",
+ ]
+
+ deps = [
+ "//base",
+ "//net",
+ "//services/metrics/public/cpp:ukm_builders",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+
+ sources = [
+ "download_stats_unittest.cc",
+ "download_ukm_helper_unittest.cc",
+ "rate_estimator_unittest.cc",
+ ]
+
+ deps = [
+ "//base/test:test_support",
+ "//components/download/public/common:public",
+ "//components/ukm:test_support",
+ "//services/metrics/public/cpp:ukm_builders",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/download/internal/common/DEPS b/chromium/components/download/internal/common/DEPS
new file mode 100644
index 00000000000..1a9dc4abaa7
--- /dev/null
+++ b/chromium/components/download/internal/common/DEPS
@@ -0,0 +1,9 @@
+include_rules = [
+ "-content",
+ "+components/download/public/common",
+ "+components/ukm/test_ukm_recorder.h",
+ "+net/http/http_content_disposition.h",
+ "+net/http/http_response_headers.h",
+ "+net/http/http_util.h",
+ "+services/metrics/public/cpp",
+]
diff --git a/chromium/components/download/internal/common/download_create_info.cc b/chromium/components/download/internal/common/download_create_info.cc
new file mode 100644
index 00000000000..eb4a1ca9d16
--- /dev/null
+++ b/chromium/components/download/internal/common/download_create_info.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/download_create_info.h"
+
+#include <string>
+
+#include "base/format_macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/stringprintf.h"
+#include "net/http/http_response_headers.h"
+
+namespace download {
+
+DownloadCreateInfo::DownloadCreateInfo(
+ const base::Time& start_time,
+ std::unique_ptr<DownloadSaveInfo> save_info)
+ : download_id(DownloadItem::kInvalidId),
+ start_time(start_time),
+ total_bytes(0),
+ offset(0),
+ has_user_gesture(false),
+ transient(false),
+ result(DOWNLOAD_INTERRUPT_REASON_NONE),
+ save_info(std::move(save_info)),
+ render_process_id(-1),
+ render_frame_id(-1),
+ accept_range(false),
+ connection_info(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN),
+ method("GET"),
+ ukm_source_id(ukm::kInvalidSourceId) {}
+
+DownloadCreateInfo::DownloadCreateInfo()
+ : DownloadCreateInfo(base::Time(), base::WrapUnique(new DownloadSaveInfo)) {
+}
+
+DownloadCreateInfo::~DownloadCreateInfo() {}
+
+const GURL& DownloadCreateInfo::url() const {
+ return url_chain.empty() ? GURL::EmptyGURL() : url_chain.back();
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/common/download_interrupt_reasons_impl.cc b/chromium/components/download/internal/common/download_interrupt_reasons_impl.cc
new file mode 100644
index 00000000000..669f324d48b
--- /dev/null
+++ b/chromium/components/download/internal/common/download_interrupt_reasons_impl.cc
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/download_interrupt_reasons.h"
+
+namespace download {
+
+std::string DownloadInterruptReasonToString(DownloadInterruptReason error) {
+#define INTERRUPT_REASON(name, value) \
+ case DOWNLOAD_INTERRUPT_REASON_##name: \
+ return #name;
+
+ switch (error) {
+ INTERRUPT_REASON(NONE, 0)
+
+#include "components/download/public/common/download_interrupt_reason_values.h"
+
+ default:
+ break;
+ }
+
+#undef INTERRUPT_REASON
+
+ return "Unknown error";
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/common/download_stats.cc b/chromium/components/download/internal/common/download_stats.cc
new file mode 100644
index 00000000000..5627b0b6057
--- /dev/null
+++ b/chromium/components/download/internal/common/download_stats.cc
@@ -0,0 +1,1065 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common//download_stats.h"
+
+#include <map>
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_util.h"
+#include "components/download/public/common/download_interrupt_reasons.h"
+#include "net/http/http_content_disposition.h"
+#include "net/http/http_util.h"
+
+namespace download {
+
+namespace {
+
+// All possible error codes from the network module. Note that the error codes
+// are all positive (since histograms expect positive sample values).
+const int kAllInterruptReasonCodes[] = {
+#define INTERRUPT_REASON(label, value) (value),
+#include "components/download/public/common/download_interrupt_reason_values.h"
+#undef INTERRUPT_REASON
+};
+
+// These values are based on net::HttpContentDisposition::ParseResult values.
+// Values other than HEADER_PRESENT and IS_VALID are only measured if |IS_VALID|
+// is true.
+enum ContentDispositionCountTypes {
+ // Count of downloads which had a Content-Disposition headers. The total
+ // number of downloads is measured by UNTHROTTLED_COUNT.
+ CONTENT_DISPOSITION_HEADER_PRESENT = 0,
+
+ // Either 'filename' or 'filename*' attributes were valid and
+ // yielded a non-empty filename.
+ CONTENT_DISPOSITION_IS_VALID,
+
+ // The following enum values correspond to
+ // net::HttpContentDisposition::ParseResult.
+ CONTENT_DISPOSITION_HAS_DISPOSITION_TYPE,
+ CONTENT_DISPOSITION_HAS_UNKNOWN_TYPE,
+
+ CONTENT_DISPOSITION_HAS_NAME, // Obsolete; kept for UMA compatiblity.
+
+ CONTENT_DISPOSITION_HAS_FILENAME,
+ CONTENT_DISPOSITION_HAS_EXT_FILENAME,
+ CONTENT_DISPOSITION_HAS_NON_ASCII_STRINGS,
+ CONTENT_DISPOSITION_HAS_PERCENT_ENCODED_STRINGS,
+ CONTENT_DISPOSITION_HAS_RFC2047_ENCODED_STRINGS,
+
+ CONTENT_DISPOSITION_HAS_NAME_ONLY, // Obsolete; kept for UMA compatiblity.
+
+ CONTENT_DISPOSITION_LAST_ENTRY
+};
+
+void RecordContentDispositionCount(ContentDispositionCountTypes type,
+ bool record) {
+ if (!record)
+ return;
+ UMA_HISTOGRAM_ENUMERATION("Download.ContentDisposition", type,
+ CONTENT_DISPOSITION_LAST_ENTRY);
+}
+
+void RecordContentDispositionCountFlag(
+ ContentDispositionCountTypes type,
+ int flags_to_test,
+ net::HttpContentDisposition::ParseResultFlags flag) {
+ RecordContentDispositionCount(type, (flags_to_test & flag) == flag);
+}
+
+// Do not insert, delete, or reorder; this is being histogrammed. Append only.
+// All of the download_file_types.asciipb entries should be in this list.
+// TODO(asanka): Replace this enum with calls to FileTypePolicies and move the
+// UMA metrics for dangerous/malicious downloads to //chrome/browser/download.
+constexpr const base::FilePath::CharType* kDangerousFileTypes[] = {
+ FILE_PATH_LITERAL(".ad"), FILE_PATH_LITERAL(".ade"),
+ FILE_PATH_LITERAL(".adp"), FILE_PATH_LITERAL(".ah"),
+ FILE_PATH_LITERAL(".apk"), FILE_PATH_LITERAL(".app"),
+ FILE_PATH_LITERAL(".application"), FILE_PATH_LITERAL(".asp"),
+ FILE_PATH_LITERAL(".asx"), FILE_PATH_LITERAL(".bas"),
+ FILE_PATH_LITERAL(".bash"), FILE_PATH_LITERAL(".bat"),
+ FILE_PATH_LITERAL(".cfg"), FILE_PATH_LITERAL(".chi"),
+ FILE_PATH_LITERAL(".chm"), FILE_PATH_LITERAL(".class"),
+ FILE_PATH_LITERAL(".cmd"), FILE_PATH_LITERAL(".com"),
+ FILE_PATH_LITERAL(".command"), FILE_PATH_LITERAL(".crt"),
+ FILE_PATH_LITERAL(".crx"), FILE_PATH_LITERAL(".csh"),
+ FILE_PATH_LITERAL(".deb"), FILE_PATH_LITERAL(".dex"),
+ FILE_PATH_LITERAL(".dll"), FILE_PATH_LITERAL(".drv"),
+ FILE_PATH_LITERAL(".exe"), FILE_PATH_LITERAL(".fxp"),
+ FILE_PATH_LITERAL(".grp"), FILE_PATH_LITERAL(".hlp"),
+ FILE_PATH_LITERAL(".hta"), FILE_PATH_LITERAL(".htm"),
+ FILE_PATH_LITERAL(".html"), FILE_PATH_LITERAL(".htt"),
+ FILE_PATH_LITERAL(".inf"), FILE_PATH_LITERAL(".ini"),
+ FILE_PATH_LITERAL(".ins"), FILE_PATH_LITERAL(".isp"),
+ FILE_PATH_LITERAL(".jar"), FILE_PATH_LITERAL(".jnlp"),
+ FILE_PATH_LITERAL(".user.js"), FILE_PATH_LITERAL(".js"),
+ FILE_PATH_LITERAL(".jse"), FILE_PATH_LITERAL(".ksh"),
+ FILE_PATH_LITERAL(".lnk"), FILE_PATH_LITERAL(".local"),
+ FILE_PATH_LITERAL(".mad"), FILE_PATH_LITERAL(".maf"),
+ FILE_PATH_LITERAL(".mag"), FILE_PATH_LITERAL(".mam"),
+ FILE_PATH_LITERAL(".manifest"), FILE_PATH_LITERAL(".maq"),
+ FILE_PATH_LITERAL(".mar"), FILE_PATH_LITERAL(".mas"),
+ FILE_PATH_LITERAL(".mat"), FILE_PATH_LITERAL(".mau"),
+ FILE_PATH_LITERAL(".mav"), FILE_PATH_LITERAL(".maw"),
+ FILE_PATH_LITERAL(".mda"), FILE_PATH_LITERAL(".mdb"),
+ FILE_PATH_LITERAL(".mde"), FILE_PATH_LITERAL(".mdt"),
+ FILE_PATH_LITERAL(".mdw"), FILE_PATH_LITERAL(".mdz"),
+ FILE_PATH_LITERAL(".mht"), FILE_PATH_LITERAL(".mhtml"),
+ FILE_PATH_LITERAL(".mmc"), FILE_PATH_LITERAL(".mof"),
+ FILE_PATH_LITERAL(".msc"), FILE_PATH_LITERAL(".msh"),
+ FILE_PATH_LITERAL(".mshxml"), FILE_PATH_LITERAL(".msi"),
+ FILE_PATH_LITERAL(".msp"), FILE_PATH_LITERAL(".mst"),
+ FILE_PATH_LITERAL(".ocx"), FILE_PATH_LITERAL(".ops"),
+ FILE_PATH_LITERAL(".pcd"), FILE_PATH_LITERAL(".pif"),
+ FILE_PATH_LITERAL(".pkg"), FILE_PATH_LITERAL(".pl"),
+ FILE_PATH_LITERAL(".plg"), FILE_PATH_LITERAL(".prf"),
+ FILE_PATH_LITERAL(".prg"), FILE_PATH_LITERAL(".pst"),
+ FILE_PATH_LITERAL(".py"), FILE_PATH_LITERAL(".pyc"),
+ FILE_PATH_LITERAL(".pyw"), FILE_PATH_LITERAL(".rb"),
+ FILE_PATH_LITERAL(".reg"), FILE_PATH_LITERAL(".rpm"),
+ FILE_PATH_LITERAL(".scf"), FILE_PATH_LITERAL(".scr"),
+ FILE_PATH_LITERAL(".sct"), FILE_PATH_LITERAL(".sh"),
+ FILE_PATH_LITERAL(".shar"), FILE_PATH_LITERAL(".shb"),
+ FILE_PATH_LITERAL(".shs"), FILE_PATH_LITERAL(".shtm"),
+ FILE_PATH_LITERAL(".shtml"), FILE_PATH_LITERAL(".spl"),
+ FILE_PATH_LITERAL(".svg"), FILE_PATH_LITERAL(".swf"),
+ FILE_PATH_LITERAL(".sys"), FILE_PATH_LITERAL(".tcsh"),
+ FILE_PATH_LITERAL(".url"), FILE_PATH_LITERAL(".vb"),
+ FILE_PATH_LITERAL(".vbe"), FILE_PATH_LITERAL(".vbs"),
+ FILE_PATH_LITERAL(".vsd"), FILE_PATH_LITERAL(".vsmacros"),
+ FILE_PATH_LITERAL(".vss"), FILE_PATH_LITERAL(".vst"),
+ FILE_PATH_LITERAL(".vsw"), FILE_PATH_LITERAL(".ws"),
+ FILE_PATH_LITERAL(".wsc"), FILE_PATH_LITERAL(".wsf"),
+ FILE_PATH_LITERAL(".wsh"), FILE_PATH_LITERAL(".xbap"),
+ FILE_PATH_LITERAL(".xht"), FILE_PATH_LITERAL(".xhtm"),
+ FILE_PATH_LITERAL(".xhtml"), FILE_PATH_LITERAL(".xml"),
+ FILE_PATH_LITERAL(".xsl"), FILE_PATH_LITERAL(".xslt"),
+ FILE_PATH_LITERAL(".website"), FILE_PATH_LITERAL(".msh1"),
+ FILE_PATH_LITERAL(".msh2"), FILE_PATH_LITERAL(".msh1xml"),
+ FILE_PATH_LITERAL(".msh2xml"), FILE_PATH_LITERAL(".ps1"),
+ FILE_PATH_LITERAL(".ps1xml"), FILE_PATH_LITERAL(".ps2"),
+ FILE_PATH_LITERAL(".ps2xml"), FILE_PATH_LITERAL(".psc1"),
+ FILE_PATH_LITERAL(".psc2"), FILE_PATH_LITERAL(".xnk"),
+ FILE_PATH_LITERAL(".appref-ms"), FILE_PATH_LITERAL(".gadget"),
+ FILE_PATH_LITERAL(".efi"), FILE_PATH_LITERAL(".fon"),
+ FILE_PATH_LITERAL(".partial"), FILE_PATH_LITERAL(".svg"),
+ FILE_PATH_LITERAL(".xml"), FILE_PATH_LITERAL(".xrm_ms"),
+ FILE_PATH_LITERAL(".xsl"), FILE_PATH_LITERAL(".action"),
+ FILE_PATH_LITERAL(".bin"), FILE_PATH_LITERAL(".inx"),
+ FILE_PATH_LITERAL(".ipa"), FILE_PATH_LITERAL(".isu"),
+ FILE_PATH_LITERAL(".job"), FILE_PATH_LITERAL(".out"),
+ FILE_PATH_LITERAL(".pad"), FILE_PATH_LITERAL(".paf"),
+ FILE_PATH_LITERAL(".rgs"), FILE_PATH_LITERAL(".u3p"),
+ FILE_PATH_LITERAL(".vbscript"), FILE_PATH_LITERAL(".workflow"),
+ FILE_PATH_LITERAL(".001"), FILE_PATH_LITERAL(".7z"),
+ FILE_PATH_LITERAL(".ace"), FILE_PATH_LITERAL(".arc"),
+ FILE_PATH_LITERAL(".arj"), FILE_PATH_LITERAL(".b64"),
+ FILE_PATH_LITERAL(".balz"), FILE_PATH_LITERAL(".bhx"),
+ FILE_PATH_LITERAL(".bz"), FILE_PATH_LITERAL(".bz2"),
+ FILE_PATH_LITERAL(".bzip2"), FILE_PATH_LITERAL(".cab"),
+ FILE_PATH_LITERAL(".cpio"), FILE_PATH_LITERAL(".fat"),
+ FILE_PATH_LITERAL(".gz"), FILE_PATH_LITERAL(".gzip"),
+ FILE_PATH_LITERAL(".hfs"), FILE_PATH_LITERAL(".hqx"),
+ FILE_PATH_LITERAL(".iso"), FILE_PATH_LITERAL(".lha"),
+ FILE_PATH_LITERAL(".lpaq1"), FILE_PATH_LITERAL(".lpaq5"),
+ FILE_PATH_LITERAL(".lpaq8"), FILE_PATH_LITERAL(".lzh"),
+ FILE_PATH_LITERAL(".lzma"), FILE_PATH_LITERAL(".mim"),
+ FILE_PATH_LITERAL(".ntfs"), FILE_PATH_LITERAL(".paq8f"),
+ FILE_PATH_LITERAL(".paq8jd"), FILE_PATH_LITERAL(".paq8l"),
+ FILE_PATH_LITERAL(".paq8o"), FILE_PATH_LITERAL(".pea"),
+ FILE_PATH_LITERAL(".quad"), FILE_PATH_LITERAL(".r00"),
+ FILE_PATH_LITERAL(".r01"), FILE_PATH_LITERAL(".r02"),
+ FILE_PATH_LITERAL(".r03"), FILE_PATH_LITERAL(".r04"),
+ FILE_PATH_LITERAL(".r05"), FILE_PATH_LITERAL(".r06"),
+ FILE_PATH_LITERAL(".r07"), FILE_PATH_LITERAL(".r08"),
+ FILE_PATH_LITERAL(".r09"), FILE_PATH_LITERAL(".r10"),
+ FILE_PATH_LITERAL(".r11"), FILE_PATH_LITERAL(".r12"),
+ FILE_PATH_LITERAL(".r13"), FILE_PATH_LITERAL(".r14"),
+ FILE_PATH_LITERAL(".r15"), FILE_PATH_LITERAL(".r16"),
+ FILE_PATH_LITERAL(".r17"), FILE_PATH_LITERAL(".r18"),
+ FILE_PATH_LITERAL(".r19"), FILE_PATH_LITERAL(".r20"),
+ FILE_PATH_LITERAL(".r21"), FILE_PATH_LITERAL(".r22"),
+ FILE_PATH_LITERAL(".r23"), FILE_PATH_LITERAL(".r24"),
+ FILE_PATH_LITERAL(".r25"), FILE_PATH_LITERAL(".r26"),
+ FILE_PATH_LITERAL(".r27"), FILE_PATH_LITERAL(".r28"),
+ FILE_PATH_LITERAL(".r29"), FILE_PATH_LITERAL(".rar"),
+ FILE_PATH_LITERAL(".squashfs"), FILE_PATH_LITERAL(".swm"),
+ FILE_PATH_LITERAL(".tar"), FILE_PATH_LITERAL(".taz"),
+ FILE_PATH_LITERAL(".tbz"), FILE_PATH_LITERAL(".tbz2"),
+ FILE_PATH_LITERAL(".tgz"), FILE_PATH_LITERAL(".tpz"),
+ FILE_PATH_LITERAL(".txz"), FILE_PATH_LITERAL(".tz"),
+ FILE_PATH_LITERAL(".udf"), FILE_PATH_LITERAL(".uu"),
+ FILE_PATH_LITERAL(".uue"), FILE_PATH_LITERAL(".vhd"),
+ FILE_PATH_LITERAL(".vmdk"), FILE_PATH_LITERAL(".wim"),
+ FILE_PATH_LITERAL(".wrc"), FILE_PATH_LITERAL(".xar"),
+ FILE_PATH_LITERAL(".xxe"), FILE_PATH_LITERAL(".xz"),
+ FILE_PATH_LITERAL(".z"), FILE_PATH_LITERAL(".zip"),
+ FILE_PATH_LITERAL(".zipx"), FILE_PATH_LITERAL(".zpaq"),
+ FILE_PATH_LITERAL(".cdr"), FILE_PATH_LITERAL(".dart"),
+ FILE_PATH_LITERAL(".dc42"), FILE_PATH_LITERAL(".diskcopy42"),
+ FILE_PATH_LITERAL(".dmg"), FILE_PATH_LITERAL(".dmgpart"),
+ FILE_PATH_LITERAL(".dvdr"), FILE_PATH_LITERAL(".img"),
+ FILE_PATH_LITERAL(".imgpart"), FILE_PATH_LITERAL(".ndif"),
+ FILE_PATH_LITERAL(".smi"), FILE_PATH_LITERAL(".sparsebundle"),
+ FILE_PATH_LITERAL(".sparseimage"), FILE_PATH_LITERAL(".toast"),
+ FILE_PATH_LITERAL(".udif"), FILE_PATH_LITERAL(".run"), // 262
+ FILE_PATH_LITERAL(".mpkg"), FILE_PATH_LITERAL(".as"), // 264
+ FILE_PATH_LITERAL(".cpgz"), FILE_PATH_LITERAL(".pax"), // 266
+ FILE_PATH_LITERAL(".xip"), FILE_PATH_LITERAL(".docx"), // 268
+ FILE_PATH_LITERAL(".docm"), FILE_PATH_LITERAL(".dott"), // 270
+ FILE_PATH_LITERAL(".dotm"), FILE_PATH_LITERAL(".docb"), // 272
+ FILE_PATH_LITERAL(".xlsx"), FILE_PATH_LITERAL(".xlsm"), // 274
+ FILE_PATH_LITERAL(".xltx"), FILE_PATH_LITERAL(".xltm"), // 276
+ FILE_PATH_LITERAL(".pptx"), FILE_PATH_LITERAL(".pptm"), // 278
+ FILE_PATH_LITERAL(".potx"), FILE_PATH_LITERAL(".ppam"), // 280
+ FILE_PATH_LITERAL(".ppsx"), FILE_PATH_LITERAL(".sldx"), // 282
+ FILE_PATH_LITERAL(".sldm"), FILE_PATH_LITERAL(".htm"), // 284
+ FILE_PATH_LITERAL(".html"), FILE_PATH_LITERAL(".xht"), // 286
+ FILE_PATH_LITERAL(".xhtm"), FILE_PATH_LITERAL(".xhtml"), // 288
+ FILE_PATH_LITERAL(".vdx"), FILE_PATH_LITERAL(".vsx"), // 290
+ FILE_PATH_LITERAL(".vtx"), FILE_PATH_LITERAL(".vsdx"), // 292
+ FILE_PATH_LITERAL(".vssx"), FILE_PATH_LITERAL(".vstx"), // 294
+ FILE_PATH_LITERAL(".vsdm"), FILE_PATH_LITERAL(".vssm"), // 296
+ FILE_PATH_LITERAL(".vstm"), FILE_PATH_LITERAL(".btapp"), // 298
+ FILE_PATH_LITERAL(".btskin"), FILE_PATH_LITERAL(".btinstall"), // 300
+ FILE_PATH_LITERAL(".btkey"), FILE_PATH_LITERAL(".btsearch"), // 302
+ FILE_PATH_LITERAL(".dhtml"), FILE_PATH_LITERAL(".dhtm"), // 304
+ FILE_PATH_LITERAL(".dht"), FILE_PATH_LITERAL(".shtml"), // 306
+ FILE_PATH_LITERAL(".shtm"), FILE_PATH_LITERAL(".sht"), // 308
+ // NOTE! When you add a type here, please add the UMA value as a comment.
+ // These must all match DownloadItem.DangerousFileType in
+ // enums.xml. From 263 onward, they should also match
+ // SBClientDownloadExtensions.
+};
+
+// The maximum size in KB for the file size metric, file size larger than this
+// will be kept in overflow bucket.
+const int64_t kMaxFileSizeKb = 4 * 1024 * 1024; /* 4GB. */
+
+const int64_t kHighBandwidthBytesPerSecond = 30 * 1024 * 1024;
+
+// Maps extensions to their matching UMA histogram int value.
+int GetDangerousFileType(const base::FilePath& file_path) {
+ for (size_t i = 0; i < arraysize(kDangerousFileTypes); ++i) {
+ if (file_path.MatchesExtension(kDangerousFileTypes[i]))
+ return i + 1;
+ }
+ return 0; // Unknown extension.
+}
+
+// Helper method to calculate the bandwidth given the data length and time.
+int64_t CalculateBandwidthBytesPerSecond(size_t length,
+ base::TimeDelta elapsed_time) {
+ int64_t elapsed_time_ms = elapsed_time.InMilliseconds();
+ if (0 == elapsed_time_ms)
+ elapsed_time_ms = 1;
+ return 1000 * static_cast<int64_t>(length) / elapsed_time_ms;
+}
+
+// Helper method to record the bandwidth for a given metric.
+void RecordBandwidthMetric(const std::string& metric, int bandwidth) {
+ base::UmaHistogramCustomCounts(metric, bandwidth, 1, 50 * 1000 * 1000, 50);
+}
+
+// Records a histogram with download source suffix.
+std::string CreateHistogramNameWithSuffix(const std::string& name,
+ DownloadSource download_source) {
+ std::string suffix;
+ switch (download_source) {
+ case DownloadSource::UNKNOWN:
+ suffix = "UnknownSource";
+ break;
+ case DownloadSource::NAVIGATION:
+ suffix = "Navigation";
+ break;
+ case DownloadSource::DRAG_AND_DROP:
+ suffix = "DragAndDrop";
+ break;
+ case DownloadSource::FROM_RENDERER:
+ suffix = "FromRenderer";
+ break;
+ case DownloadSource::EXTENSION_API:
+ suffix = "ExtensionAPI";
+ break;
+ case DownloadSource::EXTENSION_INSTALLER:
+ suffix = "ExtensionInstaller";
+ break;
+ case DownloadSource::INTERNAL_API:
+ suffix = "InternalAPI";
+ break;
+ case DownloadSource::WEB_CONTENTS_API:
+ suffix = "WebContentsAPI";
+ break;
+ case DownloadSource::OFFLINE_PAGE:
+ suffix = "OfflinePage";
+ break;
+ case DownloadSource::CONTEXT_MENU:
+ suffix = "ContextMenu";
+ break;
+ }
+
+ return name + "." + suffix;
+}
+
+} // namespace
+
+void RecordDownloadCount(DownloadCountTypes type) {
+ UMA_HISTOGRAM_ENUMERATION("Download.Counts", type,
+ DOWNLOAD_COUNT_TYPES_LAST_ENTRY);
+}
+
+void RecordDownloadCountWithSource(DownloadCountTypes type,
+ DownloadSource download_source) {
+ RecordDownloadCount(type);
+
+ std::string name =
+ CreateHistogramNameWithSuffix("Download.Counts", download_source);
+ base::UmaHistogramEnumeration(name, type, DOWNLOAD_COUNT_TYPES_LAST_ENTRY);
+}
+
+void RecordDownloadCompleted(const base::TimeTicks& start,
+ int64_t download_len,
+ bool is_parallelizable,
+ DownloadSource download_source) {
+ RecordDownloadCountWithSource(COMPLETED_COUNT, download_source);
+ UMA_HISTOGRAM_LONG_TIMES("Download.Time", (base::TimeTicks::Now() - start));
+ int64_t max = 1024 * 1024 * 1024; // One Terabyte.
+ download_len /= 1024; // In Kilobytes
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.DownloadSize", download_len, 1, max,
+ 256);
+ if (is_parallelizable) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.DownloadSize.Parallelizable",
+ download_len, 1, max, 256);
+ }
+}
+
+void RecordDownloadInterrupted(DownloadInterruptReason reason,
+ int64_t received,
+ int64_t total,
+ bool is_parallelizable,
+ bool is_parallel_download_enabled,
+ DownloadSource download_source) {
+ RecordDownloadCountWithSource(INTERRUPTED_COUNT, download_source);
+ if (is_parallelizable) {
+ RecordParallelizableDownloadCount(INTERRUPTED_COUNT,
+ is_parallel_download_enabled);
+ }
+
+ std::vector<base::HistogramBase::Sample> samples =
+ base::CustomHistogram::ArrayToCustomRanges(
+ kAllInterruptReasonCodes, arraysize(kAllInterruptReasonCodes));
+ UMA_HISTOGRAM_CUSTOM_ENUMERATION("Download.InterruptedReason", reason,
+ samples);
+
+ std::string name = CreateHistogramNameWithSuffix("Download.InterruptedReason",
+ download_source);
+ base::HistogramBase* counter = base::CustomHistogram::FactoryGet(
+ name, samples, base::HistogramBase::kUmaTargetedHistogramFlag);
+ counter->Add(reason);
+
+ if (is_parallel_download_enabled) {
+ UMA_HISTOGRAM_CUSTOM_ENUMERATION(
+ "Download.InterruptedReason.ParallelDownload", reason, samples);
+ }
+
+ // The maximum should be 2^kBuckets, to have the logarithmic bucket
+ // boundaries fall on powers of 2.
+ static const int kBuckets = 30;
+ static const int64_t kMaxKb = 1 << kBuckets; // One Terabyte, in Kilobytes.
+ int64_t delta_bytes = total - received;
+ bool unknown_size = total <= 0;
+ int64_t received_kb = received / 1024;
+ int64_t total_kb = total / 1024;
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedReceivedSizeK", received_kb,
+ 1, kMaxKb, kBuckets);
+ if (is_parallel_download_enabled) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Download.InterruptedReceivedSizeK.ParallelDownload", received_kb, 1,
+ kMaxKb, kBuckets);
+ }
+
+ if (!unknown_size) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedTotalSizeK", total_kb, 1,
+ kMaxKb, kBuckets);
+ if (is_parallel_download_enabled) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Download.InterruptedTotalSizeK.ParallelDownload", total_kb, 1,
+ kMaxKb, kBuckets);
+ }
+ if (delta_bytes == 0) {
+ RecordDownloadCountWithSource(INTERRUPTED_AT_END_COUNT, download_source);
+ UMA_HISTOGRAM_CUSTOM_ENUMERATION("Download.InterruptedAtEndReason",
+ reason, samples);
+
+ if (is_parallelizable) {
+ RecordParallelizableDownloadCount(INTERRUPTED_AT_END_COUNT,
+ is_parallel_download_enabled);
+ UMA_HISTOGRAM_CUSTOM_ENUMERATION(
+ "Download.InterruptedAtEndReason.ParallelDownload", reason,
+ samples);
+ }
+ } else if (delta_bytes > 0) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedOverrunBytes",
+ delta_bytes, 1, kMaxKb, kBuckets);
+ if (is_parallel_download_enabled) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Download.InterruptedOverrunBytes.ParallelDownload", delta_bytes, 1,
+ kMaxKb, kBuckets);
+ }
+ } else {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedUnderrunBytes",
+ -delta_bytes, 1, kMaxKb, kBuckets);
+ if (is_parallel_download_enabled) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Download.InterruptedUnderrunBytes.ParallelDownload", -delta_bytes,
+ 1, kMaxKb, kBuckets);
+ }
+ }
+ }
+
+ UMA_HISTOGRAM_BOOLEAN("Download.InterruptedUnknownSize", unknown_size);
+}
+
+void RecordMaliciousDownloadClassified(DownloadDangerType danger_type) {
+ UMA_HISTOGRAM_ENUMERATION("Download.MaliciousDownloadClassified", danger_type,
+ DOWNLOAD_DANGER_TYPE_MAX);
+}
+
+void RecordDangerousDownloadAccept(DownloadDangerType danger_type,
+ const base::FilePath& file_path) {
+ UMA_HISTOGRAM_ENUMERATION("Download.DangerousDownloadValidated", danger_type,
+ DOWNLOAD_DANGER_TYPE_MAX);
+ if (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE) {
+ base::UmaHistogramSparse(
+ "Download.DangerousFile.DangerousDownloadValidated",
+ GetDangerousFileType(file_path));
+ }
+}
+
+void RecordDangerousDownloadDiscard(DownloadDiscardReason reason,
+ DownloadDangerType danger_type,
+ const base::FilePath& file_path) {
+ switch (reason) {
+ case DOWNLOAD_DISCARD_DUE_TO_USER_ACTION:
+ UMA_HISTOGRAM_ENUMERATION("Download.UserDiscard", danger_type,
+ DOWNLOAD_DANGER_TYPE_MAX);
+ if (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE) {
+ base::UmaHistogramSparse("Download.DangerousFile.UserDiscard",
+ GetDangerousFileType(file_path));
+ }
+ break;
+ case DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN:
+ UMA_HISTOGRAM_ENUMERATION("Download.Discard", danger_type,
+ DOWNLOAD_DANGER_TYPE_MAX);
+ if (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE) {
+ base::UmaHistogramSparse("Download.DangerousFile.Discard",
+ GetDangerousFileType(file_path));
+ }
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+void RecordAcceptsRanges(const std::string& accepts_ranges,
+ int64_t download_len,
+ bool has_strong_validator) {
+ int64_t max = 1024 * 1024 * 1024; // One Terabyte.
+ download_len /= 1024; // In Kilobytes
+ static const int kBuckets = 50;
+
+ if (base::LowerCaseEqualsASCII(accepts_ranges, "none")) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.AcceptRangesNone.KBytes",
+ download_len, 1, max, kBuckets);
+ } else if (base::LowerCaseEqualsASCII(accepts_ranges, "bytes")) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.AcceptRangesBytes.KBytes",
+ download_len, 1, max, kBuckets);
+ if (has_strong_validator)
+ RecordDownloadCount(STRONG_VALIDATOR_AND_ACCEPTS_RANGES);
+ } else {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.AcceptRangesMissingOrInvalid.KBytes",
+ download_len, 1, max, kBuckets);
+ }
+}
+
+namespace {
+
+int GetMimeTypeMatch(const std::string& mime_type_string,
+ std::map<std::string, int> mime_type_map) {
+ for (const auto& entry : mime_type_map) {
+ if (entry.first == mime_type_string) {
+ return entry.second;
+ }
+ }
+ return 0;
+}
+
+static std::map<std::string, DownloadContent>
+getMimeTypeToDownloadContentMap() {
+ return {
+ {"application/octet-stream", DownloadContent::OCTET_STREAM},
+ {"binary/octet-stream", DownloadContent::OCTET_STREAM},
+ {"application/pdf", DownloadContent::PDF},
+ {"application/msword", DownloadContent::DOCUMENT},
+ {"application/"
+ "vnd.openxmlformats-officedocument.wordprocessingml.document",
+ DownloadContent::DOCUMENT},
+ {"application/rtf", DownloadContent::DOCUMENT},
+ {"application/vnd.oasis.opendocument.text", DownloadContent::DOCUMENT},
+ {"application/vnd.google-apps.document", DownloadContent::DOCUMENT},
+ {"application/vnd.ms-excel", DownloadContent::SPREADSHEET},
+ {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ DownloadContent::SPREADSHEET},
+ {"application/vnd.oasis.opendocument.spreadsheet",
+ DownloadContent::SPREADSHEET},
+ {"application/vnd.google-apps.spreadsheet", DownloadContent::SPREADSHEET},
+ {"application/vns.ms-powerpoint", DownloadContent::PRESENTATION},
+ {"application/"
+ "vnd.openxmlformats-officedocument.presentationml.presentation",
+ DownloadContent::PRESENTATION},
+ {"application/vnd.oasis.opendocument.presentation",
+ DownloadContent::PRESENTATION},
+ {"application/vnd.google-apps.presentation",
+ DownloadContent::PRESENTATION},
+ {"application/zip", DownloadContent::ARCHIVE},
+ {"application/x-gzip", DownloadContent::ARCHIVE},
+ {"application/x-rar-compressed", DownloadContent::ARCHIVE},
+ {"application/x-tar", DownloadContent::ARCHIVE},
+ {"application/x-bzip", DownloadContent::ARCHIVE},
+ {"application/x-bzip2", DownloadContent::ARCHIVE},
+ {"application/x-7z-compressed", DownloadContent::ARCHIVE},
+ {"application/x-exe", DownloadContent::EXECUTABLE},
+ {"application/java-archive", DownloadContent::EXECUTABLE},
+ {"application/vnd.apple.installer+xml", DownloadContent::EXECUTABLE},
+ {"application/x-csh", DownloadContent::EXECUTABLE},
+ {"application/x-sh", DownloadContent::EXECUTABLE},
+ {"application/x-apple-diskimage", DownloadContent::DMG},
+ {"application/x-chrome-extension", DownloadContent::CRX},
+ {"application/xhtml+xml", DownloadContent::WEB},
+ {"application/xml", DownloadContent::WEB},
+ {"application/javascript", DownloadContent::WEB},
+ {"application/json", DownloadContent::WEB},
+ {"application/typescript", DownloadContent::WEB},
+ {"application/vnd.mozilla.xul+xml", DownloadContent::WEB},
+ {"application/vnd.amazon.ebook", DownloadContent::EBOOK},
+ {"application/epub+zip", DownloadContent::EBOOK},
+ {"application/vnd.android.package-archive", DownloadContent::APK}};
+}
+
+// NOTE: Keep in sync with DownloadImageType in
+// tools/metrics/histograms/enums.xml.
+enum DownloadImage {
+ DOWNLOAD_IMAGE_UNRECOGNIZED = 0,
+ DOWNLOAD_IMAGE_GIF = 1,
+ DOWNLOAD_IMAGE_JPEG = 2,
+ DOWNLOAD_IMAGE_PNG = 3,
+ DOWNLOAD_IMAGE_TIFF = 4,
+ DOWNLOAD_IMAGE_ICON = 5,
+ DOWNLOAD_IMAGE_WEBP = 6,
+ DOWNLOAD_IMAGE_PSD = 7,
+ DOWNLOAD_IMAGE_SVG = 8,
+ DOWNLOAD_IMAGE_MAX = 9,
+};
+
+static std::map<std::string, int> getMimeTypeToDownloadImageMap() {
+ return {{"image/gif", DOWNLOAD_IMAGE_GIF},
+ {"image/jpeg", DOWNLOAD_IMAGE_JPEG},
+ {"image/png", DOWNLOAD_IMAGE_PNG},
+ {"image/tiff", DOWNLOAD_IMAGE_TIFF},
+ {"image/vnd.microsoft.icon", DOWNLOAD_IMAGE_ICON},
+ {"image/x-icon", DOWNLOAD_IMAGE_ICON},
+ {"image/webp", DOWNLOAD_IMAGE_WEBP},
+ {"image/vnd.adobe.photoshop", DOWNLOAD_IMAGE_PSD},
+ {"image/svg+xml", DOWNLOAD_IMAGE_SVG}};
+}
+
+void RecordDownloadImageType(const std::string& mime_type_string) {
+ DownloadImage download_image = DownloadImage(
+ GetMimeTypeMatch(mime_type_string, getMimeTypeToDownloadImageMap()));
+ UMA_HISTOGRAM_ENUMERATION("Download.ContentType.Image", download_image,
+ DOWNLOAD_IMAGE_MAX);
+}
+
+/** Text categories **/
+
+// NOTE: Keep in sync with DownloadTextType in
+// tools/metrics/histograms/enums.xml.
+enum DownloadText {
+ DOWNLOAD_TEXT_UNRECOGNIZED = 0,
+ DOWNLOAD_TEXT_PLAIN = 1,
+ DOWNLOAD_TEXT_CSS = 2,
+ DOWNLOAD_TEXT_CSV = 3,
+ DOWNLOAD_TEXT_HTML = 4,
+ DOWNLOAD_TEXT_CALENDAR = 5,
+ DOWNLOAD_TEXT_MAX = 6,
+};
+
+static std::map<std::string, int> getMimeTypeToDownloadTextMap() {
+ return {{"text/plain", DOWNLOAD_TEXT_PLAIN},
+ {"text/css", DOWNLOAD_TEXT_CSS},
+ {"text/csv", DOWNLOAD_TEXT_CSV},
+ {"text/html", DOWNLOAD_TEXT_HTML},
+ {"text/calendar", DOWNLOAD_TEXT_CALENDAR}};
+}
+
+void RecordDownloadTextType(const std::string& mime_type_string) {
+ DownloadText download_text = DownloadText(
+ GetMimeTypeMatch(mime_type_string, getMimeTypeToDownloadTextMap()));
+ UMA_HISTOGRAM_ENUMERATION("Download.ContentType.Text", download_text,
+ DOWNLOAD_TEXT_MAX);
+}
+
+/* Audio categories */
+
+// NOTE: Keep in sync with DownloadAudioType in
+// tools/metrics/histograms/enums.xml.
+enum DownloadAudio {
+ DOWNLOAD_AUDIO_UNRECOGNIZED = 0,
+ DOWNLOAD_AUDIO_AAC = 1,
+ DOWNLOAD_AUDIO_MIDI = 2,
+ DOWNLOAD_AUDIO_OGA = 3,
+ DOWNLOAD_AUDIO_WAV = 4,
+ DOWNLOAD_AUDIO_WEBA = 5,
+ DOWNLOAD_AUDIO_3GP = 6,
+ DOWNLOAD_AUDIO_3G2 = 7,
+ DOWNLOAD_AUDIO_MP3 = 8,
+ DOWNLOAD_AUDIO_MAX = 9,
+};
+
+static std::map<std::string, int> getMimeTypeToDownloadAudioMap() {
+ return {
+ {"audio/aac", DOWNLOAD_AUDIO_AAC}, {"audio/midi", DOWNLOAD_AUDIO_MIDI},
+ {"audio/ogg", DOWNLOAD_AUDIO_OGA}, {"audio/x-wav", DOWNLOAD_AUDIO_WAV},
+ {"audio/webm", DOWNLOAD_AUDIO_WEBA}, {"audio/3gpp", DOWNLOAD_AUDIO_3GP},
+ {"audio/3gpp2", DOWNLOAD_AUDIO_3G2}, {"audio/mp3", DOWNLOAD_AUDIO_MP3}};
+}
+
+void RecordDownloadAudioType(const std::string& mime_type_string) {
+ DownloadAudio download_audio = DownloadAudio(
+ GetMimeTypeMatch(mime_type_string, getMimeTypeToDownloadAudioMap()));
+ UMA_HISTOGRAM_ENUMERATION("Download.ContentType.Audio", download_audio,
+ DOWNLOAD_AUDIO_MAX);
+}
+
+/* Video categories */
+
+// NOTE: Keep in sync with DownloadVideoType in
+// tools/metrics/histograms/enums.xml.
+enum DownloadVideo {
+ DOWNLOAD_VIDEO_UNRECOGNIZED = 0,
+ DOWNLOAD_VIDEO_AVI = 1,
+ DOWNLOAD_VIDEO_MPEG = 2,
+ DOWNLOAD_VIDEO_OGV = 3,
+ DOWNLOAD_VIDEO_WEBM = 4,
+ DOWNLOAD_VIDEO_3GP = 5,
+ DOWNLOAD_VIDEO_3G2 = 6,
+ DOWNLOAD_VIDEO_MP4 = 7,
+ DOWNLOAD_VIDEO_MOV = 8,
+ DOWNLOAD_VIDEO_WMV = 9,
+ DOWNLOAD_VIDEO_MAX = 10,
+};
+
+static std::map<std::string, int> getMimeTypeToDownloadVideoMap() {
+ return {{"video/x-msvideo", DOWNLOAD_VIDEO_AVI},
+ {"video/mpeg", DOWNLOAD_VIDEO_MPEG},
+ {"video/ogg", DOWNLOAD_VIDEO_OGV},
+ {"video/webm", DOWNLOAD_VIDEO_WEBM},
+ {"video/3gpp", DOWNLOAD_VIDEO_3GP},
+ {"video/3ggp2", DOWNLOAD_VIDEO_3G2},
+ {"video/mp4", DOWNLOAD_VIDEO_MP4},
+ {"video/quicktime", DOWNLOAD_VIDEO_MOV},
+ {"video/x-ms-wmv", DOWNLOAD_VIDEO_WMV}};
+}
+
+void RecordDownloadVideoType(const std::string& mime_type_string) {
+ DownloadVideo download_video = DownloadVideo(
+ GetMimeTypeMatch(mime_type_string, getMimeTypeToDownloadVideoMap()));
+ UMA_HISTOGRAM_ENUMERATION("Download.ContentType.Video", download_video,
+ DOWNLOAD_VIDEO_MAX);
+}
+
+} // namespace
+
+DownloadContent DownloadContentFromMimeType(const std::string& mime_type_string,
+ bool record_content_subcategory) {
+ DownloadContent download_content = DownloadContent::UNRECOGNIZED;
+ for (const auto& entry : getMimeTypeToDownloadContentMap()) {
+ if (entry.first == mime_type_string) {
+ download_content = entry.second;
+ }
+ }
+
+ // Do partial matches.
+ if (download_content == DownloadContent::UNRECOGNIZED) {
+ if (base::StartsWith(mime_type_string, "text/",
+ base::CompareCase::SENSITIVE)) {
+ download_content = DownloadContent::TEXT;
+ if (record_content_subcategory)
+ RecordDownloadTextType(mime_type_string);
+ } else if (base::StartsWith(mime_type_string, "image/",
+ base::CompareCase::SENSITIVE)) {
+ download_content = DownloadContent::IMAGE;
+ if (record_content_subcategory)
+ RecordDownloadImageType(mime_type_string);
+ } else if (base::StartsWith(mime_type_string, "audio/",
+ base::CompareCase::SENSITIVE)) {
+ download_content = DownloadContent::AUDIO;
+ if (record_content_subcategory)
+ RecordDownloadAudioType(mime_type_string);
+ } else if (base::StartsWith(mime_type_string, "video/",
+ base::CompareCase::SENSITIVE)) {
+ download_content = DownloadContent::VIDEO;
+ if (record_content_subcategory)
+ RecordDownloadVideoType(mime_type_string);
+ } else if (base::StartsWith(mime_type_string, "font/",
+ base::CompareCase::SENSITIVE)) {
+ download_content = DownloadContent::FONT;
+ }
+ }
+
+ return download_content;
+}
+
+void RecordDownloadMimeType(const std::string& mime_type_string) {
+ DownloadContent download_content =
+ DownloadContentFromMimeType(mime_type_string, true);
+ UMA_HISTOGRAM_ENUMERATION("Download.Start.ContentType", download_content,
+ DownloadContent::MAX);
+}
+
+void RecordDownloadMimeTypeForNormalProfile(
+ const std::string& mime_type_string) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Download.Start.ContentType.NormalProfile",
+ DownloadContentFromMimeType(mime_type_string, false),
+ DownloadContent::MAX);
+}
+
+void RecordDownloadContentDisposition(
+ const std::string& content_disposition_string) {
+ if (content_disposition_string.empty())
+ return;
+ net::HttpContentDisposition content_disposition(content_disposition_string,
+ std::string());
+ int result = content_disposition.parse_result_flags();
+
+ bool is_valid = !content_disposition.filename().empty();
+ RecordContentDispositionCount(CONTENT_DISPOSITION_HEADER_PRESENT, true);
+ RecordContentDispositionCount(CONTENT_DISPOSITION_IS_VALID, is_valid);
+ if (!is_valid)
+ return;
+
+ RecordContentDispositionCountFlag(
+ CONTENT_DISPOSITION_HAS_DISPOSITION_TYPE, result,
+ net::HttpContentDisposition::HAS_DISPOSITION_TYPE);
+ RecordContentDispositionCountFlag(
+ CONTENT_DISPOSITION_HAS_UNKNOWN_TYPE, result,
+ net::HttpContentDisposition::HAS_UNKNOWN_DISPOSITION_TYPE);
+ RecordContentDispositionCountFlag(CONTENT_DISPOSITION_HAS_FILENAME, result,
+ net::HttpContentDisposition::HAS_FILENAME);
+ RecordContentDispositionCountFlag(
+ CONTENT_DISPOSITION_HAS_EXT_FILENAME, result,
+ net::HttpContentDisposition::HAS_EXT_FILENAME);
+ RecordContentDispositionCountFlag(
+ CONTENT_DISPOSITION_HAS_NON_ASCII_STRINGS, result,
+ net::HttpContentDisposition::HAS_NON_ASCII_STRINGS);
+ RecordContentDispositionCountFlag(
+ CONTENT_DISPOSITION_HAS_PERCENT_ENCODED_STRINGS, result,
+ net::HttpContentDisposition::HAS_PERCENT_ENCODED_STRINGS);
+ RecordContentDispositionCountFlag(
+ CONTENT_DISPOSITION_HAS_RFC2047_ENCODED_STRINGS, result,
+ net::HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS);
+}
+
+void RecordFileThreadReceiveBuffers(size_t num_buffers) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.FileThreadReceiveBuffers", num_buffers,
+ 1, 100, 100);
+}
+
+void RecordOpen(const base::Time& end, bool first) {
+ if (!end.is_null()) {
+ UMA_HISTOGRAM_LONG_TIMES("Download.OpenTime", (base::Time::Now() - end));
+ if (first) {
+ UMA_HISTOGRAM_LONG_TIMES("Download.FirstOpenTime",
+ (base::Time::Now() - end));
+ }
+ }
+}
+
+void RecordOpensOutstanding(int size) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.OpensOutstanding", size, 1 /*min*/,
+ (1 << 10) /*max*/, 64 /*num_buckets*/);
+}
+
+void RecordContiguousWriteTime(base::TimeDelta time_blocked) {
+ UMA_HISTOGRAM_TIMES("Download.FileThreadBlockedTime", time_blocked);
+}
+
+// Record what percentage of the time we have the network flow controlled.
+void RecordNetworkBlockage(base::TimeDelta resource_handler_lifetime,
+ base::TimeDelta resource_handler_blocked_time) {
+ int percentage = 0;
+ // Avoid division by zero errors.
+ if (!resource_handler_blocked_time.is_zero()) {
+ percentage =
+ resource_handler_blocked_time * 100 / resource_handler_lifetime;
+ }
+
+ UMA_HISTOGRAM_COUNTS_100("Download.ResourceHandlerBlockedPercentage",
+ percentage);
+}
+
+void RecordFileBandwidth(size_t length,
+ base::TimeDelta disk_write_time,
+ base::TimeDelta elapsed_time) {
+ RecordBandwidthMetric("Download.BandwidthOverallBytesPerSecond",
+ CalculateBandwidthBytesPerSecond(length, elapsed_time));
+ RecordBandwidthMetric(
+ "Download.BandwidthDiskBytesPerSecond",
+ CalculateBandwidthBytesPerSecond(length, disk_write_time));
+}
+
+void RecordParallelizableDownloadCount(DownloadCountTypes type,
+ bool is_parallel_download_enabled) {
+ std::string histogram_name = is_parallel_download_enabled
+ ? "Download.Counts.ParallelDownload"
+ : "Download.Counts.ParallelizableDownload";
+ base::UmaHistogramEnumeration(histogram_name, type,
+ DOWNLOAD_COUNT_TYPES_LAST_ENTRY);
+}
+
+void RecordParallelDownloadRequestCount(int request_count) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.ParallelDownloadRequestCount",
+ request_count, 1, 10, 11);
+}
+
+void RecordParallelDownloadAddStreamSuccess(bool success) {
+ UMA_HISTOGRAM_BOOLEAN("Download.ParallelDownloadAddStreamSuccess", success);
+}
+
+void RecordParallelizableContentLength(int64_t content_length) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.ContentLength.Parallelizable",
+ content_length / 1024, 1, kMaxFileSizeKb, 50);
+}
+
+void RecordParallelizableDownloadStats(
+ size_t bytes_downloaded_with_parallel_streams,
+ base::TimeDelta time_with_parallel_streams,
+ size_t bytes_downloaded_without_parallel_streams,
+ base::TimeDelta time_without_parallel_streams,
+ bool uses_parallel_requests) {
+ RecordParallelizableDownloadAverageStats(
+ bytes_downloaded_with_parallel_streams +
+ bytes_downloaded_without_parallel_streams,
+ time_with_parallel_streams + time_without_parallel_streams);
+
+ int64_t bandwidth_without_parallel_streams = 0;
+ if (bytes_downloaded_without_parallel_streams > 0) {
+ bandwidth_without_parallel_streams = CalculateBandwidthBytesPerSecond(
+ bytes_downloaded_without_parallel_streams,
+ time_without_parallel_streams);
+ if (uses_parallel_requests) {
+ RecordBandwidthMetric(
+ "Download.ParallelizableDownloadBandwidth."
+ "WithParallelRequestsSingleStream",
+ bandwidth_without_parallel_streams);
+ } else {
+ RecordBandwidthMetric(
+ "Download.ParallelizableDownloadBandwidth."
+ "WithoutParallelRequests",
+ bandwidth_without_parallel_streams);
+ }
+ }
+
+ if (!uses_parallel_requests)
+ return;
+
+ base::TimeDelta time_saved;
+ if (bytes_downloaded_with_parallel_streams > 0) {
+ int64_t bandwidth_with_parallel_streams = CalculateBandwidthBytesPerSecond(
+ bytes_downloaded_with_parallel_streams, time_with_parallel_streams);
+ RecordBandwidthMetric(
+ "Download.ParallelizableDownloadBandwidth."
+ "WithParallelRequestsMultipleStreams",
+ bandwidth_with_parallel_streams);
+ if (bandwidth_without_parallel_streams > 0) {
+ time_saved = base::TimeDelta::FromMilliseconds(
+ 1000.0 * bytes_downloaded_with_parallel_streams /
+ bandwidth_without_parallel_streams) -
+ time_with_parallel_streams;
+ int bandwidth_ratio_percentage =
+ (100.0 * bandwidth_with_parallel_streams) /
+ bandwidth_without_parallel_streams;
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Download.ParallelDownload.BandwidthRatioPercentage",
+ bandwidth_ratio_percentage, 0, 400, 101);
+ base::TimeDelta total_time =
+ time_with_parallel_streams + time_without_parallel_streams;
+ size_t total_size = bytes_downloaded_with_parallel_streams +
+ bytes_downloaded_without_parallel_streams;
+ base::TimeDelta non_parallel_time = base::TimeDelta::FromSecondsD(
+ static_cast<double>(total_size) / bandwidth_without_parallel_streams);
+ int time_ratio_percentage =
+ 100.0 * total_time.InSecondsF() / non_parallel_time.InSecondsF();
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Download.ParallelDownload.TotalTimeRatioPercentage",
+ time_ratio_percentage, 0, 200, 101);
+ }
+ }
+
+ int kMillisecondsPerHour =
+ base::checked_cast<int>(base::Time::kMillisecondsPerSecond * 60 * 60);
+ if (time_saved >= base::TimeDelta()) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Download.EstimatedTimeSavedWithParallelDownload",
+ time_saved.InMilliseconds(), 0, kMillisecondsPerHour, 50);
+ } else {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Download.EstimatedTimeWastedWithParallelDownload",
+ -time_saved.InMilliseconds(), 0, kMillisecondsPerHour, 50);
+ }
+}
+
+void RecordParallelizableDownloadAverageStats(
+ int64_t bytes_downloaded,
+ const base::TimeDelta& time_span) {
+ if (time_span.is_zero() || bytes_downloaded <= 0)
+ return;
+
+ int64_t average_bandwidth =
+ CalculateBandwidthBytesPerSecond(bytes_downloaded, time_span);
+ int64_t file_size_kb = bytes_downloaded / 1024;
+ RecordBandwidthMetric("Download.ParallelizableDownloadBandwidth",
+ average_bandwidth);
+ UMA_HISTOGRAM_LONG_TIMES("Download.Parallelizable.DownloadTime", time_span);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Download.Parallelizable.FileSize", file_size_kb,
+ 1, kMaxFileSizeKb, 50);
+ if (average_bandwidth > kHighBandwidthBytesPerSecond) {
+ UMA_HISTOGRAM_LONG_TIMES(
+ "Download.Parallelizable.DownloadTime.HighDownloadBandwidth",
+ time_span);
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Download.Parallelizable.FileSize.HighDownloadBandwidth", file_size_kb,
+ 1, kMaxFileSizeKb, 50);
+ }
+}
+
+void RecordParallelDownloadCreationEvent(ParallelDownloadCreationEvent event) {
+ UMA_HISTOGRAM_ENUMERATION("Download.ParallelDownload.CreationEvent", event,
+ ParallelDownloadCreationEvent::COUNT);
+}
+
+void RecordDownloadFileRenameResultAfterRetry(
+ base::TimeDelta time_since_first_failure,
+ DownloadInterruptReason interrupt_reason) {
+ if (interrupt_reason == DOWNLOAD_INTERRUPT_REASON_NONE) {
+ UMA_HISTOGRAM_TIMES("Download.TimeToRenameSuccessAfterInitialFailure",
+ time_since_first_failure);
+ } else {
+ UMA_HISTOGRAM_TIMES("Download.TimeToRenameFailureAfterInitialFailure",
+ time_since_first_failure);
+ }
+}
+
+void RecordSavePackageEvent(SavePackageEvent event) {
+ UMA_HISTOGRAM_ENUMERATION("Download.SavePackage", event,
+ SAVE_PACKAGE_LAST_ENTRY);
+}
+
+void RecordOriginStateOnResumption(bool is_partial,
+ OriginStateOnResumption state) {
+ if (is_partial)
+ UMA_HISTOGRAM_ENUMERATION("Download.OriginStateOnPartialResumption", state,
+ ORIGIN_STATE_ON_RESUMPTION_MAX);
+ else
+ UMA_HISTOGRAM_ENUMERATION("Download.OriginStateOnFullResumption", state,
+ ORIGIN_STATE_ON_RESUMPTION_MAX);
+}
+
+namespace {
+
+// Enumeration for histogramming purposes.
+// These values are written to logs. New enum values can be added, but existing
+// enums must never be renumbered or deleted and reused.
+enum DownloadConnectionSecurity {
+ DOWNLOAD_SECURE = 0, // Final download url and its redirects all use https
+ DOWNLOAD_TARGET_INSECURE =
+ 1, // Final download url uses http, redirects are all
+ // https
+ DOWNLOAD_REDIRECT_INSECURE =
+ 2, // Final download url uses https, but at least
+ // one redirect uses http
+ DOWNLOAD_REDIRECT_TARGET_INSECURE =
+ 3, // Final download url uses http, and at
+ // least one redirect uses http
+ DOWNLOAD_TARGET_OTHER = 4, // Final download url uses a scheme not present in
+ // this enumeration
+ DOWNLOAD_TARGET_BLOB = 5, // Final download url uses blob scheme
+ DOWNLOAD_TARGET_DATA = 6, // Final download url uses data scheme
+ DOWNLOAD_TARGET_FILE = 7, // Final download url uses file scheme
+ DOWNLOAD_TARGET_FILESYSTEM = 8, // Final download url uses filesystem scheme
+ DOWNLOAD_TARGET_FTP = 9, // Final download url uses ftp scheme
+ DOWNLOAD_CONNECTION_SECURITY_MAX
+};
+
+} // namespace
+
+void RecordDownloadConnectionSecurity(const GURL& download_url,
+ const std::vector<GURL>& url_chain) {
+ DownloadConnectionSecurity state = DOWNLOAD_TARGET_OTHER;
+ if (download_url.SchemeIsHTTPOrHTTPS()) {
+ bool is_final_download_secure = download_url.SchemeIsCryptographic();
+ bool is_redirect_chain_secure = true;
+ if (url_chain.size() > std::size_t(1)) {
+ for (std::size_t i = std::size_t(0); i < url_chain.size() - 1; i++) {
+ if (!url_chain[i].SchemeIsCryptographic()) {
+ is_redirect_chain_secure = false;
+ break;
+ }
+ }
+ }
+ state = is_final_download_secure
+ ? is_redirect_chain_secure ? DOWNLOAD_SECURE
+ : DOWNLOAD_REDIRECT_INSECURE
+ : is_redirect_chain_secure ? DOWNLOAD_TARGET_INSECURE
+ : DOWNLOAD_REDIRECT_TARGET_INSECURE;
+ } else if (download_url.SchemeIsBlob()) {
+ state = DOWNLOAD_TARGET_BLOB;
+ } else if (download_url.SchemeIs(url::kDataScheme)) {
+ state = DOWNLOAD_TARGET_DATA;
+ } else if (download_url.SchemeIsFile()) {
+ state = DOWNLOAD_TARGET_FILE;
+ } else if (download_url.SchemeIsFileSystem()) {
+ state = DOWNLOAD_TARGET_FILESYSTEM;
+ } else if (download_url.SchemeIs(url::kFtpScheme)) {
+ state = DOWNLOAD_TARGET_FTP;
+ }
+
+ UMA_HISTOGRAM_ENUMERATION("Download.TargetConnectionSecurity", state,
+ DOWNLOAD_CONNECTION_SECURITY_MAX);
+}
+
+void RecordDownloadSourcePageTransitionType(
+ const base::Optional<ui::PageTransition>& page_transition) {
+ if (!page_transition)
+ return;
+
+ UMA_HISTOGRAM_ENUMERATION(
+ "Download.PageTransition",
+ ui::PageTransitionStripQualifier(page_transition.value()),
+ ui::PAGE_TRANSITION_LAST_CORE + 1);
+}
+
+void RecordDownloadHttpResponseCode(int response_code) {
+ UMA_HISTOGRAM_CUSTOM_ENUMERATION(
+ "Download.HttpResponseCode",
+ net::HttpUtil::MapStatusCodeForHistogram(response_code),
+ net::HttpUtil::GetStatusCodesForHistogram());
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/common/download_stats_unittest.cc b/chromium/components/download/internal/common/download_stats_unittest.cc
new file mode 100644
index 00000000000..555bb2486a6
--- /dev/null
+++ b/chromium/components/download/internal/common/download_stats_unittest.cc
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/download_stats.h"
+
+#include "base/test/histogram_tester.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace download {
+
+namespace {
+
+void VerfiyParallelizableAverageStats(int64_t bytes_downloaded,
+ const base::TimeDelta& time_span) {
+ base::HistogramTester histogram_tester;
+ int64_t expected_bandwidth = bytes_downloaded / time_span.InSeconds();
+
+ RecordParallelizableDownloadAverageStats(bytes_downloaded, time_span);
+ histogram_tester.ExpectBucketCount("Download.ParallelizableDownloadBandwidth",
+ expected_bandwidth, 1);
+ histogram_tester.ExpectBucketCount("Download.Parallelizable.DownloadTime",
+ time_span.InMilliseconds(), 1);
+ histogram_tester.ExpectBucketCount("Download.Parallelizable.FileSize",
+ bytes_downloaded / 1024, 1);
+}
+
+} // namespace
+
+TEST(DownloadStatsTest, ParallelizableAverageStats) {
+ VerfiyParallelizableAverageStats(1, base::TimeDelta::FromSeconds(1));
+ VerfiyParallelizableAverageStats(1024 * 1024 * 20,
+ base::TimeDelta::FromSeconds(10));
+ VerfiyParallelizableAverageStats(1024 * 1024 * 1024,
+ base::TimeDelta::FromSeconds(1));
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/common/download_task_runner.cc b/chromium/components/download/internal/common/download_task_runner.cc
new file mode 100644
index 00000000000..cc24d67d5d0
--- /dev/null
+++ b/chromium/components/download/internal/common/download_task_runner.cc
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/download_task_runner.h"
+
+#include "base/task_scheduler/lazy_task_runner.h"
+#include "build/build_config.h"
+
+namespace download {
+
+namespace {
+
+#if defined(OS_WIN)
+// On Windows, the download code dips into COM and the shell here and there,
+// necessitating the use of a COM single-threaded apartment sequence.
+base::LazyCOMSTATaskRunner g_download_task_runner =
+ LAZY_COM_STA_TASK_RUNNER_INITIALIZER(
+ base::TaskTraits(base::MayBlock(), base::TaskPriority::USER_VISIBLE),
+ base::SingleThreadTaskRunnerThreadMode::SHARED);
+#else
+base::LazySequencedTaskRunner g_download_task_runner =
+ LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(
+ base::TaskTraits(base::MayBlock(), base::TaskPriority::USER_VISIBLE));
+#endif
+
+} // namespace
+
+scoped_refptr<base::SequencedTaskRunner> GetDownloadTaskRunner() {
+ return g_download_task_runner.Get();
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/common/download_ukm_helper.cc b/chromium/components/download/internal/common/download_ukm_helper.cc
new file mode 100644
index 00000000000..ec99fc75fba
--- /dev/null
+++ b/chromium/components/download/internal/common/download_ukm_helper.cc
@@ -0,0 +1,86 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/download_ukm_helper.h"
+
+#include "services/metrics/public/cpp/ukm_builders.h"
+
+namespace download {
+
+namespace {
+// Return the "size" of the bucket based on the allowed percent_error.
+double CalcBucketIncrement() {
+ double percent_error = 10;
+ return log10(1 + percent_error / 100);
+}
+} // namespace
+
+int DownloadUkmHelper::CalcExponentialBucket(int value) {
+ return static_cast<int>(floor(log10(value + 1) / CalcBucketIncrement()));
+}
+
+void DownloadUkmHelper::RecordDownloadStarted(int download_id,
+ ukm::SourceId source_id,
+ DownloadContent file_type,
+ DownloadSource download_source) {
+ ukm::builders::Download_Started(source_id)
+ .SetDownloadId(download_id)
+ .SetFileType(static_cast<int>(file_type))
+ .SetDownloadSource(static_cast<int>(download_source))
+ .Record(ukm::UkmRecorder::Get());
+}
+
+void DownloadUkmHelper::RecordDownloadInterrupted(
+ int download_id,
+ base::Optional<int> change_in_file_size,
+ DownloadInterruptReason reason,
+ int resulting_file_size,
+ const base::TimeDelta& time_since_start) {
+ ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
+ ukm::builders::Download_Interrupted builder(source_id);
+ builder.SetDownloadId(download_id)
+ .SetReason(static_cast<int>(reason))
+ .SetResultingFileSize(
+ DownloadUkmHelper::CalcExponentialBucket(resulting_file_size))
+ .SetTimeSinceStart(time_since_start.InMilliseconds());
+ if (change_in_file_size.has_value()) {
+ builder.SetChangeInFileSize(
+ DownloadUkmHelper::CalcExponentialBucket(change_in_file_size.value()));
+ }
+ builder.Record(ukm::UkmRecorder::Get());
+}
+
+void DownloadUkmHelper::RecordDownloadResumed(
+ int download_id,
+ ResumeMode mode,
+ const base::TimeDelta& time_since_start) {
+ ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
+ ukm::builders::Download_Resumed(source_id)
+ .SetDownloadId(download_id)
+ .SetMode(static_cast<int>(mode))
+ .SetTimeSinceStart(time_since_start.InMilliseconds())
+ .Record(ukm::UkmRecorder::Get());
+}
+
+void DownloadUkmHelper::RecordDownloadCompleted(
+ int download_id,
+ int resulting_file_size,
+ const base::TimeDelta& time_since_start) {
+ ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
+ ukm::builders::Download_Completed(source_id)
+ .SetDownloadId(download_id)
+ .SetResultingFileSize(
+ DownloadUkmHelper::CalcExponentialBucket(resulting_file_size))
+ .SetTimeSinceStart(time_since_start.InMilliseconds())
+ .Record(ukm::UkmRecorder::Get());
+}
+
+void DownloadUkmHelper::UpdateSourceURL(ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ const GURL& url) {
+ if (ukm_recorder)
+ ukm_recorder->UpdateSourceURL(source_id, url);
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/common/download_ukm_helper_unittest.cc b/chromium/components/download/internal/common/download_ukm_helper_unittest.cc
new file mode 100644
index 00000000000..4cc969a7f86
--- /dev/null
+++ b/chromium/components/download/internal/common/download_ukm_helper_unittest.cc
@@ -0,0 +1,121 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/download_ukm_helper.h"
+
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/ukm/test_ukm_recorder.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using UkmDownloadStarted = ukm::builders::Download_Started;
+using UkmDownloadInterrupted = ukm::builders::Download_Interrupted;
+using UkmDownloadResumed = ukm::builders::Download_Resumed;
+using UkmDownloadCompleted = ukm::builders::Download_Completed;
+
+namespace download {
+
+class DownloadUkmHelperTest : public testing::Test {
+ public:
+ DownloadUkmHelperTest() : download_id_(123) { ResetUkmRecorder(); }
+ ~DownloadUkmHelperTest() override = default;
+
+ void ResetUkmRecorder() {
+ test_recorder_.reset(new ukm::TestAutoSetUkmRecorder);
+ }
+
+ void ExpectUkmMetrics(const base::StringPiece entry_name,
+ const std::vector<base::StringPiece>& keys,
+ const std::vector<int>& values) {
+ const auto& entries = test_recorder_->GetEntriesByName(entry_name);
+ EXPECT_EQ(1u, entries.size());
+ for (const auto* entry : entries) {
+ const size_t keys_size = keys.size();
+ EXPECT_EQ(keys_size, values.size());
+ for (size_t i = 0; i < keys_size; ++i) {
+ test_recorder_->ExpectEntryMetric(entry, keys[i], values[i]);
+ }
+ }
+ }
+
+ protected:
+ int download_id_;
+
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_recorder_;
+
+ DISALLOW_COPY_AND_ASSIGN(DownloadUkmHelperTest);
+};
+
+TEST_F(DownloadUkmHelperTest, TestBasicReporting) {
+ // RecordDownloadStarted
+ ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
+ DownloadContent file_type = DownloadContent::AUDIO;
+ DownloadSource download_source = DownloadSource::UNKNOWN;
+ DownloadUkmHelper::RecordDownloadStarted(download_id_, source_id, file_type,
+ download_source);
+
+ ExpectUkmMetrics(
+ UkmDownloadStarted::kEntryName,
+ {UkmDownloadStarted::kDownloadIdName, UkmDownloadStarted::kFileTypeName,
+ UkmDownloadStarted::kDownloadSourceName},
+ {download_id_, static_cast<int>(file_type),
+ static_cast<int>(download_source)});
+
+ // RecordDownloadInterrupted, has change in file size.
+ int change_in_file_size = 1000;
+ DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_NONE;
+ int resulting_file_size = 2000;
+ int time_since_start = 250;
+ DownloadUkmHelper::RecordDownloadInterrupted(
+ download_id_, change_in_file_size, reason, resulting_file_size,
+ base::TimeDelta::FromMilliseconds(time_since_start));
+
+ ExpectUkmMetrics(
+ UkmDownloadInterrupted::kEntryName,
+ {UkmDownloadInterrupted::kDownloadIdName,
+ UkmDownloadInterrupted::kChangeInFileSizeName,
+ UkmDownloadInterrupted::kReasonName,
+ UkmDownloadInterrupted::kResultingFileSizeName,
+ UkmDownloadInterrupted::kTimeSinceStartName},
+ {download_id_,
+ DownloadUkmHelper::CalcExponentialBucket(change_in_file_size),
+ static_cast<int>(reason),
+ DownloadUkmHelper::CalcExponentialBucket(resulting_file_size),
+ time_since_start});
+
+ // RecordDownloadResumed.
+ ResumeMode mode = ResumeMode::IMMEDIATE_RESTART;
+ int time_since_start_resume = 300;
+ DownloadUkmHelper::RecordDownloadResumed(
+ download_id_, mode,
+ base::TimeDelta::FromMilliseconds(time_since_start_resume));
+
+ ExpectUkmMetrics(
+ UkmDownloadResumed::kEntryName,
+ {UkmDownloadResumed::kDownloadIdName, UkmDownloadResumed::kModeName,
+ UkmDownloadResumed::kTimeSinceStartName},
+ {download_id_, static_cast<int>(mode), time_since_start_resume});
+
+ // RecordDownloadCompleted.
+ int resulting_file_size_completed = 3000;
+ int time_since_start_completed = 400;
+ DownloadUkmHelper::RecordDownloadCompleted(
+ download_id_, resulting_file_size_completed,
+ base::TimeDelta::FromMilliseconds(time_since_start_completed));
+
+ ExpectUkmMetrics(
+ UkmDownloadCompleted::kEntryName,
+ {UkmDownloadCompleted::kDownloadIdName,
+ UkmDownloadCompleted::kResultingFileSizeName,
+ UkmDownloadCompleted::kTimeSinceStartName},
+ {download_id_,
+ DownloadUkmHelper::CalcExponentialBucket(resulting_file_size_completed),
+ time_since_start_completed});
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/common/download_utils.cc b/chromium/components/download/internal/common/download_utils.cc
new file mode 100644
index 00000000000..f59702cb72c
--- /dev/null
+++ b/chromium/components/download/internal/common/download_utils.cc
@@ -0,0 +1,11 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/download_item.h"
+
+namespace download {
+
+const uint32_t DownloadItem::kInvalidId = 0;
+
+} // namespace download
diff --git a/chromium/components/download/internal/common/rate_estimator.cc b/chromium/components/download/internal/common/rate_estimator.cc
new file mode 100644
index 00000000000..73e30ed5474
--- /dev/null
+++ b/chromium/components/download/internal/common/rate_estimator.cc
@@ -0,0 +1,121 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/rate_estimator.h"
+
+#include "base/logging.h"
+
+using base::TimeDelta;
+using base::TimeTicks;
+
+namespace download {
+
+namespace {
+
+static const int kDefaultBucketTimeSeconds = 1;
+static const size_t kDefaultNumBuckets = 10;
+
+} // namespace
+
+RateEstimator::RateEstimator()
+ : history_(kDefaultNumBuckets),
+ bucket_time_(TimeDelta::FromSeconds(kDefaultBucketTimeSeconds)),
+ oldest_index_(0),
+ bucket_count_(1) {
+ ResetBuckets(TimeTicks::Now());
+}
+
+RateEstimator::RateEstimator(TimeDelta bucket_time,
+ size_t num_buckets,
+ TimeTicks now)
+ : history_(num_buckets),
+ bucket_time_(bucket_time),
+ oldest_index_(0),
+ bucket_count_(1) {
+ DCHECK(bucket_time_.InSeconds() > 0);
+ ResetBuckets(now);
+}
+
+RateEstimator::~RateEstimator() {}
+
+void RateEstimator::Increment(uint32_t count) {
+ Increment(count, TimeTicks::Now());
+}
+
+void RateEstimator::Increment(uint32_t count, TimeTicks now) {
+ ClearOldBuckets(now);
+ int64_t seconds_since_oldest = (now - oldest_time_).InSeconds();
+ DCHECK(seconds_since_oldest >= 0);
+ int64_t delta_buckets = seconds_since_oldest / bucket_time_.InSeconds();
+ DCHECK(delta_buckets >= 0);
+ size_t index_offset = static_cast<size_t>(delta_buckets);
+ DCHECK(index_offset <= history_.size());
+ size_t current_index = (oldest_index_ + delta_buckets) % history_.size();
+ history_[current_index] += count;
+}
+
+uint64_t RateEstimator::GetCountPerSecond() const {
+ return GetCountPerSecond(TimeTicks::Now());
+}
+
+uint64_t RateEstimator::GetCountPerSecond(TimeTicks now) const {
+ const_cast<RateEstimator*>(this)->ClearOldBuckets(now);
+ // TODO(cbentzel): Support fractional seconds for active bucket?
+ // We explicitly don't check for overflow here. If it happens, unsigned
+ // arithmetic at least guarantees behavior by wrapping around. The estimate
+ // will be off, but the code will still be valid.
+ uint64_t total_count = 0;
+ for (size_t i = 0; i < bucket_count_; ++i) {
+ size_t index = (oldest_index_ + i) % history_.size();
+ total_count += history_[index];
+ }
+ return total_count / (bucket_count_ * bucket_time_.InSeconds());
+}
+
+void RateEstimator::ClearOldBuckets(TimeTicks now) {
+ int64_t seconds_since_oldest = (now - oldest_time_).InSeconds();
+
+ int64_t delta_buckets = seconds_since_oldest / bucket_time_.InSeconds();
+
+ // It's possible (although unlikely) for there to be rollover with TimeTicks.
+ // If that's the case, just reset the history.
+ if (delta_buckets < 0) {
+ ResetBuckets(now);
+ return;
+ }
+ size_t delta_index = static_cast<size_t>(delta_buckets);
+
+ // If we are within the current window, keep the existing data.
+ if (delta_index < history_.size()) {
+ bucket_count_ = delta_index + 1;
+ return;
+ }
+
+ // If it's been long enough that all history data is too stale, just
+ // clear all the buckets.
+ size_t extra_buckets = delta_index - history_.size() + 1;
+ if (extra_buckets > history_.size()) {
+ ResetBuckets(now);
+ return;
+ }
+
+ // Clear out stale buckets in the history.
+ bucket_count_ = history_.size();
+ for (size_t i = 0; i < extra_buckets; ++i) {
+ history_[oldest_index_] = 0;
+ oldest_index_ = (oldest_index_ + 1) % history_.size();
+ oldest_time_ = oldest_time_ + bucket_time_;
+ }
+}
+
+void RateEstimator::ResetBuckets(TimeTicks now) {
+ for (size_t i = 0; i < history_.size(); ++i) {
+ history_[i] = 0;
+ }
+ oldest_index_ = 0;
+ bucket_count_ = 1;
+ oldest_time_ = now;
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/common/rate_estimator_unittest.cc b/chromium/components/download/internal/common/rate_estimator_unittest.cc
new file mode 100644
index 00000000000..469018d621f
--- /dev/null
+++ b/chromium/components/download/internal/common/rate_estimator_unittest.cc
@@ -0,0 +1,58 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/rate_estimator.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::TimeDelta;
+
+namespace download {
+
+TEST(RateEstimatorTest, RateEstimator) {
+ base::TimeTicks now;
+ RateEstimator estimator(TimeDelta::FromSeconds(1), 10u, now);
+ EXPECT_EQ(0u, estimator.GetCountPerSecond(now));
+
+ estimator.Increment(50u, now);
+ EXPECT_EQ(50u, estimator.GetCountPerSecond(now));
+
+ now += TimeDelta::FromMilliseconds(800);
+ estimator.Increment(50, now);
+ EXPECT_EQ(100u, estimator.GetCountPerSecond(now));
+
+ // Advance time.
+ now += TimeDelta::FromSeconds(3);
+ EXPECT_EQ(25u, estimator.GetCountPerSecond(now));
+ estimator.Increment(60, now);
+ EXPECT_EQ(40u, estimator.GetCountPerSecond(now));
+
+ // Advance time again.
+ now += TimeDelta::FromSeconds(4);
+ EXPECT_EQ(20u, estimator.GetCountPerSecond(now));
+
+ // Advance time to the end.
+ now += TimeDelta::FromSeconds(2);
+ EXPECT_EQ(16u, estimator.GetCountPerSecond(now));
+ estimator.Increment(100, now);
+ EXPECT_EQ(26u, estimator.GetCountPerSecond(now));
+
+ // Now wrap around to the start.
+ now += TimeDelta::FromSeconds(1);
+ EXPECT_EQ(16u, estimator.GetCountPerSecond(now));
+ estimator.Increment(100, now);
+ EXPECT_EQ(26u, estimator.GetCountPerSecond(now));
+
+ // Advance far into the future.
+ now += TimeDelta::FromSeconds(40);
+ EXPECT_EQ(0u, estimator.GetCountPerSecond(now));
+ estimator.Increment(100, now);
+ EXPECT_EQ(100u, estimator.GetCountPerSecond(now));
+
+ // Pretend that there is timeticks wrap around.
+ now = base::TimeTicks();
+ EXPECT_EQ(0u, estimator.GetCountPerSecond(now));
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/in_memory_download.cc b/chromium/components/download/internal/in_memory_download.cc
deleted file mode 100644
index b1f5ed476e9..00000000000
--- a/chromium/components/download/internal/in_memory_download.cc
+++ /dev/null
@@ -1,162 +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/download/internal/in_memory_download.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/strings/string_util.h"
-#include "components/download/internal/blob_task_proxy.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_status_code.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_fetcher.h"
-#include "storage/browser/blob/blob_data_handle.h"
-#include "storage/browser/blob/blob_storage_context.h"
-
-namespace download {
-
-namespace {
-
-// Converts a string to HTTP method used by URLFetcher.
-net::URLFetcher::RequestType ToRequestType(const std::string& method) {
- // Only supports GET and POST.
- if (base::EqualsCaseInsensitiveASCII(method, "GET"))
- return net::URLFetcher::RequestType::GET;
- if (base::EqualsCaseInsensitiveASCII(method, "POST"))
- return net::URLFetcher::RequestType::POST;
-
- NOTREACHED();
- return net::URLFetcher::RequestType::GET;
-}
-
-} // namespace
-
-InMemoryDownload::InMemoryDownload(
- const std::string& guid,
- const RequestParams& request_params,
- const net::NetworkTrafficAnnotationTag& traffic_annotation,
- Delegate* delegate,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- BlobTaskProxy::BlobContextGetter blob_context_getter,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
- : guid_(guid),
- request_params_(request_params),
- traffic_annotation_(traffic_annotation),
- request_context_getter_(request_context_getter),
- blob_task_proxy_(BlobTaskProxy::Create(std::move(blob_context_getter),
- io_task_runner)),
- io_task_runner_(io_task_runner),
- state_(State::INITIAL),
- delegate_(delegate),
- bytes_downloaded_(0u),
- weak_ptr_factory_(this) {
- DCHECK(!guid_.empty());
-}
-
-InMemoryDownload::~InMemoryDownload() {
- io_task_runner_->DeleteSoon(FROM_HERE, blob_task_proxy_.release());
-}
-
-void InMemoryDownload::Start() {
- DCHECK(state_ == State::INITIAL);
- url_fetcher_ = net::URLFetcher::Create(request_params_.url,
- ToRequestType(request_params_.method),
- this, traffic_annotation_);
- url_fetcher_->SetRequestContext(request_context_getter_.get());
- url_fetcher_->SetExtraRequestHeaders(
- request_params_.request_headers.ToString());
- url_fetcher_->Start();
- state_ = State::IN_PROGRESS;
-}
-
-std::unique_ptr<storage::BlobDataHandle> InMemoryDownload::ResultAsBlob() {
- DCHECK(state_ == State::COMPLETE || state_ == State::FAILED);
- // Return a copy.
- return std::make_unique<storage::BlobDataHandle>(*blob_data_handle_);
-}
-
-void InMemoryDownload::OnURLFetchDownloadProgress(
- const net::URLFetcher* source,
- int64_t current,
- int64_t total,
- int64_t current_network_bytes) {
- bytes_downloaded_ = current;
-
- if (delegate_)
- delegate_->OnDownloadProgress(this);
-}
-
-void InMemoryDownload::OnURLFetchComplete(const net::URLFetcher* source) {
- switch (source->GetStatus().status()) {
- case net::URLRequestStatus::Status::SUCCESS:
- if (HandleResponseCode(source->GetResponseCode())) {
- SaveAsBlob();
- return;
- }
-
- state_ = State::FAILED;
- NotifyDelegateDownloadComplete();
- return;
- case net::URLRequestStatus::Status::IO_PENDING:
- return;
- case net::URLRequestStatus::Status::CANCELED:
- case net::URLRequestStatus::Status::FAILED:
- state_ = State::FAILED;
- NotifyDelegateDownloadComplete();
- break;
- }
-}
-
-bool InMemoryDownload::HandleResponseCode(int response_code) {
- switch (response_code) {
- case -1: // Non-HTTP request.
- case net::HTTP_OK:
- case net::HTTP_NON_AUTHORITATIVE_INFORMATION:
- case net::HTTP_PARTIAL_CONTENT:
- case net::HTTP_CREATED:
- case net::HTTP_ACCEPTED:
- case net::HTTP_NO_CONTENT:
- case net::HTTP_RESET_CONTENT:
- return true;
- // All other codes are considered as failed.
- default:
- return false;
- }
-}
-
-void InMemoryDownload::SaveAsBlob() {
- DCHECK(url_fetcher_);
-
- // This will copy the internal memory in |url_fetcher| into |data|.
- // TODO(xingliu): Use response writer to avoid one extra copies. And destroy
- // |url_fetcher_| at the correct time.
- std::unique_ptr<std::string> data = std::make_unique<std::string>();
- url_fetcher_->GetResponseAsString(data.get());
-
- auto callback = base::BindOnce(&InMemoryDownload::OnSaveBlobDone,
- weak_ptr_factory_.GetWeakPtr());
- blob_task_proxy_->SaveAsBlob(std::move(data), std::move(callback));
-}
-
-void InMemoryDownload::OnSaveBlobDone(
- std::unique_ptr<storage::BlobDataHandle> blob_handle,
- storage::BlobStatus status) {
- // |status| is valid on IO thread, consumer of |blob_handle| should validate
- // the data when using the blob data.
- state_ =
- (status == storage::BlobStatus::DONE) ? State::COMPLETE : State::FAILED;
- blob_data_handle_ = std::move(blob_handle);
-
- NotifyDelegateDownloadComplete();
-}
-
-void InMemoryDownload::NotifyDelegateDownloadComplete() {
- if (delegate_)
- delegate_->OnDownloadComplete(this);
-}
-
-} // namespace download
diff --git a/chromium/components/download/internal/in_memory_download_unittest.cc b/chromium/components/download/internal/in_memory_download_unittest.cc
deleted file mode 100644
index dce0b15776c..00000000000
--- a/chromium/components/download/internal/in_memory_download_unittest.cc
+++ /dev/null
@@ -1,127 +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/download/internal/in_memory_download.h"
-
-#include "base/files/file_util.h"
-#include "base/guid.h"
-#include "base/path_service.h"
-#include "base/run_loop.h"
-#include "base/threading/thread.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/url_request_test_util.h"
-#include "storage/browser/blob/blob_storage_context.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace download {
-namespace {
-
-class MockDelegate : public InMemoryDownload::Delegate {
- public:
- MockDelegate() = default;
-
- void WaitForCompletion() {
- DCHECK(!run_loop_.running());
- run_loop_.Run();
- }
-
- // InMemoryDownload::Delegate implementation.
- MOCK_METHOD1(OnDownloadProgress, void(InMemoryDownload*));
- void OnDownloadComplete(InMemoryDownload* download) {
- if (run_loop_.running())
- run_loop_.Quit();
- }
-
- private:
- base::RunLoop run_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(MockDelegate);
-};
-
-// Must run on IO thread task runner.
-base::WeakPtr<storage::BlobStorageContext> BlobStorageContextGetter(
- storage::BlobStorageContext* blob_context) {
- DCHECK(blob_context);
- return blob_context->AsWeakPtr();
-}
-
-class InMemoryDownloadTest : public testing::Test {
- public:
- InMemoryDownloadTest() = default;
- ~InMemoryDownloadTest() override = default;
-
- void SetUp() override {
- test_server_.ServeFilesFromDirectory(GetTestDataDirectory());
- ASSERT_TRUE(test_server_.Start());
-
- io_thread_.reset(new base::Thread("Network and Blob IO thread"));
- base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
- io_thread_->StartWithOptions(options);
- request_context_getter_ =
- new net::TestURLRequestContextGetter(io_thread_->task_runner());
- blob_storage_context_ = std::make_unique<storage::BlobStorageContext>();
- }
-
- void TearDown() override {
- // Say goodbye to |blob_storage_context_| on IO thread.
- io_thread_->task_runner()->DeleteSoon(FROM_HERE,
- blob_storage_context_.release());
- }
-
- protected:
- base::FilePath GetTestDataDirectory() {
- base::FilePath test_data_dir;
- EXPECT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir));
- return test_data_dir.AppendASCII("components/test/data/download");
- }
-
- // Helper method to create a download with request_params.
- void CreateDownload(const RequestParams& request_params) {
- download_ = std::make_unique<InMemoryDownload>(
- base::GenerateGUID(), request_params, TRAFFIC_ANNOTATION_FOR_TESTS,
- delegate(), request_context_getter_,
- base::BindOnce(&BlobStorageContextGetter, blob_storage_context_.get()),
- io_thread_->task_runner());
- }
-
- InMemoryDownload* download() { return download_.get(); }
- MockDelegate* delegate() { return &mock_delegate_; }
- net::EmbeddedTestServer* test_server() { return &test_server_; }
-
- private:
- // IO thread used by network and blob IO tasks.
- std::unique_ptr<base::Thread> io_thread_;
-
- // Message loop for the main thread.
- base::MessageLoop main_loop;
-
- std::unique_ptr<InMemoryDownload> download_;
- MockDelegate mock_delegate_;
-
- scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
- std::unique_ptr<storage::BlobStorageContext> blob_storage_context_;
- net::EmbeddedTestServer test_server_;
-
- DISALLOW_COPY_AND_ASSIGN(InMemoryDownloadTest);
-};
-
-TEST_F(InMemoryDownloadTest, DownloadTest) {
- RequestParams request_params;
- request_params.url = test_server()->GetURL("/text_data.json");
- CreateDownload(request_params);
- download()->Start();
- delegate()->WaitForCompletion();
-
- base::FilePath path = GetTestDataDirectory().AppendASCII("text_data.json");
- std::string data;
- EXPECT_TRUE(ReadFileToString(path, &data));
- EXPECT_EQ(InMemoryDownload::State::COMPLETE, download()->state());
- // TODO(xingliu): Read the blob and verify data.
-}
-
-} // namespace
-
-} // namespace download
diff --git a/chromium/components/download/public/BUILD.gn b/chromium/components/download/public/background_service/BUILD.gn
index 3543a1ac0e6..3543a1ac0e6 100644
--- a/chromium/components/download/public/BUILD.gn
+++ b/chromium/components/download/public/background_service/BUILD.gn
diff --git a/chromium/components/download/public/DEPS b/chromium/components/download/public/background_service/DEPS
index 6b96427e999..6b96427e999 100644
--- a/chromium/components/download/public/DEPS
+++ b/chromium/components/download/public/background_service/DEPS
diff --git a/chromium/components/download/public/client.h b/chromium/components/download/public/background_service/client.h
index beb929695d3..8f0e6bccc62 100644
--- a/chromium/components/download/public/client.h
+++ b/chromium/components/download/public/background_service/client.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_PUBLIC_CLIENT_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_CLIENT_H_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_CLIENT_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_CLIENT_H_
#include <string>
#include <vector>
@@ -120,4 +120,4 @@ class Client {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_CLIENT_H_
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_CLIENT_H_
diff --git a/chromium/components/download/public/clients.h b/chromium/components/download/public/background_service/clients.h
index 62f1123dded..f678bb9f232 100644
--- a/chromium/components/download/public/clients.h
+++ b/chromium/components/download/public/background_service/clients.h
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_PUBLIC_CLIENTS_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_CLIENTS_H_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_CLIENTS_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_CLIENTS_H_
#include <map>
#include <memory>
-#include "components/download/public/client.h"
+#include "components/download/public/background_service/client.h"
namespace download {
@@ -44,4 +44,4 @@ using DownloadClientMap = std::map<DownloadClient, std::unique_ptr<Client>>;
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_CLIENTS_H_
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_CLIENTS_H_
diff --git a/chromium/components/download/public/download_metadata.cc b/chromium/components/download/public/background_service/download_metadata.cc
index c5eb929a604..6cbe49311e4 100644
--- a/chromium/components/download/public/download_metadata.cc
+++ b/chromium/components/download/public/background_service/download_metadata.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/download/public/download_metadata.h"
+#include "components/download/public/background_service/download_metadata.h"
namespace download {
diff --git a/chromium/components/download/public/download_metadata.h b/chromium/components/download/public/background_service/download_metadata.h
index bcf01a87f9b..26f8547eb93 100644
--- a/chromium/components/download/public/download_metadata.h
+++ b/chromium/components/download/public/background_service/download_metadata.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_PUBLIC_DOWNLOAD_METADATA_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_METADATA_H_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_DOWNLOAD_METADATA_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_DOWNLOAD_METADATA_H_
#include "base/files/file_path.h"
#include "base/optional.h"
@@ -41,4 +41,4 @@ struct DownloadMetaData {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_METADATA_H_
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_DOWNLOAD_METADATA_H_
diff --git a/chromium/components/download/public/download_params.cc b/chromium/components/download/public/background_service/download_params.cc
index f5279a37b83..d5c123846c1 100644
--- a/chromium/components/download/public/download_params.cc
+++ b/chromium/components/download/public/background_service/download_params.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/public/download_params.h"
+#include "components/download/public/background_service/download_params.h"
-#include "components/download/public/clients.h"
+#include "components/download/public/background_service/clients.h"
namespace download {
diff --git a/chromium/components/download/public/download_params.h b/chromium/components/download/public/background_service/download_params.h
index 851de6dd422..aadde2f4b4b 100644
--- a/chromium/components/download/public/download_params.h
+++ b/chromium/components/download/public/background_service/download_params.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_DOWNLOAD_PUBLIC_DOWNLOAD_PARAMS_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_PARAMS_H_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_DOWNLOAD_PARAMS_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_DOWNLOAD_PARAMS_H_
#include "base/callback.h"
#include "base/time/time.h"
-#include "components/download/public/clients.h"
+#include "components/download/public/background_service/clients.h"
#include "net/http/http_request_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "url/gurl.h"
@@ -168,4 +168,4 @@ struct DownloadParams {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_PARAMS_H_
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_DOWNLOAD_PARAMS_H_
diff --git a/chromium/components/download/public/download_service.h b/chromium/components/download/public/background_service/download_service.h
index 2de7add5f6d..0d240ab21fd 100644
--- a/chromium/components/download/public/download_service.h
+++ b/chromium/components/download/public/background_service/download_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_DOWNLOAD_PUBLIC_DOWNLOAD_SERVICE_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_SERVICE_H_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_DOWNLOAD_SERVICE_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_DOWNLOAD_SERVICE_H_
#include <memory>
#include <string>
@@ -13,8 +13,8 @@
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
-#include "components/download/public/clients.h"
-#include "components/download/public/download_task_types.h"
+#include "components/download/public/background_service/clients.h"
+#include "components/download/public/background_service/download_task_types.h"
#include "components/keyed_service/core/keyed_service.h"
namespace download {
@@ -109,4 +109,4 @@ class DownloadService : public KeyedService {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_SERVICE_H_
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_DOWNLOAD_SERVICE_H_
diff --git a/chromium/components/download/public/download_task_types.h b/chromium/components/download/public/background_service/download_task_types.h
index a26bc013743..48fcfb35f9e 100644
--- a/chromium/components/download/public/download_task_types.h
+++ b/chromium/components/download/public/background_service/download_task_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_DOWNLOAD_PUBLIC_DOWNLOAD_TASK_TYPES_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_TASK_TYPES_H_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_DOWNLOAD_TASK_TYPES_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_DOWNLOAD_TASK_TYPES_H_
namespace download {
@@ -19,4 +19,4 @@ enum class DownloadTaskType {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_TASK_TYPES_H_
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_DOWNLOAD_TASK_TYPES_H_
diff --git a/chromium/components/download/public/features.cc b/chromium/components/download/public/background_service/features.cc
index f254f230c99..622393d54cb 100644
--- a/chromium/components/download/public/features.cc
+++ b/chromium/components/download/public/background_service/features.cc
@@ -2,11 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/download/public/features.h"
+#include "components/download/public/background_service/features.h"
namespace download {
const base::Feature kDownloadServiceFeature{"DownloadService",
base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kDownloadServiceIncognito{
+ "DownloadServiceIncognito", base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace download
diff --git a/chromium/components/download/public/background_service/features.h b/chromium/components/download/public/background_service/features.h
new file mode 100644
index 00000000000..959f3afa500
--- /dev/null
+++ b/chromium/components/download/public/background_service/features.h
@@ -0,0 +1,20 @@
+// 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_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_FEATURES_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace download {
+
+extern const base::Feature kDownloadServiceFeature;
+
+// Incognito support of download service. No database or file IO is allowed if
+// this feature is enabled. The download data will be saved to blob.
+extern const base::Feature kDownloadServiceIncognito;
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_FEATURES_H_
diff --git a/chromium/components/download/public/logger.h b/chromium/components/download/public/background_service/logger.h
index a3b57deb402..cc9aa3036b8 100644
--- a/chromium/components/download/public/logger.h
+++ b/chromium/components/download/public/background_service/logger.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_PUBLIC_LOGGER_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_LOGGER_H_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_LOGGER_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_LOGGER_H_
#include <memory>
@@ -99,4 +99,4 @@ class Logger {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_LOGGER_H_
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_LOGGER_H_
diff --git a/chromium/components/download/public/navigation_monitor.h b/chromium/components/download/public/background_service/navigation_monitor.h
index 5d8e065bf6e..329c10a2383 100644
--- a/chromium/components/download/public/navigation_monitor.h
+++ b/chromium/components/download/public/background_service/navigation_monitor.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_PUBLIC_NAVIGATION_MONITOR_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_NAVIGATION_MONITOR_H_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_NAVIGATION_MONITOR_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_NAVIGATION_MONITOR_H_
#include "base/time/time.h"
#include "components/keyed_service/core/keyed_service.h"
@@ -58,4 +58,4 @@ class NavigationMonitor : public KeyedService {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_NAVIGATION_MONITOR_H_
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_NAVIGATION_MONITOR_H_
diff --git a/chromium/components/download/public/service_config.h b/chromium/components/download/public/background_service/service_config.h
index 4b636c47618..8a8c85eb073 100644
--- a/chromium/components/download/public/service_config.h
+++ b/chromium/components/download/public/background_service/service_config.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_PUBLIC_SERVICE_CONFIG_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_SERVICE_CONFIG_H_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_SERVICE_CONFIG_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_SERVICE_CONFIG_H_
#include <stdint.h>
@@ -38,4 +38,4 @@ class ServiceConfig {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_SERVICE_CONFIG_H_
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_SERVICE_CONFIG_H_
diff --git a/chromium/components/download/public/task_scheduler.h b/chromium/components/download/public/background_service/task_scheduler.h
index 11fb917323e..26afbf49699 100644
--- a/chromium/components/download/public/task_scheduler.h
+++ b/chromium/components/download/public/background_service/task_scheduler.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOWNLOAD_PUBLIC_TASK_SCHEDULER_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_TASK_SCHEDULER_H_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_TASK_SCHEDULER_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_TASK_SCHEDULER_H_
-#include "components/download/public/download_task_types.h"
+#include "components/download/public/background_service/download_task_types.h"
namespace download {
@@ -34,4 +34,4 @@ class TaskScheduler {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_TASK_SCHEDULER_H_
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_TASK_SCHEDULER_H_
diff --git a/chromium/components/download/public/test/BUILD.gn b/chromium/components/download/public/background_service/test/BUILD.gn
index 9aa28f499f0..39bfe9bb7d3 100644
--- a/chromium/components/download/public/test/BUILD.gn
+++ b/chromium/components/download/public/background_service/test/BUILD.gn
@@ -25,7 +25,7 @@ source_set("test_support") {
public_deps = [
"//base",
- "//components/download/public",
+ "//components/download/public/background_service:public",
"//testing/gmock",
]
}
diff --git a/chromium/components/download/public/common/BUILD.gn b/chromium/components/download/public/common/BUILD.gn
new file mode 100644
index 00000000000..a4fcd5c24f8
--- /dev/null
+++ b/chromium/components/download/public/common/BUILD.gn
@@ -0,0 +1,87 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+if (is_android) {
+ import("//build/config/android/config.gni")
+ import("//build/config/android/rules.gni") # For generate_jni().
+}
+
+config("components_download_implementation") {
+ defines = [ "COMPONENTS_DOWNLOAD_IMPLEMENTATION" ]
+}
+
+component("public") {
+ sources = [
+ "download_content.h",
+ "download_create_info.h",
+ "download_danger_type.h",
+ "download_interrupt_reason_values.h",
+ "download_interrupt_reasons.h",
+ "download_item.h",
+ "download_request_handle_interface.h",
+ "download_save_info.cc",
+ "download_save_info.h",
+ "download_source.h",
+ "download_stats.h",
+ "download_task_runner.h",
+ "download_ukm_helper.h",
+ "download_url_parameters.cc",
+ "download_url_parameters.h",
+ "rate_estimator.h",
+ "resume_mode.h",
+ ]
+
+ configs += [ ":components_download_implementation" ]
+
+ public_deps = [
+ ":interfaces",
+ ]
+
+ deps = [
+ "//base",
+ "//components/download/internal/common:internal",
+ "//crypto",
+ "//net",
+ "//services/metrics/public/cpp:metrics_cpp",
+ "//services/network/public/cpp",
+ "//storage/browser",
+ "//ui/base",
+ ]
+
+ allow_circular_includes_from =
+ [ "//components/download/internal/common:internal" ]
+}
+
+if (is_android) {
+ android_library("public_java") {
+ srcjar_deps = [ ":jni_enums" ]
+
+ deps = [
+ "//base:base_java",
+ "//third_party/android_tools:android_support_annotations_java",
+ ]
+ }
+
+ java_cpp_enum("jni_enums") {
+ sources = [
+ "download_item.h",
+ ]
+ }
+}
+
+mojom("interfaces") {
+ sources = [
+ "download_stream.mojom",
+ ]
+
+ public_deps = [
+ "//mojo/common:common_custom_types",
+ ]
+
+ export_class_attribute = "COMPONENTS_DOWNLOAD_EXPORT"
+ export_define = "COMPONENTS_DOWNLOAD_IMPLEMENTATION=1"
+ export_header = "components/download/public/common/download_export.h"
+}
diff --git a/chromium/components/download/public/common/DEPS b/chromium/components/download/public/common/DEPS
new file mode 100644
index 00000000000..044a6af430f
--- /dev/null
+++ b/chromium/components/download/public/common/DEPS
@@ -0,0 +1,12 @@
+include_rules = [
+ "+crypto",
+ "+net/http/http_response_info.h",
+ "+net/url_request/url_request.h",
+ # TODO(qinmin): remove this once network service is enabled.
+ "+net/url_request/url_request_context_getter.h",
+ "+net/traffic_annotation/network_traffic_annotation.h",
+ "+services/metrics/public/cpp",
+ "+services/network/public/cpp",
+ "+storage/browser",
+ "+ui/base",
+]
diff --git a/chromium/components/download/public/common/OWNERS b/chromium/components/download/public/common/OWNERS
new file mode 100644
index 00000000000..61b5e28552a
--- /dev/null
+++ b/chromium/components/download/public/common/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/chromium/components/download/public/common/download_content.h b/chromium/components/download/public/common/download_content.h
new file mode 100644
index 00000000000..c88ffb0e690
--- /dev/null
+++ b/chromium/components/download/public/common/download_content.h
@@ -0,0 +1,38 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_DOWNLOAD_CONTENT_H_
+#define COMPONENTS_DOWNLOAD_DOWNLOAD_CONTENT_H_
+
+// The type of download based on mimetype.
+// This is used by UMA and UKM metrics.
+namespace download {
+
+// NOTE: Keep in sync with DownloadContentType in
+// tools/metrics/histograms/enums.xml.
+enum class DownloadContent {
+ UNRECOGNIZED = 0,
+ TEXT = 1,
+ IMAGE = 2,
+ AUDIO = 3,
+ VIDEO = 4,
+ OCTET_STREAM = 5,
+ PDF = 6,
+ DOCUMENT = 7,
+ SPREADSHEET = 8,
+ PRESENTATION = 9,
+ ARCHIVE = 10,
+ EXECUTABLE = 11,
+ DMG = 12,
+ CRX = 13,
+ WEB = 14,
+ EBOOK = 15,
+ FONT = 16,
+ APK = 17,
+ MAX = 18,
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_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
new file mode 100644
index 00000000000..c17299f6128
--- /dev/null
+++ b/chromium/components/download/public/common/download_create_info.h
@@ -0,0 +1,170 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_CREATE_INFO_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_CREATE_INFO_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#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"
+#include "components/download/public/common/download_item.h"
+#include "components/download/public/common/download_request_handle_interface.h"
+#include "components/download/public/common/download_save_info.h"
+#include "components/download/public/common/download_source.h"
+#include "net/http/http_response_info.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "ui/base/page_transition_types.h"
+#include "url/gurl.h"
+
+namespace net {
+class HttpResponseHeaders;
+}
+
+namespace download {
+
+// Used for informing the download manager of a new download, since we don't
+// want to pass |DownloadItem|s between threads.
+struct COMPONENTS_DOWNLOAD_EXPORT DownloadCreateInfo {
+ DownloadCreateInfo(const base::Time& start_time,
+ std::unique_ptr<DownloadSaveInfo> save_info);
+ DownloadCreateInfo();
+ ~DownloadCreateInfo();
+
+ // The URL from which we are downloading. This is the final URL after any
+ // redirection by the server for |url_chain|.
+ const GURL& url() const;
+
+ // The ID of the download. (Deprecated)
+ uint32_t download_id;
+
+ // The unique identifier for the download.
+ std::string guid;
+
+ // The chain of redirects that leading up to and including the final URL.
+ std::vector<GURL> url_chain;
+
+ // The URL that referred us.
+ GURL referrer_url;
+
+ // Site URL for the site instance that initiated the download.
+ GURL site_url;
+
+ // The URL of the tab that started us.
+ GURL tab_url;
+
+ // The referrer URL of the tab that started us.
+ GURL tab_referrer_url;
+
+ // The time when the download started.
+ base::Time start_time;
+
+ // The size of the response body. If content-length response header is not
+ // presented or can't be parse, set to 0.
+ int64_t total_bytes;
+
+ // The starting position of the initial request.
+ // This value matches the offset in DownloadSaveInfo.
+ // TODO(xingliu): Refactor to remove |offset| and |length|.
+ int64_t offset;
+
+ // True if the download was initiated by user action.
+ bool has_user_gesture;
+
+ // Whether the download should be transient. A transient download is
+ // short-lived and is not shown in the UI.
+ bool transient;
+
+ base::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.
+ scoped_refptr<const net::HttpResponseHeaders> response_headers;
+
+ // The remote IP address where the download was fetched from. Copied from
+ // UrlRequest::GetSocketAddress().
+ std::string remote_address;
+
+ // If the download is initially created in an interrupted state (because the
+ // response was in error), then |result| would be something other than
+ // INTERRUPT_REASON_NONE.
+ DownloadInterruptReason result;
+
+ // The download file save info.
+ std::unique_ptr<DownloadSaveInfo> save_info;
+
+ // The render process id that initiates this download.
+ int render_process_id;
+
+ // The render frame id that initiates this download.
+ int render_frame_id;
+
+ // The handle to the URLRequest sourcing this download.
+ // TODO(qinmin): remove this when network service is fully enabled.
+ std::unique_ptr<DownloadRequestHandleInterface> request_handle;
+
+ // ---------------------------------------------------------------------------
+ // The remaining fields are Entity-body properties. These are only set if
+ // |result| is DOWNLOAD_INTERRUPT_REASON_NONE.
+ // ---------------------------------------------------------------------------
+
+ // The content-disposition string from the response header.
+ std::string content_disposition;
+
+ // The mime type string from the response header (may be overridden).
+ std::string mime_type;
+
+ // The value of the content type header sent with the downloaded item. It
+ // may be different from |mime_type|, which may be set based on heuristics
+ // which may look at the file extension and first few bytes of the file.
+ std::string original_mime_type;
+
+ // For continuing a download, the modification time of the file.
+ // Storing as a string for exact match to server format on
+ // "If-Unmodified-Since" comparison.
+ std::string last_modified;
+
+ // For continuing a download, the ETag of the file.
+ std::string etag;
+
+ // If the download response can be partial content.
+ // Either "Accept-Ranges" or "Content-Range" header presents in the
+ // response header.
+ bool accept_range;
+
+ // The HTTP connection type.
+ net::HttpResponseInfo::ConnectionInfo connection_info;
+
+ // The HTTP request method.
+ std::string method;
+
+ // Whether the download should fetch the response body for non successful HTTP
+ // response.
+ bool fetch_error_body = false;
+
+ // Source ID generated for UKM.
+ ukm::SourceId ukm_source_id;
+
+ // For downloads originating from custom tabs, this records the origin
+ // of the custom tab.
+ std::string request_origin;
+
+ // Source of the download, used in metrics.
+ DownloadSource download_source = DownloadSource::UNKNOWN;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DownloadCreateInfo);
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_CREATE_INFO_H_
diff --git a/chromium/components/download/public/common/download_danger_type.h b/chromium/components/download/public/common/download_danger_type.h
new file mode 100644
index 00000000000..c97bd08eebc
--- /dev/null
+++ b/chromium/components/download/public/common/download_danger_type.h
@@ -0,0 +1,54 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_DANGER_TYPE_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_DANGER_TYPE_H_
+
+namespace download {
+
+// This enum is also used by histograms. Do not change the ordering or remove
+// items.
+enum DownloadDangerType {
+ // The download is safe.
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS = 0,
+
+ // A dangerous file to the system (e.g.: a pdf or extension from
+ // places other than gallery).
+ DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
+
+ // Safebrowsing download service shows this URL leads to malicious file
+ // download.
+ DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
+
+ // SafeBrowsing download service shows this file content as being malicious.
+ DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT,
+
+ // The content of this download may be malicious (e.g., extension is exe but
+ // SafeBrowsing has not finished checking the content).
+ DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
+
+ // SafeBrowsing download service checked the contents of the download, but
+ // didn't have enough data to determine whether it was malicious.
+ DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT,
+
+ // The download was evaluated to be one of the other types of danger,
+ // but the user told us to go ahead anyway.
+ DOWNLOAD_DANGER_TYPE_USER_VALIDATED,
+
+ // SafeBrowsing download service checked the contents of the download and
+ // didn't have data on this specific file, but the file was served from a host
+ // known to serve mostly malicious content.
+ DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST,
+
+ // Applications and extensions that modify browser and/or computer settings
+ DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED,
+
+ // Memory space for histograms is determined by the max.
+ // ALWAYS ADD NEW VALUES BEFORE THIS ONE.
+ DOWNLOAD_DANGER_TYPE_MAX
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_DANGER_TYPE_H_
diff --git a/chromium/components/download/public/common/download_export.h b/chromium/components/download/public/common/download_export.h
new file mode 100644
index 00000000000..aa74da80b52
--- /dev/null
+++ b/chromium/components/download/public/common/download_export.h
@@ -0,0 +1,29 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_EXPORT_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(COMPONENTS_DOWNLOAD_IMPLEMENTATION)
+#define COMPONENTS_DOWNLOAD_EXPORT __declspec(dllexport)
+#else
+#define COMPONENTS_DOWNLOAD_EXPORT __declspec(dllimport)
+#endif // defined(COMPONENTS_DOWNLOAD_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#if defined(COMPONENTS_DOWNLOAD_IMPLEMENTATION)
+#define COMPONENTS_DOWNLOAD_EXPORT __attribute__((visibility("default")))
+#else
+#define COMPONENTS_DOWNLOAD_EXPORT
+#endif
+#endif
+
+#else // defined(COMPONENT_BUILD)
+#define COMPONENTS_DOWNLOAD_EXPORT
+#endif
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_EXPORT_H_
diff --git a/chromium/components/download/public/common/download_interrupt_reason_values.h b/chromium/components/download/public/common/download_interrupt_reason_values.h
new file mode 100644
index 00000000000..02cd84e1aac
--- /dev/null
+++ b/chromium/components/download/public/common/download_interrupt_reason_values.h
@@ -0,0 +1,139 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Note that the embedder is welcome to persist these values across
+// invocations of the browser, and possibly across browser versions.
+// Thus individual errors may be deprecated and new errors added, but
+// the values of particular errors should not be changed.
+
+// File errors.
+
+// Generic file operation failure.
+// "File Error".
+INTERRUPT_REASON(FILE_FAILED, 1)
+
+// The file cannot be accessed due to security restrictions.
+// "Access Denied".
+INTERRUPT_REASON(FILE_ACCESS_DENIED, 2)
+
+// There is not enough room on the drive.
+// "Disk Full".
+INTERRUPT_REASON(FILE_NO_SPACE, 3)
+
+// The directory or file name is too long.
+// "Path Too Long".
+INTERRUPT_REASON(FILE_NAME_TOO_LONG, 5)
+
+// The file is too large for the file system to handle.
+// "File Too Large".
+INTERRUPT_REASON(FILE_TOO_LARGE, 6)
+
+// The file contains a virus.
+// "Virus".
+INTERRUPT_REASON(FILE_VIRUS_INFECTED, 7)
+
+// The file was in use.
+// Too many files are opened at once.
+// We have run out of memory.
+// "Temporary Problem".
+INTERRUPT_REASON(FILE_TRANSIENT_ERROR, 10)
+
+// The file was blocked due to local policy.
+// "Blocked"
+INTERRUPT_REASON(FILE_BLOCKED, 11)
+
+// An attempt to check the safety of the download failed due to unexpected
+// reasons. See http://crbug.com/153212.
+INTERRUPT_REASON(FILE_SECURITY_CHECK_FAILED, 12)
+
+// An attempt was made to seek past the end of a file in opening
+// a file (as part of resuming a previously interrupted download).
+INTERRUPT_REASON(FILE_TOO_SHORT, 13)
+
+// The partial file didn't match the expected hash.
+INTERRUPT_REASON(FILE_HASH_MISMATCH, 14)
+
+// The source and the target of the download were the same.
+INTERRUPT_REASON(FILE_SAME_AS_SOURCE, 15)
+
+// Network errors.
+
+// Generic network failure.
+// "Network Error".
+INTERRUPT_REASON(NETWORK_FAILED, 20)
+
+// The network operation timed out.
+// "Operation Timed Out".
+INTERRUPT_REASON(NETWORK_TIMEOUT, 21)
+
+// The network connection has been lost.
+// "Connection Lost".
+INTERRUPT_REASON(NETWORK_DISCONNECTED, 22)
+
+// The server has gone down.
+// "Server Down".
+INTERRUPT_REASON(NETWORK_SERVER_DOWN, 23)
+
+// The network request was invalid. This may be due to the original URL or a
+// redirected URL:
+// - Having an unsupported scheme.
+// - Being an invalid URL.
+// - Being disallowed by policy.
+INTERRUPT_REASON(NETWORK_INVALID_REQUEST, 24)
+
+// Server responses.
+
+// The server indicates that the operation has failed (generic).
+// "Server Error".
+INTERRUPT_REASON(SERVER_FAILED, 30)
+
+// The server does not support range requests.
+// Internal use only: must restart from the beginning.
+INTERRUPT_REASON(SERVER_NO_RANGE, 31)
+
+// Precondition failed. This type of interruption could legitimately occur if a
+// partial download resumption was attempted using a If-Match header. However,
+// the downloads logic no longer uses If-Match headers and instead uses If-Range
+// headers where a precondition failure is not expected.
+//
+// Obsolete: INTERRUPT_REASON(SERVER_PRECONDITION, 32)
+
+// The server does not have the requested data.
+// "Unable to get file".
+INTERRUPT_REASON(SERVER_BAD_CONTENT, 33)
+
+// Server didn't authorize access to resource.
+INTERRUPT_REASON(SERVER_UNAUTHORIZED, 34)
+
+// Server certificate problem.
+INTERRUPT_REASON(SERVER_CERT_PROBLEM, 35)
+
+// Server access forbidden.
+INTERRUPT_REASON(SERVER_FORBIDDEN, 36)
+
+// Unexpected server response. This might indicate that the responding server
+// may not be the intended server.
+INTERRUPT_REASON(SERVER_UNREACHABLE, 37)
+
+// The server sent fewer bytes than the content-length header. It may indicate
+// that the connection was closed prematurely, or the Content-Length header was
+// invalid. The download is only interrupted if strong validators are present.
+// Otherwise, it is treated as finished.
+INTERRUPT_REASON(SERVER_CONTENT_LENGTH_MISMATCH, 38)
+
+// User input.
+
+// The user canceled the download.
+// "Canceled".
+INTERRUPT_REASON(USER_CANCELED, 40)
+
+// The user shut down the browser.
+// Internal use only: resume pending downloads if possible.
+INTERRUPT_REASON(USER_SHUTDOWN, 41)
+
+// Crash.
+
+// The browser crashed.
+// Internal use only: resume pending downloads if possible.
+INTERRUPT_REASON(CRASH, 50)
diff --git a/chromium/components/download/public/common/download_interrupt_reasons.h b/chromium/components/download/public/common/download_interrupt_reasons.h
new file mode 100644
index 00000000000..b95e39ea17d
--- /dev/null
+++ b/chromium/components/download/public/common/download_interrupt_reasons.h
@@ -0,0 +1,29 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_INTERRUPT_REASONS_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_INTERRUPT_REASONS_H_
+
+#include <string>
+
+#include "components/download/public/common/download_export.h"
+
+namespace download {
+
+enum DownloadInterruptReason {
+ DOWNLOAD_INTERRUPT_REASON_NONE = 0,
+
+#define INTERRUPT_REASON(name, value) DOWNLOAD_INTERRUPT_REASON_##name = value,
+
+#include "components/download/public/common/download_interrupt_reason_values.h"
+
+#undef INTERRUPT_REASON
+};
+
+std::string COMPONENTS_DOWNLOAD_EXPORT
+DownloadInterruptReasonToString(DownloadInterruptReason error);
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_INTERRUPT_REASONS_H_
diff --git a/chromium/components/download/public/common/download_item.h b/chromium/components/download/public/common/download_item.h
new file mode 100644
index 00000000000..d5face7905e
--- /dev/null
+++ b/chromium/components/download/public/common/download_item.h
@@ -0,0 +1,464 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Each download is represented by a DownloadItem, and all DownloadItems
+// are owned by the DownloadManager which maintains a global list of all
+// downloads. DownloadItems are created when a user initiates a download,
+// and exist for the duration of the browser life time.
+//
+// Download observers:
+// DownloadItem::Observer:
+// - allows observers to receive notifications about one download from start
+// to completion
+// Use AddObserver() / RemoveObserver() on the appropriate download object to
+// receive state updates.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_ITEM_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_ITEM_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/string16.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 "ui/base/page_transition_types.h"
+
+class GURL;
+
+namespace base {
+class FilePath;
+class Time;
+class TimeDelta;
+} // namespace base
+
+namespace net {
+class HttpResponseHeaders;
+}
+
+namespace download {
+
+// One DownloadItem per download. This is the model class that stores all the
+// state for a download.
+class COMPONENTS_DOWNLOAD_EXPORT DownloadItem : public base::SupportsUserData {
+ public:
+ // A Java counterpart will be generated for this enum.
+ // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.download
+ enum DownloadState {
+ // Download is actively progressing.
+ IN_PROGRESS = 0,
+
+ // Download is completely finished.
+ COMPLETE,
+
+ // Download has been cancelled.
+ CANCELLED,
+
+ // This state indicates that the download has been interrupted.
+ INTERRUPTED,
+
+ // Maximum value.
+ MAX_DOWNLOAD_STATE
+ };
+
+ // How the final target path should be used.
+ enum TargetDisposition {
+ TARGET_DISPOSITION_OVERWRITE, // Overwrite if the target already exists.
+ TARGET_DISPOSITION_PROMPT // Prompt the user for the actual
+ // target. Implies
+ // TARGET_DISPOSITION_OVERWRITE.
+ };
+
+ // How download item is created. Used for trace event.
+ enum DownloadType {
+ TYPE_ACTIVE_DOWNLOAD,
+ TYPE_HISTORY_IMPORT,
+ TYPE_SAVE_PAGE_AS
+ };
+
+ // Callback used with AcquireFileAndDeleteDownload().
+ typedef base::Callback<void(const base::FilePath&)> AcquireFileCallback;
+
+ // Used to represent an invalid download ID.
+ static const uint32_t kInvalidId;
+
+ // Interface that observers of a particular download must implement in order
+ // to receive updates to the download's status.
+ class COMPONENTS_DOWNLOAD_EXPORT Observer {
+ public:
+ virtual void OnDownloadUpdated(DownloadItem* download) {}
+ virtual void OnDownloadOpened(DownloadItem* download) {}
+ virtual void OnDownloadRemoved(DownloadItem* download) {}
+
+ // Called when the download is being destroyed. This happens after
+ // every OnDownloadRemoved() as well as when the DownloadManager is going
+ // down.
+ virtual void OnDownloadDestroyed(DownloadItem* download) {}
+
+ virtual ~Observer() {}
+ };
+
+ // A slice of the target file that has been received so far, used when
+ // parallel downloading is enabled. Slices should have different offsets
+ // so that they don't overlap. |finished| will be marked as true when the
+ // download stream is successfully completed.
+ struct COMPONENTS_DOWNLOAD_EXPORT ReceivedSlice {
+ ReceivedSlice(int64_t offset, int64_t received_bytes)
+ : offset(offset), received_bytes(received_bytes), finished(false) {}
+
+ ReceivedSlice(int64_t offset, int64_t received_bytes, bool finished)
+ : offset(offset), received_bytes(received_bytes), finished(finished) {}
+
+ bool operator==(const ReceivedSlice& rhs) const {
+ return offset == rhs.offset && received_bytes == rhs.received_bytes &&
+ finished == rhs.finished;
+ }
+
+ int64_t offset;
+ int64_t received_bytes;
+ bool finished;
+ };
+
+ using ReceivedSlices = std::vector<DownloadItem::ReceivedSlice>;
+
+ ~DownloadItem() override {}
+
+ // Observation ---------------------------------------------------------------
+
+ virtual void AddObserver(DownloadItem::Observer* observer) = 0;
+ virtual void RemoveObserver(DownloadItem::Observer* observer) = 0;
+ virtual void UpdateObservers() = 0;
+
+ // User Actions --------------------------------------------------------------
+
+ // Called when the user has validated the download of a dangerous file.
+ virtual void ValidateDangerousDownload() = 0;
+
+ // Called to acquire a dangerous download. If |delete_file_afterward| is true,
+ // invokes |callback| on the UI thread with the path to the downloaded file,
+ // and removes the DownloadItem from views and history if appropriate.
+ // Otherwise, makes a temp copy of the download file, and invokes |callback|
+ // with the path to the temp copy. The caller is responsible for cleanup.
+ // Note: It is important for |callback| to be valid since the downloaded file
+ // will not be cleaned up if the callback fails.
+ virtual void StealDangerousDownload(bool delete_file_afterward,
+ const AcquireFileCallback& callback) = 0;
+
+ // Pause a download. Will have no effect if the download is already
+ // paused.
+ virtual void Pause() = 0;
+
+ // Resume a download that has been paused or interrupted. Will have no effect
+ // if the download is neither. Only does something if CanResume() returns
+ // true.
+ virtual void Resume() = 0;
+
+ // Cancel the download operation.
+ //
+ // Set |user_cancel| to true if the cancellation was triggered by an explicit
+ // user action. Non-user-initiated cancels typically happen when the browser
+ // is being closed with in-progress downloads.
+ virtual void Cancel(bool user_cancel) = 0;
+
+ // Removes the download from the views and history. If the download was
+ // in-progress or interrupted, then the intermediate file will also be
+ // deleted.
+ virtual void Remove() = 0;
+
+ // Open the file associated with this download. If the download is
+ // still in progress, marks the download to be opened when it is complete.
+ virtual void OpenDownload() = 0;
+
+ // Show the download via the OS shell.
+ virtual void ShowDownloadInShell() = 0;
+
+ // State accessors -----------------------------------------------------------
+
+ // Retrieve the ID for this download. The ID is provided by the owner of the
+ // DownloadItem and is expected to uniquely identify the download within the
+ // context of its container during the lifetime of the download. A valid
+ // download will never return |kInvalidId|.
+ virtual uint32_t GetId() const = 0;
+
+ // Retrieve the GUID for this download. The returned string is never empty and
+ // will satisfy base::IsValidGUID() and uniquely identifies the download
+ // during its lifetime.
+ virtual const std::string& GetGuid() const = 0;
+
+ // Get the current state of the download. See DownloadState for descriptions
+ // of each download state.
+ virtual DownloadState GetState() const = 0;
+
+ // Returns the most recent interrupt reason for this download. Returns
+ // |DOWNLOAD_INTERRUPT_REASON_NONE| if there is no previous interrupt reason.
+ // Interrupted downloads and resumed downloads return the last known interrupt
+ // reason.
+ virtual DownloadInterruptReason GetLastReason() const = 0;
+
+ // The download is currently paused. Calling Resume() will transition out of
+ // this paused state.
+ virtual bool IsPaused() const = 0;
+
+ // DEPRECATED. True if this is a temporary download and should not be
+ // persisted.
+ virtual bool IsTemporary() const = 0;
+
+ // Returns true if the download can be resumed. A download can be resumed if
+ // an in-progress download was paused or if an interrupted download requires
+ // user-interaction to resume.
+ virtual bool CanResume() const = 0;
+
+ // Returns true if the download is in a terminal state. This includes
+ // completed downloads, cancelled downloads, and interrupted downloads that
+ // can't be resumed.
+ virtual bool IsDone() const = 0;
+
+ // Origin State accessors -------------------------------------------------
+
+ // Final URL. The primary resource being downloaded is from this URL. This is
+ // the tail of GetUrlChain(). May return an empty GURL if there is no valid
+ // download URL.
+ virtual const GURL& GetURL() const = 0;
+
+ // The complete URL chain including redirects. URL at index i redirected to
+ // URL at index i+1.
+ virtual const std::vector<GURL>& GetUrlChain() const = 0;
+
+ // The URL that the download request originally attempted to fetch. This may
+ // differ from GetURL() if there were redirects. The return value from this
+ // accessor is the same as the head of GetUrlChain().
+ virtual const GURL& GetOriginalUrl() const = 0;
+
+ // URL of document that is considered the referrer for the original URL.
+ virtual const GURL& GetReferrerUrl() const = 0;
+
+ // Site instance URL. Used to locate the correct storage partition during
+ // subsequent browser sessions. This may be different from all of
+ // GetOriginalUrl(), GetURL() and GetReferrerUrl().
+ virtual const GURL& GetSiteUrl() const = 0;
+
+ // URL of the top level frame at the time the download was initiated.
+ virtual const GURL& GetTabUrl() const = 0;
+
+ // Referrer URL for top level frame.
+ virtual const GURL& GetTabReferrerUrl() const = 0;
+
+ // For downloads initiated via <a download>, this is the suggested download
+ // filename from the download attribute.
+ virtual std::string GetSuggestedFilename() const = 0;
+
+ // Returns the HTTP response headers. This contains a nullptr when the
+ // response has not yet been received, and, because the headers are not being
+ // persisted, only capture responses received during the lifetime of the
+ // current process and profile. Only for consuming headers.
+ virtual const scoped_refptr<const net::HttpResponseHeaders>&
+ GetResponseHeaders() const = 0;
+
+ // Content-Disposition header value from HTTP response.
+ virtual std::string GetContentDisposition() const = 0;
+
+ // Effective MIME type of downloaded content.
+ virtual std::string GetMimeType() const = 0;
+
+ // Content-Type header value from HTTP response. May be different from
+ // GetMimeType() if a different effective MIME type was chosen after MIME
+ // sniffing.
+ virtual std::string GetOriginalMimeType() const = 0;
+
+ // Remote address of server serving download contents.
+ virtual std::string GetRemoteAddress() const = 0;
+
+ // Whether the download request was initiated in response to a user gesture.
+ virtual bool HasUserGesture() const = 0;
+
+ // The page transition type associated with the download request.
+ virtual ui::PageTransition GetTransitionType() const = 0;
+
+ // Last-Modified header value.
+ virtual const std::string& GetLastModifiedTime() const = 0;
+
+ // ETag header value.
+ virtual const std::string& GetETag() const = 0;
+
+ // Whether this download is a SavePackage download.
+ virtual bool IsSavePackageDownload() const = 0;
+
+ // Destination State accessors --------------------------------------------
+
+ // Full path to the downloaded or downloading file. This is the path to the
+ // physical file, if one exists. It should be considered a hint; changes to
+ // this value and renames of the file on disk are not atomic with each other.
+ // May be empty if the in-progress path hasn't been determined yet or if the
+ // download was interrupted.
+ //
+ // DO NOT USE THIS METHOD to access the target path of the DownloadItem. Use
+ // GetTargetFilePath() instead. While the download is in progress, the
+ // intermediate file named by GetFullPath() may be renamed or disappear
+ // completely on the download sequence. The path may also be reset to empty
+ // when the download is interrupted.
+ virtual const base::FilePath& GetFullPath() const = 0;
+
+ // Target path of an in-progress download. We may be downloading to a
+ // temporary or intermediate file (specified by GetFullPath()); this is the
+ // name we will use once the download completes.
+ // May be empty if the target path hasn't yet been determined.
+ virtual const base::FilePath& GetTargetFilePath() const = 0;
+
+ // If the download forced a path rather than requesting name determination,
+ // return the path requested.
+ virtual const base::FilePath& GetForcedFilePath() const = 0;
+
+ // Returns the file-name that should be reported to the user. If a display
+ // name has been explicitly set using SetDisplayName(), this function returns
+ // that display name. Otherwise returns the final target filename.
+ virtual base::FilePath GetFileNameToReportUser() const = 0;
+
+ // See TargetDisposition.
+ virtual TargetDisposition GetTargetDisposition() const = 0;
+
+ // Final hash of completely downloaded file, or partial hash of an interrupted
+ // download; only valid if GetState() == COMPLETED or INTERRUPTED. If
+ // non-empty the returned string contains a raw SHA-256 hash (i.e. not hex
+ // encoded).
+ virtual const std::string& GetHash() const = 0;
+
+ // True if the file associated with the download has been removed by
+ // external action.
+ virtual bool GetFileExternallyRemoved() const = 0;
+
+ // If the file is successfully deleted, then GetFileExternallyRemoved() will
+ // become true, GetFullPath() will become empty, and
+ // DownloadItem::OnDownloadUpdated() will be called. Does nothing if
+ // GetState() == COMPLETE or GetFileExternallyRemoved() is already true or
+ // GetFullPath() is already empty. The callback is always run, and it is
+ // always run asynchronously. It will be passed true if the file is
+ // successfully deleted or if GetFilePath() was already empty or if
+ // GetFileExternallyRemoved() was already true. The callback will be passed
+ // false if the DownloadItem was not yet complete or if the file could not be
+ // deleted for any reason.
+ virtual void DeleteFile(const base::Callback<void(bool)>& callback) = 0;
+
+ // True if the file that will be written by the download is dangerous
+ // and we will require a call to ValidateDangerousDownload() to complete.
+ // False if the download is safe or that function has been called.
+ virtual bool IsDangerous() const = 0;
+
+ // Why |safety_state_| is not SAFE.
+ virtual DownloadDangerType GetDangerType() const = 0;
+
+ // Progress State accessors -----------------------------------------------
+
+ // Simple calculation of the amount of time remaining to completion. Fills
+ // |*remaining| with the amount of time remaining if successful. Fails and
+ // returns false if we do not have the number of bytes or the speed so can
+ // not estimate.
+ virtual bool TimeRemaining(base::TimeDelta* remaining) const = 0;
+
+ // Simple speed estimate in bytes/s
+ virtual int64_t CurrentSpeed() const = 0;
+
+ // Rough percent complete. Returns -1 if progress is unknown. 100 if the
+ // download is already complete.
+ virtual int PercentComplete() const = 0;
+
+ // Returns true if this download has saved all of its data. A download may
+ // have saved all its data but still be waiting for some other process to
+ // complete before the download is considered complete. E.g. A dangerous
+ // download needs to be accepted by the user before the file is renamed to its
+ // final name.
+ virtual bool AllDataSaved() const = 0;
+
+ // Total number of expected bytes. Returns -1 if the total size is unknown.
+ virtual int64_t GetTotalBytes() const = 0;
+
+ // Total number of bytes that have been received and written to the download
+ // file.
+ virtual int64_t GetReceivedBytes() const = 0;
+
+ // Return the slices that have been received so far, ordered by their offset.
+ // This is only used when parallel downloading is enabled.
+ virtual const std::vector<ReceivedSlice>& GetReceivedSlices() const = 0;
+
+ // Time the download was first started. This timestamp is always valid and
+ // doesn't change.
+ virtual base::Time GetStartTime() const = 0;
+
+ // Time the download was marked as complete. Returns base::Time() if the
+ // download hasn't reached a completion state yet.
+ virtual base::Time GetEndTime() const = 0;
+
+ // Open/Show State accessors ----------------------------------------------
+
+ // Returns true if it is OK to open a folder which this file is inside.
+ virtual bool CanShowInFolder() = 0;
+
+ // Returns true if it is OK to open the download.
+ virtual bool CanOpenDownload() = 0;
+
+ // Tests if a file type should be opened automatically.
+ virtual bool ShouldOpenFileBasedOnExtension() = 0;
+
+ // Returns true if the download will be auto-opened when complete.
+ virtual bool GetOpenWhenComplete() const = 0;
+
+ // Returns true if the download has been auto-opened by the system.
+ virtual bool GetAutoOpened() = 0;
+
+ // Returns true if the download has been opened.
+ virtual bool GetOpened() const = 0;
+
+ // Time the download was last accessed. Returns NULL if the download has never
+ // been opened.
+ virtual base::Time GetLastAccessTime() const = 0;
+
+ // Returns whether the download item is transient. Transient items are cleaned
+ // up after completion and not shown in the UI, and will not prompt to user
+ // for target file path determination.
+ virtual bool IsTransient() const = 0;
+
+ // External state transitions/setters ----------------------------------------
+
+ // TODO(rdsmith): These should all be removed; the download item should
+ // control its own state transitions.
+
+ // Called if a check of the download contents was performed and the results of
+ // the test are available. This should only be called after AllDataSaved() is
+ // true. If |reason| is not DOWNLOAD_INTERRUPT_REASON_NONE, then the download
+ // file should be blocked.
+ // TODO(crbug.com/733291): Move DownloadInterruptReason out of here and add a
+ // new Interrupt method instead. Same for other methods supporting
+ // interruptions.
+ virtual void OnContentCheckCompleted(DownloadDangerType danger_type,
+ DownloadInterruptReason reason) = 0;
+
+ // Mark the download to be auto-opened when completed.
+ virtual void SetOpenWhenComplete(bool open) = 0;
+
+ // Mark the download as having been opened (without actually opening it).
+ virtual void SetOpened(bool opened) = 0;
+
+ // Updates the last access time of the download.
+ virtual void SetLastAccessTime(base::Time last_access_time) = 0;
+
+ // Set a display name for the download that will be independent of the target
+ // filename. If |name| is not empty, then GetFileNameToReportUser() will
+ // return |name|. Has no effect on the final target filename.
+ virtual void SetDisplayName(const base::FilePath& name) = 0;
+
+ // Debug/testing -------------------------------------------------------------
+ virtual std::string DebugString(bool verbose) const = 0;
+ virtual void SimulateErrorForTesting(DownloadInterruptReason reason) = 0;
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_ITEM_H_
diff --git a/chromium/components/download/public/common/download_request_handle_interface.h b/chromium/components/download/public/common/download_request_handle_interface.h
new file mode 100644
index 00000000000..31678df4a4d
--- /dev/null
+++ b/chromium/components/download/public/common/download_request_handle_interface.h
@@ -0,0 +1,29 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_REQUEST_HANDLE_INTERFACE_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_REQUEST_HANDLE_INTERFACE_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "components/download/public/common/download_export.h"
+
+namespace download {
+
+// A handle used by the download system for operations on the network request.
+class COMPONENTS_DOWNLOAD_EXPORT DownloadRequestHandleInterface {
+ public:
+ virtual ~DownloadRequestHandleInterface() = default;
+
+ // Pauses or resumes the network request.
+ virtual void PauseRequest() = 0;
+ virtual void ResumeRequest() = 0;
+
+ // Cancels the request.
+ virtual void CancelRequest(bool user_cancel) = 0;
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_REQUEST_HANDLE_INTERFACE_H_
diff --git a/chromium/components/download/public/common/download_save_info.cc b/chromium/components/download/public/common/download_save_info.cc
new file mode 100644
index 00000000000..075ba24545e
--- /dev/null
+++ b/chromium/components/download/public/common/download_save_info.cc
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/download_save_info.h"
+
+namespace download {
+
+// static
+const int64_t DownloadSaveInfo::kLengthFullContent = 0;
+
+DownloadSaveInfo::DownloadSaveInfo()
+ : offset(0), length(kLengthFullContent), prompt_for_save_location(false) {}
+
+DownloadSaveInfo::~DownloadSaveInfo() {}
+
+DownloadSaveInfo::DownloadSaveInfo(DownloadSaveInfo&& that)
+ : file_path(std::move(that.file_path)),
+ suggested_name(std::move(that.suggested_name)),
+ file(std::move(that.file)),
+ offset(that.offset),
+ length(that.length),
+ hash_state(std::move(that.hash_state)),
+ hash_of_partial_file(std::move(that.hash_of_partial_file)),
+ prompt_for_save_location(that.prompt_for_save_location) {}
+
+} // namespace download
diff --git a/chromium/components/download/public/common/download_save_info.h b/chromium/components/download/public/common/download_save_info.h
new file mode 100644
index 00000000000..b43d0f9746c
--- /dev/null
+++ b/chromium/components/download/public/common/download_save_info.h
@@ -0,0 +1,78 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_SAVE_INFO_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_SAVE_INFO_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "components/download/public/common/download_export.h"
+#include "crypto/secure_hash.h"
+
+namespace download {
+
+// Holds the information about how to save a download file.
+// In the case of download continuation, |file_path| is set to the current file
+// name, |offset| is set to the point where we left off, and |hash_state| will
+// hold the state of the hash algorithm where we left off.
+struct COMPONENTS_DOWNLOAD_EXPORT DownloadSaveInfo {
+ // The default value for |length|. Used when request the rest of the file
+ // starts from |offset|.
+ static const int64_t kLengthFullContent;
+
+ DownloadSaveInfo();
+ ~DownloadSaveInfo();
+ DownloadSaveInfo(DownloadSaveInfo&& that);
+
+ // If non-empty, contains the full target path of the download that has been
+ // determined prior to download initiation. This is considered to be a trusted
+ // path.
+ base::FilePath file_path;
+
+ // If non-empty, contains an untrusted filename suggestion. This can't contain
+ // a path (only a filename), and is only effective if |file_path| is empty.
+ base::string16 suggested_name;
+
+ // If valid, contains the source data stream for the file contents.
+ base::File file;
+
+ // The file offset at which to start the download. May be 0.
+ int64_t offset;
+
+ // The number of the bytes to download from |offset|. Set to
+ // |kLengthFullContent| by default.
+ // Ask to retrieve segment of the download file when length is greater than 0.
+ // Request the rest of the file starting from |offset|, when length is
+ // |kLengthFullContent|.
+ int64_t length;
+
+ // The state of the hash. If specified, this hash state must indicate the
+ // state of the partial file for the first |offset| bytes.
+ std::unique_ptr<crypto::SecureHash> hash_state;
+
+ // SHA-256 hash of the first |offset| bytes of the file. Only used if |offset|
+ // is non-zero and either |file_path| or |file| specifies the file which
+ // contains the |offset| number of bytes. Can be empty, in which case no
+ // verification is done on the existing file.
+ std::string hash_of_partial_file;
+
+ // If |prompt_for_save_location| is true, and |file_path| is empty, then
+ // the user will be prompted for a location to save the download. Otherwise,
+ // the location will be determined automatically using |file_path| as a
+ // basis if |file_path| is not empty.
+ // |prompt_for_save_location| defaults to false.
+ bool prompt_for_save_location;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DownloadSaveInfo);
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_SAVE_INFO_H_
diff --git a/chromium/components/download/public/common/download_source.h b/chromium/components/download/public/common/download_source.h
new file mode 100644
index 00000000000..1a330ebf0d2
--- /dev/null
+++ b/chromium/components/download/public/common/download_source.h
@@ -0,0 +1,48 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_SOURCE_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_SOURCE_H_
+
+namespace download {
+
+// The source of download.
+// Used in UMA metrics and persisted to disk.
+// Entries in this enum can only be appended instead of being deleted or reused.
+// Any changes here also needs to apply to enums.xml.
+enum class DownloadSource {
+ // The source is unknown.
+ UNKNOWN = 0,
+
+ // Download is triggered from navigation request.
+ NAVIGATION = 1,
+
+ // Drag and drop.
+ DRAG_AND_DROP = 2,
+
+ // Renderer initiated download, mostly from Javascript or HTML <a> tag.
+ FROM_RENDERER = 3,
+
+ // Extension download API.
+ EXTENSION_API = 4,
+
+ // Extension web store installer.
+ EXTENSION_INSTALLER = 5,
+
+ // Download service API background download.
+ INTERNAL_API = 6,
+
+ // Download through web contents API.
+ WEB_CONTENTS_API = 7,
+
+ // Offline page download.
+ OFFLINE_PAGE = 8,
+
+ // Context menu download.
+ CONTEXT_MENU = 9,
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_SOURCE_H_
diff --git a/chromium/components/download/public/common/download_stats.h b/chromium/components/download/public/common/download_stats.h
new file mode 100644
index 00000000000..e70100393cb
--- /dev/null
+++ b/chromium/components/download/public/common/download_stats.h
@@ -0,0 +1,378 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Holds helpers for gathering UMA stats about downloads.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_STATS_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_STATS_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "base/optional.h"
+#include "components/download/public/common/download_content.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_source.h"
+#include "ui/base/page_transition_types.h"
+#include "url/gurl.h"
+
+namespace base {
+class FilePath;
+class Time;
+class TimeDelta;
+class TimeTicks;
+} // namespace base
+
+namespace download {
+
+// We keep a count of how often various events occur in the
+// histogram "Download.Counts".
+enum DownloadCountTypes {
+ // Stale enum values left around so that values passed to UMA don't
+ // change.
+ DOWNLOAD_COUNT_UNUSED_0 = 0,
+ DOWNLOAD_COUNT_UNUSED_1,
+ DOWNLOAD_COUNT_UNUSED_2,
+ DOWNLOAD_COUNT_UNUSED_3,
+ DOWNLOAD_COUNT_UNUSED_4,
+
+ // Downloads that made it to DownloadResourceHandler
+ UNTHROTTLED_COUNT,
+
+ // Downloads that actually complete.
+ COMPLETED_COUNT,
+
+ // Downloads that are cancelled before completion (user action or error).
+ CANCELLED_COUNT,
+
+ // Downloads that are started.
+ START_COUNT,
+
+ // Downloads that were interrupted by the OS.
+ INTERRUPTED_COUNT,
+
+ // (Deprecated) Write sizes for downloads.
+ // This is equal to the number of samples in Download.WriteSize histogram.
+ DOWNLOAD_COUNT_UNUSED_10,
+
+ // (Deprecated) Counts iterations of the BaseFile::AppendDataToFile() loop.
+ // This is equal to the number of samples in Download.WriteLoopCount
+ // histogram.
+ DOWNLOAD_COUNT_UNUSED_11,
+
+ // Counts interruptions that happened at the end of the download.
+ INTERRUPTED_AT_END_COUNT,
+
+ // Counts errors due to writes to BaseFiles that have been detached already.
+ // This can happen when saving web pages as complete packages. It happens
+ // when we get messages to append data to files that have already finished and
+ // been detached, but haven't yet been removed from the list of files in
+ // progress.
+ APPEND_TO_DETACHED_FILE_COUNT,
+
+ // (Deprecated) Counts the number of instances where the downloaded file is
+ // missing after a successful invocation of ScanAndSaveDownloadedFile().
+ DOWNLOAD_COUNT_UNUSED_14,
+
+ // (Deprecated) Count of downloads with a strong ETag and specified
+ // 'Accept-Ranges: bytes'.
+ DOWNLOAD_COUNT_UNUSED_15,
+
+ // Count of downloads that didn't have a valid WebContents at the time it was
+ // interrupted.
+ INTERRUPTED_WITHOUT_WEBCONTENTS,
+
+ // Count of downloads that supplies a strong validator (implying byte-wise
+ // equivalence) and has a 'Accept-Ranges: bytes' header. These downloads are
+ // candidates for partial resumption.
+ STRONG_VALIDATOR_AND_ACCEPTS_RANGES,
+
+ // (Deprecated) Count of downloads that uses parallel download requests.
+ USES_PARALLEL_REQUESTS,
+
+ // Count of new downloads.
+ NEW_DOWNLOAD_COUNT,
+
+ // Count of new downloads that are started in normal profile.
+ NEW_DOWNLOAD_COUNT_NORMAL_PROFILE,
+
+ // Downloads that are actually completed in normal profile.
+ COMPLETED_COUNT_NORMAL_PROFILE,
+
+ // Downloads that are completed with a content length mismatch error.
+ COMPLETED_WITH_CONTENT_LENGTH_MISMATCH_COUNT,
+
+ // After a download is interrupted with a content length mismatch error, more
+ // bytes are received when resuming the download.
+ MORE_BYTES_RECEIVED_AFTER_CONTENT_LENGTH_MISMATCH_COUNT,
+
+ // After a download is interrupted with a content length mismatch error, no
+ // bytes are received when resuming the download.
+ NO_BYTES_RECEIVED_AFTER_CONTENT_LENGTH_MISMATCH_COUNT,
+
+ // Count of downloads that requested target determination.
+ DETERMINE_DOWNLOAD_TARGET_COUNT,
+
+ // Count of downloads that has target determination completed.
+ DOWNLOAD_TARGET_DETERMINED_COUNT,
+
+ // A cross origin download without a content disposition header.
+ CROSS_ORIGIN_DOWNLOAD_WITHOUT_CONTENT_DISPOSITION,
+
+ // Count of attempts that triggered the download flow, before any network
+ // requests are sent.
+ DOWNLOAD_TRIGGERED_COUNT,
+
+ // Count of attempts for manual download resumption.
+ MANUAL_RESUMPTION_COUNT,
+
+ // Count of attempts for auto download resumption.
+ AUTO_RESUMPTION_COUNT,
+
+ DOWNLOAD_COUNT_TYPES_LAST_ENTRY
+};
+
+enum DownloadDiscardReason {
+ // The download is being discarded due to a user action.
+ DOWNLOAD_DISCARD_DUE_TO_USER_ACTION,
+
+ // The download is being discarded due to the browser being shut down.
+ DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN
+};
+
+// When parallel download is enabled, the download may fall back to a normal
+// download for various reasons. This enum counts the number of parallel
+// download and fallbacks. Also records the reasons why the download falls back
+// to a normal download. The reasons are not mutually exclusive.
+// Used in histogram "Download.ParallelDownload.CreationEvent" and should be
+// treated as append-only.
+enum class ParallelDownloadCreationEvent {
+ // The total number of downloads started as parallel download.
+ STARTED_PARALLEL_DOWNLOAD = 0,
+
+ // The total number of downloads fell back to normal download when parallel
+ // download is enabled.
+ FELL_BACK_TO_NORMAL_DOWNLOAD,
+
+ // No ETag or Last-Modified response header.
+ FALLBACK_REASON_STRONG_VALIDATORS,
+
+ // No Accept-Range response header.
+ FALLBACK_REASON_ACCEPT_RANGE_HEADER,
+
+ // No Content-Length response header.
+ FALLBACK_REASON_CONTENT_LENGTH_HEADER,
+
+ // File size is not complied to finch configuration.
+ FALLBACK_REASON_FILE_SIZE,
+
+ // The HTTP connection type does not meet the requirement.
+ FALLBACK_REASON_CONNECTION_TYPE,
+
+ // The remaining time does not meet the requirement.
+ FALLBACK_REASON_REMAINING_TIME,
+
+ // The http method or url scheme does not meet the requirement.
+ FALLBACK_REASON_HTTP_METHOD,
+
+ // Last entry of the enum.
+ COUNT,
+};
+
+// Increment one of the above counts.
+COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadCount(DownloadCountTypes type);
+
+// Record download count with download source.
+COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadCountWithSource(
+ DownloadCountTypes type,
+ DownloadSource download_source);
+
+// Record COMPLETED_COUNT and how long the download took.
+COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadCompleted(
+ const base::TimeTicks& start,
+ int64_t download_len,
+ bool is_parallelizable,
+ DownloadSource download_source);
+
+// Record INTERRUPTED_COUNT, |reason|, |received| and |total| bytes.
+COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadInterrupted(
+ DownloadInterruptReason reason,
+ int64_t received,
+ int64_t total,
+ bool is_parallelizable,
+ bool is_parallel_download_enabled,
+ DownloadSource download_source);
+
+// Record that a download has been classified as malicious.
+COMPONENTS_DOWNLOAD_EXPORT void RecordMaliciousDownloadClassified(
+ DownloadDangerType danger_type);
+
+// Record a dangerous download accept event.
+COMPONENTS_DOWNLOAD_EXPORT void RecordDangerousDownloadAccept(
+ DownloadDangerType danger_type,
+ const base::FilePath& file_path);
+
+// Record a dangerous download discard event.
+COMPONENTS_DOWNLOAD_EXPORT void RecordDangerousDownloadDiscard(
+ DownloadDiscardReason reason,
+ DownloadDangerType danger_type,
+ const base::FilePath& file_path);
+
+// Returns the type of download.
+COMPONENTS_DOWNLOAD_EXPORT DownloadContent
+DownloadContentFromMimeType(const std::string& mime_type_string,
+ bool record_content_subcategory);
+
+// Records the mime type of the download.
+COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadMimeType(
+ const std::string& mime_type);
+
+// Records the mime type of the download for normal profile.
+COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadMimeTypeForNormalProfile(
+ const std::string& mime_type);
+
+// Records usage of Content-Disposition header.
+COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadContentDisposition(
+ const std::string& content_disposition);
+
+// Record the number of buffers piled up by the IO thread
+// before the file thread gets to draining them.
+COMPONENTS_DOWNLOAD_EXPORT void RecordFileThreadReceiveBuffers(
+ size_t num_buffers);
+
+// Record the time of both the first open and all subsequent opens since the
+// download completed.
+COMPONENTS_DOWNLOAD_EXPORT void RecordOpen(const base::Time& end, bool first);
+
+// Record whether or not the server accepts ranges, and the download size. Also
+// counts if a strong validator is supplied. The combination of range request
+// support and ETag indicates downloads that are candidates for partial
+// resumption.
+COMPONENTS_DOWNLOAD_EXPORT void RecordAcceptsRanges(
+ const std::string& accepts_ranges,
+ int64_t download_len,
+ bool has_strong_validator);
+
+// Record the number of completed unopened downloads when a download is opened.
+COMPONENTS_DOWNLOAD_EXPORT void RecordOpensOutstanding(int size);
+
+// Record how long we block the file thread at a time.
+COMPONENTS_DOWNLOAD_EXPORT void RecordContiguousWriteTime(
+ base::TimeDelta time_blocked);
+
+// Record the percentage of time we had to block the network (i.e.
+// how often, for each download, something other than the network
+// was the bottleneck).
+COMPONENTS_DOWNLOAD_EXPORT void RecordNetworkBlockage(
+ base::TimeDelta resource_handler_lifetime,
+ base::TimeDelta resource_handler_blocked_time);
+
+// Record overall bandwidth stats at the file end.
+// Does not count in any hash computation or file open/close time.
+COMPONENTS_DOWNLOAD_EXPORT void RecordFileBandwidth(
+ size_t length,
+ base::TimeDelta disk_write_time,
+ base::TimeDelta elapsed_time);
+
+// Records the size of the download from content-length header.
+COMPONENTS_DOWNLOAD_EXPORT void RecordParallelizableContentLength(
+ int64_t content_length);
+
+// Increment one of the count for parallelizable download.
+COMPONENTS_DOWNLOAD_EXPORT void RecordParallelizableDownloadCount(
+ DownloadCountTypes type,
+ bool is_parallel_download_enabled);
+
+// Records the actual total number of requests sent for a parallel download,
+// including the initial request.
+COMPONENTS_DOWNLOAD_EXPORT void RecordParallelDownloadRequestCount(
+ int request_count);
+
+// Records if each byte stream is successfully added to download sink.
+COMPONENTS_DOWNLOAD_EXPORT void RecordParallelDownloadAddStreamSuccess(
+ bool success);
+
+// Records the bandwidth for parallelizable download and estimates the saved
+// time at the file end. Does not count in any hash computation or file
+// open/close time.
+COMPONENTS_DOWNLOAD_EXPORT void RecordParallelizableDownloadStats(
+ size_t bytes_downloaded_with_parallel_streams,
+ base::TimeDelta time_with_parallel_streams,
+ size_t bytes_downloaded_without_parallel_streams,
+ base::TimeDelta time_without_parallel_streams,
+ bool uses_parallel_requests);
+
+// Records the average bandwidth, time, and file size for parallelizable
+// download.
+COMPONENTS_DOWNLOAD_EXPORT void RecordParallelizableDownloadAverageStats(
+ int64_t bytes_downloaded,
+ const base::TimeDelta& time_span);
+
+// Records the parallel download creation counts and the reasons why the
+// download falls back to non-parallel download.
+COMPONENTS_DOWNLOAD_EXPORT void RecordParallelDownloadCreationEvent(
+ ParallelDownloadCreationEvent event);
+
+// Record the result of a download file rename.
+COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadFileRenameResultAfterRetry(
+ base::TimeDelta time_since_first_failure,
+ DownloadInterruptReason interrupt_reason);
+
+enum SavePackageEvent {
+ // The user has started to save a page as a package.
+ SAVE_PACKAGE_STARTED,
+
+ // The save package operation was cancelled.
+ SAVE_PACKAGE_CANCELLED,
+
+ // The save package operation finished without being cancelled.
+ SAVE_PACKAGE_FINISHED,
+
+ // The save package tried to write to an already completed file.
+ SAVE_PACKAGE_WRITE_TO_COMPLETED,
+
+ // The save package tried to write to an already failed file.
+ SAVE_PACKAGE_WRITE_TO_FAILED,
+
+ // Instead of using save package API, used download API to save non HTML
+ // format files.
+ SAVE_PACKAGE_DOWNLOAD_ON_NON_HTML,
+
+ SAVE_PACKAGE_LAST_ENTRY
+};
+
+COMPONENTS_DOWNLOAD_EXPORT void RecordSavePackageEvent(SavePackageEvent event);
+
+enum OriginStateOnResumption {
+ ORIGIN_STATE_ON_RESUMPTION_ADDITIONAL_REDIRECTS = 1 << 0,
+ ORIGIN_STATE_ON_RESUMPTION_VALIDATORS_CHANGED = 1 << 1,
+ ORIGIN_STATE_ON_RESUMPTION_CONTENT_DISPOSITION_CHANGED = 1 << 2,
+ ORIGIN_STATE_ON_RESUMPTION_MAX = 1 << 3
+};
+
+// Record the state of the origin information across a download resumption
+// request. |state| is a combination of values from OriginStateOnResumption
+// enum.
+COMPONENTS_DOWNLOAD_EXPORT void RecordOriginStateOnResumption(
+ bool is_partial,
+ OriginStateOnResumption state);
+
+COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadConnectionSecurity(
+ const GURL& download_url,
+ const std::vector<GURL>& url_chain);
+
+COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadSourcePageTransitionType(
+ const base::Optional<ui::PageTransition>& transition);
+
+COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadHttpResponseCode(
+ int response_code);
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_STATS_H_
diff --git a/chromium/components/download/public/common/download_stream.mojom b/chromium/components/download/public/common/download_stream.mojom
new file mode 100644
index 00000000000..5083aaa903f
--- /dev/null
+++ b/chromium/components/download/public/common/download_stream.mojom
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module download.mojom;
+
+enum NetworkRequestStatus {
+ OK,
+ NETWORK_TIMEOUT,
+ NETWORK_DISCONNECTED,
+ NETWORK_SERVER_DOWN,
+ SERVER_NO_RANGE,
+ SERVER_CONTENT_LENGTH_MISMATCH,
+ SERVER_UNREACHABLE,
+ SERVER_CERT_PROBLEM,
+ USER_CANCELED,
+ NETWORK_FAILED,
+};
+
+// Used to pass the interruption status to the consumer of the data pipe.
+interface DownloadStreamClient {
+ OnStreamCompleted(NetworkRequestStatus status);
+};
+
+struct DownloadStreamHandle {
+ handle<data_pipe_consumer> stream;
+ DownloadStreamClient& client_request;
+}; \ No newline at end of file
diff --git a/chromium/components/download/public/common/download_task_runner.h b/chromium/components/download/public/common/download_task_runner.h
new file mode 100644
index 00000000000..b7d5bd3ef83
--- /dev/null
+++ b/chromium/components/download/public/common/download_task_runner.h
@@ -0,0 +1,19 @@
+// 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_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_TASK_RUNNER_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_TASK_RUNNER_H_
+
+#include "base/sequenced_task_runner.h"
+#include "components/download/public/common/download_export.h"
+
+namespace download {
+
+// Returns the task runner used to save files and do other blocking operations.
+COMPONENTS_DOWNLOAD_EXPORT scoped_refptr<base::SequencedTaskRunner>
+GetDownloadTaskRunner();
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_TASK_RUNNER_H_
diff --git a/chromium/components/download/public/common/download_ukm_helper.h b/chromium/components/download/public/common/download_ukm_helper.h
new file mode 100644
index 00000000000..8920790d2aa
--- /dev/null
+++ b/chromium/components/download/public/common/download_ukm_helper.h
@@ -0,0 +1,64 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Holds helpers for gathering UKM stats about downloads.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_UKM_HELPER_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_UKM_HELPER_H_
+
+#include "components/download/public/common/download_content.h"
+#include "components/download/public/common/download_interrupt_reasons.h"
+#include "components/download/public/common/download_source.h"
+#include "components/download/public/common/resume_mode.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
+#include "url/gurl.h"
+
+namespace download {
+
+class COMPONENTS_DOWNLOAD_EXPORT DownloadUkmHelper {
+ public:
+ // Calculate which exponential bucket the value falls in. This is used to mask
+ // the actual value of the metric due to privacy concerns for certain metrics
+ // that could trace back the user's exact actions.
+ static int CalcExponentialBucket(int value);
+
+ // Record when the download has started.
+ static void RecordDownloadStarted(int download_id,
+ ukm::SourceId source_id,
+ DownloadContent file_type,
+ DownloadSource download_source);
+
+ // Record when the download is interrupted.
+ static void RecordDownloadInterrupted(
+ int download_id,
+ base::Optional<int> change_in_file_size,
+ download::DownloadInterruptReason reason,
+ int resulting_file_size,
+ const base::TimeDelta& time_since_start);
+
+ // Record when the download is resumed.
+ static void RecordDownloadResumed(int download_id,
+ ResumeMode mode,
+ const base::TimeDelta& time_since_start);
+
+ // Record when the download is completed.
+ static void RecordDownloadCompleted(int download_id,
+ int resulting_file_size,
+ const base::TimeDelta& time_since_start);
+
+ // Friended Helper for recording main frame URLs to UKM.
+ static void UpdateSourceURL(ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ const GURL& url);
+
+ private:
+ DownloadUkmHelper();
+ ~DownloadUkmHelper();
+
+ DISALLOW_COPY_AND_ASSIGN(DownloadUkmHelper);
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_UKM_HELPER_H_
diff --git a/chromium/components/download/public/common/download_url_parameters.cc b/chromium/components/download/public/common/download_url_parameters.cc
new file mode 100644
index 00000000000..d30ea271cbb
--- /dev/null
+++ b/chromium/components/download/public/common/download_url_parameters.cc
@@ -0,0 +1,48 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/download_url_parameters.h"
+
+namespace download {
+
+DownloadUrlParameters::DownloadUrlParameters(
+ const GURL& url,
+ net::URLRequestContextGetter* url_request_context_getter,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation)
+ : DownloadUrlParameters(url,
+ -1,
+ -1,
+ -1,
+ url_request_context_getter,
+ traffic_annotation) {}
+
+DownloadUrlParameters::DownloadUrlParameters(
+ const GURL& url,
+ int render_process_host_id,
+ int render_view_host_routing_id,
+ int render_frame_host_routing_id,
+ net::URLRequestContextGetter* url_request_context_getter,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation)
+ : content_initiated_(false),
+ use_if_range_(true),
+ method_("GET"),
+ post_id_(-1),
+ prefer_cache_(false),
+ referrer_policy_(
+ net::URLRequest::
+ CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
+ render_process_host_id_(render_process_host_id),
+ render_view_host_routing_id_(render_view_host_routing_id),
+ render_frame_host_routing_id_(render_frame_host_routing_id),
+ url_request_context_getter_(url_request_context_getter),
+ url_(url),
+ do_not_prompt_for_login_(false),
+ fetch_error_body_(false),
+ transient_(false),
+ traffic_annotation_(traffic_annotation),
+ download_source_(DownloadSource::UNKNOWN) {}
+
+DownloadUrlParameters::~DownloadUrlParameters() = default;
+
+} // namespace download
diff --git a/chromium/components/download/public/common/download_url_parameters.h b/chromium/components/download/public/common/download_url_parameters.h
new file mode 100644
index 00000000000..20538650ca7
--- /dev/null
+++ b/chromium/components/download/public/common/download_url_parameters.h
@@ -0,0 +1,331 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_PARAMETERS_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_PARAMETERS_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.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"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/resource_request_body.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace download {
+
+class DownloadItem;
+
+// Pass an instance of DownloadUrlParameters to DownloadManager::DownloadUrl()
+// to download the content at |url|. All parameters with setters are optional.
+// |referrer| and |referrer_encoding| are the referrer for the download. If
+// |prefer_cache| is true, then if the response to |url| is in the HTTP cache it
+// will be used without revalidation. If |post_id| is non-negative, then it
+// identifies the post transaction used to originally retrieve the |url|
+// resource - it also requires |prefer_cache| to be |true| since re-post'ing is
+// not done. |save_info| specifies where the downloaded file should be saved,
+// and whether the user should be prompted about the download. If not null,
+// |callback| will be called when the download starts, or if an error occurs
+// that prevents a download item from being created. We send a pointer to
+// content::ResourceContext instead of the usual reference so that a copy of the
+// object isn't made.
+
+class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters {
+ public:
+ // An OnStartedCallback is invoked when a response is available for the
+ // download request. For new downloads, this callback is invoked after the
+ // OnDownloadCreated notification is issued by the DownloadManager. If the
+ // download fails, then the DownloadInterruptReason parameter will indicate
+ // the failure.
+ //
+ // DownloadItem* may be nullptr if no DownloadItem was created. DownloadItems
+ // are not created when a resource throttle or a resource handler blocks the
+ // download request. I.e. the download triggered a warning of some sort and
+ // the user chose to not to proceed with the download as a result.
+ typedef base::Callback<void(DownloadItem*, DownloadInterruptReason)>
+ OnStartedCallback;
+
+ typedef std::pair<std::string, std::string> RequestHeadersNameValuePair;
+ typedef std::vector<RequestHeadersNameValuePair> RequestHeadersType;
+
+ using BlobStorageContextGetter =
+ base::OnceCallback<storage::BlobStorageContext*()>;
+
+ // Constructs a download not associated with a frame.
+ //
+ // It is not safe to have downloads not associated with a frame and
+ // this should only be done in a limited set of cases where the download URL
+ // has been previously vetted. A download that's initiated without
+ // associating it with a frame don't receive the same security checks
+ // as a request that's associated with one. Hence, downloads that are not
+ // associated with a frame should only be made for URLs that are either
+ // trusted or URLs that have previously been successfully issued using a
+ // non-privileged frame.
+ DownloadUrlParameters(
+ const GURL& url,
+ net::URLRequestContextGetter* url_request_context_getter,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation);
+
+ // The RenderView routing ID must correspond to the RenderView of the
+ // RenderFrame, both of which share the same RenderProcess. This may be a
+ // different RenderView than the WebContents' main RenderView.
+ DownloadUrlParameters(
+ const GURL& url,
+ int render_process_host_id,
+ int render_view_host_routing_id,
+ int render_frame_host_routing_id,
+ net::URLRequestContextGetter* url_request_context_getter,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation);
+
+ ~DownloadUrlParameters();
+
+ // Should be set to true if the download was initiated by a script or a web
+ // page. I.e. if the download request cannot be attributed to an explicit user
+ // request for a download, then set this value to true.
+ void set_content_initiated(bool content_initiated) {
+ content_initiated_ = content_initiated;
+ }
+ void add_request_header(const std::string& name, const std::string& value) {
+ request_headers_.push_back(make_pair(name, value));
+ }
+
+ // HTTP Referrer, referrer policy and encoding.
+ void set_referrer(const GURL& referrer) { referrer_ = referrer; }
+ void set_referrer_policy(net::URLRequest::ReferrerPolicy referrer_policy) {
+ referrer_policy_ = referrer_policy;
+ }
+ void set_referrer_encoding(const std::string& referrer_encoding) {
+ referrer_encoding_ = referrer_encoding;
+ }
+
+ // The origin of the context which initiated the request. See
+ // net::URLRequest::initiator().
+ void set_initiator(const base::Optional<url::Origin>& initiator) {
+ initiator_ = initiator;
+ }
+
+ // If this is a request for resuming an HTTP/S download, |last_modified|
+ // should be the value of the last seen Last-Modified response header.
+ void set_last_modified(const std::string& last_modified) {
+ last_modified_ = last_modified;
+ }
+
+ // If this is a request for resuming an HTTP/S download, |etag| should be the
+ // last seen Etag response header.
+ void set_etag(const std::string& etag) { etag_ = etag; }
+
+ // If the "If-Range" header is used in a partial request.
+ void set_use_if_range(bool use_if_range) { use_if_range_ = use_if_range; }
+
+ // HTTP method to use.
+ void set_method(const std::string& method) { method_ = method; }
+
+ // Body of the HTTP POST request.
+ void set_post_body(scoped_refptr<network::ResourceRequestBody> post_body) {
+ post_body_ = post_body;
+ }
+
+ // The blob storage context to be used for uploading blobs, if any.
+ void set_blob_storage_context_getter(BlobStorageContextGetter blob_getter) {
+ blob_storage_context_getter_ = std::move(blob_getter);
+ }
+
+ // If |prefer_cache| is true and the response to |url| is in the HTTP cache,
+ // it will be used without validation. If |method| is POST, then |post_id_|
+ // shoud be set via |set_post_id()| below to the identifier of the POST
+ // transaction used to originally retrieve the resource.
+ void set_prefer_cache(bool prefer_cache) { prefer_cache_ = prefer_cache; }
+
+ // See set_prefer_cache() above.
+ void set_post_id(int64_t post_id) { post_id_ = post_id; }
+
+ // See OnStartedCallback above.
+ void set_callback(const OnStartedCallback& callback) { callback_ = callback; }
+
+ // If not empty, specifies the full target path for the download. This value
+ // overrides the filename suggested by a Content-Disposition headers. It
+ // should only be set for programmatic downloads where the caller can verify
+ // the safety of the filename and the resulting download.
+ void set_file_path(const base::FilePath& file_path) {
+ save_info_.file_path = file_path;
+ }
+
+ // Suggested filename for the download. The suggestion can be overridden by
+ // either a Content-Disposition response header or a |file_path|.
+ void set_suggested_name(const base::string16& suggested_name) {
+ save_info_.suggested_name = suggested_name;
+ }
+
+ // If |offset| is non-zero, then a byte range request will be issued to fetch
+ // the range of bytes starting at |offset|.
+ // Use |set_length| to specify the last byte position, or the range
+ // request will be "Range:bytes={offset}-" to retrieve the rest of the file.
+ void set_offset(int64_t offset) { save_info_.offset = offset; }
+
+ // When |length| > 0, the range of bytes will be from
+ // |save_info_.offset| to |save_info_.offset| + |length| - 1.
+ // See |DownloadSaveInfo.length|.
+ void set_length(int64_t length) { save_info_.length = length; }
+
+ // If |offset| is non-zero, then |hash_of_partial_file| contains the raw
+ // SHA-256 hash of the first |offset| bytes of the target file. Only
+ // meaningful if a partial file exists and is identified by either the
+ // |file_path()| or |file()|.
+ void set_hash_of_partial_file(const std::string& hash_of_partial_file) {
+ save_info_.hash_of_partial_file = hash_of_partial_file;
+ }
+
+ // If |offset| is non-zero, then |hash_state| indicates the SHA-256 hash state
+ // of the first |offset| bytes of the target file. In this case, the prefix
+ // hash will be ignored since the |hash_state| is assumed to be correct if
+ // provided.
+ void set_hash_state(std::unique_ptr<crypto::SecureHash> hash_state) {
+ save_info_.hash_state = std::move(hash_state);
+ }
+
+ // If |prompt| is true, then the user will be prompted for a filename. Ignored
+ // if |file_path| is non-empty.
+ void set_prompt(bool prompt) { save_info_.prompt_for_save_location = prompt; }
+ void set_file(base::File file) { save_info_.file = std::move(file); }
+ void set_do_not_prompt_for_login(bool do_not_prompt) {
+ do_not_prompt_for_login_ = do_not_prompt;
+ }
+
+ // Sets whether to download the response body even if the server returns
+ // non-successful HTTP response code, like "HTTP NOT FOUND".
+ void set_fetch_error_body(bool fetch_error_body) {
+ fetch_error_body_ = fetch_error_body;
+ }
+
+ // Sets whether the download is to be treated as transient. A transient
+ // download is short-lived and is not shown in the UI, and will not prompt
+ // to user for target file path determination.
+ void set_transient(bool transient) { transient_ = transient; }
+
+ // Sets the optional guid for the download, the guid serves as the unique
+ // identitfier for the download item. If no guid is provided, download
+ // system will automatically generate one.
+ void set_guid(const std::string& guid) { guid_ = guid; }
+
+ // For downloads originating from custom tabs, this records the origin
+ // of the custom tab.
+ void set_request_origin(const std::string& origin) {
+ request_origin_ = origin;
+ }
+
+ // Sets the download source, which will be used in metrics recording.
+ void set_download_source(DownloadSource download_source) {
+ download_source_ = download_source;
+ }
+
+ const OnStartedCallback& callback() const { return callback_; }
+ bool content_initiated() const { return content_initiated_; }
+ const std::string& last_modified() const { return last_modified_; }
+ const std::string& etag() const { return etag_; }
+ bool use_if_range() const { return use_if_range_; }
+ const std::string& method() const { return method_; }
+ scoped_refptr<network::ResourceRequestBody> post_body() { return post_body_; }
+ int64_t post_id() const { return post_id_; }
+ bool prefer_cache() const { return prefer_cache_; }
+ const GURL& referrer() const { return referrer_; }
+ net::URLRequest::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 std::string& request_origin() const { return request_origin_; }
+ BlobStorageContextGetter get_blob_storage_context_getter() {
+ return std::move(blob_storage_context_getter_);
+ }
+
+ // These will be -1 if the request is not associated with a frame. See
+ // the constructors for more.
+ int render_process_host_id() const { return render_process_host_id_; }
+ int render_view_host_routing_id() const {
+ return render_view_host_routing_id_;
+ }
+ int render_frame_host_routing_id() const {
+ return render_frame_host_routing_id_;
+ }
+
+ const RequestHeadersType& request_headers() const { return request_headers_; }
+ net::URLRequestContextGetter* url_request_context_getter() {
+ return url_request_context_getter_.get();
+ }
+ const base::FilePath& file_path() const { return save_info_.file_path; }
+ const base::string16& suggested_name() const {
+ return save_info_.suggested_name;
+ }
+ int64_t offset() const { return save_info_.offset; }
+ int64_t length() const { return save_info_.length; }
+ const std::string& hash_of_partial_file() const {
+ return save_info_.hash_of_partial_file;
+ }
+ bool prompt() const { return save_info_.prompt_for_save_location; }
+ const GURL& url() const { return url_; }
+ bool do_not_prompt_for_login() const { return do_not_prompt_for_login_; }
+ bool fetch_error_body() const { return fetch_error_body_; }
+ bool is_transient() const { return transient_; }
+ std::string guid() const { return guid_; }
+
+ // STATE CHANGING: All save_info_ sub-objects will be in an indeterminate
+ // state following this call.
+ DownloadSaveInfo GetSaveInfo() { return std::move(save_info_); }
+
+ const net::NetworkTrafficAnnotationTag& GetNetworkTrafficAnnotation() {
+ return traffic_annotation_;
+ }
+
+ DownloadSource download_source() const { return download_source_; }
+
+ private:
+ OnStartedCallback callback_;
+ bool content_initiated_;
+ RequestHeadersType request_headers_;
+ std::string last_modified_;
+ std::string etag_;
+ bool use_if_range_;
+ std::string method_;
+ scoped_refptr<network::ResourceRequestBody> post_body_;
+ BlobStorageContextGetter blob_storage_context_getter_;
+ int64_t post_id_;
+ bool prefer_cache_;
+ GURL referrer_;
+ net::URLRequest::ReferrerPolicy referrer_policy_;
+ base::Optional<url::Origin> initiator_;
+ std::string referrer_encoding_;
+ int render_process_host_id_;
+ int render_view_host_routing_id_;
+ int render_frame_host_routing_id_;
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+ DownloadSaveInfo save_info_;
+ GURL url_;
+ bool do_not_prompt_for_login_;
+ bool fetch_error_body_;
+ bool transient_;
+ std::string guid_;
+ const net::NetworkTrafficAnnotationTag traffic_annotation_;
+ std::string request_origin_;
+ DownloadSource download_source_;
+
+ DISALLOW_COPY_AND_ASSIGN(DownloadUrlParameters);
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_PARAMETERS_H_
diff --git a/chromium/components/download/public/common/rate_estimator.h b/chromium/components/download/public/common/rate_estimator.h
new file mode 100644
index 00000000000..b37e6a35107
--- /dev/null
+++ b/chromium/components/download/public/common/rate_estimator.h
@@ -0,0 +1,54 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_RATE_ESTIMATOR_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_RATE_ESTIMATOR_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "base/time/time.h"
+#include "components/download/public/common/download_export.h"
+
+namespace download {
+
+// RateEstimator generates rate estimates based on recent activity.
+//
+// Internally it uses a fixed-size ring buffer, and develops estimates
+// based on a small sliding window of activity.
+class COMPONENTS_DOWNLOAD_EXPORT RateEstimator {
+ public:
+ RateEstimator();
+ RateEstimator(base::TimeDelta bucket_time,
+ size_t num_buckets,
+ base::TimeTicks now);
+ ~RateEstimator();
+
+ // Increment the counter by |count|. The first variant uses the current time,
+ // the second variant provides the time that |count| is observed.
+ void Increment(uint32_t count);
+ void Increment(uint32_t count, base::TimeTicks now);
+
+ // Get a rate estimate, in terms of counts/second. The first variant uses the
+ // current time, the second variant provides the time.
+ uint64_t GetCountPerSecond() const;
+ uint64_t GetCountPerSecond(base::TimeTicks now) const;
+
+ private:
+ void ClearOldBuckets(base::TimeTicks now);
+ void ResetBuckets(base::TimeTicks now);
+
+ std::vector<uint32_t> history_;
+ base::TimeDelta bucket_time_;
+ size_t oldest_index_;
+ size_t bucket_count_;
+ base::TimeTicks oldest_time_;
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_RATE_ESTIMATOR_H_
diff --git a/chromium/components/download/public/common/resume_mode.h b/chromium/components/download/public/common/resume_mode.h
new file mode 100644
index 00000000000..eb8b0a43668
--- /dev/null
+++ b/chromium/components/download/public/common/resume_mode.h
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_RESUME_MODE_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_RESUME_MODE_H_
+
+// The means by which the download was resumed.
+// Used by DownloadItemImpl and UKM metrics.
+namespace download {
+
+enum class ResumeMode {
+ INVALID = 0,
+ IMMEDIATE_CONTINUE,
+ IMMEDIATE_RESTART,
+ USER_CONTINUE,
+ USER_RESTART
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_RESUME_MODE_H_
diff --git a/chromium/components/download/public/features.h b/chromium/components/download/public/features.h
deleted file mode 100644
index 13117191bc8..00000000000
--- a/chromium/components/download/public/features.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_DOWNLOAD_PUBLIC_FEATURES_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_FEATURES_H_
-
-#include "base/feature_list.h"
-
-namespace download {
-
-extern const base::Feature kDownloadServiceFeature;
-
-} // namespace download
-
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_FEATURES_H_
diff --git a/chromium/components/download/quarantine/BUILD.gn b/chromium/components/download/quarantine/BUILD.gn
new file mode 100644
index 00000000000..2c4014c5e60
--- /dev/null
+++ b/chromium/components/download/quarantine/BUILD.gn
@@ -0,0 +1,59 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/chromecast_build.gni")
+
+if (is_android) {
+ import("//build/config/android/rules.gni")
+}
+
+static_library("quarantine") {
+ sources = [
+ "quarantine.cc",
+ "quarantine.h",
+ "quarantine_constants_linux.h",
+ "quarantine_linux.cc",
+ "quarantine_mac.mm",
+ "quarantine_win.cc",
+ ]
+
+ deps = [
+ "//base",
+ "//net",
+ "//url",
+ ]
+
+ if (is_mac) {
+ libs = [
+ "Carbon.framework",
+ "Foundation.framework",
+ ]
+ }
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "quarantine_linux_unittest.cc",
+ "quarantine_mac_unittest.mm",
+ "quarantine_win_unittest.cc",
+ ]
+
+ # Chromecasts do not have extended attributes enabled; even if it were
+ # enabled, the devices use tmpfs which restricts the extended attributes that
+ # can be set such that quarantining still would not work. (The platform
+ # specific tests include a runtime guard to skip tests that need xattr.)
+ if (!is_chromecast) {
+ sources += [ "quarantine_unittest.cc" ]
+ }
+
+ deps = [
+ ":quarantine",
+ "//base",
+ "//base/test:test_support",
+ "//net",
+ "//testing/gtest",
+ "//url",
+ ]
+}
diff --git a/chromium/components/download/quarantine/DEPS b/chromium/components/download/quarantine/DEPS
new file mode 100644
index 00000000000..14fd9aaa042
--- /dev/null
+++ b/chromium/components/download/quarantine/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+net/base/filename_util.h",
+] \ No newline at end of file
diff --git a/chromium/components/download/quarantine/quarantine.cc b/chromium/components/download/quarantine/quarantine.cc
new file mode 100644
index 00000000000..a8fa994166b
--- /dev/null
+++ b/chromium/components/download/quarantine/quarantine.cc
@@ -0,0 +1,28 @@
+// 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/download/quarantine/quarantine.h"
+
+#include "build/build_config.h"
+
+#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX)
+
+namespace download {
+
+QuarantineFileResult QuarantineFile(const base::FilePath& file,
+ const GURL& source_url,
+ const GURL& referrer_url,
+ const std::string& client_guid) {
+ return QuarantineFileResult::OK;
+}
+
+bool IsFileQuarantined(const base::FilePath& file,
+ const GURL& source_url,
+ const GURL& referrer_url) {
+ return false;
+}
+
+} // namespace download
+
+#endif // !WIN && !MAC && !LINUX
diff --git a/chromium/components/download/quarantine/quarantine.h b/chromium/components/download/quarantine/quarantine.h
new file mode 100644
index 00000000000..cdd296d8f5e
--- /dev/null
+++ b/chromium/components/download/quarantine/quarantine.h
@@ -0,0 +1,103 @@
+// 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_DOWNLOAD_QUARANTINE_QUARANTINE_H_
+#define COMPONENTS_DOWNLOAD_QUARANTINE_QUARANTINE_H_
+
+#include <string>
+
+class GURL;
+
+namespace base {
+class FilePath;
+}
+
+namespace download {
+
+// Return value for QuarantineFile.
+enum class QuarantineFileResult {
+ OK, // Success.
+ ACCESS_DENIED, // Access to the file was denied. The safety of the file could
+ // not be determined.
+ BLOCKED_BY_POLICY, // Downloads from |source_url| are not allowed by policy.
+ // The file has been deleted.
+ ANNOTATION_FAILED, // Unable to write the mark-of-the-web or otherwise
+ // annotate the file as being downloaded from
+ // |source_url|.
+ FILE_MISSING, // |file| does not name a valid file.
+ SECURITY_CHECK_FAILED, // An unknown error occurred while checking |file|.
+ // The file may have been deleted.
+ VIRUS_INFECTED // |file| was found to be infected by a virus and was deleted.
+};
+
+// Quarantine a file that was downloaded from the internet.
+//
+// Ensures that |file| is handled as safely as possible given that it was
+// downloaded from |source_url|. The details of how a downloaded file is handled
+// are platform dependent. Please refer to the individual quarantine_<os>
+// implementation.
+//
+// This function should be called for all files downloaded from the internet and
+// placed in a manner discoverable by the user, or exposed to an external
+// application. Furthermore, it should be called:
+//
+// * **AFTER** all the data has been written to the file. On Windows, registered
+// anti-virus products will be invoked for scanning the contents of the file.
+// Hence it's important to have the final contents of the file be available at
+// the point at which this function is called.
+//
+// Exception: Zero-length files will be handled solely on the basis of the
+// |source_url| and the file type. This exception accommodates situations
+// where the file contents cannot be determined before it is made visible to
+// an external application.
+//
+// * **AFTER** the file has been renamed to its final name. The file type is
+// significant and is derived from the filename.
+//
+// * **BEFORE** the file is made visible to an external application or the user.
+// Security checks and mark-of-the-web annotations must be made prior to
+// exposing the file externally.
+//
+// Note that it is possible for this method to take a long time to complete
+// (several seconds or more). In addition to blocking during this time, this
+// delay also introduces a window during which a browser shutdown may leave the
+// downloaded file unannotated.
+//
+// Parameters:
+// |file| : Final name of the file.
+// |source_url|: URL from which the file content was downloaded.
+// |referrer_url|: Referring URL.
+// |client_guid|: Only used on Windows. Identifies the client application
+// that downloaded the file.
+QuarantineFileResult QuarantineFile(const base::FilePath& file,
+ const GURL& source_url,
+ const GURL& referrer_url,
+ const std::string& client_guid);
+
+// Determine if a file has quarantine metadata attached to it.
+//
+// If |source_url| is non-empty, then the download source URL in
+// quarantine metadata should match |source_url| exactly. The function returns
+// |false| if there is a mismatch. If |source_url| is empty, then this function
+// only checks for the existence of a download source URL in quarantine
+// metadata.
+//
+// If |referrer_url| is valid, then the download referrer URL in quarantine
+// metadata must match |referrer_url| exactly. The function returns |false| if
+// there is a mismatch in the |referrer_url| even if the |source_url| matches.
+// No referrer URL checks are performed if |referrer_url| is empty.
+//
+// If both |source_url| and |referrer_url|, then the funciton returns true if
+// any quarantine metadata is present for the file.
+//
+// **Note**: On Windows, this function only checks if the |ZoneIdentifier|
+// metadata is present. |source_url| and |referrer_url| are ignored. Windows
+// currently doesn't store individual URLs as part of the mark-of-the-web.
+bool IsFileQuarantined(const base::FilePath& file,
+ const GURL& source_url,
+ const GURL& referrer_url);
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_QUARANTINE_QUARANTINE_H_
diff --git a/chromium/components/download/quarantine/quarantine_constants_linux.h b/chromium/components/download/quarantine/quarantine_constants_linux.h
new file mode 100644
index 00000000000..31bb4745c2e
--- /dev/null
+++ b/chromium/components/download/quarantine/quarantine_constants_linux.h
@@ -0,0 +1,21 @@
+// 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_DOWNLOAD_QUARANTINE_QUARANTINE_CONSTANTS_LINUX_H_
+#define COMPONENTS_DOWNLOAD_QUARANTINE_QUARANTINE_CONSTANTS_LINUX_H_
+
+namespace download {
+
+// Attribute names to be used with setxattr and friends.
+//
+// The source URL attribute is part of the XDG standard.
+// The referrer URL attribute is not part of the XDG standard,
+// but it is used to keep the naming consistent.
+// http://freedesktop.org/wiki/CommonExtendedAttributes
+extern const char kSourceURLExtendedAttrName[];
+extern const char kReferrerURLExtendedAttrName[];
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_QUARANTINE_QUARANTINE_CONSTANTS_LINUX_H_
diff --git a/chromium/components/download/quarantine/quarantine_linux.cc b/chromium/components/download/quarantine/quarantine_linux.cc
new file mode 100644
index 00000000000..fe932fe00ba
--- /dev/null
+++ b/chromium/components/download/quarantine/quarantine_linux.cc
@@ -0,0 +1,100 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/quarantine/quarantine.h"
+
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
+#include "components/download/quarantine/quarantine.h"
+#include "components/download/quarantine/quarantine_constants_linux.h"
+#include "url/gurl.h"
+
+namespace download {
+
+const char kSourceURLExtendedAttrName[] = "user.xdg.origin.url";
+const char kReferrerURLExtendedAttrName[] = "user.xdg.referrer.url";
+
+namespace {
+
+bool SetExtendedFileAttribute(const char* path,
+ const char* name,
+ const char* value,
+ size_t value_size,
+ int flags) {
+ base::AssertBlockingAllowed();
+ int result = setxattr(path, name, value, value_size, flags);
+ if (result) {
+ DPLOG(ERROR) << "Could not set extended attribute " << name << " on file "
+ << path;
+ return false;
+ }
+ return true;
+}
+
+std::string GetExtendedFileAttribute(const char* path, const char* name) {
+ base::AssertBlockingAllowed();
+ ssize_t len = getxattr(path, name, nullptr, 0);
+ if (len <= 0)
+ return std::string();
+
+ std::vector<char> buffer(len);
+ len = getxattr(path, name, buffer.data(), buffer.size());
+ if (len < static_cast<ssize_t>(buffer.size()))
+ return std::string();
+ return std::string(buffer.begin(), buffer.end());
+}
+
+} // namespace
+
+QuarantineFileResult QuarantineFile(const base::FilePath& file,
+ const GURL& source_url,
+ const GURL& referrer_url,
+ const std::string& client_guid) {
+ DCHECK(base::PathIsWritable(file));
+
+ bool source_succeeded =
+ source_url.is_valid() &&
+ SetExtendedFileAttribute(file.value().c_str(), kSourceURLExtendedAttrName,
+ source_url.spec().c_str(),
+ source_url.spec().length(), 0);
+
+ // Referrer being empty is not considered an error. This could happen if the
+ // referrer policy resulted in an empty referrer for the download request.
+ bool referrer_succeeded =
+ !referrer_url.is_valid() ||
+ SetExtendedFileAttribute(
+ file.value().c_str(), kReferrerURLExtendedAttrName,
+ referrer_url.spec().c_str(), referrer_url.spec().length(), 0);
+ return source_succeeded && referrer_succeeded
+ ? QuarantineFileResult::OK
+ : QuarantineFileResult::ANNOTATION_FAILED;
+}
+
+bool IsFileQuarantined(const base::FilePath& file,
+ const GURL& source_url,
+ const GURL& referrer_url) {
+ if (!base::PathExists(file))
+ return false;
+
+ std::string url_value = GetExtendedFileAttribute(file.value().c_str(),
+ kSourceURLExtendedAttrName);
+ if (source_url.is_empty())
+ return !url_value.empty();
+
+ if (source_url != GURL(url_value))
+ return false;
+
+ return !referrer_url.is_valid() ||
+ GURL(GetExtendedFileAttribute(file.value().c_str(),
+ kReferrerURLExtendedAttrName)) ==
+ referrer_url;
+}
+
+} // namespace download
diff --git a/chromium/components/download/quarantine/quarantine_linux_unittest.cc b/chromium/components/download/quarantine/quarantine_linux_unittest.cc
new file mode 100644
index 00000000000..b34d61ab58d
--- /dev/null
+++ b/chromium/components/download/quarantine/quarantine_linux_unittest.cc
@@ -0,0 +1,183 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <errno.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+
+#include <algorithm>
+#include <sstream>
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/strings/string_split.h"
+#include "components/download/quarantine/quarantine.h"
+#include "components/download/quarantine/quarantine_constants_linux.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace download {
+namespace {
+
+using std::istringstream;
+using std::string;
+using std::vector;
+
+class QuarantineLinuxTest : public testing::Test {
+ public:
+ QuarantineLinuxTest()
+ : source_url_("http://www.source.com"),
+ referrer_url_("http://www.referrer.com"),
+ is_xattr_supported_(false) {}
+
+ const base::FilePath& test_file() const { return test_file_; }
+
+ const base::FilePath& test_dir() const { return temp_dir_.GetPath(); }
+
+ const GURL& source_url() const { return source_url_; }
+
+ const GURL& referrer_url() const { return referrer_url_; }
+
+ bool is_xattr_supported() const { return is_xattr_supported_; }
+
+ protected:
+ void SetUp() override {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ ASSERT_TRUE(
+ base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &test_file_));
+ int result =
+ setxattr(test_file_.value().c_str(), "user.test", "test", 4, 0);
+ is_xattr_supported_ = (!result) || (errno != ENOTSUP);
+ if (!is_xattr_supported_) {
+ LOG(WARNING) << "Test will be skipped because extended attributes are "
+ "not supported on this OS/file system.";
+ }
+ }
+
+ void GetExtendedAttributeNames(vector<string>* attr_names) const {
+ ssize_t len = listxattr(test_file().value().c_str(), nullptr, 0);
+ if (len <= static_cast<ssize_t>(0))
+ return;
+ char* buffer = new char[len];
+ len = listxattr(test_file().value().c_str(), buffer, len);
+ *attr_names =
+ base::SplitString(string(buffer, len), std::string(1, '\0'),
+ base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ delete[] buffer;
+ }
+
+ private:
+ base::ScopedTempDir temp_dir_;
+ base::FilePath test_file_;
+ GURL source_url_;
+ GURL referrer_url_;
+ bool is_xattr_supported_;
+};
+
+} // namespace
+
+TEST_F(QuarantineLinuxTest, CheckMetadataSetCorrectly) {
+ if (!is_xattr_supported())
+ return;
+ EXPECT_EQ(
+ QuarantineFileResult::OK,
+ QuarantineFile(test_file(), source_url(), referrer_url(), std::string()));
+ EXPECT_TRUE(IsFileQuarantined(test_file(), source_url(), referrer_url()));
+}
+
+TEST_F(QuarantineLinuxTest, SetMetadataMultipleTimes) {
+ if (!is_xattr_supported())
+ return;
+ GURL dummy_url("http://www.dummy.com");
+ EXPECT_EQ(QuarantineFileResult::OK,
+ QuarantineFile(test_file(), dummy_url, dummy_url, std::string()));
+ EXPECT_EQ(
+ QuarantineFileResult::OK,
+ QuarantineFile(test_file(), source_url(), referrer_url(), std::string()));
+ EXPECT_TRUE(IsFileQuarantined(test_file(), source_url(), referrer_url()));
+}
+
+TEST_F(QuarantineLinuxTest, InvalidSourceURLTest) {
+ if (!is_xattr_supported())
+ return;
+ GURL invalid_url;
+ vector<string> attr_names;
+ EXPECT_EQ(
+ QuarantineFileResult::ANNOTATION_FAILED,
+ QuarantineFile(test_file(), invalid_url, referrer_url(), std::string()));
+ GetExtendedAttributeNames(&attr_names);
+ EXPECT_EQ(attr_names.end(), find(attr_names.begin(), attr_names.end(),
+ kSourceURLExtendedAttrName));
+ EXPECT_NE(attr_names.end(), find(attr_names.begin(), attr_names.end(),
+ kReferrerURLExtendedAttrName));
+}
+
+TEST_F(QuarantineLinuxTest, InvalidReferrerURLTest) {
+ if (!is_xattr_supported())
+ return;
+ GURL invalid_url;
+ vector<string> attr_names;
+ EXPECT_EQ(
+ QuarantineFileResult::OK,
+ QuarantineFile(test_file(), source_url(), invalid_url, std::string()));
+ GetExtendedAttributeNames(&attr_names);
+ EXPECT_EQ(attr_names.end(), find(attr_names.begin(), attr_names.end(),
+ kReferrerURLExtendedAttrName));
+ EXPECT_TRUE(IsFileQuarantined(test_file(), source_url(), GURL()));
+}
+
+TEST_F(QuarantineLinuxTest, InvalidURLsTest) {
+ if (!is_xattr_supported())
+ return;
+ GURL invalid_url;
+ vector<string> attr_names;
+ EXPECT_EQ(
+ QuarantineFileResult::ANNOTATION_FAILED,
+ QuarantineFile(test_file(), invalid_url, invalid_url, std::string()));
+ GetExtendedAttributeNames(&attr_names);
+ EXPECT_EQ(attr_names.end(), find(attr_names.begin(), attr_names.end(),
+ kSourceURLExtendedAttrName));
+ EXPECT_EQ(attr_names.end(), find(attr_names.begin(), attr_names.end(),
+ kReferrerURLExtendedAttrName));
+ EXPECT_FALSE(IsFileQuarantined(test_file(), GURL(), GURL()));
+}
+
+TEST_F(QuarantineLinuxTest, IsFileQuarantined) {
+ if (!is_xattr_supported())
+ return;
+ base::FilePath does_not_exist = test_dir().AppendASCII("a.jar");
+ EXPECT_FALSE(IsFileQuarantined(does_not_exist, GURL(), GURL()));
+
+ base::FilePath no_annotations = test_dir().AppendASCII("b.jar");
+ ASSERT_EQ(5, base::WriteFile(no_annotations, "Hello", 5));
+ EXPECT_FALSE(IsFileQuarantined(no_annotations, GURL(), GURL()));
+
+ base::FilePath source_only = test_dir().AppendASCII("c.jar");
+ ASSERT_EQ(5, base::WriteFile(source_only, "Hello", 5));
+ ASSERT_EQ(QuarantineFileResult::OK,
+ QuarantineFile(source_only, source_url(), GURL(), std::string()));
+ EXPECT_TRUE(IsFileQuarantined(source_only, source_url(), GURL()));
+ EXPECT_TRUE(IsFileQuarantined(source_only, GURL(), GURL()));
+ EXPECT_TRUE(IsFileQuarantined(source_only, GURL(), referrer_url()));
+ EXPECT_FALSE(IsFileQuarantined(source_only, referrer_url(), GURL()));
+
+ base::FilePath fully_annotated = test_dir().AppendASCII("d.jar");
+ ASSERT_EQ(5, base::WriteFile(fully_annotated, "Hello", 5));
+ ASSERT_EQ(QuarantineFileResult::OK,
+ QuarantineFile(fully_annotated, source_url(), referrer_url(),
+ std::string()));
+ EXPECT_TRUE(IsFileQuarantined(fully_annotated, GURL(), GURL()));
+ EXPECT_TRUE(IsFileQuarantined(fully_annotated, source_url(), GURL()));
+ EXPECT_TRUE(IsFileQuarantined(fully_annotated, source_url(), referrer_url()));
+ EXPECT_TRUE(IsFileQuarantined(fully_annotated, GURL(), referrer_url()));
+ EXPECT_FALSE(IsFileQuarantined(fully_annotated, source_url(), source_url()));
+ EXPECT_FALSE(
+ IsFileQuarantined(fully_annotated, referrer_url(), referrer_url()));
+}
+
+} // namespace download
diff --git a/chromium/components/download/quarantine/quarantine_mac.mm b/chromium/components/download/quarantine/quarantine_mac.mm
new file mode 100644
index 00000000000..aa5d013cf92
--- /dev/null
+++ b/chromium/components/download/quarantine/quarantine_mac.mm
@@ -0,0 +1,342 @@
+// 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/download/quarantine/quarantine.h"
+
+#import <ApplicationServices/ApplicationServices.h>
+#import <Foundation/Foundation.h>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/mac/availability.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/mac_logging.h"
+#include "base/mac/mac_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/threading/thread_restrictions.h"
+#include "url/gurl.h"
+
+namespace {
+
+// Once Chrome no longer supports macOS 10.9, this code will no longer be
+// necessary. Note that LSCopyItemAttribute was deprecated in macOS 10.8, but
+// the replacement to kLSItemQuarantineProperties did not exist until macOS
+// 10.10.
+#if !defined(MAC_OS_X_VERSION_10_10) || \
+ MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+bool GetQuarantinePropertiesDeprecated(
+ const base::FilePath& file,
+ base::scoped_nsobject<NSMutableDictionary>* properties) {
+ const UInt8* path = reinterpret_cast<const UInt8*>(file.value().c_str());
+ FSRef file_ref;
+ if (FSPathMakeRef(path, &file_ref, nullptr) != noErr)
+ return false;
+
+ base::ScopedCFTypeRef<CFTypeRef> quarantine_properties;
+ OSStatus status =
+ LSCopyItemAttribute(&file_ref, kLSRolesAll, kLSItemQuarantineProperties,
+ quarantine_properties.InitializeInto());
+ if (status != noErr)
+ return true;
+
+ CFDictionaryRef quarantine_properties_dict =
+ base::mac::CFCast<CFDictionaryRef>(quarantine_properties.get());
+ if (!quarantine_properties_dict) {
+ LOG(WARNING) << "kLSItemQuarantineProperties is not a dictionary on file "
+ << file.value();
+ return false;
+ }
+
+ properties->reset(
+ [base::mac::CFToNSCast(quarantine_properties_dict) mutableCopy]);
+ return true;
+}
+
+bool SetQuarantinePropertiesDeprecated(const base::FilePath& file,
+ NSDictionary* properties) {
+ const UInt8* path = reinterpret_cast<const UInt8*>(file.value().c_str());
+ FSRef file_ref;
+ if (FSPathMakeRef(path, &file_ref, nullptr) != noErr)
+ return false;
+
+ OSStatus os_error = LSSetItemAttribute(
+ &file_ref, kLSRolesAll, kLSItemQuarantineProperties, properties);
+ if (os_error != noErr) {
+ OSSTATUS_LOG(WARNING, os_error)
+ << "Unable to set quarantine attributes on file " << file.value();
+ return false;
+ }
+ return true;
+}
+#pragma clang diagnostic pop
+#endif
+
+API_AVAILABLE(macos(10.10))
+bool GetQuarantineProperties(
+ const base::FilePath& file,
+ base::scoped_nsobject<NSMutableDictionary>* properties) {
+ base::scoped_nsobject<NSURL> file_url([[NSURL alloc]
+ initFileURLWithPath:base::SysUTF8ToNSString(file.value())]);
+ if (!file_url)
+ return false;
+
+ NSError* error = nil;
+ id quarantine_properties = nil;
+ BOOL success = [file_url getResourceValue:&quarantine_properties
+ forKey:NSURLQuarantinePropertiesKey
+ error:&error];
+ if (!success) {
+ std::string error_message(error ? error.description.UTF8String : "");
+ LOG(WARNING) << "Unable to get quarantine attributes for file "
+ << file.value() << ". Error: " << error_message;
+ return false;
+ }
+
+ if (!quarantine_properties)
+ return true;
+
+ NSDictionary* quarantine_properties_dict =
+ base::mac::ObjCCast<NSDictionary>(quarantine_properties);
+ if (!quarantine_properties_dict) {
+ LOG(WARNING) << "Quarantine properties have wrong class: "
+ << base::SysNSStringToUTF8(
+ [[quarantine_properties class] description]);
+ return false;
+ }
+
+ properties->reset([quarantine_properties_dict mutableCopy]);
+ return true;
+}
+
+API_AVAILABLE(macos(10.10))
+bool SetQuarantineProperties(const base::FilePath& file,
+ NSDictionary* properties) {
+ base::scoped_nsobject<NSURL> file_url([[NSURL alloc]
+ initFileURLWithPath:base::SysUTF8ToNSString(file.value())]);
+ if (!file_url)
+ return false;
+
+ NSError* error = nil;
+ bool success = [file_url setResourceValue:properties
+ forKey:NSURLQuarantinePropertiesKey
+ error:&error];
+ if (!success) {
+ std::string error_message(error ? error.description.UTF8String : "");
+ LOG(WARNING) << "Unable to set quarantine attributes on file "
+ << file.value() << ". Error: " << error_message;
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+namespace download {
+
+namespace {
+
+// As of Mac OS X 10.4 ("Tiger"), files can be tagged with metadata describing
+// various attributes. Metadata is integrated with the system's Spotlight
+// feature and is searchable. Ordinarily, metadata can only be set by
+// Spotlight importers, which requires that the importer own the target file.
+// However, there's an attribute intended to describe the origin of a
+// file, that can store the source URL and referrer of a downloaded file.
+// It's stored as a "com.apple.metadata:kMDItemWhereFroms" extended attribute,
+// structured as a binary1-format plist containing a list of sources. This
+// attribute can only be populated by the downloader, not a Spotlight importer.
+// Safari on 10.4 and later populates this attribute.
+//
+// With this metadata set, you can locate downloads by performing a Spotlight
+// search for their source or referrer URLs, either from within the Spotlight
+// UI or from the command line:
+// mdfind 'kMDItemWhereFroms == "http://releases.mozilla.org/*"'
+//
+// There is no documented API to set metadata on a file directly as of the
+// 10.5 SDK. The MDSetItemAttribute function does exist to perform this task,
+// but it's undocumented.
+bool AddOriginMetadataToFile(const base::FilePath& file,
+ const GURL& source,
+ const GURL& referrer) {
+ base::AssertBlockingAllowed();
+ // There's no declaration for MDItemSetAttribute in any known public SDK.
+ // It exists in the 10.4 and 10.5 runtimes. To play it safe, do the lookup
+ // at runtime instead of declaring it ourselves and linking against what's
+ // provided. This has two benefits:
+ // - If Apple relents and declares the function in a future SDK (it's
+ // happened before), our build won't break.
+ // - If Apple removes or renames the function in a future runtime, the
+ // loader won't refuse to let the application launch. Instead, we'll
+ // silently fail to set any metadata.
+ typedef OSStatus (*MDItemSetAttribute_type)(MDItemRef, CFStringRef,
+ CFTypeRef);
+ static MDItemSetAttribute_type md_item_set_attribute_func = NULL;
+
+ static bool did_symbol_lookup = false;
+ if (!did_symbol_lookup) {
+ did_symbol_lookup = true;
+ CFBundleRef metadata_bundle =
+ CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Metadata"));
+ if (!metadata_bundle)
+ return false;
+
+ md_item_set_attribute_func =
+ (MDItemSetAttribute_type)CFBundleGetFunctionPointerForName(
+ metadata_bundle, CFSTR("MDItemSetAttribute"));
+ }
+ if (!md_item_set_attribute_func)
+ return false;
+
+ NSString* file_path = [NSString stringWithUTF8String:file.value().c_str()];
+ if (!file_path)
+ return false;
+
+ base::ScopedCFTypeRef<MDItemRef> md_item(
+ MDItemCreate(NULL, base::mac::NSToCFCast(file_path)));
+ if (!md_item) {
+ LOG(WARNING) << "MDItemCreate failed for path " << file.value();
+ return false;
+ }
+
+ // We won't put any more than 2 items into the attribute.
+ NSMutableArray* list = [NSMutableArray arrayWithCapacity:2];
+
+ // Follow Safari's lead: the first item in the list is the source URL of
+ // the downloaded file. If the referrer is known, store that, too.
+ NSString* origin_url = [NSString stringWithUTF8String:source.spec().c_str()];
+ if (origin_url)
+ [list addObject:origin_url];
+ NSString* referrer_url =
+ [NSString stringWithUTF8String:referrer.spec().c_str()];
+ if (referrer_url)
+ [list addObject:referrer_url];
+
+ md_item_set_attribute_func(md_item, kMDItemWhereFroms,
+ base::mac::NSToCFCast(list));
+ return true;
+}
+
+// Adds quarantine metadata to the file, assuming it has already been
+// quarantined by the OS.
+// |source| should be the source URL for the download, and |referrer| should be
+// the URL the user initiated the download from.
+
+// The OS will automatically quarantine files due to the
+// LSFileQuarantineEnabled entry in our Info.plist, but it knows relatively
+// little about the files. We add more information about the download to
+// improve the UI shown by the OS when the users tries to open the file.
+bool AddQuarantineMetadataToFile(const base::FilePath& file,
+ const GURL& source,
+ const GURL& referrer) {
+ base::AssertBlockingAllowed();
+ base::scoped_nsobject<NSMutableDictionary> properties;
+ bool success = false;
+ if (@available(macos 10.10, *)) {
+ success = GetQuarantineProperties(file, &properties);
+ } else {
+ success = GetQuarantinePropertiesDeprecated(file, &properties);
+ }
+
+ if (!success)
+ return false;
+
+ if (!properties) {
+ // If there are no quarantine properties, then the file isn't quarantined
+ // (e.g., because the user has set up exclusions for certain file types).
+ // We don't want to add any metadata, because that will cause the file to
+ // be quarantined against the user's wishes.
+ return true;
+ }
+
+ // kLSQuarantineAgentNameKey, kLSQuarantineAgentBundleIdentifierKey, and
+ // kLSQuarantineTimeStampKey are set for us (see LSQuarantine.h), so we only
+ // need to set the values that the OS can't infer.
+
+ if (![properties valueForKey:(NSString*)kLSQuarantineTypeKey]) {
+ CFStringRef type = source.SchemeIsHTTPOrHTTPS()
+ ? kLSQuarantineTypeWebDownload
+ : kLSQuarantineTypeOtherDownload;
+ [properties setValue:(NSString*)type
+ forKey:(NSString*)kLSQuarantineTypeKey];
+ }
+
+ if (![properties valueForKey:(NSString*)kLSQuarantineOriginURLKey] &&
+ referrer.is_valid()) {
+ NSString* referrer_url =
+ [NSString stringWithUTF8String:referrer.spec().c_str()];
+ [properties setValue:referrer_url
+ forKey:(NSString*)kLSQuarantineOriginURLKey];
+ }
+
+ if (![properties valueForKey:(NSString*)kLSQuarantineDataURLKey] &&
+ source.is_valid()) {
+ NSString* origin_url =
+ [NSString stringWithUTF8String:source.spec().c_str()];
+ [properties setValue:origin_url forKey:(NSString*)kLSQuarantineDataURLKey];
+ }
+
+ if (@available(macos 10.10, *)) {
+ return SetQuarantineProperties(file, properties);
+ } else {
+ return SetQuarantinePropertiesDeprecated(file, properties);
+ }
+}
+
+} // namespace
+
+QuarantineFileResult QuarantineFile(const base::FilePath& file,
+ const GURL& source_url,
+ const GURL& referrer_url,
+ const std::string& client_guid) {
+ if (!base::PathExists(file))
+ return QuarantineFileResult::FILE_MISSING;
+
+ // Don't consider it an error if we fail to add origin metadata.
+ AddOriginMetadataToFile(file, source_url, referrer_url);
+ bool quarantine_succeeded =
+ AddQuarantineMetadataToFile(file, source_url, referrer_url);
+ return quarantine_succeeded ? QuarantineFileResult::OK
+ : QuarantineFileResult::ANNOTATION_FAILED;
+}
+
+bool IsFileQuarantined(const base::FilePath& file,
+ const GURL& expected_source_url,
+ const GURL& referrer_url) {
+ base::AssertBlockingAllowed();
+
+ if (!base::PathExists(file))
+ return false;
+
+ base::scoped_nsobject<NSMutableDictionary> properties;
+ bool success = false;
+ if (@available(macos 10.10, *)) {
+ success = GetQuarantineProperties(file, &properties);
+ } else {
+ success = GetQuarantinePropertiesDeprecated(file, &properties);
+ }
+
+ if (!success || !properties)
+ return false;
+
+ NSString* source_url =
+ [[properties valueForKey:(NSString*)kLSQuarantineDataURLKey] description];
+
+ if (!expected_source_url.is_valid())
+ return [source_url length] > 0;
+
+ if (![source_url
+ isEqualToString:base::SysUTF8ToNSString(expected_source_url.spec())])
+ return false;
+
+ return !referrer_url.is_valid() ||
+ [[[properties valueForKey:(NSString*)kLSQuarantineOriginURLKey]
+ description]
+ isEqualToString:base::SysUTF8ToNSString(referrer_url.spec())];
+}
+
+} // namespace download
diff --git a/chromium/components/download/quarantine/quarantine_mac_unittest.mm b/chromium/components/download/quarantine/quarantine_mac_unittest.mm
new file mode 100644
index 00000000000..7cbccd3b9c9
--- /dev/null
+++ b/chromium/components/download/quarantine/quarantine_mac_unittest.mm
@@ -0,0 +1,122 @@
+// 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 <sys/xattr.h>
+
+#import <Foundation/Foundation.h>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/mac/availability.h"
+#include "base/mac/mac_util.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/download/quarantine/quarantine.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+#include "url/gurl.h"
+
+namespace download {
+namespace {
+
+class QuarantineMacTest : public testing::Test {
+ public:
+ QuarantineMacTest()
+ : source_url_("http://www.source.example.com"),
+ referrer_url_("http://www.referrer.example.com") {}
+
+ protected:
+ void SetUp() override {
+ if (@available(macos 10.10, *)) {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ ASSERT_TRUE(
+ base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &test_file_));
+ file_url_.reset([[NSURL alloc]
+ initFileURLWithPath:base::SysUTF8ToNSString(test_file_.value())]);
+
+ base::scoped_nsobject<NSMutableDictionary> properties(
+ [[NSMutableDictionary alloc] init]);
+ [properties setValue:@"com.google.Chrome"
+ forKey:static_cast<NSString*>(
+ kLSQuarantineAgentBundleIdentifierKey)];
+ [properties setValue:@"Google Chrome.app"
+ forKey:static_cast<NSString*>(kLSQuarantineAgentNameKey)];
+ [properties setValue:@(1) forKey:@"kLSQuarantineIsOwnedByCurrentUserKey"];
+ bool success = [file_url_ setResourceValue:properties
+ forKey:NSURLQuarantinePropertiesKey
+ error:nullptr];
+ ASSERT_TRUE(success);
+ } else {
+ LOG(WARNING) << "Test suite requires Mac OS X 10.10 or later";
+ }
+ }
+
+ base::ScopedTempDir temp_dir_;
+ base::FilePath test_file_;
+ GURL source_url_;
+ GURL referrer_url_;
+ base::scoped_nsobject<NSURL> file_url_;
+};
+
+TEST_F(QuarantineMacTest, CheckMetadataSetCorrectly) {
+ if (base::mac::IsAtMostOS10_9())
+ return;
+ EXPECT_EQ(QuarantineFileResult::OK,
+ QuarantineFile(test_file_, source_url_, referrer_url_, ""));
+ EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, referrer_url_));
+}
+
+TEST_F(QuarantineMacTest, SetMetadataMultipleTimes) {
+ if (base::mac::IsAtMostOS10_9())
+ return;
+ 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, ""));
+ EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, referrer_url_));
+}
+
+TEST_F(QuarantineMacTest, IsFileQuarantined_NoFile) {
+ if (base::mac::IsAtMostOS10_9())
+ return;
+ base::FilePath does_not_exist = temp_dir_.GetPath().AppendASCII("a.jar");
+ EXPECT_FALSE(IsFileQuarantined(does_not_exist, GURL(), GURL()));
+}
+
+TEST_F(QuarantineMacTest, IsFileQuarantined_NoAnnotationsOnFile) {
+ if (base::mac::IsAtMostOS10_9())
+ return;
+ EXPECT_FALSE(IsFileQuarantined(test_file_, GURL(), GURL()));
+}
+
+TEST_F(QuarantineMacTest, IsFileQuarantined_SourceUrlOnly) {
+ if (base::mac::IsAtMostOS10_9())
+ return;
+ ASSERT_EQ(QuarantineFileResult::OK,
+ QuarantineFile(test_file_, source_url_, GURL(), std::string()));
+ EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, GURL()));
+ EXPECT_TRUE(IsFileQuarantined(test_file_, GURL(), GURL()));
+ EXPECT_TRUE(IsFileQuarantined(test_file_, GURL(), referrer_url_));
+ EXPECT_FALSE(IsFileQuarantined(test_file_, referrer_url_, GURL()));
+}
+
+TEST_F(QuarantineMacTest, IsFileQuarantined_FullMetadata) {
+ if (base::mac::IsAtMostOS10_9())
+ return;
+ ASSERT_EQ(
+ QuarantineFileResult::OK,
+ QuarantineFile(test_file_, source_url_, referrer_url_, std::string()));
+ EXPECT_TRUE(IsFileQuarantined(test_file_, GURL(), GURL()));
+ EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, GURL()));
+ EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, referrer_url_));
+ EXPECT_TRUE(IsFileQuarantined(test_file_, GURL(), referrer_url_));
+ EXPECT_FALSE(IsFileQuarantined(test_file_, source_url_, source_url_));
+ EXPECT_FALSE(IsFileQuarantined(test_file_, referrer_url_, referrer_url_));
+}
+
+} // namespace
+} // namespace downlod
diff --git a/chromium/components/download/quarantine/quarantine_unittest.cc b/chromium/components/download/quarantine/quarantine_unittest.cc
new file mode 100644
index 00000000000..0c73c4974bc
--- /dev/null
+++ b/chromium/components/download/quarantine/quarantine_unittest.cc
@@ -0,0 +1,58 @@
+// 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/download/quarantine/quarantine.h"
+
+#include <iterator>
+#include <string>
+
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace download {
+
+namespace {
+
+const char kTestData[] = "It's okay to have a trailing nul.";
+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";
+
+} // namespace
+
+TEST(QuarantineTest, FileCanBeOpenedForReadAfterAnnotation) {
+ base::ScopedTempDir test_dir;
+ ASSERT_TRUE(test_dir.CreateUniqueTempDir());
+
+ base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.class");
+ ASSERT_EQ(static_cast<int>(arraysize(kTestData)),
+ base::WriteFile(test_file, kTestData, arraysize(kTestData)));
+
+ EXPECT_EQ(QuarantineFileResult::OK,
+ QuarantineFile(test_file, GURL(kInternetURL),
+ GURL(kInternetReferrerURL), kTestGUID));
+
+ std::string contents;
+ EXPECT_TRUE(base::ReadFileToString(test_file, &contents));
+ EXPECT_EQ(std::string(std::begin(kTestData), std::end(kTestData)), contents);
+}
+
+TEST(QuarantineTest, FileCanBeAnnotatedWithNoGUID) {
+ base::ScopedTempDir test_dir;
+ ASSERT_TRUE(test_dir.CreateUniqueTempDir());
+
+ base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.class");
+ ASSERT_EQ(static_cast<int>(arraysize(kTestData)),
+ base::WriteFile(test_file, kTestData, arraysize(kTestData)));
+
+ EXPECT_EQ(QuarantineFileResult::OK,
+ QuarantineFile(test_file, GURL(kInternetURL),
+ GURL(kInternetReferrerURL), std::string()));
+}
+
+} // namespace download
diff --git a/chromium/components/download/quarantine/quarantine_win.cc b/chromium/components/download/quarantine/quarantine_win.cc
new file mode 100644
index 00000000000..948c59682a6
--- /dev/null
+++ b/chromium/components/download/quarantine/quarantine_win.cc
@@ -0,0 +1,352 @@
+// 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/download/quarantine/quarantine.h"
+
+#include <windows.h>
+#include <wrl/client.h>
+
+#include <cguid.h>
+#include <objbase.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#include <shobjidl.h>
+#include <wininet.h>
+
+#include <vector>
+
+#include "base/files/file_util.h"
+#include "base/guid.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/win/scoped_handle.h"
+#include "url/gurl.h"
+
+namespace download {
+namespace {
+
+// [MS-FSCC] Section 5.6.1
+const base::FilePath::CharType kZoneIdentifierStreamSuffix[] =
+ FILE_PATH_LITERAL(":Zone.Identifier");
+
+// UMA enumeration for recording Download.AttachmentServicesResult.
+enum class AttachmentServicesResult : int {
+ SUCCESS_WITH_MOTW = 0,
+ SUCCESS_WITHOUT_MOTW = 1,
+ SUCCESS_WITHOUT_FILE = 2,
+ NO_ATTACHMENT_SERVICES = 3,
+ FAILED_TO_SET_PARAMETER = 4,
+ BLOCKED_WITH_FILE = 5,
+ BLOCKED_WITHOUT_FILE = 6,
+ INFECTED_WITH_FILE = 7,
+ INFECTED_WITHOUT_FILE = 8,
+ ACCESS_DENIED_WITH_FILE = 9,
+ ACCESS_DENIED_WITHOUT_FILE = 10,
+ OTHER_WITH_FILE = 11,
+ OTHER_WITHOUT_FILE = 12,
+};
+
+void RecordAttachmentServicesResult(AttachmentServicesResult type) {
+ base::UmaHistogramSparse("Download.AttachmentServices.Result",
+ static_cast<int>(type));
+}
+
+bool ZoneIdentifierPresentForFile(const base::FilePath& path) {
+ const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ base::FilePath::StringType zone_identifier_path =
+ path.value() + kZoneIdentifierStreamSuffix;
+ base::win::ScopedHandle file(
+ CreateFile(zone_identifier_path.c_str(), GENERIC_READ, kShare, nullptr,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
+ if (!file.IsValid())
+ return false;
+
+ // The zone identifier contents is expected to be:
+ // "[ZoneTransfer]\r\nZoneId=3\r\n". The actual ZoneId can be different. A
+ // buffer of 32 bytes is sufficient for verifying the contents.
+ std::vector<char> zone_identifier_contents_buffer(32);
+ DWORD actual_length = 0;
+ if (!ReadFile(file.Get(), &zone_identifier_contents_buffer.front(),
+ zone_identifier_contents_buffer.size(), &actual_length, NULL))
+ return false;
+ zone_identifier_contents_buffer.resize(actual_length);
+
+ std::string zone_identifier_contents(zone_identifier_contents_buffer.begin(),
+ zone_identifier_contents_buffer.end());
+
+ std::vector<base::StringPiece> lines =
+ base::SplitStringPiece(zone_identifier_contents, "\n",
+ base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ return lines.size() > 1 && lines[0] == "[ZoneTransfer]" &&
+ lines[1].find("ZoneId=") == 0;
+}
+
+void RecordAttachmentServicesSaveResult(const base::FilePath& file,
+ HRESULT hr) {
+ bool file_exists = base::PathExists(file);
+ switch (hr) {
+ case INET_E_SECURITY_PROBLEM:
+ RecordAttachmentServicesResult(
+ file_exists ? AttachmentServicesResult::BLOCKED_WITH_FILE
+ : AttachmentServicesResult::BLOCKED_WITHOUT_FILE);
+ break;
+
+ case E_FAIL:
+ RecordAttachmentServicesResult(
+ file_exists ? AttachmentServicesResult::INFECTED_WITH_FILE
+ : AttachmentServicesResult::INFECTED_WITHOUT_FILE);
+ break;
+
+ case E_ACCESSDENIED:
+ case ERROR_ACCESS_DENIED:
+ // ERROR_ACCESS_DENIED is not a valid HRESULT. However,
+ // IAttachmentExecute::Save() is known to return it and other system error
+ // codes in practice.
+ RecordAttachmentServicesResult(
+ file_exists ? AttachmentServicesResult::ACCESS_DENIED_WITH_FILE
+ : AttachmentServicesResult::ACCESS_DENIED_WITHOUT_FILE);
+ break;
+
+ default:
+ if (SUCCEEDED(hr)) {
+ bool motw_exists = file_exists && ZoneIdentifierPresentForFile(file);
+ RecordAttachmentServicesResult(
+ file_exists ? motw_exists
+ ? AttachmentServicesResult::SUCCESS_WITH_MOTW
+ : AttachmentServicesResult::SUCCESS_WITHOUT_MOTW
+ : AttachmentServicesResult::SUCCESS_WITHOUT_FILE);
+ return;
+ }
+
+ // Failure codes.
+ RecordAttachmentServicesResult(
+ file_exists ? AttachmentServicesResult::OTHER_WITH_FILE
+ : AttachmentServicesResult::OTHER_WITHOUT_FILE);
+ }
+}
+
+// Sets the Zone Identifier on the file to "Internet" (3). Returns true if the
+// function succeeds, false otherwise. A failure is expected if alternate
+// streams are not supported, like a file on a FAT32 filesystem. This function
+// does not invoke Windows Attachment Execution Services.
+//
+// |full_path| is the path to the downloaded file.
+QuarantineFileResult SetInternetZoneIdentifierDirectly(
+ const base::FilePath& full_path) {
+ const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ std::wstring path = full_path.value() + kZoneIdentifierStreamSuffix;
+ HANDLE file = CreateFile(path.c_str(), GENERIC_WRITE, kShare, nullptr,
+ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (INVALID_HANDLE_VALUE == file)
+ return QuarantineFileResult::ANNOTATION_FAILED;
+
+ static const char kIdentifier[] = "[ZoneTransfer]\r\nZoneId=3\r\n";
+ // Don't include trailing null in data written.
+ static const DWORD kIdentifierSize = arraysize(kIdentifier) - 1;
+ DWORD written = 0;
+ BOOL write_result =
+ WriteFile(file, kIdentifier, kIdentifierSize, &written, nullptr);
+ BOOL flush_result = FlushFileBuffers(file);
+ CloseHandle(file);
+
+ return write_result && flush_result && written == kIdentifierSize
+ ? QuarantineFileResult::OK
+ : QuarantineFileResult::ANNOTATION_FAILED;
+}
+
+// Invokes IAttachmentExecute::Save on CLSID_AttachmentServices to validate the
+// downloaded file. The call may scan the file for viruses and if necessary,
+// annotate it with evidence. As a result of the validation, the file may be
+// deleted. See: http://msdn.microsoft.com/en-us/bb776299
+//
+// IAE::Save() will delete the file if it was found to be blocked by local
+// security policy or if it was found to be infected. The call may also delete
+// the file due to other failures (http://crbug.com/153212). A failure code will
+// be returned in these cases.
+//
+// The return value is |false| iff the function fails to invoke
+// IAttachmentExecute::Save(). If the function returns |true|, then the result
+// of invoking IAttachmentExecute::Save() is stored in |save_result|.
+//
+// Typical |save_result| values:
+// S_OK : The file was okay. If any viruses were found, they were cleaned.
+// E_FAIL : Virus infected.
+// INET_E_SECURITY_PROBLEM : The file was blocked due to security policy.
+//
+// Any other return value indicates an unexpected error during the scan.
+//
+// |full_path| : is the path to the downloaded file. This should be the final
+// path of the download. Must be present.
+// |source_url|: the source URL for the download. If empty, the source will
+// be set to 'about:internet'.
+// |referrer_url|: the referrer URL for the download. If empty, the referrer
+// will not be set.
+// |client_guid|: the GUID to be set in the IAttachmentExecute client slot.
+// Used to identify the app to the system AV function.
+// |save_result|: Receives the result of invoking IAttachmentExecute::Save().
+bool InvokeAttachmentServices(const base::FilePath& full_path,
+ const std::string& source_url,
+ const std::string& referrer_url,
+ const GUID& client_guid,
+ HRESULT* save_result) {
+ Microsoft::WRL::ComPtr<IAttachmentExecute> attachment_services;
+ HRESULT hr = ::CoCreateInstance(CLSID_AttachmentServices, nullptr, CLSCTX_ALL,
+ IID_PPV_ARGS(&attachment_services));
+ *save_result = S_OK;
+
+ if (FAILED(hr)) {
+ // The thread must have COM initialized.
+ DCHECK_NE(CO_E_NOTINITIALIZED, hr);
+ RecordAttachmentServicesResult(
+ AttachmentServicesResult::NO_ATTACHMENT_SERVICES);
+ return false;
+ }
+
+ // Note that it is mandatory to check the return values from here on out. If
+ // setting one of the parameters fails, it could leave the object in a state
+ // where the final Save() call will also fail.
+
+ hr = attachment_services->SetClientGuid(client_guid);
+ if (FAILED(hr)) {
+ RecordAttachmentServicesResult(
+ AttachmentServicesResult::FAILED_TO_SET_PARAMETER);
+ return false;
+ }
+
+ hr = attachment_services->SetLocalPath(full_path.value().c_str());
+ if (FAILED(hr)) {
+ RecordAttachmentServicesResult(
+ AttachmentServicesResult::FAILED_TO_SET_PARAMETER);
+ return false;
+ }
+
+ // The source URL could be empty if it was not a valid URL or was not HTTP/S.
+ // If so, user "about:internet" as a fallback URL. The latter is known to
+ // reliably map to the Internet zone.
+ //
+ // In addition, URLs that are longer than INTERNET_MAX_URL_LENGTH are also
+ // known to cause problems for URLMon. Hence also use "about:internet" in
+ // these cases. See http://crbug.com/601538.
+ hr = attachment_services->SetSource(
+ source_url.empty() || source_url.size() > INTERNET_MAX_URL_LENGTH
+ ? L"about:internet"
+ : base::UTF8ToWide(source_url).c_str());
+ if (FAILED(hr)) {
+ RecordAttachmentServicesResult(
+ AttachmentServicesResult::FAILED_TO_SET_PARAMETER);
+ return false;
+ }
+
+ // Only set referrer if one is present and shorter than
+ // INTERNET_MAX_URL_LENGTH. Also, the source_url is authoritative for
+ // determining the relative danger of |full_path| so we don't consider it an
+ // error if we have to skip the |referrer_url|.
+ if (!referrer_url.empty() && referrer_url.size() < INTERNET_MAX_URL_LENGTH) {
+ hr = attachment_services->SetReferrer(
+ base::UTF8ToWide(referrer_url).c_str());
+ if (FAILED(hr)) {
+ RecordAttachmentServicesResult(
+ AttachmentServicesResult::FAILED_TO_SET_PARAMETER);
+ return false;
+ }
+ }
+
+ {
+ // This method has been known to take longer than 10 seconds in some
+ // instances.
+ SCOPED_UMA_HISTOGRAM_LONG_TIMER("Download.AttachmentServices.Duration");
+ *save_result = attachment_services->Save();
+ }
+ RecordAttachmentServicesSaveResult(full_path, *save_result);
+ return true;
+}
+
+// Maps a return code from an unsuccessful IAttachmentExecute::Save() call to a
+// QuarantineFileResult.
+QuarantineFileResult FailedSaveResultToQuarantineResult(HRESULT result) {
+ switch (result) {
+ case INET_E_SECURITY_PROBLEM: // 0x800c000e
+ // This is returned if the download was blocked due to security
+ // restrictions. E.g. if the source URL was in the Restricted Sites zone
+ // and downloads are blocked on that zone, then the download would be
+ // deleted and this error code is returned.
+ return QuarantineFileResult::BLOCKED_BY_POLICY;
+
+ case E_FAIL: // 0x80004005
+ // Returned if an anti-virus product reports an infection in the
+ // downloaded file during IAE::Save().
+ return QuarantineFileResult::VIRUS_INFECTED;
+
+ default:
+ // Any other error that occurs during IAttachmentExecute::Save() likely
+ // indicates a problem with the security check, but not necessarily the
+ // download. This also includes cases where SUCCEEDED(result) is true. In
+ // the latter case we are likely dealing with a situation where the file
+ // is missing after a successful scan. See http://crbug.com/153212.
+ return QuarantineFileResult::SECURITY_CHECK_FAILED;
+ }
+}
+
+} // namespace
+
+QuarantineFileResult QuarantineFile(const base::FilePath& file,
+ const GURL& source_url,
+ const GURL& referrer_url,
+ const std::string& client_guid) {
+ base::AssertBlockingAllowed();
+
+ int64_t file_size = 0;
+ if (!base::PathExists(file) || !base::GetFileSize(file, &file_size))
+ return QuarantineFileResult::FILE_MISSING;
+
+ std::string braces_guid = "{" + client_guid + "}";
+ GUID guid = GUID_NULL;
+ if (base::IsValidGUID(client_guid)) {
+ HRESULT hr = CLSIDFromString(base::UTF8ToUTF16(braces_guid).c_str(), &guid);
+ if (FAILED(hr))
+ guid = GUID_NULL;
+ }
+
+ if (file_size == 0 || IsEqualGUID(guid, GUID_NULL)) {
+ // 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);
+ }
+
+ HRESULT save_result = S_OK;
+ bool attachment_services_available = InvokeAttachmentServices(
+ file, source_url.spec(), referrer_url.spec(), guid, &save_result);
+ if (!attachment_services_available)
+ return SetInternetZoneIdentifierDirectly(file);
+
+ // If the download file is missing after the call, then treat this as an
+ // interrupted download.
+ //
+ // If InvokeAttachmentServices() failed, but the downloaded file is still
+ // around, then don't interrupt the download. Attachment Execution Services
+ // deletes the submitted file if the downloaded file is blocked by policy or
+ // if it was found to be infected.
+ //
+ // If the file is still there, then the error could be due to Windows
+ // Attachment Services not being available or some other error during the AES
+ // invocation. In either case, we don't surface the error to the user.
+ if (!base::PathExists(file))
+ return FailedSaveResultToQuarantineResult(save_result);
+ return QuarantineFileResult::OK;
+}
+
+bool IsFileQuarantined(const base::FilePath& file,
+ const GURL& source_url,
+ const GURL& referrer_url) {
+ return ZoneIdentifierPresentForFile(file);
+}
+
+} // namespace download
diff --git a/chromium/components/download/quarantine/quarantine_win_unittest.cc b/chromium/components/download/quarantine/quarantine_win_unittest.cc
new file mode 100644
index 00000000000..c169a66996f
--- /dev/null
+++ b/chromium/components/download/quarantine/quarantine_win_unittest.cc
@@ -0,0 +1,263 @@
+// 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 <windows.h>
+
+#include <wininet.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/test/histogram_tester.h"
+#include "base/test/test_file_util.h"
+#include "components/download/quarantine/quarantine.h"
+#include "net/base/filename_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace download {
+
+namespace {
+
+const char kDummySourceUrl[] = "https://example.com/foo";
+const char kDummyReferrerUrl[] = "https://example.com/referrer";
+const char kDummyClientGuid[] = "A1B69307-8FA2-4B6F-9181-EA06051A48A7";
+
+const char kMotwForInternetZone[] = "[ZoneTransfer]\r\nZoneId=3\r\n";
+const base::FilePath::CharType kMotwStreamSuffix[] =
+ FILE_PATH_LITERAL(":Zone.Identifier");
+
+const char kTestData[] = "Hello world!";
+
+const char* const kUntrustedURLs[] = {
+ "http://example.com/foo",
+ "https://example.com/foo",
+ "ftp://example.com/foo",
+ "ftp://example.com:2121/foo",
+ "data:text/plain,Hello%20world",
+ "blob://example.com/126278b3-58f3-4b4a-a914-1d1185d634f6",
+ "about:internet",
+ ""};
+
+} // namespace
+
+// If the file is missing, the QuarantineFile() call should return FILE_MISSING.
+TEST(QuarantineWinTest, MissingFile) {
+ base::ScopedTempDir test_dir;
+ ASSERT_TRUE(test_dir.CreateUniqueTempDir());
+
+ EXPECT_EQ(QuarantineFileResult::FILE_MISSING,
+ QuarantineFile(test_dir.GetPath().AppendASCII("does-not-exist.exe"),
+ GURL(kDummySourceUrl), GURL(kDummyReferrerUrl),
+ kDummyClientGuid));
+}
+
+// On Windows systems, files downloaded from a local source are considered
+// trustworthy. Hence they aren't annotated with source information. This test
+// verifies this behavior since the other tests in this suite would pass with a
+// false positive if local files are being annotated with the MOTW for the
+// internet zone.
+TEST(QuarantineWinTest, LocalFile_DependsOnLocalConfig) {
+ base::HistogramTester histogram_tester;
+ base::ScopedTempDir test_dir;
+ ASSERT_TRUE(test_dir.CreateUniqueTempDir());
+ base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
+
+ const char* const kLocalSourceURLs[] = {"http://localhost/foo",
+ "file:///C:/some-local-dir/foo.exe"};
+
+ for (const char* source_url : kLocalSourceURLs) {
+ SCOPED_TRACE(::testing::Message() << "Trying URL " << source_url);
+ ASSERT_EQ(static_cast<int>(arraysize(kTestData)),
+ base::WriteFile(test_file, kTestData, arraysize(kTestData)));
+
+ EXPECT_EQ(
+ QuarantineFileResult::OK,
+ QuarantineFile(test_file, GURL(source_url), GURL(), kDummyClientGuid));
+
+ std::string motw_contents;
+ base::ReadFileToString(
+ base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents);
+
+ // These warnings aren't displayed on successful test runs. They are there
+ // so that we can check for deviations in behavior during manual testing.
+ if (!motw_contents.empty()) {
+ LOG(WARNING) << "Unexpected zone marker for file " << test_file.value()
+ << " Source URL:" << source_url;
+ if (motw_contents != kMotwForInternetZone)
+ LOG(WARNING) << "Zone marker contents: " << motw_contents;
+ }
+
+ base::DeleteFile(test_file, false);
+ }
+
+ // Bucket 1 is SUCCESS_WITHOUT_MOTW.
+ histogram_tester.ExpectUniqueSample("Download.AttachmentServices.Result", 1,
+ arraysize(kLocalSourceURLs));
+}
+
+// A file downloaded from the internet should be annotated with .. something.
+// The specific zone assigned to our dummy source URL depends on the local
+// configuration. But no sane configuration should be treating the dummy URL as
+// a trusted source for anything.
+TEST(QuarantineWinTest, DownloadedFile_DependsOnLocalConfig) {
+ base::HistogramTester histogram_tester;
+ base::ScopedTempDir test_dir;
+ ASSERT_TRUE(test_dir.CreateUniqueTempDir());
+ base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
+
+ for (const char* source_url : kUntrustedURLs) {
+ SCOPED_TRACE(::testing::Message() << "Trying URL " << source_url);
+ ASSERT_EQ(static_cast<int>(arraysize(kTestData)),
+ base::WriteFile(test_file, kTestData, arraysize(kTestData)));
+ EXPECT_EQ(
+ QuarantineFileResult::OK,
+ QuarantineFile(test_file, GURL(source_url), GURL(), kDummyClientGuid));
+ std::string motw_contents;
+ ASSERT_TRUE(base::ReadFileToString(
+ base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
+ // The actual assigned zone could be anything. So only testing that there is
+ // a zone annotation.
+ EXPECT_FALSE(motw_contents.empty());
+
+ // These warnings aren't displayed on successful test runs. They are there
+ // so that we can check for deviations in behavior during manual testing.
+ if (motw_contents != kMotwForInternetZone)
+ LOG(WARNING) << "Unexpected zone marker: " << motw_contents;
+ base::DeleteFile(test_file, false);
+ }
+
+ // Bucket 0 is SUCCESS_WITH_MOTW.
+ histogram_tester.ExpectUniqueSample("Download.AttachmentServices.Result", 0,
+ arraysize(kUntrustedURLs));
+}
+
+TEST(QuarantineWinTest, UnsafeReferrer_DependsOnLocalConfig) {
+ base::HistogramTester histogram_tester;
+ base::ScopedTempDir test_dir;
+ ASSERT_TRUE(test_dir.CreateUniqueTempDir());
+ base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
+
+ std::vector<std::string> unsafe_referrers(std::begin(kUntrustedURLs),
+ std::end(kUntrustedURLs));
+
+ std::string huge_referrer = "http://example.com/";
+ huge_referrer.append(INTERNET_MAX_URL_LENGTH * 2, 'a');
+ unsafe_referrers.push_back(huge_referrer);
+
+ for (const auto referrer_url : unsafe_referrers) {
+ SCOPED_TRACE(::testing::Message() << "Trying URL " << referrer_url);
+ ASSERT_EQ(static_cast<int>(arraysize(kTestData)),
+ base::WriteFile(test_file, kTestData, arraysize(kTestData)));
+ EXPECT_EQ(QuarantineFileResult::OK,
+ QuarantineFile(test_file, GURL("http://example.com/good"),
+ GURL(referrer_url), kDummyClientGuid));
+ std::string motw_contents;
+ ASSERT_TRUE(base::ReadFileToString(
+ base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
+ // The actual assigned zone could be anything. So only testing that there is
+ // a zone annotation.
+ EXPECT_FALSE(motw_contents.empty());
+
+ // These warnings aren't displayed on successful test runs. They are there
+ // so that we can check for deviations in behavior during manual testing.
+ if (motw_contents != kMotwForInternetZone)
+ LOG(WARNING) << "Unexpected zone marker: " << motw_contents;
+ base::DeleteFile(test_file, false);
+ }
+
+ // Bucket 0 is SUCCESS_WITH_MOTW.
+ histogram_tester.ExpectUniqueSample("Download.AttachmentServices.Result", 0,
+ unsafe_referrers.size());
+}
+
+// An empty source URL should result in a file that's treated the same as one
+// downloaded from the internet.
+TEST(QuarantineWinTest, EmptySource_DependsOnLocalConfig) {
+ base::HistogramTester histogram_tester;
+ base::ScopedTempDir test_dir;
+ ASSERT_TRUE(test_dir.CreateUniqueTempDir());
+ base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
+ ASSERT_EQ(static_cast<int>(arraysize(kTestData)),
+ base::WriteFile(test_file, kTestData, arraysize(kTestData)));
+
+ EXPECT_EQ(QuarantineFileResult::OK,
+ QuarantineFile(test_file, GURL(), GURL(), kDummyClientGuid));
+ std::string motw_contents;
+ ASSERT_TRUE(base::ReadFileToString(
+ base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
+ // The actual assigned zone could be anything. So only testing that there is a
+ // zone annotation.
+ EXPECT_FALSE(motw_contents.empty());
+
+ // Bucket 0 is SUCCESS_WITH_MOTW.
+ histogram_tester.ExpectUniqueSample("Download.AttachmentServices.Result", 0,
+ 1);
+}
+
+// Empty files aren't passed to AVScanFile. They are instead marked manually. If
+// the file is passed to AVScanFile, then there wouldn't be a MOTW attached to
+// it and the test would fail.
+TEST(QuarantineWinTest, EmptyFile) {
+ base::HistogramTester histogram_tester;
+ base::ScopedTempDir test_dir;
+ ASSERT_TRUE(test_dir.CreateUniqueTempDir());
+ base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
+ ASSERT_EQ(0, base::WriteFile(test_file, "", 0u));
+
+ EXPECT_EQ(QuarantineFileResult::OK,
+ QuarantineFile(test_file, net::FilePathToFileURL(test_file), GURL(),
+ kDummyClientGuid));
+ std::string motw_contents;
+ ASSERT_TRUE(base::ReadFileToString(
+ base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
+ EXPECT_STREQ(kMotwForInternetZone, motw_contents.c_str());
+
+ // Attachment services shouldn't have been invoked at all.
+ histogram_tester.ExpectTotalCount("Download.AttachmentServices.Result", 0);
+}
+
+// If there is no client GUID supplied to the QuarantineFile() call, then rather
+// than invoking AVScanFile, the MOTW will be applied manually. If the file is
+// passed to AVScanFile, then there wouldn't be a MOTW attached to it and the
+// test would fail.
+TEST(QuarantineWinTest, NoClientGuid) {
+ base::ScopedTempDir test_dir;
+ ASSERT_TRUE(test_dir.CreateUniqueTempDir());
+ base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
+ ASSERT_EQ(static_cast<int>(arraysize(kTestData)),
+ base::WriteFile(test_file, kTestData, arraysize(kTestData)));
+
+ EXPECT_EQ(QuarantineFileResult::OK,
+ QuarantineFile(test_file, net::FilePathToFileURL(test_file), GURL(),
+ std::string()));
+ std::string motw_contents;
+ ASSERT_TRUE(base::ReadFileToString(
+ base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
+ EXPECT_STREQ(kMotwForInternetZone, motw_contents.c_str());
+}
+
+// URLs longer than INTERNET_MAX_URL_LENGTH are known to break URLMon. Such a
+// URL, when used as a source URL shouldn't break QuarantineFile() which should
+// mark the file as being from the internet zone as a safe fallback.
+TEST(QuarantineWinTest, SuperLongURL) {
+ base::ScopedTempDir test_dir;
+ ASSERT_TRUE(test_dir.CreateUniqueTempDir());
+ base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
+ ASSERT_EQ(static_cast<int>(arraysize(kTestData)),
+ base::WriteFile(test_file, kTestData, arraysize(kTestData)));
+
+ 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()));
+
+ std::string motw_contents;
+ ASSERT_TRUE(base::ReadFileToString(
+ base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
+ EXPECT_STREQ(kMotwForInternetZone, motw_contents.c_str());
+}
+
+} // namespace download
diff --git a/chromium/components/drive/BUILD.gn b/chromium/components/drive/BUILD.gn
index d16147b1409..1ef9c4321b2 100644
--- a/chromium/components/drive/BUILD.gn
+++ b/chromium/components/drive/BUILD.gn
@@ -58,7 +58,7 @@ static_library("drive") {
"//content/public/browser",
"//google_apis:google_apis",
"//net:net",
- "//services/device/public/interfaces",
+ "//services/device/public/mojom",
"//third_party/cacheinvalidation",
"//third_party/leveldatabase",
"//third_party/re2",
diff --git a/chromium/components/error_page/common/localized_error.cc b/chromium/components/error_page/common/localized_error.cc
index ddf472aeccf..aff41dbc7aa 100644
--- a/chromium/components/error_page/common/localized_error.cc
+++ b/chromium/components/error_page/common/localized_error.cc
@@ -6,6 +6,7 @@
#include <stddef.h>
+#include <memory>
#include <utility>
#include "base/command_line.h"
@@ -535,7 +536,7 @@ void AddSingleEntryDictionaryToList(base::ListValue* list,
const char* path,
int message_id,
bool insert_as_first_item) {
- auto suggestion_list_item = base::MakeUnique<base::DictionaryValue>();
+ auto suggestion_list_item = std::make_unique<base::DictionaryValue>();
suggestion_list_item->SetString(path, l10n_util::GetStringUTF16(message_id));
if (insert_as_first_item) {
@@ -657,7 +658,7 @@ void GetSuggestionsSummaryList(int error_code,
if (failed_origin.unique())
return;
- auto suggestion = base::MakeUnique<base::DictionaryValue>();
+ auto suggestion = std::make_unique<base::DictionaryValue>();
suggestion->SetString("summary",
l10n_util::GetStringUTF16(
IDS_ERRORPAGES_SUGGESTION_NAVIGATE_TO_ORIGIN));
@@ -911,13 +912,13 @@ void LocalizedError::GetStrings(
std::string icon_class = GetIconClassForError(error_domain, error_code);
error_strings->SetString("iconClass", icon_class);
- auto heading = base::MakeUnique<base::DictionaryValue>();
+ auto heading = std::make_unique<base::DictionaryValue>();
heading->SetString("msg",
l10n_util::GetStringUTF16(options.heading_resource_id));
heading->SetString("hostName", host_name);
error_strings->Set("heading", std::move(heading));
- auto summary = base::MakeUnique<base::DictionaryValue>();
+ auto summary = std::make_unique<base::DictionaryValue>();
// Set summary message under the heading.
summary->SetString(
@@ -970,9 +971,9 @@ void LocalizedError::GetStrings(
if (!params->override_suggestions) {
// Detailed suggestion information.
suggestions_details = error_strings->SetList(
- "suggestionsDetails", base::MakeUnique<base::ListValue>());
+ "suggestionsDetails", std::make_unique<base::ListValue>());
suggestions_summary_list = error_strings->SetList(
- "suggestionsSummaryList", base::MakeUnique<base::ListValue>());
+ "suggestionsSummaryList", std::make_unique<base::ListValue>());
} else {
suggestions_summary_list = error_strings->SetList(
"suggestionsSummaryList", std::move(params->override_suggestions));
@@ -1002,7 +1003,7 @@ void LocalizedError::GetStrings(
#if defined(OS_ANDROID)
reload_visible = true;
#endif // defined(OS_ANDROID)
- auto reload_button = base::MakeUnique<base::DictionaryValue>();
+ auto reload_button = std::make_unique<base::DictionaryValue>();
reload_button->SetString(
"msg", l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_RELOAD));
reload_button->SetString("reloadUrl", failed_url.spec());
@@ -1041,7 +1042,7 @@ void LocalizedError::GetStrings(
(show_saved_copy_primary || show_saved_copy_secondary));
if (show_saved_copy_visible) {
- auto show_saved_copy_button = base::MakeUnique<base::DictionaryValue>();
+ auto show_saved_copy_button = std::make_unique<base::DictionaryValue>();
show_saved_copy_button->SetString(
"msg", l10n_util::GetStringUTF16(
IDS_ERRORPAGES_BUTTON_SHOW_SAVED_COPY));
@@ -1060,7 +1061,7 @@ void LocalizedError::GetStrings(
failed_url.SchemeIsHTTPOrHTTPS() &&
IsSuggested(options.suggestions, SUGGEST_OFFLINE_CHECKS)) {
std::unique_ptr<base::DictionaryValue> download_button =
- base::MakeUnique<base::DictionaryValue>();
+ std::make_unique<base::DictionaryValue>();
download_button->SetString(
"msg",
l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_DOWNLOAD));
diff --git a/chromium/components/exo/buffer.cc b/chromium/components/exo/buffer.cc
index 5b350b216c5..af29a74abb8 100644
--- a/chromium/components/exo/buffer.cc
+++ b/chromium/components/exo/buffer.cc
@@ -55,7 +55,8 @@ GLenum GLInternalFormat(gfx::BufferFormat format) {
GL_RGB, // RGBX_8888
GL_RGBA, // RGBA_8888
GL_RGB, // BGRX_8888
- GL_RGB, // BGRX_1010102
+ GL_RGB10_A2_EXT, // BGRX_1010102
+ GL_RGB10_A2_EXT, // RGBX_1010102
GL_BGRA_EXT, // BGRA_8888
GL_RGBA, // RGBA_F16
GL_RGB_YCRCB_420_CHROMIUM, // YVU_420
diff --git a/chromium/components/exo/client_controlled_shell_surface.cc b/chromium/components/exo/client_controlled_shell_surface.cc
index 7139392ef6e..142d5c9dbe3 100644
--- a/chromium/components/exo/client_controlled_shell_surface.cc
+++ b/chromium/components/exo/client_controlled_shell_surface.cc
@@ -13,6 +13,7 @@
#include "ash/wm/drag_details.h"
#include "ash/wm/drag_window_resizer.h"
#include "ash/wm/toplevel_window_event_handler.h"
+#include "ash/wm/window_positioning_utils.h"
#include "ash/wm/window_properties.h"
#include "ash/wm/window_resizer.h"
#include "ash/wm/window_state.h"
@@ -26,6 +27,8 @@
#include "components/exo/wm_helper.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/base/class_property.h"
#include "ui/compositor/compositor_lock.h"
#include "ui/display/display.h"
@@ -84,6 +87,7 @@ class ClientControlledStateDelegate
next_state);
}
void HandleBoundsRequest(ash::wm::WindowState* window_state,
+ ash::mojom::WindowStateType requested_state,
const gfx::Rect& bounds) override {
bool is_resize = window_state->window()->bounds().size() != bounds.size();
@@ -95,7 +99,8 @@ class ClientControlledStateDelegate
.id();
shell_surface_->OnBoundsChangeEvent(
- window_state->GetStateType(), display_id, bounds_in_screen, is_resize,
+ window_state->GetStateType(), requested_state, display_id,
+ bounds_in_screen, is_resize,
window_state->drag_details()
? window_state->drag_details()->bounds_change
: 0);
@@ -243,24 +248,34 @@ ClientControlledShellSurface::~ClientControlledShellSurface() {
void ClientControlledShellSurface::SetMaximized() {
TRACE_EVENT0("exo", "ClientControlledShellSurface::SetMaximized");
- pending_show_state_ = ui::SHOW_STATE_MAXIMIZED;
+ pending_window_state_ = ash::mojom::WindowStateType::MAXIMIZED;
}
void ClientControlledShellSurface::SetMinimized() {
TRACE_EVENT0("exo", "ClientControlledShellSurface::SetMinimized");
- pending_show_state_ = ui::SHOW_STATE_MINIMIZED;
+ pending_window_state_ = ash::mojom::WindowStateType::MINIMIZED;
}
void ClientControlledShellSurface::SetRestored() {
TRACE_EVENT0("exo", "ClientControlledShellSurface::SetRestored");
- pending_show_state_ = ui::SHOW_STATE_NORMAL;
+ pending_window_state_ = ash::mojom::WindowStateType::NORMAL;
}
void ClientControlledShellSurface::SetFullscreen(bool fullscreen) {
TRACE_EVENT1("exo", "ClientControlledShellSurface::SetFullscreen",
"fullscreen", fullscreen);
- pending_show_state_ =
- fullscreen ? ui::SHOW_STATE_FULLSCREEN : ui::SHOW_STATE_NORMAL;
+ pending_window_state_ = fullscreen ? ash::mojom::WindowStateType::FULLSCREEN
+ : ash::mojom::WindowStateType::NORMAL;
+}
+
+void ClientControlledShellSurface::SetSnappedToLeft() {
+ TRACE_EVENT0("exo", "ClientControlledShellSurface::SetSnappedToLeft");
+ pending_window_state_ = ash::mojom::WindowStateType::LEFT_SNAPPED;
+}
+
+void ClientControlledShellSurface::SetSnappedToRight() {
+ TRACE_EVENT0("exo", "ClientControlledShellSurface::SetSnappedToRight");
+ pending_window_state_ = ash::mojom::WindowStateType::RIGHT_SNAPPED;
}
void ClientControlledShellSurface::SetPinned(ash::mojom::WindowPinType type) {
@@ -349,13 +364,13 @@ void ClientControlledShellSurface::OnWindowStateChangeEvent(
state_changed_callback_.Run(current_state, next_state);
}
-void ClientControlledShellSurface::StartResize_DEPRECATED() {
- TRACE_EVENT0("exo", "ClientControlledShellSurface::StartResize");
+void ClientControlledShellSurface::StartResize(int component) {
+ TRACE_EVENT1("exo", "ClientControlledShellSurface::StartResize", "component",
+ component);
- if (!widget_ || !client_controlled_move_resize_)
+ if (!widget_ || client_controlled_move_resize_)
return;
-
- AttemptToStartDrag(HTBORDER);
+ AttemptToStartDrag(component, GetMouseLocation());
}
void ClientControlledShellSurface::StartMove(const gfx::Point& location) {
@@ -363,15 +378,29 @@ void ClientControlledShellSurface::StartMove(const gfx::Point& location) {
if (!widget_)
return;
+ AttemptToStartDrag(HTCAPTION, location);
+}
- gfx::Point point_in_root(location);
- wm::ConvertPointFromScreen(widget_->GetNativeWindow()->GetRootWindow(),
- &point_in_root);
-
+void ClientControlledShellSurface::AttemptToStartDrag(
+ int component,
+ const gfx::Point& location) {
aura::Window* target = widget_->GetNativeWindow();
- ash::Shell::Get()->toplevel_window_event_handler()->AttemptToStartDrag(
- target, point_in_root, HTCAPTION,
- ash::wm::WmToplevelWindowEventHandler::EndClosure());
+ ash::ToplevelWindowEventHandler* toplevel_handler =
+ ash::Shell::Get()->toplevel_window_event_handler();
+ aura::Window* mouse_pressed_handler =
+ target->GetHost()->dispatcher()->mouse_pressed_handler();
+ // Start dragging only if ...
+ // 1) touch guesture is in progres.
+ // 2) mouse was pressed on the target or its subsurfaces.
+ if (toplevel_handler->gesture_target() ||
+ (mouse_pressed_handler && target->Contains(mouse_pressed_handler))) {
+
+ gfx::Point point_in_root(location);
+ wm::ConvertPointFromScreen(target->GetRootWindow(), &point_in_root);
+ toplevel_handler->AttemptToStartDrag(
+ target, point_in_root, component,
+ ash::wm::WmToplevelWindowEventHandler::EndClosure());
+ }
}
void ClientControlledShellSurface::SetCanMaximize(bool can_maximize) {
@@ -384,13 +413,14 @@ void ClientControlledShellSurface::SetCanMaximize(bool can_maximize) {
void ClientControlledShellSurface::OnBoundsChangeEvent(
ash::mojom::WindowStateType current_state,
+ ash::mojom::WindowStateType requested_state,
int64_t display_id,
const gfx::Rect& bounds,
bool is_resize,
int bounds_change) {
if (!bounds.IsEmpty() && !bounds_changed_callback_.is_null()) {
- bounds_changed_callback_.Run(current_state, display_id, bounds, is_resize,
- bounds_change);
+ bounds_changed_callback_.Run(current_state, requested_state, display_id,
+ bounds, is_resize, bounds_change);
}
}
@@ -409,38 +439,31 @@ void ClientControlledShellSurface::OnDragFinished(bool canceled,
void ClientControlledShellSurface::OnSurfaceCommit() {
if (!widget_)
- CreateShellSurfaceWidget(pending_show_state_);
+ CreateShellSurfaceWidget(ash::ToWindowShowState(pending_window_state_));
- if (widget_->GetNativeWindow()->GetProperty(aura::client::kShowStateKey) !=
- pending_show_state_) {
- ash::wm::WindowState* window_state = GetWindowState();
+ ash::wm::WindowState* window_state = GetWindowState();
+ if (window_state->GetStateType() != pending_window_state_) {
if (!IsPinned(window_state)) {
- ash::mojom::WindowStateType next_window_state =
- ash::mojom::WindowStateType::NORMAL;
ash::wm::ClientControlledState::BoundsChangeAnimationType animation_type =
ash::wm::ClientControlledState::kAnimationNone;
- switch (pending_show_state_) {
- case ui::SHOW_STATE_NORMAL:
- if (widget_->IsMaximized() || widget_->IsFullscreen())
+ switch (pending_window_state_) {
+ case ash::mojom::WindowStateType::NORMAL:
+ if (widget_->IsMaximized() || widget_->IsFullscreen()) {
animation_type =
ash::wm::ClientControlledState::kAnimationCrossFade;
+ }
break;
- case ui::SHOW_STATE_MINIMIZED:
- next_window_state = ash::mojom::WindowStateType::MINIMIZED;
- break;
- case ui::SHOW_STATE_MAXIMIZED:
- animation_type = ash::wm::ClientControlledState::kAnimationCrossFade;
- next_window_state = ash::mojom::WindowStateType::MAXIMIZED;
- break;
- case ui::SHOW_STATE_FULLSCREEN:
+
+ case ash::mojom::WindowStateType::MAXIMIZED:
+ case ash::mojom::WindowStateType::FULLSCREEN:
animation_type = ash::wm::ClientControlledState::kAnimationCrossFade;
- next_window_state = ash::mojom::WindowStateType::FULLSCREEN;
break;
+
default:
break;
}
- client_controlled_state_->EnterNextState(window_state, next_window_state,
- animation_type);
+ client_controlled_state_->EnterNextState(
+ window_state, pending_window_state_, animation_type);
} else {
VLOG(1) << "State change was requested while it is pinned";
}
@@ -620,8 +643,22 @@ void ClientControlledShellSurface::SetWidgetBounds(const gfx::Rect& bounds) {
(client_controlled_move_resize_ &&
(!resizer_ || resizer_->details().window_component != HTCAPTION))) {
{
- ScopedSetBoundsLocally scoped_set_bounds(this);
- widget_->SetBounds(bounds);
+ // Calculate a minimum window visibility required bounds.
+ aura::Window* window = widget_->GetNativeWindow();
+ gfx::Rect rect(bounds);
+ wm::ConvertRectFromScreen(window->GetRootWindow(), &rect);
+ ash::wm::ClientControlledState::AdjustBoundsForMinimumWindowVisibility(
+ window, &rect);
+ wm::ConvertRectToScreen(window->GetRootWindow(), &rect);
+
+ if (bounds != rect) {
+ // Request the client a new bounds to ensure that it has enough visible
+ // area.
+ window->SetBounds(rect);
+ } else {
+ ScopedSetBoundsLocally scoped_set_bounds(this);
+ widget_->SetBounds(bounds);
+ }
}
UpdateSurfaceBounds();
return;
diff --git a/chromium/components/exo/client_controlled_shell_surface.h b/chromium/components/exo/client_controlled_shell_surface.h
index 3fda1e29f85..b046bf3c2c2 100644
--- a/chromium/components/exo/client_controlled_shell_surface.h
+++ b/chromium/components/exo/client_controlled_shell_surface.h
@@ -63,9 +63,15 @@ class ClientControlledShellSurface
// Called when the client was restored.
void SetRestored();
- // Called when the client chagned the fullscreen state.
+ // Called when the client changed the fullscreen state.
void SetFullscreen(bool fullscreen);
+ // Called when the client was snapped to left.
+ void SetSnappedToLeft();
+
+ // Called when the client was snapped to right.
+ void SetSnappedToRight();
+
// Set the callback to run when the surface state changed.
using StateChangedCallback =
base::RepeatingCallback<void(ash::mojom::WindowStateType old_state_type,
@@ -77,7 +83,8 @@ class ClientControlledShellSurface
// Set the callback to run when the surface bounds changed.
using BoundsChangedCallback = base::RepeatingCallback<void(
- ash::mojom::WindowStateType current_state_type,
+ ash::mojom::WindowStateType current_state,
+ ash::mojom::WindowStateType requested_state,
int64_t display_id,
const gfx::Rect& bounds,
bool is_resize,
@@ -130,17 +137,20 @@ class ClientControlledShellSurface
// Sends the window bounds change event to client. |display_id| specifies in
// which display the surface should live in. |drag_bounds_change| is
// a masked value of ash::WindowResizer::kBoundsChange_Xxx, and specifies
- // how the bounds was changed.
+ // how the bounds was changed. The bounds change event may also come from a
+ // snapped window state change |requested_state|.
void OnBoundsChangeEvent(ash::mojom::WindowStateType current_state,
+ ash::mojom::WindowStateType requested_state,
int64_t display_id,
const gfx::Rect& bounds,
bool is_resize,
int drag_bounds_change);
+
// Sends the window drag events to client.
void OnDragStarted(int component);
void OnDragFinished(bool cancel, const gfx::Point& location);
- void StartResize_DEPRECATED();
+ void StartResize(int component);
// Starts the move-by-drag operation.
void StartMove(const gfx::Point& location);
@@ -209,6 +219,8 @@ class ClientControlledShellSurface
void UpdateBackdrop();
+ void AttemptToStartDrag(int component, const gfx::Point& location);
+
// Lock the compositor if it's not already locked, or extends the
// lock timeout if it's already locked.
// TODO(reveman): Remove this when using configure callbacks for orientation.
@@ -238,7 +250,8 @@ class ClientControlledShellSurface
ash::wm::ClientControlledState* client_controlled_state_ = nullptr;
- ui::WindowShowState pending_show_state_ = ui::SHOW_STATE_NORMAL;
+ ash::mojom::WindowStateType pending_window_state_ =
+ ash::mojom::WindowStateType::NORMAL;
bool can_maximize_ = true;
diff --git a/chromium/components/exo/client_controlled_shell_surface_unittest.cc b/chromium/components/exo/client_controlled_shell_surface_unittest.cc
index 68ff31e7c4b..a0e69ebf1e7 100644
--- a/chromium/components/exo/client_controlled_shell_surface_unittest.cc
+++ b/chromium/components/exo/client_controlled_shell_surface_unittest.cc
@@ -9,6 +9,7 @@
#include "ash/shell.h"
#include "ash/shell_test_api.h"
#include "ash/system/tray/system_tray.h"
+#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/window_positioning_utils.h"
#include "ash/wm/window_state.h"
@@ -52,7 +53,7 @@ bool IsWidgetPinned(views::Widget* widget) {
type == ash::mojom::WindowPinType::TRUSTED_PINNED;
}
-wm::ShadowElevation GetShadowElevation(aura::Window* window) {
+int GetShadowElevation(aura::Window* window) {
return window->GetProperty(wm::kShadowElevationKey);
}
@@ -249,11 +250,8 @@ TEST_F(ClientControlledShellSurfaceTest, SurfaceShadow) {
aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
- // 1) Initial state, no shadow.
- wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window);
- ASSERT_TRUE(shadow);
- EXPECT_FALSE(shadow->layer()->visible());
-
+ // 1) Initial state, no shadow (SurfaceFrameType is NONE);
+ EXPECT_FALSE(wm::ShadowController::GetShadowForWindow(window));
std::unique_ptr<Display> display(new Display);
// 2) Just creating a sub surface won't create a shadow.
@@ -265,11 +263,14 @@ TEST_F(ClientControlledShellSurfaceTest, SurfaceShadow) {
display->CreateSubSurface(child.get(), surface.get()));
surface->Commit();
- EXPECT_FALSE(shadow->layer()->visible());
+ EXPECT_FALSE(wm::ShadowController::GetShadowForWindow(window));
// 3) Create a shadow.
+ surface->SetFrame(SurfaceFrameType::NORMAL);
shell_surface->SetShadowBounds(gfx::Rect(10, 10, 100, 100));
surface->Commit();
+ wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window);
+ ASSERT_TRUE(shadow);
EXPECT_TRUE(shadow->layer()->visible());
gfx::Rect before = shadow->layer()->bounds();
@@ -296,14 +297,14 @@ TEST_F(ClientControlledShellSurfaceTest, SurfaceShadow) {
shell_surface->SetShadowBounds(gfx::Rect());
surface->Commit();
- EXPECT_EQ(wm::ShadowElevation::NONE, GetShadowElevation(window));
+ EXPECT_EQ(wm::kShadowElevationNone, GetShadowElevation(window));
EXPECT_FALSE(shadow->layer()->visible());
// 6) This should enable non surface shadow again.
shell_surface->SetShadowBounds(gfx::Rect(10, 10, 100, 100));
surface->Commit();
- EXPECT_EQ(wm::ShadowElevation::DEFAULT, GetShadowElevation(window));
+ EXPECT_EQ(wm::kShadowElevationDefault, GetShadowElevation(window));
EXPECT_TRUE(shadow->layer()->visible());
}
@@ -320,6 +321,7 @@ TEST_F(ClientControlledShellSurfaceTest, ShadowWithStateChange) {
const gfx::Rect original_bounds(gfx::Point(10, 10), content_size);
shell_surface->SetGeometry(original_bounds);
surface->Attach(buffer.get());
+ surface->SetFrame(SurfaceFrameType::NORMAL);
surface->Commit();
// Placing a shadow at screen origin will make the shadow's origin (-10, -10).
@@ -335,7 +337,7 @@ TEST_F(ClientControlledShellSurfaceTest, ShadowWithStateChange) {
shell_surface->SetShadowBounds(shadow_bounds);
surface->Commit();
- EXPECT_EQ(wm::ShadowElevation::DEFAULT, GetShadowElevation(window));
+ EXPECT_EQ(wm::kShadowElevationDefault, GetShadowElevation(window));
EXPECT_TRUE(shadow->layer()->visible());
// Origin must be in sync.
@@ -378,6 +380,7 @@ TEST_F(ClientControlledShellSurfaceTest, ShadowWithTransform) {
const gfx::Rect original_bounds(gfx::Point(10, 10), content_size);
shell_surface->SetGeometry(original_bounds);
surface->Attach(buffer.get());
+ surface->SetFrame(SurfaceFrameType::NORMAL);
surface->Commit();
aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
@@ -407,6 +410,7 @@ TEST_F(ClientControlledShellSurfaceTest, ShadowStartMaximized) {
exo_test_helper()->CreateClientControlledShellSurface(surface.get());
shell_surface->SetMaximized();
surface->Attach(buffer.get());
+ surface->SetFrame(SurfaceFrameType::NORMAL);
surface->Commit();
views::Widget* widget = shell_surface->GetWidget();
@@ -415,7 +419,7 @@ TEST_F(ClientControlledShellSurfaceTest, ShadowStartMaximized) {
// There is no shadow when started in maximized state.
EXPECT_FALSE(wm::ShadowController::GetShadowForWindow(window));
- // Sending a shadow bounds in maximized state won't create a shaodw.
+ // Sending a shadow bounds in maximized state won't create a shadow.
shell_surface->SetShadowBounds(gfx::Rect(10, 10, 100, 100));
surface->Commit();
EXPECT_FALSE(wm::ShadowController::GetShadowForWindow(window));
@@ -801,4 +805,100 @@ TEST_F(ClientControlledShellSurfaceTest, ShellSurfaceInSystemModalHitTest) {
EXPECT_FALSE(window->Contains(found));
}
+// Test the snap functionalities in splitscreen in tablet mode.
+TEST_F(ClientControlledShellSurfaceTest, SnapWindowInSplitViewModeTest) {
+ UpdateDisplay("807x607");
+ ash::Shell* shell = ash::Shell::Get();
+ shell->tablet_mode_controller()->EnableTabletModeWindowManager(true);
+
+ const gfx::Size buffer_size(800, 600);
+ std::unique_ptr<Buffer> buffer1(
+ new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
+ std::unique_ptr<Surface> surface1(new Surface);
+ auto shell_surface1 =
+ exo_test_helper()->CreateClientControlledShellSurface(surface1.get());
+ // Start in maximized.
+ shell_surface1->SetMaximized();
+ surface1->Attach(buffer1.get());
+ surface1->Commit();
+
+ aura::Window* window1 = shell_surface1->GetWidget()->GetNativeWindow();
+ ash::wm::WindowState* window_state1 = ash::wm::GetWindowState(window1);
+ ash::wm::ClientControlledState* state1 =
+ static_cast<ash::wm::ClientControlledState*>(
+ ash::wm::WindowState::TestApi::GetStateImpl(window_state1));
+ EXPECT_EQ(window_state1->GetStateType(),
+ ash::mojom::WindowStateType::MAXIMIZED);
+
+ // Snap window to left.
+ ash::SplitViewController* split_view_controller =
+ shell->split_view_controller();
+ split_view_controller->SnapWindow(window1, ash::SplitViewController::LEFT);
+ state1->set_bounds_locally(true);
+ window1->SetBounds(split_view_controller->GetSnappedWindowBoundsInScreen(
+ window1, ash::SplitViewController::LEFT));
+ state1->set_bounds_locally(false);
+ EXPECT_EQ(window_state1->GetStateType(),
+ ash::mojom::WindowStateType::LEFT_SNAPPED);
+ EXPECT_EQ(shell_surface1->GetWidget()->GetWindowBoundsInScreen(),
+ split_view_controller->GetSnappedWindowBoundsInScreen(
+ window1, ash::SplitViewController::LEFT));
+ EXPECT_TRUE(HasBackdrop());
+ split_view_controller->EndSplitView();
+
+ // Snap window to right.
+ split_view_controller->SnapWindow(window1, ash::SplitViewController::RIGHT);
+ state1->set_bounds_locally(true);
+ window1->SetBounds(split_view_controller->GetSnappedWindowBoundsInScreen(
+ window1, ash::SplitViewController::RIGHT));
+ state1->set_bounds_locally(false);
+ EXPECT_EQ(window_state1->GetStateType(),
+ ash::mojom::WindowStateType::RIGHT_SNAPPED);
+ EXPECT_EQ(shell_surface1->GetWidget()->GetWindowBoundsInScreen(),
+ split_view_controller->GetSnappedWindowBoundsInScreen(
+ window1, ash::SplitViewController::RIGHT));
+ EXPECT_TRUE(HasBackdrop());
+}
+
+// The shell surface in SystemModal container should not become target
+// at the edge.
+TEST_F(ClientControlledShellSurfaceTest, ClientIniatedResize) {
+ std::unique_ptr<Surface> surface(new Surface);
+ auto shell_surface =
+ exo_test_helper()->CreateClientControlledShellSurface(surface.get());
+ shell_surface->set_client_controlled_move_resize(false);
+
+ display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
+
+ gfx::Size window_size(100, 100);
+ std::unique_ptr<Buffer> desktop_buffer(
+ new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(window_size)));
+ surface->Attach(desktop_buffer.get());
+ shell_surface->SetGeometry(gfx::Rect(window_size));
+ surface->Commit();
+
+ EXPECT_TRUE(shell_surface->GetWidget()->widget_delegate()->CanResize());
+ shell_surface->StartResize(HTTOP);
+
+ aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
+ // Client cannot start drag if mouse isn't pressed.
+ ash::wm::WindowState* window_state = ash::wm::GetWindowState(window);
+ ASSERT_FALSE(window_state->is_dragged());
+
+ // Client can start drag only when the mouse is pressed on the widget.
+ ui::test::EventGenerator& event_generator = GetEventGenerator();
+ event_generator.MoveMouseToCenterOf(window);
+ event_generator.PressLeftButton();
+ shell_surface->StartResize(HTTOP);
+ ASSERT_TRUE(window_state->is_dragged());
+ event_generator.ReleaseLeftButton();
+ ASSERT_FALSE(window_state->is_dragged());
+
+ // Press pressed outside of the window.
+ event_generator.MoveMouseTo(gfx::Point(200, 50));
+ event_generator.PressLeftButton();
+ shell_surface->StartResize(HTTOP);
+ ASSERT_FALSE(window_state->is_dragged());
+}
+
} // namespace exo
diff --git a/chromium/components/exo/data_device_unittest.cc b/chromium/components/exo/data_device_unittest.cc
index e721cfdc422..382129bf2eb 100644
--- a/chromium/components/exo/data_device_unittest.cc
+++ b/chromium/components/exo/data_device_unittest.cc
@@ -114,11 +114,10 @@ class TestFileHelper : public FileHelper {
GURL* out) override {
return true;
}
- bool GetUrlFromFileSystemUrl(const std::string& app_id,
- const GURL& url,
- GURL* out) override {
- return false;
- }
+ bool HasUrlsInPickle(const base::Pickle& pickle) override { return false; }
+ void GetUrlsFromPickle(const std::string& app_id,
+ const base::Pickle& pickle,
+ UrlsFromPickleCallback callback) override {}
private:
DISALLOW_COPY_AND_ASSIGN(TestFileHelper);
diff --git a/chromium/components/exo/data_offer.cc b/chromium/components/exo/data_offer.cc
index 13fca50d435..6f057580939 100644
--- a/chromium/components/exo/data_offer.cc
+++ b/chromium/components/exo/data_offer.cc
@@ -6,6 +6,7 @@
#include "base/files/file_util.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "components/exo/data_offer_delegate.h"
@@ -52,9 +53,38 @@ void WriteFileDescriptor(base::ScopedFD fd,
DLOG(ERROR) << "Failed to write drop data";
}
+// Gets a comma-separated list of urls extracted from |data|->file.
+bool GetUrlListFromDataFile(FileHelper* file_helper,
+ const ui::OSExchangeData& data,
+ base::string16* url_list_string) {
+ if (!data.HasFile())
+ return false;
+ std::vector<ui::FileInfo> files;
+ if (data.GetFilenames(&files)) {
+ for (const auto& info : files) {
+ GURL url;
+ // TODO(niwa): Need to fill the correct app_id.
+ if (file_helper->GetUrlFromPath(/* app_id */ "", info.path, &url)) {
+ if (!url_list_string->empty())
+ *url_list_string += base::UTF8ToUTF16(kUriListSeparator);
+ *url_list_string += base::UTF8ToUTF16(url.spec());
+ }
+ }
+ }
+ return !url_list_string->empty();
+}
+
+ui::Clipboard::FormatType GetClipboardFormatType() {
+ static const char kFormatString[] = "chromium/x-file-system-files";
+ CR_DEFINE_STATIC_LOCAL(ui::Clipboard::FormatType, format_type,
+ (ui::Clipboard::GetFormatType(kFormatString)));
+ return format_type;
+}
+
} // namespace
-DataOffer::DataOffer(DataOfferDelegate* delegate) : delegate_(delegate) {}
+DataOffer::DataOffer(DataOfferDelegate* delegate)
+ : delegate_(delegate), weak_ptr_factory_(this) {}
DataOffer::~DataOffer() {
delegate_->OnDataOfferDestroying(this);
@@ -74,15 +104,20 @@ void DataOffer::RemoveObserver(DataOfferObserver* observer) {
void DataOffer::Accept(const std::string& mime_type) {}
void DataOffer::Receive(const std::string& mime_type, base::ScopedFD fd) {
- const auto it = data_.find(mime_type);
- if (it == data_.end()) {
+ const auto data_it = data_.find(mime_type);
+ if (data_it == data_.end()) {
DLOG(ERROR) << "Unexpected mime type is requested";
return;
}
-
- base::PostTaskWithTraits(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
- base::BindOnce(&WriteFileDescriptor, std::move(fd), it->second));
+ if (data_it->second) {
+ base::PostTaskWithTraits(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ base::BindOnce(&WriteFileDescriptor, std::move(fd), data_it->second));
+ } else {
+ // Data bytes for this mime type are being processed currently.
+ pending_receive_requests_.push_back(
+ std::make_pair(mime_type, std::move(fd)));
+ }
}
void DataOffer::Finish() {}
@@ -102,32 +137,39 @@ void DataOffer::SetSourceActions(
void DataOffer::SetDropData(FileHelper* file_helper,
const ui::OSExchangeData& data) {
DCHECK_EQ(0u, data_.size());
- if (data.HasString()) {
- base::string16 string_content;
- if (data.GetString(&string_content)) {
- data_.emplace(std::string(ui::Clipboard::kMimeTypeText),
- RefCountedString16::TakeString(std::move(string_content)));
- }
+
+ const std::string uri_list_mime_type = file_helper->GetMimeTypeForUriList();
+ base::string16 url_list_string;
+ if (GetUrlListFromDataFile(file_helper, data, &url_list_string)) {
+ data_.emplace(uri_list_mime_type,
+ RefCountedString16::TakeString(std::move(url_list_string)));
+ delegate_->OnOffer(uri_list_mime_type);
+ return;
}
- if (data.HasFile()) {
- std::vector<ui::FileInfo> files;
- if (data.GetFilenames(&files)) {
- base::string16 url_list;
- for (const auto& info : files) {
- GURL url;
- // TODO(hirono): Need to fill the corret app_id.
- if (file_helper->GetUrlFromPath(/* app_id */ "", info.path, &url)) {
- if (!url_list.empty())
- url_list += base::UTF8ToUTF16(kUriListSeparator);
- url_list += base::UTF8ToUTF16(url.spec());
- }
- }
- data_.emplace(file_helper->GetMimeTypeForUriList(),
- RefCountedString16::TakeString(std::move(url_list)));
- }
+
+ base::Pickle pickle;
+ if (data.GetPickledData(GetClipboardFormatType(), &pickle) &&
+ file_helper->HasUrlsInPickle(pickle)) {
+ // Set nullptr as a temporary value for the mime type.
+ // The value will be overriden in the callback below.
+ data_.emplace(uri_list_mime_type, nullptr);
+ // TODO(niwa): Need to fill the correct app_id.
+ file_helper->GetUrlsFromPickle(
+ /* app_id */ "", pickle,
+ base::BindOnce(&DataOffer::OnPickledUrlsResolved,
+ weak_ptr_factory_.GetWeakPtr(), uri_list_mime_type));
+ delegate_->OnOffer(uri_list_mime_type);
+ return;
}
- for (const auto& pair : data_) {
- delegate_->OnOffer(pair.first);
+
+ base::string16 string_content;
+ if (data.HasString() && data.GetString(&string_content)) {
+ const std::string text_mime_type =
+ std::string(ui::Clipboard::kMimeTypeText);
+ data_.emplace(text_mime_type,
+ RefCountedString16::TakeString(std::move(string_content)));
+ delegate_->OnOffer(text_mime_type);
+ return;
}
}
@@ -141,9 +183,41 @@ void DataOffer::SetClipboardData(FileHelper* file_helper,
std::string utf8_content = base::UTF16ToUTF8(content);
data_.emplace(std::string(kTextMimeTypeUtf8),
base::RefCountedString::TakeString(&utf8_content));
+ delegate_->OnOffer(std::string(kTextMimeTypeUtf8));
}
- for (const auto& pair : data_) {
- delegate_->OnOffer(pair.first);
+}
+
+void DataOffer::OnPickledUrlsResolved(const std::string& mime_type,
+ const std::vector<GURL>& urls) {
+ const auto data_it = data_.find(mime_type);
+ DCHECK(data_it != data_.end());
+ DCHECK(!data_it->second); // nullptr should be set as a temporary value.
+ data_.erase(data_it);
+
+ base::string16 url_list_string;
+ for (const GURL& url : urls) {
+ if (!url.is_valid())
+ continue;
+ if (!url_list_string.empty())
+ url_list_string += base::UTF8ToUTF16(kUriListSeparator);
+ url_list_string += base::UTF8ToUTF16(url.spec());
+ }
+ const auto ref_counted_memory =
+ RefCountedString16::TakeString(std::move(url_list_string));
+ data_.emplace(mime_type, ref_counted_memory);
+
+ // Process pending receive requests for this mime type, if there are any.
+ auto it = pending_receive_requests_.begin();
+ while (it != pending_receive_requests_.end()) {
+ if (it->first == mime_type) {
+ base::PostTaskWithTraits(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ base::BindOnce(&WriteFileDescriptor, std::move(it->second),
+ ref_counted_memory));
+ it = pending_receive_requests_.erase(it);
+ } else {
+ ++it;
+ }
}
}
diff --git a/chromium/components/exo/data_offer.h b/chromium/components/exo/data_offer.h
index 45fc91dfede..a3abf03b2af 100644
--- a/chromium/components/exo/data_offer.h
+++ b/chromium/components/exo/data_offer.h
@@ -15,6 +15,7 @@
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "ui/base/class_property.h"
+#include "url/gurl.h"
namespace base {
class RefCountedMemory;
@@ -60,6 +61,10 @@ class DataOffer final : public ui::PropertyHandler {
// Sets the dropped data from |data| to the DataOffer object. |file_helper|
// will be used to convert paths to handle mount points which is mounted in
// the mount point namespace of clinet process.
+ // While this function immediately calls DataOfferDelegate::OnOffer inside it
+ // with found mime types, dropped data bytes may be populated asynchronously
+ // after this function call.
+ // (e.g. Asynchronous lookup is required for resolving file system urls.)
void SetDropData(FileHelper* file_helper, const ui::OSExchangeData& data);
// Sets the clipboard data from |data| to the DataOffer object.
@@ -72,13 +77,22 @@ class DataOffer final : public ui::PropertyHandler {
DndAction dnd_action() { return dnd_action_; }
private:
+ void OnPickledUrlsResolved(const std::string& uri_list_mime_type,
+ const std::vector<GURL>& urls);
+
DataOfferDelegate* const delegate_;
// Map between mime type and drop data bytes.
+ // nullptr may be set as a temporary value until data bytes are populated.
base::flat_map<std::string, scoped_refptr<base::RefCountedMemory>> data_;
+ // Unprocessed receive requests (pairs of mime type and FD) that are waiting
+ // for unpopulated (nullptr) data bytes in |data_| to be populated.
+ std::vector<std::pair<std::string, base::ScopedFD>> pending_receive_requests_;
+
base::flat_set<DndAction> source_actions_;
DndAction dnd_action_;
base::ObserverList<DataOfferObserver> observers_;
+ base::WeakPtrFactory<DataOffer> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DataOffer);
};
diff --git a/chromium/components/exo/data_offer_unittest.cc b/chromium/components/exo/data_offer_unittest.cc
index 0c8976ec1bf..86d5954d550 100644
--- a/chromium/components/exo/data_offer_unittest.cc
+++ b/chromium/components/exo/data_offer_unittest.cc
@@ -77,13 +77,20 @@ class TestFileHelper : public FileHelper {
*out = GURL("file://" + path.AsUTF8Unsafe());
return true;
}
- bool GetUrlFromFileSystemUrl(const std::string& app_id,
- const GURL& url,
- GURL* out) override {
- return false;
+ bool HasUrlsInPickle(const base::Pickle& pickle) override { return true; }
+ void GetUrlsFromPickle(const std::string& app_id,
+ const base::Pickle& pickle,
+ UrlsFromPickleCallback callback) override {
+ callback_ = std::move(callback);
+ }
+
+ void RunUrlsCallback(std::vector<GURL> urls) {
+ std::move(callback_).Run(urls);
}
private:
+ UrlsFromPickleCallback callback_;
+
DISALLOW_COPY_AND_ASSIGN(TestFileHelper);
};
@@ -165,6 +172,26 @@ TEST_F(DataOfferTest, SetFileDropData) {
EXPECT_EQ("text/uri-list", delegate.mime_types()[0]);
}
+TEST_F(DataOfferTest, SetPickleDropData) {
+ TestDataOfferDelegate delegate;
+ DataOffer data_offer(&delegate);
+
+ TestFileHelper file_helper;
+ ui::OSExchangeData data;
+
+ base::Pickle pickle;
+ pickle.WriteUInt32(1); // num files
+ pickle.WriteString("filesystem:chrome-extension://path/to/file1");
+ pickle.WriteInt64(1000); // file size
+ pickle.WriteString("id"); // filesystem id
+ data.SetPickledData(
+ ui::Clipboard::GetFormatType("chromium/x-file-system-files"), pickle);
+ data_offer.SetDropData(&file_helper, data);
+
+ EXPECT_EQ(1u, delegate.mime_types().size());
+ EXPECT_EQ("text/uri-list", delegate.mime_types()[0]);
+}
+
TEST_F(DataOfferTest, ReceiveString) {
TestDataOfferDelegate delegate;
DataOffer data_offer(&delegate);
@@ -203,6 +230,123 @@ TEST_F(DataOfferTest, ReceiveUriList) {
EXPECT_EQ(base::ASCIIToUTF16("file:///test/downloads/file"), result);
}
+TEST_F(DataOfferTest, ReceiveUriListFromPickle_ReceiveAfterUrlIsResolved) {
+ TestDataOfferDelegate delegate;
+ DataOffer data_offer(&delegate);
+
+ TestFileHelper file_helper;
+ ui::OSExchangeData data;
+
+ base::Pickle pickle;
+ pickle.WriteUInt32(1); // num files
+ pickle.WriteString("filesystem:chrome-extension://path/to/file1");
+ pickle.WriteInt64(1000); // file size
+ pickle.WriteString("id"); // filesystem id
+ data.SetPickledData(
+ ui::Clipboard::GetFormatType("chromium/x-file-system-files"), pickle);
+ data_offer.SetDropData(&file_helper, data);
+
+ // Run callback with a resolved URL.
+ std::vector<GURL> urls;
+ urls.push_back(
+ GURL("content://org.chromium.arc.chromecontentprovider/path/to/file1"));
+ file_helper.RunUrlsCallback(urls);
+
+ base::ScopedFD read_pipe;
+ base::ScopedFD write_pipe;
+ CreatePipe(&read_pipe, &write_pipe);
+
+ // Receive is called after UrlsCallback runs.
+ data_offer.Receive("text/uri-list", std::move(write_pipe));
+ base::string16 result;
+ ASSERT_TRUE(ReadString16(std::move(read_pipe), &result));
+ EXPECT_EQ(
+ base::ASCIIToUTF16(
+ "content://org.chromium.arc.chromecontentprovider/path/to/file1"),
+ result);
+}
+
+TEST_F(DataOfferTest, ReceiveUriListFromPickle_ReceiveBeforeUrlIsResolved) {
+ TestDataOfferDelegate delegate;
+ DataOffer data_offer(&delegate);
+
+ TestFileHelper file_helper;
+ ui::OSExchangeData data;
+
+ base::Pickle pickle;
+ pickle.WriteUInt32(1); // num files
+ pickle.WriteString("filesystem:chrome-extension://path/to/file1");
+ pickle.WriteInt64(1000); // file size
+ pickle.WriteString("id"); // filesystem id
+ data.SetPickledData(
+ ui::Clipboard::GetFormatType("chromium/x-file-system-files"), pickle);
+ data_offer.SetDropData(&file_helper, data);
+
+ base::ScopedFD read_pipe1;
+ base::ScopedFD write_pipe1;
+ CreatePipe(&read_pipe1, &write_pipe1);
+ base::ScopedFD read_pipe2;
+ base::ScopedFD write_pipe2;
+ CreatePipe(&read_pipe2, &write_pipe2);
+
+ // Receive is called (twice) before UrlsFromPickleCallback runs.
+ data_offer.Receive("text/uri-list", std::move(write_pipe1));
+ data_offer.Receive("text/uri-list", std::move(write_pipe2));
+
+ // Run callback with a resolved URL.
+ std::vector<GURL> urls;
+ urls.push_back(
+ GURL("content://org.chromium.arc.chromecontentprovider/path/to/file1"));
+ file_helper.RunUrlsCallback(urls);
+
+ base::string16 result1;
+ ASSERT_TRUE(ReadString16(std::move(read_pipe1), &result1));
+ EXPECT_EQ(
+ base::ASCIIToUTF16(
+ "content://org.chromium.arc.chromecontentprovider/path/to/file1"),
+ result1);
+ base::string16 result2;
+ ASSERT_TRUE(ReadString16(std::move(read_pipe2), &result2));
+ EXPECT_EQ(
+ base::ASCIIToUTF16(
+ "content://org.chromium.arc.chromecontentprovider/path/to/file1"),
+ result2);
+}
+
+TEST_F(DataOfferTest,
+ ReceiveUriListFromPickle_ReceiveBeforeEmptyUrlIsReturned) {
+ TestDataOfferDelegate delegate;
+ DataOffer data_offer(&delegate);
+
+ TestFileHelper file_helper;
+ ui::OSExchangeData data;
+
+ base::Pickle pickle;
+ pickle.WriteUInt32(1); // num files
+ pickle.WriteString("filesystem:chrome-extension://path/to/file1");
+ pickle.WriteInt64(1000); // file size
+ pickle.WriteString("id"); // filesystem id
+ data.SetPickledData(
+ ui::Clipboard::GetFormatType("chromium/x-file-system-files"), pickle);
+ data_offer.SetDropData(&file_helper, data);
+
+ base::ScopedFD read_pipe;
+ base::ScopedFD write_pipe;
+ CreatePipe(&read_pipe, &write_pipe);
+
+ // Receive is called before UrlsCallback runs.
+ data_offer.Receive("text/uri-list", std::move(write_pipe));
+
+ // Run callback with an empty URL.
+ std::vector<GURL> urls;
+ urls.push_back(GURL(""));
+ file_helper.RunUrlsCallback(urls);
+
+ base::string16 result;
+ ASSERT_TRUE(ReadString16(std::move(read_pipe), &result));
+ EXPECT_EQ(base::ASCIIToUTF16(""), result);
+}
+
TEST_F(DataOfferTest, SetClipboardData) {
TestDataOfferDelegate delegate;
DataOffer data_offer(&delegate);
diff --git a/chromium/components/exo/display_unittest.cc b/chromium/components/exo/display_unittest.cc
index cf56b5596ad..fd80b228f84 100644
--- a/chromium/components/exo/display_unittest.cc
+++ b/chromium/components/exo/display_unittest.cc
@@ -232,11 +232,10 @@ class TestFileHelper : public FileHelper {
GURL* out) override {
return true;
}
- bool GetUrlFromFileSystemUrl(const std::string& app_id,
- const GURL& url,
- GURL* out) override {
- return false;
- }
+ bool HasUrlsInPickle(const base::Pickle& pickle) override { return false; }
+ void GetUrlsFromPickle(const std::string& app_id,
+ const base::Pickle& pickle,
+ UrlsFromPickleCallback callback) override {}
};
TEST_F(DisplayTest, CreateDataDevice) {
diff --git a/chromium/components/exo/file_helper.h b/chromium/components/exo/file_helper.h
index 28702db66c2..80c746badea 100644
--- a/chromium/components/exo/file_helper.h
+++ b/chromium/components/exo/file_helper.h
@@ -33,11 +33,19 @@ class FileHelper {
const base::FilePath& path,
GURL* out) = 0;
- // Converts filesystem:// URL to something that applications can understand.
- // e.g. content:// URI for Android apps.
- virtual bool GetUrlFromFileSystemUrl(const std::string& app_id,
- const GURL& file_system_url,
- GURL* out) = 0;
+ // Takes in |pickle| constructed by the web contents view and returns true if
+ // it contains any valid filesystem URLs.
+ virtual bool HasUrlsInPickle(const base::Pickle& pickle) = 0;
+
+ using UrlsFromPickleCallback =
+ base::OnceCallback<void(const std::vector<GURL>& urls)>;
+
+ // Takes in |pickle| constructed by the web contents view, reads filesystem
+ // URLs from it and converts the URLs to something that applications can
+ // understand. e.g. content:// URI for Android apps.
+ virtual void GetUrlsFromPickle(const std::string& app_id,
+ const base::Pickle& pickle,
+ UrlsFromPickleCallback callback) = 0;
};
} // namespace exo
diff --git a/chromium/components/exo/keyboard.cc b/chromium/components/exo/keyboard.cc
index b42fb1153f6..fc0810012dc 100644
--- a/chromium/components/exo/keyboard.cc
+++ b/chromium/components/exo/keyboard.cc
@@ -241,28 +241,32 @@ void Keyboard::OnKeyEvent(ui::KeyEvent* event) {
switch (event->type()) {
case ui::ET_KEY_PRESSED:
- if (focus_ && !consumed_by_ime && !event->handled()) {
- uint32_t serial =
- delegate_->OnKeyboardKey(event->time_stamp(), event->code(), true);
- if (are_keyboard_key_acks_needed_) {
- pending_key_acks_.insert(
- {serial,
- {*event, base::TimeTicks::Now() +
- expiration_delay_for_pending_key_acks_}});
- event->SetHandled();
+ if (pressed_keys_.insert(event->code()).second) {
+ if (focus_ && !consumed_by_ime && !event->handled()) {
+ uint32_t serial = delegate_->OnKeyboardKey(event->time_stamp(),
+ event->code(), true);
+ if (are_keyboard_key_acks_needed_) {
+ pending_key_acks_.insert(
+ {serial,
+ {*event, base::TimeTicks::Now() +
+ expiration_delay_for_pending_key_acks_}});
+ event->SetHandled();
+ }
}
}
break;
case ui::ET_KEY_RELEASED:
- if (focus_ && !consumed_by_ime && !event->handled()) {
- uint32_t serial =
- delegate_->OnKeyboardKey(event->time_stamp(), event->code(), false);
- if (are_keyboard_key_acks_needed_) {
- pending_key_acks_.insert(
- {serial,
- {*event, base::TimeTicks::Now() +
- expiration_delay_for_pending_key_acks_}});
- event->SetHandled();
+ if (pressed_keys_.erase(event->code())) {
+ if (focus_ && !consumed_by_ime && !event->handled()) {
+ uint32_t serial = delegate_->OnKeyboardKey(event->time_stamp(),
+ event->code(), false);
+ if (are_keyboard_key_acks_needed_) {
+ pending_key_acks_.insert(
+ {serial,
+ {*event, base::TimeTicks::Now() +
+ expiration_delay_for_pending_key_acks_}});
+ event->SetHandled();
+ }
}
}
break;
@@ -336,8 +340,9 @@ void Keyboard::SetFocus(Surface* surface) {
}
if (surface) {
modifier_flags_ = seat_->modifier_flags() & kModifierMask;
+ pressed_keys_ = seat_->pressed_keys();
delegate_->OnKeyboardModifiers(modifier_flags_);
- delegate_->OnKeyboardEnter(surface, seat_->pressed_keys());
+ delegate_->OnKeyboardEnter(surface, pressed_keys_);
focus_ = surface;
focus_->AddSurfaceObserver(this);
}
diff --git a/chromium/components/exo/keyboard.h b/chromium/components/exo/keyboard.h
index 871e26a5e83..539e3fd4e4c 100644
--- a/chromium/components/exo/keyboard.h
+++ b/chromium/components/exo/keyboard.h
@@ -9,6 +9,7 @@
#include "ash/wm/tablet_mode/tablet_mode_observer.h"
#include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "components/exo/keyboard_observer.h"
@@ -19,6 +20,7 @@
#include "ui/events/event_handler.h"
namespace ui {
+enum class DomCode;
class KeyEvent;
}
@@ -39,6 +41,8 @@ class Keyboard : public ui::EventHandler,
Keyboard(KeyboardDelegate* delegate, Seat* seat);
~Keyboard() override;
+ KeyboardDelegate* delegate() const { return delegate_; }
+
bool HasDeviceConfigurationDelegate() const;
void SetDeviceConfigurationDelegate(
KeyboardDeviceConfigurationDelegate* delegate);
@@ -107,6 +111,9 @@ class Keyboard : public ui::EventHandler,
// The current focus surface for the keyboard.
Surface* focus_ = nullptr;
+ // Set of currently pressed keys.
+ base::flat_set<ui::DomCode> pressed_keys_;
+
// Current set of modifier flags.
int modifier_flags_ = 0;
diff --git a/chromium/components/exo/keyboard_unittest.cc b/chromium/components/exo/keyboard_unittest.cc
index 7948ca0b77b..82f453bd744 100644
--- a/chromium/components/exo/keyboard_unittest.cc
+++ b/chromium/components/exo/keyboard_unittest.cc
@@ -174,6 +174,9 @@ TEST_F(KeyboardTest, OnKeyboardKey) {
EXPECT_CALL(delegate, OnKeyboardKey(testing::_, ui::DomCode::US_A, true));
generator.PressKey(ui::VKEY_A, 0);
+ // This should not generate another press event for KEY_A.
+ generator.PressKey(ui::VKEY_A, 0);
+
// This should only generate a release event for KEY_A.
EXPECT_CALL(delegate, OnKeyboardKey(testing::_, ui::DomCode::US_A, false));
generator.ReleaseKey(ui::VKEY_A, 0);
diff --git a/chromium/components/exo/pointer.cc b/chromium/components/exo/pointer.cc
index 6e46f09336d..5df27aa527f 100644
--- a/chromium/components/exo/pointer.cc
+++ b/chromium/components/exo/pointer.cc
@@ -391,6 +391,10 @@ void Pointer::CaptureCursor(const gfx::Point& hotspot) {
DCHECK(root_surface());
DCHECK(focus_surface_);
+ // Defer capture until surface commit.
+ if (host_window()->bounds().IsEmpty())
+ return;
+
// Submit compositor frame to be captured.
SubmitCompositorFrame();
diff --git a/chromium/components/exo/pointer.h b/chromium/components/exo/pointer.h
index 56a0753a74b..e4766e4a635 100644
--- a/chromium/components/exo/pointer.h
+++ b/chromium/components/exo/pointer.h
@@ -48,6 +48,8 @@ class Pointer : public SurfaceTreeHost,
explicit Pointer(PointerDelegate* delegate);
~Pointer() override;
+ PointerDelegate* delegate() const { return delegate_; }
+
// Set the pointer surface, i.e., the surface that contains the pointer image
// (cursor). The |hotspot| argument defines the position of the pointer
// surface relative to the pointer location. Its top-left corner is always at
diff --git a/chromium/components/exo/shell_surface.cc b/chromium/components/exo/shell_surface.cc
index b14d7aafd1f..960ba6b9cfb 100644
--- a/chromium/components/exo/shell_surface.cc
+++ b/chromium/components/exo/shell_surface.cc
@@ -163,8 +163,8 @@ void ShellSurface::OnPreWindowStateTypeChange(
ash::wm::WindowState* window_state,
ash::mojom::WindowStateType old_type) {
ash::mojom::WindowStateType new_type = window_state->GetStateType();
- if (old_type == ash::mojom::WindowStateType::MINIMIZED ||
- new_type == ash::mojom::WindowStateType::MINIMIZED) {
+ if (ash::IsMinimizedWindowStateType(old_type) ||
+ ash::IsMinimizedWindowStateType(new_type)) {
return;
}
diff --git a/chromium/components/exo/shell_surface_base.cc b/chromium/components/exo/shell_surface_base.cc
index 7023369b1d4..72e89ad04ee 100644
--- a/chromium/components/exo/shell_surface_base.cc
+++ b/chromium/components/exo/shell_surface_base.cc
@@ -904,7 +904,8 @@ void ShellSurfaceBase::OnWindowBoundsChanged(aura::Window* window,
UpdateSurfaceBounds();
// The shadow size may be updated to match the widget. Change it back
- // to the shadow content size.
+ // to the shadow content size. Note that this relies on wm::ShadowController
+ // being notified of the change before |this|.
UpdateShadow();
Configure();
@@ -1255,9 +1256,9 @@ void ShellSurfaceBase::UpdateShadow() {
aura::Window* window = widget_->GetNativeWindow();
if (!shadow_bounds_) {
- wm::SetShadowElevation(window, wm::ShadowElevation::NONE);
+ wm::SetShadowElevation(window, wm::kShadowElevationNone);
} else {
- wm::SetShadowElevation(window, wm::ShadowElevation::DEFAULT);
+ wm::SetShadowElevation(window, wm::kShadowElevationDefault);
wm::Shadow* shadow = wm::ShadowController::GetShadowForWindow(window);
// Maximized/Fullscreen window does not create a shadow.
@@ -1268,7 +1269,7 @@ void ShellSurfaceBase::UpdateShadow() {
// Surfaces that can't be activated are usually menus and tooltips. Use a
// small style shadow for them.
if (!activatable_)
- shadow->SetElevation(wm::ShadowElevation::SMALL);
+ shadow->SetElevation(wm::kShadowElevationMenuOrTooltip);
// We don't have rounded corners unless frame is enabled.
if (!frame_enabled_)
shadow->SetRoundedCornerRadius(0);
diff --git a/chromium/components/exo/shell_surface_unittest.cc b/chromium/components/exo/shell_surface_unittest.cc
index ea3e69d668b..9eb38d8eb2a 100644
--- a/chromium/components/exo/shell_surface_unittest.cc
+++ b/chromium/components/exo/shell_surface_unittest.cc
@@ -34,9 +34,6 @@
#include "ui/display/manager/display_manager.h"
#include "ui/display/screen.h"
#include "ui/views/widget/widget.h"
-#include "ui/wm/core/shadow.h"
-#include "ui/wm/core/shadow_controller.h"
-#include "ui/wm/core/shadow_types.h"
#include "ui/wm/core/window_util.h"
namespace exo {
diff --git a/chromium/components/exo/surface.cc b/chromium/components/exo/surface.cc
index 4ec4511ac0c..cb4793db31f 100644
--- a/chromium/components/exo/surface.cc
+++ b/chromium/components/exo/surface.cc
@@ -23,7 +23,6 @@
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/resources/single_release_callback.h"
-#include "components/viz/common/surfaces/sequence_surface_reference_factory.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_manager.h"
#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
diff --git a/chromium/components/exo/touch.h b/chromium/components/exo/touch.h
index 63b37a8caea..88d1048ca2d 100644
--- a/chromium/components/exo/touch.h
+++ b/chromium/components/exo/touch.h
@@ -27,6 +27,8 @@ class Touch : public ui::EventHandler, public SurfaceObserver {
explicit Touch(TouchDelegate* delegate);
~Touch() override;
+ TouchDelegate* delegate() const { return delegate_; }
+
// Set delegate for stylus events.
void SetStylusDelegate(TouchStylusDelegate* delegate);
bool HasStylusDelegate() const;
diff --git a/chromium/components/exo/wayland/BUILD.gn b/chromium/components/exo/wayland/BUILD.gn
index 3c166c0d41e..4244919a0b9 100644
--- a/chromium/components/exo/wayland/BUILD.gn
+++ b/chromium/components/exo/wayland/BUILD.gn
@@ -72,6 +72,7 @@ source_set("wayland") {
"//third_party/wayland:wayland_server",
"//third_party/wayland-protocols:alpha_compositing_protocol",
"//third_party/wayland-protocols:gaming_input_protocol",
+ "//third_party/wayland-protocols:input_timestamps_protocol",
"//third_party/wayland-protocols:keyboard_configuration_protocol",
"//third_party/wayland-protocols:keyboard_extension_protocol",
"//third_party/wayland-protocols:pointer_gestures_protocol",
@@ -153,6 +154,7 @@ source_set("client_support") {
public_deps = [
"//skia",
"//third_party/wayland:wayland_client",
+ "//third_party/wayland-protocols:input_timestamps_protocol",
"//third_party/wayland-protocols:linux_dmabuf_protocol",
"//third_party/wayland-protocols:presentation_time_protocol",
]
@@ -183,6 +185,7 @@ executable("wayland_rects_client") {
"//build/config:exe_and_shlib_deps",
"//skia",
"//third_party/wayland:wayland_client",
+ "//third_party/wayland-protocols:input_timestamps_protocol",
"//third_party/wayland-protocols:linux_dmabuf_protocol",
"//third_party/wayland-protocols:presentation_time_protocol",
"//ui/gfx/geometry",
diff --git a/chromium/components/exo/wayland/clients/client_base.cc b/chromium/components/exo/wayland/clients/client_base.cc
index 88e6255b3e2..a086acaa591 100644
--- a/chromium/components/exo/wayland/clients/client_base.cc
+++ b/chromium/components/exo/wayland/clients/client_base.cc
@@ -72,7 +72,7 @@ namespace {
const int32_t kShmFormat = WL_SHM_FORMAT_ARGB8888;
const SkColorType kColorType = kBGRA_8888_SkColorType;
#if defined(USE_GBM)
-const GrPixelConfig kGrPixelConfig = kBGRA_8888_GrPixelConfig;
+const GLenum kSizedInternalFormat = GL_BGRA8_EXT;
#endif
const size_t kBytesPerPixel = 4;
@@ -112,6 +112,10 @@ void RegistryHandler(void* data,
} else if (strcmp(interface, "wl_subcompositor") == 0) {
globals->subcompositor.reset(static_cast<wl_subcompositor*>(
wl_registry_bind(registry, id, &wl_subcompositor_interface, 1)));
+ } else if (strcmp(interface, "zwp_input_timestamps_manager_v1") == 0) {
+ globals->input_timestamps_manager.reset(
+ static_cast<zwp_input_timestamps_manager_v1*>(wl_registry_bind(
+ registry, id, &zwp_input_timestamps_manager_v1_interface, 1)));
}
}
@@ -668,11 +672,13 @@ std::unique_ptr<ClientBase::Buffer> ClientBase::CreateDrmBuffer(
GrGLTextureInfo texture_info;
texture_info.fID = buffer->texture->get();
texture_info.fTarget = GL_TEXTURE_2D;
+ texture_info.fFormat = kSizedInternalFormat;
GrBackendTexture backend_texture(size.width(), size.height(),
- kGrPixelConfig, texture_info);
+ GrMipMapped::kNo, texture_info);
buffer->sk_surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
gr_context_.get(), backend_texture, kTopLeft_GrSurfaceOrigin,
- /* sampleCnt */ 0, /* colorSpace */ nullptr, /* props */ nullptr);
+ /* sampleCnt */ 0, kColorType, /* colorSpace */ nullptr,
+ /* props */ nullptr);
DCHECK(buffer->sk_surface);
#if defined(USE_VULKAN)
diff --git a/chromium/components/exo/wayland/clients/client_base.h b/chromium/components/exo/wayland/clients/client_base.h
index 3122ce55180..4b395dbf4aa 100644
--- a/chromium/components/exo/wayland/clients/client_base.h
+++ b/chromium/components/exo/wayland/clients/client_base.h
@@ -68,6 +68,7 @@ class ClientBase {
std::unique_ptr<wl_seat> seat;
std::unique_ptr<wl_subcompositor> subcompositor;
std::unique_ptr<zaura_shell> aura_shell;
+ std::unique_ptr<zwp_input_timestamps_manager_v1> input_timestamps_manager;
};
struct Buffer {
diff --git a/chromium/components/exo/wayland/clients/client_helper.cc b/chromium/components/exo/wayland/clients/client_helper.cc
index 943e3045d88..7d0a1ecaf75 100644
--- a/chromium/components/exo/wayland/clients/client_helper.cc
+++ b/chromium/components/exo/wayland/clients/client_helper.cc
@@ -4,6 +4,7 @@
#include "components/exo/wayland/clients/client_helper.h"
+#include <input-timestamps-unstable-v1-client-protocol.h>
#include <linux-dmabuf-unstable-v1-client-protocol.h>
#include <presentation-time-client-protocol.h>
#include <wayland-client-core.h>
@@ -47,6 +48,9 @@ DEFAULT_DELETER(struct wp_presentation_feedback,
DEFAULT_DELETER(zaura_shell, zaura_shell_destroy)
DEFAULT_DELETER(zaura_surface, zaura_surface_destroy)
DEFAULT_DELETER(zaura_output, zaura_output_destroy)
+DEFAULT_DELETER(zwp_input_timestamps_manager_v1,
+ zwp_input_timestamps_manager_v1_destroy);
+DEFAULT_DELETER(zwp_input_timestamps_v1, zwp_input_timestamps_v1_destroy)
DEFAULT_DELETER(zwp_linux_buffer_params_v1, zwp_linux_buffer_params_v1_destroy)
DEFAULT_DELETER(zwp_linux_dmabuf_v1, zwp_linux_dmabuf_v1_destroy)
diff --git a/chromium/components/exo/wayland/clients/client_helper.h b/chromium/components/exo/wayland/clients/client_helper.h
index 0f3eb96f95b..f7910862c38 100644
--- a/chromium/components/exo/wayland/clients/client_helper.h
+++ b/chromium/components/exo/wayland/clients/client_helper.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_EXO_WAYLAND_CLIENTS_CLIENT_HELPER_H_
#define COMPONENTS_EXO_WAYLAND_CLIENTS_CLIENT_HELPER_H_
+#include <input-timestamps-unstable-v1-client-protocol.h>
#include <linux-dmabuf-unstable-v1-client-protocol.h>
#include <presentation-time-client-protocol.h>
#include <wayland-client-core.h>
@@ -52,6 +53,8 @@ DEFAULT_DELETER_FDECL(struct wp_presentation_feedback)
DEFAULT_DELETER_FDECL(zaura_shell)
DEFAULT_DELETER_FDECL(zaura_surface)
DEFAULT_DELETER_FDECL(zaura_output)
+DEFAULT_DELETER_FDECL(zwp_input_timestamps_manager_v1)
+DEFAULT_DELETER_FDECL(zwp_input_timestamps_v1)
DEFAULT_DELETER_FDECL(zwp_linux_buffer_params_v1)
DEFAULT_DELETER_FDECL(zwp_linux_dmabuf_v1)
diff --git a/chromium/components/exo/wayland/clients/rects.cc b/chromium/components/exo/wayland/clients/rects.cc
index f15af3066a0..3c74efa5ea2 100644
--- a/chromium/components/exo/wayland/clients/rects.cc
+++ b/chromium/components/exo/wayland/clients/rects.cc
@@ -47,7 +47,11 @@ const double kRotationSpeed = 360.0;
// Benchmark warmup frames before starting measurement.
const int kBenchmarkWarmupFrames = 10;
-using EventTimeStack = std::vector<uint32_t>;
+struct EventTimes {
+ std::vector<base::TimeTicks> motion_timestamps;
+ base::TimeTicks pointer_timestamp;
+ base::TimeTicks touch_timestamp;
+};
void PointerEnter(void* data,
wl_pointer* pointer,
@@ -66,9 +70,9 @@ void PointerMotion(void* data,
uint32_t time,
wl_fixed_t x,
wl_fixed_t y) {
- EventTimeStack* stack = static_cast<EventTimeStack*>(data);
+ EventTimes* event_times = static_cast<EventTimes*>(data);
- stack->push_back(time);
+ event_times->motion_timestamps.push_back(event_times->pointer_timestamp);
}
void PointerButton(void* data,
@@ -119,9 +123,9 @@ void TouchMotion(void* data,
int32_t id,
wl_fixed_t x,
wl_fixed_t y) {
- EventTimeStack* stack = static_cast<EventTimeStack*>(data);
+ EventTimes* event_times = static_cast<EventTimes*>(data);
- stack->push_back(time);
+ event_times->motion_timestamps.push_back(event_times->touch_timestamp);
}
void TouchFrame(void* data, wl_touch* touch) {}
@@ -207,6 +211,20 @@ void FeedbackDiscarded(void* data,
LOG(WARNING) << "Frame discarded";
}
+void InputTimestamp(void* data,
+ struct zwp_input_timestamps_v1* zwp_input_timestamps_v1,
+ uint32_t tv_sec_hi,
+ uint32_t tv_sec_lo,
+ uint32_t tv_nsec) {
+ auto* timestamp = static_cast<base::TimeTicks*>(data);
+ int64_t seconds = (static_cast<int64_t>(tv_sec_hi) << 32) + tv_sec_lo;
+ int64_t microseconds = seconds * base::Time::kMicrosecondsPerSecond +
+ tv_nsec / base::Time::kNanosecondsPerMicrosecond;
+
+ *timestamp =
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(microseconds);
+}
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -237,7 +255,7 @@ int RectsClient::Run(const ClientBase::InitParams& params,
if (!ClientBase::Init(params))
return 1;
- EventTimeStack event_times;
+ EventTimes event_times;
std::unique_ptr<wl_pointer> pointer(
static_cast<wl_pointer*>(wl_seat_get_pointer(globals_.seat.get())));
@@ -262,6 +280,30 @@ int RectsClient::Run(const ClientBase::InitParams& params,
TouchFrame, TouchCancel};
wl_touch_add_listener(touch.get(), &touch_listener, &event_times);
+ zwp_input_timestamps_v1_listener input_timestamps_listener = {InputTimestamp};
+
+ std::unique_ptr<zwp_input_timestamps_v1> pointer_timestamps(
+ zwp_input_timestamps_manager_v1_get_pointer_timestamps(
+ globals_.input_timestamps_manager.get(), pointer.get()));
+ if (!pointer_timestamps) {
+ LOG(ERROR) << "Can't get pointer timestamps";
+ return 1;
+ }
+ zwp_input_timestamps_v1_add_listener(pointer_timestamps.get(),
+ &input_timestamps_listener,
+ &event_times.pointer_timestamp);
+
+ std::unique_ptr<zwp_input_timestamps_v1> touch_timestamps(
+ zwp_input_timestamps_manager_v1_get_touch_timestamps(
+ globals_.input_timestamps_manager.get(), touch.get()));
+ if (!touch_timestamps) {
+ LOG(ERROR) << "Can't get touch timestamps";
+ return 1;
+ }
+ zwp_input_timestamps_v1_add_listener(touch_timestamps.get(),
+ &input_timestamps_listener,
+ &event_times.touch_timestamp);
+
Schedule schedule;
std::unique_ptr<wl_callback> frame_callback;
wl_callback_listener frame_listener = {FrameCallback};
@@ -336,7 +378,7 @@ int RectsClient::Run(const ClientBase::InitParams& params,
}
SkCanvas* canvas = buffer->sk_surface->getCanvas();
- if (event_times.empty()) {
+ if (event_times.motion_timestamps.empty()) {
canvas->clear(transparent_background_ ? SK_ColorTRANSPARENT
: SK_ColorBLACK);
} else {
@@ -344,20 +386,22 @@ int RectsClient::Run(const ClientBase::InitParams& params,
// since last frame. Latest event at the top.
int y = 0;
// Note: Rounding up to ensure we cover the whole canvas.
- int h =
- (size_.height() + (event_times.size() / 2)) / event_times.size();
- while (!event_times.empty()) {
+ int h = (size_.height() + (event_times.motion_timestamps.size() / 2)) /
+ event_times.motion_timestamps.size();
+ while (!event_times.motion_timestamps.empty()) {
SkIRect rect = SkIRect::MakeXYWH(0, y, size_.width(), h);
SkPaint paint;
- paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0,
- (event_times.back() & 0x00ff00) >> 8,
- (event_times.back() & 0xff0000) >> 16));
+ base::TimeDelta event_time =
+ event_times.motion_timestamps.back() - base::TimeTicks();
+ int64_t event_time_msec = event_time.InMilliseconds();
+ paint.setColor(SkColorSetRGB((event_time_msec & 0x0000ff) >> 0,
+ (event_time_msec & 0x00ff00) >> 8,
+ (event_time_msec & 0xff0000) >> 16));
canvas->drawIRect(rect, paint);
- std::string text = base::UintToString(event_times.back());
+ std::string text = base::NumberToString(event_time.InMicroseconds());
canvas->drawText(text.c_str(), text.length(), 8, y + 32, text_paint);
- frame->event_times.push_back(base::TimeTicks::FromInternalValue(
- event_times.back() * base::Time::kMicrosecondsPerMillisecond));
- event_times.pop_back();
+ frame->event_times.push_back(event_times.motion_timestamps.back());
+ event_times.motion_timestamps.pop_back();
y += h;
}
}
diff --git a/chromium/components/exo/wayland/server.cc b/chromium/components/exo/wayland/server.cc
index d9feec46565..543b2e05933 100644
--- a/chromium/components/exo/wayland/server.cc
+++ b/chromium/components/exo/wayland/server.cc
@@ -9,6 +9,7 @@
#include <gaming-input-unstable-v1-server-protocol.h>
#include <gaming-input-unstable-v2-server-protocol.h>
#include <grp.h>
+#include <input-timestamps-unstable-v1-server-protocol.h>
#include <keyboard-configuration-unstable-v1-server-protocol.h>
#include <keyboard-extension-unstable-v1-server-protocol.h>
#include <linux/input.h>
@@ -30,6 +31,7 @@
#include <cstdlib>
#include <iterator>
#include <map>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -195,6 +197,41 @@ uint32_t NowInMilliseconds() {
return TimeTicksToMilliseconds(base::TimeTicks::Now());
}
+class WaylandInputDelegate {
+ public:
+ class Observer {
+ public:
+ virtual void OnDelegateDestroying(WaylandInputDelegate* delegate) = 0;
+ virtual void OnSendTimestamp(base::TimeTicks time_stamp) = 0;
+
+ protected:
+ virtual ~Observer() = default;
+ };
+
+ void AddObserver(Observer* observer) { observers_.AddObserver(observer); }
+
+ void RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+ }
+
+ void SendTimestamp(base::TimeTicks time_stamp) {
+ for (auto& observer : observers_)
+ observer.OnSendTimestamp(time_stamp);
+ }
+
+ protected:
+ WaylandInputDelegate() = default;
+ virtual ~WaylandInputDelegate() {
+ for (auto& observer : observers_)
+ observer.OnDelegateDestroying(this);
+ }
+
+ private:
+ base::ObserverList<Observer> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandInputDelegate);
+};
+
uint32_t WaylandDataDeviceManagerDndAction(DndAction action) {
switch (action) {
case DndAction::kNone:
@@ -244,6 +281,61 @@ base::flat_set<DndAction> DataDeviceManagerDndActions(uint32_t value) {
return actions;
}
+uint32_t ResizeDirection(int component) {
+ switch (component) {
+ case HTCAPTION:
+ return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE;
+ case HTTOP:
+ return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP;
+ case HTTOPRIGHT:
+ return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT;
+ case HTRIGHT:
+ return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT;
+ case HTBOTTOMRIGHT:
+ return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT;
+ case HTBOTTOM:
+ return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM;
+ case HTBOTTOMLEFT:
+ return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT;
+ case HTLEFT:
+ return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT;
+ case HTTOPLEFT:
+ return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT;
+ default:
+ LOG(ERROR) << "Unknown component:" << component;
+ break;
+ }
+ NOTREACHED();
+ return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE;
+}
+
+int Component(uint32_t direction) {
+ switch (direction) {
+ case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE:
+ return HTNOWHERE;
+ case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP:
+ return HTTOP;
+ case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT:
+ return HTTOPRIGHT;
+ case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT:
+ return HTRIGHT;
+ case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT:
+ return HTBOTTOMRIGHT;
+ case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM:
+ return HTBOTTOM;
+ case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT:
+ return HTBOTTOMLEFT;
+ case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT:
+ return HTLEFT;
+ case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT:
+ return HTTOPLEFT;
+ default:
+ VLOG(2) << "Unknown direction:" << direction;
+ break;
+ }
+ return HTNOWHERE;
+}
+
// A property key containing the surface resource that is associated with
// window. If unset, no surface resource is associated with surface object.
DEFINE_UI_CLASS_PROPERTY_KEY(wl_resource*, kSurfaceResourceKey, nullptr);
@@ -1553,6 +1645,7 @@ class WaylandToplevel : public aura::WindowObserver {
AddState(&states, ZXDG_TOPLEVEL_V6_STATE_ACTIVATED);
zxdg_toplevel_v6_send_configure(resource_, size.width(), size.height(),
&states);
+ wl_array_release(&states);
}
wl_resource* const resource_;
@@ -2033,9 +2126,10 @@ void remote_surface_set_window_type(wl_client* client,
}
}
-void remote_surface_resize(wl_client* client, wl_resource* resource) {
- GetUserDataAs<ClientControlledShellSurface>(resource)
- ->StartResize_DEPRECATED();
+void remote_surface_resize(wl_client* client,
+ wl_resource* resource,
+ uint32_t direction) {
+ // DEPRECATED
}
void remote_surface_set_resize_outset(wl_client* client,
@@ -2078,6 +2172,23 @@ void remote_surface_set_max_size(wl_client* client,
gfx::Size(width, height));
}
+void remote_surface_set_snapped_to_left(wl_client* client,
+ wl_resource* resource) {
+ GetUserDataAs<ClientControlledShellSurface>(resource)->SetSnappedToLeft();
+}
+
+void remote_surface_set_snapped_to_right(wl_client* client,
+ wl_resource* resource) {
+ GetUserDataAs<ClientControlledShellSurface>(resource)->SetSnappedToRight();
+}
+
+void remote_surface_start_resize(wl_client* client,
+ wl_resource* resource,
+ uint32_t direction) {
+ GetUserDataAs<ClientControlledShellSurface>(resource)->StartResize(
+ Component(direction));
+}
+
const struct zcr_remote_surface_v1_interface remote_surface_implementation = {
remote_surface_destroy,
remote_surface_set_app_id,
@@ -2111,7 +2222,10 @@ const struct zcr_remote_surface_v1_interface remote_surface_implementation = {
remote_surface_set_can_maximize,
remote_surface_unset_can_maximize,
remote_surface_set_min_size,
- remote_surface_set_max_size};
+ remote_surface_set_max_size,
+ remote_surface_set_snapped_to_left,
+ remote_surface_set_snapped_to_right,
+ remote_surface_start_resize};
////////////////////////////////////////////////////////////////////////////////
// notification_surface_interface:
@@ -2366,6 +2480,12 @@ void HandleRemoteSurfaceStateChangedCallback(
case ash::mojom::WindowStateType::TRUSTED_PINNED:
state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_TRUSTED_PINNED;
break;
+ case ash::mojom::WindowStateType::LEFT_SNAPPED:
+ state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_LEFT_SNAPPED;
+ break;
+ case ash::mojom::WindowStateType::RIGHT_SNAPPED:
+ state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_RIGHT_SNAPPED;
+ break;
default:
break;
}
@@ -2376,7 +2496,8 @@ void HandleRemoteSurfaceStateChangedCallback(
void HandleRemoteSurfaceBoundsChangedCallback(
wl_resource* resource,
- ash::mojom::WindowStateType current_state_type,
+ ash::mojom::WindowStateType current_state,
+ ash::mojom::WindowStateType requested_state,
int64_t display_id,
const gfx::Rect& bounds,
bool resize,
@@ -2388,6 +2509,10 @@ void HandleRemoteSurfaceBoundsChangedCallback(
reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_RESIZE;
} else if (bounds_change & ash::WindowResizer::kBoundsChange_Repositions) {
reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_MOVE;
+ } else if (requested_state == ash::mojom::WindowStateType::LEFT_SNAPPED) {
+ reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT;
+ } else if (requested_state == ash::mojom::WindowStateType::RIGHT_SNAPPED) {
+ reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT;
}
zcr_remote_surface_v1_send_bounds_changed(
resource, static_cast<uint32_t>(display_id >> 32),
@@ -2396,34 +2521,6 @@ void HandleRemoteSurfaceBoundsChangedCallback(
wl_client_flush(wl_resource_get_client(resource));
}
-uint32_t ResizeDirection(int component) {
- switch (component) {
- case HTCAPTION:
- return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE;
- case HTTOP:
- return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP;
- case HTTOPRIGHT:
- return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT;
- case HTRIGHT:
- return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT;
- case HTBOTTOMRIGHT:
- return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT;
- case HTBOTTOM:
- return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM;
- case HTBOTTOMLEFT:
- return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT;
- case HTLEFT:
- return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT;
- case HTTOPLEFT:
- return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT;
- default:
- LOG(ERROR) << "Unknown component:" << component;
- break;
- }
- NOTREACHED();
- return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE;
-}
-
void HandleRemoteSurfaceDragStartedCallback(wl_resource* resource,
int component) {
zcr_remote_surface_v1_send_drag_started(resource, ResizeDirection(component));
@@ -2555,7 +2652,7 @@ const struct zcr_remote_shell_v1_interface remote_shell_implementation = {
remote_shell_destroy, remote_shell_get_remote_surface,
remote_shell_get_notification_surface};
-const uint32_t remote_shell_version = 10;
+const uint32_t remote_shell_version = 12;
void bind_remote_shell(wl_client* client,
void* data,
@@ -3128,7 +3225,8 @@ void bind_data_device_manager(wl_client* client,
// Pointer delegate class that accepts events for surfaces owned by the same
// client as a pointer resource.
-class WaylandPointerDelegate : public PointerDelegate {
+class WaylandPointerDelegate : public WaylandInputDelegate,
+ public PointerDelegate {
public:
explicit WaylandPointerDelegate(wl_resource* pointer_resource)
: pointer_resource_(pointer_resource) {}
@@ -3160,6 +3258,7 @@ class WaylandPointerDelegate : public PointerDelegate {
}
void OnPointerMotion(base::TimeTicks time_stamp,
const gfx::PointF& location) override {
+ SendTimestamp(time_stamp);
wl_pointer_send_motion(
pointer_resource_, TimeTicksToMilliseconds(time_stamp),
wl_fixed_from_double(location.x()), wl_fixed_from_double(location.y()));
@@ -3180,6 +3279,7 @@ class WaylandPointerDelegate : public PointerDelegate {
uint32_t serial = next_serial();
for (auto button : buttons) {
if (button_flags & button.flag) {
+ SendTimestamp(time_stamp);
wl_pointer_send_button(
pointer_resource_, serial, TimeTicksToMilliseconds(time_stamp),
button.value, pressed ? WL_POINTER_BUTTON_STATE_PRESSED
@@ -3201,11 +3301,13 @@ class WaylandPointerDelegate : public PointerDelegate {
}
double x_value = offset.x() * kAxisStepDistance;
+ SendTimestamp(time_stamp);
wl_pointer_send_axis(pointer_resource_, TimeTicksToMilliseconds(time_stamp),
WL_POINTER_AXIS_HORIZONTAL_SCROLL,
wl_fixed_from_double(-x_value));
double y_value = offset.y() * kAxisStepDistance;
+ SendTimestamp(time_stamp);
wl_pointer_send_axis(pointer_resource_, TimeTicksToMilliseconds(time_stamp),
WL_POINTER_AXIS_VERTICAL_SCROLL,
wl_fixed_from_double(-y_value));
@@ -3213,9 +3315,11 @@ class WaylandPointerDelegate : public PointerDelegate {
void OnPointerScrollStop(base::TimeTicks time_stamp) override {
if (wl_resource_get_version(pointer_resource_) >=
WL_POINTER_AXIS_STOP_SINCE_VERSION) {
+ SendTimestamp(time_stamp);
wl_pointer_send_axis_stop(pointer_resource_,
TimeTicksToMilliseconds(time_stamp),
WL_POINTER_AXIS_HORIZONTAL_SCROLL);
+ SendTimestamp(time_stamp);
wl_pointer_send_axis_stop(pointer_resource_,
TimeTicksToMilliseconds(time_stamp),
WL_POINTER_AXIS_VERTICAL_SCROLL);
@@ -3264,7 +3368,6 @@ void pointer_release(wl_client* client, wl_resource* resource) {
const struct wl_pointer_interface pointer_implementation = {pointer_set_cursor,
pointer_release};
-#if BUILDFLAG(USE_XKBCOMMON)
////////////////////////////////////////////////////////////////////////////////
// wl_keyboard_interface:
@@ -3272,13 +3375,15 @@ const struct wl_pointer_interface pointer_implementation = {pointer_set_cursor,
// Keyboard delegate class that accepts events for surfaces owned by the same
// client as a keyboard resource.
class WaylandKeyboardDelegate
- : public KeyboardDelegate,
+ : public WaylandInputDelegate,
+ public KeyboardDelegate,
public KeyboardObserver
#if defined(OS_CHROMEOS)
,
public chromeos::input_method::ImeKeyboard::Observer
#endif
{
+#if BUILDFLAG(USE_XKBCOMMON)
public:
explicit WaylandKeyboardDelegate(wl_resource* keyboard_resource)
: keyboard_resource_(keyboard_resource),
@@ -3340,6 +3445,7 @@ class WaylandKeyboardDelegate
ui::DomCode key,
bool pressed) override {
uint32_t serial = next_serial();
+ SendTimestamp(time_stamp);
wl_keyboard_send_key(keyboard_resource_, serial,
TimeTicksToMilliseconds(time_stamp), DomCodeToKey(key),
pressed ? WL_KEYBOARD_KEY_STATE_PRESSED
@@ -3458,8 +3564,11 @@ class WaylandKeyboardDelegate
std::unique_ptr<xkb_state, ui::XkbStateDeleter> xkb_state_;
DISALLOW_COPY_AND_ASSIGN(WaylandKeyboardDelegate);
+#endif
};
+#if BUILDFLAG(USE_XKBCOMMON)
+
void keyboard_release(wl_client* client, wl_resource* resource) {
wl_resource_destroy(resource);
}
@@ -3473,7 +3582,7 @@ const struct wl_keyboard_interface keyboard_implementation = {keyboard_release};
// Touch delegate class that accepts events for surfaces owned by the same
// client as a touch resource.
-class WaylandTouchDelegate : public TouchDelegate {
+class WaylandTouchDelegate : public WaylandInputDelegate, public TouchDelegate {
public:
explicit WaylandTouchDelegate(wl_resource* touch_resource)
: touch_resource_(touch_resource) {}
@@ -3493,18 +3602,21 @@ class WaylandTouchDelegate : public TouchDelegate {
const gfx::PointF& location) override {
wl_resource* surface_resource = GetSurfaceResource(surface);
DCHECK(surface_resource);
+ SendTimestamp(time_stamp);
wl_touch_send_down(touch_resource_, next_serial(),
TimeTicksToMilliseconds(time_stamp), surface_resource,
id, wl_fixed_from_double(location.x()),
wl_fixed_from_double(location.y()));
}
void OnTouchUp(base::TimeTicks time_stamp, int id) override {
+ SendTimestamp(time_stamp);
wl_touch_send_up(touch_resource_, next_serial(),
TimeTicksToMilliseconds(time_stamp), id);
}
void OnTouchMotion(base::TimeTicks time_stamp,
int id,
const gfx::PointF& location) override {
+ SendTimestamp(time_stamp);
wl_touch_send_motion(touch_resource_, TimeTicksToMilliseconds(time_stamp),
id, wl_fixed_from_double(location.x()),
wl_fixed_from_double(location.y()));
@@ -4350,7 +4462,7 @@ void pointer_gestures_get_pinch_gesture(wl_client* client,
client, &zwp_pointer_gesture_pinch_v1_interface, 1, id);
SetImplementation(pointer_gesture_pinch_resource,
&pointer_gesture_pinch_implementation,
- base::MakeUnique<WaylandPointerGesturePinchDelegate>(
+ std::make_unique<WaylandPointerGesturePinchDelegate>(
pointer_gesture_pinch_resource, pointer));
}
@@ -4635,6 +4747,94 @@ void bind_keyboard_extension(wl_client* client,
data, nullptr);
}
+////////////////////////////////////////////////////////////////////////////////
+// input_timestamps_v1 interface:
+
+class WaylandInputTimestamps : public WaylandInputDelegate::Observer {
+ public:
+ WaylandInputTimestamps(wl_resource* resource, WaylandInputDelegate* delegate)
+ : resource_(resource), delegate_(delegate) {
+ delegate_->AddObserver(this);
+ }
+
+ ~WaylandInputTimestamps() override {
+ if (delegate_)
+ delegate_->RemoveObserver(this);
+ }
+
+ // Overridden from WaylandInputDelegate::Observer:
+ void OnDelegateDestroying(WaylandInputDelegate* delegate) override {
+ DCHECK(delegate_ == delegate);
+ delegate_ = nullptr;
+ }
+ void OnSendTimestamp(base::TimeTicks time_stamp) override {
+ timespec ts = (time_stamp - base::TimeTicks()).ToTimeSpec();
+
+ zwp_input_timestamps_v1_send_timestamp(
+ resource_, static_cast<uint64_t>(ts.tv_sec) >> 32,
+ ts.tv_sec & 0xffffffff, ts.tv_nsec);
+ }
+
+ private:
+ wl_resource* const resource_;
+ WaylandInputDelegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandInputTimestamps);
+};
+
+void input_timestamps_destroy(struct wl_client* client,
+ struct wl_resource* resource) {
+ wl_resource_destroy(resource);
+}
+
+const struct zwp_input_timestamps_v1_interface input_timestamps_implementation =
+ {input_timestamps_destroy};
+
+////////////////////////////////////////////////////////////////////////////////
+// input_timestamps_manager_v1 interface:
+
+void input_timestamps_manager_destroy(struct wl_client* client,
+ struct wl_resource* resource) {
+ wl_resource_destroy(resource);
+}
+
+template <typename T, typename D>
+void input_timestamps_manager_get_timestamps(wl_client* client,
+ wl_resource* resource,
+ uint32_t id,
+ wl_resource* input_resource) {
+ wl_resource* input_timestamps_resource =
+ wl_resource_create(client, &zwp_input_timestamps_v1_interface, 1, id);
+
+ auto input_timestamps = std::make_unique<WaylandInputTimestamps>(
+ input_timestamps_resource,
+ static_cast<WaylandInputDelegate*>(
+ static_cast<D*>(GetUserDataAs<T>(input_resource)->delegate())));
+
+ SetImplementation(input_timestamps_resource, &input_timestamps_implementation,
+ std::move(input_timestamps));
+}
+
+const struct zwp_input_timestamps_manager_v1_interface
+ input_timestamps_manager_implementation = {
+ input_timestamps_manager_destroy,
+ input_timestamps_manager_get_timestamps<Keyboard,
+ WaylandKeyboardDelegate>,
+ input_timestamps_manager_get_timestamps<Pointer,
+ WaylandPointerDelegate>,
+ input_timestamps_manager_get_timestamps<Touch, WaylandTouchDelegate>};
+
+void bind_input_timestamps_manager(wl_client* client,
+ void* data,
+ uint32_t version,
+ uint32_t id) {
+ wl_resource* resource = wl_resource_create(
+ client, &zwp_input_timestamps_manager_v1_interface, 1, id);
+
+ wl_resource_set_implementation(
+ resource, &input_timestamps_manager_implementation, nullptr, nullptr);
+}
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -4689,6 +4889,9 @@ Server::Server(Display* display)
display_, bind_stylus_tools);
wl_global_create(wl_display_.get(), &zcr_keyboard_extension_v1_interface, 1,
display_, bind_keyboard_extension);
+ wl_global_create(wl_display_.get(),
+ &zwp_input_timestamps_manager_v1_interface, 1, display_,
+ bind_input_timestamps_manager);
}
Server::~Server() {}
diff --git a/chromium/components/favicon/core/favicon_driver_impl.cc b/chromium/components/favicon/core/favicon_driver_impl.cc
index e4f05888102..74ba6c7e075 100644
--- a/chromium/components/favicon/core/favicon_driver_impl.cc
+++ b/chromium/components/favicon/core/favicon_driver_impl.cc
@@ -4,8 +4,9 @@
#include "components/favicon/core/favicon_driver_impl.h"
+#include <memory>
+
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
@@ -33,12 +34,12 @@ FaviconDriverImpl::FaviconDriverImpl(FaviconService* favicon_service,
return;
if (kEnableTouchIcon) {
- handlers_.push_back(base::MakeUnique<FaviconHandler>(
+ handlers_.push_back(std::make_unique<FaviconHandler>(
favicon_service_, this, FaviconDriverObserver::NON_TOUCH_LARGEST));
- handlers_.push_back(base::MakeUnique<FaviconHandler>(
+ handlers_.push_back(std::make_unique<FaviconHandler>(
favicon_service_, this, FaviconDriverObserver::TOUCH_LARGEST));
} else {
- handlers_.push_back(base::MakeUnique<FaviconHandler>(
+ handlers_.push_back(std::make_unique<FaviconHandler>(
favicon_service_, this, FaviconDriverObserver::NON_TOUCH_16_DIP));
}
}
diff --git a/chromium/components/favicon/core/favicon_handler.cc b/chromium/components/favicon/core/favicon_handler.cc
index 1e7cd5b5a80..9410afbc14f 100644
--- a/chromium/components/favicon/core/favicon_handler.cc
+++ b/chromium/components/favicon/core/favicon_handler.cc
@@ -454,6 +454,10 @@ void FaviconHandler::OnGotInitialHistoryDataAndIconURLCandidates() {
return;
}
+ if (!current_candidate()) {
+ return;
+ }
+
if (!initial_history_result_expired_or_incomplete_ &&
current_candidate()->icon_url == notification_icon_url_ &&
current_candidate()->icon_type == notification_icon_type_) {
diff --git a/chromium/components/favicon/core/favicon_handler_unittest.cc b/chromium/components/favicon/core/favicon_handler_unittest.cc
index a1c2306fbfd..d88b7ab0ba9 100644
--- a/chromium/components/favicon/core/favicon_handler_unittest.cc
+++ b/chromium/components/favicon/core/favicon_handler_unittest.cc
@@ -11,8 +11,8 @@
#include <utility>
#include <vector>
+#include "base/bind_helpers.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/histogram_tester.h"
@@ -432,7 +432,7 @@ class FakeFaviconService {
// We use PostTaskAndReply() to cause |callback| being run in the current
// TaskRunner.
return tracker->PostTaskAndReply(manual_callback_task_runner_.get(),
- FROM_HERE, base::Bind(&base::DoNothing),
+ FROM_HERE, base::DoNothing(),
bound_callback);
}
@@ -515,7 +515,7 @@ class FaviconHandlerTest : public testing::Test {
FaviconDriverObserver::NotificationIconType handler_type,
const std::vector<FaviconURL>& candidates,
const GURL& manifest_url = GURL()) {
- auto handler = base::MakeUnique<FaviconHandler>(&favicon_service_,
+ auto handler = std::make_unique<FaviconHandler>(&favicon_service_,
&delegate_, handler_type);
handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
// The first RunUntilIdle() causes the FaviconService lookups be faster than
@@ -737,7 +737,7 @@ TEST_F(FaviconHandlerTest, UpdateFaviconMappingsAndFetchWithMultipleURLs) {
base::flat_set<GURL>{kPageURL, kDifferentPageURL},
kIconURL16x16, _, _, _, _));
- std::unique_ptr<FaviconHandler> handler = base::MakeUnique<FaviconHandler>(
+ std::unique_ptr<FaviconHandler> handler = std::make_unique<FaviconHandler>(
&favicon_service_, &delegate_, FaviconDriverObserver::NON_TOUCH_16_DIP);
handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
base::RunLoop().RunUntilIdle();
@@ -765,7 +765,7 @@ TEST_F(FaviconHandlerTest, CloneFaviconMappingsForPageInHistory) {
kPageURL, favicon_base::IconTypeSet({kFavicon}),
base::flat_set<GURL>({kPageURL})));
- std::unique_ptr<FaviconHandler> handler = base::MakeUnique<FaviconHandler>(
+ std::unique_ptr<FaviconHandler> handler = std::make_unique<FaviconHandler>(
&favicon_service_, &delegate_, FaviconDriverObserver::NON_TOUCH_16_DIP);
handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
base::RunLoop().RunUntilIdle();
@@ -782,7 +782,7 @@ TEST_F(FaviconHandlerTest, CloneFaviconMappingsWithMultipleURLs) {
favicon_service_.fake()->Store(kPageURLInHistory, kIconURL16x16,
CreateRawBitmapResult(kIconURL16x16));
- std::unique_ptr<FaviconHandler> handler = base::MakeUnique<FaviconHandler>(
+ std::unique_ptr<FaviconHandler> handler = std::make_unique<FaviconHandler>(
&favicon_service_, &delegate_, FaviconDriverObserver::NON_TOUCH_16_DIP);
handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
base::RunLoop().RunUntilIdle();
@@ -805,7 +805,7 @@ TEST_F(FaviconHandlerTest, NotCloneFaviconMappingsInIncognito) {
EXPECT_CALL(favicon_service_, CloneFaviconMappingsForPages(_, _, _)).Times(0);
- std::unique_ptr<FaviconHandler> handler = base::MakeUnique<FaviconHandler>(
+ std::unique_ptr<FaviconHandler> handler = std::make_unique<FaviconHandler>(
&favicon_service_, &delegate_, FaviconDriverObserver::NON_TOUCH_16_DIP);
handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
base::RunLoop().RunUntilIdle();
@@ -1655,7 +1655,7 @@ TEST_F(FaviconHandlerTest, SetFaviconsForLastPageUrlOnly) {
FaviconDriverObserver::NON_TOUCH_16_DIP,
kIconURL12x12, _, _));
- std::unique_ptr<FaviconHandler> handler = base::MakeUnique<FaviconHandler>(
+ std::unique_ptr<FaviconHandler> handler = std::make_unique<FaviconHandler>(
&favicon_service_, &delegate_, FaviconDriverObserver::NON_TOUCH_16_DIP);
handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
base::RunLoop().RunUntilIdle();
@@ -1683,7 +1683,7 @@ TEST_F(FaviconHandlerTest, SetFaviconsForMultipleUrlsWithinDocument) {
FaviconDriverObserver::NON_TOUCH_16_DIP,
kIconURL12x12, _, _));
- std::unique_ptr<FaviconHandler> handler = base::MakeUnique<FaviconHandler>(
+ std::unique_ptr<FaviconHandler> handler = std::make_unique<FaviconHandler>(
&favicon_service_, &delegate_, FaviconDriverObserver::NON_TOUCH_16_DIP);
handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
base::RunLoop().RunUntilIdle();
diff --git a/chromium/components/favicon/core/favicon_service.h b/chromium/components/favicon/core/favicon_service.h
index 0b66c9daae3..e91ef9d5308 100644
--- a/chromium/components/favicon/core/favicon_service.h
+++ b/chromium/components/favicon/core/favicon_service.h
@@ -199,9 +199,17 @@ class FaviconService : public KeyedService {
const favicon_base::IconTypeSet& icon_types,
const base::flat_set<GURL>& page_urls_to_write) = 0;
+ // 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|.
+ virtual void CanSetOnDemandFavicons(
+ const GURL& page_url,
+ favicon_base::IconType icon_type,
+ base::OnceCallback<void(bool)> callback) const = 0;
+
// Same as SetFavicons with three differences:
- // 1) It will be a no-op if there is an existing cached favicon for *any* type
- // for |page_url|.
+ // 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).
@@ -221,7 +229,7 @@ class FaviconService : public KeyedService {
const GURL& icon_url,
favicon_base::IconType icon_type,
const gfx::Image& image,
- base::Callback<void(bool)> callback) = 0;
+ base::OnceCallback<void(bool)> callback) = 0;
// Avoid repeated requests to download missing favicon.
virtual void UnableToDownloadFavicon(const GURL& icon_url) = 0;
diff --git a/chromium/components/favicon/core/favicon_service_impl.cc b/chromium/components/favicon/core/favicon_service_impl.cc
index f1ef6478ffa..225205bd13c 100644
--- a/chromium/components/favicon/core/favicon_service_impl.cc
+++ b/chromium/components/favicon/core/favicon_service_impl.cc
@@ -250,14 +250,23 @@ void FaviconServiceImpl::CloneFaviconMappingsForPages(
page_urls_to_write);
}
+void FaviconServiceImpl::CanSetOnDemandFavicons(
+ const GURL& page_url,
+ favicon_base::IconType icon_type,
+ base::OnceCallback<void(bool)> callback) const {
+ history_service_->CanSetOnDemandFavicons(page_url, icon_type,
+ std::move(callback));
+}
+
void FaviconServiceImpl::SetOnDemandFavicons(
const GURL& page_url,
const GURL& icon_url,
favicon_base::IconType icon_type,
const gfx::Image& image,
- base::Callback<void(bool)> callback) {
- history_service_->SetOnDemandFavicons(
- page_url, icon_type, icon_url, ExtractSkBitmapsToStore(image), callback);
+ base::OnceCallback<void(bool)> callback) {
+ history_service_->SetOnDemandFavicons(page_url, icon_type, icon_url,
+ ExtractSkBitmapsToStore(image),
+ std::move(callback));
}
void FaviconServiceImpl::UnableToDownloadFavicon(const GURL& icon_url) {
diff --git a/chromium/components/favicon/core/favicon_service_impl.h b/chromium/components/favicon/core/favicon_service_impl.h
index d99d7a0493f..376366503e7 100644
--- a/chromium/components/favicon/core/favicon_service_impl.h
+++ b/chromium/components/favicon/core/favicon_service_impl.h
@@ -111,11 +111,15 @@ class FaviconServiceImpl : public FaviconService {
const GURL& page_url_to_read,
const favicon_base::IconTypeSet& icon_types,
const base::flat_set<GURL>& page_urls_to_write) override;
+ void CanSetOnDemandFavicons(
+ const GURL& page_url,
+ favicon_base::IconType icon_type,
+ base::OnceCallback<void(bool)> callback) const override;
void SetOnDemandFavicons(const GURL& page_url,
const GURL& icon_url,
favicon_base::IconType icon_type,
const gfx::Image& image,
- base::Callback<void(bool)> callback) override;
+ base::OnceCallback<void(bool)> callback) override;
void UnableToDownloadFavicon(const GURL& icon_url) override;
bool WasUnableToDownloadFavicon(const GURL& icon_url) const override;
void ClearUnableToDownloadFavicons() override;
diff --git a/chromium/components/favicon/core/large_icon_service.cc b/chromium/components/favicon/core/large_icon_service.cc
index 8d8c73a09c8..7e72267399b 100644
--- a/chromium/components/favicon/core/large_icon_service.cc
+++ b/chromium/components/favicon/core/large_icon_service.cc
@@ -14,7 +14,6 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h"
#include "base/metrics/field_trial_params.h"
@@ -23,7 +22,6 @@
#include "base/strings/stringprintf.h"
#include "base/task_runner.h"
#include "base/task_scheduler/post_task.h"
-#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
#include "components/favicon/core/favicon_service.h"
@@ -334,7 +332,7 @@ LargeIconWorker::LargeIconWorker(
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
tracker_(tracker),
fallback_icon_style_(
- base::MakeUnique<favicon_base::FallbackIconStyle>()) {}
+ std::make_unique<favicon_base::FallbackIconStyle>()) {}
LargeIconWorker::~LargeIconWorker() {
}
diff --git a/chromium/components/favicon/core/large_icon_service_unittest.cc b/chromium/components/favicon/core/large_icon_service_unittest.cc
index ced6caa7e4a..b5f3ba73623 100644
--- a/chromium/components/favicon/core/large_icon_service_unittest.cc
+++ b/chromium/components/favicon/core/large_icon_service_unittest.cc
@@ -64,8 +64,8 @@ ACTION_P2(PostFetchReplyWithMetadata, p0, p1) {
}
ACTION_P(PostBoolReply, p0) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::Bind(arg4, p0));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(*arg4), p0));
}
SkBitmap CreateTestSkBitmap(int w, int h, SkColor color) {
@@ -429,7 +429,7 @@ class LargeIconServiceGetterTest : public LargeIconServiceTest,
void RawBitmapResultCallback(const favicon_base::LargeIconResult& result) {
if (result.bitmap.is_valid()) {
returned_bitmap_size_ =
- base::MakeUnique<gfx::Size>(result.bitmap.pixel_size);
+ std::make_unique<gfx::Size>(result.bitmap.pixel_size);
}
StoreFallbackStyle(result.fallback_icon_style.get());
}
@@ -437,7 +437,7 @@ class LargeIconServiceGetterTest : public LargeIconServiceTest,
void ImageResultCallback(const favicon_base::LargeIconImageResult& result) {
if (!result.image.IsEmpty()) {
returned_bitmap_size_ =
- base::MakeUnique<gfx::Size>(result.image.ToImageSkia()->size());
+ std::make_unique<gfx::Size>(result.image.ToImageSkia()->size());
ASSERT_TRUE(result.icon_url.is_valid());
}
StoreFallbackStyle(result.fallback_icon_style.get());
@@ -447,7 +447,7 @@ class LargeIconServiceGetterTest : public LargeIconServiceTest,
const favicon_base::FallbackIconStyle* fallback_style) {
if (fallback_style) {
returned_fallback_style_ =
- base::MakeUnique<favicon_base::FallbackIconStyle>(*fallback_style);
+ std::make_unique<favicon_base::FallbackIconStyle>(*fallback_style);
}
}
diff --git a/chromium/components/favicon/ios/web_favicon_driver.mm b/chromium/components/favicon/ios/web_favicon_driver.mm
index 64537f567f3..dc155d3eef6 100644
--- a/chromium/components/favicon/ios/web_favicon_driver.mm
+++ b/chromium/components/favicon/ios/web_favicon_driver.mm
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
-#include "base/threading/sequenced_worker_pool.h"
#include "components/favicon/core/favicon_url.h"
#include "components/favicon/ios/favicon_url_util.h"
#include "ios/web/public/browser_state.h"
diff --git a/chromium/components/favicon_base/select_favicon_frames.cc b/chromium/components/favicon_base/select_favicon_frames.cc
index a182311b215..7317ab078c5 100644
--- a/chromium/components/favicon_base/select_favicon_frames.cc
+++ b/chromium/components/favicon_base/select_favicon_frames.cc
@@ -8,11 +8,11 @@
#include <cmath>
#include <limits>
#include <map>
+#include <memory>
#include <set>
#include <utility>
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "components/favicon_base/favicon_util.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkCanvas.h"
@@ -245,7 +245,7 @@ gfx::ImageSkia CreateFaviconImageSkia(
return gfx::ImageSkia(gfx::ImageSkiaRep(bitmaps[index], 1.0f));
}
- auto image_source = base::MakeUnique<FaviconImageSource>();
+ auto image_source = std::make_unique<FaviconImageSource>();
for (size_t i = 0; i < results.size(); ++i) {
size_t index = results[i].index;
diff --git a/chromium/components/feature_engagement/BUILD.gn b/chromium/components/feature_engagement/BUILD.gn
index 1c520848170..e415d23ea63 100644
--- a/chromium/components/feature_engagement/BUILD.gn
+++ b/chromium/components/feature_engagement/BUILD.gn
@@ -10,14 +10,14 @@ if (is_android) {
import("//build/config/android/rules.gni")
}
-buildflag_header("features") {
- header = "features.h"
+buildflag_header("buildflags") {
+ header = "buildflags.h"
flags = [ "ENABLE_DESKTOP_IN_PRODUCT_HELP=$enable_desktop_in_product_help" ]
}
group("feature_engagement") {
public_deps = [
- ":features",
+ ":buildflags",
"//components/feature_engagement/public",
]
diff --git a/chromium/components/feature_engagement/internal/in_memory_event_store.cc b/chromium/components/feature_engagement/internal/in_memory_event_store.cc
index 140d6ea571b..348727a939f 100644
--- a/chromium/components/feature_engagement/internal/in_memory_event_store.cc
+++ b/chromium/components/feature_engagement/internal/in_memory_event_store.cc
@@ -5,6 +5,7 @@
#include "components/feature_engagement/internal/in_memory_event_store.h"
#include <memory>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -44,7 +45,7 @@ void InMemoryEventStore::DeleteEvent(const std::string& event_name) {
void InMemoryEventStore::HandleLoadResult(const OnLoadedCallback& callback,
bool success) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, success, base::Passed(&events_)));
+ FROM_HERE, base::BindOnce(callback, success, std::move(events_)));
ready_ = success;
}
diff --git a/chromium/components/feature_engagement/internal/tracker_impl_unittest.cc b/chromium/components/feature_engagement/internal/tracker_impl_unittest.cc
index 2de896253fc..bbcf9235695 100644
--- a/chromium/components/feature_engagement/internal/tracker_impl_unittest.cc
+++ b/chromium/components/feature_engagement/internal/tracker_impl_unittest.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/feature_list.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
@@ -175,8 +176,6 @@ class TestDisplayLockController : public DisplayLockController {
next_display_lock_handle_ = std::move(display_lock_handle);
}
- void NoopCallback() {}
-
private:
// The next DisplayLockHandle to return.
std::unique_ptr<DisplayLockHandle> next_display_lock_handle_;
@@ -858,9 +857,7 @@ TEST_F(TrackerImplTest, TestNotifyEvent) {
}
TEST_F(TrackerImplTest, ShouldPassThroughAcquireDisplayLock) {
- auto lock_handle = std::make_unique<DisplayLockHandle>(
- base::Bind(&TestDisplayLockController::NoopCallback,
- base::Unretained(display_lock_controller_)));
+ auto lock_handle = std::make_unique<DisplayLockHandle>(base::DoNothing());
DisplayLockHandle* lock_handle_ptr = lock_handle.get();
display_lock_controller_->SetNextDisplayLockHandle(std::move(lock_handle));
EXPECT_EQ(lock_handle_ptr, tracker_->AcquireDisplayLock().get());
diff --git a/chromium/components/feature_engagement/public/BUILD.gn b/chromium/components/feature_engagement/public/BUILD.gn
index 88ee1bd7523..ede4df0a652 100644
--- a/chromium/components/feature_engagement/public/BUILD.gn
+++ b/chromium/components/feature_engagement/public/BUILD.gn
@@ -21,7 +21,7 @@ source_set("public") {
deps = [
"//base",
- "//components/feature_engagement:features",
+ "//components/feature_engagement:buildflags",
"//components/flags_ui",
"//components/keyed_service/core",
]
diff --git a/chromium/components/feature_engagement/public/event_constants.cc b/chromium/components/feature_engagement/public/event_constants.cc
index 5d93f962d5b..b0e351a465f 100644
--- a/chromium/components/feature_engagement/public/event_constants.cc
+++ b/chromium/components/feature_engagement/public/event_constants.cc
@@ -5,7 +5,7 @@
#include "components/feature_engagement/public/event_constants.h"
#include "build/build_config.h"
-#include "components/feature_engagement/features.h"
+#include "components/feature_engagement/buildflags.h"
namespace feature_engagement {
diff --git a/chromium/components/feature_engagement/public/event_constants.h b/chromium/components/feature_engagement/public/event_constants.h
index 1d087288c31..1b95ad1b7ab 100644
--- a/chromium/components/feature_engagement/public/event_constants.h
+++ b/chromium/components/feature_engagement/public/event_constants.h
@@ -6,7 +6,7 @@
#define COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_EVENT_CONSTANTS_H_
#include "build/build_config.h"
-#include "components/feature_engagement/features.h"
+#include "components/feature_engagement/buildflags.h"
namespace feature_engagement {
diff --git a/chromium/components/feature_engagement/public/feature_constants.cc b/chromium/components/feature_engagement/public/feature_constants.cc
index 4ad114103d0..3c44da07016 100644
--- a/chromium/components/feature_engagement/public/feature_constants.cc
+++ b/chromium/components/feature_engagement/public/feature_constants.cc
@@ -4,7 +4,7 @@
#include "components/feature_engagement/public/feature_constants.h"
-#include "components/feature_engagement/features.h"
+#include "components/feature_engagement/buildflags.h"
namespace feature_engagement {
diff --git a/chromium/components/feature_engagement/public/feature_constants.h b/chromium/components/feature_engagement/public/feature_constants.h
index fb513ffa82d..bf2857d4042 100644
--- a/chromium/components/feature_engagement/public/feature_constants.h
+++ b/chromium/components/feature_engagement/public/feature_constants.h
@@ -7,7 +7,7 @@
#include "base/feature_list.h"
#include "build/build_config.h"
-#include "components/feature_engagement/features.h"
+#include "components/feature_engagement/buildflags.h"
namespace feature_engagement {
diff --git a/chromium/components/feature_engagement/public/feature_list.cc b/chromium/components/feature_engagement/public/feature_list.cc
index 91666e5d0f1..9b7a306176a 100644
--- a/chromium/components/feature_engagement/public/feature_list.cc
+++ b/chromium/components/feature_engagement/public/feature_list.cc
@@ -4,7 +4,7 @@
#include "components/feature_engagement/public/feature_list.h"
-#include "components/feature_engagement/features.h"
+#include "components/feature_engagement/buildflags.h"
#include "components/feature_engagement/public/feature_constants.h"
namespace feature_engagement {
diff --git a/chromium/components/feature_engagement/public/feature_list.h b/chromium/components/feature_engagement/public/feature_list.h
index 4e5ad21e20f..2b189656a00 100644
--- a/chromium/components/feature_engagement/public/feature_list.h
+++ b/chromium/components/feature_engagement/public/feature_list.h
@@ -9,7 +9,7 @@
#include "base/feature_list.h"
#include "build/build_config.h"
-#include "components/feature_engagement/features.h"
+#include "components/feature_engagement/buildflags.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/flags_ui/feature_entry.h"
diff --git a/chromium/components/feedback/anonymizer_tool.cc b/chromium/components/feedback/anonymizer_tool.cc
index f132d3484f8..73f2f97d291 100644
--- a/chromium/components/feedback/anonymizer_tool.cc
+++ b/chromium/components/feedback/anonymizer_tool.cc
@@ -4,9 +4,9 @@
#include "components/feedback/anonymizer_tool.h"
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -260,7 +260,7 @@ RE2* AnonymizerTool::GetRegExp(const std::string& pattern) {
RE2::Options options;
// set_multiline of pcre is not supported by RE2, yet.
options.set_dot_nl(true); // Dot matches a new line.
- std::unique_ptr<RE2> re = base::MakeUnique<RE2>(pattern, options);
+ std::unique_ptr<RE2> re = std::make_unique<RE2>(pattern, options);
DCHECK_EQ(re2::RE2::NoError, re->error_code())
<< "Failed to parse:\n" << pattern << "\n" << re->error();
regexp_cache_[pattern] = std::move(re);
diff --git a/chromium/components/feedback/feedback_data.cc b/chromium/components/feedback/feedback_data.cc
index 5beccf77eca..c58dce1f077 100644
--- a/chromium/components/feedback/feedback_data.cc
+++ b/chromium/components/feedback/feedback_data.cc
@@ -86,10 +86,10 @@ void FeedbackData::SetAndCompressHistograms(
++pending_op_count_;
base::PostTaskWithTraitsAndReply(
FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
- base::Bind(&FeedbackData::CompressFile, this,
- base::FilePath(kHistogramsFilename), kHistogramsAttachmentName,
- base::Passed(&histograms)),
- base::Bind(&FeedbackData::OnCompressComplete, this));
+ base::BindOnce(&FeedbackData::CompressFile, this,
+ base::FilePath(kHistogramsFilename),
+ kHistogramsAttachmentName, std::move(histograms)),
+ base::BindOnce(&FeedbackData::OnCompressComplete, this));
}
void FeedbackData::AttachAndCompressFileData(
@@ -103,9 +103,9 @@ void FeedbackData::AttachAndCompressFileData(
base::FilePath::FromUTF8Unsafe(attached_filename_);
base::PostTaskWithTraitsAndReply(
FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
- base::Bind(&FeedbackData::CompressFile, this, attached_file,
- std::string(), base::Passed(&attached_filedata)),
- base::Bind(&FeedbackData::OnCompressComplete, this));
+ base::BindOnce(&FeedbackData::CompressFile, this, attached_file,
+ std::string(), std::move(attached_filedata)),
+ base::BindOnce(&FeedbackData::OnCompressComplete, this));
}
void FeedbackData::OnGetTraceData(
diff --git a/chromium/components/feedback/feedback_data_unittest.cc b/chromium/components/feedback/feedback_data_unittest.cc
index 6b15c186c57..06fb1ffef33 100644
--- a/chromium/components/feedback/feedback_data_unittest.cc
+++ b/chromium/components/feedback/feedback_data_unittest.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "components/feedback/feedback_report.h"
@@ -44,7 +43,7 @@ class MockUploader : public FeedbackUploader {
};
std::unique_ptr<std::string> MakeScoped(const char* str) {
- return base::MakeUnique<std::string>(str);
+ return std::make_unique<std::string>(str);
}
} // namespace
diff --git a/chromium/components/feedback/feedback_report.cc b/chromium/components/feedback/feedback_report.cc
index 984ba9c10c1..5acb44b2a1c 100644
--- a/chromium/components/feedback/feedback_report.cc
+++ b/chromium/components/feedback/feedback_report.cc
@@ -11,7 +11,6 @@
#include "base/guid.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
-#include "base/threading/sequenced_worker_pool.h"
namespace {
diff --git a/chromium/components/feedback/feedback_uploader_unittest.cc b/chromium/components/feedback/feedback_uploader_unittest.cc
index 90c6a0a5b02..7abe3aea312 100644
--- a/chromium/components/feedback/feedback_uploader_unittest.cc
+++ b/chromium/components/feedback/feedback_uploader_unittest.cc
@@ -8,7 +8,6 @@
#include <set>
#include "base/bind.h"
-#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
@@ -43,7 +42,7 @@ class MockFeedbackUploader : public FeedbackUploader {
void RunMessageLoop() {
if (ProcessingComplete())
return;
- run_loop_ = base::MakeUnique<base::RunLoop>();
+ run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();
}
@@ -94,7 +93,7 @@ class FeedbackUploaderTest : public testing::Test {
public:
FeedbackUploaderTest() {
FeedbackUploader::SetMinimumRetryDelayForTesting(kRetryDelayForTest);
- uploader_ = base::MakeUnique<MockFeedbackUploader>(&context_);
+ uploader_ = std::make_unique<MockFeedbackUploader>(&context_);
}
~FeedbackUploaderTest() override = default;
diff --git a/chromium/components/feedback/system_logs/system_logs_fetcher.cc b/chromium/components/feedback/system_logs/system_logs_fetcher.cc
index 936ba19519b..dbeb4756669 100644
--- a/chromium/components/feedback/system_logs/system_logs_fetcher.cc
+++ b/chromium/components/feedback/system_logs/system_logs_fetcher.cc
@@ -4,11 +4,11 @@
#include "components/feedback/system_logs/system_logs_fetcher.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/memory/ptr_util.h"
#include "base/task_scheduler/post_task.h"
#include "base/task_scheduler/task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -48,7 +48,7 @@ void Anonymize(feedback::AnonymizerTool* anonymizer,
} // namespace
SystemLogsFetcher::SystemLogsFetcher(bool scrub_data)
- : response_(base::MakeUnique<SystemLogsResponse>()),
+ : response_(std::make_unique<SystemLogsResponse>()),
num_pending_requests_(0),
task_runner_for_anonymizer_(base::CreateSequencedTaskRunnerWithTraits(
{// User visible because this is called when the user is looking at
@@ -57,7 +57,7 @@ SystemLogsFetcher::SystemLogsFetcher(bool scrub_data)
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})),
weak_ptr_factory_(this) {
if (scrub_data)
- anonymizer_ = base::MakeUnique<feedback::AnonymizerTool>();
+ anonymizer_ = std::make_unique<feedback::AnonymizerTool>();
}
SystemLogsFetcher::~SystemLogsFetcher() {
diff --git a/chromium/components/feedback/system_logs/system_logs_fetcher.h b/chromium/components/feedback/system_logs/system_logs_fetcher.h
index d8103b6c0a8..0d821a5ccdb 100644
--- a/chromium/components/feedback/system_logs/system_logs_fetcher.h
+++ b/chromium/components/feedback/system_logs/system_logs_fetcher.h
@@ -36,8 +36,8 @@ using SysLogsFetcherCallback =
// }
// void GetLogs() {
// SystemLogsFetcher* fetcher = new SystemLogsFetcher(/*scrub_data=*/ true);
-// fetcher->AddSource(base::MakeUnique<LogSourceOne>());
-// fetcher->AddSource(base::MakeUnique<LogSourceTwo>());
+// fetcher->AddSource(std::make_unique<LogSourceOne>());
+// fetcher->AddSource(std::make_unique<LogSourceTwo>());
// fetcher->Fetch(base::Bind(&Example::ProcessLogs, this));
// }
// };
diff --git a/chromium/components/filename_generation/BUILD.gn b/chromium/components/filename_generation/BUILD.gn
new file mode 100644
index 00000000000..aa9c88d7636
--- /dev/null
+++ b/chromium/components/filename_generation/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if (is_android) {
+ import("//build/config/android/rules.gni")
+}
+
+static_library("filename_generation") {
+ sources = [
+ "filename_generation.cc",
+ "filename_generation.h",
+ ]
+
+ deps = [
+ "//base",
+ "//base:i18n",
+ "//components/url_formatter:url_formatter",
+ "//net",
+ "//url",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "filename_generation_unittest.cc",
+ ]
+
+ deps = [
+ ":filename_generation",
+ "//base",
+ "//net",
+ "//testing/gtest",
+ "//url",
+ ]
+}
diff --git a/chromium/components/filename_generation/DEPS b/chromium/components/filename_generation/DEPS
new file mode 100644
index 00000000000..9e70d23f7bc
--- /dev/null
+++ b/chromium/components/filename_generation/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+components/url_formatter",
+ "+net/base",
+]
diff --git a/chromium/components/filename_generation/OWNERS b/chromium/components/filename_generation/OWNERS
new file mode 100644
index 00000000000..cdd1fbd98a4
--- /dev/null
+++ b/chromium/components/filename_generation/OWNERS
@@ -0,0 +1,6 @@
+dtrainor@chromium.org
+petewil@chromium.org
+qinmin@chromium.org
+romax@chromium.org
+
+# COMPONENT: UI>Browser>Downloads
diff --git a/chromium/components/filename_generation/filename_generation.cc b/chromium/components/filename_generation/filename_generation.cc
new file mode 100644
index 00000000000..f595c3738cc
--- /dev/null
+++ b/chromium/components/filename_generation/filename_generation.cc
@@ -0,0 +1,187 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/filename_generation/filename_generation.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/i18n/file_util_icu.h"
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/third_party/icu/icu_utf.h"
+#include "base/threading/thread_restrictions.h"
+#include "build/build_config.h"
+#include "components/url_formatter/url_formatter.h"
+#include "net/base/filename_util.h"
+#include "net/base/mime_util.h"
+#include "url/gurl.h"
+
+namespace filename_generation {
+
+namespace {
+
+// The lower bound for file name truncation. If the truncation results in a name
+// shorter than this limit, we give up automatic truncation and prompt the user.
+const size_t kTruncatedNameLengthLowerbound = 5;
+
+const base::FilePath::CharType kDefaultHtmlExtension[] =
+ FILE_PATH_LITERAL("html");
+
+// Check whether we can save page as complete-HTML for the contents which
+// have specified a MIME type. Now only contents which have the MIME type
+// "text/html" can be saved as complete-HTML.
+bool CanSaveAsComplete(const std::string& contents_mime_type) {
+ return contents_mime_type == "text/html" ||
+ contents_mime_type == "application/xhtml+xml";
+}
+
+} // namespace
+
+const base::FilePath::CharType* ExtensionForMimeType(
+ const std::string& contents_mime_type) {
+ static const struct {
+ const char* mime_type;
+ const base::FilePath::CharType* suggested_extension;
+ } kExtensions[] = {
+ {"text/html", kDefaultHtmlExtension},
+ {"text/xml", FILE_PATH_LITERAL("xml")},
+ {"application/xhtml+xml", FILE_PATH_LITERAL("xhtml")},
+ {"text/plain", FILE_PATH_LITERAL("txt")},
+ {"text/css", FILE_PATH_LITERAL("css")},
+ {"multipart/related", FILE_PATH_LITERAL("mhtml")},
+ };
+ for (const auto& extension : kExtensions) {
+ if (contents_mime_type == extension.mime_type)
+ return extension.suggested_extension;
+ }
+ return FILE_PATH_LITERAL("");
+}
+
+base::FilePath EnsureHtmlExtension(const base::FilePath& name) {
+ base::AssertBlockingAllowed();
+
+ base::FilePath::StringType ext = name.Extension();
+ if (!ext.empty())
+ ext.erase(ext.begin()); // Erase preceding '.'.
+ std::string mime_type;
+ if (!net::GetMimeTypeFromExtension(ext, &mime_type) ||
+ !CanSaveAsComplete(mime_type)) {
+ return base::FilePath(name.value() + FILE_PATH_LITERAL(".") +
+ kDefaultHtmlExtension);
+ }
+ return name;
+}
+
+base::FilePath EnsureMimeExtension(const base::FilePath& name,
+ const std::string& contents_mime_type) {
+ base::AssertBlockingAllowed();
+
+ // Start extension at 1 to skip over period if non-empty.
+ base::FilePath::StringType ext = name.Extension();
+ if (!ext.empty())
+ ext = ext.substr(1);
+ base::FilePath::StringType suggested_extension =
+ ExtensionForMimeType(contents_mime_type);
+ std::string mime_type;
+ if (!suggested_extension.empty() &&
+ !net::GetMimeTypeFromExtension(ext, &mime_type)) {
+ // Extension is absent or needs to be updated.
+ return base::FilePath(name.value() + FILE_PATH_LITERAL(".") +
+ suggested_extension);
+ }
+
+ // Special treatment for MHTML: we would always want to add ".mhtml" as the
+ // extension even if there's another recognized mime_type based on |ext|.
+ // For example: the name is "page.html", we would like to have
+ // "page.html.mhtml" instead of "page.html".
+ if (contents_mime_type == "multipart/related" &&
+ mime_type != "multipart/related") {
+ return base::FilePath(name.value() + FILE_PATH_LITERAL(".mhtml"));
+ }
+
+ return name;
+}
+
+base::FilePath GenerateFilename(const base::string16& title,
+ const GURL& url,
+ bool can_save_as_complete,
+ std::string contents_mime_type) {
+ base::FilePath name_with_proper_ext = base::FilePath::FromUTF16Unsafe(title);
+
+ // If the page's title matches its URL, use the URL. Try to use the last path
+ // component or if there is none, the domain as the file name.
+ // Normally we want to base the filename on the page title, or if it doesn't
+ // exist, on the URL. It's not easy to tell if the page has no title, because
+ // if the page has no title, WebContents::GetTitle() will return the page's
+ // URL (adjusted for display purposes). Therefore, we convert the "title"
+ // back to a URL, and if it matches the original page URL, we know the page
+ // had no title (or had a title equal to its URL, which is fine to treat
+ // similarly).
+ if (title == url_formatter::FormatUrl(url)) {
+ std::string url_path;
+ if (!url.SchemeIs(url::kDataScheme)) {
+ name_with_proper_ext = net::GenerateFileName(
+ url, std::string(), std::string(), std::string(), contents_mime_type,
+ std::string());
+
+ // If host is used as file name, try to decode punycode.
+ if (name_with_proper_ext.AsUTF8Unsafe() == url.host()) {
+ name_with_proper_ext = base::FilePath::FromUTF16Unsafe(
+ url_formatter::IDNToUnicode(url.host()));
+ }
+ } else {
+ name_with_proper_ext = base::FilePath::FromUTF8Unsafe("dataurl");
+ }
+ }
+
+ // Ask user for getting final saving name.
+ name_with_proper_ext =
+ EnsureMimeExtension(name_with_proper_ext, contents_mime_type);
+ // Adjust extension for complete types.
+ if (can_save_as_complete)
+ name_with_proper_ext = EnsureHtmlExtension(name_with_proper_ext);
+
+ base::FilePath::StringType file_name = name_with_proper_ext.value();
+ base::i18n::ReplaceIllegalCharactersInPath(&file_name, '_');
+ return base::FilePath(file_name);
+}
+
+bool TruncateFilename(base::FilePath* path, size_t limit) {
+ base::FilePath basename(path->BaseName());
+ // It is already short enough.
+ if (basename.value().size() <= limit)
+ return true;
+
+ base::FilePath dir(path->DirName());
+ base::FilePath::StringType ext(basename.Extension());
+ base::FilePath::StringType name(basename.RemoveExtension().value());
+
+ // Impossible to satisfy the limit.
+ if (limit < kTruncatedNameLengthLowerbound + ext.size())
+ return false;
+ limit -= ext.size();
+
+ // Encoding specific truncation logic.
+ base::FilePath::StringType truncated;
+#if defined(OS_CHROMEOS) || defined(OS_MACOSX)
+ // UTF-8.
+ base::TruncateUTF8ToByteSize(name, limit, &truncated);
+#elif defined(OS_WIN)
+ // UTF-16.
+ DCHECK(name.size() > limit);
+ truncated = name.substr(0, CBU16_IS_TRAIL(name[limit]) ? limit - 1 : limit);
+#else
+// We cannot generally assume that the file name encoding is in UTF-8 (see
+// the comment for FilePath::AsUTF8Unsafe), hence no safe way to truncate.
+#endif
+
+ if (truncated.size() < kTruncatedNameLengthLowerbound)
+ return false;
+ *path = dir.Append(truncated + ext);
+ return true;
+}
+
+} // namespace filename_generation
diff --git a/chromium/components/filename_generation/filename_generation.h b/chromium/components/filename_generation/filename_generation.h
new file mode 100644
index 00000000000..49cb2ffe6be
--- /dev/null
+++ b/chromium/components/filename_generation/filename_generation.h
@@ -0,0 +1,48 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_FILENAME_GENERATION_FILENAME_GENERATION_H_
+#define COMPONENTS_FILENAME_GENERATION_FILENAME_GENERATION_H_
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/strings/string16.h"
+
+class GURL;
+
+namespace filename_generation {
+
+// Returns extension for supported MIME types (for example, for "text/plain"
+// it returns "txt").
+const base::FilePath::CharType* ExtensionForMimeType(
+ const std::string& contents_mime_type);
+
+// Ensures that the file name has a proper extension for HTML by adding ".htm"
+// if necessary.
+base::FilePath EnsureHtmlExtension(const base::FilePath& name);
+
+// Ensures that the file name has a proper extension for supported formats
+// if necessary.
+base::FilePath EnsureMimeExtension(const base::FilePath& name,
+ const std::string& contents_mime_type);
+
+// Function for generating a filename based on |title|, if it is empty, |url|
+// will be used as a fallback.
+base::FilePath GenerateFilename(const base::string16& title,
+ const GURL& url,
+ bool can_save_as_complete,
+ std::string contents_mime_type);
+
+// Truncates path->BaseName() to make path->BaseName().value().size() <= limit.
+// - It keeps the extension as is. Only truncates the body part.
+// - Only truncates if the base filename can maintain a minimum length
+// (currently a hardcoded internval constant kTruncatedNameLengthLowerbound,
+// but could be parameterized if ever required).
+// If it was unable to shorten the name, returns false.
+bool TruncateFilename(base::FilePath* path, size_t limit);
+
+} // namespace filename_generation
+
+#endif // COMPONENTS_FILENAME_GENERATION_FILENAME_GENERATION_H_
diff --git a/chromium/components/filename_generation/filename_generation_unittest.cc b/chromium/components/filename_generation/filename_generation_unittest.cc
new file mode 100644
index 00000000000..e4db3d12912
--- /dev/null
+++ b/chromium/components/filename_generation/filename_generation_unittest.cc
@@ -0,0 +1,229 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/filename_generation/filename_generation.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace filename_generation {
+
+#define FPL FILE_PATH_LITERAL
+#define HTML_EXTENSION ".html"
+#if defined(OS_WIN)
+#define FPL_HTML_EXTENSION L".html"
+#else
+#define FPL_HTML_EXTENSION ".html"
+#endif
+
+namespace {
+
+base::FilePath GetLongNamePathInDirectory(
+ int max_length,
+ const base::FilePath::CharType* suffix,
+ const base::FilePath& dir) {
+ base::FilePath::StringType name(max_length, FILE_PATH_LITERAL('a'));
+ base::FilePath path = dir.Append(name + suffix).NormalizePathSeparators();
+ return path;
+}
+
+} // namespace
+
+static const struct {
+ const base::FilePath::CharType* page_title;
+ const base::FilePath::CharType* expected_name;
+} kExtensionTestCases[] = {
+ // Extension is preserved if it is already proper for HTML.
+ {FPL("filename.html"), FPL("filename.html")},
+ {FPL("filename.HTML"), FPL("filename.HTML")},
+ {FPL("filename.XHTML"), FPL("filename.XHTML")},
+ {FPL("filename.xhtml"), FPL("filename.xhtml")},
+ {FPL("filename.htm"), FPL("filename.htm")},
+ // ".htm" is added if the extension is improper for HTML.
+ {FPL("hello.world"), FPL("hello.world") FPL_HTML_EXTENSION},
+ {FPL("hello.txt"), FPL("hello.txt") FPL_HTML_EXTENSION},
+ {FPL("is.html.good"), FPL("is.html.good") FPL_HTML_EXTENSION},
+ // ".htm" is added if the name doesn't have an extension.
+ {FPL("helloworld"), FPL("helloworld") FPL_HTML_EXTENSION},
+ {FPL("helloworld."), FPL("helloworld.") FPL_HTML_EXTENSION},
+};
+
+// Crashing on Windows, see http://crbug.com/79365
+#if defined(OS_WIN)
+#define MAYBE_TestEnsureHtmlExtension DISABLED_TestEnsureHtmlExtension
+#else
+#define MAYBE_TestEnsureHtmlExtension TestEnsureHtmlExtension
+#endif
+TEST(FilenameGenerationTest, MAYBE_TestEnsureHtmlExtension) {
+ for (size_t i = 0; i < arraysize(kExtensionTestCases); ++i) {
+ base::FilePath original = base::FilePath(kExtensionTestCases[i].page_title);
+ base::FilePath expected =
+ base::FilePath(kExtensionTestCases[i].expected_name);
+ base::FilePath actual = EnsureHtmlExtension(original);
+ EXPECT_EQ(expected.value(), actual.value())
+ << "Failed for page title: " << kExtensionTestCases[i].page_title;
+ }
+}
+
+// Crashing on Windows, see http://crbug.com/79365
+#if defined(OS_WIN)
+#define MAYBE_TestEnsureMimeExtension DISABLED_TestEnsureMimeExtension
+#else
+#define MAYBE_TestEnsureMimeExtension TestEnsureMimeExtension
+#endif
+TEST(FilenameGenerationTest, MAYBE_TestEnsureMimeExtension) {
+ static const struct {
+ const base::FilePath::CharType* page_title;
+ const base::FilePath::CharType* expected_name;
+ const char* contents_mime_type;
+ } kExtensionTests[] = {
+ {FPL("filename.html"), FPL("filename.html"), "text/html"},
+ {FPL("filename.htm"), FPL("filename.htm"), "text/html"},
+ {FPL("filename.xhtml"), FPL("filename.xhtml"), "text/html"},
+#if defined(OS_WIN)
+ {FPL("filename"), FPL("filename.htm"), "text/html"},
+#else // defined(OS_WIN)
+ {FPL("filename"), FPL("filename.html"), "text/html"},
+#endif // defined(OS_WIN)
+ {FPL("filename.html"), FPL("filename.html"), "text/xml"},
+ {FPL("filename.xml"), FPL("filename.xml"), "text/xml"},
+ {FPL("filename"), FPL("filename.xml"), "text/xml"},
+ {FPL("filename.xhtml"), FPL("filename.xhtml"), "application/xhtml+xml"},
+ {FPL("filename.html"), FPL("filename.html"), "application/xhtml+xml"},
+ {FPL("filename"), FPL("filename.xhtml"), "application/xhtml+xml"},
+ {FPL("filename.txt"), FPL("filename.txt"), "text/plain"},
+ {FPL("filename"), FPL("filename.txt"), "text/plain"},
+ {FPL("filename.css"), FPL("filename.css"), "text/css"},
+ {FPL("filename"), FPL("filename.css"), "text/css"},
+ {FPL("filename.mhtml"), FPL("filename.mhtml"), "multipart/related"},
+ {FPL("filename.html"), FPL("filename.html.mhtml"), "multipart/related"},
+ {FPL("filename.txt"), FPL("filename.txt.mhtml"), "multipart/related"},
+ {FPL("filename"), FPL("filename.mhtml"), "multipart/related"},
+ {FPL("filename.abc"), FPL("filename.abc"), "unknown/unknown"},
+ {FPL("filename"), FPL("filename"), "unknown/unknown"},
+ };
+ for (uint32_t i = 0; i < arraysize(kExtensionTests); ++i) {
+ base::FilePath original = base::FilePath(kExtensionTests[i].page_title);
+ base::FilePath expected = base::FilePath(kExtensionTests[i].expected_name);
+ std::string mime_type(kExtensionTests[i].contents_mime_type);
+ base::FilePath actual = EnsureMimeExtension(original, mime_type);
+ EXPECT_EQ(expected.value(), actual.value())
+ << "Failed for page title: " << kExtensionTests[i].page_title
+ << " MIME:" << mime_type;
+ }
+}
+
+// Test that the suggested names generated are reasonable:
+// If the name is a URL, retrieve only the path component since the path name
+// generation code will turn the entire URL into the file name leading to bad
+// extension names. For example, a page with no title and a URL:
+// http://www.foo.com/a/path/name.txt will turn into file:
+// "http www.foo.com a path name.txt", when we want to save it as "name.txt".
+
+static const struct GenerateFilenameTestCase {
+ const char* page_url;
+ const base::string16 page_title;
+ const base::FilePath::CharType* expected_name;
+ bool ensure_html_extension;
+} kGenerateFilenameCases[] = {
+ // Title overrides the URL.
+ {"http://foo.com", base::ASCIIToUTF16("A page title"),
+ FPL("A page title") FPL_HTML_EXTENSION, true},
+ // Extension is preserved.
+ {"http://foo.com", base::ASCIIToUTF16("A page title with.ext"),
+ FPL("A page title with.ext"), false},
+ // If the title matches the URL, use the last component of the URL.
+ {"http://foo.com/bar", base::ASCIIToUTF16("foo.com/bar"), FPL("bar"),
+ false},
+ // A URL with escaped special characters, when title matches the URL.
+ {"http://foo.com/%40.txt", base::ASCIIToUTF16("foo.com/%40.txt"),
+ FPL("@.txt"), false},
+ // A URL with unescaped special characters, when title matches the URL.
+ {"http://foo.com/@.txt", base::ASCIIToUTF16("foo.com/@.txt"), FPL("@.txt"),
+ false},
+ // A URL with punycode in the host name, when title matches the URL.
+ {"http://xn--bcher-kva.com", base::UTF8ToUTF16("bücher.com"),
+ FPL("bücher.com"), false},
+ // If the title matches the URL, but there is no "filename" component,
+ // use the domain.
+ {"http://foo.com", base::ASCIIToUTF16("foo.com"), FPL("foo.com"), false},
+ // Make sure fuzzy matching works.
+ {"http://foo.com/bar", base::ASCIIToUTF16("foo.com/bar"), FPL("bar"),
+ false},
+ // A URL-like title that does not match the title is respected in full.
+ {"http://foo.com", base::ASCIIToUTF16("http://www.foo.com/path/title.txt"),
+ FPL("http___www.foo.com_path_title.txt"), false},
+};
+
+// Crashing on Windows, see http://crbug.com/79365
+#if defined(OS_WIN)
+#define MAYBE_TestGenerateFilename DISABLED_TestGenerateFilename
+#else
+#define MAYBE_TestGenerateFilename TestGenerateFilename
+#endif
+TEST(FilenameGenerationTest, MAYBE_TestGenerateFilename) {
+ for (size_t i = 0; i < arraysize(kGenerateFilenameCases); ++i) {
+ base::FilePath save_name = GenerateFilename(
+ kGenerateFilenameCases[i].page_title,
+ GURL(kGenerateFilenameCases[i].page_url),
+ kGenerateFilenameCases[i].ensure_html_extension, std::string());
+ EXPECT_EQ(kGenerateFilenameCases[i].expected_name, save_name.value())
+ << "Test case " << i;
+ }
+}
+
+TEST(FilenameGenerationTest, TestBasicTruncation) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+ int max_length = base::GetMaximumPathComponentLength(temp_dir.GetPath());
+ ASSERT_NE(-1, max_length);
+
+ base::FilePath::StringType extension(FILE_PATH_LITERAL(".txt"));
+ base::FilePath path(GetLongNamePathInDirectory(
+ max_length, FILE_PATH_LITERAL(".txt"), temp_dir.GetPath()));
+ base::FilePath truncated_path = path;
+
+// The file path will only be truncated o the platforms that have known
+// encoding. Otherwise no truncation will be performed.
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
+ // The file name length is truncated to max_length.
+ EXPECT_TRUE(TruncateFilename(&truncated_path, max_length));
+ EXPECT_EQ(size_t(max_length), truncated_path.BaseName().value().size());
+#else
+ EXPECT_FALSE(TruncateFilename(&truncated_path, max_length));
+ EXPECT_EQ(truncated_path, path);
+ EXPECT_LT(size_t(max_length), truncated_path.BaseName().value().size());
+#endif
+ // But the extension is kept unchanged.
+ EXPECT_EQ(path.Extension(), truncated_path.Extension());
+}
+
+TEST(FilenameGenerationTest, TestTruncationFail) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+ int max_length = base::GetMaximumPathComponentLength(temp_dir.GetPath());
+ ASSERT_NE(-1, max_length);
+
+ base::FilePath path(
+ (FILE_PATH_LITERAL("a.") + base::FilePath::StringType(max_length, 'b'))
+ .c_str());
+ path = temp_dir.GetPath().Append(path);
+
+ base::FilePath truncated_path = path;
+
+ // We cannot truncate a path with very long extension. This will fail and no
+ // truncation will be performed on all platforms.
+ EXPECT_FALSE(TruncateFilename(&truncated_path, max_length));
+ EXPECT_EQ(truncated_path, path);
+}
+
+} // filename_generation
diff --git a/chromium/components/filesystem/BUILD.gn b/chromium/components/filesystem/BUILD.gn
index ff3ec9b517a..c070209cd37 100644
--- a/chromium/components/filesystem/BUILD.gn
+++ b/chromium/components/filesystem/BUILD.gn
@@ -31,7 +31,7 @@ static_library("lib") {
"//mojo/common:common_base",
"//mojo/public/cpp/system",
"//services/service_manager/public/cpp",
- "//services/service_manager/public/interfaces",
+ "//services/service_manager/public/mojom",
"//url",
]
}
diff --git a/chromium/components/filesystem/directory_impl.cc b/chromium/components/filesystem/directory_impl.cc
index 1209f6ecfcc..0e289031a5a 100644
--- a/chromium/components/filesystem/directory_impl.cc
+++ b/chromium/components/filesystem/directory_impl.cc
@@ -4,6 +4,7 @@
#include "components/filesystem/directory_impl.h"
+#include <memory>
#include <utility>
#include "base/files/file.h"
@@ -11,7 +12,6 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "components/filesystem/file_impl.h"
#include "components/filesystem/lock_table.h"
@@ -82,7 +82,7 @@ void DirectoryImpl::OpenFile(const std::string& raw_path,
if (file.is_pending()) {
mojo::MakeStrongBinding(
- base::MakeUnique<FileImpl>(path, std::move(base_file), temp_dir_,
+ std::make_unique<FileImpl>(path, std::move(base_file), temp_dir_,
lock_table_),
std::move(file));
}
@@ -146,7 +146,7 @@ void DirectoryImpl::OpenDirectory(const std::string& raw_path,
if (directory.is_pending()) {
mojo::MakeStrongBinding(
- base::MakeUnique<DirectoryImpl>(path, temp_dir_, lock_table_),
+ std::make_unique<DirectoryImpl>(path, temp_dir_, lock_table_),
std::move(directory));
}
@@ -295,7 +295,7 @@ void DirectoryImpl::StatFile(const std::string& raw_path,
void DirectoryImpl::Clone(mojom::DirectoryRequest directory) {
if (directory.is_pending()) {
- mojo::MakeStrongBinding(base::MakeUnique<DirectoryImpl>(
+ mojo::MakeStrongBinding(std::make_unique<DirectoryImpl>(
directory_path_, temp_dir_, lock_table_),
std::move(directory));
}
diff --git a/chromium/components/filesystem/file_impl.cc b/chromium/components/filesystem/file_impl.cc
index e853a91fd42..3fff0f3a7e7 100644
--- a/chromium/components/filesystem/file_impl.cc
+++ b/chromium/components/filesystem/file_impl.cc
@@ -7,12 +7,12 @@
#include <stddef.h>
#include <stdint.h>
#include <limits>
+#include <memory>
#include <utility>
#include "base/files/file_path.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "components/filesystem/lock_table.h"
#include "components/filesystem/shared_temp_dir.h"
@@ -299,7 +299,7 @@ void FileImpl::Dup(mojom::FileRequest file, DupCallback callback) {
if (file.is_pending()) {
mojo::MakeStrongBinding(
- base::MakeUnique<FileImpl>(path_, std::move(new_file), temp_dir_,
+ std::make_unique<FileImpl>(path_, std::move(new_file), temp_dir_,
lock_table_),
std::move(file));
}
diff --git a/chromium/components/filesystem/file_system_app.cc b/chromium/components/filesystem/file_system_app.cc
index b4ab6fe3689..69965c4d464 100644
--- a/chromium/components/filesystem/file_system_app.cc
+++ b/chromium/components/filesystem/file_system_app.cc
@@ -9,7 +9,6 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
-#include "base/memory/ptr_util.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/service_context.h"
@@ -57,7 +56,7 @@ void FileSystemApp::OnBindInterface(
void FileSystemApp::Create(mojom::FileSystemRequest request,
const service_manager::BindSourceInfo& source_info) {
mojo::MakeStrongBinding(
- base::MakeUnique<FileSystemImpl>(source_info.identity, GetUserDataDir(),
+ std::make_unique<FileSystemImpl>(source_info.identity, GetUserDataDir(),
lock_table_),
std::move(request));
}
diff --git a/chromium/components/filesystem/file_system_impl.cc b/chromium/components/filesystem/file_system_impl.cc
index 59e84de2451..508b4bc7a31 100644
--- a/chromium/components/filesystem/file_system_impl.cc
+++ b/chromium/components/filesystem/file_system_impl.cc
@@ -43,7 +43,7 @@ void FileSystemImpl::OpenTempDirectory(mojom::DirectoryRequest directory,
base::FilePath path = temp_dir->GetPath();
scoped_refptr<SharedTempDir> shared_temp_dir =
new SharedTempDir(std::move(temp_dir));
- mojo::MakeStrongBinding(base::MakeUnique<DirectoryImpl>(
+ mojo::MakeStrongBinding(std::make_unique<DirectoryImpl>(
path, std::move(shared_temp_dir), lock_table_),
std::move(directory));
std::move(callback).Run(mojom::FileError::OK);
@@ -60,7 +60,7 @@ void FileSystemImpl::OpenPersistentFileSystem(
scoped_refptr<SharedTempDir> shared_temp_dir =
new SharedTempDir(std::move(temp_dir));
- mojo::MakeStrongBinding(base::MakeUnique<DirectoryImpl>(
+ mojo::MakeStrongBinding(std::make_unique<DirectoryImpl>(
path, std::move(shared_temp_dir), lock_table_),
std::move(directory));
std::move(callback).Run(mojom::FileError::OK);
diff --git a/chromium/components/filesystem/public/interfaces/types.mojom b/chromium/components/filesystem/public/interfaces/types.mojom
index c3abf6c7fbf..7c8fff84676 100644
--- a/chromium/components/filesystem/public/interfaces/types.mojom
+++ b/chromium/components/filesystem/public/interfaces/types.mojom
@@ -79,6 +79,8 @@ const uint32 kFlagWrite = 0x40;
const uint32 kFlagAppend = 0x80;
// Deletes the file when closed.
const uint32 kDeleteOnClose = 0x2000;
+// May change modified time of the file (used on Windows only).
+const uint32 kFlagWriteAttributes = 0x4000;
// File types.
//
diff --git a/chromium/components/flags_ui/feature_entry.h b/chromium/components/flags_ui/feature_entry.h
index 64283844bc5..073eceae435 100644
--- a/chromium/components/flags_ui/feature_entry.h
+++ b/chromium/components/flags_ui/feature_entry.h
@@ -116,8 +116,8 @@ struct FeatureEntry {
const FeatureParam* params;
int num_params;
// A variation id number in the format of
- // VariationsHttpHeaderProvider::SetDefaultVariationIds or nullptr
- // if you do not need to set any variation_id for this feature variation.
+ // VariationsHttpHeaderProvider::ForceVariationIds() or nullptr if you do
+ // not need to set any variation_id for this feature variation.
const char* variation_id;
};
@@ -203,8 +203,8 @@ namespace testing {
// name-of-experiment + kMultiSeparator + selected_index.
extern const char kMultiSeparator[];
-} // namespace
+} // namespace testing
-} // namespace flag_ui
+} // namespace flags_ui
#endif // COMPONENTS_FLAGS_UI_FEATURE_ENTRY_H_
diff --git a/chromium/components/flags_ui/flags_state.cc b/chromium/components/flags_ui/flags_state.cc
index fba9512d9c8..b28bd45acb0 100644
--- a/chromium/components/flags_ui/flags_state.cc
+++ b/chromium/components/flags_ui/flags_state.cc
@@ -13,7 +13,6 @@
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
#include "base/stl_util.h"
#include "base/strings/string_piece.h"
@@ -198,9 +197,9 @@ std::unique_ptr<base::Value> CreateOptionsData(
entry.type == FeatureEntry::ENABLE_DISABLE_VALUE ||
entry.type == FeatureEntry::FEATURE_VALUE ||
entry.type == FeatureEntry::FEATURE_WITH_PARAMS_VALUE);
- auto result = base::MakeUnique<base::ListValue>();
+ auto result = std::make_unique<base::ListValue>();
for (int i = 0; i < entry.num_options; ++i) {
- auto value = base::MakeUnique<base::DictionaryValue>();
+ auto value = std::make_unique<base::DictionaryValue>();
const std::string name = entry.NameForOption(i);
value->SetString("internal_name", name);
value->SetString("description", entry.DescriptionForOption(i));
@@ -532,7 +531,7 @@ void FlagsState::GetFlagFeatureEntries(
data->SetString("description",
base::StringPiece(entry.visible_description));
- auto supported_platforms = base::MakeUnique<base::ListValue>();
+ auto supported_platforms = std::make_unique<base::ListValue>();
AddOsStrings(entry.supported_platforms, supported_platforms.get());
data->Set("supported_platforms", std::move(supported_platforms));
// True if the switch is not currently passed.
diff --git a/chromium/components/font_service/public/cpp/BUILD.gn b/chromium/components/font_service/public/cpp/BUILD.gn
index b51c79cdbbe..667d32ad6a6 100644
--- a/chromium/components/font_service/public/cpp/BUILD.gn
+++ b/chromium/components/font_service/public/cpp/BUILD.gn
@@ -19,7 +19,7 @@ source_set("cpp") {
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//services/service_manager/public/cpp",
- "//services/service_manager/public/interfaces",
+ "//services/service_manager/public/mojom",
"//skia",
]
}
diff --git a/chromium/components/gcm_driver/BUILD.gn b/chromium/components/gcm_driver/BUILD.gn
index d9e23063a22..fc55dc63925 100644
--- a/chromium/components/gcm_driver/BUILD.gn
+++ b/chromium/components/gcm_driver/BUILD.gn
@@ -5,13 +5,15 @@
import("//build/buildflag_header.gni")
import("//components/gcm_driver/config.gni")
-buildflag_header("gcm_build_features") {
- header = "gcm_build_features.h"
+buildflag_header("gcm_buildflags") {
+ header = "gcm_buildflags.h"
flags = [ "USE_GCM_FROM_PLATFORM=$use_gcm_from_platform" ]
}
static_library("gcm_driver") {
sources = [
+ "features.cc",
+ "features.h",
"gcm_account_tracker.cc",
"gcm_account_tracker.h",
"gcm_activity.cc",
@@ -49,7 +51,7 @@ static_library("gcm_driver") {
"//components/gcm_driver/instance_id",
]
deps = [
- ":gcm_build_features",
+ ":gcm_buildflags",
"//base:i18n",
"//components/crx_file",
"//components/data_use_measurement/core",
@@ -144,6 +146,7 @@ static_library("test_support") {
}
}
+# This is part of the components_unittests BUILD target.
source_set("unit_tests") {
testonly = true
diff --git a/chromium/components/gcm_driver/android/BUILD.gn b/chromium/components/gcm_driver/android/BUILD.gn
index 5909fd4a83c..99135a02fe4 100644
--- a/chromium/components/gcm_driver/android/BUILD.gn
+++ b/chromium/components/gcm_driver/android/BUILD.gn
@@ -34,6 +34,7 @@ junit_binary("components_gcm_driver_junit_tests") {
":gcm_driver_java",
"//base:base_java",
"//base:base_java_test_support",
+ "//base:base_junit_test_support",
"//third_party/hamcrest:hamcrest_java",
]
}
diff --git a/chromium/components/gcm_driver/crypto/BUILD.gn b/chromium/components/gcm_driver/crypto/BUILD.gn
index 5ee3c7db667..30cda558f01 100644
--- a/chromium/components/gcm_driver/crypto/BUILD.gn
+++ b/chromium/components/gcm_driver/crypto/BUILD.gn
@@ -65,6 +65,8 @@ source_set("unit_tests") {
"//base",
"//base/test:test_support",
"//components/gcm_driver/common",
+ "//components/gcm_driver/crypto/proto",
+ "//components/leveldb_proto",
"//crypto",
"//crypto:platform",
"//net:test_support",
diff --git a/chromium/components/gcm_driver/crypto/proto/BUILD.gn b/chromium/components/gcm_driver/crypto/proto/BUILD.gn
index b6d951c9afe..975000a858a 100644
--- a/chromium/components/gcm_driver/crypto/proto/BUILD.gn
+++ b/chromium/components/gcm_driver/crypto/proto/BUILD.gn
@@ -5,7 +5,10 @@
import("//third_party/protobuf/proto_library.gni")
proto_library("proto") {
- visibility = [ "//components/gcm_driver/crypto" ]
+ visibility = [
+ "//components/gcm_driver/crypto:crypto",
+ "//components/gcm_driver/crypto:unit_tests",
+ ]
sources = [
"gcm_encryption_data.proto",
diff --git a/chromium/components/gcm_driver/instance_id/BUILD.gn b/chromium/components/gcm_driver/instance_id/BUILD.gn
index b36c16ccbfc..e3aa405450c 100644
--- a/chromium/components/gcm_driver/instance_id/BUILD.gn
+++ b/chromium/components/gcm_driver/instance_id/BUILD.gn
@@ -65,7 +65,7 @@ source_set("unit_tests") {
":instance_id",
":test_support",
"//base",
- "//components/gcm_driver:gcm_build_features",
+ "//components/gcm_driver:gcm_buildflags",
"//google_apis/gcm",
"//net:test_support",
"//testing/gtest",
diff --git a/chromium/components/grpc_support/bidirectional_stream.cc b/chromium/components/grpc_support/bidirectional_stream.cc
index 129b3341935..814e9ece76b 100644
--- a/chromium/components/grpc_support/bidirectional_stream.cc
+++ b/chromium/components/grpc_support/bidirectional_stream.cc
@@ -6,6 +6,7 @@
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -100,8 +101,8 @@ int BidirectionalStream::Start(const char* url,
request_info->end_stream_on_headers = end_of_stream;
write_end_of_stream_ = end_of_stream;
PostToNetworkThread(FROM_HERE,
- base::Bind(&BidirectionalStream::StartOnNetworkThread,
- weak_this_, base::Passed(&request_info)));
+ base::BindOnce(&BidirectionalStream::StartOnNetworkThread,
+ weak_this_, std::move(request_info)));
return 0;
}
@@ -111,9 +112,9 @@ bool BidirectionalStream::ReadData(char* buffer, int capacity) {
scoped_refptr<net::WrappedIOBuffer> read_buffer(
new net::WrappedIOBuffer(buffer));
- PostToNetworkThread(FROM_HERE,
- base::Bind(&BidirectionalStream::ReadDataOnNetworkThread,
- weak_this_, read_buffer, capacity));
+ PostToNetworkThread(
+ FROM_HERE, base::BindOnce(&BidirectionalStream::ReadDataOnNetworkThread,
+ weak_this_, read_buffer, capacity));
return true;
}
@@ -127,30 +128,31 @@ bool BidirectionalStream::WriteData(const char* buffer,
new net::WrappedIOBuffer(buffer));
PostToNetworkThread(
- FROM_HERE, base::Bind(&BidirectionalStream::WriteDataOnNetworkThread,
- weak_this_, write_buffer, count, end_of_stream));
+ FROM_HERE,
+ base::BindOnce(&BidirectionalStream::WriteDataOnNetworkThread, weak_this_,
+ write_buffer, count, end_of_stream));
return true;
}
void BidirectionalStream::Flush() {
PostToNetworkThread(
FROM_HERE,
- base::Bind(&BidirectionalStream::FlushOnNetworkThread, weak_this_));
+ base::BindOnce(&BidirectionalStream::FlushOnNetworkThread, weak_this_));
}
void BidirectionalStream::Cancel() {
PostToNetworkThread(
FROM_HERE,
- base::Bind(&BidirectionalStream::CancelOnNetworkThread, weak_this_));
+ base::BindOnce(&BidirectionalStream::CancelOnNetworkThread, weak_this_));
}
void BidirectionalStream::Destroy() {
// Destroy could be called from any thread, including network thread (if
// posting task to executor throws an exception), but is posted, so |this|
// is valid until calling task is complete.
- PostToNetworkThread(FROM_HERE,
- base::Bind(&BidirectionalStream::DestroyOnNetworkThread,
- base::Unretained(this)));
+ PostToNetworkThread(
+ FROM_HERE, base::BindOnce(&BidirectionalStream::DestroyOnNetworkThread,
+ base::Unretained(this)));
}
void BidirectionalStream::OnStreamReady(bool request_headers_sent) {
@@ -249,9 +251,9 @@ void BidirectionalStream::OnFailed(int error) {
read_state_ = write_state_ = ERR;
weak_factory_.InvalidateWeakPtrs();
// Delete underlying |bidi_stream_| asynchronously as it may still be used.
- PostToNetworkThread(FROM_HERE,
- base::Bind(&base::DeletePointer<net::BidirectionalStream>,
- bidi_stream_.release()));
+ PostToNetworkThread(
+ FROM_HERE, base::BindOnce(&base::DeletePointer<net::BidirectionalStream>,
+ bidi_stream_.release()));
delegate_->OnFailed(error);
}
@@ -381,8 +383,9 @@ void BidirectionalStream::MaybeOnSucceded() {
weak_factory_.InvalidateWeakPtrs();
// Delete underlying |bidi_stream_| asynchronously as it may still be used.
PostToNetworkThread(
- FROM_HERE, base::Bind(&base::DeletePointer<net::BidirectionalStream>,
- bidi_stream_.release()));
+ FROM_HERE,
+ base::BindOnce(&base::DeletePointer<net::BidirectionalStream>,
+ bidi_stream_.release()));
delegate_->OnSucceeded();
}
}
@@ -393,8 +396,9 @@ bool BidirectionalStream::IsOnNetworkThread() {
}
void BidirectionalStream::PostToNetworkThread(const base::Location& from_here,
- const base::Closure& task) {
- request_context_getter_->GetNetworkTaskRunner()->PostTask(from_here, task);
+ base::OnceClosure task) {
+ request_context_getter_->GetNetworkTaskRunner()->PostTask(from_here,
+ std::move(task));
}
-} // namespace cronet
+} // namespace grpc_support
diff --git a/chromium/components/grpc_support/bidirectional_stream.h b/chromium/components/grpc_support/bidirectional_stream.h
index e7363196ce1..b65be345db8 100644
--- a/chromium/components/grpc_support/bidirectional_stream.h
+++ b/chromium/components/grpc_support/bidirectional_stream.h
@@ -17,7 +17,7 @@
namespace base {
class Location;
-} // namespace tracked_objects
+} // namespace base
namespace net {
class HttpRequestHeaders;
@@ -193,7 +193,7 @@ class BidirectionalStream : public net::BidirectionalStream::Delegate {
bool IsOnNetworkThread();
void PostToNetworkThread(const base::Location& from_here,
- const base::Closure& task);
+ base::OnceClosure task);
// Read state is tracking reading flow. Only accessed on network thread.
// | <--- READING <--- |
diff --git a/chromium/components/grpc_support/bidirectional_stream_c.cc b/chromium/components/grpc_support/bidirectional_stream_c.cc
index 05b9aa46cb6..aa7902b7de0 100644
--- a/chromium/components/grpc_support/bidirectional_stream_c.cc
+++ b/chromium/components/grpc_support/bidirectional_stream_c.cc
@@ -14,7 +14,6 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -39,12 +38,12 @@ namespace {
class HeadersArray : public bidirectional_stream_header_array {
public:
- HeadersArray(const net::SpdyHeaderBlock& header_block);
+ explicit HeadersArray(const net::SpdyHeaderBlock& header_block);
~HeadersArray();
private:
- DISALLOW_COPY_AND_ASSIGN(HeadersArray);
base::StringPairs headers_strings_;
+ DISALLOW_COPY_AND_ASSIGN(HeadersArray);
};
HeadersArray::HeadersArray(const net::SpdyHeaderBlock& header_block)
@@ -118,7 +117,7 @@ BidirectionalStreamAdapter::BidirectionalStreamAdapter(
bidirectional_stream_callback* callback)
: request_context_getter_(
reinterpret_cast<net::URLRequestContextGetter*>(engine->obj)),
- c_stream_(base::MakeUnique<bidirectional_stream>()),
+ c_stream_(std::make_unique<bidirectional_stream>()),
c_callback_(callback) {
DCHECK(request_context_getter_);
bidirectional_stream_ =
@@ -196,8 +195,9 @@ void BidirectionalStreamAdapter::DestroyAdapterForStream(
// is valid until calling task is complete.
adapter->bidirectional_stream_->Destroy();
adapter->request_context_getter_->GetNetworkTaskRunner()->PostTask(
- FROM_HERE, base::Bind(&BidirectionalStreamAdapter::DestroyOnNetworkThread,
- base::Unretained(adapter)));
+ FROM_HERE,
+ base::BindOnce(&BidirectionalStreamAdapter::DestroyOnNetworkThread,
+ base::Unretained(adapter)));
}
void BidirectionalStreamAdapter::DestroyOnNetworkThread() {
diff --git a/chromium/components/grpc_support/bidirectional_stream_unittest.cc b/chromium/components/grpc_support/bidirectional_stream_unittest.cc
index 1abaad5fac7..e0bea67d43a 100644
--- a/chromium/components/grpc_support/bidirectional_stream_unittest.cc
+++ b/chromium/components/grpc_support/bidirectional_stream_unittest.cc
@@ -7,9 +7,10 @@
#include <map>
#include <string>
+#include <memory>
+
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/strcat.h"
#include "base/synchronization/waitable_event.h"
#include "components/grpc_support/include/bidirectional_stream_c.h"
@@ -118,13 +119,14 @@ class TestBidirectionalStreamCallback {
static TestBidirectionalStreamCallback* FromStream(
bidirectional_stream* stream) {
DCHECK(stream);
- return (TestBidirectionalStreamCallback*)stream->annotation;
+ return reinterpret_cast<TestBidirectionalStreamCallback*>(
+ stream->annotation);
}
virtual bool MaybeCancel(bidirectional_stream* stream, ResponseStep step) {
DCHECK_EQ(stream, this->stream);
response_step = step;
- DLOG(WARNING) << "Step: " << step;
+ DVLOG(3) << "Step: " << step;
if (step != cancel_from_step)
return false;
@@ -141,7 +143,7 @@ class TestBidirectionalStreamCallback {
void AddWriteData(const std::string& data) { AddWriteData(data, true); }
void AddWriteData(const std::string& data, bool flush) {
- write_data.push_back(base::MakeUnique<WriteData>(data, flush));
+ write_data.push_back(std::make_unique<WriteData>(data, flush));
}
virtual void MaybeWriteNextData(bidirectional_stream* stream) {
@@ -537,9 +539,8 @@ TEST_P(BidirectionalStreamTest, StreamFailBeforeReadIsExecutedOnNetworkThread) {
: public TestBidirectionalStreamCallback {
bool MaybeCancel(bidirectional_stream* stream, ResponseStep step) override {
if (step == ResponseStep::ON_READ_COMPLETED) {
- // Shut down the server, and the stream should error out.
- // The second call to ShutdownQuicTestServer is no-op.
- ShutdownQuicTestServer();
+ // Shut down the server dispatcher, and the stream should error out.
+ ShutdownQuicTestServerDispatcher();
}
return TestBidirectionalStreamCallback::MaybeCancel(stream, step);
}
@@ -581,9 +582,8 @@ TEST_P(BidirectionalStreamTest, StreamFailAfterStreamReadyCallback) {
: public TestBidirectionalStreamCallback {
bool MaybeCancel(bidirectional_stream* stream, ResponseStep step) override {
if (step == ResponseStep::ON_STREAM_READY) {
- // Shut down the server, and the stream should error out.
- // The second call to ShutdownQuicTestServer is no-op.
- ShutdownQuicTestServer();
+ // Shut down the server dispatcher, and the stream should error out.
+ ShutdownQuicTestServerDispatcher();
}
return TestBidirectionalStreamCallback::MaybeCancel(stream, step);
}
@@ -611,9 +611,8 @@ TEST_P(BidirectionalStreamTest,
: public TestBidirectionalStreamCallback {
bool MaybeCancel(bidirectional_stream* stream, ResponseStep step) override {
if (step == ResponseStep::ON_WRITE_COMPLETED) {
- // Shut down the server, and the stream should error out.
- // The second call to ShutdownQuicTestServer is no-op.
- ShutdownQuicTestServer();
+ // Shut down the server dispatcher, and the stream should error out.
+ ShutdownQuicTestServerDispatcher();
}
return TestBidirectionalStreamCallback::MaybeCancel(stream, step);
}
diff --git a/chromium/components/guest_view/browser/guest_view_base.cc b/chromium/components/guest_view/browser/guest_view_base.cc
index 9a4a5613f9e..865dec78f43 100644
--- a/chromium/components/guest_view/browser/guest_view_base.cc
+++ b/chromium/components/guest_view/browser/guest_view_base.cc
@@ -4,11 +4,11 @@
#include "components/guest_view/browser/guest_view_base.h"
+#include <memory>
#include <utility>
#include "base/lazy_instance.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/guest_view/browser/guest_view_event.h"
#include "components/guest_view/browser/guest_view_manager.h"
@@ -228,7 +228,7 @@ void GuestViewBase::InitWithWebContents(
// an observer to the owner WebContents. This observer will be responsible
// for destroying the guest WebContents if the owner goes away.
owner_contents_observer_ =
- base::MakeUnique<OwnerContentsObserver>(this, owner_web_contents_);
+ std::make_unique<OwnerContentsObserver>(this, owner_web_contents_);
WebContentsObserver::Observe(guest_web_contents);
guest_web_contents->SetDelegate(this);
@@ -263,13 +263,13 @@ void GuestViewBase::DispatchOnResizeEvent(const gfx::Size& old_size,
return;
// Dispatch the onResize event.
- auto args = base::MakeUnique<base::DictionaryValue>();
+ auto args = std::make_unique<base::DictionaryValue>();
args->SetInteger(kOldWidth, old_size.width());
args->SetInteger(kOldHeight, old_size.height());
args->SetInteger(kNewWidth, new_size.width());
args->SetInteger(kNewHeight, new_size.height());
DispatchEventToGuestProxy(
- base::MakeUnique<GuestViewEvent>(kEventResize, std::move(args)));
+ std::make_unique<GuestViewEvent>(kEventResize, std::move(args)));
}
gfx::Size GuestViewBase::GetDefaultSize() const {
@@ -391,8 +391,6 @@ bool GuestViewBase::ZoomPropagatesFromEmbedderToGuest() const {
return true;
}
-void GuestViewBase::SetContextMenuPosition(const gfx::Point& position) {}
-
GuestViewManager* GuestViewBase::GetGuestViewManager() {
return GuestViewManager::FromBrowserContext(browser_context());
}
@@ -501,7 +499,7 @@ void GuestViewBase::SetOpener(GuestViewBase* guest) {
opener_ = guest->weak_ptr_factory_.GetWeakPtr();
if (!attached()) {
opener_lifetime_observer_ =
- base::MakeUnique<OpenerLifetimeObserver>(this);
+ std::make_unique<OpenerLifetimeObserver>(this);
}
return;
}
@@ -534,7 +532,7 @@ void GuestViewBase::WillAttach(WebContents* embedder_web_contents,
DCHECK_EQ(owner_contents_observer_->web_contents(), owner_web_contents_);
owner_web_contents_ = embedder_web_contents;
owner_contents_observer_ =
- base::MakeUnique<OwnerContentsObserver>(this, embedder_web_contents);
+ std::make_unique<OwnerContentsObserver>(this, embedder_web_contents);
SetOwnerHost();
}
diff --git a/chromium/components/guest_view/browser/guest_view_base.h b/chromium/components/guest_view/browser/guest_view_base.h
index da1748a87d0..32341e9197a 100644
--- a/chromium/components/guest_view/browser/guest_view_base.h
+++ b/chromium/components/guest_view/browser/guest_view_base.h
@@ -213,9 +213,6 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate,
~GuestViewBase() override;
- // BrowserPluginGuestDelegate implementation.
- void SetContextMenuPosition(const gfx::Point& position) override;
-
// TODO(ekaramad): If a guest is based on BrowserPlugin and is embedded inside
// a cross-process frame, we need to notify the destruction of the frame so
// that the clean-up on the browser side is done appropriately. Remove this
diff --git a/chromium/components/guest_view/browser/guest_view_message_filter.cc b/chromium/components/guest_view/browser/guest_view_message_filter.cc
index 3479d603f6b..ba433599c9f 100644
--- a/chromium/components/guest_view/browser/guest_view_message_filter.cc
+++ b/chromium/components/guest_view/browser/guest_view_message_filter.cc
@@ -4,7 +4,8 @@
#include "components/guest_view/browser/guest_view_message_filter.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "components/guest_view/browser/bad_message.h"
#include "components/guest_view/browser/guest_view_base.h"
#include "components/guest_view/browser/guest_view_manager.h"
@@ -53,7 +54,7 @@ GuestViewManager* GuestViewMessageFilter::GetOrCreateGuestViewManager() {
auto* manager = GuestViewManager::FromBrowserContext(browser_context_);
if (!manager) {
manager = GuestViewManager::CreateWithDelegate(
- browser_context_, base::MakeUnique<GuestViewManagerDelegate>());
+ browser_context_, std::make_unique<GuestViewManagerDelegate>());
}
return manager;
}
diff --git a/chromium/components/guest_view/browser/test_guest_view_manager.cc b/chromium/components/guest_view/browser/test_guest_view_manager.cc
index 84ca6d85f98..8dfc283bc7e 100644
--- a/chromium/components/guest_view/browser/test_guest_view_manager.cc
+++ b/chromium/components/guest_view/browser/test_guest_view_manager.cc
@@ -4,9 +4,9 @@
#include "components/guest_view/browser/test_guest_view_manager.h"
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "components/guest_view/browser/guest_view_base.h"
#include "components/guest_view/browser/guest_view_manager_delegate.h"
@@ -112,7 +112,7 @@ void TestGuestViewManager::AddGuest(int guest_instance_id,
GuestViewManager::AddGuest(guest_instance_id, guest_web_contents);
guest_web_contents_watchers_.push_back(
- base::MakeUnique<content::WebContentsDestroyedWatcher>(
+ std::make_unique<content::WebContentsDestroyedWatcher>(
guest_web_contents));
if (created_message_loop_runner_.get())
diff --git a/chromium/components/history/content/browser/BUILD.gn b/chromium/components/history/content/browser/BUILD.gn
index 55bdb007f23..41f00a52289 100644
--- a/chromium/components/history/content/browser/BUILD.gn
+++ b/chromium/components/history/content/browser/BUILD.gn
@@ -18,6 +18,7 @@ static_library("browser") {
deps = [
"//base",
+ "//components/download/public/common:public",
"//components/history/core/browser",
"//components/visitedlink/browser",
"//content/public/browser",
diff --git a/chromium/components/history/content/browser/DEPS b/chromium/components/history/content/browser/DEPS
index 4ef4ecea372..e42f69322d9 100644
--- a/chromium/components/history/content/browser/DEPS
+++ b/chromium/components/history/content/browser/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+components/download/public/common",
"+components/visitedlink/browser",
"+content/public/browser",
]
diff --git a/chromium/components/history/content/browser/content_history_backend_db_unittest.cc b/chromium/components/history/content/browser/content_history_backend_db_unittest.cc
index f364b846fc5..ecac62e4034 100644
--- a/chromium/components/history/content/browser/content_history_backend_db_unittest.cc
+++ b/chromium/components/history/content/browser/content_history_backend_db_unittest.cc
@@ -44,7 +44,7 @@ struct InterruptReasonAssociation {
// in order.
const InterruptReasonAssociation current_reasons[] = {
#define INTERRUPT_REASON(a, b) { #a, b },
-#include "content/public/browser/download_interrupt_reason_values.h"
+#include "components/download/public/common/download_interrupt_reason_values.h"
#undef INTERRUPT_REASON
};
diff --git a/chromium/components/history/content/browser/content_visit_delegate.cc b/chromium/components/history/content/browser/content_visit_delegate.cc
index 803a7b46c2e..a905e350922 100644
--- a/chromium/components/history/content/browser/content_visit_delegate.cc
+++ b/chromium/components/history/content/browser/content_visit_delegate.cc
@@ -120,7 +120,7 @@ void ContentVisitDelegate::RebuildTable(
const scoped_refptr<URLEnumerator>& enumerator) {
DCHECK(history_service_);
std::unique_ptr<HistoryDBTask> task(new IterateUrlsDBTask(enumerator));
- history_service_->ScheduleDBTask(std::move(task), &task_tracker_);
+ history_service_->ScheduleDBTask(FROM_HERE, std::move(task), &task_tracker_);
}
} // namespace history
diff --git a/chromium/components/history/content/browser/download_conversions.cc b/chromium/components/history/content/browser/download_conversions.cc
index ea9f1128783..3a6fd5c21a5 100644
--- a/chromium/components/history/content/browser/download_conversions.cc
+++ b/chromium/components/history/content/browser/download_conversions.cc
@@ -9,38 +9,38 @@
namespace history {
-content::DownloadItem::DownloadState ToContentDownloadState(
+download::DownloadItem::DownloadState ToContentDownloadState(
DownloadState state) {
switch (state) {
case DownloadState::IN_PROGRESS:
- return content::DownloadItem::IN_PROGRESS;
+ return download::DownloadItem::IN_PROGRESS;
case DownloadState::COMPLETE:
- return content::DownloadItem::COMPLETE;
+ return download::DownloadItem::COMPLETE;
case DownloadState::CANCELLED:
- return content::DownloadItem::CANCELLED;
+ return download::DownloadItem::CANCELLED;
case DownloadState::INTERRUPTED:
- return content::DownloadItem::INTERRUPTED;
+ return download::DownloadItem::INTERRUPTED;
case DownloadState::INVALID:
case DownloadState::BUG_140687:
NOTREACHED();
- return content::DownloadItem::MAX_DOWNLOAD_STATE;
+ return download::DownloadItem::MAX_DOWNLOAD_STATE;
}
NOTREACHED();
- return content::DownloadItem::MAX_DOWNLOAD_STATE;
+ return download::DownloadItem::MAX_DOWNLOAD_STATE;
}
DownloadState ToHistoryDownloadState(
- content::DownloadItem::DownloadState state) {
+ download::DownloadItem::DownloadState state) {
switch (state) {
- case content::DownloadItem::IN_PROGRESS:
+ case download::DownloadItem::IN_PROGRESS:
return DownloadState::IN_PROGRESS;
- case content::DownloadItem::COMPLETE:
+ case download::DownloadItem::COMPLETE:
return DownloadState::COMPLETE;
- case content::DownloadItem::CANCELLED:
+ case download::DownloadItem::CANCELLED:
return DownloadState::CANCELLED;
- case content::DownloadItem::INTERRUPTED:
+ case download::DownloadItem::INTERRUPTED:
return DownloadState::INTERRUPTED;
- case content::DownloadItem::MAX_DOWNLOAD_STATE:
+ case download::DownloadItem::MAX_DOWNLOAD_STATE:
NOTREACHED();
return DownloadState::INVALID;
}
@@ -48,55 +48,55 @@ DownloadState ToHistoryDownloadState(
return DownloadState::INVALID;
}
-content::DownloadDangerType ToContentDownloadDangerType(
+download::DownloadDangerType ToContentDownloadDangerType(
DownloadDangerType danger_type) {
switch (danger_type) {
case DownloadDangerType::NOT_DANGEROUS:
- return content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
+ return download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
case DownloadDangerType::DANGEROUS_FILE:
- return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
+ return download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
case DownloadDangerType::DANGEROUS_URL:
- return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL;
+ return download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL;
case DownloadDangerType::DANGEROUS_CONTENT:
- return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT;
+ return download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT;
case DownloadDangerType::MAYBE_DANGEROUS_CONTENT:
- return content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT;
+ return download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT;
case DownloadDangerType::UNCOMMON_CONTENT:
- return content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT;
+ return download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT;
case DownloadDangerType::USER_VALIDATED:
- return content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED;
+ return download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED;
case DownloadDangerType::DANGEROUS_HOST:
- return content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST;
+ return download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST;
case DownloadDangerType::POTENTIALLY_UNWANTED:
- return content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED;
+ return download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED;
case DownloadDangerType::INVALID:
NOTREACHED();
- return content::DOWNLOAD_DANGER_TYPE_MAX;
+ return download::DOWNLOAD_DANGER_TYPE_MAX;
}
NOTREACHED();
- return content::DOWNLOAD_DANGER_TYPE_MAX;
+ return download::DOWNLOAD_DANGER_TYPE_MAX;
}
DownloadDangerType ToHistoryDownloadDangerType(
- content::DownloadDangerType danger_type) {
+ download::DownloadDangerType danger_type) {
switch (danger_type) {
- case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
+ case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
return DownloadDangerType::NOT_DANGEROUS;
- case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
+ case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
return DownloadDangerType::DANGEROUS_FILE;
- case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
+ case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
return DownloadDangerType::DANGEROUS_URL;
- case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
+ case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
return DownloadDangerType::DANGEROUS_CONTENT;
- case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
+ case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
return DownloadDangerType::MAYBE_DANGEROUS_CONTENT;
- case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
+ case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
return DownloadDangerType::UNCOMMON_CONTENT;
- case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
+ case download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
return DownloadDangerType::USER_VALIDATED;
- case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
+ case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
return DownloadDangerType::DANGEROUS_HOST;
- case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+ case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
return DownloadDangerType::POTENTIALLY_UNWANTED;
default:
NOTREACHED();
@@ -104,13 +104,13 @@ DownloadDangerType ToHistoryDownloadDangerType(
}
}
-content::DownloadInterruptReason ToContentDownloadInterruptReason(
+download::DownloadInterruptReason ToContentDownloadInterruptReason(
DownloadInterruptReason interrupt_reason) {
- return static_cast<content::DownloadInterruptReason>(interrupt_reason);
+ return static_cast<download::DownloadInterruptReason>(interrupt_reason);
}
DownloadInterruptReason ToHistoryDownloadInterruptReason(
- content::DownloadInterruptReason interrupt_reason) {
+ download::DownloadInterruptReason interrupt_reason) {
return static_cast<DownloadInterruptReason>(interrupt_reason);
}
@@ -120,26 +120,30 @@ uint32_t ToContentDownloadId(DownloadId id) {
}
DownloadId ToHistoryDownloadId(uint32_t id) {
- DCHECK_NE(id, content::DownloadItem::kInvalidId);
+ DCHECK_NE(id, download::DownloadItem::kInvalidId);
return static_cast<DownloadId>(id);
}
-std::vector<content::DownloadItem::ReceivedSlice> ToContentReceivedSlices(
+std::vector<download::DownloadItem::ReceivedSlice> ToContentReceivedSlices(
const std::vector<DownloadSliceInfo>& slice_infos) {
- std::vector<content::DownloadItem::ReceivedSlice> result;
+ std::vector<download::DownloadItem::ReceivedSlice> result;
- for (const auto& slice_info : slice_infos)
- result.emplace_back(slice_info.offset, slice_info.received_bytes);
+ for (const auto& slice_info : slice_infos) {
+ result.emplace_back(slice_info.offset, slice_info.received_bytes,
+ slice_info.finished);
+ }
return result;
}
std::vector<DownloadSliceInfo> GetHistoryDownloadSliceInfos(
- const content::DownloadItem& item) {
+ const download::DownloadItem& item) {
std::vector<DownloadSliceInfo> result;
- for (const auto& slice : item.GetReceivedSlices())
- result.emplace_back(item.GetId(), slice.offset, slice.received_bytes);
+ for (const auto& slice : item.GetReceivedSlices()) {
+ result.emplace_back(item.GetId(), slice.offset, slice.received_bytes,
+ slice.finished);
+ }
return result;
}
diff --git a/chromium/components/history/content/browser/download_conversions.h b/chromium/components/history/content/browser/download_conversions.h
index e708944a86b..1482efab9a6 100644
--- a/chromium/components/history/content/browser/download_conversions.h
+++ b/chromium/components/history/content/browser/download_conversions.h
@@ -9,36 +9,36 @@
#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"
#include "components/history/core/browser/download_slice_info.h"
#include "components/history/core/browser/download_types.h"
-#include "content/public/browser/download_danger_type.h"
-#include "content/public/browser/download_interrupt_reasons.h"
-#include "content/public/browser/download_item.h"
namespace history {
-// Utility functions to convert between content::DownloadItem::DownloadState
+// Utility functions to convert between download::DownloadItem::DownloadState
// enumeration and history::DownloadState constants.
-content::DownloadItem::DownloadState ToContentDownloadState(
+download::DownloadItem::DownloadState ToContentDownloadState(
DownloadState state);
DownloadState ToHistoryDownloadState(
- content::DownloadItem::DownloadState state);
+ download::DownloadItem::DownloadState state);
-// Utility functions to convert between content::DownloadDangerType enumeration
+// Utility functions to convert between download::DownloadDangerType enumeration
// and history::DownloadDangerType constants.
-content::DownloadDangerType ToContentDownloadDangerType(
+download::DownloadDangerType ToContentDownloadDangerType(
DownloadDangerType danger_type);
DownloadDangerType ToHistoryDownloadDangerType(
- content::DownloadDangerType danger_type);
+ download::DownloadDangerType danger_type);
-// Utility functions to convert between content::DownloadInterruptReason
+// Utility functions to convert between download::DownloadInterruptReason
// enumeration and history::DownloadInterruptReason type (value have no
// meaning in history, but have a different type to avoid bugs due to
// implicit conversions).
-content::DownloadInterruptReason ToContentDownloadInterruptReason(
+download::DownloadInterruptReason ToContentDownloadInterruptReason(
DownloadInterruptReason interrupt_reason);
DownloadInterruptReason ToHistoryDownloadInterruptReason(
- content::DownloadInterruptReason interrupt_reason);
+ download::DownloadInterruptReason interrupt_reason);
// Utility functions to convert between content download id values and
// history::DownloadId type (value have no meaning in history, except
@@ -47,14 +47,14 @@ uint32_t ToContentDownloadId(DownloadId id);
DownloadId ToHistoryDownloadId(uint32_t id);
// Utility function to convert a history::DownloadSliceInfo vector into a
-// vector of content::DownloadItem::ReceivedSlice.
-std::vector<content::DownloadItem::ReceivedSlice> ToContentReceivedSlices(
+// vector of download::DownloadItem::ReceivedSlice.
+std::vector<download::DownloadItem::ReceivedSlice> ToContentReceivedSlices(
const std::vector<DownloadSliceInfo>& slice_infos);
// Construct a vector of history::DownloadSliceInfo from a
-// content::DownloadItem object.
+// download::DownloadItem object.
std::vector<DownloadSliceInfo> GetHistoryDownloadSliceInfos(
- const content::DownloadItem& item);
+ const download::DownloadItem& item);
} // namespace history
diff --git a/chromium/components/history/content/browser/download_conversions_unittest.cc b/chromium/components/history/content/browser/download_conversions_unittest.cc
index d972c8640b5..ecbc30d0560 100644
--- a/chromium/components/history/content/browser/download_conversions_unittest.cc
+++ b/chromium/components/history/content/browser/download_conversions_unittest.cc
@@ -18,15 +18,19 @@ TEST(DownloadConversionsTest, ToContentReceivedSlices) {
int64_t offset2 = 1000;
int64_t received2 = 50;
DownloadId id = 1;
- info.emplace_back(id, offset1, received1);
- info.emplace_back(id, offset2, received2);
- std::vector<content::DownloadItem::ReceivedSlice> received_slices =
+ info.emplace_back(id, offset1, received1, false);
+ info.emplace_back(id, offset2, received2, true);
+ std::vector<download::DownloadItem::ReceivedSlice> received_slices =
ToContentReceivedSlices(info);
EXPECT_EQ(2u, received_slices.size());
+
EXPECT_EQ(offset1, received_slices[0].offset);
EXPECT_EQ(received1, received_slices[0].received_bytes);
+ EXPECT_FALSE(received_slices[0].finished);
+
EXPECT_EQ(offset2, received_slices[1].offset);
EXPECT_EQ(received2, received_slices[1].received_bytes);
+ EXPECT_TRUE(received_slices[1].finished);
}
} // namespace history
diff --git a/chromium/components/history/content/browser/history_database_helper.cc b/chromium/components/history/content/browser/history_database_helper.cc
index 8d0b7fd2cae..295a8d35c3e 100644
--- a/chromium/components/history/content/browser/history_database_helper.cc
+++ b/chromium/components/history/content/browser/history_database_helper.cc
@@ -5,20 +5,19 @@
#include "components/history/content/browser/history_database_helper.h"
#include "base/files/file_path.h"
+#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/history/content/browser/download_conversions.h"
#include "components/history/core/browser/history_database_params.h"
-#include "content/public/browser/download_interrupt_reasons.h"
namespace history {
HistoryDatabaseParams HistoryDatabaseParamsForPath(
const base::FilePath& history_dir) {
- return HistoryDatabaseParams(
- history_dir,
- history::ToHistoryDownloadInterruptReason(
- content::DOWNLOAD_INTERRUPT_REASON_NONE),
- history::ToHistoryDownloadInterruptReason(
- content::DOWNLOAD_INTERRUPT_REASON_CRASH));
+ return HistoryDatabaseParams(history_dir,
+ history::ToHistoryDownloadInterruptReason(
+ download::DOWNLOAD_INTERRUPT_REASON_NONE),
+ history::ToHistoryDownloadInterruptReason(
+ download::DOWNLOAD_INTERRUPT_REASON_CRASH));
}
} // namespace
diff --git a/chromium/components/history/core/browser/BUILD.gn b/chromium/components/history/core/browser/BUILD.gn
index e4b67e5fd18..d3a9b446dbd 100644
--- a/chromium/components/history/core/browser/BUILD.gn
+++ b/chromium/components/history/core/browser/BUILD.gn
@@ -68,16 +68,12 @@ static_library("browser") {
"top_sites_impl.h",
"top_sites_observer.h",
"top_sites_provider.h",
- "typed_url_data_type_controller.cc",
- "typed_url_data_type_controller.h",
"typed_url_model_type_controller.cc",
"typed_url_model_type_controller.h",
"typed_url_sync_bridge.cc",
"typed_url_sync_bridge.h",
"typed_url_sync_metadata_database.cc",
"typed_url_sync_metadata_database.h",
- "typed_url_syncable_service.cc",
- "typed_url_syncable_service.h",
"url_database.cc",
"url_database.h",
"url_row.cc",
@@ -174,6 +170,7 @@ bundle_data("unit_tests_bundle_data") {
"//components/test/data/history/history.30.sql",
"//components/test/data/history/history.31.sql",
"//components/test/data/history/history.32.sql",
+ "//components/test/data/history/history.38.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",
@@ -209,7 +206,6 @@ source_set("unit_tests") {
"top_sites_impl_unittest.cc",
"typed_url_sync_bridge_unittest.cc",
"typed_url_sync_metadata_database_unittest.cc",
- "typed_url_syncable_service_unittest.cc",
"url_database_unittest.cc",
"url_utils_unittest.cc",
"visit_database_unittest.cc",
diff --git a/chromium/components/history/core/browser/OWNERS b/chromium/components/history/core/browser/OWNERS
index f782f95e7cf..797e0dd9199 100644
--- a/chromium/components/history/core/browser/OWNERS
+++ b/chromium/components/history/core/browser/OWNERS
@@ -1,5 +1,2 @@
-per-file typed_url_data_type_controller*=gangwu@chromium.org
-per-file typed_url_model_type_controller*=gangwu@chromium.org
-per-file typed_url_sync_bridge*=gangwu@chromium.org
-per-file typed_url_syncable_service*=gangwu@chromium.org
-per-file typed_url_syncable_service*=zea@chromium.org
+per-file typed_url_model_type_controller*=file://components/sync/OWNERS
+per-file typed_url_sync_bridge*=file://components/sync/OWNERS
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 fb33ef4eee8..ec292a15908 100644
--- a/chromium/components/history/core/browser/browsing_history_service_unittest.cc
+++ b/chromium/components/history/core/browser/browsing_history_service_unittest.cc
@@ -53,9 +53,6 @@ struct TestResult {
HistoryEntry::EntryType type;
};
-// Used to bind a callback.
-void DoNothing(bool ignored) {}
-
class TestSyncService : public syncer::FakeSyncService {
public:
int GetObserverCount() { return observer_count_; }
@@ -128,7 +125,7 @@ class TestWebHistoryService : public FakeWebHistoryService {
void TriggerOnWebHistoryDeleted() {
TestRequest request;
- ExpireHistoryCompletionCallback(base::Bind(&DoNothing), &request, true);
+ ExpireHistoryCompletionCallback(base::DoNothing(), &request, true);
}
protected:
diff --git a/chromium/components/history/core/browser/delete_directive_handler.cc b/chromium/components/history/core/browser/delete_directive_handler.cc
index f0a8e90bcf7..de730f6de8b 100644
--- a/chromium/components/history/core/browser/delete_directive_handler.cc
+++ b/chromium/components/history/core/browser/delete_directive_handler.cc
@@ -302,6 +302,7 @@ void DeleteDirectiveHandler::Start(
if (!initial_sync_data.empty()) {
// Drop processed delete directives during startup.
history_service->ScheduleDBTask(
+ FROM_HERE,
std::unique_ptr<HistoryDBTask>(
new DeleteDirectiveTask(weak_ptr_factory_.GetWeakPtr(),
initial_sync_data, DROP_AFTER_PROCESSING)),
@@ -407,6 +408,7 @@ syncer::SyncError DeleteDirectiveHandler::ProcessSyncChanges(
// redelivered delete directives to avoid processing them again and again
// in one chrome session.
history_service->ScheduleDBTask(
+ FROM_HERE,
std::unique_ptr<HistoryDBTask>(
new DeleteDirectiveTask(weak_ptr_factory_.GetWeakPtr(),
delete_directives, KEEP_AFTER_PROCESSING)),
diff --git a/chromium/components/history/core/browser/download_database.cc b/chromium/components/history/core/browser/download_database.cc
index c43a451f008..837b2951800 100644
--- a/chromium/components/history/core/browser/download_database.cc
+++ b/chromium/components/history/core/browser/download_database.cc
@@ -30,6 +30,10 @@ namespace history {
namespace {
+const char kDownloadsTable[] = "downloads";
+
+const char kDownloadsSlicesTable[] = "downloads_slices";
+
// Reason for dropping a particular record. Used for UMA.
enum DroppedReason {
DROPPED_REASON_BAD_STATE = 0,
@@ -82,8 +86,15 @@ DownloadDatabase::~DownloadDatabase() {
bool DownloadDatabase::EnsureColumnExists(const std::string& name,
const std::string& type) {
- std::string add_col = "ALTER TABLE downloads ADD COLUMN " + name + " " + type;
- return GetDB().DoesColumnExist("downloads", name.c_str()) ||
+ return EnsureColumnExistsInTable(kDownloadsTable, name, type);
+}
+
+bool DownloadDatabase::EnsureColumnExistsInTable(const std::string& table,
+ const std::string& name,
+ const std::string& type) {
+ std::string add_col =
+ "ALTER TABLE " + table + " ADD COLUMN " + name + " " + type;
+ return GetDB().DoesColumnExist(table.c_str(), name.c_str()) ||
GetDB().Execute(add_col.c_str());
}
@@ -96,7 +107,8 @@ bool DownloadDatabase::MigrateMimeType() {
bool DownloadDatabase::MigrateDownloadsState() {
sql::Statement statement(GetDB().GetUniqueStatement(
- "UPDATE downloads SET state=? WHERE state=?"));
+ base::StringPrintf("UPDATE %s SET state=? WHERE state=?", kDownloadsTable)
+ .c_str()));
statement.BindInt(0, DownloadStateToInt(DownloadState::INTERRUPTED));
statement.BindInt(1, DownloadStateToInt(DownloadState::BUG_140687));
return statement.Run();
@@ -105,11 +117,14 @@ bool DownloadDatabase::MigrateDownloadsState() {
bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() {
// We need to rename the table and copy back from it because SQLite
// provides no way to rename or delete a column.
- if (!GetDB().Execute("ALTER TABLE downloads RENAME TO downloads_tmp"))
+ if (!GetDB().Execute(
+ base::StringPrintf("ALTER TABLE %s RENAME TO downloads_tmp",
+ kDownloadsTable)
+ .c_str()))
return false;
- const char kReasonPathDangerSchema[] =
- "CREATE TABLE downloads ("
+ const std::string kReasonPathDangerSchema = base::StringPrintf(
+ "CREATE TABLE %s ("
"id INTEGER PRIMARY KEY,"
"current_path LONGVARCHAR NOT NULL,"
"target_path LONGVARCHAR NOT NULL,"
@@ -120,7 +135,8 @@ bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() {
"danger_type INTEGER NOT NULL,"
"interrupt_reason INTEGER NOT NULL,"
"end_time INTEGER NOT NULL,"
- "opened INTEGER NOT NULL)";
+ "opened INTEGER NOT NULL)",
+ kDownloadsTable);
static const char kReasonPathDangerUrlChainSchema[] =
"CREATE TABLE downloads_url_chains ("
@@ -133,7 +149,7 @@ bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() {
// Recreate main table.
- if (!GetDB().Execute(kReasonPathDangerSchema))
+ if (!GetDB().Execute(kReasonPathDangerSchema.c_str()))
return false;
// Populate it. As we do so, we transform the time values from time_t
@@ -141,18 +157,22 @@ bool DownloadDatabase::MigrateDownloadsReasonPathsAndDangerType() {
// since the Windows Epoch). Note that this is dependent on the
// internal representation of base::Time and needs to change if that changes.
sql::Statement statement_populate(GetDB().GetUniqueStatement(
- "INSERT INTO downloads "
- "( id, current_path, target_path, start_time, received_bytes, "
- " total_bytes, state, danger_type, interrupt_reason, end_time, opened ) "
- "SELECT id, full_path, full_path, "
- " CASE start_time WHEN 0 THEN 0 ELSE "
- " (start_time + 11644473600) * 1000000 END, "
- " received_bytes, total_bytes, "
- " state, ?, ?, "
- " CASE end_time WHEN 0 THEN 0 ELSE "
- " (end_time + 11644473600) * 1000000 END, "
- " opened "
- "FROM downloads_tmp"));
+ base::StringPrintf(
+ "INSERT INTO %s "
+ "( id, current_path, target_path, start_time, received_bytes, "
+ " total_bytes, state, danger_type, interrupt_reason, end_time, "
+ "opened ) "
+ "SELECT id, full_path, full_path, "
+ " CASE start_time WHEN 0 THEN 0 ELSE "
+ " (start_time + 11644473600) * 1000000 END, "
+ " received_bytes, total_bytes, "
+ " state, ?, ?, "
+ " CASE end_time WHEN 0 THEN 0 ELSE "
+ " (end_time + 11644473600) * 1000000 END, "
+ " opened "
+ "FROM downloads_tmp",
+ kDownloadsTable)
+ .c_str()));
statement_populate.BindInt(
0, DownloadInterruptReasonToInt(download_interrupt_reason_none_));
statement_populate.BindInt(
@@ -242,9 +262,11 @@ bool DownloadDatabase::MigrateHashHttpMethodAndGenerateGuids() {
// have an elevated risk of collision with GUIDs generated via
// base::GenerateGUID() and are considered valid by all known consumers. Hence
// no additional migration logic is being introduced to fix those GUIDs.
- sql::Statement select(GetDB().GetUniqueStatement("SELECT id FROM downloads"));
- sql::Statement update(
- GetDB().GetUniqueStatement("UPDATE downloads SET guid = ? WHERE id = ?"));
+ sql::Statement select(GetDB().GetUniqueStatement(
+ base::StringPrintf("SELECT id FROM %s", kDownloadsTable).c_str()));
+ sql::Statement update(GetDB().GetUniqueStatement(
+ base::StringPrintf("UPDATE %s SET guid = ? WHERE id = ?", kDownloadsTable)
+ .c_str()));
while (select.Step()) {
uint32_t id = select.ColumnInt(0);
uint64_t r1 = base::RandUint64();
@@ -281,9 +303,14 @@ bool DownloadDatabase::MigrateDownloadTransient() {
return EnsureColumnExists("transient", "INTEGER NOT NULL DEFAULT 0");
}
+bool DownloadDatabase::MigrateDownloadSliceFinished() {
+ return EnsureColumnExistsInTable(kDownloadsSlicesTable, "finished",
+ "INTEGER NOT NULL DEFAULT 0");
+}
+
bool DownloadDatabase::InitDownloadTable() {
- const char kSchema[] =
- "CREATE TABLE downloads ("
+ const std::string kSchema = base::StringPrintf(
+ "CREATE TABLE %s ("
"id INTEGER PRIMARY KEY," // Primary key.
"guid VARCHAR NOT NULL," // GUID.
"current_path LONGVARCHAR NOT NULL," // Current disk location
@@ -298,13 +325,15 @@ bool DownloadDatabase::InitDownloadTable() {
"end_time INTEGER NOT NULL," // When the download completed.
"opened INTEGER NOT NULL," // 1 if it has ever been opened
// else 0
- "last_access_time INTEGER NOT NULL," // The last time it was accessed.
+ "last_access_time INTEGER NOT NULL," // The last time it was
+ // accessed.
"transient INTEGER NOT NULL," // 1 if it is transient, else 0.
"referrer VARCHAR NOT NULL," // HTTP Referrer
"site_url VARCHAR NOT NULL," // Site URL for initiating site
// instance.
"tab_url VARCHAR NOT NULL," // Tab URL for initiator.
- "tab_referrer_url VARCHAR NOT NULL," // Tag referrer URL for initiator.
+ "tab_referrer_url VARCHAR NOT NULL," // Tag referrer URL for
+ // initiator.
"http_method VARCHAR NOT NULL," // HTTP method.
"by_ext_id VARCHAR NOT NULL," // ID of extension that started the
// download
@@ -312,7 +341,9 @@ bool DownloadDatabase::InitDownloadTable() {
"etag VARCHAR NOT NULL," // ETag
"last_modified VARCHAR NOT NULL," // Last-Modified header
"mime_type VARCHAR(255) NOT NULL," // MIME type.
- "original_mime_type VARCHAR(255) NOT NULL)"; // Original MIME type.
+ "original_mime_type VARCHAR(255) NOT NULL)" // Original MIME type.
+ ,
+ kDownloadsTable);
const char kUrlChainSchema[] =
"CREATE TABLE downloads_url_chains ("
@@ -323,15 +354,17 @@ bool DownloadDatabase::InitDownloadTable() {
"url LONGVARCHAR NOT NULL, " // URL.
"PRIMARY KEY (id, chain_index) )";
- const char kSlicesSchema[] =
- "CREATE TABLE downloads_slices ("
- "download_id INTEGER NOT NULL," // downloads.id.
- "offset INTEGER NOT NULL," // Offset in the target file.
- "received_bytes INTEGER NOT NULL," // Total bytes downloaded.
- "PRIMARY KEY (download_id, offset) )";
+ const std::string kSlicesSchema = base::StringPrintf(
+ "CREATE TABLE %s ("
+ "download_id INTEGER NOT NULL," // downloads.id.
+ "offset INTEGER NOT NULL," // Offset in the target file.
+ "received_bytes INTEGER NOT NULL," // Total bytes downloaded.
+ "finished INTEGER NOT NULL DEFAULT 0," // If the slice is finished.
+ "PRIMARY KEY (download_id, offset) )",
+ kDownloadsSlicesTable);
bool ret;
- if (GetDB().DoesTableExist("downloads")) {
+ if (GetDB().DoesTableExist(kDownloadsTable)) {
// If the "downloads" table exists, "downloads_url_chain" might not be there
// as it is introduced in version 24. A migration function will be run to
// create it later.
@@ -342,18 +375,19 @@ bool DownloadDatabase::InitDownloadTable() {
// "downloads_url_chain" table.
ret = !GetDB().DoesTableExist("downloads_url_chain");
// Recreate the "downloads" and "downloads_url_chain" table.
- ret = ret && GetDB().Execute(kSchema) && GetDB().Execute(kUrlChainSchema);
+ ret = ret && GetDB().Execute(kSchema.c_str()) &&
+ GetDB().Execute(kUrlChainSchema);
}
// Making sure the "downloads_slices" table is created as it is introduced in
// version 33. This table doesn't require migration of existing tables.
- return ret && (GetDB().DoesTableExist("downloads_slices") ||
- GetDB().Execute(kSlicesSchema));
+ return ret && (GetDB().DoesTableExist(kDownloadsSlicesTable) ||
+ GetDB().Execute(kSlicesSchema.c_str()));
}
uint32_t DownloadDatabase::GetNextDownloadId() {
sql::Statement select_max_id(GetDB().GetUniqueStatement(
- "SELECT max(id) FROM downloads"));
+ base::StringPrintf("SELECT max(id) FROM %s", kDownloadsTable).c_str()));
bool result = select_max_id.Step();
DCHECK(result);
// If there are zero records in the downloads table, then max(id) will
@@ -374,7 +408,8 @@ uint32_t DownloadDatabase::GetNextDownloadId() {
}
bool DownloadDatabase::DropDownloadTable() {
- return GetDB().Execute("DROP TABLE downloads");
+ return GetDB().Execute(
+ base::StringPrintf("DROP TABLE %s", kDownloadsTable).c_str());
}
void DownloadDatabase::QueryDownloads(std::vector<DownloadRow>* results) {
@@ -388,12 +423,15 @@ void DownloadDatabase::QueryDownloads(std::vector<DownloadRow>* results) {
sql::Statement statement_main(GetDB().GetCachedStatement(
SQL_FROM_HERE,
- "SELECT id, guid, current_path, target_path, mime_type, "
- "original_mime_type, start_time, received_bytes, total_bytes, state, "
- "danger_type, interrupt_reason, hash, end_time, opened, "
- "last_access_time, transient, referrer, site_url, tab_url, "
- "tab_referrer_url, http_method, by_ext_id, by_ext_name, etag, "
- "last_modified FROM downloads ORDER BY start_time"));
+ base::StringPrintf(
+ "SELECT id, guid, current_path, target_path, mime_type, "
+ "original_mime_type, start_time, received_bytes, total_bytes, state, "
+ "danger_type, interrupt_reason, hash, end_time, opened, "
+ "last_access_time, transient, referrer, site_url, tab_url, "
+ "tab_referrer_url, http_method, by_ext_id, by_ext_name, etag, "
+ "last_modified FROM %s ORDER BY start_time",
+ kDownloadsTable)
+ .c_str()));
while (statement_main.Step()) {
std::unique_ptr<DownloadRow> info(new DownloadRow());
@@ -538,13 +576,17 @@ bool DownloadDatabase::UpdateDownload(const DownloadRow& data) {
sql::Statement statement(GetDB().GetCachedStatement(
SQL_FROM_HERE,
- "UPDATE downloads "
- "SET current_path=?, target_path=?, "
- "mime_type=?, original_mime_type=?, "
- "received_bytes=?, state=?, "
- "danger_type=?, interrupt_reason=?, hash=?, end_time=?, total_bytes=?, "
- "opened=?, last_access_time=?, transient=?, by_ext_id=?, by_ext_name=?, "
- "etag=?, last_modified=? WHERE id=?"));
+ base::StringPrintf("UPDATE %s "
+ "SET current_path=?, target_path=?, "
+ "mime_type=?, original_mime_type=?, "
+ "received_bytes=?, state=?, "
+ "danger_type=?, interrupt_reason=?, hash=?, "
+ "end_time=?, total_bytes=?, "
+ "opened=?, last_access_time=?, transient=?, "
+ "by_ext_id=?, by_ext_name=?, "
+ "etag=?, last_modified=? WHERE id=?",
+ kDownloadsTable)
+ .c_str()));
int column = 0;
BindFilePath(statement, data.current_path, column++);
BindFilePath(statement, data.target_path, column++);
@@ -586,8 +628,12 @@ void DownloadDatabase::EnsureInProgressEntriesCleanedUp() {
if (in_progress_entry_cleanup_completed_)
return;
- sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
- "UPDATE downloads SET state=?, interrupt_reason=? WHERE state=?"));
+ sql::Statement statement(GetDB().GetCachedStatement(
+ SQL_FROM_HERE,
+ base::StringPrintf(
+ "UPDATE %s SET state=?, interrupt_reason=? WHERE state=?",
+ kDownloadsTable)
+ .c_str()));
statement.BindInt(0, DownloadStateToInt(DownloadState::INTERRUPTED));
statement.BindInt(
1, DownloadInterruptReasonToInt(download_interrupt_reason_crash_));
@@ -615,16 +661,20 @@ bool DownloadDatabase::CreateDownload(const DownloadRow& info) {
{
sql::Statement statement_insert(GetDB().GetCachedStatement(
SQL_FROM_HERE,
- "INSERT INTO downloads "
- "(id, guid, current_path, target_path, mime_type, original_mime_type, "
- " start_time, received_bytes, total_bytes, state, danger_type, "
- " interrupt_reason, hash, end_time, opened, last_access_time, "
- "transient, referrer, site_url, tab_url, tab_referrer_url, "
- "http_method, "
- " by_ext_id, by_ext_name, etag, last_modified) "
- "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
- " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
- " ?, ?, ?, ?, ?, ?)"));
+ base::StringPrintf(
+ "INSERT INTO %s "
+ "(id, guid, current_path, target_path, mime_type, "
+ "original_mime_type, "
+ " start_time, received_bytes, total_bytes, state, danger_type, "
+ " interrupt_reason, hash, end_time, opened, last_access_time, "
+ "transient, referrer, site_url, tab_url, tab_referrer_url, "
+ "http_method, "
+ " by_ext_id, by_ext_name, etag, last_modified) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
+ " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
+ " ?, ?, ?, ?, ?, ?)",
+ kDownloadsTable)
+ .c_str()));
int column = 0;
statement_insert.BindInt(column++, DownloadIdToInt(info.id));
@@ -714,8 +764,10 @@ bool DownloadDatabase::CreateDownload(const DownloadRow& info) {
void DownloadDatabase::RemoveDownload(DownloadId id) {
EnsureInProgressEntriesCleanedUp();
- sql::Statement downloads_statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
- "DELETE FROM downloads WHERE id=?"));
+ sql::Statement downloads_statement(GetDB().GetCachedStatement(
+ SQL_FROM_HERE,
+ base::StringPrintf("DELETE FROM %s WHERE id=?", kDownloadsTable)
+ .c_str()));
downloads_statement.BindInt(0, id);
if (!downloads_statement.Run()) {
UMA_HISTOGRAM_ENUMERATION("Download.DatabaseMainDeleteError",
@@ -739,8 +791,9 @@ void DownloadDatabase::RemoveDownloadURLs(DownloadId id) {
size_t DownloadDatabase::CountDownloads() {
EnsureInProgressEntriesCleanedUp();
- sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
- "SELECT count(*) from downloads"));
+ sql::Statement statement(GetDB().GetCachedStatement(
+ SQL_FROM_HERE,
+ base::StringPrintf("SELECT count(*) from %s", kDownloadsTable).c_str()));
statement.Step();
return statement.ColumnInt(0);
}
@@ -754,19 +807,24 @@ bool DownloadDatabase::CreateOrUpdateDownloadSlice(
return true;
sql::Statement statement_replace(GetDB().GetCachedStatement(
SQL_FROM_HERE,
- "REPLACE INTO downloads_slices "
- "(download_id, offset, received_bytes) "
- "VALUES (?, ?, ?)"));
+ base::StringPrintf("REPLACE INTO %s "
+ "(download_id, offset, received_bytes, finished) "
+ "VALUES (?, ?, ?, ?)",
+ kDownloadsSlicesTable)
+ .c_str()));
int column = 0;
statement_replace.BindInt(column++, info.download_id);
statement_replace.BindInt64(column++, info.offset);
statement_replace.BindInt64(column++, info.received_bytes);
+ statement_replace.BindInt64(column++, (info.finished ? 1 : 0));
return statement_replace.Run();
}
void DownloadDatabase::RemoveDownloadSlices(DownloadId id) {
- sql::Statement statement_delete(GetDB().GetCachedStatement(SQL_FROM_HERE,
- "DELETE FROM downloads_slices WHERE download_id=?"));
+ sql::Statement statement_delete(GetDB().GetCachedStatement(
+ SQL_FROM_HERE, base::StringPrintf("DELETE FROM %s WHERE download_id=?",
+ kDownloadsSlicesTable)
+ .c_str()));
statement_delete.BindInt(0, id);
statement_delete.Run();
}
@@ -775,9 +833,11 @@ void DownloadDatabase::QueryDownloadSlices(DownloadRowMap* download_row_map) {
DCHECK(download_row_map);
sql::Statement statement_query(GetDB().GetCachedStatement(
SQL_FROM_HERE,
- "SELECT download_id, offset, received_bytes "
- "FROM downloads_slices "
- "ORDER BY download_id, offset"));
+ base::StringPrintf("SELECT download_id, offset, received_bytes, finished "
+ "FROM %s "
+ "ORDER BY download_id, offset",
+ kDownloadsSlicesTable)
+ .c_str()));
while (statement_query.Step()) {
int column = 0;
@@ -789,6 +849,7 @@ void DownloadDatabase::QueryDownloadSlices(DownloadRowMap* download_row_map) {
<< signed_id;
info.offset = statement_query.ColumnInt64(column++);
info.received_bytes = statement_query.ColumnInt64(column++);
+ info.finished = static_cast<bool>(statement_query.ColumnInt64(column++));
// Confirm the download_id has already been seen--if it hasn't, discard the
// record.
diff --git a/chromium/components/history/core/browser/download_database.h b/chromium/components/history/core/browser/download_database.h
index 7a80f69eb00..2b214fe77c7 100644
--- a/chromium/components/history/core/browser/download_database.h
+++ b/chromium/components/history/core/browser/download_database.h
@@ -99,6 +99,9 @@ class DownloadDatabase {
// Returns true if able to add transient column to the download table.
bool MigrateDownloadTransient();
+ // Returns true if able to add the finished column to downloads slices table.
+ bool MigrateDownloadSliceFinished();
+
// Creates the downloads table if needed.
bool InitDownloadTable();
@@ -117,8 +120,14 @@ class DownloadDatabase {
// 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|.
+ bool EnsureColumnExistsInTable(const std::string& table,
+ const std::string& name,
+ const std::string& type);
+
void RemoveDownloadURLs(DownloadId id);
// Creates a new download slice if it doesn't exist, or updates an existing
diff --git a/chromium/components/history/core/browser/download_slice_info.cc b/chromium/components/history/core/browser/download_slice_info.cc
index 7087ca01595..c359d017804 100644
--- a/chromium/components/history/core/browser/download_slice_info.cc
+++ b/chromium/components/history/core/browser/download_slice_info.cc
@@ -11,14 +11,17 @@ namespace history {
DownloadSliceInfo::DownloadSliceInfo()
: download_id(kInvalidDownloadId),
offset(0),
- received_bytes(0) {}
+ received_bytes(0),
+ finished(false) {}
DownloadSliceInfo::DownloadSliceInfo(DownloadId download_id,
int64_t offset,
- int64_t received_bytes)
+ int64_t received_bytes,
+ bool finished)
: download_id(download_id),
offset(offset),
- received_bytes(received_bytes) {}
+ received_bytes(received_bytes),
+ finished(finished) {}
DownloadSliceInfo::DownloadSliceInfo(const DownloadSliceInfo& other) = default;
@@ -26,7 +29,7 @@ DownloadSliceInfo::~DownloadSliceInfo() = default;
bool DownloadSliceInfo::operator==(const DownloadSliceInfo& rhs) const {
return download_id == rhs.download_id && offset == rhs.offset &&
- received_bytes == rhs.received_bytes;
+ received_bytes == rhs.received_bytes && finished == rhs.finished;
}
} // namespace history
diff --git a/chromium/components/history/core/browser/download_slice_info.h b/chromium/components/history/core/browser/download_slice_info.h
index 4af8efbc030..296f48568c3 100644
--- a/chromium/components/history/core/browser/download_slice_info.h
+++ b/chromium/components/history/core/browser/download_slice_info.h
@@ -19,7 +19,8 @@ struct DownloadSliceInfo {
DownloadSliceInfo();
DownloadSliceInfo(DownloadId download_id,
int64_t offset,
- int64_t received_bytes);
+ int64_t received_bytes,
+ bool finished);
DownloadSliceInfo(const DownloadSliceInfo& other);
~DownloadSliceInfo();
@@ -33,6 +34,9 @@ struct DownloadSliceInfo {
// The number of bytes received (so far).
int64_t received_bytes;
+
+ // If the download stream is successfully finished for this slice.
+ bool finished;
};
} // namespace history
diff --git a/chromium/components/history/core/browser/download_slice_info_unittest.cc b/chromium/components/history/core/browser/download_slice_info_unittest.cc
index 59ee172e565..ef5ec6d454e 100644
--- a/chromium/components/history/core/browser/download_slice_info_unittest.cc
+++ b/chromium/components/history/core/browser/download_slice_info_unittest.cc
@@ -9,11 +9,14 @@
namespace history {
TEST(DownloadSliceInfoTest, CompareDownloadSliceInfo) {
- DownloadSliceInfo info1(1, 500, 10);
- DownloadSliceInfo info2(1, 500, 1000);
+ DownloadSliceInfo info1(1, 500, 10, false);
+ DownloadSliceInfo info2(1, 500, 1000, true);
EXPECT_FALSE(info1 == info2);
info1.received_bytes = 1000;
+ EXPECT_FALSE(info1 == info2);
+
+ info1.finished = true;
EXPECT_TRUE(info1 == info2);
info1.offset = 1;
diff --git a/chromium/components/history/core/browser/expire_history_backend.cc b/chromium/components/history/core/browser/expire_history_backend.cc
index c0c17ea2603..e55dc56bf4e 100644
--- a/chromium/components/history/core/browser/expire_history_backend.cc
+++ b/chromium/components/history/core/browser/expire_history_backend.cc
@@ -212,7 +212,8 @@ void ExpireHistoryBackend::DeleteURLs(const std::vector<GURL>& urls) {
DeleteFaviconsIfPossible(&effects);
- BroadcastNotifications(&effects, DELETION_USER_INITIATED);
+ BroadcastNotifications(&effects, DELETION_USER_INITIATED,
+ DeletionTimeRange::Invalid());
}
void ExpireHistoryBackend::ExpireHistoryBetween(
@@ -228,7 +229,7 @@ void ExpireHistoryBackend::ExpireHistoryBetween(
if (!restrict_urls.empty()) {
std::set<URLID> url_ids;
for (std::set<GURL>::const_iterator url = restrict_urls.begin();
- url != restrict_urls.end(); ++url)
+ url != restrict_urls.end(); ++url)
url_ids.insert(main_db_->GetRowForURL(*url, nullptr));
VisitVector all_visits;
all_visits.swap(visits);
@@ -238,7 +239,10 @@ void ExpireHistoryBackend::ExpireHistoryBetween(
visits.push_back(*visit);
}
}
- ExpireVisits(visits);
+ DeletionTimeRange time_range = restrict_urls.empty()
+ ? DeletionTimeRange(begin_time, end_time)
+ : DeletionTimeRange::Invalid();
+ ExpireVisitsInternal(visits, time_range);
}
void ExpireHistoryBackend::ExpireHistoryForTimes(
@@ -261,6 +265,12 @@ void ExpireHistoryBackend::ExpireHistoryForTimes(
}
void ExpireHistoryBackend::ExpireVisits(const VisitVector& visits) {
+ ExpireVisitsInternal(visits, DeletionTimeRange::Invalid());
+}
+
+void ExpireHistoryBackend::ExpireVisitsInternal(
+ const VisitVector& visits,
+ const DeletionTimeRange& time_range) {
if (visits.empty())
return;
@@ -277,7 +287,7 @@ void ExpireHistoryBackend::ExpireVisits(const VisitVector& visits) {
// and we don't want to leave any evidence.
ExpireURLsForVisits(visits_and_redirects, &effects);
DeleteFaviconsIfPossible(&effects);
- BroadcastNotifications(&effects, DELETION_USER_INITIATED);
+ BroadcastNotifications(&effects, DELETION_USER_INITIATED, time_range);
// Pick up any bits possibly left over.
ParanoidExpireHistory();
@@ -359,14 +369,15 @@ void ExpireHistoryBackend::DeleteFaviconsIfPossible(DeleteEffects* effects) {
}
}
-void ExpireHistoryBackend::BroadcastNotifications(DeleteEffects* effects,
- DeletionType type) {
+void ExpireHistoryBackend::BroadcastNotifications(
+ DeleteEffects* effects,
+ DeletionType type,
+ const DeletionTimeRange& time_range) {
if (!effects->modified_urls.empty()) {
notifier_->NotifyURLsModified(effects->modified_urls);
}
- if (!effects->deleted_urls.empty()) {
- notifier_->NotifyURLsDeleted(false,
- type == DELETION_EXPIRED,
+ if (!effects->deleted_urls.empty() || time_range.IsValid()) {
+ notifier_->NotifyURLsDeleted(time_range, type == DELETION_EXPIRED,
effects->deleted_urls,
effects->deleted_favicons);
}
@@ -578,7 +589,8 @@ void ExpireHistoryBackend::ClearOldOnDemandFaviconsIfPossible(
effects.deleted_favicons.insert(mappings.icon_url);
}
- BroadcastNotifications(&effects, DELETION_EXPIRED);
+ BroadcastNotifications(&effects, DELETION_EXPIRED,
+ DeletionTimeRange::Invalid());
}
bool ExpireHistoryBackend::ExpireSomeOldHistory(
@@ -601,8 +613,10 @@ bool ExpireHistoryBackend::ExpireSomeOldHistory(
DeleteVisitRelatedInfo(deleted_visits, &deleted_effects);
ExpireURLsForVisits(deleted_visits, &deleted_effects);
DeleteFaviconsIfPossible(&deleted_effects);
-
- BroadcastNotifications(&deleted_effects, DELETION_EXPIRED);
+ DeletionTimeRange time_range =
+ more_to_expire ? DeletionTimeRange::Invalid()
+ : DeletionTimeRange(base::Time(), end_time);
+ BroadcastNotifications(&deleted_effects, DELETION_EXPIRED, time_range);
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 24510db5545..1c89f47e8fd 100644
--- a/chromium/components/history/core/browser/expire_history_backend.h
+++ b/chromium/components/history/core/browser/expire_history_backend.h
@@ -201,6 +201,9 @@ class ExpireHistoryBackend {
// any now-unused favicons.
void ExpireURLsForVisits(const VisitVector& visits, DeleteEffects* effects);
+ void ExpireVisitsInternal(const VisitVector& visits,
+ const DeletionTimeRange& time_range);
+
// Deletes the favicons listed in |effects->affected_favicons| if they are
// unsued. 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
@@ -218,7 +221,9 @@ class ExpireHistoryBackend {
};
// Broadcasts URL modified and deleted notifications.
- void BroadcastNotifications(DeleteEffects* effects, DeletionType type);
+ void BroadcastNotifications(DeleteEffects* effects,
+ DeletionType type,
+ const DeletionTimeRange& time_range);
// Schedules a call to DoExpireIteration.
void ScheduleExpire();
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 fa076933a1d..2e98f96b093 100644
--- a/chromium/components/history/core/browser/expire_history_backend_unittest.cc
+++ b/chromium/components/history/core/browser/expire_history_backend_unittest.cc
@@ -105,6 +105,11 @@ class ExpireHistoryTest : public testing::Test, public HistoryBackendNotifier {
// |expired|, or manually deleted.
void EnsureURLInfoGone(const URLRow& row, bool expired);
+ DeletionTimeRange GetLastDeletionTimeRange() {
+ EXPECT_FALSE(urls_deleted_notifications_.empty());
+ return std::get<0>(urls_deleted_notifications_.back());
+ }
+
// Returns whether HistoryBackendNotifier::NotifyURLsModified was
// called for |url|.
bool ModifiedNotificationSent(const GURL& url);
@@ -143,7 +148,8 @@ class ExpireHistoryTest : public testing::Test, public HistoryBackendNotifier {
typedef std::vector<URLRows> URLsModifiedNotificationList;
URLsModifiedNotificationList urls_modified_notifications_;
- typedef std::vector<std::pair<bool, URLRows>> URLsDeletedNotificationList;
+ typedef std::vector<std::tuple<DeletionTimeRange, bool, URLRows>>
+ URLsDeletedNotificationList;
URLsDeletedNotificationList urls_deleted_notifications_;
private:
@@ -201,11 +207,11 @@ class ExpireHistoryTest : public testing::Test, public HistoryBackendNotifier {
void NotifyURLsModified(const URLRows& rows) override {
urls_modified_notifications_.push_back(rows);
}
- void NotifyURLsDeleted(bool all_history,
+ void NotifyURLsDeleted(const DeletionTimeRange& time_range,
bool expired,
const URLRows& rows,
const std::set<GURL>& favicon_urls) override {
- urls_deleted_notifications_.push_back(std::make_pair(expired, rows));
+ urls_deleted_notifications_.push_back(std::tie(time_range, expired, rows));
}
};
@@ -367,9 +373,9 @@ void ExpireHistoryTest::EnsureURLInfoGone(const URLRow& row, bool expired) {
// EXPECT_FALSE(HasThumbnail(row.id()));
bool found_delete_notification = false;
- for (const auto& pair : urls_deleted_notifications_) {
- EXPECT_EQ(expired, pair.first);
- const history::URLRows& rows(pair.second);
+ for (const auto& tuple : urls_deleted_notifications_) {
+ EXPECT_EQ(expired, std::get<1>(tuple));
+ const history::URLRows& rows(std::get<2>(tuple));
history::URLRows::const_iterator it_row = std::find_if(
rows.begin(), rows.end(), history::URLRow::URLRowHasURL(row.url()));
if (it_row != rows.end()) {
@@ -616,6 +622,8 @@ TEST_F(ExpireHistoryTest, FlushRecentURLsUnstarred) {
// This should delete the last two visits.
std::set<GURL> restrict_urls;
expirer_.ExpireHistoryBetween(restrict_urls, visit_times[2], base::Time());
+ EXPECT_EQ(GetLastDeletionTimeRange().begin(), visit_times[2]);
+ EXPECT_EQ(GetLastDeletionTimeRange().end(), base::Time());
// Verify that the middle URL had its last visit deleted only.
visits.clear();
@@ -805,6 +813,7 @@ TEST_F(ExpireHistoryTest, FlushURLsForTimes) {
times.push_back(visit_times[3]);
times.push_back(visit_times[2]);
expirer_.ExpireHistoryForTimes(times);
+ EXPECT_FALSE(GetLastDeletionTimeRange().IsValid());
// Verify that the middle URL had its last visit deleted only.
visits.clear();
@@ -1022,10 +1031,15 @@ TEST_F(ExpireHistoryTest, ExpireSomeOldHistory) {
// Deleting a time range with no URLs should return false (nothing found).
EXPECT_FALSE(expirer_.ExpireSomeOldHistory(
visit_times[0] - base::TimeDelta::FromDays(100), reader, 1));
+ EXPECT_EQ(GetLastDeletionTimeRange().begin(), base::Time());
+ EXPECT_EQ(GetLastDeletionTimeRange().end(),
+ visit_times[0] - base::TimeDelta::FromDays(100));
// Deleting a time range with not up the the max results should also return
// false (there will only be one visit deleted in this range).
EXPECT_FALSE(expirer_.ExpireSomeOldHistory(visit_times[0], reader, 2));
+ EXPECT_EQ(GetLastDeletionTimeRange().begin(), base::Time());
+ EXPECT_EQ(GetLastDeletionTimeRange().end(), visit_times[0]);
// Deleting a time range with the max number of results should return true
// (max deleted).
diff --git a/chromium/components/history/core/browser/history_backend.cc b/chromium/components/history/core/browser/history_backend.cc
index 79cdaab3db0..edb7134d250 100644
--- a/chromium/components/history/core/browser/history_backend.cc
+++ b/chromium/components/history/core/browser/history_backend.cc
@@ -16,9 +16,7 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
-#include "base/feature_list.h"
#include "base/files/file_enumerator.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
#include "base/sequenced_task_runner.h"
@@ -41,9 +39,7 @@
#include "components/history/core/browser/in_memory_history_backend.h"
#include "components/history/core/browser/keyword_search_term.h"
#include "components/history/core/browser/page_usage_data.h"
-#include "components/history/core/browser/typed_url_syncable_service.h"
#include "components/history/core/browser/url_utils.h"
-#include "components/sync/driver/sync_driver_switches.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "sql/error_delegate_util.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -82,8 +78,6 @@ void RunUnlessCanceled(
closure.Run();
}
-} // namespace
-
// How long we'll wait to do a commit, so that things are batched together.
const int kCommitIntervalSeconds = 10;
@@ -98,6 +92,32 @@ const int kMaxRedirectCount = 32;
// and is deleted.
const int kExpireDaysThreshold = 90;
+bool IsFaviconBitmapExpired(base::Time last_updated) {
+ return (Time::Now() - last_updated) >
+ TimeDelta::FromDays(kFaviconRefetchDays);
+}
+
+bool AreIconTypesEquivalent(favicon_base::IconType type_a,
+ favicon_base::IconType type_b) {
+ if (type_a == type_b)
+ return true;
+
+ // Two icon types are considered 'equivalent' if both types are one of
+ // kTouchIcon, kTouchPrecomposedIcon or kWebManifestIcon.
+ const favicon_base::IconTypeSet equivalent_types = {
+ favicon_base::IconType::kTouchIcon,
+ favicon_base::IconType::kTouchPrecomposedIcon,
+ favicon_base::IconType::kWebManifestIcon};
+
+ if (equivalent_types.count(type_a) != 0 &&
+ equivalent_types.count(type_b) != 0) {
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
QueuedHistoryDBTask::QueuedHistoryDBTask(
std::unique_ptr<HistoryDBTask> task,
scoped_refptr<base::SingleThreadTaskRunner> origin_loop,
@@ -195,16 +215,12 @@ void HistoryBackend::Init(
if (!force_fail)
InitImpl(history_database_params);
delegate_->DBLoaded();
- if (base::FeatureList::IsEnabled(switches::kSyncUSSTypedURL)) {
- typed_url_sync_bridge_ = base::MakeUnique<TypedURLSyncBridge>(
- this, db_.get(),
- base::BindRepeating(&ModelTypeChangeProcessor::Create,
- base::RepeatingClosure()));
- typed_url_sync_bridge_->Init();
- } else {
- typed_url_syncable_service_ =
- base::MakeUnique<TypedUrlSyncableService>(this);
- }
+
+ typed_url_sync_bridge_ = std::make_unique<TypedURLSyncBridge>(
+ this, db_.get(),
+ base::BindRepeating(&ModelTypeChangeProcessor::Create,
+ base::RepeatingClosure()));
+ typed_url_sync_bridge_->Init();
memory_pressure_listener_.reset(new base::MemoryPressureListener(
base::Bind(&HistoryBackend::OnMemoryPressure, base::Unretained(this))));
@@ -650,7 +666,8 @@ void HistoryBackend::InitImpl(
// The frequency of this UMA will indicate how often history
// initialization fails.
UMA_HISTOGRAM_BOOLEAN("History.AttemptedToFixProfileError", kill_db);
- } // Falls through.
+ FALLTHROUGH;
+ }
case sql::INIT_TOO_NEW: {
db_diagnostics_ += sql::GetCorruptFileDiagnosticsInfo(history_name);
delegate_->NotifyProfileError(status, db_diagnostics_);
@@ -1064,10 +1081,6 @@ void HistoryBackend::QueryURL(const GURL& url,
db_->GetVisitsForURL(result->row.id(), &result->visits);
}
-TypedUrlSyncableService* HistoryBackend::GetTypedUrlSyncableService() const {
- return typed_url_syncable_service_.get();
-}
-
TypedURLSyncBridge* HistoryBackend::GetTypedURLSyncBridge() const {
return typed_url_sync_bridge_.get();
}
@@ -1536,8 +1549,7 @@ void HistoryBackend::GetLargestFaviconForURL(
return;
}
- bitmap_result.expired =
- (Time::Now() - last_updated) > TimeDelta::FromDays(kFaviconRefetchDays);
+ bitmap_result.expired = IsFaviconBitmapExpired(last_updated);
bitmap_result.fetched_because_of_page_visit = last_requested.is_null();
if (bitmap_result.is_valid())
*favicon_bitmap_result = bitmap_result;
@@ -1648,7 +1660,8 @@ void HistoryBackend::MergeFavicon(
// Expire the favicon bitmap because sync can provide incorrect
// |bitmap_data|. See crbug.com/474421 for more details. Expiring the
// favicon bitmap causes it to be redownloaded the next time that the
- // user visits any page which uses |icon_url|.
+ // user visits any page which uses |icon_url|. It also allows storing an
+ // on-demand icon along with the icon from sync.
thumbnail_db_->SetFaviconBitmap(bitmap_id_sizes[i].bitmap_id,
bitmap_data, base::Time());
replaced_bitmap = true;
@@ -1674,9 +1687,14 @@ void HistoryBackend::MergeFavicon(
thumbnail_db_->DeleteFaviconBitmap(bitmap_id_sizes[0].bitmap_id);
favicon_sizes.erase(favicon_sizes.begin());
}
+ // Set the new bitmap as expired because the bitmaps from sync/profile
+ // import/etc. are not authoritative. Expiring the favicon bitmap causes the
+ // bitmaps to be redownloaded the next time that the user visits any page
+ // which uses |icon_url|. It also allows storing an on-demand icon along
+ // with the icon from sync.
thumbnail_db_->AddFaviconBitmap(favicon_id, bitmap_data,
- FaviconBitmapType::ON_VISIT,
- base::Time::Now(), pixel_size);
+ FaviconBitmapType::ON_VISIT, base::Time(),
+ pixel_size);
favicon_sizes.push_back(pixel_size);
}
@@ -1818,18 +1836,39 @@ void HistoryBackend::CloneFaviconMappingsForPages(
}
}
+bool HistoryBackend::CanSetOnDemandFavicons(const GURL& page_url,
+ favicon_base::IconType icon_type) {
+ if (!thumbnail_db_ || !db_)
+ return false;
+
+ // We allow writing an on demand favicon of type |icon_type| only if there is
+ // no icon of such type in the DB (so that we never overwrite anything) and if
+ // all other icons are expired. This in particular allows writing an on-demand
+ // icon if there is only an icon from sync (icons from sync are immediately
+ // set as expired).
+ std::vector<IconMapping> mapping_data;
+ thumbnail_db_->GetIconMappingsForPageURL(page_url, &mapping_data);
+
+ for (const IconMapping& mapping : mapping_data) {
+ if (AreIconTypesEquivalent(mapping.icon_type, icon_type))
+ return false;
+
+ base::Time last_updated;
+ if (thumbnail_db_->GetFaviconLastUpdatedTime(mapping.icon_id,
+ &last_updated) &&
+ !IsFaviconBitmapExpired(last_updated)) {
+ return false;
+ }
+ }
+ return true;
+}
+
bool HistoryBackend::SetOnDemandFavicons(const GURL& page_url,
favicon_base::IconType icon_type,
const GURL& icon_url,
const std::vector<SkBitmap>& bitmaps) {
- if (!thumbnail_db_ || !db_)
- return false;
-
- // Verify there's no known data for the page URL.
- if (thumbnail_db_->GetIconMappingsForPageURL(page_url,
- /*mapping_data=*/nullptr)) {
+ if (!CanSetOnDemandFavicons(page_url, icon_type))
return false;
- }
return SetFaviconsImpl({page_url}, icon_type, icon_url, bitmaps,
FaviconBitmapType::ON_DEMAND);
@@ -2220,14 +2259,6 @@ bool HistoryBackend::SetFaviconMappingsForPage(
favicon_base::IconType icon_type,
favicon_base::FaviconID icon_id) {
bool mappings_changed = false;
-
- // Two icon types are considered 'equivalent' if both types are one of
- // kTouchIcon, kTouchPrecomposedIcon or kWebManifestIcon.
- const favicon_base::IconTypeSet equivalent_types = {
- favicon_base::IconType::kTouchIcon,
- favicon_base::IconType::kTouchPrecomposedIcon,
- favicon_base::IconType::kWebManifestIcon};
-
// Sets the icon mappings from |page_url| for |icon_type| to the favicon
// with |icon_id|. Mappings for |page_url| to favicons of type |icon_type|
// with FaviconID other than |icon_id| are removed. All icon mappings for
@@ -2247,9 +2278,7 @@ bool HistoryBackend::SetFaviconMappingsForPage(
continue;
}
- if (icon_type == m->icon_type ||
- (equivalent_types.count(icon_type) != 0 &&
- equivalent_types.count(m->icon_type) != 0)) {
+ if (AreIconTypesEquivalent(icon_type, m->icon_type)) {
thumbnail_db_->DeleteIconMapping(m->mapping_id);
// Removing the icon mapping may have orphaned the associated favicon so
@@ -2574,7 +2603,7 @@ void HistoryBackend::ProcessDBTask(
scoped_refptr<base::SingleThreadTaskRunner> origin_loop,
const base::CancelableTaskTracker::IsCanceledCallback& is_canceled) {
bool scheduled = !queued_history_db_tasks_.empty();
- queued_history_db_tasks_.push_back(base::MakeUnique<QueuedHistoryDBTask>(
+ queued_history_db_tasks_.push_back(std::make_unique<QueuedHistoryDBTask>(
std::move(task), origin_loop, is_canceled));
if (!scheduled)
ProcessDBTaskImpl();
@@ -2605,18 +2634,18 @@ void HistoryBackend::NotifyURLsModified(const URLRows& rows) {
delegate_->NotifyURLsModified(rows);
}
-void HistoryBackend::NotifyURLsDeleted(bool all_history,
+void HistoryBackend::NotifyURLsDeleted(const DeletionTimeRange& time_range,
bool expired,
const URLRows& rows,
const std::set<GURL>& favicon_urls) {
URLRows copied_rows(rows);
for (HistoryBackendObserver& observer : observers_) {
- observer.OnURLsDeleted(this, all_history, expired, copied_rows,
+ observer.OnURLsDeleted(this, time_range.IsAllTime(), expired, copied_rows,
favicon_urls);
}
if (delegate_)
- delegate_->NotifyURLsDeleted(all_history, expired, copied_rows,
+ delegate_->NotifyURLsDeleted(time_range, expired, copied_rows,
favicon_urls);
}
@@ -2674,7 +2703,8 @@ void HistoryBackend::DeleteAllHistory() {
// Send out the notification that history is cleared. The in-memory database
// will pick this up and clear itself.
- NotifyURLsDeleted(true, false, URLRows(), std::set<GURL>());
+ NotifyURLsDeleted(DeletionTimeRange::AllTime(), false, URLRows(),
+ std::set<GURL>());
}
bool HistoryBackend::ClearAllThumbnailHistory(
diff --git a/chromium/components/history/core/browser/history_backend.h b/chromium/components/history/core/browser/history_backend.h
index 35898bbd3fd..fa77efd2dfe 100644
--- a/chromium/components/history/core/browser/history_backend.h
+++ b/chromium/components/history/core/browser/history_backend.h
@@ -54,7 +54,6 @@ class HistoryDatabase;
struct HistoryDatabaseParams;
class HistoryDBTask;
class InMemoryHistoryBackend;
-class TypedUrlSyncableService;
class HistoryBackendHelper;
class URLDatabase;
@@ -144,7 +143,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// Notify HistoryService that some or all of the URLs have been deleted.
// The event will be forwarded to the HistoryServiceObservers in the correct
// thread.
- virtual void NotifyURLsDeleted(bool all_history,
+ virtual void NotifyURLsDeleted(const DeletionTimeRange& time_range,
bool expired,
const URLRows& deleted_rows,
const std::set<GURL>& favicon_urls) = 0;
@@ -338,6 +337,9 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
const GURL& icon_url,
const std::vector<SkBitmap>& bitmaps);
+ bool CanSetOnDemandFavicons(const GURL& page_url,
+ favicon_base::IconType icon_type);
+
void SetFaviconsOutOfDateForPage(const GURL& page_url);
void TouchOnDemandFavicon(const GURL& icon_url);
@@ -408,10 +410,6 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
bool GetURLByID(URLID url_id, URLRow* url_row);
- // Returns the syncable service for syncing typed urls. The returned service
- // is owned by |this| object.
- virtual TypedUrlSyncableService* GetTypedUrlSyncableService() const;
-
// Returns the sync bridge for syncing typed urls. The returned service
// is owned by |this| object.
TypedURLSyncBridge* GetTypedURLSyncBridge() const;
@@ -820,7 +818,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
const RedirectList& redirects,
base::Time visit_time) override;
void NotifyURLsModified(const URLRows& rows) override;
- void NotifyURLsDeleted(bool all_history,
+ void NotifyURLsDeleted(const DeletionTimeRange& time_range,
bool expired,
const URLRows& rows,
const std::set<GURL>& favicon_urls) override;
@@ -933,11 +931,9 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// List of observers
base::ObserverList<HistoryBackendObserver> observers_;
- // Used to manage syncing of the typed urls datatype. They will be null before
- // Init is called, and only one will be instantiated after Init is called
- // depending on switches::kSyncUSSTypedURL. Defined after observers_ because
+ // Used to manage syncing of the typed urls datatype. It will be null before
+ // HistoryBackend::Init is called. Defined after observers_ because
// it unregisters itself as observer during destruction.
- std::unique_ptr<TypedUrlSyncableService> typed_url_syncable_service_;
std::unique_ptr<TypedURLSyncBridge> typed_url_sync_bridge_;
DISALLOW_COPY_AND_ASSIGN(HistoryBackend);
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 0fb1d52eba3..077da13c3dd 100644
--- a/chromium/components/history/core/browser/history_backend_db_unittest.cc
+++ b/chromium/components/history/core/browser/history_backend_db_unittest.cc
@@ -986,7 +986,8 @@ TEST_F(HistoryBackendDBTest, ConfirmDownloadRowCreateAndDelete) {
db_->QueryDownloads(&results);
ASSERT_EQ(1u, results.size());
// Add a download slice and update the DB
- results[0].download_slice_info.push_back(DownloadSliceInfo(id1, 500, 100));
+ results[0].download_slice_info.push_back(
+ DownloadSliceInfo(id1, 500, 100, false));
ASSERT_TRUE(db_->UpdateDownload(results[0]));
AddDownload(id2,
@@ -1017,6 +1018,7 @@ TEST_F(HistoryBackendDBTest, ConfirmDownloadRowCreateAndDelete) {
"Select Count(*) from downloads_slices"));
EXPECT_TRUE(statement2.Step());
EXPECT_EQ(1, statement2.ColumnInt(0));
+ EXPECT_EQ(0, statement2.ColumnInt(3));
}
// Delete some rows and make sure the results are still correct.
@@ -1118,7 +1120,8 @@ TEST_F(HistoryBackendDBTest, ConfirmDownloadInProgressCleanup) {
db_->QueryDownloads(&results);
ASSERT_EQ(1u, results.size());
// Add a download slice and update the DB
- results[0].download_slice_info.push_back(DownloadSliceInfo(id, 500, 100));
+ results[0].download_slice_info.push_back(
+ DownloadSliceInfo(id, 500, 100, true));
ASSERT_TRUE(db_->UpdateDownload(results[0]));
// Confirm that they made it into the DB unchanged.
@@ -1205,7 +1208,7 @@ TEST_F(HistoryBackendDBTest, CreateAndUpdateDownloadingSlice) {
download.by_ext_id = "extension-id";
download.by_ext_name = "extension-name";
download.download_slice_info.push_back(
- DownloadSliceInfo(download.id, 500, download.received_bytes));
+ DownloadSliceInfo(download.id, 500, download.received_bytes, true));
ASSERT_TRUE(db_->CreateDownload(download));
std::vector<DownloadRow> results;
@@ -1259,7 +1262,7 @@ TEST_F(HistoryBackendDBTest, UpdateDownloadWithNewSlice) {
// Add a new slice and call UpdateDownload().
download.download_slice_info.push_back(
- DownloadSliceInfo(download.id, 500, 100));
+ DownloadSliceInfo(download.id, 500, 100, true));
ASSERT_TRUE(db_->UpdateDownload(download));
std::vector<DownloadRow> results;
db_->QueryDownloads(&results);
@@ -1300,14 +1303,14 @@ TEST_F(HistoryBackendDBTest, DownloadSliceDeletedIfEmpty) {
download.by_ext_id = "extension-id";
download.by_ext_name = "extension-name";
download.download_slice_info.push_back(
- DownloadSliceInfo(download.id, 0, download.received_bytes));
+ DownloadSliceInfo(download.id, 0, download.received_bytes, false));
download.download_slice_info.push_back(
- DownloadSliceInfo(download.id, 500, download.received_bytes));
+ DownloadSliceInfo(download.id, 500, download.received_bytes, false));
download.download_slice_info.push_back(
- DownloadSliceInfo(download.id, 100, download.received_bytes));
+ DownloadSliceInfo(download.id, 100, download.received_bytes, false));
// The empty slice will not be inserted.
download.download_slice_info.push_back(
- DownloadSliceInfo(download.id, 1500, 0));
+ DownloadSliceInfo(download.id, 1500, 0, true));
ASSERT_TRUE(db_->CreateDownload(download));
std::vector<DownloadRow> results;
@@ -1541,6 +1544,45 @@ TEST_F(HistoryBackendDBTest, MigrateVisitSegmentNames) {
EXPECT_EQ(0u, db_->GetSegmentNamed(legacy_segment_name2));
}
+// Test to verify the finished column will be correctly added to download slices
+// table during migration to version 39.
+TEST_F(HistoryBackendDBTest, MigrateDownloadSliceFinished) {
+ ASSERT_NO_FATAL_FAILURE(CreateDBVersion(38));
+ {
+ sql::Connection db;
+ ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename)));
+ }
+ CreateBackendAndDatabase();
+ DeleteBackend();
+
+ {
+ // Re-open the db for manual manipulation.
+ sql::Connection db;
+ ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename)));
+ // The version should have been updated.
+ int cur_version = HistoryDatabase::GetCurrentVersion();
+ ASSERT_LE(38, cur_version);
+ {
+ sql::Statement s(db.GetUniqueStatement(
+ "SELECT value FROM meta WHERE key = 'version'"));
+ EXPECT_TRUE(s.Step());
+ EXPECT_EQ(cur_version, s.ColumnInt(0));
+ }
+ {
+ // The downloads_slices table should have the finished column.
+ sql::Statement s1(
+ db.GetUniqueStatement("SELECT COUNT(*) from downloads_slices"));
+ EXPECT_TRUE(s1.Step());
+ EXPECT_EQ(0, s1.ColumnInt(0));
+ const char kInsertStatement[] =
+ "INSERT INTO downloads_slices "
+ "(download_id, offset, received_bytes, finished) VALUES (1, 0, 100, "
+ "1)";
+ ASSERT_TRUE(db.Execute(kInsertStatement));
+ }
+ }
+}
+
bool FilterURL(const GURL& url) {
return url.SchemeIsHTTPOrHTTPS();
}
diff --git a/chromium/components/history/core/browser/history_backend_notifier.h b/chromium/components/history/core/browser/history_backend_notifier.h
index 0c0cfd835f0..668185016ec 100644
--- a/chromium/components/history/core/browser/history_backend_notifier.h
+++ b/chromium/components/history/core/browser/history_backend_notifier.h
@@ -40,12 +40,14 @@ class HistoryBackendNotifier {
virtual void NotifyURLsModified(const URLRows& changed_urls) = 0;
// Sends notification that some or the totality of the URLs have been
- // deleted. If |all_history| is true, then all the URLs in the history have
- // been deleted, otherwise |deleted_urls| list the deleted URLs. If the URL
- // deletion is due to expiration, then |expired| is true. |favicon_urls| is
- // the list of favicon URLs that correspond to the deleted URLs (empty if
- // |all_history| is true).
- virtual void NotifyURLsDeleted(bool all_history,
+ // deleted. If time_range.IsValid() is true, all URLs between
+ // time_range.begin() and time_range.end() have been removed.
+ // If time_range.IsAllTime() is true, then all the URLs in the
+ // history have been deleted, otherwise |deleted_urls| list the deleted URLs.
+ // If the URL deletion is due to expiration, then |expired| is true.
+ // |favicon_urls| is the list of favicon URLs that correspond to the deleted
+ // URLs (empty if |time_range.IsAllTime()| is true).
+ virtual void NotifyURLsDeleted(const DeletionTimeRange& time_range,
bool expired,
const URLRows& deleted_urls,
const std::set<GURL>& favicon_urls) = 0;
diff --git a/chromium/components/history/core/browser/history_backend_unittest.cc b/chromium/components/history/core/browser/history_backend_unittest.cc
index 845232ce6fe..e1eb945adff 100644
--- a/chromium/components/history/core/browser/history_backend_unittest.cc
+++ b/chromium/components/history/core/browser/history_backend_unittest.cc
@@ -137,7 +137,7 @@ class HistoryBackendTestDelegate : public HistoryBackend::Delegate {
const RedirectList& redirects,
base::Time visit_time) override;
void NotifyURLsModified(const URLRows& changed_urls) override;
- void NotifyURLsDeleted(bool all_history,
+ void NotifyURLsDeleted(const DeletionTimeRange& time_range,
bool expired,
const URLRows& deleted_rows,
const std::set<GURL>& favicon_urls) override;
@@ -228,13 +228,14 @@ class HistoryBackendTestBase : public testing::Test {
urls_modified_notifications_.push_back(changed_urls);
}
- void NotifyURLsDeleted(bool all_history,
+ void NotifyURLsDeleted(const DeletionTimeRange& time_range,
bool expired,
const URLRows& deleted_rows,
const std::set<GURL>& favicon_urls) {
- mem_backend_->OnURLsDeleted(nullptr, all_history, expired, deleted_rows,
- favicon_urls);
- urls_deleted_notifications_.push_back(std::make_pair(all_history, expired));
+ mem_backend_->OnURLsDeleted(nullptr, time_range.IsAllTime(), expired,
+ deleted_rows, favicon_urls);
+ urls_deleted_notifications_.push_back(
+ std::make_pair(time_range.IsAllTime(), expired));
}
void NotifyKeywordSearchTermUpdated(const URLRow& row,
@@ -317,11 +318,11 @@ void HistoryBackendTestDelegate::NotifyURLsModified(
}
void HistoryBackendTestDelegate::NotifyURLsDeleted(
- bool all_history,
+ const DeletionTimeRange& time_range,
bool expired,
const URLRows& deleted_rows,
const std::set<GURL>& favicon_urls) {
- test_->NotifyURLsDeleted(all_history, expired, deleted_rows, favicon_urls);
+ test_->NotifyURLsDeleted(time_range, expired, deleted_rows, favicon_urls);
}
void HistoryBackendTestDelegate::NotifyKeywordSearchTermUpdated(
@@ -501,7 +502,8 @@ class InMemoryHistoryBackendTest : public HistoryBackendTestBase {
if (row2) rows.push_back(*row2);
if (row3) rows.push_back(*row3);
- NotifyURLsDeleted(false, false, rows, std::set<GURL>());
+ NotifyURLsDeleted(DeletionTimeRange::Invalid(), false, rows,
+ std::set<GURL>());
}
size_t GetNumberOfMatchingSearchTerms(const int keyword_id,
@@ -1371,6 +1373,7 @@ TEST_F(HistoryBackendTest, AddPageVisitSource) {
break;
case history::SOURCE_SYNCED:
sources |= 0x4;
+ break;
default:
break;
}
@@ -2220,7 +2223,7 @@ TEST_F(HistoryBackendTest, MergeFaviconPageURLNotInDB) {
kSmallSize);
// |page_url| should now be mapped to |icon_url| and the favicon bitmap should
- // not be expired.
+ // be expired.
std::vector<IconMapping> icon_mappings;
EXPECT_TRUE(backend_->thumbnail_db_->GetIconMappingsForPageURL(
page_url, &icon_mappings));
@@ -2229,7 +2232,7 @@ TEST_F(HistoryBackendTest, MergeFaviconPageURLNotInDB) {
FaviconBitmap favicon_bitmap;
EXPECT_TRUE(GetOnlyFaviconBitmap(icon_mappings[0].icon_id, &favicon_bitmap));
- EXPECT_NE(base::Time(), favicon_bitmap.last_updated);
+ EXPECT_EQ(base::Time(), favicon_bitmap.last_updated);
EXPECT_TRUE(BitmapDataEqual('a', favicon_bitmap.bitmap_data));
EXPECT_EQ(kSmallSize, favicon_bitmap.pixel_size);
@@ -2333,7 +2336,7 @@ TEST_F(HistoryBackendTest, MergeFaviconPageURLInDB) {
std::vector<FaviconBitmap> favicon_bitmaps;
EXPECT_TRUE(GetSortedFaviconBitmaps(icon_mappings[0].icon_id,
&favicon_bitmaps));
- EXPECT_NE(base::Time(), favicon_bitmaps[0].last_updated);
+ EXPECT_EQ(base::Time(), favicon_bitmaps[0].last_updated);
EXPECT_TRUE(BitmapDataEqual('c', favicon_bitmaps[0].bitmap_data));
EXPECT_EQ(kTinySize, favicon_bitmaps[0].pixel_size);
EXPECT_EQ(base::Time(), favicon_bitmaps[1].last_updated);
@@ -2363,7 +2366,7 @@ TEST_F(HistoryBackendTest, MergeFaviconPageURLInDB) {
EXPECT_EQ(kTinySize, favicon_bitmaps[0].pixel_size);
// The favicon being merged should take precedence over the preexisting
// favicon bitmaps.
- EXPECT_NE(base::Time(), favicon_bitmaps[1].last_updated);
+ EXPECT_EQ(base::Time(), favicon_bitmaps[1].last_updated);
EXPECT_TRUE(BitmapDataEqual('d', favicon_bitmaps[1].bitmap_data));
EXPECT_EQ(kSmallSize, favicon_bitmaps[1].pixel_size);
}
@@ -3860,6 +3863,7 @@ TEST_F(HistoryBackendTest, DeleteFTSIndexDatabases) {
// Tests that calling DatabaseErrorCallback doesn't cause crash. (Regression
// test for https://crbug.com/796138)
TEST_F(HistoryBackendTest, DatabaseError) {
+ backend_->SetTypedURLSyncBridgeForTest(nullptr);
EXPECT_EQ(nullptr, backend_->GetTypedURLSyncBridge());
backend_->DatabaseErrorCallback(SQLITE_CORRUPT, nullptr);
// Run loop to let any posted callbacks run before TearDown().
diff --git a/chromium/components/history/core/browser/history_database.cc b/chromium/components/history/core/browser/history_database.cc
index d0fce2b0c1f..2a983559f11 100644
--- a/chromium/components/history/core/browser/history_database.cc
+++ b/chromium/components/history/core/browser/history_database.cc
@@ -38,7 +38,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 = 38;
+const int kCurrentVersionNumber = 39;
const int kCompatibleVersionNumber = 16;
const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
const int kMaxHostsInMemory = 10000;
@@ -593,6 +593,13 @@ sql::InitStatus HistoryDatabase::EnsureCurrentVersion() {
meta_table_.SetVersionNumber(cur_version);
}
+ if (cur_version == 38) {
+ if (!MigrateDownloadSliceFinished())
+ return LogMigrationFailure(38);
+ 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_model_worker.cc b/chromium/components/history/core/browser/history_model_worker.cc
index 7ae6d603873..155e526ecd7 100644
--- a/chromium/components/history/core/browser/history_model_worker.cc
+++ b/chromium/components/history/core/browser/history_model_worker.cc
@@ -4,9 +4,9 @@
#include "components/history/core/browser/history_model_worker.h"
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "components/history/core/browser/history_db_task.h"
#include "components/history/core/browser/history_service.h"
@@ -44,7 +44,8 @@ void PostWorkerTask(
base::CancelableTaskTracker* cancelable_tracker) {
if (history_service.get()) {
history_service->ScheduleDBTask(
- base::MakeUnique<WorkerTask>(std::move(work)), cancelable_tracker);
+ FROM_HERE, std::make_unique<WorkerTask>(std::move(work)),
+ cancelable_tracker);
}
}
@@ -78,9 +79,9 @@ HistoryModelWorker::~HistoryModelWorker() {
}
void HistoryModelWorker::ScheduleWork(base::OnceClosure work) {
- ui_thread_->PostTask(FROM_HERE, base::Bind(&PostWorkerTask, history_service_,
- base::Passed(std::move(work)),
- cancelable_tracker_.get()));
+ ui_thread_->PostTask(
+ FROM_HERE, base::BindOnce(&PostWorkerTask, history_service_,
+ std::move(work), cancelable_tracker_.get()));
}
} // namespace browser_sync
diff --git a/chromium/components/history/core/browser/history_model_worker_unittest.cc b/chromium/components/history/core/browser/history_model_worker_unittest.cc
index 1877558782c..be489085f37 100644
--- a/chromium/components/history/core/browser/history_model_worker_unittest.cc
+++ b/chromium/components/history/core/browser/history_model_worker_unittest.cc
@@ -29,15 +29,17 @@ class HistoryServiceMock : public history::HistoryService {
: history_thread_(std::move(history_thread)) {}
base::CancelableTaskTracker::TaskId ScheduleDBTask(
+ const base::Location& from_here,
std::unique_ptr<history::HistoryDBTask> task,
base::CancelableTaskTracker* tracker) override {
history::HistoryDBTask* task_raw = task.get();
history_thread_->PostTaskAndReply(
- FROM_HERE,
- base::Bind(base::IgnoreResult(&history::HistoryDBTask::RunOnDBThread),
- base::Unretained(task_raw), nullptr, nullptr),
- base::Bind(&history::HistoryDBTask::DoneRunOnMainThread,
- base::Passed(std::move(task))));
+ from_here,
+ base::BindOnce(
+ base::IgnoreResult(&history::HistoryDBTask::RunOnDBThread),
+ base::Unretained(task_raw), nullptr, nullptr),
+ base::BindOnce(&history::HistoryDBTask::DoneRunOnMainThread,
+ std::move(task)));
return base::CancelableTaskTracker::kBadTaskId; // Unused.
}
@@ -78,9 +80,9 @@ class HistoryModelWorkerTest : public testing::Test {
void DoWorkAndWaitUntilDoneOnSyncThread(base::Closure work) {
sync_thread_.task_runner()->PostTask(
FROM_HERE,
- base::Bind(
+ base::BindOnce(
base::IgnoreResult(&HistoryModelWorker::DoWorkAndWaitUntilDone),
- worker_, base::Passed(ClosureToWorkCallback(work))));
+ worker_, ClosureToWorkCallback(work)));
sync_thread_.task_runner()->PostTask(
FROM_HERE, base::Bind(&base::AtomicFlag::Set,
base::Unretained(&sync_thread_unblocked_)));
diff --git a/chromium/components/history/core/browser/history_service.cc b/chromium/components/history/core/browser/history_service.cc
index 606bec34910..d10919a3946 100644
--- a/chromium/components/history/core/browser/history_service.cc
+++ b/chromium/components/history/core/browser/history_service.cc
@@ -124,8 +124,8 @@ class HistoryService::BackendDelegate : public HistoryBackend::Delegate {
std::unique_ptr<InMemoryHistoryBackend> backend) override {
// Send the backend to the history service on the main thread.
service_task_runner_->PostTask(
- FROM_HERE, base::Bind(&HistoryService::SetInMemoryBackend,
- history_service_, base::Passed(&backend)));
+ FROM_HERE, base::BindOnce(&HistoryService::SetInMemoryBackend,
+ history_service_, std::move(backend)));
}
void NotifyFaviconsChanged(const std::set<GURL>& page_urls,
@@ -152,14 +152,14 @@ class HistoryService::BackendDelegate : public HistoryBackend::Delegate {
history_service_, changed_urls));
}
- void NotifyURLsDeleted(bool all_history,
+ void NotifyURLsDeleted(const DeletionTimeRange& time_range,
bool expired,
const URLRows& deleted_rows,
const std::set<GURL>& favicon_urls) override {
service_task_runner_->PostTask(
FROM_HERE,
base::Bind(&HistoryService::NotifyURLsDeleted, history_service_,
- all_history, expired, deleted_rows, favicon_urls));
+ time_range, expired, deleted_rows, favicon_urls));
}
void NotifyKeywordSearchTermUpdated(const URLRow& row,
@@ -239,10 +239,6 @@ TypedURLSyncBridge* HistoryService::GetTypedURLSyncBridge() const {
return history_backend_->GetTypedURLSyncBridge();
}
-TypedUrlSyncableService* HistoryService::GetTypedUrlSyncableService() const {
- return history_backend_->GetTypedUrlSyncableService();
-}
-
void HistoryService::Shutdown() {
DCHECK(thread_checker_.CalledOnValidThread());
Cleanup();
@@ -306,6 +302,7 @@ void HistoryService::RemoveObserver(HistoryServiceObserver* observer) {
}
base::CancelableTaskTracker::TaskId HistoryService::ScheduleDBTask(
+ const base::Location& from_here,
std::unique_ptr<HistoryDBTask> task,
base::CancelableTaskTracker* tracker) {
DCHECK(backend_task_runner_) << "History service being called after cleanup";
@@ -317,15 +314,15 @@ base::CancelableTaskTracker::TaskId HistoryService::ScheduleDBTask(
// the current message loop so that we can forward the call to the method
// HistoryDBTask::DoneRunOnMainThread() in the correct thread.
backend_task_runner_->PostTask(
- FROM_HERE, base::Bind(&HistoryBackend::ProcessDBTask, history_backend_,
- base::Passed(&task),
- base::ThreadTaskRunnerHandle::Get(), is_canceled));
+ from_here,
+ base::BindOnce(&HistoryBackend::ProcessDBTask, history_backend_,
+ std::move(task), base::ThreadTaskRunnerHandle::Get(),
+ is_canceled));
return task_id;
}
void HistoryService::FlushForTest(const base::Closure& flushed) {
- backend_task_runner_->PostTaskAndReply(FROM_HERE,
- base::Bind(&base::DoNothing), flushed);
+ backend_task_runner_->PostTaskAndReply(FROM_HERE, base::DoNothing(), flushed);
}
void HistoryService::SetOnBackendDestroyTask(const base::Closure& task) {
@@ -661,21 +658,42 @@ void HistoryService::CloneFaviconMappingsForPages(
page_urls_to_write));
}
-void HistoryService::SetOnDemandFavicons(const GURL& page_url,
- favicon_base::IconType icon_type,
- const GURL& icon_url,
- const std::vector<SkBitmap>& bitmaps,
- base::Callback<void(bool)> callback) {
+void HistoryService::CanSetOnDemandFavicons(
+ const GURL& page_url,
+ favicon_base::IconType icon_type,
+ base::OnceCallback<void(bool)> callback) {
DCHECK(backend_task_runner_) << "History service being called after cleanup";
DCHECK(thread_checker_.CalledOnValidThread());
- if (history_client_ && !history_client_->CanAddURL(page_url))
+ if (history_client_ && !history_client_->CanAddURL(page_url)) {
+ std::move(callback).Run(false);
return;
+ }
PostTaskAndReplyWithResult(
backend_task_runner_.get(), FROM_HERE,
- base::Bind(&HistoryBackend::SetOnDemandFavicons, history_backend_,
- page_url, icon_type, icon_url, bitmaps),
- callback);
+ base::BindOnce(&HistoryBackend::CanSetOnDemandFavicons, history_backend_,
+ page_url, icon_type),
+ std::move(callback));
+}
+
+void HistoryService::SetOnDemandFavicons(
+ const GURL& page_url,
+ favicon_base::IconType icon_type,
+ const GURL& icon_url,
+ const std::vector<SkBitmap>& bitmaps,
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK(backend_task_runner_) << "History service being called after cleanup";
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (history_client_ && !history_client_->CanAddURL(page_url)) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ PostTaskAndReplyWithResult(
+ backend_task_runner_.get(), FROM_HERE,
+ base::BindOnce(&HistoryBackend::SetOnDemandFavicons, history_backend_,
+ page_url, icon_type, icon_url, bitmaps),
+ std::move(callback));
}
void HistoryService::SetFaviconsOutOfDateForPage(const GURL& page_url) {
@@ -768,13 +786,13 @@ void HistoryService::QueryDownloads(const DownloadQueryCallback& callback) {
std::vector<DownloadRow>* rows = new std::vector<DownloadRow>();
std::unique_ptr<std::vector<DownloadRow>> scoped_rows(rows);
// Beware! The first Bind() does not simply |scoped_rows.get()| because
- // base::Passed(&scoped_rows) nullifies |scoped_rows|, and compilers do not
+ // std::move(scoped_rows) nullifies |scoped_rows|, and compilers do not
// guarantee that the first Bind's arguments are evaluated before the second
// Bind's arguments.
backend_task_runner_->PostTaskAndReply(
FROM_HERE,
- base::Bind(&HistoryBackend::QueryDownloads, history_backend_, rows),
- base::Bind(callback, base::Passed(&scoped_rows)));
+ base::BindOnce(&HistoryBackend::QueryDownloads, history_backend_, rows),
+ base::BindOnce(callback, std::move(scoped_rows)));
}
// Handle updates for a particular download. This is a 'fire and forget'
@@ -1164,11 +1182,12 @@ void HistoryService::NotifyURLsModified(const URLRows& changed_urls) {
observer.OnURLsModified(this, changed_urls);
}
-void HistoryService::NotifyURLsDeleted(bool all_history,
+void HistoryService::NotifyURLsDeleted(const DeletionTimeRange& time_range,
bool expired,
const URLRows& deleted_rows,
const std::set<GURL>& favicon_urls) {
DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!time_range.IsAllTime() || deleted_rows.empty());
if (!backend_task_runner_)
return;
@@ -1181,7 +1200,7 @@ void HistoryService::NotifyURLsDeleted(bool all_history,
// respectful of privacy and never tell the user something is gone when it
// isn't. Therefore, we update the delete URLs after the fact.
if (visit_delegate_) {
- if (all_history) {
+ if (time_range.IsAllTime()) {
visit_delegate_->DeleteAllURLs();
} else {
std::vector<GURL> urls;
@@ -1193,7 +1212,9 @@ void HistoryService::NotifyURLsDeleted(bool all_history,
}
for (HistoryServiceObserver& observer : observers_) {
- observer.OnURLsDeleted(this, all_history, expired, deleted_rows,
+ observer.OnURLsDeleted(this, time_range.IsAllTime(), expired, deleted_rows,
+ favicon_urls);
+ observer.OnURLsDeleted(this, time_range, expired, deleted_rows,
favicon_urls);
}
}
diff --git a/chromium/components/history/core/browser/history_service.h b/chromium/components/history/core/browser/history_service.h
index 43d8f53fbec..d0e1a2805fb 100644
--- a/chromium/components/history/core/browser/history_service.h
+++ b/chromium/components/history/core/browser/history_service.h
@@ -18,6 +18,7 @@
#include "base/callback_list.h"
#include "base/containers/flat_set.h"
#include "base/files/file_path.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -35,7 +36,6 @@
#include "components/history/core/browser/history_types.h"
#include "components/history/core/browser/keyword_id.h"
#include "components/history/core/browser/typed_url_sync_bridge.h"
-#include "components/history/core/browser/typed_url_syncable_service.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/sync/model/syncable_service.h"
#include "sql/init_status.h"
@@ -136,11 +136,6 @@ class HistoryService : public syncer::SyncableService, public KeyedService {
// returned bridge is intended to be accessed only via the history thread.
TypedURLSyncBridge* GetTypedURLSyncBridge() const;
- // Returns a pointer to the TypedUrlSyncableService owned by HistoryBackend.
- // This method should only be called from the history thread, because the
- // returned service is intended to be accessed only via the history thread.
- TypedUrlSyncableService* GetTypedUrlSyncableService() const;
-
// KeyedService:
void Shutdown() override;
@@ -468,6 +463,7 @@ class HistoryService : public syncer::SyncableService, public KeyedService {
// Schedules a HistoryDBTask for running on the history backend thread. See
// 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,
base::CancelableTaskTracker* tracker);
@@ -615,7 +611,7 @@ class HistoryService : public syncer::SyncableService, public KeyedService {
// |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.
- void NotifyURLsDeleted(bool all_history,
+ void NotifyURLsDeleted(const DeletionTimeRange& time_range,
bool expired,
const URLRows& deleted_rows,
const std::set<GURL>& favicon_urls);
@@ -771,9 +767,16 @@ class HistoryService : public syncer::SyncableService, public KeyedService {
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|.
+ 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 there is an existing cached favicon for *any* type
- // for |page_url|.
+ // 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).
@@ -793,7 +796,7 @@ class HistoryService : public syncer::SyncableService, public KeyedService {
favicon_base::IconType icon_type,
const GURL& icon_url,
const std::vector<SkBitmap>& bitmaps,
- base::Callback<void(bool)> callback);
+ base::OnceCallback<void(bool)> callback);
// Used by the FaviconService to mark the favicon for the page as being out
// of date.
diff --git a/chromium/components/history/core/browser/history_service_observer.h b/chromium/components/history/core/browser/history_service_observer.h
index 4e4438735b1..3220ce56e47 100644
--- a/chromium/components/history/core/browser/history_service_observer.h
+++ b/chromium/components/history/core/browser/history_service_observer.h
@@ -47,12 +47,29 @@ class HistoryServiceObserver {
// |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.
+ // DEPRECATED, use OnURLsDeleted() with |time_range| parameter.
+ // TODO(dullweber): Migrate observers to new OnURLsDeleted() method.
virtual void OnURLsDeleted(HistoryService* history_service,
bool all_history,
bool expired,
const URLRows& deleted_rows,
const std::set<GURL>& favicon_urls) {}
+ // Called when one or more of URLs are deleted.
+ //
+ // |time_range| If time_range.IsValid() is true, all URLs between
+ // time_range.begin() and time_range.end() have been removed.
+ // If time_range.IsAllTime() is true, all URLs are deleted and
+ // |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.
+ virtual void OnURLsDeleted(HistoryService* history_service,
+ const DeletionTimeRange& time_range,
+ bool expired,
+ const URLRows& deleted_rows,
+ const std::set<GURL>& favicon_urls) {}
+
// Is called to notify when |history_service| has finished loading.
virtual void OnHistoryServiceLoaded(HistoryService* history_service) {}
diff --git a/chromium/components/history/core/browser/history_service_unittest.cc b/chromium/components/history/core/browser/history_service_unittest.cc
index 5aff0e5f7b5..4ed089e1f4a 100644
--- a/chromium/components/history/core/browser/history_service_unittest.cc
+++ b/chromium/components/history/core/browser/history_service_unittest.cc
@@ -35,8 +35,6 @@
#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/attachments/attachment_id.h"
-#include "components/sync/model/attachments/attachment_service_proxy_for_test.h"
#include "components/sync/model/fake_sync_change_processor.h"
#include "components/sync/model/sync_change.h"
#include "components/sync/model/sync_change_processor.h"
@@ -629,6 +627,7 @@ TEST_F(HistoryServiceTest, HistoryDBTask) {
int invoke_count = 0;
bool done_invoked = false;
history_service_->ScheduleDBTask(
+ FROM_HERE,
std::unique_ptr<history::HistoryDBTask>(
new HistoryDBTaskImpl(&invoke_count, &done_invoked)),
&task_tracker);
@@ -649,6 +648,7 @@ TEST_F(HistoryServiceTest, HistoryDBTaskCanceled) {
int invoke_count = 0;
bool done_invoked = false;
history_service_->ScheduleDBTask(
+ FROM_HERE,
std::unique_ptr<history::HistoryDBTask>(
new HistoryDBTaskImpl(&invoke_count, &done_invoked)),
&task_tracker);
@@ -752,12 +752,8 @@ TEST_F(HistoryServiceTest, ProcessGlobalIdDeleteDirective) {
.ToInternalValue());
global_id_directive->set_start_time_usec(3);
global_id_directive->set_end_time_usec(10);
- directives.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- entity_specs,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ directives.push_back(
+ syncer::SyncData::CreateRemoteData(1, entity_specs, base::Time()));
// 2nd directive.
global_id_directive->Clear();
@@ -766,12 +762,8 @@ TEST_F(HistoryServiceTest, ProcessGlobalIdDeleteDirective) {
.ToInternalValue());
global_id_directive->set_start_time_usec(13);
global_id_directive->set_end_time_usec(19);
- directives.push_back(syncer::SyncData::CreateRemoteData(
- 2,
- entity_specs,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ directives.push_back(
+ syncer::SyncData::CreateRemoteData(2, entity_specs, base::Time()));
syncer::FakeSyncChangeProcessor change_processor;
EXPECT_FALSE(history_service_
@@ -838,23 +830,15 @@ TEST_F(HistoryServiceTest, 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(
- 1,
- entity_specs,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ directives.push_back(
+ syncer::SyncData::CreateRemoteData(1, entity_specs, base::Time()));
// 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(
- 2,
- entity_specs,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ directives.push_back(
+ syncer::SyncData::CreateRemoteData(2, entity_specs, base::Time()));
syncer::FakeSyncChangeProcessor change_processor;
EXPECT_FALSE(history_service_
diff --git a/chromium/components/history/core/browser/history_types.cc b/chromium/components/history/core/browser/history_types.cc
index 50ce78be147..cd5113a8f99 100644
--- a/chromium/components/history/core/browser/history_types.cc
+++ b/chromium/components/history/core/browser/history_types.cc
@@ -357,4 +357,22 @@ void ExpireHistoryArgs::SetTimeRangeForOneDay(base::Time time) {
end_time = (begin_time + base::TimeDelta::FromHours(36)).LocalMidnight();
}
+// DeletionTimeRange ----------------------------------------------------------
+
+DeletionTimeRange DeletionTimeRange::Invalid() {
+ return DeletionTimeRange();
+}
+
+DeletionTimeRange DeletionTimeRange::AllTime() {
+ return DeletionTimeRange(base::Time(), base::Time::Max());
+}
+
+bool DeletionTimeRange::IsValid() const {
+ return end_.is_null() || begin_ <= end_;
+}
+
+bool DeletionTimeRange::IsAllTime() const {
+ return begin_.is_null() && (end_.is_null() || end_.is_max());
+}
+
} // namespace history
diff --git a/chromium/components/history/core/browser/history_types.h b/chromium/components/history/core/browser/history_types.h
index 4f9c2cd6c6c..ff27b0d7406 100644
--- a/chromium/components/history/core/browser/history_types.h
+++ b/chromium/components/history/core/browser/history_types.h
@@ -583,6 +583,45 @@ struct ExpireHistoryArgs {
base::Time end_time;
};
+// 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 {
+ public:
+ static DeletionTimeRange Invalid();
+
+ static DeletionTimeRange AllTime();
+
+ DeletionTimeRange(base::Time begin, base::Time end)
+ : begin_(begin), end_(end) {
+ DCHECK(IsValid());
+ }
+
+ base::Time begin() const {
+ DCHECK(IsValid());
+ return begin_;
+ }
+
+ base::Time end() const {
+ DCHECK(IsValid());
+ return end_;
+ }
+
+ bool IsValid() const;
+
+ // Returns true if this time range covers history from the beginning of time.
+ bool IsAllTime() const;
+
+ private:
+ // Creates an invalid time range by assigning impossible start and end times.
+ DeletionTimeRange() : begin_(base::Time::Max()), end_(base::Time::Min()) {}
+
+ // Begin of a history deletion.
+ base::Time begin_;
+ // End of a history deletion.
+ base::Time end_;
+};
+
} // namespace history
#endif // COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_TYPES_H_
diff --git a/chromium/components/history/core/browser/history_types_unittest.cc b/chromium/components/history/core/browser/history_types_unittest.cc
index 27ecabb116a..4391e28b0d9 100644
--- a/chromium/components/history/core/browser/history_types_unittest.cc
+++ b/chromium/components/history/core/browser/history_types_unittest.cc
@@ -117,4 +117,24 @@ TEST(HistoryQueryResult, ResultDeleteURL) {
EXPECT_FALSE(results.MatchesForURL(url2, nullptr));
}
+// Tests time ranges.
+TEST(HistoryTypes, DeletionTimeRange) {
+ auto invalid = DeletionTimeRange::Invalid();
+ EXPECT_FALSE(invalid.IsValid());
+ EXPECT_FALSE(invalid.IsAllTime());
+
+ auto some_hours = DeletionTimeRange(
+ base::Time::Now() - base::TimeDelta::FromHours(1), base::Time::Now());
+ EXPECT_TRUE(some_hours.IsValid());
+ EXPECT_FALSE(some_hours.IsAllTime());
+
+ auto all_time = DeletionTimeRange::AllTime();
+ EXPECT_TRUE(all_time.IsValid());
+ EXPECT_TRUE(all_time.IsAllTime());
+
+ auto another_all_time = DeletionTimeRange(base::Time(), base::Time());
+ EXPECT_TRUE(another_all_time.IsValid());
+ EXPECT_TRUE(another_all_time.IsAllTime());
+}
+
} // namespace history
diff --git a/chromium/components/history/core/browser/thumbnail_database.cc b/chromium/components/history/core/browser/thumbnail_database.cc
index 235f34c0aa0..26307b9de72 100644
--- a/chromium/components/history/core/browser/thumbnail_database.cc
+++ b/chromium/components/history/core/browser/thumbnail_database.cc
@@ -427,7 +427,7 @@ ThumbnailDatabase::GetOldOnDemandFavicons(base::Time threshold) {
"JOIN icon_mapping ON (icon_mapping.icon_id = favicon_bitmaps.icon_id) "
"WHERE (favicon_bitmaps.last_requested > 0 AND "
" favicon_bitmaps.last_requested < ?)"));
- old_icons.BindInt64(0, threshold.ToInternalValue());
+ old_icons.BindInt64(0, threshold.ToDeltaSinceWindowsEpoch().InMicroseconds());
std::map<favicon_base::FaviconID, IconMappingsForExpiry> icon_mappings;
@@ -482,8 +482,8 @@ bool ThumbnailDatabase::GetFaviconBitmaps(
FaviconBitmap favicon_bitmap;
favicon_bitmap.bitmap_id = statement.ColumnInt64(0);
favicon_bitmap.icon_id = icon_id;
- favicon_bitmap.last_updated =
- base::Time::FromInternalValue(statement.ColumnInt64(1));
+ favicon_bitmap.last_updated = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(statement.ColumnInt64(1)));
if (statement.ColumnByteLength(2) > 0) {
scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes());
statement.ColumnBlobAsVector(2, &data->data());
@@ -491,8 +491,8 @@ bool ThumbnailDatabase::GetFaviconBitmaps(
}
favicon_bitmap.pixel_size = gfx::Size(statement.ColumnInt(3),
statement.ColumnInt(4));
- favicon_bitmap.last_requested =
- base::Time::FromInternalValue(statement.ColumnInt64(5));
+ favicon_bitmap.last_requested = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(statement.ColumnInt64(5)));
favicon_bitmaps->push_back(favicon_bitmap);
}
return result;
@@ -513,8 +513,10 @@ bool ThumbnailDatabase::GetFaviconBitmap(
if (!statement.Step())
return false;
- if (last_updated)
- *last_updated = base::Time::FromInternalValue(statement.ColumnInt64(0));
+ if (last_updated) {
+ *last_updated = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(statement.ColumnInt64(0)));
+ }
if (png_icon_data && statement.ColumnByteLength(1) > 0) {
scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes());
@@ -527,8 +529,10 @@ bool ThumbnailDatabase::GetFaviconBitmap(
statement.ColumnInt(3));
}
- if (last_requested)
- *last_requested = base::Time::FromInternalValue(statement.ColumnInt64(4));
+ if (last_requested) {
+ *last_requested = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(statement.ColumnInt64(4)));
+ }
return true;
}
@@ -557,12 +561,16 @@ FaviconBitmapID ThumbnailDatabase::AddFaviconBitmap(
// On-visit bitmaps:
// - keep track of last_updated: last write time is used for expiration;
// - always have last_requested==0: no need to keep track of last read time.
- statement.BindInt64(2, type == ON_VISIT ? time.ToInternalValue() : 0);
+ statement.BindInt64(2, type == ON_VISIT
+ ? time.ToDeltaSinceWindowsEpoch().InMicroseconds()
+ : 0);
// On-demand bitmaps:
// - always have last_updated==0: last write time is not stored as they are
// always expired and thus ready to be replaced by ON_VISIT icons;
// - keep track of last_requested: last read time is used for cache eviction.
- statement.BindInt64(3, type == ON_DEMAND ? time.ToInternalValue() : 0);
+ statement.BindInt64(3, type == ON_DEMAND
+ ? time.ToDeltaSinceWindowsEpoch().InMicroseconds()
+ : 0);
statement.BindInt(4, pixel_size.width());
statement.BindInt(5, pixel_size.height());
@@ -590,7 +598,7 @@ bool ThumbnailDatabase::SetFaviconBitmap(
} else {
statement.BindNull(0);
}
- statement.BindInt64(1, time.ToInternalValue());
+ statement.BindInt64(1, time.ToDeltaSinceWindowsEpoch().InMicroseconds());
statement.BindInt64(2, 0);
statement.BindInt64(3, bitmap_id);
@@ -608,7 +616,7 @@ bool ThumbnailDatabase::SetFaviconBitmapLastUpdateTime(
db_.GetCachedStatement(SQL_FROM_HERE,
"UPDATE favicon_bitmaps SET last_updated=?, "
"last_requested=? WHERE id=?"));
- statement.BindInt64(0, time.ToInternalValue());
+ statement.BindInt64(0, time.ToDeltaSinceWindowsEpoch().InMicroseconds());
statement.BindInt64(1, 0);
statement.BindInt64(2, bitmap_id);
return statement.Run();
@@ -635,9 +643,10 @@ bool ThumbnailDatabase::TouchOnDemandFavicon(const GURL& icon_url,
SQL_FROM_HERE,
"UPDATE favicon_bitmaps SET last_requested=? WHERE icon_id=? AND "
"last_requested>0 AND last_requested<=?"));
- statement.BindInt64(0, time.ToInternalValue());
+ statement.BindInt64(0, time.ToDeltaSinceWindowsEpoch().InMicroseconds());
statement.BindInt64(1, icon_id);
- statement.BindInt64(2, max_time.ToInternalValue());
+ statement.BindInt64(2,
+ max_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
if (!statement.Run())
return false;
}
@@ -660,6 +669,28 @@ bool ThumbnailDatabase::SetFaviconOutOfDate(favicon_base::FaviconID icon_id) {
return statement.Run();
}
+bool ThumbnailDatabase::GetFaviconLastUpdatedTime(
+ favicon_base::FaviconID icon_id,
+ base::Time* last_updated) {
+ sql::Statement statement(db_.GetCachedStatement(
+ SQL_FROM_HERE,
+ "SELECT MAX(last_updated) FROM favicon_bitmaps WHERE icon_id=?"));
+ statement.BindInt64(0, icon_id);
+
+ if (!statement.Step())
+ return false;
+
+ // Return false also if there there is no bitmap with |icon_id|.
+ if (statement.ColumnType(0) == sql::COLUMN_TYPE_NULL)
+ return false;
+
+ if (last_updated) {
+ *last_updated = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(statement.ColumnInt64(0)));
+ }
+ return true;
+}
+
favicon_base::FaviconID ThumbnailDatabase::GetFaviconIDForFaviconURL(
const GURL& icon_url,
favicon_base::IconType icon_type) {
diff --git a/chromium/components/history/core/browser/thumbnail_database.h b/chromium/components/history/core/browser/thumbnail_database.h
index 29ca88b12ea..5196835f54a 100644
--- a/chromium/components/history/core/browser/thumbnail_database.h
+++ b/chromium/components/history/core/browser/thumbnail_database.h
@@ -137,6 +137,11 @@ class ThumbnailDatabase {
// of the bitmaps for |icon_id| to be out of date.
bool SetFaviconOutOfDate(favicon_base::FaviconID icon_id);
+ // Retrieves the newest |last_updated| time across all bitmaps for |icon_id|.
+ // Returns true if successful and if there is at least one bitmap.
+ bool GetFaviconLastUpdatedTime(favicon_base::FaviconID icon_id,
+ base::Time* last_updated);
+
// Mark all bitmaps of type ON_DEMAND at |icon_url| as requested at |time|.
// This postpones their automatic eviction from the database. Not all calls
// end up in a write into the DB:
diff --git a/chromium/components/history/core/browser/thumbnail_database_unittest.cc b/chromium/components/history/core/browser/thumbnail_database_unittest.cc
index 0b7d696d10a..4a3f3d793bd 100644
--- a/chromium/components/history/core/browser/thumbnail_database_unittest.cc
+++ b/chromium/components/history/core/browser/thumbnail_database_unittest.cc
@@ -290,6 +290,49 @@ TEST_F(ThumbnailDatabaseTest, AddFaviconBitmapCreatesCorrectTimestamps) {
EXPECT_EQ(base::Time(), last_requested);
}
+TEST_F(ThumbnailDatabaseTest,
+ GetFaviconLastUpdatedTimeReturnsFalseForNoBitmaps) {
+ ThumbnailDatabase db(nullptr);
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_));
+ db.BeginTransaction();
+
+ GURL url("http://google.com");
+ favicon_base::FaviconID icon =
+ db.AddFavicon(url, favicon_base::IconType::kFavicon);
+ ASSERT_NE(0, icon);
+
+ base::Time last_updated;
+ ASSERT_FALSE(db.GetFaviconLastUpdatedTime(icon, &last_updated));
+}
+
+TEST_F(ThumbnailDatabaseTest, GetFaviconLastUpdatedTimeReturnsMaxTime) {
+ ThumbnailDatabase db(nullptr);
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_name_));
+ db.BeginTransaction();
+
+ base::Time add_time1;
+ ASSERT_TRUE(
+ base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &add_time1));
+ base::Time add_time2 = add_time1 - base::TimeDelta::FromSeconds(1);
+ std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1));
+ scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data));
+
+ GURL url("http://google.com");
+ favicon_base::FaviconID icon =
+ db.AddFavicon(url, favicon_base::IconType::kFavicon);
+ ASSERT_NE(0, icon);
+ FaviconBitmapID bitmap1 = db.AddFaviconBitmap(
+ icon, favicon, FaviconBitmapType::ON_VISIT, add_time1, gfx::Size());
+ ASSERT_NE(0, bitmap1);
+ FaviconBitmapID bitmap2 = db.AddFaviconBitmap(
+ icon, favicon, FaviconBitmapType::ON_VISIT, add_time2, gfx::Size());
+ ASSERT_NE(0, bitmap2);
+
+ base::Time last_updated;
+ ASSERT_TRUE(db.GetFaviconLastUpdatedTime(icon, &last_updated));
+ EXPECT_EQ(add_time1, last_updated);
+}
+
TEST_F(ThumbnailDatabaseTest, TouchUpdatesOnDemandFavicons) {
ThumbnailDatabase db(nullptr);
ASSERT_EQ(sql::INIT_OK, db.Init(file_name_));
@@ -963,15 +1006,6 @@ TEST_F(ThumbnailDatabaseTest, Version8) {
}
TEST_F(ThumbnailDatabaseTest, Recovery) {
- // This code tests the recovery module in concert with Chromium's
- // custom recover virtual table. Under USE_SYSTEM_SQLITE, this is
- // not available. This is detected dynamically because corrupt
- // databases still need to be handled, perhaps by Raze(), and the
- // recovery module is an obvious layer to abstract that to.
- // TODO(shess): Handle that case for real!
- if (!sql::Recovery::FullRecoverySupported())
- return;
-
// Create an example database.
{
EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "Favicons.v8.sql"));
@@ -1084,15 +1118,6 @@ TEST_F(ThumbnailDatabaseTest, Recovery) {
}
TEST_F(ThumbnailDatabaseTest, Recovery7) {
- // This code tests the recovery module in concert with Chromium's
- // custom recover virtual table. Under USE_SYSTEM_SQLITE, this is
- // not available. This is detected dynamically because corrupt
- // databases still need to be handled, perhaps by Raze(), and the
- // recovery module is an obvious layer to abstract that to.
- // TODO(shess): Handle that case for real!
- if (!sql::Recovery::FullRecoverySupported())
- return;
-
// Create an example database without loading into ThumbnailDatabase
// (which would upgrade it).
EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "Favicons.v7.sql"));
@@ -1188,10 +1213,6 @@ TEST_F(ThumbnailDatabaseTest, Recovery7) {
}
TEST_F(ThumbnailDatabaseTest, Recovery6) {
- // TODO(shess): See comment at top of Recovery test.
- if (!sql::Recovery::FullRecoverySupported())
- return;
-
// Create an example database without loading into ThumbnailDatabase
// (which would upgrade it).
EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "Favicons.v6.sql"));
@@ -1236,10 +1257,6 @@ TEST_F(ThumbnailDatabaseTest, Recovery6) {
}
TEST_F(ThumbnailDatabaseTest, Recovery5) {
- // TODO(shess): See comment at top of Recovery test.
- if (!sql::Recovery::FullRecoverySupported())
- return;
-
// Create an example database without loading into ThumbnailDatabase
// (which would upgrade it).
EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "Favicons.v5.sql"));
diff --git a/chromium/components/history/core/browser/top_sites_backend.cc b/chromium/components/history/core/browser/top_sites_backend.cc
index b71945d2457..66ddfc7ee8f 100644
--- a/chromium/components/history/core/browser/top_sites_backend.cc
+++ b/chromium/components/history/core/browser/top_sites_backend.cc
@@ -77,8 +77,8 @@ void TopSitesBackend::ResetDatabase() {
void TopSitesBackend::DoEmptyRequest(const base::Closure& reply,
base::CancelableTaskTracker* tracker) {
- tracker->PostTaskAndReply(db_task_runner_.get(), FROM_HERE,
- base::Bind(&base::DoNothing), reply);
+ tracker->PostTaskAndReply(db_task_runner_.get(), FROM_HERE, base::DoNothing(),
+ reply);
}
TopSitesBackend::~TopSitesBackend() {
diff --git a/chromium/components/history/core/browser/top_sites_database_unittest.cc b/chromium/components/history/core/browser/top_sites_database_unittest.cc
index 4788bc197fd..f05ecb81224 100644
--- a/chromium/components/history/core/browser/top_sites_database_unittest.cc
+++ b/chromium/components/history/core/browser/top_sites_database_unittest.cc
@@ -131,10 +131,6 @@ TEST_F(TopSitesDatabaseTest, Version3) {
// Version 1 is deprecated, the resulting schema should be current,
// with no data.
TEST_F(TopSitesDatabaseTest, Recovery1) {
- // Recovery module only supports some platforms at this time.
- if (!sql::Recovery::FullRecoverySupported())
- return;
-
// Create an example database.
EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "TopSites.v1.sql"));
@@ -166,10 +162,6 @@ TEST_F(TopSitesDatabaseTest, Recovery1) {
}
TEST_F(TopSitesDatabaseTest, Recovery2) {
- // Recovery module only supports some platforms at this time.
- if (!sql::Recovery::FullRecoverySupported())
- return;
-
// Create an example database.
EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "TopSites.v2.sql"));
@@ -201,10 +193,6 @@ TEST_F(TopSitesDatabaseTest, Recovery2) {
}
TEST_F(TopSitesDatabaseTest, Recovery3) {
- // Recovery module only supports some platforms at this time.
- if (!sql::Recovery::FullRecoverySupported())
- return;
-
// Create an example database.
EXPECT_TRUE(CreateDatabaseFromSQL(file_name_, "TopSites.v3.sql"));
diff --git a/chromium/components/history/core/browser/top_sites_impl.cc b/chromium/components/history/core/browser/top_sites_impl.cc
index 908fc22844a..0ed5797f860 100644
--- a/chromium/components/history/core/browser/top_sites_impl.cc
+++ b/chromium/components/history/core/browser/top_sites_impl.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
#include <algorithm>
+#include <memory>
#include <set>
#include <utility>
@@ -14,7 +15,6 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/md5.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
@@ -118,8 +118,8 @@ TopSitesImpl::TopSitesImpl(PrefService* pref_service,
const PrepopulatedPageList& prepopulated_pages,
const CanAddURLToHistoryFn& can_add_url_to_history)
: backend_(nullptr),
- cache_(base::MakeUnique<TopSitesCache>()),
- thread_safe_cache_(base::MakeUnique<TopSitesCache>()),
+ cache_(std::make_unique<TopSitesCache>()),
+ thread_safe_cache_(std::make_unique<TopSitesCache>()),
prepopulated_pages_(prepopulated_pages),
pref_service_(pref_service),
history_service_(history_service),
@@ -281,7 +281,7 @@ bool TopSitesImpl::HasBlacklistedItems() const {
void TopSitesImpl::AddBlacklistedURL(const GURL& url) {
DCHECK(thread_checker_.CalledOnValidThread());
- auto dummy = base::MakeUnique<base::Value>();
+ auto dummy = std::make_unique<base::Value>();
{
DictionaryPrefUpdate update(pref_service_, kMostVisitedURLsBlacklist);
base::DictionaryValue* blacklist = update.Get();
diff --git a/chromium/components/history/core/browser/typed_url_data_type_controller.cc b/chromium/components/history/core/browser/typed_url_data_type_controller.cc
deleted file mode 100644
index 2fc2c86ab21..00000000000
--- a/chromium/components/history/core/browser/typed_url_data_type_controller.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/history/core/browser/typed_url_data_type_controller.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/metrics/histogram.h"
-#include "components/history/core/browser/history_db_task.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/prefs/pref_service.h"
-#include "components/sync/driver/sync_client.h"
-
-namespace browser_sync {
-
-namespace {
-
-// The history service exposes a special non-standard task API which calls back
-// once a task has been dispatched, so we have to build a special wrapper around
-// the tasks we want to run.
-class RunTaskOnHistoryThread : public history::HistoryDBTask {
- public:
- explicit RunTaskOnHistoryThread(const base::Closure& task)
- : task_(new base::Closure(task)) {}
-
- bool RunOnDBThread(history::HistoryBackend* backend,
- history::HistoryDatabase* db) override {
- // Invoke the task, then free it immediately so we don't keep a reference
- // around all the way until DoneRunOnMainThread() is invoked back on the
- // main thread - we want to release references as soon as possible to avoid
- // keeping them around too long during shutdown.
- task_->Run();
- task_.reset();
- return true;
- }
-
- void DoneRunOnMainThread() override {}
-
- protected:
- ~RunTaskOnHistoryThread() override {}
-
- std::unique_ptr<base::Closure> task_;
-};
-
-} // namespace
-
-TypedUrlDataTypeController::TypedUrlDataTypeController(
- const base::Closure& dump_stack,
- syncer::SyncClient* sync_client,
- const char* history_disabled_pref_name)
- : AsyncDirectoryTypeController(syncer::TYPED_URLS,
- dump_stack,
- sync_client,
- syncer::GROUP_HISTORY,
- nullptr),
- history_disabled_pref_name_(history_disabled_pref_name),
- sync_client_(sync_client) {
- pref_registrar_.Init(sync_client->GetPrefService());
- pref_registrar_.Add(
- history_disabled_pref_name_,
- base::Bind(
- &TypedUrlDataTypeController::OnSavingBrowserHistoryDisabledChanged,
- base::AsWeakPtr(this)));
-}
-
-bool TypedUrlDataTypeController::ReadyForStart() const {
- DCHECK(CalledOnValidThread());
- return !sync_client_->GetPrefService()->GetBoolean(
- history_disabled_pref_name_);
-}
-
-void TypedUrlDataTypeController::OnSavingBrowserHistoryDisabledChanged() {
- DCHECK(CalledOnValidThread());
- if (sync_client_->GetPrefService()->GetBoolean(history_disabled_pref_name_)) {
- // We've turned off history persistence, so if we are running,
- // generate an unrecoverable error. This can be fixed by restarting
- // Chrome (on restart, typed urls will not be a registered type).
- if (state() != NOT_RUNNING && state() != STOPPING) {
- PostTaskOnModelThread(
- FROM_HERE,
- base::Bind(&syncer::DataTypeErrorHandler::OnUnrecoverableError,
- base::Passed(CreateErrorHandler()),
- syncer::SyncError(
- FROM_HERE, syncer::SyncError::DATATYPE_POLICY_ERROR,
- "History saving is now disabled by policy.", type())));
- }
- }
-}
-
-bool TypedUrlDataTypeController::PostTaskOnModelThread(
- const base::Location& from_here,
- const base::Closure& task) {
- DCHECK(CalledOnValidThread());
- history::HistoryService* history = sync_client_->GetHistoryService();
- if (history) {
- history->ScheduleDBTask(std::unique_ptr<history::HistoryDBTask>(
- new RunTaskOnHistoryThread(task)),
- &task_tracker_);
- return true;
- } else {
- // History must be disabled - don't start.
- LOG(WARNING) << "Cannot access history service - disabling typed url sync";
- return false;
- }
-}
-
-TypedUrlDataTypeController::~TypedUrlDataTypeController() {}
-
-} // namespace browser_sync
diff --git a/chromium/components/history/core/browser/typed_url_data_type_controller.h b/chromium/components/history/core/browser/typed_url_data_type_controller.h
deleted file mode 100644
index 1883652170d..00000000000
--- a/chromium/components/history/core/browser/typed_url_data_type_controller.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_DATA_TYPE_CONTROLLER_H__
-#define COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_DATA_TYPE_CONTROLLER_H__
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/task/cancelable_task_tracker.h"
-#include "components/prefs/pref_change_registrar.h"
-#include "components/sync/driver/async_directory_type_controller.h"
-#include "components/sync/driver/sync_api_component_factory.h"
-
-namespace browser_sync {
-
-// A class that manages the startup and shutdown of typed_url sync.
-class TypedUrlDataTypeController : public syncer::AsyncDirectoryTypeController {
- public:
- // |dump_stack| is called when an unrecoverable error occurs.
- TypedUrlDataTypeController(const base::Closure& dump_stack,
- syncer::SyncClient* sync_client,
- const char* history_disabled_pref_name);
- ~TypedUrlDataTypeController() override;
-
- // AsyncDirectoryTypeController implementation.
- bool ReadyForStart() const override;
-
- protected:
- // AsyncDirectoryTypeController implementation.
- bool PostTaskOnModelThread(const base::Location& from_here,
- const base::Closure& task) override;
-
- private:
- void OnSavingBrowserHistoryDisabledChanged();
-
- // Name of the pref that indicates whether saving history is disabled.
- const char* history_disabled_pref_name_;
-
- PrefChangeRegistrar pref_registrar_;
-
- // Helper object to make sure we don't leave tasks running on the history
- // thread.
- base::CancelableTaskTracker task_tracker_;
-
- syncer::SyncClient* const sync_client_;
-
- DISALLOW_COPY_AND_ASSIGN(TypedUrlDataTypeController);
-};
-
-} // namespace browser_sync
-
-#endif // COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_DATA_TYPE_CONTROLLER_H__
diff --git a/chromium/components/history/core/browser/typed_url_model_type_controller.cc b/chromium/components/history/core/browser/typed_url_model_type_controller.cc
index b1587826449..33fc6d462b4 100644
--- a/chromium/components/history/core/browser/typed_url_model_type_controller.cc
+++ b/chromium/components/history/core/browser/typed_url_model_type_controller.cc
@@ -78,7 +78,7 @@ void TypedURLModelTypeController::PostBridgeTask(const base::Location& location,
}
history->ScheduleDBTask(
- std::make_unique<RunTaskOnHistoryThread>(std::move(task)),
+ FROM_HERE, std::make_unique<RunTaskOnHistoryThread>(std::move(task)),
&task_tracker_);
}
@@ -89,8 +89,8 @@ void TypedURLModelTypeController::OnSavingBrowserHistoryDisabledChanged() {
// generate an unrecoverable error. This can be fixed by restarting
// Chrome (on restart, typed urls will not be a registered type).
if (state() != NOT_RUNNING && state() != STOPPING) {
- ReportModelError(syncer::ModelError(
- FROM_HERE, "History saving is now disabled by policy."));
+ ReportModelError(
+ {FROM_HERE, "History saving is now disabled by policy."});
}
}
}
diff --git a/chromium/components/history/core/browser/typed_url_sync_bridge.cc b/chromium/components/history/core/browser/typed_url_sync_bridge.cc
index 701aaa291c8..e1e05051d1d 100644
--- a/chromium/components/history/core/browser/typed_url_sync_bridge.cc
+++ b/chromium/components/history/core/browser/typed_url_sync_bridge.cc
@@ -4,9 +4,10 @@
#include "components/history/core/browser/typed_url_sync_bridge.h"
+#include <memory>
+
#include "base/auto_reset.h"
#include "base/big_endian.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "components/history/core/browser/history_backend.h"
@@ -98,7 +99,7 @@ TypedURLSyncBridge::~TypedURLSyncBridge() {
std::unique_ptr<MetadataChangeList>
TypedURLSyncBridge::CreateMetadataChangeList() {
DCHECK(sequence_checker_.CalledOnValidSequence());
- return base::MakeUnique<syncer::SyncMetadataStoreChangeList>(
+ return std::make_unique<syncer::SyncMetadataStoreChangeList>(
sync_metadata_database_, syncer::TYPED_URLS);
}
@@ -262,7 +263,7 @@ void TypedURLSyncBridge::GetData(StorageKeyList storage_keys,
DataCallback callback) {
DCHECK(sequence_checker_.CalledOnValidSequence());
- auto batch = base::MakeUnique<MutableDataBatch>();
+ auto batch = std::make_unique<MutableDataBatch>();
for (const std::string& key : storage_keys) {
URLRow url_row;
URLID url_id = TypedURLSyncMetadataDatabase::StorageKeyToURLID(key);
@@ -297,12 +298,12 @@ void TypedURLSyncBridge::GetAllData(DataCallback callback) {
++num_db_accesses_;
if (!history_backend_->GetAllTypedURLs(&typed_urls)) {
++num_db_errors_;
- change_processor()->ReportError(FROM_HERE,
- "Could not get the typed_url entries.");
+ change_processor()->ReportError(
+ {FROM_HERE, "Could not get the typed_url entries."});
return;
}
- auto batch = base::MakeUnique<MutableDataBatch>();
+ auto batch = std::make_unique<MutableDataBatch>();
for (URLRow& url : typed_urls) {
VisitVector visits_vector;
if (!FixupURLAndGetVisits(&url, &visits_vector))
@@ -415,11 +416,11 @@ void TypedURLSyncBridge::OnURLsDeleted(HistoryBackend* history_backend,
CreateMetadataChangeList();
if (all_history) {
- auto batch = base::MakeUnique<syncer::MetadataBatch>();
+ auto batch = std::make_unique<syncer::MetadataBatch>();
if (!sync_metadata_database_->GetAllSyncMetadata(batch.get())) {
- change_processor()->ReportError(FROM_HERE,
- "Failed reading typed url metadata from "
- "TypedURLSyncMetadataDatabase.");
+ change_processor()->ReportError({FROM_HERE,
+ "Failed reading typed url metadata from "
+ "TypedURLSyncMetadataDatabase."});
return;
}
@@ -445,8 +446,8 @@ void TypedURLSyncBridge::Init() {
void TypedURLSyncBridge::OnDatabaseError() {
sync_metadata_database_ = nullptr;
- change_processor()->ReportError(FROM_HERE,
- "HistoryDatabase encountered error");
+ change_processor()->ReportError(
+ {FROM_HERE, "HistoryDatabase encountered error"});
}
int TypedURLSyncBridge::GetErrorPercentage() const {
@@ -727,15 +728,15 @@ void TypedURLSyncBridge::UpdateURLRowFromTypedUrlSpecifics(
void TypedURLSyncBridge::LoadMetadata() {
if (!history_backend_ || !sync_metadata_database_) {
change_processor()->ReportError(
- FROM_HERE, "Failed to load TypedURLSyncMetadataDatabase.");
+ {FROM_HERE, "Failed to load TypedURLSyncMetadataDatabase."});
return;
}
- auto batch = base::MakeUnique<syncer::MetadataBatch>();
+ auto batch = std::make_unique<syncer::MetadataBatch>();
if (!sync_metadata_database_->GetAllSyncMetadata(batch.get())) {
- change_processor()->ReportError(
- FROM_HERE,
- "Failed reading typed url metadata from TypedURLSyncMetadataDatabase.");
+ change_processor()->ReportError({FROM_HERE,
+ "Failed reading typed url metadata from "
+ "TypedURLSyncMetadataDatabase."});
return;
}
change_processor()->ModelReadyToSync(std::move(batch));
@@ -1136,7 +1137,7 @@ bool TypedURLSyncBridge::FixupURLAndGetVisits(URLRow* url,
std::unique_ptr<EntityData> TypedURLSyncBridge::CreateEntityData(
const URLRow& row,
const VisitVector& visits) {
- auto entity_data = base::MakeUnique<EntityData>();
+ auto entity_data = std::make_unique<EntityData>();
TypedUrlSpecifics* specifics = entity_data->specifics.mutable_typed_url();
if (!WriteToTypedUrlSpecifics(row, visits, specifics)) {
diff --git a/chromium/components/history/core/browser/typed_url_sync_bridge_unittest.cc b/chromium/components/history/core/browser/typed_url_sync_bridge_unittest.cc
index 2b61ceba28c..c60962f72d0 100644
--- a/chromium/components/history/core/browser/typed_url_sync_bridge_unittest.cc
+++ b/chromium/components/history/core/browser/typed_url_sync_bridge_unittest.cc
@@ -4,6 +4,8 @@
#include "components/history/core/browser/typed_url_sync_bridge.h"
+#include <memory>
+
#include "base/big_endian.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
@@ -176,7 +178,7 @@ class TestHistoryBackendDelegate : public HistoryBackend::Delegate {
const RedirectList& redirects,
base::Time visit_time) override {}
void NotifyURLsModified(const URLRows& changed_urls) override {}
- void NotifyURLsDeleted(bool all_history,
+ void NotifyURLsDeleted(const DeletionTimeRange& time_range,
bool expired,
const URLRows& deleted_rows,
const std::set<GURL>& favicon_urls) override {}
@@ -237,7 +239,7 @@ class TypedURLSyncBridgeTest : public testing::Test {
fake_history_backend_->Init(
false, TestHistoryDatabaseParamsForPath(test_dir_.GetPath()));
std::unique_ptr<TypedURLSyncBridge> bridge =
- base::MakeUnique<TypedURLSyncBridge>(
+ std::make_unique<TypedURLSyncBridge>(
fake_history_backend_.get(), fake_history_backend_->db(),
RecordingModelTypeChangeProcessor::FactoryForBridgeTest(&processor_,
false));
diff --git a/chromium/components/history/core/browser/typed_url_syncable_service.cc b/chromium/components/history/core/browser/typed_url_syncable_service.cc
deleted file mode 100644
index 43a6f5042fd..00000000000
--- a/chromium/components/history/core/browser/typed_url_syncable_service.cc
+++ /dev/null
@@ -1,1105 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/history/core/browser/typed_url_syncable_service.h"
-
-#include <stddef.h>
-
-#include <utility>
-
-#include "base/auto_reset.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "components/history/core/browser/history_backend.h"
-#include "components/sync/protocol/sync.pb.h"
-#include "components/sync/protocol/typed_url_specifics.pb.h"
-#include "net/base/url_util.h"
-
-namespace history {
-
-namespace {
-
-// The server backend can't handle arbitrarily large node sizes, so to keep
-// the size under control we limit the visit array.
-static const int kMaxTypedUrlVisits = 100;
-
-// There's no limit on how many visits the history DB could have for a given
-// typed URL, so we limit how many we fetch from the DB to avoid crashes due to
-// running out of memory (http://crbug.com/89793). This value is different
-// from kMaxTypedUrlVisits, as some of the visits fetched from the DB may be
-// RELOAD visits, which will be stripped.
-static const int kMaxVisitsToFetch = 1000;
-
-// This is the threshold at which we start throttling sync updates for typed
-// URLs - any URLs with a typed_count >= this threshold will be throttled.
-static const int kTypedUrlVisitThrottleThreshold = 10;
-
-// This is the multiple we use when throttling sync updates. If the multiple is
-// N, we sync up every Nth update (i.e. when typed_count % N == 0).
-static const int kTypedUrlVisitThrottleMultiple = 10;
-
-} // namespace
-
-// Enforce oldest to newest visit order.
-static bool CheckVisitOrdering(const VisitVector& visits) {
- int64_t previous_visit_time = 0;
- for (VisitVector::const_iterator visit = visits.begin();
- visit != visits.end(); ++visit) {
- if (visit != visits.begin()) {
- // We allow duplicate visits here - they shouldn't really be allowed, but
- // they still seem to show up sometimes and we haven't figured out the
- // source, so we just log an error instead of failing an assertion.
- // (http://crbug.com/91473).
- if (previous_visit_time == visit->visit_time.ToInternalValue())
- DVLOG(1) << "Duplicate visit time encountered";
- else if (previous_visit_time > visit->visit_time.ToInternalValue())
- return false;
- }
-
- previous_visit_time = visit->visit_time.ToInternalValue();
- }
- return true;
-}
-
-TypedUrlSyncableService::TypedUrlSyncableService(
- HistoryBackend* history_backend)
- : history_backend_(history_backend),
- processing_syncer_changes_(false),
- num_db_accesses_(0),
- num_db_errors_(0),
- history_backend_observer_(this) {
- DCHECK(history_backend_);
- DCHECK(sequence_checker_.CalledOnValidSequence());
-}
-
-TypedUrlSyncableService::~TypedUrlSyncableService() {
-}
-
-syncer::SyncMergeResult TypedUrlSyncableService::MergeDataAndStartSyncing(
- syncer::ModelType type,
- const syncer::SyncDataList& initial_sync_data,
- std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
- std::unique_ptr<syncer::SyncErrorFactory> error_handler) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
- DCHECK(!sync_processor_.get());
- DCHECK(sync_processor.get());
- DCHECK(error_handler.get());
- DCHECK_EQ(type, syncer::TYPED_URLS);
-
- syncer::SyncMergeResult merge_result(type);
- sync_processor_ = std::move(sync_processor);
- sync_error_handler_ = std::move(error_handler);
-
- ClearErrorStats();
-
- DVLOG(1) << "Associating TypedUrl: MergeDataAndStartSyncing";
-
- // Create a mapping of all local data by URLID. These will be narrowed down
- // by CreateOrUpdateUrl() to include only the entries different from sync
- // server data.
- TypedUrlMap new_db_urls;
-
- // Get all the visits and map the URLRows by URL.
- UrlVisitVectorMap visit_vectors;
-
- {
- // Get all the typed urls from the history db.
- history::URLRows typed_urls;
- ++num_db_accesses_;
- if (!history_backend_->GetAllTypedURLs(&typed_urls)) {
- ++num_db_errors_;
- merge_result.set_error(sync_error_handler_->CreateAndUploadError(
- FROM_HERE, "Could not get the typed_url entries."));
- return merge_result;
- }
-
- for (history::URLRows::iterator iter = typed_urls.begin();
- iter != typed_urls.end();) {
- DCHECK_EQ(0U, visit_vectors.count(iter->url()));
- if (!FixupURLAndGetVisits(&(*iter), &(visit_vectors[iter->url()])) ||
- ShouldIgnoreUrl(iter->url()) ||
- ShouldIgnoreVisits(visit_vectors[iter->url()])) {
- // Ignore this URL if we couldn't load the visits or if there's some
- // other problem with it (it was empty, or imported and never visited).
- iter = typed_urls.erase(iter);
- } else {
- // Add url to map.
- new_db_urls[iter->url()] =
- std::make_pair(syncer::SyncChange::ACTION_ADD, *iter);
- ++iter;
- }
- }
- }
-
- // New sync data organized for different write operations to history backend.
- history::URLRows new_synced_urls;
- history::URLRows updated_synced_urls;
- TypedUrlVisitVector new_synced_visits;
-
- // List of updates to push to sync.
- syncer::SyncChangeList new_changes;
-
- // Iterate through initial_sync_data and check for all the urls that
- // sync already knows about. CreateOrUpdateUrl() will remove urls that
- // are the same as the synced ones from |new_db_urls|.
- for (syncer::SyncDataList::const_iterator sync_iter =
- initial_sync_data.begin();
- sync_iter != initial_sync_data.end(); ++sync_iter) {
- // Extract specifics
- const sync_pb::EntitySpecifics& specifics = sync_iter->GetSpecifics();
- const sync_pb::TypedUrlSpecifics& typed_url(specifics.typed_url());
-
- if (ShouldIgnoreUrl(GURL(typed_url.url())))
- continue;
-
- // Add url to cache of sync state. Note that this is done irrespective of
- // whether the synced url is ignored locally, so that we know what to delete
- // at a later point.
- synced_typed_urls_.insert(GURL(typed_url.url()));
-
- // Ignore old sync urls that don't have any transition data stored with
- // them, or transition data that does not match the visit data (will be
- // deleted below).
- if (typed_url.visit_transitions_size() == 0 ||
- typed_url.visit_transitions_size() != typed_url.visits_size()) {
- // Generate a debug assertion to help track down http://crbug.com/91473,
- // even though we gracefully handle this case by overwriting this node.
- DCHECK_EQ(typed_url.visits_size(), typed_url.visit_transitions_size());
- DVLOG(1) << "Ignoring obsolete sync url with no visit transition info.";
-
- // Check if local db has typed visits for the url
- TypedUrlMap::iterator it = new_db_urls.find(GURL(typed_url.url()));
- if (it != new_db_urls.end()) {
- // Overwrite server data with local data
- it->second.first = syncer::SyncChange::ACTION_UPDATE;
- }
- continue;
- }
-
- CreateOrUpdateUrl(typed_url, &new_db_urls, &visit_vectors, &new_synced_urls,
- &new_synced_visits, &updated_synced_urls);
- }
-
- for (TypedUrlMap::iterator i = new_db_urls.begin(); i != new_db_urls.end();
- ++i) {
- std::string tag = i->first.spec();
- AddTypedUrlToChangeList(i->second.first, i->second.second,
- visit_vectors[i->first], tag, &new_changes);
- }
-
- // Send history changes to the sync server
- merge_result.set_error(
- sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes));
-
- if (!merge_result.error().IsSet()) {
- WriteToHistoryBackend(&new_synced_urls, &updated_synced_urls, nullptr,
- &new_synced_visits, nullptr);
- }
-
- history_backend_observer_.Add(history_backend_);
-
- UMA_HISTOGRAM_PERCENTAGE("Sync.TypedUrlMergeAndStartSyncingErrors",
- GetErrorPercentage());
- ClearErrorStats();
-
- return merge_result;
-}
-
-void TypedUrlSyncableService::StopSyncing(syncer::ModelType type) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
- DCHECK_EQ(type, syncer::TYPED_URLS);
-
- // Clear cache of server state.
- synced_typed_urls_.clear();
-
- history_backend_observer_.RemoveAll();
-
- ClearErrorStats();
-
- sync_processor_.reset();
- sync_error_handler_.reset();
-}
-
-syncer::SyncDataList TypedUrlSyncableService::GetAllSyncData(
- syncer::ModelType type) const {
- DCHECK(sequence_checker_.CalledOnValidSequence());
- syncer::SyncDataList list;
-
- // TODO(sync): Add implementation
-
- return list;
-}
-
-syncer::SyncError TypedUrlSyncableService::ProcessSyncChanges(
- const base::Location& from_here,
- const syncer::SyncChangeList& change_list) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
-
- std::vector<GURL> pending_deleted_urls;
- history::URLRows new_synced_urls;
- history::URLRows updated_synced_urls;
- TypedUrlVisitVector new_synced_visits;
- history::VisitVector deleted_visits;
-
- for (syncer::SyncChangeList::const_iterator it = change_list.begin();
- it != change_list.end(); ++it) {
- const sync_pb::EntitySpecifics& specifics = it->sync_data().GetSpecifics();
- DCHECK(specifics.has_typed_url())
- << "Typed URL delete change does not have necessary specifics.";
- GURL url(specifics.typed_url().url());
-
- if (syncer::SyncChange::ACTION_DELETE == it->change_type()) {
- pending_deleted_urls.push_back(url);
- if (synced_typed_urls_.find(url) != synced_typed_urls_.end()) {
- // Delete typed url from cache.
- synced_typed_urls_.erase(url);
- }
- continue;
- }
-
- // Ensure cache of server state is up to date.
- synced_typed_urls_.insert(url);
-
- if (ShouldIgnoreUrl(url))
- continue;
-
- const sync_pb::TypedUrlSpecifics& typed_url(specifics.typed_url());
- DCHECK(typed_url.visits_size());
- sync_pb::TypedUrlSpecifics filtered_url = FilterExpiredVisits(typed_url);
- if (filtered_url.visits_size() == 0)
- continue;
-
- UpdateFromSyncDB(filtered_url, &new_synced_visits, &deleted_visits,
- &updated_synced_urls, &new_synced_urls);
- }
-
- WriteToHistoryBackend(&new_synced_urls, &updated_synced_urls,
- &pending_deleted_urls, &new_synced_visits,
- &deleted_visits);
-
- return syncer::SyncError();
-}
-
-void TypedUrlSyncableService::OnURLsModified(
- history::HistoryBackend* history_backend,
- const history::URLRows& changed_urls) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
-
- if (processing_syncer_changes_)
- return; // These are changes originating from us, ignore.
- if (!sync_processor_.get())
- return; // Sync processor not yet initialized, don't sync.
-
- // Create SyncChangeList.
- syncer::SyncChangeList changes;
-
- for (const auto& row : changed_urls) {
- // Only care if the modified URL is typed.
- if (row.typed_count() >= 0) {
- // If there were any errors updating the sync node, just ignore them and
- // continue on to process the next URL.
- CreateOrUpdateSyncNode(row, &changes);
- }
- }
-
- // Send SyncChangeList to server if there are any changes.
- if (changes.size() > 0)
- sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
-}
-
-void TypedUrlSyncableService::OnURLVisited(
- history::HistoryBackend* history_backend,
- ui::PageTransition transition,
- const history::URLRow& row,
- const history::RedirectList& redirects,
- base::Time visit_time) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
-
- if (processing_syncer_changes_)
- return; // These are changes originating from us, ignore.
- if (!sync_processor_.get())
- return; // Sync processor not yet initialized, don't sync.
- if (!ShouldSyncVisit(row.typed_count(), transition))
- return;
-
- // Create SyncChangeList.
- syncer::SyncChangeList changes;
-
- CreateOrUpdateSyncNode(row, &changes);
-
- // Send SyncChangeList to server if there are any changes.
- if (changes.size() > 0)
- sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
-}
-
-void TypedUrlSyncableService::OnURLsDeleted(
- history::HistoryBackend* history_backend,
- bool all_history,
- bool expired,
- const history::URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
-
- if (processing_syncer_changes_)
- return; // These are changes originating from us, ignore.
- if (!sync_processor_.get())
- return; // Sync processor not yet initialized, don't sync.
-
- // Ignore URLs expired due to old age (we don't want to sync them as deletions
- // to avoid extra traffic up to the server, and also to make sure that a
- // client with a bad clock setting won't go on an expiration rampage and
- // delete all history from every client). The server will gracefully age out
- // the sync DB entries when they've been idle for long enough.
- if (expired)
- return;
-
- // Create SyncChangeList.
- syncer::SyncChangeList changes;
-
- if (all_history) {
- // Delete all synced typed urls.
- for (const auto& url : synced_typed_urls_) {
- VisitVector visits;
- URLRow row(url);
- AddTypedUrlToChangeList(syncer::SyncChange::ACTION_DELETE, row, visits,
- url.spec(), &changes);
- }
- // Clear cache of server state.
- synced_typed_urls_.clear();
- } else {
- // Delete rows.
- for (const auto& row : deleted_rows) {
- // Add specifics to change list for all synced urls that were deleted.
- if (synced_typed_urls_.find(row.url()) != synced_typed_urls_.end()) {
- VisitVector visits;
- AddTypedUrlToChangeList(syncer::SyncChange::ACTION_DELETE, row, visits,
- row.url().spec(), &changes);
- // Delete typed url from cache.
- synced_typed_urls_.erase(row.url());
- }
- }
- }
-
- // Send SyncChangeList to server if there are any changes.
- if (changes.size() > 0)
- sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
-}
-
-void TypedUrlSyncableService::CreateOrUpdateUrl(
- const sync_pb::TypedUrlSpecifics& typed_url,
- TypedUrlMap* loaded_data,
- UrlVisitVectorMap* visit_vectors,
- history::URLRows* new_synced_urls,
- TypedUrlVisitVector* new_synced_visits,
- history::URLRows* updated_synced_urls) {
- DCHECK(typed_url.visits_size() != 0);
- DCHECK_EQ(typed_url.visits_size(), typed_url.visit_transitions_size());
-
- // Ignore empty urls.
- if (typed_url.url().empty()) {
- DVLOG(1) << "Ignoring empty URL in sync DB";
- return;
- }
- // Now, get rid of the expired visits. If there are no un-expired visits
- // left, ignore this url - any local data should just replace it.
- sync_pb::TypedUrlSpecifics sync_url = FilterExpiredVisits(typed_url);
- if (sync_url.visits_size() == 0) {
- DVLOG(1) << "Ignoring expired URL in sync DB: " << sync_url.url();
- return;
- }
-
- // Check if local db already has the url from sync.
- TypedUrlMap::iterator it = loaded_data->find(GURL(sync_url.url()));
- if (it == loaded_data->end()) {
- // There are no matching typed urls from the local db, check for untyped
- history::URLRow untyped_url(GURL(sync_url.url()));
-
- // The URL may still exist in the local db if it is an untyped url.
- // An untyped url will transition to a typed url after receiving visits
- // from sync, and sync should receive any visits already existing locally
- // for the url, so the full list of visits is consistent.
- bool is_existing_url =
- history_backend_->GetURL(untyped_url.url(), &untyped_url);
- if (is_existing_url) {
- // Add a new entry to |loaded_data|, and set the iterator to it.
- history::VisitVector untyped_visits;
- if (!FixupURLAndGetVisits(&untyped_url, &untyped_visits)) {
- return;
- }
- (*visit_vectors)[untyped_url.url()] = untyped_visits;
-
- // Store row info that will be used to update sync's visits.
- (*loaded_data)[untyped_url.url()] =
- std::pair<syncer::SyncChange::SyncChangeType, history::URLRow>(
- syncer::SyncChange::ACTION_UPDATE, untyped_url);
-
- // Set iterator |it| to point to this entry.
- it = loaded_data->find(untyped_url.url());
- DCHECK(it != loaded_data->end());
- // Continue with merge below.
- } else {
- // The url is new to the local history DB.
- // Create new db entry for url.
- history::URLRow new_url(GURL(sync_url.url()));
- UpdateURLRowFromTypedUrlSpecifics(sync_url, &new_url);
- new_synced_urls->push_back(new_url);
-
- // Add entries for url visits.
- std::vector<history::VisitInfo> added_visits;
- size_t visit_count = sync_url.visits_size();
-
- for (size_t index = 0; index < visit_count; ++index) {
- base::Time visit_time =
- base::Time::FromInternalValue(sync_url.visits(index));
- ui::PageTransition transition =
- ui::PageTransitionFromInt(sync_url.visit_transitions(index));
- added_visits.push_back(history::VisitInfo(visit_time, transition));
- }
- new_synced_visits->push_back(
- std::pair<GURL, std::vector<history::VisitInfo>>(new_url.url(),
- added_visits));
- return;
- }
- }
-
- // Same URL exists in sync data and in history data - compare the
- // entries to see if there's any difference.
- history::VisitVector& visits = (*visit_vectors)[it->first];
- std::vector<history::VisitInfo> added_visits;
-
- // Empty URLs should be filtered out by ShouldIgnoreUrl() previously.
- DCHECK(!it->second.second.url().spec().empty());
-
- // 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).
- history::URLRow new_url(it->second.second);
-
- MergeResult difference =
- MergeUrls(sync_url, it->second.second, &visits, &new_url, &added_visits);
-
- if (difference != DIFF_NONE) {
- it->second.second = new_url;
- if (difference & DIFF_UPDATE_NODE) {
- // Edit map entry to reflect update to sync.
- it->second.first = syncer::SyncChange::ACTION_UPDATE;
- // We don't want to resurrect old visits that have been aged out by
- // other clients, so remove all visits that are older than the
- // earliest existing visit in the sync node.
- //
- // TODO(sync): This logic should be unnecessary now that filtering of
- // expired visits is performed separately. Non-expired visits older than
- // the earliest existing sync visits should still be synced, so this
- // logic should be removed.
- if (sync_url.visits_size() > 0) {
- base::Time earliest_visit =
- base::Time::FromInternalValue(sync_url.visits(0));
- for (history::VisitVector::iterator i = visits.begin();
- i != visits.end() && i->visit_time < earliest_visit;) {
- i = visits.erase(i);
- }
- // Should never be possible to delete all the items, since the
- // visit vector contains newer local visits it will keep and/or the
- // visits in typed_url.visits newer than older local visits.
- DCHECK(visits.size() > 0);
- }
- DCHECK_EQ(new_url.last_visit().ToInternalValue(),
- visits.back().visit_time.ToInternalValue());
- }
- if (difference & DIFF_LOCAL_ROW_CHANGED) {
- // Add entry to updated_synced_urls to update the local db.
- DCHECK_EQ(it->second.second.id(), new_url.id());
- updated_synced_urls->push_back(new_url);
- }
- if (difference & DIFF_LOCAL_VISITS_ADDED) {
- // Add entry with new visits to new_synced_visits to update the local db.
- new_synced_visits->push_back(
- std::pair<GURL, std::vector<history::VisitInfo>>(it->first,
- added_visits));
- }
- } else {
- // No difference in urls, erase from map
- loaded_data->erase(it);
- }
-}
-
-sync_pb::TypedUrlSpecifics TypedUrlSyncableService::FilterExpiredVisits(
- const sync_pb::TypedUrlSpecifics& source) {
- // Make a copy of the source, then regenerate the visits.
- sync_pb::TypedUrlSpecifics specifics(source);
- specifics.clear_visits();
- specifics.clear_visit_transitions();
- for (int i = 0; i < source.visits_size(); ++i) {
- base::Time time = base::Time::FromInternalValue(source.visits(i));
- if (!history_backend_->IsExpiredVisitTime(time)) {
- specifics.add_visits(source.visits(i));
- specifics.add_visit_transitions(source.visit_transitions(i));
- }
- }
- DCHECK(specifics.visits_size() == specifics.visit_transitions_size());
- return specifics;
-}
-
-// static
-TypedUrlSyncableService::MergeResult TypedUrlSyncableService::MergeUrls(
- const sync_pb::TypedUrlSpecifics& sync_url,
- const history::URLRow& url,
- history::VisitVector* visits,
- history::URLRow* new_url,
- std::vector<history::VisitInfo>* new_visits) {
- DCHECK(new_url);
- DCHECK(!sync_url.url().compare(url.url().spec()));
- DCHECK(!sync_url.url().compare(new_url->url().spec()));
- DCHECK(visits->size());
- DCHECK_GT(sync_url.visits_size(), 0);
- CHECK_EQ(sync_url.visits_size(), sync_url.visit_transitions_size());
-
- // Convert these values only once.
- base::string16 sync_url_title(base::UTF8ToUTF16(sync_url.title()));
- base::Time sync_url_last_visit = base::Time::FromInternalValue(
- sync_url.visits(sync_url.visits_size() - 1));
-
- // This is a bitfield representing what we'll need to update with the output
- // value.
- MergeResult different = DIFF_NONE;
-
- // Check if the non-incremented values changed.
- if ((sync_url_title.compare(url.title()) != 0) ||
- (sync_url.hidden() != url.hidden())) {
- // Use the values from the most recent visit.
- if (sync_url_last_visit >= url.last_visit()) {
- new_url->set_title(sync_url_title);
- new_url->set_hidden(sync_url.hidden());
- different |= DIFF_LOCAL_ROW_CHANGED;
- } else {
- new_url->set_title(url.title());
- new_url->set_hidden(url.hidden());
- different |= DIFF_UPDATE_NODE;
- }
- } else {
- // No difference.
- new_url->set_title(url.title());
- new_url->set_hidden(url.hidden());
- }
-
- size_t sync_url_num_visits = sync_url.visits_size();
- size_t history_num_visits = visits->size();
- size_t sync_url_visit_index = 0;
- size_t history_visit_index = 0;
- base::Time earliest_history_time = (*visits)[0].visit_time;
- // Walk through the two sets of visits and figure out if any new visits were
- // added on either side.
- while (sync_url_visit_index < sync_url_num_visits ||
- history_visit_index < history_num_visits) {
- // Time objects are initialized to "earliest possible time".
- base::Time sync_url_time, history_time;
- if (sync_url_visit_index < sync_url_num_visits)
- sync_url_time =
- base::Time::FromInternalValue(sync_url.visits(sync_url_visit_index));
- if (history_visit_index < history_num_visits)
- history_time = (*visits)[history_visit_index].visit_time;
- if (sync_url_visit_index >= sync_url_num_visits ||
- (history_visit_index < history_num_visits &&
- sync_url_time > history_time)) {
- // We found a visit in the history DB that doesn't exist in the sync DB,
- // so mark the sync_url as modified so the caller will update the sync
- // node.
- different |= DIFF_UPDATE_NODE;
- ++history_visit_index;
- } else if (history_visit_index >= history_num_visits ||
- sync_url_time < history_time) {
- // Found a visit in the sync node that doesn't exist in the history DB, so
- // add it to our list of new visits and set the appropriate flag so the
- // caller will update the history DB.
- // If the sync_url visit is older than any existing visit in the history
- // DB, don't re-add it - this keeps us from resurrecting visits that were
- // aged out locally.
- //
- // TODO(sync): This extra check should be unnecessary now that filtering
- // expired visits is performed separately. Non-expired visits older than
- // the earliest existing history visits should still be synced, so this
- // check should be removed.
- if (sync_url_time > earliest_history_time) {
- different |= DIFF_LOCAL_VISITS_ADDED;
- new_visits->push_back(history::VisitInfo(
- sync_url_time, ui::PageTransitionFromInt(sync_url.visit_transitions(
- sync_url_visit_index))));
- }
- // This visit is added to visits below.
- ++sync_url_visit_index;
- } else {
- // Same (already synced) entry found in both DBs - no need to do anything.
- ++sync_url_visit_index;
- ++history_visit_index;
- }
- }
-
- DCHECK(CheckVisitOrdering(*visits));
- if (different & DIFF_LOCAL_VISITS_ADDED) {
- // If the server does not have the same visits as the local db, then the
- // new visits from the server need to be added to the vector containing
- // local visits. These visits will be passed to the server.
- // Insert new visits into the appropriate place in the visits vector.
- history::VisitVector::iterator visit_ix = visits->begin();
- for (std::vector<history::VisitInfo>::iterator new_visit =
- new_visits->begin();
- new_visit != new_visits->end(); ++new_visit) {
- while (visit_ix != visits->end() &&
- new_visit->first > visit_ix->visit_time) {
- ++visit_ix;
- }
- visit_ix =
- visits->insert(visit_ix, history::VisitRow(url.id(), new_visit->first,
- 0, new_visit->second, 0));
- ++visit_ix;
- }
- }
- DCHECK(CheckVisitOrdering(*visits));
-
- new_url->set_last_visit(visits->back().visit_time);
- return different;
-}
-
-void TypedUrlSyncableService::WriteToHistoryBackend(
- const history::URLRows* new_urls,
- const history::URLRows* updated_urls,
- const std::vector<GURL>* deleted_urls,
- const TypedUrlVisitVector* new_visits,
- const history::VisitVector* deleted_visits) {
- // Set flag to stop accepting history change notifications from backend
- base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
-
- if (deleted_urls && !deleted_urls->empty())
- history_backend_->DeleteURLs(*deleted_urls);
-
- if (new_urls) {
- history_backend_->AddPagesWithDetails(*new_urls, history::SOURCE_SYNCED);
- }
- if (updated_urls) {
- ++num_db_accesses_;
- // This is an existing entry in the URL database. We don't verify the
- // visit_count or typed_count values here, because either one (or both)
- // could be zero in the case of bookmarks, or in the case of a URL
- // transitioning from non-typed to typed as a result of this sync.
- // In the field we sometimes run into errors on specific URLs. It's OK
- // to just continue on (we can try writing again on the next model
- // association).
- size_t num_successful_updates = history_backend_->UpdateURLs(*updated_urls);
- num_db_errors_ += updated_urls->size() - num_successful_updates;
- }
- if (new_visits) {
- for (TypedUrlVisitVector::const_iterator visits = new_visits->begin();
- visits != new_visits->end(); ++visits) {
- // If there are no visits to add, just skip this.
- if (visits->second.empty())
- continue;
- ++num_db_accesses_;
- if (!history_backend_->AddVisits(visits->first, visits->second,
- history::SOURCE_SYNCED)) {
- ++num_db_errors_;
- DLOG(ERROR) << "Could not add visits.";
- }
- }
- }
- if (deleted_visits) {
- ++num_db_accesses_;
- if (!history_backend_->RemoveVisits(*deleted_visits)) {
- ++num_db_errors_;
- DLOG(ERROR) << "Could not remove visits.";
- // This is bad news, since it means we may end up resurrecting history
- // entries on the next reload. It's unavoidable so we'll just keep on
- // syncing.
- }
- }
-}
-
-void TypedUrlSyncableService::GetSyncedUrls(std::set<GURL>* urls) const {
- urls->insert(synced_typed_urls_.begin(), synced_typed_urls_.end());
-}
-
-void TypedUrlSyncableService::ClearErrorStats() {
- num_db_accesses_ = 0;
- num_db_errors_ = 0;
-}
-
-int TypedUrlSyncableService::GetErrorPercentage() const {
- return num_db_accesses_ ? (100 * num_db_errors_ / num_db_accesses_) : 0;
-}
-
-bool TypedUrlSyncableService::ShouldIgnoreUrl(const GURL& url) {
- // Ignore empty URLs. Not sure how this can happen (maybe import from other
- // busted browsers, or misuse of the history API, or just plain bugs) but we
- // can't deal with them.
- if (url.spec().empty())
- return true;
-
- // Ignore local file URLs.
- if (url.SchemeIsFile())
- return true;
-
- // Ignore localhost URLs.
- if (net::IsLocalhost(url))
- return true;
-
- // Ignore username and password, sonce history backend will remove user name
- // and password in URLDatabase::GURLToDatabaseURL and send username/password
- // removed url to sync later.
- if (url.has_username() || url.has_password())
- return true;
-
- return false;
-}
-
-bool TypedUrlSyncableService::ShouldIgnoreVisits(
- const history::VisitVector& visits) {
- // We ignore URLs that were imported, but have never been visited by
- // chromium.
- static const int kFirstImportedSource = history::SOURCE_FIREFOX_IMPORTED;
- history::VisitSourceMap map;
- if (!history_backend_->GetVisitsSource(visits, &map))
- return false; // If we can't read the visit, assume it's not imported.
-
- // Walk the list of visits and look for a non-imported item.
- for (history::VisitVector::const_iterator it = visits.begin();
- it != visits.end(); ++it) {
- if (map.count(it->visit_id) == 0 ||
- map[it->visit_id] < kFirstImportedSource) {
- return false;
- }
- }
- // We only saw imported visits, so tell the caller to ignore them.
- return true;
-}
-
-bool TypedUrlSyncableService::ShouldSyncVisit(int typed_count,
- ui::PageTransition transition) {
- // Just use an ad-hoc criteria to determine whether to ignore this
- // notification. For most users, the distribution of visits is roughly a bell
- // curve with a long tail - there are lots of URLs with < 5 visits so we want
- // to make sure we sync up every visit to ensure the proper ordering of
- // suggestions. But there are relatively few URLs with > 10 visits, and those
- // tend to be more broadly distributed such that there's no need to sync up
- // every visit to preserve their relative ordering.
- return (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED) &&
- typed_count >= 0 &&
- (typed_count < kTypedUrlVisitThrottleThreshold ||
- (typed_count % kTypedUrlVisitThrottleMultiple) == 0));
-}
-
-bool TypedUrlSyncableService::CreateOrUpdateSyncNode(
- URLRow url,
- syncer::SyncChangeList* changes) {
- DCHECK_GE(url.typed_count(), 0);
-
- if (ShouldIgnoreUrl(url.url()))
- return true;
-
- // Get the visits for this node.
- VisitVector visit_vector;
- if (!FixupURLAndGetVisits(&url, &visit_vector)) {
- return false;
- }
-
- DCHECK(!visit_vector.empty());
-
- std::string title = url.url().spec();
- syncer::SyncChange::SyncChangeType change_type;
-
- // If server already has URL, then send a sync update, else add it.
- change_type = (synced_typed_urls_.find(url.url()) != synced_typed_urls_.end())
- ? syncer::SyncChange::ACTION_UPDATE
- : syncer::SyncChange::ACTION_ADD;
-
- AddTypedUrlToChangeList(change_type, url, visit_vector, title, changes);
-
- return true;
-}
-
-void TypedUrlSyncableService::AddTypedUrlToChangeList(
- syncer::SyncChange::SyncChangeType change_type,
- const URLRow& row,
- const VisitVector& visits,
- std::string title,
- syncer::SyncChangeList* change_list) {
- sync_pb::EntitySpecifics entity_specifics;
- sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
- std::string tag = row.url().spec();
-
- if (change_type == syncer::SyncChange::ACTION_DELETE) {
- typed_url->set_url(tag);
- } else {
- if (!WriteToTypedUrlSpecifics(row, visits, typed_url)) {
- // Cannot write to specifics, ex. no TYPED visits.
- return;
- }
-
- // Ensure cache of server state is up to date.
- synced_typed_urls_.insert(row.url());
- }
-
- change_list->push_back(syncer::SyncChange(
- FROM_HERE, change_type,
- syncer::SyncData::CreateLocalData(tag, title, entity_specifics)));
-}
-
-bool TypedUrlSyncableService::WriteToTypedUrlSpecifics(
- const URLRow& url,
- const VisitVector& visits,
- sync_pb::TypedUrlSpecifics* typed_url) {
- DCHECK(!url.last_visit().is_null());
- DCHECK(!visits.empty());
- DCHECK_EQ(url.last_visit().ToInternalValue(),
- visits.back().visit_time.ToInternalValue());
-
- typed_url->set_url(url.url().spec());
- typed_url->set_title(base::UTF16ToUTF8(url.title()));
- typed_url->set_hidden(url.hidden());
-
- DCHECK(CheckVisitOrdering(visits));
-
- bool only_typed = false;
- int skip_count = 0;
-
- if (std::find_if(visits.begin(), visits.end(),
- [](const history::VisitRow& visit) {
- return ui::PageTransitionCoreTypeIs(
- visit.transition, ui::PAGE_TRANSITION_TYPED);
- }) == visits.end()) {
- // This URL has no TYPED visits, don't sync it
- return false;
- }
-
- if (visits.size() > static_cast<size_t>(kMaxTypedUrlVisits)) {
- int typed_count = 0;
- int total = 0;
- // Walk the passed-in visit vector and count the # of typed visits.
- for (VisitVector::const_iterator visit = visits.begin();
- visit != visits.end(); ++visit) {
- // We ignore reload visits.
- if (PageTransitionCoreTypeIs(visit->transition,
- ui::PAGE_TRANSITION_RELOAD)) {
- continue;
- }
- ++total;
- if (PageTransitionCoreTypeIs(visit->transition,
- ui::PAGE_TRANSITION_TYPED)) {
- ++typed_count;
- }
- }
-
- // We should have at least one typed visit. This can sometimes happen if
- // the history DB has an inaccurate count for some reason (there's been
- // bugs in the history code in the past which has left users in the wild
- // with incorrect counts - http://crbug.com/84258).
- DCHECK(typed_count > 0);
-
- if (typed_count > kMaxTypedUrlVisits) {
- only_typed = true;
- skip_count = typed_count - kMaxTypedUrlVisits;
- } else if (total > kMaxTypedUrlVisits) {
- skip_count = total - kMaxTypedUrlVisits;
- }
- }
-
- for (VisitVector::const_iterator visit = visits.begin();
- visit != visits.end(); ++visit) {
- // Skip reload visits.
- if (PageTransitionCoreTypeIs(visit->transition, ui::PAGE_TRANSITION_RELOAD))
- continue;
-
- // If we only have room for typed visits, then only add typed visits.
- if (only_typed &&
- !PageTransitionCoreTypeIs(visit->transition,
- ui::PAGE_TRANSITION_TYPED)) {
- continue;
- }
-
- if (skip_count > 0) {
- // We have too many entries to fit, so we need to skip the oldest ones.
- // Only skip typed URLs if there are too many typed URLs to fit.
- if (only_typed ||
- !PageTransitionCoreTypeIs(visit->transition,
- ui::PAGE_TRANSITION_TYPED)) {
- --skip_count;
- continue;
- }
- }
- typed_url->add_visits(visit->visit_time.ToInternalValue());
- typed_url->add_visit_transitions(visit->transition);
- }
- DCHECK_EQ(skip_count, 0);
-
- CHECK_GT(typed_url->visits_size(), 0);
- CHECK_LE(typed_url->visits_size(), kMaxTypedUrlVisits);
- CHECK_EQ(typed_url->visits_size(), typed_url->visit_transitions_size());
-
- return true;
-}
-
-// static
-void TypedUrlSyncableService::UpdateURLRowFromTypedUrlSpecifics(
- const sync_pb::TypedUrlSpecifics& typed_url,
- history::URLRow* new_url) {
- DCHECK_GT(typed_url.visits_size(), 0);
- CHECK_EQ(typed_url.visit_transitions_size(), typed_url.visits_size());
- new_url->set_title(base::UTF8ToUTF16(typed_url.title()));
- new_url->set_hidden(typed_url.hidden());
- // Only provide the initial value for the last_visit field - after that, let
- // the history code update the last_visit field on its own.
- if (new_url->last_visit().is_null()) {
- new_url->set_last_visit(base::Time::FromInternalValue(
- typed_url.visits(typed_url.visits_size() - 1)));
- }
-}
-
-bool TypedUrlSyncableService::FixupURLAndGetVisits(URLRow* url,
- VisitVector* visits) {
- ++num_db_accesses_;
- CHECK(history_backend_);
- if (!history_backend_->GetMostRecentVisitsForURL(url->id(), kMaxVisitsToFetch,
- visits)) {
- ++num_db_errors_;
- // Couldn't load the visits for this URL due to some kind of DB error.
- // Don't bother writing this URL to the history DB (if we ignore the
- // error and continue, we might end up duplicating existing visits).
- DLOG(ERROR) << "Could not load visits for url: " << url->url();
- return false;
- }
-
- // Sometimes (due to a bug elsewhere in the history or sync code, or due to
- // a crash between adding a URL to the history database and updating the
- // visit DB) the visit vector for a URL can be empty. If this happens, just
- // create a new visit whose timestamp is the same as the last_visit time.
- // This is a workaround for http://crbug.com/84258.
- if (visits->empty()) {
- DVLOG(1) << "Found empty visits for URL: " << url->url();
- if (url->last_visit().is_null()) {
- // If modified URL is bookmarked, history backend treats it as modified
- // even if all its visits are deleted. Return false to stop further
- // processing because sync expects valid visit time for modified entry.
- return false;
- }
-
- VisitRow visit(url->id(), url->last_visit(), 0, ui::PAGE_TRANSITION_TYPED,
- 0);
- visits->push_back(visit);
- }
-
- // GetMostRecentVisitsForURL() returns the data in the opposite order that
- // we need it, so reverse it.
- std::reverse(visits->begin(), visits->end());
-
- // Sometimes, the last_visit field in the URL doesn't match the timestamp of
- // the last visit in our visit array (they come from different tables, so
- // crashes/bugs can cause them to mismatch), so just set it here.
- url->set_last_visit(visits->back().visit_time);
- DCHECK(CheckVisitOrdering(*visits));
-
- // Removes all visits that are older than the current expiration time. Visits
- // are in ascending order now, so we can check from beginning to check how
- // many expired visits.
- size_t num_expired_visits = 0;
- for (auto& visit : *visits) {
- base::Time time = visit.visit_time;
- if (!history_backend_->IsExpiredVisitTime(time))
- break;
- ++num_expired_visits;
- }
- if (num_expired_visits != 0) {
- if (num_expired_visits == visits->size()) {
- DVLOG(1) << "All visits are expired for url: " << url->url();
- visits->clear();
- return false;
- }
- visits->erase(visits->begin(), visits->begin() + num_expired_visits);
- }
- DCHECK(CheckVisitOrdering(*visits));
-
- return true;
-}
-
-void TypedUrlSyncableService::UpdateFromSyncDB(
- const sync_pb::TypedUrlSpecifics& typed_url,
- TypedUrlVisitVector* visits_to_add,
- history::VisitVector* visits_to_remove,
- history::URLRows* updated_urls,
- history::URLRows* new_urls) {
- history::URLRow new_url(GURL(typed_url.url()));
- history::VisitVector existing_visits;
- bool existing_url = history_backend_->GetURL(new_url.url(), &new_url);
- if (existing_url) {
- // This URL already exists locally - fetch the visits so we can
- // merge them below.
- if (!FixupURLAndGetVisits(&new_url, &existing_visits)) {
- return;
- }
- }
- visits_to_add->push_back(std::pair<GURL, std::vector<history::VisitInfo>>(
- new_url.url(), std::vector<history::VisitInfo>()));
-
- // Update the URL with information from the typed URL.
- UpdateURLRowFromTypedUrlSpecifics(typed_url, &new_url);
-
- // Figure out which visits we need to add.
- DiffVisits(existing_visits, typed_url, &visits_to_add->back().second,
- visits_to_remove);
-
- if (existing_url) {
- updated_urls->push_back(new_url);
- } else {
- new_urls->push_back(new_url);
- }
-}
-
-// static
-void TypedUrlSyncableService::DiffVisits(
- const history::VisitVector& history_visits,
- const sync_pb::TypedUrlSpecifics& sync_specifics,
- std::vector<history::VisitInfo>* new_visits,
- history::VisitVector* removed_visits) {
- DCHECK(new_visits);
- size_t old_visit_count = history_visits.size();
- size_t new_visit_count = sync_specifics.visits_size();
- size_t old_index = 0;
- size_t new_index = 0;
- while (old_index < old_visit_count && new_index < new_visit_count) {
- base::Time new_visit_time =
- base::Time::FromInternalValue(sync_specifics.visits(new_index));
- if (history_visits[old_index].visit_time < new_visit_time) {
- if (new_index > 0 && removed_visits) {
- // If there are visits missing from the start of the node, that
- // means that they were probably clipped off due to our code that
- // limits the size of the sync nodes - don't delete them from our
- // local history.
- removed_visits->push_back(history_visits[old_index]);
- }
- ++old_index;
- } else if (history_visits[old_index].visit_time > new_visit_time) {
- new_visits->push_back(history::VisitInfo(
- new_visit_time, ui::PageTransitionFromInt(
- sync_specifics.visit_transitions(new_index))));
- ++new_index;
- } else {
- ++old_index;
- ++new_index;
- }
- }
-
- if (removed_visits) {
- for (; old_index < old_visit_count; ++old_index) {
- removed_visits->push_back(history_visits[old_index]);
- }
- }
-
- for (; new_index < new_visit_count; ++new_index) {
- new_visits->push_back(history::VisitInfo(
- base::Time::FromInternalValue(sync_specifics.visits(new_index)),
- ui::PageTransitionFromInt(
- sync_specifics.visit_transitions(new_index))));
- }
-}
-
-} // namespace history
diff --git a/chromium/components/history/core/browser/typed_url_syncable_service.h b/chromium/components/history/core/browser/typed_url_syncable_service.h
deleted file mode 100644
index 9cad7f2acd5..00000000000
--- a/chromium/components/history/core/browser/typed_url_syncable_service.h
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright (c) 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_HISTORY_CORE_BROWSER_TYPED_URL_SYNCABLE_SERVICE_H_
-#define COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_SYNCABLE_SERVICE_H_
-
-#include <stdint.h>
-
-#include <set>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/scoped_observer.h"
-#include "base/sequence_checker.h"
-#include "components/history/core/browser/history_backend_observer.h"
-#include "components/history/core/browser/history_types.h"
-#include "components/sync/model/sync_change.h"
-#include "components/sync/model/sync_data.h"
-#include "components/sync/model/sync_error.h"
-#include "components/sync/model/sync_error_factory.h"
-#include "components/sync/model/syncable_service.h"
-#include "ui/base/page_transition_types.h"
-
-class GURL;
-
-namespace sync_pb {
-class TypedUrlSpecifics;
-};
-
-namespace history {
-
-class HistoryBackend;
-class TypedUrlSyncableServiceTest;
-class URLRow;
-
-class TypedUrlSyncableService : public syncer::SyncableService,
- public history::HistoryBackendObserver {
- public:
- explicit TypedUrlSyncableService(HistoryBackend* history_backend);
- ~TypedUrlSyncableService() override;
-
- static syncer::ModelType model_type() { return syncer::TYPED_URLS; }
-
- // syncer::SyncableService implementation.
- syncer::SyncMergeResult 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;
- syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
- syncer::SyncError ProcessSyncChanges(
- const base::Location& from_here,
- const syncer::SyncChangeList& change_list) override;
-
- // history::HistoryBackendObserver:
- void OnURLVisited(history::HistoryBackend* history_backend,
- ui::PageTransition transition,
- const history::URLRow& row,
- const history::RedirectList& redirects,
- base::Time visit_time) override;
- void OnURLsModified(history::HistoryBackend* history_backend,
- const history::URLRows& changed_urls) override;
- void OnURLsDeleted(history::HistoryBackend* history_backend,
- bool all_history,
- bool expired,
- const history::URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) override;
-
- // Returns the percentage of DB accesses that have resulted in an error.
- int GetErrorPercentage() const;
-
- // Return true if this function successfully converts the passed URL
- // information to a TypedUrlSpecifics structure for writing to the sync DB.
- static bool WriteToTypedUrlSpecifics(const URLRow& url,
- const VisitVector& visits,
- sync_pb::TypedUrlSpecifics* specifics)
- WARN_UNUSED_RESULT;
-
- private:
- friend class TypedUrlSyncableServiceTest;
-
- typedef std::vector<std::pair<URLID, URLRow>> TypedUrlUpdateVector;
- typedef std::vector<std::pair<GURL, std::vector<VisitInfo>>>
- TypedUrlVisitVector;
-
- // This is a helper map used only in Merge/Process* functions. The lifetime
- // of the iterator is longer than the map object.
- typedef std::map<GURL, std::pair<syncer::SyncChange::SyncChangeType, URLRow>>
- TypedUrlMap;
-
- // This is a helper map used to associate visit vectors from the history db
- // to the typed urls in the above map.
- typedef std::map<GURL, VisitVector> UrlVisitVectorMap;
-
- // Bitfield returned from MergeUrls to specify the result of a merge.
- typedef uint32_t MergeResult;
- static const MergeResult DIFF_NONE = 0;
- static const MergeResult DIFF_UPDATE_NODE = 1 << 0;
- static const MergeResult DIFF_LOCAL_ROW_CHANGED = 1 << 1;
- static const MergeResult DIFF_LOCAL_VISITS_ADDED = 1 << 2;
-
- // Helper method for getting the set of synced urls.
- // Set it as virtual for testing.
- void GetSyncedUrls(std::set<GURL>* urls) const;
-
- // Helper function that clears our error counters (used to reset stats after
- // model association so we can track model association errors separately).
- virtual void ClearErrorStats();
-
- // Compares |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 CreateOrUpdateUrl(const sync_pb::TypedUrlSpecifics& typed_url,
- TypedUrlMap* loaded_data,
- UrlVisitVectorMap* visit_vectors,
- history::URLRows* new_synced_urls,
- TypedUrlVisitVector* new_synced_visits,
- history::URLRows* updated_synced_urls);
-
- // Given a TypedUrlSpecifics object, removes all visits that are older than
- // the current expiration time. Note that this can result in having no visits
- // at all.
- sync_pb::TypedUrlSpecifics FilterExpiredVisits(
- const sync_pb::TypedUrlSpecifics& specifics);
-
- // 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
- // should be persisted to the sync node.
- // 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
- // 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,
- const history::URLRow& url,
- history::VisitVector* visits,
- history::URLRow* new_url,
- std::vector<history::VisitInfo>* new_visits);
-
- // Writes new typed url data from sync server to history backend.
- void WriteToHistoryBackend(const history::URLRows* new_urls,
- const history::URLRows* updated_urls,
- const std::vector<GURL>* deleted_urls,
- const TypedUrlVisitVector* new_visits,
- const history::VisitVector* deleted_visits);
-
- // Helper function that determines if we should ignore a URL for the purposes
- // of sync, because it contains invalid data.
- bool ShouldIgnoreUrl(const GURL& url);
-
- // Helper function that determines if we should ignore a URL for the purposes
- // of sync, based on the visits the URL had.
- bool ShouldIgnoreVisits(const history::VisitVector& visits);
-
- // Returns true if the caller should sync as a result of the passed visit
- // notification. We use this to throttle the number of sync changes we send
- // to the server so we don't hit the server for every
- // single typed URL visit.
- bool ShouldSyncVisit(int typed_count, ui::PageTransition transition);
-
- // Utility routine that either updates an existing sync node or creates a
- // new one for the passed |typed_url| if one does not already exist. Returns
- // false and sets an unrecoverable error if the operation failed.
- bool CreateOrUpdateSyncNode(URLRow typed_url,
- syncer::SyncChangeList* changes);
-
- // Utility routine for building a change from a typed url.
- void AddTypedUrlToChangeList(syncer::SyncChange::SyncChangeType change_type,
- const history::URLRow& row,
- const history::VisitVector& visits,
- std::string title,
- syncer::SyncChangeList* change_list);
-
- // Fills |new_url| with formatted data from |typed_url|.
- static void UpdateURLRowFromTypedUrlSpecifics(
- const sync_pb::TypedUrlSpecifics& typed_url,
- history::URLRow* new_url);
-
- // Fetches visits from the history DB corresponding to the passed URL. This
- // 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.
- // Returns false in two cases.
- // 1. we could not fetch the visits for the passed URL, and tracks DB error
- // statistics internally for reporting via UMA.
- // 2. All the visits are expired.
- virtual bool FixupURLAndGetVisits(URLRow* url, VisitVector* visits);
-
- // 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
- // 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
- // in the history DB.
- void UpdateFromSyncDB(const sync_pb::TypedUrlSpecifics& typed_url,
- TypedUrlVisitVector* visits_to_add,
- history::VisitVector* visits_to_remove,
- history::URLRows* updated_urls,
- history::URLRows* new_urls);
-
- // 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
- // care about which visits to remove.
- static void DiffVisits(const history::VisitVector& history_visits,
- const sync_pb::TypedUrlSpecifics& sync_specifics,
- std::vector<history::VisitInfo>* new_visits,
- history::VisitVector* removed_visits);
-
- // TODO(sync): Consider using "delete all" sync logic instead of in-memory
- // cache of typed urls. See http://crbug.com/231689.
- std::set<GURL> synced_typed_urls_;
-
- // The backend we're syncing local changes from and sync changes to.
- HistoryBackend* const history_backend_;
-
- // Whether we're currently processing changes from the syncer. While this is
- // true, we ignore any local url changes, since we triggered them.
- bool processing_syncer_changes_;
-
- // We receive ownership of |sync_processor_| and |error_handler_| in
- // MergeDataAndStartSyncing() and destroy them in StopSyncing().
- std::unique_ptr<syncer::SyncChangeProcessor> sync_processor_;
- std::unique_ptr<syncer::SyncErrorFactory> sync_error_handler_;
-
- // Statistics for the purposes of tracking the percentage of DB accesses that
- // fail for each client via UMA.
- int num_db_accesses_;
- int num_db_errors_;
-
- base::SequenceChecker sequence_checker_;
-
- ScopedObserver<history::HistoryBackend, history::HistoryBackendObserver>
- history_backend_observer_;
-
- DISALLOW_COPY_AND_ASSIGN(TypedUrlSyncableService);
-};
-
-} // namespace history
-
-#endif // COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_SYNCABLE_SERVICE_H_
diff --git a/chromium/components/history/core/browser/typed_url_syncable_service_unittest.cc b/chromium/components/history/core/browser/typed_url_syncable_service_unittest.cc
deleted file mode 100644
index 64641c22eea..00000000000
--- a/chromium/components/history/core/browser/typed_url_syncable_service_unittest.cc
+++ /dev/null
@@ -1,1616 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/history/core/browser/typed_url_syncable_service.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "components/history/core/browser/history_backend.h"
-#include "components/history/core/browser/history_backend_client.h"
-#include "components/history/core/browser/history_database_params.h"
-#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/model/attachments/attachment_service_proxy_for_test.h"
-#include "components/sync/model/fake_sync_change_processor.h"
-#include "components/sync/model/sync_change_processor_wrapper_for_test.h"
-#include "components/sync/model/sync_error.h"
-#include "components/sync/model/sync_error_factory_mock.h"
-#include "components/sync/protocol/sync.pb.h"
-#include "components/sync/protocol/typed_url_specifics.pb.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using history::HistoryBackend;
-using history::URLID;
-using history::URLRow;
-using history::URLRows;
-using history::VisitRow;
-using history::VisitVector;
-
-namespace history {
-
-namespace {
-
-// Constants used to limit size of visits processed. See
-// equivalent constants in typed_url_syncable_service.cc for descriptions.
-const int kMaxTypedUrlVisits = 100;
-const int kVisitThrottleThreshold = 10;
-const int kVisitThrottleMultiple = 10;
-
-// Visits with this timestamp are treated as expired.
-const int kExpiredVisit = -1;
-
-// Helper constants for tests.
-const char kTitle[] = "pie";
-const char kTitle2[] = "pie2";
-const char kURL[] = "http://pie.com/";
-
-bool URLsEqual(URLRow& row, sync_pb::TypedUrlSpecifics& specifics) {
- return ((row.url().spec().compare(specifics.url()) == 0) &&
- (base::UTF16ToUTF8(row.title()).compare(specifics.title()) == 0) &&
- (row.hidden() == specifics.hidden()));
-}
-
-bool URLsEqual(history::URLRow& lhs, history::URLRow& rhs) {
- // Only compare synced fields (ignore typed_count and visit_count as those
- // are maintained by the history subsystem).
- return (lhs.url().spec().compare(rhs.url().spec()) == 0) &&
- (lhs.title().compare(rhs.title()) == 0) &&
- (lhs.hidden() == rhs.hidden());
-}
-
-void AddNewestVisit(ui::PageTransition transition,
- int64_t visit_time,
- URLRow* url,
- VisitVector* visits) {
- base::Time time = base::Time::FromInternalValue(visit_time);
- visits->insert(visits->begin(), VisitRow(url->id(), time, 0, transition, 0));
-
- if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED)) {
- url->set_typed_count(url->typed_count() + 1);
- }
-
- url->set_last_visit(time);
- url->set_visit_count(visits->size());
-}
-
-void AddOldestVisit(ui::PageTransition transition,
- int64_t visit_time,
- URLRow* url,
- VisitVector* visits) {
- base::Time time = base::Time::FromInternalValue(visit_time);
- visits->push_back(VisitRow(url->id(), time, 0, transition, 0));
-
- if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED)) {
- url->set_typed_count(url->typed_count() + 1);
- }
-
- 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.
-URLRow MakeTypedUrlRow(const std::string& url,
- const std::string& title,
- int typed_count,
- int64_t last_visit,
- bool hidden,
- VisitVector* visits) {
- // Give each URL a unique ID, to mimic the behavior of the real database.
- GURL gurl(url);
- URLRow history_url(gurl);
- history_url.set_title(base::UTF8ToUTF16(title));
- history_url.set_typed_count(typed_count);
- history_url.set_hidden(hidden);
-
- base::Time last_visit_time = base::Time::FromInternalValue(last_visit);
- history_url.set_last_visit(last_visit_time);
-
- if (typed_count > 0) {
- // Add a typed visit for time |last_visit|.
- visits->push_back(VisitRow(history_url.id(), last_visit_time, 0,
- ui::PAGE_TRANSITION_TYPED, 0));
- } else {
- // Add a non-typed visit for time |last_visit|.
- visits->push_back(VisitRow(history_url.id(), last_visit_time, 0,
- ui::PAGE_TRANSITION_RELOAD, 0));
- }
-
- history_url.set_visit_count(visits->size());
- return history_url;
-}
-
-static sync_pb::TypedUrlSpecifics MakeTypedUrlSpecifics(const char* url,
- const char* title,
- int64_t last_visit,
- bool hidden) {
- sync_pb::TypedUrlSpecifics typed_url;
- typed_url.set_url(url);
- typed_url.set_title(title);
- typed_url.set_hidden(hidden);
- typed_url.add_visits(last_visit);
- typed_url.add_visit_transitions(ui::PAGE_TRANSITION_TYPED);
- return typed_url;
-}
-
-class TestHistoryBackend;
-
-class TestHistoryBackendDelegate : public HistoryBackend::Delegate {
- public:
- TestHistoryBackendDelegate() {}
-
- void NotifyProfileError(sql::InitStatus init_status,
- const std::string& diagnostics) override {}
- void SetInMemoryBackend(
- std::unique_ptr<InMemoryHistoryBackend> backend) override {}
- void NotifyFaviconsChanged(const std::set<GURL>& page_urls,
- const GURL& icon_url) override {}
- void NotifyURLVisited(ui::PageTransition transition,
- const URLRow& row,
- const RedirectList& redirects,
- base::Time visit_time) override {}
- void NotifyURLsModified(const URLRows& changed_urls) override {}
- void NotifyURLsDeleted(bool all_history,
- bool expired,
- const URLRows& deleted_rows,
- const std::set<GURL>& favicon_urls) override {}
- void NotifyKeywordSearchTermUpdated(const URLRow& row,
- KeywordID keyword_id,
- const base::string16& term) override {}
- void NotifyKeywordSearchTermDeleted(URLID url_id) override {}
- void DBLoaded() override {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestHistoryBackendDelegate);
-};
-
-class TestHistoryBackend : public HistoryBackend {
- public:
- TestHistoryBackend()
- : HistoryBackend(new TestHistoryBackendDelegate(),
- nullptr,
- base::ThreadTaskRunnerHandle::Get()) {}
-
- bool IsExpiredVisitTime(const base::Time& time) override {
- return time.ToInternalValue() == kExpiredVisit;
- }
-
- URLID GetIdByUrl(const GURL& gurl) {
- return db()->GetRowForURL(gurl, nullptr);
- }
-
- void SetVisitsForUrl(URLRow& new_url, const VisitVector visits) {
- std::vector<history::VisitInfo> added_visits;
- URLRows new_urls;
- DeleteURL(new_url.url());
- for (const auto& visit : visits) {
- added_visits.push_back(
- history::VisitInfo(visit.visit_time, visit.transition));
- }
- new_urls.push_back(new_url);
- AddPagesWithDetails(new_urls, history::SOURCE_SYNCED);
- AddVisits(new_url.url(), added_visits, history::SOURCE_SYNCED);
- new_url.set_id(GetIdByUrl(new_url.url()));
- }
-
- private:
- ~TestHistoryBackend() override {}
-};
-
-} // namespace
-
-class TypedUrlSyncableServiceTest : public testing::Test {
- public:
- TypedUrlSyncableServiceTest() : typed_url_sync_service_(nullptr) {}
- ~TypedUrlSyncableServiceTest() override {}
-
- void SetUp() override {
- fake_history_backend_ = new TestHistoryBackend();
- ASSERT_TRUE(test_dir_.CreateUniqueTempDir());
- fake_history_backend_->Init(
- false, TestHistoryDatabaseParamsForPath(test_dir_.GetPath()));
- typed_url_sync_service_ =
- fake_history_backend_->GetTypedUrlSyncableService();
- fake_change_processor_.reset(new syncer::FakeSyncChangeProcessor);
- }
-
- void TearDown() override {
- fake_history_backend_->Closing();
- }
-
- // Starts sync for |typed_url_sync_service_| with |initial_data| as the
- // initial sync data.
- void StartSyncing(const syncer::SyncDataList& initial_data);
-
- // Builds a set of url rows and visit vectors based on |num_typed_urls| and
- // |num_reload_urls|, and |urls|. The rows are stored into |rows|, the visit
- // vectors in |visit_vectors|, and the changes are pushed into the history
- // backend.
- // Returns true if sync receives the proper number of changes, false
- // otherwise.
- bool BuildAndPushLocalChanges(unsigned int num_typed_urls,
- unsigned int num_reload_urls,
- const std::vector<std::string>& urls,
- URLRows* rows,
- std::vector<VisitVector>* visit_vectors);
-
- // Fills |urls| with the set of synced urls within |typed_url_sync_service_|.
- void GetSyncedUrls(std::set<GURL>* urls) const;
-
- // Create and apply a change for url and its visits into history backend.
- VisitVector ApplyUrlAndVisitsChange(
- const std::string& url,
- const std::string& title,
- int typed_count,
- int64_t last_visit,
- bool hidden,
- syncer::SyncChange::SyncChangeType change_type);
-
- // Add typed_url_sync_service_ to fake_history_backend_'s observer's list.
- void AddObserver();
-
- // Fills |specifics| with the sync data for |url| and |visits|.
- static bool WriteToTypedUrlSpecifics(const URLRow& url,
- const VisitVector& visits,
- sync_pb::TypedUrlSpecifics* specifics);
-
- // Helper to call TypedUrlSyncableService's MergeURLs method.
- static TypedUrlSyncableService::MergeResult MergeUrls(
- const sync_pb::TypedUrlSpecifics& typed_url,
- const history::URLRow& url,
- history::VisitVector* visits,
- history::URLRow* new_url,
- std::vector<history::VisitInfo>* new_visits);
-
- // Helper to call TypedUrlSyncableService's DiffVisits method.
- static void DiffVisits(const history::VisitVector& history_visits,
- const sync_pb::TypedUrlSpecifics& sync_specifics,
- std::vector<history::VisitInfo>* new_visits,
- history::VisitVector* removed_visits);
-
- // Create a new row associated with a specific visit's time.
- static history::VisitRow CreateVisit(ui::PageTransition type,
- int64_t timestamp);
-
- static const TypedUrlSyncableService::MergeResult DIFF_NONE =
- TypedUrlSyncableService::DIFF_NONE;
- static const TypedUrlSyncableService::MergeResult DIFF_UPDATE_NODE =
- TypedUrlSyncableService::DIFF_UPDATE_NODE;
- static const TypedUrlSyncableService::MergeResult DIFF_LOCAL_ROW_CHANGED =
- TypedUrlSyncableService::DIFF_LOCAL_ROW_CHANGED;
- static const TypedUrlSyncableService::MergeResult DIFF_LOCAL_VISITS_ADDED =
- TypedUrlSyncableService::DIFF_LOCAL_VISITS_ADDED;
-
- protected:
- base::MessageLoop message_loop_;
- base::ScopedTempDir test_dir_;
- scoped_refptr<TestHistoryBackend> fake_history_backend_;
- TypedUrlSyncableService* typed_url_sync_service_;
- std::unique_ptr<syncer::FakeSyncChangeProcessor> fake_change_processor_;
-};
-
-void TypedUrlSyncableServiceTest::StartSyncing(
- const syncer::SyncDataList& initial_data) {
- DCHECK(fake_change_processor_.get());
-
- // Set change processor.
- syncer::SyncMergeResult result =
- typed_url_sync_service_->MergeDataAndStartSyncing(
- syncer::TYPED_URLS, initial_data,
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- fake_change_processor_.get())),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new syncer::SyncErrorFactoryMock()));
- typed_url_sync_service_->history_backend_observer_.RemoveAll();
- EXPECT_FALSE(result.error().IsSet()) << result.error().message();
-}
-
-bool TypedUrlSyncableServiceTest::BuildAndPushLocalChanges(
- unsigned int num_typed_urls,
- unsigned int num_reload_urls,
- const std::vector<std::string>& urls,
- URLRows* rows,
- std::vector<VisitVector>* visit_vectors) {
- unsigned int total_urls = num_typed_urls + num_reload_urls;
- DCHECK(urls.size() >= total_urls);
- if (!typed_url_sync_service_)
- return false;
-
- if (total_urls) {
- // Create new URL rows, populate the mock backend with its visits, and
- // send to the sync service.
- URLRows changed_urls;
-
- for (unsigned int i = 0; i < total_urls; ++i) {
- int typed = i < num_typed_urls ? 1 : 0;
- VisitVector visits;
- visit_vectors->push_back(visits);
- rows->push_back(MakeTypedUrlRow(urls[i], kTitle, typed, i + 3, false,
- &visit_vectors->back()));
- fake_history_backend_->SetVisitsForUrl(rows->back(),
- visit_vectors->back());
- changed_urls.push_back(rows->back());
- }
-
- typed_url_sync_service_->OnURLsModified(fake_history_backend_.get(),
- changed_urls);
- }
-
- // Check that communication with sync was successful.
- if (num_typed_urls != fake_change_processor_->changes().size())
- return false;
- return true;
-}
-
-void TypedUrlSyncableServiceTest::GetSyncedUrls(std::set<GURL>* urls) const {
- return typed_url_sync_service_->GetSyncedUrls(urls);
-}
-
-VisitVector TypedUrlSyncableServiceTest::ApplyUrlAndVisitsChange(
- const std::string& url,
- const std::string& title,
- int typed_count,
- int64_t last_visit,
- bool hidden,
- syncer::SyncChange::SyncChangeType change_type) {
- VisitVector visits;
- URLRow row =
- MakeTypedUrlRow(url, title, typed_count, last_visit, hidden, &visits);
- syncer::SyncChangeList change_list;
- sync_pb::EntitySpecifics entity_specifics;
- sync_pb::TypedUrlSpecifics* typed_url_specifics =
- entity_specifics.mutable_typed_url();
- WriteToTypedUrlSpecifics(row, visits, typed_url_specifics);
- syncer::SyncData sync_data = syncer::SyncData::CreateRemoteData(
- 1, entity_specifics, base::Time(), syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create());
- syncer::SyncChange sync_change(FROM_HERE, change_type, sync_data);
- change_list.push_back(sync_change);
- typed_url_sync_service_->ProcessSyncChanges(FROM_HERE, change_list);
- return visits;
-}
-
-void TypedUrlSyncableServiceTest::AddObserver() {
- typed_url_sync_service_->history_backend_observer_.Add(
- fake_history_backend_.get());
-}
-
-// Static.
-bool TypedUrlSyncableServiceTest::WriteToTypedUrlSpecifics(
- const URLRow& url,
- const VisitVector& visits,
- sync_pb::TypedUrlSpecifics* specifics) {
- return TypedUrlSyncableService::WriteToTypedUrlSpecifics(url, visits,
- specifics);
-}
-
-// Static.
-TypedUrlSyncableService::MergeResult TypedUrlSyncableServiceTest::MergeUrls(
- const sync_pb::TypedUrlSpecifics& typed_url,
- const history::URLRow& url,
- history::VisitVector* visits,
- history::URLRow* new_url,
- std::vector<history::VisitInfo>* new_visits) {
- return TypedUrlSyncableService::MergeUrls(typed_url, url, visits, new_url,
- new_visits);
-}
-
-// Static.
-void TypedUrlSyncableServiceTest::DiffVisits(
- const history::VisitVector& history_visits,
- const sync_pb::TypedUrlSpecifics& sync_specifics,
- std::vector<history::VisitInfo>* new_visits,
- history::VisitVector* removed_visits) {
- TypedUrlSyncableService::DiffVisits(history_visits, sync_specifics,
- new_visits, removed_visits);
-}
-
-// Static.
-history::VisitRow TypedUrlSyncableServiceTest::CreateVisit(
- ui::PageTransition type,
- int64_t timestamp) {
- return history::VisitRow(0, base::Time::FromInternalValue(timestamp), 0, type,
- 0);
-}
-
-// Create a local typed URL with one TYPED visit after sync has started. Check
-// that sync is sent an ADD change for the new URL.
-TEST_F(TypedUrlSyncableServiceTest, AddLocalTypedUrl) {
- // Create a local typed URL (simulate a typed visit) that is not already
- // in sync. Check that sync is sent an ADD change for the existing URL.
- URLRows url_rows;
- std::vector<VisitVector> visit_vectors;
- std::vector<std::string> urls;
- urls.push_back(kURL);
-
- StartSyncing(syncer::SyncDataList());
- ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
-
- URLRow url_row = url_rows.front();
- VisitVector visits = visit_vectors.front();
-
- // Check change processor.
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- ASSERT_EQ(1U, changes.size());
- ASSERT_TRUE(changes[0].IsValid());
- EXPECT_EQ(syncer::TYPED_URLS, changes[0].sync_data().GetDataType());
- EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
-
- // Get typed url specifics.
- sync_pb::TypedUrlSpecifics url_specifics =
- changes[0].sync_data().GetSpecifics().typed_url();
-
- EXPECT_TRUE(URLsEqual(url_row, url_specifics));
- ASSERT_EQ(1, url_specifics.visits_size());
- ASSERT_EQ(static_cast<const int>(visits.size()), url_specifics.visits_size());
- EXPECT_EQ(visits[0].visit_time.ToInternalValue(), url_specifics.visits(0));
- EXPECT_EQ(static_cast<const int>(visits[0].transition),
- url_specifics.visit_transitions(0));
-
- // Check that in-memory representation of sync state is accurate.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_FALSE(sync_state.empty());
- EXPECT_EQ(1U, sync_state.size());
- EXPECT_TRUE(sync_state.end() != sync_state.find(url_row.url()));
-}
-
-// Update a local typed URL that is already synced. Check that sync is sent an
-// UPDATE for the existing url, but RELOAD visits aren't synced.
-TEST_F(TypedUrlSyncableServiceTest, UpdateLocalTypedUrl) {
- URLRows url_rows;
- std::vector<VisitVector> visit_vectors;
- std::vector<std::string> urls;
- urls.push_back(kURL);
-
- StartSyncing(syncer::SyncDataList());
- ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- changes.clear();
-
- // Update the URL row, adding another typed visit to the visit vector.
- URLRow url_row = url_rows.front();
- VisitVector visits = visit_vectors.front();
-
- URLRows changed_urls;
- AddNewestVisit(ui::PAGE_TRANSITION_TYPED, 7, &url_row, &visits);
- AddNewestVisit(ui::PAGE_TRANSITION_RELOAD, 8, &url_row, &visits);
- AddNewestVisit(ui::PAGE_TRANSITION_LINK, 9, &url_row, &visits);
- fake_history_backend_->SetVisitsForUrl(url_row, visits);
- changed_urls.push_back(url_row);
-
- // Notify typed url sync service of the update.
- typed_url_sync_service_->OnURLsModified(fake_history_backend_.get(),
- changed_urls);
-
- ASSERT_EQ(1U, changes.size());
- ASSERT_TRUE(changes[0].IsValid());
- EXPECT_EQ(syncer::TYPED_URLS, changes[0].sync_data().GetDataType());
- EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
-
- sync_pb::TypedUrlSpecifics url_specifics =
- changes[0].sync_data().GetSpecifics().typed_url();
-
- EXPECT_TRUE(URLsEqual(url_row, url_specifics));
- ASSERT_EQ(3, url_specifics.visits_size());
- ASSERT_EQ(static_cast<const int>(visits.size()) - 1,
- url_specifics.visits_size());
-
- // Check that each visit has been translated/communicated correctly.
- // Note that the specifics record visits in chronological order, and the
- // visits from the db are in reverse chronological order.
- EXPECT_EQ(visits[0].visit_time.ToInternalValue(), url_specifics.visits(2));
- EXPECT_EQ(static_cast<const int>(visits[0].transition),
- url_specifics.visit_transitions(2));
- EXPECT_EQ(visits[2].visit_time.ToInternalValue(), url_specifics.visits(1));
- EXPECT_EQ(static_cast<const int>(visits[3].transition),
- url_specifics.visit_transitions(1));
- EXPECT_EQ(visits[3].visit_time.ToInternalValue(), url_specifics.visits(0));
- EXPECT_EQ(static_cast<const int>(visits[3].transition),
- url_specifics.visit_transitions(0));
-
- // Check that in-memory representation of sync state is accurate.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_FALSE(sync_state.empty());
- EXPECT_EQ(1U, sync_state.size());
- EXPECT_TRUE(sync_state.end() != sync_state.find(url_row.url()));
-}
-
-// Append a RELOAD visit to a typed url that is already synced. Check that sync
-// does not receive any updates.
-TEST_F(TypedUrlSyncableServiceTest, ReloadVisitLocalTypedUrl) {
- URLRows url_rows;
- std::vector<VisitVector> visit_vectors;
- std::vector<std::string> urls;
- urls.push_back(kURL);
-
- StartSyncing(syncer::SyncDataList());
- ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- changes.clear();
-
- // Update the URL row, adding another typed visit to the visit vector.
- URLRow url_row = url_rows.front();
- VisitVector visits = visit_vectors.front();
-
- URLRows changed_urls;
- AddNewestVisit(ui::PAGE_TRANSITION_RELOAD, 7, &url_row, &visits);
- fake_history_backend_->SetVisitsForUrl(url_row, visits);
- changed_urls.push_back(url_row);
-
- // Notify typed url sync service of the update.
- typed_url_sync_service_->OnURLVisited(
- fake_history_backend_.get(), ui::PAGE_TRANSITION_RELOAD, url_row,
- RedirectList(), base::Time::FromInternalValue(7));
-
- ASSERT_EQ(0U, changes.size());
-
- // Check that in-memory representation of sync state is accurate.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_FALSE(sync_state.empty());
- EXPECT_EQ(1U, sync_state.size());
- EXPECT_TRUE(sync_state.end() != sync_state.find(url_row.url()));
-}
-
-// Appends a LINK visit to an existing typed url. Check that sync does not
-// receive any changes.
-TEST_F(TypedUrlSyncableServiceTest, LinkVisitLocalTypedUrl) {
- URLRows url_rows;
- std::vector<VisitVector> visit_vectors;
- std::vector<std::string> urls;
- urls.push_back(kURL);
-
- StartSyncing(syncer::SyncDataList());
- ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- changes.clear();
-
- URLRow url_row = url_rows.front();
- VisitVector visits = visit_vectors.front();
-
- // Update the URL row, adding a non-typed visit to the visit vector.
- AddNewestVisit(ui::PAGE_TRANSITION_LINK, 6, &url_row, &visits);
- fake_history_backend_->SetVisitsForUrl(url_row, visits);
-
- ui::PageTransition transition = ui::PAGE_TRANSITION_LINK;
- // Notify typed url sync service of non-typed visit, expect no change.
- typed_url_sync_service_->OnURLVisited(fake_history_backend_.get(), transition,
- url_row, RedirectList(),
- base::Time::FromInternalValue(6));
- ASSERT_EQ(0u, changes.size());
-}
-
-// Appends a series of LINK visits followed by a TYPED one to an existing typed
-// url. Check that sync receives an UPDATE with the newest visit data.
-TEST_F(TypedUrlSyncableServiceTest, TypedVisitLocalTypedUrl) {
- URLRows url_rows;
- std::vector<VisitVector> visit_vectors;
- std::vector<std::string> urls;
- urls.push_back(kURL);
-
- StartSyncing(syncer::SyncDataList());
- ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- changes.clear();
-
- URLRow url_row = url_rows.front();
- VisitVector visits = visit_vectors.front();
-
- // Update the URL row, adding another typed visit to the visit vector.
- AddOldestVisit(ui::PAGE_TRANSITION_LINK, 1, &url_row, &visits);
- AddNewestVisit(ui::PAGE_TRANSITION_LINK, 6, &url_row, &visits);
- AddNewestVisit(ui::PAGE_TRANSITION_TYPED, 7, &url_row, &visits);
- fake_history_backend_->SetVisitsForUrl(url_row, visits);
-
- // Notify typed url sync service of typed visit.
- ui::PageTransition transition = ui::PAGE_TRANSITION_TYPED;
- typed_url_sync_service_->OnURLVisited(fake_history_backend_.get(), transition,
- url_row, RedirectList(),
- base::Time::Now());
-
- ASSERT_EQ(1U, changes.size());
- ASSERT_TRUE(changes[0].IsValid());
- EXPECT_EQ(syncer::TYPED_URLS, changes[0].sync_data().GetDataType());
- EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
-
- sync_pb::TypedUrlSpecifics url_specifics =
- changes[0].sync_data().GetSpecifics().typed_url();
-
- EXPECT_TRUE(URLsEqual(url_row, url_specifics));
- ASSERT_EQ(4u, visits.size());
- EXPECT_EQ(static_cast<const int>(visits.size()), url_specifics.visits_size());
-
- // Check that each visit has been translated/communicated correctly.
- // Note that the specifics record visits in chronological order, and the
- // visits from the db are in reverse chronological order.
- int r = url_specifics.visits_size() - 1;
- for (int i = 0; i < url_specifics.visits_size(); ++i, --r) {
- EXPECT_EQ(visits[i].visit_time.ToInternalValue(), url_specifics.visits(r));
- EXPECT_EQ(static_cast<const int>(visits[i].transition),
- url_specifics.visit_transitions(r));
- }
-
- // Check that in-memory representation of sync state is accurate.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_FALSE(sync_state.empty());
- EXPECT_EQ(1U, sync_state.size());
- EXPECT_TRUE(sync_state.end() != sync_state.find(url_row.url()));
-}
-
-// Delete several (but not all) local typed urls. Check that sync receives the
-// DELETE changes, and the non-deleted urls remain synced.
-TEST_F(TypedUrlSyncableServiceTest, DeleteLocalTypedUrl) {
- URLRows url_rows;
- std::vector<VisitVector> visit_vectors;
- std::vector<std::string> urls;
- urls.push_back("http://pie.com/");
- urls.push_back("http://cake.com/");
- urls.push_back("http://google.com/");
- urls.push_back("http://foo.com/");
- urls.push_back("http://bar.com/");
-
- StartSyncing(syncer::SyncDataList());
- ASSERT_TRUE(BuildAndPushLocalChanges(4, 1, urls, &url_rows, &visit_vectors));
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- changes.clear();
-
- // Check that in-memory representation of sync state is accurate.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_FALSE(sync_state.empty());
- EXPECT_EQ(4u, sync_state.size());
-
- // Simulate visit expiry of typed visit, no syncing is done
- // This is to test that sync relies on the in-memory cache to know
- // which urls were typed and synced, and should be deleted.
- url_rows[0].set_typed_count(0);
- VisitVector visits;
- fake_history_backend_->SetVisitsForUrl(url_rows[0], visits);
-
- // Delete some urls from backend and create deleted row vector.
- URLRows rows;
- for (size_t i = 0; i < 3u; ++i) {
- fake_history_backend_->DeleteURL(url_rows[i].url());
- rows.push_back(url_rows[i]);
- }
-
- // Notify typed url sync service.
- typed_url_sync_service_->OnURLsDeleted(fake_history_backend_.get(), false,
- false, rows, std::set<GURL>());
-
- ASSERT_EQ(3u, changes.size());
- for (size_t i = 0; i < changes.size(); ++i) {
- ASSERT_TRUE(changes[i].IsValid());
- ASSERT_EQ(syncer::TYPED_URLS, changes[i].sync_data().GetDataType());
- EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, changes[i].change_type());
- sync_pb::TypedUrlSpecifics url_specifics =
- changes[i].sync_data().GetSpecifics().typed_url();
- EXPECT_EQ(url_rows[i].url().spec(), url_specifics.url());
- }
-
- // Check that in-memory representation of sync state is accurate.
- std::set<GURL> sync_state_deleted;
- GetSyncedUrls(&sync_state_deleted);
- ASSERT_EQ(1u, sync_state_deleted.size());
- EXPECT_TRUE(sync_state_deleted.end() !=
- sync_state_deleted.find(url_rows[3].url()));
-}
-
-// Delete all local typed urls. Check that sync receives them all the DELETE
-// changes, and that the sync state afterwards is empty.
-TEST_F(TypedUrlSyncableServiceTest, DeleteAllLocalTypedUrl) {
- URLRows url_rows;
- std::vector<VisitVector> visit_vectors;
- std::vector<std::string> urls;
- urls.push_back("http://pie.com/");
- urls.push_back("http://cake.com/");
- urls.push_back("http://google.com/");
- urls.push_back("http://foo.com/");
- urls.push_back("http://bar.com/");
-
- StartSyncing(syncer::SyncDataList());
- ASSERT_TRUE(BuildAndPushLocalChanges(4, 1, urls, &url_rows, &visit_vectors));
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- changes.clear();
-
- // Check that in-memory representation of sync state is accurate.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_EQ(4u, sync_state.size());
-
- // Delete urls from backend.
- for (size_t i = 0; i < 4u; ++ i) {
- fake_history_backend_->DeleteURL(url_rows[i].url());
- }
- // Delete urls with |all_history| flag set.
- bool all_history = true;
-
- // Notify typed url sync service.
- typed_url_sync_service_->OnURLsDeleted(fake_history_backend_.get(),
- all_history, false, URLRows(),
- std::set<GURL>());
-
- ASSERT_EQ(4u, changes.size());
- for (size_t i = 0; i < changes.size(); ++i) {
- ASSERT_TRUE(changes[i].IsValid());
- ASSERT_EQ(syncer::TYPED_URLS, changes[i].sync_data().GetDataType());
- EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, changes[i].change_type());
- }
- // Check that in-memory representation of sync state is accurate.
- std::set<GURL> sync_state_deleted;
- GetSyncedUrls(&sync_state_deleted);
- EXPECT_TRUE(sync_state_deleted.empty());
-}
-
-// Saturate the visits for a typed url with both TYPED and LINK navigations.
-// Check that no more than kMaxTypedURLVisits are synced, and that LINK visits
-// are dropped rather than TYPED ones.
-TEST_F(TypedUrlSyncableServiceTest, MaxVisitLocalTypedUrl) {
- URLRows url_rows;
- std::vector<VisitVector> visit_vectors;
- std::vector<std::string> urls;
- urls.push_back(kURL);
-
- StartSyncing(syncer::SyncDataList());
- ASSERT_TRUE(BuildAndPushLocalChanges(0, 1, urls, &url_rows, &visit_vectors));
-
- URLRow url_row = url_rows.front();
- VisitVector visits;
-
- // 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)
- AddNewestVisit(ui::PAGE_TRANSITION_TYPED, i, &url_row, &visits);
- for (; i <= kMaxTypedUrlVisits; ++i)
- AddNewestVisit(ui::PAGE_TRANSITION_LINK, i, &url_row, &visits);
- for (; i <= kMaxTypedUrlVisits + 10; ++i)
- AddNewestVisit(ui::PAGE_TRANSITION_TYPED, i, &url_row, &visits);
-
- fake_history_backend_->SetVisitsForUrl(url_row, visits);
-
- // Notify typed url sync service of typed visit.
- ui::PageTransition transition = ui::PAGE_TRANSITION_TYPED;
- typed_url_sync_service_->OnURLVisited(fake_history_backend_.get(), transition,
- url_row, RedirectList(),
- base::Time::Now());
-
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- ASSERT_EQ(1U, changes.size());
- ASSERT_TRUE(changes[0].IsValid());
- ASSERT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
- sync_pb::TypedUrlSpecifics url_specifics =
- changes[0].sync_data().GetSpecifics().typed_url();
- ASSERT_EQ(kMaxTypedUrlVisits, url_specifics.visits_size());
-
- // Check that each visit has been translated/communicated correctly.
- // Note that the specifics records visits in chronological order, and the
- // visits from the db are in reverse chronological order.
- int num_typed_visits_synced = 0;
- int num_other_visits_synced = 0;
- int r = url_specifics.visits_size() - 1;
- for (int i = 0; i < url_specifics.visits_size(); ++i, --r) {
- if (url_specifics.visit_transitions(i) ==
- static_cast<int32_t>(ui::PAGE_TRANSITION_TYPED)) {
- ++num_typed_visits_synced;
- } else {
- ++num_other_visits_synced;
- }
- }
- EXPECT_EQ(kMaxTypedUrlVisits - 10, num_typed_visits_synced);
- EXPECT_EQ(10, num_other_visits_synced);
-}
-
-// Add enough visits to trigger throttling of updates to a typed url. Check that
-// sync does not receive an update until the proper throttle interval has been
-// reached.
-TEST_F(TypedUrlSyncableServiceTest, ThrottleVisitLocalTypedUrl) {
- URLRows url_rows;
- std::vector<VisitVector> visit_vectors;
- std::vector<std::string> urls;
- urls.push_back(kURL);
-
- StartSyncing(syncer::SyncDataList());
- ASSERT_TRUE(BuildAndPushLocalChanges(0, 1, urls, &url_rows, &visit_vectors));
-
- URLRow url_row = url_rows.front();
- VisitVector visits;
-
- // Add enough visits to the url so that typed count is above the throttle
- // limit, and not right on the interval that gets synced.
- int i = 1;
- for (; i < kVisitThrottleThreshold + kVisitThrottleMultiple / 2; ++i)
- AddNewestVisit(ui::PAGE_TRANSITION_TYPED, i, &url_row, &visits);
- fake_history_backend_->SetVisitsForUrl(url_row, visits);
-
- // Notify typed url sync service of typed visit.
- ui::PageTransition transition = ui::PAGE_TRANSITION_TYPED;
- typed_url_sync_service_->OnURLVisited(fake_history_backend_.get(), transition,
- url_row, RedirectList(),
- base::Time::Now());
-
- // Should throttle, so sync and local cache should not update.
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- ASSERT_EQ(0u, changes.size());
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_TRUE(sync_state.empty());
-
- for (; i % kVisitThrottleMultiple != 1; ++i)
- AddNewestVisit(ui::PAGE_TRANSITION_TYPED, i, &url_row, &visits);
- --i; // Account for the increment before the condition ends.
- fake_history_backend_->SetVisitsForUrl(url_row, visits);
-
- // Notify typed url sync service of typed visit.
- typed_url_sync_service_->OnURLVisited(fake_history_backend_.get(), transition,
- url_row, RedirectList(),
- base::Time::Now());
-
- ASSERT_EQ(1u, changes.size());
- ASSERT_TRUE(changes[0].IsValid());
- ASSERT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
- sync_pb::TypedUrlSpecifics url_specifics =
- changes[0].sync_data().GetSpecifics().typed_url();
- ASSERT_EQ(i, url_specifics.visits_size());
-
- GetSyncedUrls(&sync_state);
- EXPECT_FALSE(sync_state.empty());
-}
-
-// Add a typed url locally and one to sync with the same data. Starting sync
-// should result in no changes.
-TEST_F(TypedUrlSyncableServiceTest, MergeUrlNoChange) {
- // Add a url to backend.
- VisitVector visits;
- URLRow row = MakeTypedUrlRow(kURL, kTitle, 1, 3, false, &visits);
- fake_history_backend_->SetVisitsForUrl(row, visits);
-
- // Create the same data in sync.
- syncer::SyncDataList initial_sync_data;
- sync_pb::EntitySpecifics entity_specifics;
- sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
- WriteToTypedUrlSpecifics(row, visits, typed_url);
- syncer::SyncData data =
- syncer::SyncData::CreateLocalData(kURL, kTitle, entity_specifics);
-
- initial_sync_data.push_back(data);
- StartSyncing(initial_sync_data);
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- EXPECT_TRUE(changes.empty());
-
- // Check that the local cache was is still correct.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_FALSE(sync_state.empty());
- EXPECT_EQ(sync_state.count(row.url()), 1U);
-}
-
-// Add a corupted typed url locally, has typed url count 1, but no real typed
-// url visit. Starting sync should not pick up this url.
-TEST_F(TypedUrlSyncableServiceTest, MergeUrlNoTypedUrl) {
- // Add a url to backend.
- VisitVector visits;
- URLRow row = MakeTypedUrlRow(kURL, kTitle, 0, 3, false, &visits);
-
- // Mark typed_count to 1 even when there is no typed url visit.
- row.set_typed_count(1);
- fake_history_backend_->SetVisitsForUrl(row, visits);
-
- StartSyncing(syncer::SyncDataList());
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- EXPECT_TRUE(changes.empty());
-
- // Check that the local cache was is still correct.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_TRUE(sync_state.empty());
- EXPECT_EQ(sync_state.count(row.url()), 0U);
-}
-
-// Starting sync with no sync data should just push the local url to sync.
-TEST_F(TypedUrlSyncableServiceTest, MergeUrlEmptySync) {
- // Add a url to backend.
- VisitVector visits;
- URLRow row = MakeTypedUrlRow(kURL, kTitle, 1, 3, false, &visits);
- fake_history_backend_->SetVisitsForUrl(row, visits);
-
- StartSyncing(syncer::SyncDataList());
-
- // Check that the local cache is still correct.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_FALSE(sync_state.empty());
- EXPECT_EQ(sync_state.count(row.url()), 1U);
-
- // Check that the server was updated correctly.
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- ASSERT_EQ(1U, changes.size());
- ASSERT_TRUE(changes[0].IsValid());
- EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
- sync_pb::TypedUrlSpecifics url_specifics =
- changes[0].sync_data().GetSpecifics().typed_url();
- ASSERT_EQ(1, url_specifics.visits_size());
- EXPECT_EQ(3, url_specifics.visits(0));
- ASSERT_EQ(1, url_specifics.visit_transitions_size());
- EXPECT_EQ(static_cast<const int>(visits[0].transition),
- url_specifics.visit_transitions(0));
-}
-
-// Starting sync with no local data should just push the synced url into the
-// backend.
-TEST_F(TypedUrlSyncableServiceTest, MergeUrlEmptyLocal) {
- // Create the sync data.
- VisitVector visits;
- URLRow row = MakeTypedUrlRow(kURL, kTitle, 1, 3, false, &visits);
- syncer::SyncDataList initial_sync_data;
- sync_pb::EntitySpecifics entity_specifics;
- sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
- WriteToTypedUrlSpecifics(row, visits, typed_url);
- syncer::SyncData data =
- syncer::SyncData::CreateLocalData(kURL, kTitle, entity_specifics);
-
- initial_sync_data.push_back(data);
- StartSyncing(initial_sync_data);
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- EXPECT_TRUE(changes.empty());
-
- // Check that the local cache is updated correctly.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_FALSE(sync_state.empty());
- EXPECT_EQ(sync_state.count(row.url()), 1U);
-
- // Check that the backend was updated correctly.
- VisitVector all_visits;
- base::Time server_time = base::Time::FromInternalValue(3);
- URLID url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
- ASSERT_NE(0, url_id);
- fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
- ASSERT_EQ(1U, all_visits.size());
- EXPECT_EQ(server_time, all_visits[0].visit_time);
- EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
- all_visits[0].transition, visits[0].transition));
-}
-
-// Add a url to the local and sync data before sync begins, with the sync data
-// having more recent visits. Check that starting sync updates the backend
-// with the sync visit, while the older local visit is not pushed to sync.
-// The title should be updated to the sync version due to the more recent
-// timestamp.
-TEST_F(TypedUrlSyncableServiceTest, MergeUrlOldLocal) {
- // Add a url to backend.
- VisitVector visits;
- URLRow local_row = MakeTypedUrlRow(kURL, kTitle, 1, 3, false, &visits);
- fake_history_backend_->SetVisitsForUrl(local_row, visits);
-
- // Create sync data for the same url with a more recent visit.
- VisitVector server_visits;
- URLRow server_row =
- MakeTypedUrlRow(kURL, kTitle2, 1, 6, false, &server_visits);
- server_row.set_id(fake_history_backend_->GetIdByUrl(GURL(kURL)));
- syncer::SyncDataList initial_sync_data;
- sync_pb::EntitySpecifics entity_specifics;
- sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
- WriteToTypedUrlSpecifics(server_row, server_visits, typed_url);
- syncer::SyncData data =
- syncer::SyncData::CreateLocalData(kURL, kTitle2, entity_specifics);
-
- initial_sync_data.push_back(data);
- StartSyncing(initial_sync_data);
-
- // Check that the local cache was updated correctly.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_FALSE(sync_state.empty());
-
- // Check that the backend was updated correctly.
- VisitVector all_visits;
- base::Time server_time = base::Time::FromInternalValue(6);
- URLID url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
- ASSERT_NE(0, url_id);
- fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
- ASSERT_EQ(2U, all_visits.size());
- EXPECT_EQ(server_time, all_visits.back().visit_time);
- EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
- all_visits.back().transition, server_visits[0].transition));
- URLRow url_row;
- EXPECT_TRUE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
- EXPECT_EQ(kTitle2, base::UTF16ToUTF8(url_row.title()));
-
- // Check that the server was updated correctly.
- // The local history visit should not be added to sync because it is older
- // than sync's oldest visit.
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- ASSERT_EQ(1U, changes.size());
- ASSERT_TRUE(changes[0].IsValid());
- sync_pb::TypedUrlSpecifics url_specifics =
- changes[0].sync_data().GetSpecifics().typed_url();
- ASSERT_EQ(1, url_specifics.visits_size());
- EXPECT_EQ(6, url_specifics.visits(0));
- ASSERT_EQ(1, url_specifics.visit_transitions_size());
- EXPECT_EQ(static_cast<const int>(visits[0].transition),
- url_specifics.visit_transitions(0));
-}
-
-// Add a url to the local and sync data before sync begins, with the local data
-// having more recent visits. Check that starting sync updates the sync
-// with the local visits, while the older sync visit is not pushed to the
-// backend. Sync's title should be updated to the local version due to the more
-// recent timestamp.
-TEST_F(TypedUrlSyncableServiceTest, MergeUrlOldSync) {
- // Add a url to backend.
- VisitVector visits;
- URLRow local_row = MakeTypedUrlRow(kURL, kTitle2, 1, 3, false, &visits);
- fake_history_backend_->SetVisitsForUrl(local_row, visits);
-
- // Create sync data for the same url with an older visit.
- VisitVector server_visits;
- URLRow server_row =
- MakeTypedUrlRow(kURL, kTitle, 1, 2, false, &server_visits);
- syncer::SyncDataList initial_sync_data;
- sync_pb::EntitySpecifics entity_specifics;
- sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
- WriteToTypedUrlSpecifics(server_row, server_visits, typed_url);
- syncer::SyncData data =
- syncer::SyncData::CreateLocalData(kURL, kTitle, entity_specifics);
-
- initial_sync_data.push_back(data);
- StartSyncing(initial_sync_data);
-
- // Check that the local cache was updated correctly.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_FALSE(sync_state.empty());
-
- // Check that the backend was not updated.
- VisitVector all_visits;
- base::Time local_visit_time = base::Time::FromInternalValue(3);
- URLID url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
- ASSERT_NE(0, url_id);
- fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
- ASSERT_EQ(1U, all_visits.size());
- EXPECT_EQ(local_visit_time, all_visits[0].visit_time);
-
- // Check that the server was updated correctly.
- // The local history visit should not be added to sync because it is older
- // than sync's oldest visit.
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- ASSERT_EQ(1U, changes.size());
- ASSERT_TRUE(changes[0].IsValid());
- sync_pb::TypedUrlSpecifics url_specifics =
- changes[0].sync_data().GetSpecifics().typed_url();
- ASSERT_EQ(1, url_specifics.visits_size());
- EXPECT_EQ(3, url_specifics.visits(0));
- EXPECT_EQ(kTitle2, url_specifics.title());
- ASSERT_EQ(1, url_specifics.visit_transitions_size());
- EXPECT_EQ(static_cast<const int>(visits[0].transition),
- url_specifics.visit_transitions(0));
-}
-
-// Check that there is no crash during start sync, if history backend and sync
-// have same url, but sync has username/password in it.
-// Also check sync will not accept url with username and password.
-TEST_F(TypedUrlSyncableServiceTest, MergeUrlsWithUsernameAndPassword) {
- const char kURLWithUsernameAndPassword[] =
- "http://username:password@pie.com/";
-
- // Add a url to backend.
- VisitVector visits;
- URLRow local_row = MakeTypedUrlRow(kURL, kTitle2, 1, 3, false, &visits);
- fake_history_backend_->SetVisitsForUrl(local_row, visits);
-
- // Create sync data for the same url but contain username and password.
- VisitVector server_visits;
- URLRow server_row = MakeTypedUrlRow(kURLWithUsernameAndPassword, kTitle, 1, 3,
- false, &server_visits);
- syncer::SyncDataList initial_sync_data;
- sync_pb::EntitySpecifics entity_specifics;
- sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
- WriteToTypedUrlSpecifics(server_row, server_visits, typed_url);
- syncer::SyncData data =
- syncer::SyncData::CreateLocalData(kURL, kTitle, entity_specifics);
-
- // Make sure there is no crash when merge two urls.
- initial_sync_data.push_back(data);
- StartSyncing(initial_sync_data);
-
- // Check that the username and password url did not get merged.
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_EQ(1U, sync_state.size());
- EXPECT_EQ(1U, sync_state.count(GURL(kURL)));
-
- // Notify typed url sync service of the update.
- typed_url_sync_service_->OnURLVisited(
- fake_history_backend_.get(), ui::PAGE_TRANSITION_TYPED, server_row,
- RedirectList(), base::Time::FromInternalValue(7));
-
- // Check username/password url is not synced.
- GetSyncedUrls(&sync_state);
- EXPECT_EQ(1U, sync_state.size());
- EXPECT_EQ(1U, sync_state.count(GURL(kURL)));
-}
-
-// Create a remote typed URL and visit, then send to syncable service after sync
-// has started. Check that local DB is received the new URL and visit.
-TEST_F(TypedUrlSyncableServiceTest, AddUrlAndVisits) {
- StartSyncing(syncer::SyncDataList());
- VisitVector visits = ApplyUrlAndVisitsChange(kURL, kTitle, 1, 3, false,
- syncer::SyncChange::ACTION_ADD);
-
- base::Time visit_time = base::Time::FromInternalValue(3);
- VisitVector all_visits;
- URLID url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
- ASSERT_NE(0, url_id);
- fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
- EXPECT_EQ(1U, all_visits.size());
- EXPECT_EQ(visit_time, all_visits[0].visit_time);
- EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
- all_visits[0].transition, visits[0].transition));
- URLRow url_row;
- EXPECT_TRUE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
- EXPECT_EQ(kTitle, base::UTF16ToUTF8(url_row.title()));
-}
-
-// Update a remote typed URL and create a new visit that is already synced, then
-// send the update to syncable service. Check that local DB is received an
-// UPDATE for the existing url and new visit.
-TEST_F(TypedUrlSyncableServiceTest, UpdateUrlAndVisits) {
- StartSyncing(syncer::SyncDataList());
-
- std::set<GURL> sync_state;
- GetSyncedUrls(&sync_state);
- EXPECT_EQ(0U, sync_state.size());
-
- VisitVector visits = ApplyUrlAndVisitsChange(kURL, kTitle, 1, 3, false,
- syncer::SyncChange::ACTION_ADD);
- base::Time visit_time = base::Time::FromInternalValue(3);
- VisitVector all_visits;
- URLRow url_row;
-
- URLID url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
- ASSERT_NE(0, url_id);
-
- fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
- sync_state.clear();
- GetSyncedUrls(&sync_state);
- EXPECT_EQ(1U, all_visits.size());
- EXPECT_EQ(visit_time, all_visits[0].visit_time);
- EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
- all_visits[0].transition, visits[0].transition));
- EXPECT_EQ(1U, sync_state.size());
- EXPECT_TRUE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
- EXPECT_EQ(kTitle, base::UTF16ToUTF8(url_row.title()));
-
- VisitVector new_visits = ApplyUrlAndVisitsChange(
- kURL, kTitle2, 2, 6, false, syncer::SyncChange::ACTION_UPDATE);
-
- sync_state.clear();
- GetSyncedUrls(&sync_state);
- EXPECT_EQ(1U, sync_state.size());
- base::Time new_visit_time = base::Time::FromInternalValue(6);
- url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
- ASSERT_NE(0, url_id);
- fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
-
- EXPECT_EQ(2U, all_visits.size());
- EXPECT_EQ(new_visit_time, all_visits.back().visit_time);
- EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
- all_visits.back().transition, new_visits[0].transition));
- EXPECT_TRUE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
- EXPECT_EQ(kTitle2, base::UTF16ToUTF8(url_row.title()));
-}
-
-// Delete a typed urls which already synced. Check that local DB receives the
-// DELETE changes.
-TEST_F(TypedUrlSyncableServiceTest, DeleteUrlAndVisits) {
- URLRows url_rows;
- std::vector<VisitVector> visit_vectors;
- std::vector<std::string> urls;
- std::set<GURL> sync_state;
- urls.push_back(kURL);
-
- StartSyncing(syncer::SyncDataList());
- ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- changes.clear();
-
- base::Time visit_time = base::Time::FromInternalValue(3);
- VisitVector all_visits;
- URLID url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
- ASSERT_NE(0, url_id);
- fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
- EXPECT_EQ(1U, all_visits.size());
- EXPECT_EQ(visit_time, all_visits[0].visit_time);
- EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
- all_visits[0].transition, visit_vectors[0][0].transition));
- URLRow url_row;
- EXPECT_TRUE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
- EXPECT_EQ(kTitle, base::UTF16ToUTF8(url_row.title()));
- GetSyncedUrls(&sync_state);
- EXPECT_EQ(1U, sync_state.size());
-
- // Add observer back to check if TypedUrlSyncableService receive delete
- // changes back from fake_history_backend_.
- AddObserver();
-
- ApplyUrlAndVisitsChange(kURL, kTitle, 1, 3, false,
- syncer::SyncChange::ACTION_DELETE);
-
- sync_state.clear();
- GetSyncedUrls(&sync_state);
- EXPECT_EQ(0U, sync_state.size());
- EXPECT_FALSE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
- url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
- ASSERT_EQ(0, url_id);
-
- // Check TypedUrlSyncableService did not receive update since the update is
- // trigered by it.
- ASSERT_EQ(0u, changes.size());
-}
-
-// Create two set of visits for history DB and sync DB, two same set of visits
-// are same. Check DiffVisits will return empty set of diff visits.
-TEST_F(TypedUrlSyncableServiceTest, DiffVisitsSame) {
- history::VisitVector old_visits;
- sync_pb::TypedUrlSpecifics new_url;
-
- const int64_t visits[] = {1024, 2065, 65534, 1237684};
-
- for (int64_t visit : visits) {
- old_visits.push_back(history::VisitRow(0,
- base::Time::FromInternalValue(visit),
- 0, ui::PAGE_TRANSITION_TYPED, 0));
- new_url.add_visits(visit);
- new_url.add_visit_transitions(ui::PAGE_TRANSITION_TYPED);
- }
-
- std::vector<history::VisitInfo> new_visits;
- history::VisitVector removed_visits;
-
- DiffVisits(old_visits, new_url, &new_visits, &removed_visits);
- EXPECT_TRUE(new_visits.empty());
- EXPECT_TRUE(removed_visits.empty());
-}
-
-// Create two set of visits for history DB and sync DB. Check DiffVisits will
-// return correct set of diff visits.
-TEST_F(TypedUrlSyncableServiceTest, DiffVisitsRemove) {
- history::VisitVector old_visits;
- sync_pb::TypedUrlSpecifics new_url;
-
- const int64_t visits_left[] = {1, 2, 1024, 1500, 2065,
- 6000, 65534, 1237684, 2237684};
- const int64_t visits_right[] = {1024, 2065, 65534, 1237684};
-
- // DiffVisits will not remove the first visit, because we never delete visits
- // from the start of the array (since those visits can get truncated by the
- // size-limiting code).
- const int64_t visits_removed[] = {1500, 6000, 2237684};
-
- for (int64_t visit : visits_left) {
- old_visits.push_back(history::VisitRow(0,
- base::Time::FromInternalValue(visit),
- 0, ui::PAGE_TRANSITION_TYPED, 0));
- }
-
- for (int64_t visit : visits_right) {
- new_url.add_visits(visit);
- new_url.add_visit_transitions(ui::PAGE_TRANSITION_TYPED);
- }
-
- std::vector<history::VisitInfo> new_visits;
- history::VisitVector removed_visits;
-
- DiffVisits(old_visits, new_url, &new_visits, &removed_visits);
- EXPECT_TRUE(new_visits.empty());
- ASSERT_EQ(removed_visits.size(), arraysize(visits_removed));
- for (size_t i = 0; i < arraysize(visits_removed); ++i) {
- EXPECT_EQ(removed_visits[i].visit_time.ToInternalValue(),
- visits_removed[i]);
- }
-}
-
-// Create two set of visits for history DB and sync DB. Check DiffVisits will
-// return correct set of diff visits.
-TEST_F(TypedUrlSyncableServiceTest, DiffVisitsAdd) {
- history::VisitVector old_visits;
- sync_pb::TypedUrlSpecifics new_url;
-
- const int64_t visits_left[] = {1024, 2065, 65534, 1237684};
- const int64_t visits_right[] = {1, 1024, 1500, 2065,
- 6000, 65534, 1237684, 2237684};
-
- const int64_t visits_added[] = {1, 1500, 6000, 2237684};
-
- for (int64_t visit : visits_left) {
- old_visits.push_back(history::VisitRow(0,
- base::Time::FromInternalValue(visit),
- 0, ui::PAGE_TRANSITION_TYPED, 0));
- }
-
- for (int64_t visit : visits_right) {
- new_url.add_visits(visit);
- new_url.add_visit_transitions(ui::PAGE_TRANSITION_TYPED);
- }
-
- std::vector<history::VisitInfo> new_visits;
- history::VisitVector removed_visits;
-
- DiffVisits(old_visits, new_url, &new_visits, &removed_visits);
- EXPECT_TRUE(removed_visits.empty());
- ASSERT_TRUE(new_visits.size() == arraysize(visits_added));
- for (size_t i = 0; i < arraysize(visits_added); ++i) {
- EXPECT_EQ(new_visits[i].first.ToInternalValue(), visits_added[i]);
- EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
- new_visits[i].second, ui::PAGE_TRANSITION_TYPED));
- }
-}
-
-// Create three visits, check RELOAD visit is removed by
-// WriteToTypedUrlSpecifics so it won't apply to sync DB.
-TEST_F(TypedUrlSyncableServiceTest, WriteTypedUrlSpecifics) {
- history::VisitVector visits;
- visits.push_back(CreateVisit(ui::PAGE_TRANSITION_TYPED, 1));
- visits.push_back(CreateVisit(ui::PAGE_TRANSITION_RELOAD, 2));
- visits.push_back(CreateVisit(ui::PAGE_TRANSITION_LINK, 3));
-
- history::URLRow url(MakeTypedUrlRow(kURL, kTitle, 0, 100, false, &visits));
- sync_pb::TypedUrlSpecifics typed_url;
- WriteToTypedUrlSpecifics(url, visits, &typed_url);
- // RELOAD visits should be removed.
- EXPECT_EQ(2, typed_url.visits_size());
- EXPECT_EQ(typed_url.visit_transitions_size(), typed_url.visits_size());
- EXPECT_EQ(1, typed_url.visits(0));
- EXPECT_EQ(3, typed_url.visits(1));
- EXPECT_EQ(static_cast<int32_t>(ui::PAGE_TRANSITION_TYPED),
- typed_url.visit_transitions(0));
- EXPECT_EQ(static_cast<int32_t>(ui::PAGE_TRANSITION_LINK),
- typed_url.visit_transitions(1));
-}
-
-// Create 101 visits, check WriteToTypedUrlSpecifics will only keep 100 visits.
-TEST_F(TypedUrlSyncableServiceTest, TooManyVisits) {
- history::VisitVector visits;
- int64_t timestamp = 1000;
- visits.push_back(CreateVisit(ui::PAGE_TRANSITION_TYPED, timestamp++));
- for (int i = 0; i < 100; ++i) {
- visits.push_back(CreateVisit(ui::PAGE_TRANSITION_LINK, timestamp++));
- }
- history::URLRow url(
- MakeTypedUrlRow(kURL, kTitle, 0, timestamp++, false, &visits));
- sync_pb::TypedUrlSpecifics typed_url;
- WriteToTypedUrlSpecifics(url, visits, &typed_url);
- // # visits should be capped at 100.
- EXPECT_EQ(100, typed_url.visits_size());
- EXPECT_EQ(typed_url.visit_transitions_size(), typed_url.visits_size());
- EXPECT_EQ(1000, typed_url.visits(0));
- // Visit with timestamp of 1001 should be omitted since we should have
- // skipped that visit to stay under the cap.
- EXPECT_EQ(1002, typed_url.visits(1));
- EXPECT_EQ(static_cast<int32_t>(ui::PAGE_TRANSITION_TYPED),
- typed_url.visit_transitions(0));
- EXPECT_EQ(static_cast<int32_t>(ui::PAGE_TRANSITION_LINK),
- typed_url.visit_transitions(1));
-}
-
-// Create 306 visits, check WriteToTypedUrlSpecifics will only keep 100 typed
-// visits.
-TEST_F(TypedUrlSyncableServiceTest, TooManyTypedVisits) {
- history::VisitVector visits;
- int64_t timestamp = 1000;
- for (int i = 0; i < 102; ++i) {
- visits.push_back(CreateVisit(ui::PAGE_TRANSITION_TYPED, timestamp++));
- visits.push_back(CreateVisit(ui::PAGE_TRANSITION_LINK, timestamp++));
- visits.push_back(CreateVisit(ui::PAGE_TRANSITION_RELOAD, timestamp++));
- }
- history::URLRow url(
- MakeTypedUrlRow(kURL, kTitle, 0, timestamp++, false, &visits));
- sync_pb::TypedUrlSpecifics typed_url;
- WriteToTypedUrlSpecifics(url, visits, &typed_url);
- // # visits should be capped at 100.
- EXPECT_EQ(100, typed_url.visits_size());
- EXPECT_EQ(typed_url.visit_transitions_size(), typed_url.visits_size());
- // First two typed visits should be skipped.
- EXPECT_EQ(1006, typed_url.visits(0));
-
- // Ensure there are no non-typed visits since that's all that should fit.
- for (int i = 0; i < typed_url.visits_size(); ++i) {
- EXPECT_EQ(static_cast<int32_t>(ui::PAGE_TRANSITION_TYPED),
- typed_url.visit_transitions(i));
- }
-}
-
-// Create a typed url without visit, check WriteToTypedUrlSpecifics will return
-// false for it.
-TEST_F(TypedUrlSyncableServiceTest, NoTypedVisits) {
- history::VisitVector visits;
- history::URLRow url(MakeTypedUrlRow(kURL, kTitle, 0, 1000, false, &visits));
- sync_pb::TypedUrlSpecifics typed_url;
- EXPECT_FALSE(WriteToTypedUrlSpecifics(url, visits, &typed_url));
- // URLs with no typed URL visits should not been written to specifics.
- EXPECT_EQ(0, typed_url.visits_size());
-}
-
-TEST_F(TypedUrlSyncableServiceTest, MergeUrls) {
- history::VisitVector visits1;
- history::URLRow row1(MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &visits1));
- sync_pb::TypedUrlSpecifics specs1(
- MakeTypedUrlSpecifics(kURL, kTitle, 3, false));
- history::URLRow new_row1((GURL(kURL)));
- std::vector<history::VisitInfo> new_visits1;
- EXPECT_TRUE(TypedUrlSyncableServiceTest::MergeUrls(specs1, row1, &visits1,
- &new_row1, &new_visits1) ==
- TypedUrlSyncableServiceTest::DIFF_NONE);
-
- history::VisitVector visits2;
- history::URLRow row2(MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &visits2));
- sync_pb::TypedUrlSpecifics specs2(
- MakeTypedUrlSpecifics(kURL, kTitle, 3, true));
- history::VisitVector expected_visits2;
- history::URLRow expected2(
- MakeTypedUrlRow(kURL, kTitle, 2, 3, true, &expected_visits2));
- history::URLRow new_row2((GURL(kURL)));
- std::vector<history::VisitInfo> new_visits2;
- EXPECT_TRUE(TypedUrlSyncableServiceTest::MergeUrls(specs2, row2, &visits2,
- &new_row2, &new_visits2) ==
- TypedUrlSyncableServiceTest::DIFF_LOCAL_ROW_CHANGED);
- EXPECT_TRUE(URLsEqual(new_row2, expected2));
-
- history::VisitVector visits3;
- history::URLRow row3(MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &visits3));
- sync_pb::TypedUrlSpecifics specs3(
- MakeTypedUrlSpecifics(kURL, kTitle2, 3, true));
- history::VisitVector expected_visits3;
- history::URLRow expected3(
- MakeTypedUrlRow(kURL, kTitle2, 2, 3, true, &expected_visits3));
- history::URLRow new_row3((GURL(kURL)));
- std::vector<history::VisitInfo> new_visits3;
- EXPECT_EQ(TypedUrlSyncableServiceTest::DIFF_LOCAL_ROW_CHANGED |
- TypedUrlSyncableServiceTest::DIFF_NONE,
- TypedUrlSyncableServiceTest::MergeUrls(specs3, row3, &visits3,
- &new_row3, &new_visits3));
- EXPECT_TRUE(URLsEqual(new_row3, expected3));
-
- // Create one node in history DB with timestamp of 3, and one node in sync
- // DB with timestamp of 4. Result should contain one new item (4).
- history::VisitVector visits4;
- history::URLRow row4(MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &visits4));
- sync_pb::TypedUrlSpecifics specs4(
- MakeTypedUrlSpecifics(kURL, kTitle2, 4, false));
- history::VisitVector expected_visits4;
- history::URLRow expected4(
- MakeTypedUrlRow(kURL, kTitle2, 2, 4, false, &expected_visits4));
- history::URLRow new_row4((GURL(kURL)));
- std::vector<history::VisitInfo> new_visits4;
- EXPECT_EQ(TypedUrlSyncableServiceTest::DIFF_UPDATE_NODE |
- TypedUrlSyncableServiceTest::DIFF_LOCAL_ROW_CHANGED |
- TypedUrlSyncableServiceTest::DIFF_LOCAL_VISITS_ADDED,
- TypedUrlSyncableServiceTest::MergeUrls(specs4, row4, &visits4,
- &new_row4, &new_visits4));
- EXPECT_EQ(1U, new_visits4.size());
- EXPECT_EQ(specs4.visits(0), new_visits4[0].first.ToInternalValue());
- EXPECT_TRUE(URLsEqual(new_row4, expected4));
- EXPECT_EQ(2U, visits4.size());
-
- history::VisitVector visits5;
- history::URLRow row5(MakeTypedUrlRow(kURL, kTitle, 1, 4, false, &visits5));
- sync_pb::TypedUrlSpecifics specs5(
- MakeTypedUrlSpecifics(kURL, kTitle, 3, false));
- history::VisitVector expected_visits5;
- history::URLRow expected5(
- MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &expected_visits5));
- history::URLRow new_row5((GURL(kURL)));
- std::vector<history::VisitInfo> new_visits5;
-
- // UPDATE_NODE should be set because row5 has a newer last_visit timestamp.
- EXPECT_EQ(TypedUrlSyncableServiceTest::DIFF_UPDATE_NODE |
- TypedUrlSyncableServiceTest::DIFF_NONE,
- TypedUrlSyncableServiceTest::MergeUrls(specs5, row5, &visits5,
- &new_row5, &new_visits5));
- EXPECT_TRUE(URLsEqual(new_row5, expected5));
- EXPECT_EQ(0U, new_visits5.size());
-}
-
-TEST_F(TypedUrlSyncableServiceTest, MergeUrlsAfterExpiration) {
- // Tests to ensure that we don't resurrect expired URLs (URLs that have been
- // deleted from the history DB but still exist in the sync DB).
-
- // First, create a history row that has two visits, with timestamps 2 and 3.
- history::VisitVector(history_visits);
- history_visits.push_back(history::VisitRow(
- 0, base::Time::FromInternalValue(2), 0, ui::PAGE_TRANSITION_TYPED, 0));
- history::URLRow history_url(
- MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &history_visits));
-
- // Now, create a sync node with visits at timestamps 1, 2, 3, 4.
- sync_pb::TypedUrlSpecifics node(
- MakeTypedUrlSpecifics(kURL, kTitle, 1, false));
- node.add_visits(2);
- node.add_visits(3);
- node.add_visits(4);
- node.add_visit_transitions(2);
- node.add_visit_transitions(3);
- node.add_visit_transitions(4);
- history::URLRow new_history_url(history_url.url());
- std::vector<history::VisitInfo> new_visits;
- EXPECT_EQ(
- TypedUrlSyncableServiceTest::DIFF_NONE |
- TypedUrlSyncableServiceTest::DIFF_LOCAL_VISITS_ADDED,
- TypedUrlSyncableServiceTest::MergeUrls(node, history_url, &history_visits,
- &new_history_url, &new_visits));
- EXPECT_TRUE(URLsEqual(history_url, new_history_url));
- EXPECT_EQ(1U, new_visits.size());
- EXPECT_EQ(4U, new_visits[0].first.ToInternalValue());
- // We should not sync the visit with timestamp #1 since it is earlier than
- // any other visit for this URL in the history DB. But we should sync visit
- // #4.
- EXPECT_EQ(3U, history_visits.size());
- EXPECT_EQ(2U, history_visits[0].visit_time.ToInternalValue());
- EXPECT_EQ(3U, history_visits[1].visit_time.ToInternalValue());
- EXPECT_EQ(4U, history_visits[2].visit_time.ToInternalValue());
-}
-
-// Create a local typed URL with one expired TYPED visit,
-// MergeDataAndStartSyncing should not pass it to sync. And then add a non
-// expired visit, OnURLsModified should only send the non expired visit to sync.
-TEST_F(TypedUrlSyncableServiceTest, LocalExpiredTypedUrlDoNotSync) {
- URLRow row;
- URLRows changed_urls;
- VisitVector visits;
-
- // Add an expired typed URL to local.
- row = MakeTypedUrlRow(kURL, kTitle, 1, kExpiredVisit, false, &visits);
- fake_history_backend_->SetVisitsForUrl(row, visits);
-
- StartSyncing(syncer::SyncDataList());
-
- // Check change processor did not receive expired typed URL.
- syncer::SyncChangeList& changes = fake_change_processor_->changes();
- ASSERT_EQ(0U, changes.size());
-
- // Add a non expired typed URL to local.
- row = MakeTypedUrlRow(kURL, kTitle, 2, 1, false, &visits);
- fake_history_backend_->SetVisitsForUrl(row, visits);
-
- changed_urls.push_back(row);
- // Notify typed url sync service of the update.
- typed_url_sync_service_->OnURLsModified(fake_history_backend_.get(),
- changed_urls);
-
- // Check change processor did not receive expired typed URL.
- ASSERT_EQ(1U, changes.size());
- ASSERT_TRUE(changes[0].IsValid());
- EXPECT_EQ(syncer::TYPED_URLS, changes[0].sync_data().GetDataType());
- EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
-
- // Get typed url specifics. Verify only a non-expired visit received.
- sync_pb::TypedUrlSpecifics url_specifics =
- changes[0].sync_data().GetSpecifics().typed_url();
-
- EXPECT_TRUE(URLsEqual(row, url_specifics));
- ASSERT_EQ(1, url_specifics.visits_size());
- ASSERT_EQ(static_cast<const int>(visits.size() - 1),
- url_specifics.visits_size());
- EXPECT_EQ(visits[1].visit_time.ToInternalValue(), url_specifics.visits(0));
- EXPECT_EQ(static_cast<const int>(visits[1].transition),
- url_specifics.visit_transitions(0));
-}
-
-} // namespace history
diff --git a/chromium/components/history/core/browser/url_database.cc b/chromium/components/history/core/browser/url_database.cc
index 1ef2f03f61c..a60dc9ce1cf 100644
--- a/chromium/components/history/core/browser/url_database.cc
+++ b/chromium/components/history/core/browser/url_database.cc
@@ -253,8 +253,9 @@ bool URLDatabase::InitURLEnumeratorForSignificant(URLEnumerator* enumerator) {
DCHECK(!enumerator->initialized_);
std::string sql("SELECT ");
sql.append(kURLRowFields);
- sql.append(" FROM urls WHERE last_visit_time >= ? OR visit_count >= ? OR "
- "typed_count >= ?");
+ sql.append(
+ " FROM urls WHERE hidden = 0 AND "
+ "(last_visit_time >= ? OR visit_count >= ? OR typed_count >= ?)");
sql.append(
" ORDER BY typed_count DESC, last_visit_time DESC, visit_count "
"DESC");
diff --git a/chromium/components/history/core/browser/url_database_unittest.cc b/chromium/components/history/core/browser/url_database_unittest.cc
index 76692a116a4..a3f7fd6af9d 100644
--- a/chromium/components/history/core/browser/url_database_unittest.cc
+++ b/chromium/components/history/core/browser/url_database_unittest.cc
@@ -271,6 +271,11 @@ TEST_F(URLDatabaseTest, EnumeratorForSignificant) {
TimeDelta::FromDays(kLowQualityMatchAgeLimitInDays + 1));
EXPECT_TRUE(AddURL(url_no_match_last_visit));
+ URLRow url_hidden(GURL("http://www.url_match_higher_typed_count.com/hidden"));
+ url_hidden.set_typed_count(kLowQualityMatchTypedLimit + 1);
+ url_hidden.set_hidden(true);
+ EXPECT_TRUE(AddURL(url_hidden));
+
URLDatabase::URLEnumerator history_enum;
EXPECT_TRUE(InitURLEnumeratorForSignificant(&history_enum));
diff --git a/chromium/components/history/core/browser/url_row.cc b/chromium/components/history/core/browser/url_row.cc
index 130442d6eeb..cc974a258ca 100644
--- a/chromium/components/history/core/browser/url_row.cc
+++ b/chromium/components/history/core/browser/url_row.cc
@@ -6,6 +6,8 @@
#include <algorithm>
+#include "base/trace_event/memory_usage_estimator.h"
+
namespace history {
URLRow::URLRow() {
@@ -33,6 +35,7 @@ URLRow::~URLRow() {
}
URLRow& URLRow::operator=(const URLRow& other) = default;
+URLRow& URLRow::operator=(URLRow&& other) = default;
void URLRow::Swap(URLRow* other) {
std::swap(id_, other->id_);
@@ -44,6 +47,11 @@ void URLRow::Swap(URLRow* other) {
std::swap(hidden_, other->hidden_);
}
+size_t URLRow::EstimateMemoryUsage() const {
+ return base::trace_event::EstimateMemoryUsage(url_) +
+ base::trace_event::EstimateMemoryUsage(title_);
+}
+
URLResult::URLResult() {}
URLResult::URLResult(const GURL& url, base::Time visit_time)
diff --git a/chromium/components/history/core/browser/url_row.h b/chromium/components/history/core/browser/url_row.h
index 907ad2a1bf8..8f6f9cf5a0d 100644
--- a/chromium/components/history/core/browser/url_row.h
+++ b/chromium/components/history/core/browser/url_row.h
@@ -35,6 +35,7 @@ class URLRow {
virtual ~URLRow();
URLRow& operator=(const URLRow& other);
+ URLRow& operator=(URLRow&& other);
URLID id() const { return id_; }
@@ -96,6 +97,10 @@ class URLRow {
hidden_ = hidden;
}
+ // Estimates dynamic memory usage.
+ // See base/trace_event/memory_usage_estimator.h for more info.
+ size_t EstimateMemoryUsage() const;
+
// Helper functor that determines if an URLRow refers to a given URL.
class URLRowHasURL {
public:
diff --git a/chromium/components/history/core/browser/visitsegment_database.cc b/chromium/components/history/core/browser/visitsegment_database.cc
index b088f292abc..ea5eb049e25 100644
--- a/chromium/components/history/core/browser/visitsegment_database.cc
+++ b/chromium/components/history/core/browser/visitsegment_database.cc
@@ -9,13 +9,13 @@
#include <stdint.h>
#include <algorithm>
+#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "components/history/core/browser/page_usage_data.h"
@@ -153,16 +153,6 @@ bool VisitSegmentDatabase::UpdateSegmentRepresentationURL(SegmentID segment_id,
return statement.Run();
}
-URLID VisitSegmentDatabase::GetSegmentRepresentationURL(SegmentID segment_id) {
- sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
- "SELECT url_id FROM segments WHERE id = ?"));
- statement.BindInt64(0, segment_id);
-
- if (statement.Step())
- return statement.ColumnInt64(0);
- return 0;
-}
-
SegmentID VisitSegmentDatabase::CreateSegment(URLID url_id,
const std::string& segment_name) {
sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
@@ -235,7 +225,7 @@ VisitSegmentDatabase::QuerySegmentUsage(
while (statement.Step()) {
SegmentID segment_id = statement.ColumnInt64(0);
if (segment_id != previous_segment_id) {
- segments.push_back(base::MakeUnique<PageUsageData>(segment_id));
+ segments.push_back(std::make_unique<PageUsageData>(segment_id));
previous_segment_id = segment_id;
}
@@ -292,14 +282,6 @@ VisitSegmentDatabase::QuerySegmentUsage(
return results;
}
-bool VisitSegmentDatabase::DeleteSegmentData(base::Time older_than) {
- sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
- "DELETE FROM segment_usage WHERE time_slot < ?"));
- statement.BindInt64(0, older_than.LocalMidnight().ToInternalValue());
-
- return statement.Run();
-}
-
bool VisitSegmentDatabase::DeleteSegmentForURL(URLID url_id) {
sql::Statement delete_usage(GetDB().GetCachedStatement(SQL_FROM_HERE,
"DELETE FROM segment_usage WHERE segment_id IN "
diff --git a/chromium/components/history/core/browser/visitsegment_database.h b/chromium/components/history/core/browser/visitsegment_database.h
index e50685affa3..795c35bbcf6 100644
--- a/chromium/components/history/core/browser/visitsegment_database.h
+++ b/chromium/components/history/core/browser/visitsegment_database.h
@@ -41,10 +41,6 @@ class VisitSegmentDatabase {
bool UpdateSegmentRepresentationURL(SegmentID segment_id,
URLID url_id);
- // Return the ID of the URL currently used to represent this segment or 0 if
- // an error occured.
- URLID GetSegmentRepresentationURL(SegmentID segment_id);
-
// Create a segment for the provided URL ID with the given name. Returns the
// ID of the newly created segment, or 0 on failure.
SegmentID CreateSegment(URLID url_id, const std::string& segment_name);
@@ -62,13 +58,6 @@ class VisitSegmentDatabase {
int max_result_count,
const base::Callback<bool(const GURL&)>& url_filter);
- // Delete all the segment usage data which is older than the provided time
- // stamp.
- bool DeleteSegmentData(base::Time older_than);
-
- // Change the presentation id for the segment identified by |segment_id|
- bool SetSegmentPresentationIndex(SegmentID segment_id, int index);
-
// Delete the segment currently using the provided url for representation.
// This will also delete any associated segment usage data.
bool DeleteSegmentForURL(URLID url_id);
diff --git a/chromium/components/history/ios/browser/history_database_helper.cc b/chromium/components/history/ios/browser/history_database_helper.cc
index 6f2f22e01d8..6378dbb9268 100644
--- a/chromium/components/history/ios/browser/history_database_helper.cc
+++ b/chromium/components/history/ios/browser/history_database_helper.cc
@@ -10,7 +10,8 @@
namespace history {
namespace {
-// Values are copied from content/public/browser/download_interrupt_reasons.h.
+// Values are copied from
+// components/download/public/common/download_interrupt_reasons.h.
// Their value is irrelevant for iOS but must be kept in sync until iOS code
// downstream stops compiling some part of content.
diff --git a/chromium/components/image_fetcher/core/image_data_fetcher.cc b/chromium/components/image_fetcher/core/image_data_fetcher.cc
index a58fc4ac596..1ccc3b5cc8a 100644
--- a/chromium/components/image_fetcher/core/image_data_fetcher.cc
+++ b/chromium/components/image_fetcher/core/image_data_fetcher.cc
@@ -24,6 +24,8 @@ const char kContentLocationHeader[] = "Content-Location";
namespace image_fetcher {
+const int ImageDataFetcher::kFirstUrlFetcherId = 163163;
+
// An active image URL fetcher request. The struct contains the related requests
// state.
struct ImageDataFetcher::ImageDataFetcherRequest {
@@ -44,7 +46,7 @@ ImageDataFetcher::ImageDataFetcher(
net::URLRequestContextGetter* url_request_context_getter)
: url_request_context_getter_(url_request_context_getter),
data_use_service_name_(DataUseUserData::IMAGE_FETCHER_UNTAGGED),
- next_url_fetcher_id_(0) {}
+ next_url_fetcher_id_(kFirstUrlFetcherId) {}
ImageDataFetcher::~ImageDataFetcher() {}
diff --git a/chromium/components/image_fetcher/core/image_data_fetcher.h b/chromium/components/image_fetcher/core/image_data_fetcher.h
index 503487da2b9..fb7558d5c2b 100644
--- a/chromium/components/image_fetcher/core/image_data_fetcher.h
+++ b/chromium/components/image_fetcher/core/image_data_fetcher.h
@@ -29,6 +29,11 @@ namespace image_fetcher {
class ImageDataFetcher : public net::URLFetcherDelegate {
public:
+ // Fetchers created by this class will be assigned an incremental id starting
+ // from |kFirstUrlFetcherId|, so unit tests can differentiate the URLFetchers
+ // used by this class from other fetchers.
+ const static int kFirstUrlFetcherId;
+
// Callback with the |image_data|. If an error prevented a http response,
// |request_metadata.response_code| will be RESPONSE_CODE_INVALID.
// TODO(treib): Pass |image_data| out by value, or use RefCountedBytes, to
diff --git a/chromium/components/image_fetcher/core/image_data_fetcher_unittest.cc b/chromium/components/image_fetcher/core/image_data_fetcher_unittest.cc
index 99c45a318c6..d0ffca406e1 100644
--- a/chromium/components/image_fetcher/core/image_data_fetcher_unittest.cc
+++ b/chromium/components/image_fetcher/core/image_data_fetcher_unittest.cc
@@ -73,7 +73,8 @@ TEST_F(ImageDataFetcherTest, FetchImageData) {
expected_metadata));
// Get and configure the TestURLFetcher.
- net::TestURLFetcher* test_url_fetcher = fetcher_factory_.GetFetcherByID(0);
+ net::TestURLFetcher* test_url_fetcher =
+ fetcher_factory_.GetFetcherByID(ImageDataFetcher::kFirstUrlFetcherId);
ASSERT_NE(nullptr, test_url_fetcher);
EXPECT_TRUE(test_url_fetcher->GetLoadFlags() & net::LOAD_DO_NOT_SEND_COOKIES);
EXPECT_TRUE(test_url_fetcher->GetLoadFlags() & net::LOAD_DO_NOT_SAVE_COOKIES);
@@ -111,7 +112,8 @@ TEST_F(ImageDataFetcherTest, FetchImageData_FromCache) {
expected_metadata));
// Get and configure the TestURLFetcher.
- net::TestURLFetcher* test_url_fetcher = fetcher_factory_.GetFetcherByID(0);
+ net::TestURLFetcher* test_url_fetcher =
+ fetcher_factory_.GetFetcherByID(ImageDataFetcher::kFirstUrlFetcherId);
ASSERT_NE(nullptr, test_url_fetcher);
test_url_fetcher->set_status(
net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK));
@@ -145,7 +147,8 @@ TEST_F(ImageDataFetcherTest, FetchImageData_NotFound) {
EXPECT_CALL(*this, OnImageDataFetched(std::string(), expected_metadata));
// Get and configure the TestURLFetcher.
- net::TestURLFetcher* test_url_fetcher = fetcher_factory_.GetFetcherByID(0);
+ net::TestURLFetcher* test_url_fetcher =
+ fetcher_factory_.GetFetcherByID(ImageDataFetcher::kFirstUrlFetcherId);
ASSERT_NE(nullptr, test_url_fetcher);
test_url_fetcher->set_status(
net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK));
@@ -178,7 +181,8 @@ TEST_F(ImageDataFetcherTest, FetchImageData_WithContentLocation) {
EXPECT_CALL(*this, OnImageDataFetched(std::string(), expected_metadata));
// Get and configure the TestURLFetcher.
- net::TestURLFetcher* test_url_fetcher = fetcher_factory_.GetFetcherByID(0);
+ net::TestURLFetcher* test_url_fetcher =
+ fetcher_factory_.GetFetcherByID(ImageDataFetcher::kFirstUrlFetcherId);
ASSERT_NE(nullptr, test_url_fetcher);
test_url_fetcher->set_status(
net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK));
@@ -210,7 +214,8 @@ TEST_F(ImageDataFetcherTest, FetchImageData_FailedRequest) {
*this, OnImageDataFetchedFailedRequest(std::string(), expected_metadata));
// Get and configure the TestURLFetcher.
- net::TestURLFetcher* test_url_fetcher = fetcher_factory_.GetFetcherByID(0);
+ net::TestURLFetcher* test_url_fetcher =
+ fetcher_factory_.GetFetcherByID(ImageDataFetcher::kFirstUrlFetcherId);
ASSERT_NE(nullptr, test_url_fetcher);
test_url_fetcher->set_status(net::URLRequestStatus(
net::URLRequestStatus::FAILED, net::ERR_INVALID_URL));
@@ -233,11 +238,13 @@ TEST_F(ImageDataFetcherTest, FetchImageData_MultipleRequests) {
// Multiple calls to FetchImageData for the same URL will result in
// multiple URLFetchers being created.
- net::TestURLFetcher* test_url_fetcher = fetcher_factory_.GetFetcherByID(0);
+ net::TestURLFetcher* test_url_fetcher =
+ fetcher_factory_.GetFetcherByID(ImageDataFetcher::kFirstUrlFetcherId);
ASSERT_NE(nullptr, test_url_fetcher);
test_url_fetcher->delegate()->OnURLFetchComplete(test_url_fetcher);
- test_url_fetcher = fetcher_factory_.GetFetcherByID(1);
+ test_url_fetcher =
+ fetcher_factory_.GetFetcherByID(ImageDataFetcher::kFirstUrlFetcherId + 1);
ASSERT_NE(nullptr, test_url_fetcher);
test_url_fetcher->delegate()->OnURLFetchComplete(test_url_fetcher);
}
@@ -263,7 +270,8 @@ TEST_F(ImageDataFetcherTest, FetchImageData_CancelFetchIfImageExceedsMaxSize) {
EXPECT_CALL(*this, OnImageDataFetched(std::string(), expected_metadata));
// Get and configure the TestURLFetcher.
- net::TestURLFetcher* test_url_fetcher = fetcher_factory_.GetFetcherByID(0);
+ net::TestURLFetcher* test_url_fetcher =
+ fetcher_factory_.GetFetcherByID(ImageDataFetcher::kFirstUrlFetcherId);
ASSERT_NE(nullptr, test_url_fetcher);
// Create a completely valid response that is never used. This is to make sure
@@ -286,26 +294,30 @@ TEST_F(ImageDataFetcherTest, FetchImageData_CancelFetchIfImageExceedsMaxSize) {
/*total=*/-1, // not determined
/*current_network_bytes=*/0); // not relevant
// The URL fetch should be running ...
- ASSERT_NE(nullptr, fetcher_factory_.GetFetcherByID(0));
+ ASSERT_NE(nullptr, fetcher_factory_.GetFetcherByID(
+ ImageDataFetcher::kFirstUrlFetcherId));
test_url_fetcher->delegate()->OnURLFetchDownloadProgress(
test_url_fetcher,
768 * 1024, // Current bytes are not exeeding the limit.
/*total=*/-1, /*current_network_bytes=*/0);
// ... and running ...
- ASSERT_NE(nullptr, fetcher_factory_.GetFetcherByID(0));
+ ASSERT_NE(nullptr, fetcher_factory_.GetFetcherByID(
+ ImageDataFetcher::kFirstUrlFetcherId));
test_url_fetcher->delegate()->OnURLFetchDownloadProgress(
test_url_fetcher, kMaxDownloadBytes, // Still not exeeding the limit.
/*total=*/-1, /*current_network_bytes=*/0);
// ... and running ...
- ASSERT_NE(nullptr, fetcher_factory_.GetFetcherByID(0));
+ ASSERT_NE(nullptr, fetcher_factory_.GetFetcherByID(
+ ImageDataFetcher::kFirstUrlFetcherId));
test_url_fetcher->delegate()->OnURLFetchDownloadProgress(
test_url_fetcher, kMaxDownloadBytes + 1, // Limits are exceeded.
/*total=*/-1, /*current_network_bytes=*/0);
// ... and be canceled.
- EXPECT_EQ(nullptr, fetcher_factory_.GetFetcherByID(0));
+ EXPECT_EQ(nullptr, fetcher_factory_.GetFetcherByID(
+ ImageDataFetcher::kFirstUrlFetcherId));
}
} // namespace image_fetcher
diff --git a/chromium/components/image_fetcher/core/image_fetcher_impl.cc b/chromium/components/image_fetcher/core/image_fetcher_impl.cc
index ccbc25cf8d7..0cf6c102e8c 100644
--- a/chromium/components/image_fetcher/core/image_fetcher_impl.cc
+++ b/chromium/components/image_fetcher/core/image_fetcher_impl.cc
@@ -101,7 +101,8 @@ void ImageFetcherImpl::OnImageDecoded(const GURL& image_url,
// Run all callbacks
for (const auto& callback : request->callbacks) {
- callback.Run(request->id, image, metadata);
+ if (callback)
+ callback.Run(request->id, image, metadata);
}
// Inform the ImageFetcherDelegate.
diff --git a/chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm b/chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm
index 6cedad9ca2b..75230cc7d1c 100644
--- a/chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm
+++ b/chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm
@@ -6,10 +6,11 @@
#import <UIKit/UIKit.h>
+#include <memory>
+
#include "base/ios/ios_util.h"
#include "base/mac/scoped_block.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread.h"
@@ -111,7 +112,7 @@ class IOSImageDataFetcherWrapperTest : public PlatformTest {
result_ = [UIImage imageWithData:data];
called_ = true;
} copy]) {
- image_fetcher_ = base::MakeUnique<IOSImageDataFetcherWrapper>(
+ image_fetcher_ = std::make_unique<IOSImageDataFetcherWrapper>(
new net::TestURLRequestContextGetter(
base::ThreadTaskRunnerHandle::Get()));
}
@@ -120,7 +121,8 @@ class IOSImageDataFetcherWrapperTest : public PlatformTest {
image_fetcher_->FetchImageDataWebpDecoded(GURL(kTestUrl), callback_);
EXPECT_EQ(nil, result_);
EXPECT_EQ(false, called_);
- net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
+ net::TestURLFetcher* fetcher =
+ factory_.GetFetcherByID(ImageDataFetcher::kFirstUrlFetcherId);
DCHECK(fetcher);
DCHECK(fetcher->delegate());
return fetcher;
diff --git a/chromium/components/image_fetcher/ios/ios_image_decoder_impl.mm b/chromium/components/image_fetcher/ios/ios_image_decoder_impl.mm
index 2e7ca0e68ea..ee900df7a45 100644
--- a/chromium/components/image_fetcher/ios/ios_image_decoder_impl.mm
+++ b/chromium/components/image_fetcher/ios/ios_image_decoder_impl.mm
@@ -6,10 +6,11 @@
#import <UIKit/UIKit.h>
+#include <memory>
+
#include "base/callback.h"
#import "base/mac/bind_objc_block.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/task_scheduler/post_task.h"
#import "components/image_fetcher/ios/webp_decoder.h"
@@ -103,7 +104,7 @@ void IOSImageDecoderImpl::CreateUIImageAndRunCallback(
}
std::unique_ptr<ImageDecoder> CreateIOSImageDecoder() {
- return base::MakeUnique<IOSImageDecoderImpl>();
+ return std::make_unique<IOSImageDecoderImpl>();
}
} // namespace image_fetcher
diff --git a/chromium/components/infobars/core/infobar.cc b/chromium/components/infobars/core/infobar.cc
index b475c37f883..1859ce16ce2 100644
--- a/chromium/components/infobars/core/infobar.cc
+++ b/chromium/components/infobars/core/infobar.cc
@@ -34,17 +34,6 @@ InfoBar::~InfoBar() {
DCHECK(!owner_);
}
-// static
-SkColor InfoBar::GetBackgroundColor(InfoBarDelegate::Type infobar_type) {
- static const SkColor kWarningBackgroundColor =
- SkColorSetRGB(0xFF, 0xEC, 0xB3); // Yellow
- static constexpr SkColor kPageActionBackgroundColor = SK_ColorWHITE;
-
- return infobar_type == InfoBarDelegate::WARNING_TYPE
- ? kWarningBackgroundColor
- : kPageActionBackgroundColor;
-}
-
void InfoBar::SetOwner(InfoBarManager* owner) {
DCHECK(!owner_);
owner_ = owner;
diff --git a/chromium/components/infobars/core/infobar.h b/chromium/components/infobars/core/infobar.h
index 3c631100640..0fbeb8e4b33 100644
--- a/chromium/components/infobars/core/infobar.h
+++ b/chromium/components/infobars/core/infobar.h
@@ -44,8 +44,6 @@ class InfoBar : public gfx::AnimationDelegate {
explicit InfoBar(std::unique_ptr<InfoBarDelegate> delegate);
~InfoBar() override;
- static SkColor GetBackgroundColor(InfoBarDelegate::Type infobar_type);
-
InfoBarManager* owner() { return owner_; }
InfoBarDelegate* delegate() const { return delegate_.get(); }
void set_container(InfoBarContainer* container) { container_ = container; }
diff --git a/chromium/components/infobars/core/infobar_delegate.cc b/chromium/components/infobars/core/infobar_delegate.cc
index 08c10bc1e37..a975c13c03c 100644
--- a/chromium/components/infobars/core/infobar_delegate.cc
+++ b/chromium/components/infobars/core/infobar_delegate.cc
@@ -29,10 +29,6 @@ InfoBarDelegate::InfoBarAutomationType
return UNKNOWN_INFOBAR;
}
-InfoBarDelegate::Type InfoBarDelegate::GetInfoBarType() const {
- return WARNING_TYPE;
-}
-
int InfoBarDelegate::GetIconId() const {
return kNoIconID;
}
@@ -46,10 +42,8 @@ gfx::Image InfoBarDelegate::GetIcon() const {
#if !defined(OS_IOS) && !defined(OS_ANDROID)
const gfx::VectorIcon& vector_icon = GetVectorIcon();
if (!vector_icon.is_empty()) {
- return gfx::Image(gfx::CreateVectorIcon(vector_icon, 16,
- GetInfoBarType() == WARNING_TYPE
- ? SkColorSetRGB(0xFF, 0x67, 0)
- : gfx::kGoogleBlue500));
+ return gfx::Image(
+ gfx::CreateVectorIcon(vector_icon, 20, gfx::kGoogleBlue500));
}
#endif
diff --git a/chromium/components/infobars/core/infobar_delegate.h b/chromium/components/infobars/core/infobar_delegate.h
index 62860bb6241..2a996972987 100644
--- a/chromium/components/infobars/core/infobar_delegate.h
+++ b/chromium/components/infobars/core/infobar_delegate.h
@@ -148,6 +148,7 @@ class InfoBarDelegate {
FRAMEBUST_BLOCK_INFOBAR_ANDROID = 77,
SURVEY_INFOBAR_ANDROID = 78,
NEAR_OOM_INFOBAR_ANDROID = 79,
+ INSTALLABLE_AMBIENT_BADGE_INFOBAR_DELEGATE = 80,
};
// Describes navigation events, used to decide whether infobars should be
@@ -170,10 +171,6 @@ class InfoBarDelegate {
// this point nothing is visible onscreen.
virtual ~InfoBarDelegate();
- // Returns the type of the infobar. The type determines the appearance (such
- // as background color) of the infobar.
- virtual Type GetInfoBarType() const;
-
// Returns a unique value identifying the infobar.
// New implementers must append a new value to the InfoBarIdentifier enum here
// and in histograms.xml.
diff --git a/chromium/components/invalidation/impl/BUILD.gn b/chromium/components/invalidation/impl/BUILD.gn
index ac43ff82d12..b56a91a2eaf 100644
--- a/chromium/components/invalidation/impl/BUILD.gn
+++ b/chromium/components/invalidation/impl/BUILD.gn
@@ -248,6 +248,7 @@ if (is_android) {
":java",
"//base:base_java",
"//base:base_java_test_support",
+ "//base:base_junit_test_support",
]
}
generate_jni("jni_headers") {
diff --git a/chromium/components/json_schema/json_schema_validator.cc b/chromium/components/json_schema/json_schema_validator.cc
index e494bac1ccd..8806e900756 100644
--- a/chromium/components/json_schema/json_schema_validator.cc
+++ b/chromium/components/json_schema/json_schema_validator.cc
@@ -9,6 +9,7 @@
#include <algorithm>
#include <cfloat>
#include <cmath>
+#include <memory>
#include <vector>
#include "base/json/json_reader.h"
@@ -612,7 +613,7 @@ void JSONSchemaValidator::ValidateObject(const base::DictionaryValue* instance,
if (schema->GetDictionary(schema::kPatternProperties, &pattern_properties)) {
for (base::DictionaryValue::Iterator it(*pattern_properties); !it.IsAtEnd();
it.Advance()) {
- auto prop_pattern = base::MakeUnique<re2::RE2>(it.key());
+ auto prop_pattern = std::make_unique<re2::RE2>(it.key());
if (!prop_pattern->ok()) {
LOG(WARNING) << "Regular expression /" << it.key()
<< "/ is invalid: " << prop_pattern->error() << ".";
diff --git a/chromium/components/json_schema/json_schema_validator_unittest_base.cc b/chromium/components/json_schema/json_schema_validator_unittest_base.cc
index a4097bf82a9..2a19e710714 100644
--- a/chromium/components/json_schema/json_schema_validator_unittest_base.cc
+++ b/chromium/components/json_schema/json_schema_validator_unittest_base.cc
@@ -13,7 +13,6 @@
#include "base/files/file_util.h"
#include "base/json/json_file_value_serializer.h"
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/path_service.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
@@ -99,7 +98,7 @@ void JSONSchemaValidatorTestBase::TestComplex() {
ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
instance->Remove(instance->GetSize() - 1, nullptr);
ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->Append(base::MakeUnique<base::DictionaryValue>());
+ instance->Append(std::make_unique<base::DictionaryValue>());
ExpectNotValid(
TEST_SOURCE, instance.get(), schema.get(), nullptr, "1",
JSONSchemaValidator::FormatErrorMessage(
@@ -150,7 +149,7 @@ void JSONSchemaValidatorTestBase::TestEnum() {
ExpectNotValid(
TEST_SOURCE, std::unique_ptr<base::Value>(new base::Value("42")).get(),
schema.get(), nullptr, std::string(), JSONSchemaValidator::kInvalidEnum);
- ExpectNotValid(TEST_SOURCE, base::MakeUnique<base::Value>().get(),
+ ExpectNotValid(TEST_SOURCE, std::make_unique<base::Value>().get(),
schema.get(), nullptr, std::string(),
JSONSchemaValidator::kInvalidEnum);
}
@@ -159,7 +158,7 @@ void JSONSchemaValidatorTestBase::TestChoices() {
std::unique_ptr<base::DictionaryValue> schema(
LoadDictionary("choices_schema.json"));
- ExpectValid(TEST_SOURCE, base::MakeUnique<base::Value>().get(), schema.get(),
+ ExpectValid(TEST_SOURCE, std::make_unique<base::Value>().get(), schema.get(),
nullptr);
ExpectValid(TEST_SOURCE,
std::unique_ptr<base::Value>(new base::Value(42)).get(),
@@ -249,7 +248,7 @@ void JSONSchemaValidatorTestBase::TestObject() {
// Test additional properties.
base::DictionaryValue* additional_properties = schema->SetDictionary(
- schema::kAdditionalProperties, base::MakeUnique<base::DictionaryValue>());
+ schema::kAdditionalProperties, std::make_unique<base::DictionaryValue>());
additional_properties->SetString(schema::kType, schema::kAny);
instance->SetBoolean("extra", true);
@@ -278,7 +277,7 @@ void JSONSchemaValidatorTestBase::TestObject() {
ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
instance->Remove("bar", nullptr);
ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->Set("bar", base::MakeUnique<base::Value>());
+ instance->Set("bar", std::make_unique<base::Value>());
ExpectNotValid(
TEST_SOURCE, instance.get(), schema.get(), nullptr, "bar",
JSONSchemaValidator::FormatErrorMessage(JSONSchemaValidator::kInvalidType,
@@ -386,7 +385,7 @@ void JSONSchemaValidatorTestBase::TestArrayTuple() {
ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "1",
JSONSchemaValidator::kArrayItemRequired);
- instance->Set(0, base::MakeUnique<base::Value>(42));
+ instance->Set(0, std::make_unique<base::Value>(42));
instance->AppendInteger(42);
ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "0",
JSONSchemaValidator::FormatErrorMessage(
@@ -394,12 +393,12 @@ void JSONSchemaValidatorTestBase::TestArrayTuple() {
schema::kInteger));
base::DictionaryValue* additional_properties = schema->SetDictionary(
- schema::kAdditionalProperties, base::MakeUnique<base::DictionaryValue>());
+ schema::kAdditionalProperties, std::make_unique<base::DictionaryValue>());
additional_properties->SetString(schema::kType, schema::kAny);
- instance->Set(0, base::MakeUnique<base::Value>("42"));
+ instance->Set(0, std::make_unique<base::Value>("42"));
instance->AppendString("anything");
ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->Set(2, base::MakeUnique<base::ListValue>());
+ instance->Set(2, std::make_unique<base::ListValue>());
ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
additional_properties->SetString(schema::kType, schema::kBoolean);
@@ -407,7 +406,7 @@ void JSONSchemaValidatorTestBase::TestArrayTuple() {
TEST_SOURCE, instance.get(), schema.get(), nullptr, "2",
JSONSchemaValidator::FormatErrorMessage(
JSONSchemaValidator::kInvalidType, schema::kBoolean, schema::kArray));
- instance->Set(2, base::MakeUnique<base::Value>(false));
+ instance->Set(2, std::make_unique<base::Value>(false));
ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
base::ListValue* items_schema = nullptr;
@@ -419,9 +418,9 @@ void JSONSchemaValidatorTestBase::TestArrayTuple() {
ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
// TODO(aa): I think this is inconsistent with the handling of NULL+optional
// for objects.
- instance->Set(0, base::MakeUnique<base::Value>());
+ instance->Set(0, std::make_unique<base::Value>());
ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->Set(0, base::MakeUnique<base::Value>(42));
+ instance->Set(0, std::make_unique<base::Value>(42));
ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "0",
JSONSchemaValidator::FormatErrorMessage(
JSONSchemaValidator::kInvalidType, schema::kString,
@@ -582,7 +581,7 @@ void JSONSchemaValidatorTestBase::TestTypeClassifier() {
std::unique_ptr<base::Value>(new base::DictionaryValue()).get()));
EXPECT_EQ(std::string(schema::kNull),
JSONSchemaValidator::GetJSONSchemaType(
- base::MakeUnique<base::Value>().get()));
+ std::make_unique<base::Value>().get()));
}
void JSONSchemaValidatorTestBase::TestTypes() {
@@ -648,7 +647,7 @@ void JSONSchemaValidatorTestBase::TestTypes() {
schema.get(), nullptr);
schema->SetString(schema::kType, schema::kNull);
- ExpectValid(TEST_SOURCE, base::MakeUnique<base::Value>().get(), schema.get(),
+ ExpectValid(TEST_SOURCE, std::make_unique<base::Value>().get(), schema.get(),
nullptr);
// not valid
@@ -661,7 +660,7 @@ void JSONSchemaValidatorTestBase::TestTypes() {
schema->SetString(schema::kType, schema::kObject);
ExpectNotValid(
- TEST_SOURCE, base::MakeUnique<base::Value>().get(), schema.get(), nullptr,
+ TEST_SOURCE, std::make_unique<base::Value>().get(), schema.get(), nullptr,
std::string(),
JSONSchemaValidator::FormatErrorMessage(JSONSchemaValidator::kInvalidType,
schema::kObject, schema::kNull));
diff --git a/chromium/components/language/content/browser/BUILD.gn b/chromium/components/language/content/browser/BUILD.gn
index 06b29c29d6f..2930633d3c1 100644
--- a/chromium/components/language/content/browser/BUILD.gn
+++ b/chromium/components/language/content/browser/BUILD.gn
@@ -45,7 +45,7 @@ static_library("browser") {
":language_code_locator",
"//base",
"//net",
- "//services/device/public/interfaces:interfaces",
+ "//services/device/public/mojom",
"//services/service_manager/public/cpp",
]
}
@@ -61,7 +61,7 @@ source_set("unit_tests") {
":language_code_locator",
"//base",
"//base/test:test_support",
- "//services/device/public/interfaces:interfaces",
+ "//services/device/public/mojom",
"//services/service_manager/public/cpp",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/components/language/content/browser/DEPS b/chromium/components/language/content/browser/DEPS
index 9d2ba3a3188..f7af194ce54 100644
--- a/chromium/components/language/content/browser/DEPS
+++ b/chromium/components/language/content/browser/DEPS
@@ -1,6 +1,5 @@
include_rules = [
- "+device/geolocation/public/interfaces",
"+net",
- "+services/device/public/interfaces",
+ "+services/device/public/mojom",
"+services/service_manager/public",
]
diff --git a/chromium/components/language/content/browser/geo_language_provider.cc b/chromium/components/language/content/browser/geo_language_provider.cc
index b06bb4743c9..0ee3bbc1c69 100644
--- a/chromium/components/language/content/browser/geo_language_provider.cc
+++ b/chromium/components/language/content/browser/geo_language_provider.cc
@@ -8,8 +8,8 @@
#include "base/task_scheduler/post_task.h"
#include "base/time/time.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "services/device/public/interfaces/constants.mojom.h"
-#include "services/device/public/interfaces/public_ip_address_geolocation_provider.mojom.h"
+#include "services/device/public/mojom/constants.mojom.h"
+#include "services/device/public/mojom/public_ip_address_geolocation_provider.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace language {
diff --git a/chromium/components/language/content/browser/geo_language_provider.h b/chromium/components/language/content/browser/geo_language_provider.h
index b361a639926..20e04721a14 100644
--- a/chromium/components/language/content/browser/geo_language_provider.h
+++ b/chromium/components/language/content/browser/geo_language_provider.h
@@ -12,7 +12,7 @@
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "components/language/content/browser/language_code_locator.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
+#include "services/device/public/mojom/geolocation.mojom.h"
namespace base {
template <typename T>
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 bb73e412492..3b4f71ffc80 100644
--- a/chromium/components/language/content/browser/geo_language_provider_unittest.cc
+++ b/chromium/components/language/content/browser/geo_language_provider_unittest.cc
@@ -11,12 +11,12 @@
#include "base/macros.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/timer/timer.h"
-#include "device/geolocation/public/interfaces/geolocation.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/device/public/interfaces/constants.mojom.h"
-#include "services/device/public/interfaces/public_ip_address_geolocation_provider.mojom.h"
+#include "services/device/public/mojom/constants.mojom.h"
+#include "services/device/public/mojom/geolocation.mojom.h"
+#include "services/device/public/mojom/public_ip_address_geolocation_provider.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
-#include "services/service_manager/public/interfaces/connector.mojom.h"
+#include "services/service_manager/public/mojom/connector.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -93,7 +93,7 @@ class GeoLanguageProviderTest : public testing::Test {
connector_ = service_manager::Connector::Create(&request);
service_manager::Connector::TestApi test_api(connector_.get());
test_api.OverrideBinderForTesting(
- device::mojom::kServiceName,
+ service_manager::Identity(device::mojom::kServiceName),
device::mojom::PublicIpAddressGeolocationProvider::Name_,
base::BindRepeating(&MockIpGeoLocationProvider::Bind,
base::Unretained(&mock_ip_geo_location_provider_)));
diff --git a/chromium/components/language/core/common/BUILD.gn b/chromium/components/language/core/common/BUILD.gn
new file mode 100644
index 00000000000..6d8f155e37b
--- /dev/null
+++ b/chromium/components/language/core/common/BUILD.gn
@@ -0,0 +1,28 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("common") {
+ sources = [
+ "locale_util.cc",
+ "locale_util.h",
+ ]
+
+ deps = [
+ "//base",
+ "//ui/base",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "locale_util_unittest.cc",
+ ]
+ deps = [
+ ":common",
+ "//base",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/language/core/common/DEPS b/chromium/components/language/core/common/DEPS
new file mode 100644
index 00000000000..ebbc9b86eb7
--- /dev/null
+++ b/chromium/components/language/core/common/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+ui/base/l10n",
+]
diff --git a/chromium/components/language/core/common/locale_util.cc b/chromium/components/language/core/common/locale_util.cc
new file mode 100644
index 00000000000..7ed93d67083
--- /dev/null
+++ b/chromium/components/language/core/common/locale_util.cc
@@ -0,0 +1,117 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/language/core/common/locale_util.h"
+
+#include <algorithm>
+#include <set>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/strings/string_split.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace language {
+
+namespace {
+
+// Pair of locales, where the first element should fallback to the second one.
+struct LocaleUIFallbackPair {
+ const char* const chosen_locale;
+ const char* const fallback_locale;
+};
+
+// This list MUST be sorted by the first element in the pair, because we perform
+// binary search on it.
+// TODO(claudiomagni): Investigate Norvegian language. There are 2 codes ("nn",
+// "no") that fallback to "nb", but the base language should be "nn".
+const LocaleUIFallbackPair kLocaleUIFallbackTable[] = {
+ {"en", "en-US"}, {"en-AU", "en-GB"}, {"en-CA", "en-GB"},
+ {"en-IN", "en-GB"}, {"en-NZ", "en-GB"}, {"en-ZA", "en-GB"},
+ {"es-AR", "es-419"}, {"es-CL", "es-419"}, {"es-CO", "es-419"},
+ {"es-CR", "es-419"}, {"es-HN", "es-419"}, {"es-MX", "es-419"},
+ {"es-PE", "es-419"}, {"es-US", "es-419"}, {"es-UY", "es-419"},
+ {"es-VE", "es-419"}, {"it-CH", "it"}, {"nn", "nb"},
+ {"no", "nb"}, {"pt", "pt-PT"}};
+
+bool LocaleCompare(const LocaleUIFallbackPair& p1, const std::string& p2) {
+ return p1.chosen_locale < p2;
+}
+
+bool GetUIFallbackLocale(const std::string& input, std::string* const output) {
+ *output = input;
+ const auto* it =
+ std::lower_bound(std::begin(kLocaleUIFallbackTable),
+ std::end(kLocaleUIFallbackTable), input, LocaleCompare);
+ if (it != std::end(kLocaleUIFallbackTable) && it->chosen_locale == input) {
+ *output = it->fallback_locale;
+ return true;
+ }
+ return false;
+}
+
+// Given a language code, extract the base language only.
+// Example: from "en-US", extract "en".
+std::string ExtractBaseLanguage(const std::string& language_code) {
+ std::string base;
+ std::string tail;
+ SplitIntoMainAndTail(language_code, &base, &tail);
+ return base;
+}
+
+} // namespace
+
+void SplitIntoMainAndTail(const std::string& locale,
+ std::string* main_part,
+ std::string* tail_part) {
+ DCHECK(main_part);
+ DCHECK(tail_part);
+
+ std::vector<base::StringPiece> chunks = base::SplitStringPiece(
+ locale, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ if (chunks.empty())
+ return;
+
+ chunks[0].CopyToString(main_part);
+ *tail_part = locale.substr(main_part->size());
+}
+
+bool ContainsSameBaseLanguage(const std::vector<std::string>& list,
+ const std::string& language_code) {
+ const std::string base_language = ExtractBaseLanguage(language_code);
+ for (const auto& item : list) {
+ const std::string compare_base = ExtractBaseLanguage(item);
+ if (compare_base == base_language)
+ return true;
+ }
+
+ return false;
+}
+
+bool ConvertToActualUILocale(std::string* input_locale) {
+ const std::vector<std::string>& ui_locales = l10n_util::GetAvailableLocales();
+ const std::set<std::string> ui_set(ui_locales.begin(), ui_locales.end());
+
+ // 1) Convert input to a fallback, if available.
+ std::string fallback;
+ GetUIFallbackLocale(*input_locale, &fallback);
+
+ // 2) Check if input is part of the UI languages.
+ if (ui_set.count(fallback) > 0) {
+ *input_locale = fallback;
+ return true;
+ }
+
+ // 3) Check if the base language of the input is part of the UI languages.
+ const std::string base = ExtractBaseLanguage(*input_locale);
+ if (base != *input_locale && ui_set.count(base) > 0) {
+ *input_locale = base;
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace language
diff --git a/chromium/components/language/core/common/locale_util.h b/chromium/components/language/core/common/locale_util.h
new file mode 100644
index 00000000000..68f5563e779
--- /dev/null
+++ b/chromium/components/language/core/common/locale_util.h
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_LANGUAGE_CORE_COMMON_LOCALE_UTIL_H_
+#define COMPONENTS_LANGUAGE_CORE_COMMON_LOCALE_UTIL_H_
+
+#include <string>
+#include <vector>
+
+namespace language {
+
+// Split the |locale| into two parts. For example, if |locale| is 'en-US',
+// this will be split into the main part 'en' and the tail part '-US'.
+void SplitIntoMainAndTail(const std::string& locale,
+ std::string* main_part,
+ std::string* tail_part);
+
+// Returns whether or not the given list includes at least one language with
+// the same base as the input language.
+// For example: "en-US" and "en-UK" share the same base "en".
+bool ContainsSameBaseLanguage(const std::vector<std::string>& list,
+ const std::string& language_code);
+
+// Converts the input locale into its corresponding actual UI locale that
+// Chrome should use for display and returns whether such locale exist.
+// This method must be called whenever the display locale preference is
+// read, because users can select a set of languages that is larger than
+// the set of actual UI locales.
+// If |input_locale| cannot be used as display UI, this method returns false
+// and the content of |input_locale| is not modified.
+bool ConvertToActualUILocale(std::string* input_locale);
+
+} // namespace language
+
+#endif // COMPONENTS_LANGUAGE_CORE_COMMON_LOCALE_UTIL_H_
diff --git a/chromium/components/language/core/common/locale_util_unittest.cc b/chromium/components/language/core/common/locale_util_unittest.cc
new file mode 100644
index 00000000000..eb06a0be84d
--- /dev/null
+++ b/chromium/components/language/core/common/locale_util_unittest.cc
@@ -0,0 +1,264 @@
+// 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/language/core/common/locale_util.h"
+
+#include "base/command_line.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+typedef testing::Test LocaleUtilTest;
+
+TEST_F(LocaleUtilTest, SplitIntoMainAndTail) {
+ std::string locale;
+ std::string main;
+ std::string tail;
+
+ locale = "";
+ language::SplitIntoMainAndTail(locale, &main, &tail);
+ EXPECT_TRUE(main.empty());
+ EXPECT_TRUE(tail.empty());
+
+ locale = "en";
+ main.clear();
+ tail.clear();
+ language::SplitIntoMainAndTail(locale, &main, &tail);
+ EXPECT_EQ("en", main);
+ EXPECT_TRUE(tail.empty());
+
+ locale = "ogard543i";
+ main.clear();
+ tail.clear();
+ language::SplitIntoMainAndTail(locale, &main, &tail);
+ EXPECT_EQ("ogard543i", main);
+ EXPECT_TRUE(tail.empty());
+
+ locale = "en-AU";
+ main.clear();
+ tail.clear();
+ language::SplitIntoMainAndTail(locale, &main, &tail);
+ EXPECT_EQ("en", main);
+ EXPECT_EQ("-AU", tail);
+
+ locale = "es-419";
+ main.clear();
+ tail.clear();
+ language::SplitIntoMainAndTail(locale, &main, &tail);
+ EXPECT_EQ("es", main);
+ EXPECT_EQ("-419", tail);
+
+ locale = "en-AU-2009";
+ main.clear();
+ tail.clear();
+ language::SplitIntoMainAndTail(locale, &main, &tail);
+ EXPECT_EQ("en", main);
+ EXPECT_EQ("-AU-2009", tail);
+}
+
+TEST_F(LocaleUtilTest, ContainsSameBaseLanguage) {
+ std::vector<std::string> list;
+
+ // Empty input.
+ EXPECT_EQ(false, language::ContainsSameBaseLanguage(list, ""));
+
+ // Empty list.
+ EXPECT_EQ(false, language::ContainsSameBaseLanguage(list, "fr-FR"));
+
+ // Empty language.
+ list = {"en-US"};
+ EXPECT_EQ(false, language::ContainsSameBaseLanguage(list, ""));
+
+ // One element, no match.
+ list = {"en-US"};
+ EXPECT_EQ(false, language::ContainsSameBaseLanguage(list, "fr-FR"));
+
+ // One element, with match.
+ list = {"fr-CA"};
+ EXPECT_EQ(true, language::ContainsSameBaseLanguage(list, "fr-FR"));
+
+ // Multiple elements, no match.
+ list = {"en-US", "es-AR", "en-UK"};
+ EXPECT_EQ(false, language::ContainsSameBaseLanguage(list, "fr-FR"));
+
+ // Multiple elements, with match.
+ list = {"en-US", "fr-CA", "es-AR"};
+ EXPECT_EQ(true, language::ContainsSameBaseLanguage(list, "fr-FR"));
+
+ // Multiple elements matching.
+ list = {"en-US", "fr-CA", "es-AR", "fr-FR"};
+ EXPECT_EQ(true, language::ContainsSameBaseLanguage(list, "fr-FR"));
+
+ // List includes base language.
+ list = {"en-US", "fr", "es-AR", "fr-FR"};
+ EXPECT_EQ(true, language::ContainsSameBaseLanguage(list, "fr-FR"));
+}
+
+TEST_F(LocaleUtilTest, ConvertToActualUILocale) {
+ std::string locale;
+
+ //---------------------------------------------------------------------------
+ // Languages that are enabled as display UI.
+ //---------------------------------------------------------------------------
+ locale = "en-US";
+ bool is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("en-US", locale);
+
+ locale = "it";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("it", locale);
+
+ locale = "fr-FR";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("fr-FR", locale);
+
+ //---------------------------------------------------------------------------
+ // Languages that are converted to their fallback version.
+ //---------------------------------------------------------------------------
+
+ // All Latin American Spanish languages fall back to "es-419".
+ locale = "es-AR";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("es-419", locale);
+
+ locale = "es-CL";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("es-419", locale);
+
+ locale = "es-CO";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("es-419", locale);
+
+ locale = "es-CR";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("es-419", locale);
+
+ locale = "es-HN";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("es-419", locale);
+
+ locale = "es-MX";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("es-419", locale);
+
+ locale = "es-PE";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("es-419", locale);
+
+ locale = "es-US";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("es-419", locale);
+
+ locale = "es-UY";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("es-419", locale);
+
+ locale = "es-VE";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("es-419", locale);
+
+ // English falls back to US.
+ locale = "en";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("en-US", locale);
+
+ // All other regional English languages fall back to UK.
+ locale = "en-AU";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("en-GB", locale);
+
+ locale = "en-CA";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("en-GB", locale);
+
+ locale = "en-IN";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("en-GB", locale);
+
+ locale = "en-NZ";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("en-GB", locale);
+
+ locale = "en-ZA";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("en-GB", locale);
+
+ locale = "pt";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("pt-PT", locale);
+
+ locale = "it-CH";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("it", locale);
+
+ locale = "nn";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("nb", locale);
+
+ locale = "no";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("nb", locale);
+
+ //---------------------------------------------------------------------------
+ // Languages that have their base language is a UI language.
+ //---------------------------------------------------------------------------
+ locale = "it-IT";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("it", locale);
+
+ locale = "de-DE";
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_TRUE(is_ui);
+ EXPECT_EQ("de", locale);
+
+//---------------------------------------------------------------------------
+// Languages that cannot be used as display UI.
+//---------------------------------------------------------------------------
+// This only matters for ChromeOS and Windows, as they are the only systems
+// where users can set the display UI.
+#if defined(OS_CHROMEOS) || defined(OS_WIN)
+ locale = "sd"; // Sindhi
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_FALSE(is_ui);
+
+ locale = "af"; // Afrikaans
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_FALSE(is_ui);
+
+ locale = "ga"; // Irish
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_FALSE(is_ui);
+
+ locale = "ky"; // Kyrgyz
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_FALSE(is_ui);
+
+ locale = "zu"; // Zulu
+ is_ui = language::ConvertToActualUILocale(&locale);
+ EXPECT_FALSE(is_ui);
+#endif
+}
diff --git a/chromium/components/leveldb/leveldb_service_impl.cc b/chromium/components/leveldb/leveldb_service_impl.cc
index 321056515a4..639c38f956e 100644
--- a/chromium/components/leveldb/leveldb_service_impl.cc
+++ b/chromium/components/leveldb/leveldb_service_impl.cc
@@ -7,7 +7,6 @@
#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "components/leveldb/env_mojo.h"
#include "components/leveldb/leveldb_database_impl.h"
#include "components/leveldb/public/cpp/util.h"
@@ -64,7 +63,7 @@ void LevelDBServiceImpl::OpenWithOptions(
if (s.ok()) {
mojo::MakeStrongAssociatedBinding(
- base::MakeUnique<LevelDBDatabaseImpl>(
+ std::make_unique<LevelDBDatabaseImpl>(
std::move(env_mojo), std::move(db), nullptr, memory_dump_id),
std::move(database));
}
@@ -90,7 +89,7 @@ void LevelDBServiceImpl::OpenInMemory(
if (s.ok()) {
mojo::MakeStrongAssociatedBinding(
- base::MakeUnique<LevelDBDatabaseImpl>(std::move(env), std::move(db),
+ std::make_unique<LevelDBDatabaseImpl>(std::move(env), std::move(db),
nullptr, memory_dump_id),
std::move(database));
}
diff --git a/chromium/components/leveldb_proto/proto_database_impl.h b/chromium/components/leveldb_proto/proto_database_impl.h
index 85f4dfe0883..b7ecf115ee0 100644
--- a/chromium/components/leveldb_proto/proto_database_impl.h
+++ b/chromium/components/leveldb_proto/proto_database_impl.h
@@ -18,7 +18,6 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
-#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_checker.h"
#include "components/leveldb_proto/leveldb_database.h"
#include "components/leveldb_proto/proto_database.h"
@@ -245,8 +244,7 @@ void ProtoDatabaseImpl<T>::Destroy(
bool* success = new bool(false);
task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::Bind(DestroyFromTaskRunner, base::Passed(std::move(db_)), success),
+ FROM_HERE, base::BindOnce(DestroyFromTaskRunner, std::move(db_), success),
base::BindOnce(RunDestroyCallback<T>, std::move(callback),
base::Owned(success)));
}
@@ -279,9 +277,9 @@ void ProtoDatabaseImpl<T>::UpdateEntries(
bool* success = new bool(false);
task_runner_->PostTaskAndReply(
FROM_HERE,
- base::Bind(UpdateEntriesFromTaskRunner<T>, base::Unretained(db_.get()),
- base::Passed(&entries_to_save), base::Passed(&keys_to_remove),
- success),
+ base::BindOnce(UpdateEntriesFromTaskRunner<T>,
+ base::Unretained(db_.get()), std::move(entries_to_save),
+ std::move(keys_to_remove), success),
base::BindOnce(RunUpdateCallback<T>, std::move(callback),
base::Owned(success)));
}
@@ -293,30 +291,30 @@ void ProtoDatabaseImpl<T>::LoadEntries(
bool* success = new bool(false);
std::unique_ptr<std::vector<T>> entries(new std::vector<T>());
- // Get this pointer before entries is base::Passed() so we can use it below.
+ // Get this pointer before entries is std::move()'d so we can use it below.
std::vector<T>* entries_ptr = entries.get();
task_runner_->PostTaskAndReply(
FROM_HERE,
- base::Bind(LoadEntriesFromTaskRunner<T>, base::Unretained(db_.get()),
- entries_ptr, success),
+ base::BindOnce(LoadEntriesFromTaskRunner<T>, base::Unretained(db_.get()),
+ entries_ptr, success),
base::BindOnce(RunLoadCallback<T>, std::move(callback),
- base::Owned(success), base::Passed(&entries)));
+ base::Owned(success), std::move(entries)));
}
template <typename T>
void ProtoDatabaseImpl<T>::LoadKeys(
typename ProtoDatabase<T>::LoadKeysCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
- auto success = base::MakeUnique<bool>(false);
- auto keys = base::MakeUnique<std::vector<std::string>>();
+ auto success = std::make_unique<bool>(false);
+ auto keys = std::make_unique<std::vector<std::string>>();
auto load_task =
base::Bind(LoadKeysFromTaskRunner, base::Unretained(db_.get()),
keys.get(), success.get());
task_runner_->PostTaskAndReply(
FROM_HERE, load_task,
base::BindOnce(RunLoadKeysCallback<T>, std::move(callback),
- base::Passed(&success), base::Passed(&keys)));
+ std::move(success), std::move(keys)));
}
template <typename T>
@@ -328,16 +326,16 @@ void ProtoDatabaseImpl<T>::GetEntry(
bool* found = new bool(false);
std::unique_ptr<T> entry(new T());
- // Get this pointer before entry is base::Passed() so we can use it below.
+ // Get this pointer before entry is std::move()'d so we can use it below.
T* entry_ptr = entry.get();
task_runner_->PostTaskAndReply(
FROM_HERE,
- base::Bind(GetEntryFromTaskRunner<T>, base::Unretained(db_.get()), key,
- entry_ptr, found, success),
+ base::BindOnce(GetEntryFromTaskRunner<T>, base::Unretained(db_.get()),
+ key, entry_ptr, found, success),
base::BindOnce(RunGetCallback<T>, std::move(callback),
base::Owned(success), base::Owned(found),
- base::Passed(&entry)));
+ std::move(entry)));
}
} // namespace leveldb_proto
diff --git a/chromium/components/leveldb_proto/proto_database_impl_unittest.cc b/chromium/components/leveldb_proto/proto_database_impl_unittest.cc
index 656e67caf8b..f09895e899f 100644
--- a/chromium/components/leveldb_proto/proto_database_impl_unittest.cc
+++ b/chromium/components/leveldb_proto/proto_database_impl_unittest.cc
@@ -11,6 +11,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
@@ -372,8 +373,8 @@ TEST(ProtoDatabaseImplLevelDBTest, TestDBSaveAndLoadKeys) {
ProtoDatabase<TestProto>::KeyEntryVector data_set(
{{"0", test_proto}, {"1", test_proto}, {"2", test_proto}});
db->UpdateEntries(
- base::MakeUnique<ProtoDatabase<TestProto>::KeyEntryVector>(data_set),
- base::MakeUnique<std::vector<std::string>>(), expect_update_success);
+ std::make_unique<ProtoDatabase<TestProto>::KeyEntryVector>(data_set),
+ std::make_unique<std::vector<std::string>>(), expect_update_success);
run_update_entries.Run();
base::RunLoop run_load_keys;
@@ -391,8 +392,8 @@ TEST(ProtoDatabaseImplLevelDBTest, TestDBSaveAndLoadKeys) {
// Shutdown database.
db.reset();
base::RunLoop run_destruction;
- db_thread.task_runner()->PostTaskAndReply(
- FROM_HERE, base::Bind(base::DoNothing), run_destruction.QuitClosure());
+ db_thread.task_runner()->PostTaskAndReply(FROM_HERE, base::DoNothing(),
+ run_destruction.QuitClosure());
run_destruction.Run();
}
@@ -596,8 +597,8 @@ TEST(ProtoDatabaseImplThreadingTest, TestDBDestruction) {
db.reset();
base::RunLoop run_loop;
- db_thread.task_runner()->PostTaskAndReply(
- FROM_HERE, base::Bind(base::DoNothing), run_loop.QuitClosure());
+ db_thread.task_runner()->PostTaskAndReply(FROM_HERE, base::DoNothing(),
+ run_loop.QuitClosure());
run_loop.Run();
}
@@ -628,8 +629,8 @@ TEST(ProtoDatabaseImplThreadingTest, TestDBDestroy) {
db.reset();
base::RunLoop run_loop;
- db_thread.task_runner()->PostTaskAndReply(
- FROM_HERE, base::Bind(base::DoNothing), run_loop.QuitClosure());
+ db_thread.task_runner()->PostTaskAndReply(FROM_HERE, base::DoNothing(),
+ run_loop.QuitClosure());
run_loop.Run();
// Verify the db is actually destroyed.
diff --git a/chromium/components/leveldb_proto/testing/fake_db.h b/chromium/components/leveldb_proto/testing/fake_db.h
index bea5346bf65..8be2645af7e 100644
--- a/chromium/components/leveldb_proto/testing/fake_db.h
+++ b/chromium/components/leveldb_proto/testing/fake_db.h
@@ -122,8 +122,8 @@ void FakeDB<T>::LoadEntries(typename ProtoDatabase<T>::LoadCallback callback) {
for (const auto& pair : *db_)
entries->push_back(pair.second);
- load_callback_ = base::BindOnce(RunLoadCallback, std::move(callback),
- base::Passed(&entries));
+ load_callback_ =
+ base::BindOnce(RunLoadCallback, std::move(callback), std::move(entries));
}
template <typename T>
@@ -133,8 +133,8 @@ void FakeDB<T>::LoadKeys(typename ProtoDatabase<T>::LoadKeysCallback callback) {
for (const auto& pair : *db_)
keys->push_back(pair.first);
- load_keys_callback_ = base::BindOnce(RunLoadKeysCallback, std::move(callback),
- base::Passed(&keys));
+ load_keys_callback_ =
+ base::BindOnce(RunLoadKeysCallback, std::move(callback), std::move(keys));
}
template <typename T>
@@ -146,7 +146,7 @@ void FakeDB<T>::GetEntry(const std::string& key,
entry.reset(new T(it->second));
get_callback_ =
- base::BindOnce(RunGetCallback, std::move(callback), base::Passed(&entry));
+ base::BindOnce(RunGetCallback, std::move(callback), std::move(entry));
}
template <typename T>
diff --git a/chromium/components/login/screens/screen_context.cc b/chromium/components/login/screens/screen_context.cc
index f1ebd76d72f..f90bbe18537 100644
--- a/chromium/components/login/screens/screen_context.cc
+++ b/chromium/components/login/screens/screen_context.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
namespace login {
@@ -179,7 +178,7 @@ bool ScreenContext::Set(const KeyType& key, base::Value* value) {
if (in_storage && new_value->Equals(current_value))
return false;
- changes_.Set(key, base::MakeUnique<base::Value>(new_value->Clone()));
+ changes_.Set(key, std::make_unique<base::Value>(new_value->Clone()));
storage_.Set(key, std::move(new_value));
return true;
}
diff --git a/chromium/components/login_dialog_strings.grdp b/chromium/components/login_dialog_strings.grdp
index bd4417ced3a..db851ccd99a 100644
--- a/chromium/components/login_dialog_strings.grdp
+++ b/chromium/components/login_dialog_strings.grdp
@@ -1,20 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
+ <message name="IDS_LOGIN_DIALOG_TITLE" desc="In sentence case: String to be displayed in the title bar of the login prompt dialog" formatter_data="android_java">
+ Sign in
+ </message>
<if expr="use_titlecase">
- <message name="IDS_LOGIN_DIALOG_TITLE" desc="In title case: String to be displayed in the title bar of the login prompt dialog" formatter_data="android_java">
- Authentication Required
- </message>
- <message name="IDS_LOGIN_DIALOG_OK_BUTTON_LABEL" desc="In title case: The label of the 'Log In' button on the login prompt dialog" formatter_data="android_java">
- Log In
+ <message name="IDS_LOGIN_DIALOG_OK_BUTTON_LABEL" desc="In Title Case: The label of the 'Log In' button on the login prompt dialog" formatter_data="android_java">
+ Sign In
</message>
</if>
<if expr="not use_titlecase">
- <message name="IDS_LOGIN_DIALOG_TITLE" desc="In sentence case: String to be displayed in the title bar of the login prompt dialog" formatter_data="android_java">
- Authentication required
- </message>
<message name="IDS_LOGIN_DIALOG_OK_BUTTON_LABEL" desc="In sentence case: The label of the 'Log in' button on the login prompt dialog" formatter_data="android_java">
- Log in
+ Sign in
</message>
</if>
<message name="IDS_LOGIN_DIALOG_AUTHORITY" desc="String to be displayed in the login prompt dialog to explain that the user needs to log in, and the name of the web site">
diff --git a/chromium/components/metrics/BUILD.gn b/chromium/components/metrics/BUILD.gn
index 825b7ea61d1..5287fb4b2e9 100644
--- a/chromium/components/metrics/BUILD.gn
+++ b/chromium/components/metrics/BUILD.gn
@@ -94,6 +94,8 @@ static_library("metrics") {
"system_memory_stats_recorder.h",
"system_memory_stats_recorder_linux.cc",
"system_memory_stats_recorder_win.cc",
+ "system_session_analyzer_win.cc",
+ "system_session_analyzer_win.h",
"url_constants.cc",
"url_constants.h",
"version_utils.cc",
@@ -101,11 +103,11 @@ static_library("metrics") {
]
public_deps = [
+ ":call_stack_profile_params",
"//third_party/metrics_proto",
]
deps = [
- ":call_stack_profile_params",
"//base",
"//base:base_static",
"//components/prefs",
@@ -132,6 +134,7 @@ static_library("metrics") {
if (is_win) {
sources -= [ "machine_id_provider_stub.cc" ]
deps += [ "//components/browser_watcher:stability_client" ]
+ libs = [ "wevtapi.lib" ]
}
if (is_fuchsia) {
@@ -243,7 +246,7 @@ static_library("single_sample_metrics") {
deps = [
"//mojo/public/cpp/bindings",
"//services/service_manager/public/cpp",
- "//services/service_manager/public/interfaces",
+ "//services/service_manager/public/mojom",
]
public_deps = [
@@ -346,6 +349,7 @@ source_set("unit_tests") {
"single_sample_metrics_factory_impl_unittest.cc",
"stability_metrics_helper_unittest.cc",
"stability_metrics_provider_unittest.cc",
+ "system_session_analyzer_win_unittest.cc",
"ui/screen_info_metrics_provider_unittest.cc",
]
diff --git a/chromium/components/metrics/OWNERS b/chromium/components/metrics/OWNERS
index c9290272739..68c3f9cbc00 100644
--- a/chromium/components/metrics/OWNERS
+++ b/chromium/components/metrics/OWNERS
@@ -1,3 +1,5 @@
file://base/metrics/OWNERS
+per-file *call_stack_profile*=wittman@chromium.org
+
# COMPONENT: Internals>Metrics
diff --git a/chromium/components/metrics/call_stack_profile_collector.cc b/chromium/components/metrics/call_stack_profile_collector.cc
index 3d35abf54ee..3dfb1dedafe 100644
--- a/chromium/components/metrics/call_stack_profile_collector.cc
+++ b/chromium/components/metrics/call_stack_profile_collector.cc
@@ -7,7 +7,8 @@
#include <utility>
#include <vector>
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "components/metrics/call_stack_profile_metrics_provider.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -25,7 +26,7 @@ void CallStackProfileCollector::Create(
CallStackProfileParams::Process expected_process,
mojom::CallStackProfileCollectorRequest request) {
mojo::MakeStrongBinding(
- base::MakeUnique<CallStackProfileCollector>(expected_process),
+ std::make_unique<CallStackProfileCollector>(expected_process),
std::move(request));
}
diff --git a/chromium/components/metrics/call_stack_profile_metrics_provider.cc b/chromium/components/metrics/call_stack_profile_metrics_provider.cc
index 4a22264680e..078509b9716 100644
--- a/chromium/components/metrics/call_stack_profile_metrics_provider.cc
+++ b/chromium/components/metrics/call_stack_profile_metrics_provider.cc
@@ -56,14 +56,24 @@ const ProcessPhase
ProcessPhase::SHUTDOWN_START,
};
-// Parameters for browser process sampling. Not const since these may be
-// changed when transitioning from start-up profiling to periodic profiling.
-CallStackProfileParams g_browser_process_sampling_params(
+// Parameters for UI thread of browser process sampling. Not const since these
+// may be changed when transitioning from start-up profiling to periodic
+// profiling.
+CallStackProfileParams g_ui_thread_sampling_params(
CallStackProfileParams::BROWSER_PROCESS,
CallStackProfileParams::UI_THREAD,
CallStackProfileParams::PROCESS_STARTUP,
CallStackProfileParams::MAY_SHUFFLE);
+// Parameters for IO thread of browser process sampling. Not const since these
+// may be changed when transitioning from start-up profiling to periodic
+// profiling.
+CallStackProfileParams g_io_thread_sampling_params(
+ CallStackProfileParams::BROWSER_PROCESS,
+ CallStackProfileParams::IO_THREAD,
+ CallStackProfileParams::PROCESS_STARTUP,
+ CallStackProfileParams::MAY_SHUFFLE);
+
// ProfilesState --------------------------------------------------------------
// A set of profiles and the CallStackProfileMetricsProvider state associated
@@ -296,7 +306,8 @@ ReceiveCompletedProfilesImpl(
// over this, for example ending sampling after some amount of time.
if (CallStackProfileMetricsProvider::IsPeriodicSamplingEnabled() &&
params->process == CallStackProfileParams::BROWSER_PROCESS &&
- params->thread == CallStackProfileParams::UI_THREAD) {
+ (params->thread == CallStackProfileParams::UI_THREAD ||
+ params->thread == CallStackProfileParams::IO_THREAD)) {
params->trigger = CallStackProfileParams::PERIODIC_COLLECTION;
params->start_timestamp = base::TimeTicks::Now();
@@ -467,24 +478,18 @@ Thread ToExecutionContextThread(CallStackProfileParams::Thread thread) {
return UNKNOWN_THREAD;
case CallStackProfileParams::UI_THREAD:
return UI_THREAD;
- case CallStackProfileParams::FILE_THREAD:
- return FILE_THREAD;
- case CallStackProfileParams::FILE_USER_BLOCKING_THREAD:
- return FILE_USER_BLOCKING_THREAD;
case CallStackProfileParams::PROCESS_LAUNCHER_THREAD:
return PROCESS_LAUNCHER_THREAD;
- case CallStackProfileParams::CACHE_THREAD:
- return CACHE_THREAD;
case CallStackProfileParams::IO_THREAD:
return IO_THREAD;
- case CallStackProfileParams::DB_THREAD:
- return DB_THREAD;
case CallStackProfileParams::GPU_MAIN_THREAD:
return GPU_MAIN_THREAD;
case CallStackProfileParams::RENDER_THREAD:
return RENDER_THREAD;
case CallStackProfileParams::UTILITY_THREAD:
return UTILITY_THREAD;
+ case CallStackProfileParams::COMPOSITOR_THREAD:
+ return COMPOSITOR_THREAD;
}
NOTREACHED();
return UNKNOWN_THREAD;
@@ -554,8 +559,19 @@ CallStackProfileMetricsProvider::~CallStackProfileMetricsProvider() {
}
StackSamplingProfiler::CompletedCallback
-CallStackProfileMetricsProvider::GetProfilerCallbackForBrowserProcessStartup() {
- return internal::GetProfilerCallback(&g_browser_process_sampling_params);
+CallStackProfileMetricsProvider::GetProfilerCallbackForBrowserProcess(
+ CallStackProfileParams* params) {
+ return internal::GetProfilerCallback(params);
+}
+
+StackSamplingProfiler::CompletedCallback CallStackProfileMetricsProvider::
+ GetProfilerCallbackForBrowserProcessUIThreadStartup() {
+ return internal::GetProfilerCallback(&g_ui_thread_sampling_params);
+}
+
+StackSamplingProfiler::CompletedCallback CallStackProfileMetricsProvider::
+ GetProfilerCallbackForBrowserProcessIOThreadStartup() {
+ return internal::GetProfilerCallback(&g_io_thread_sampling_params);
}
// static
@@ -608,14 +624,14 @@ void CallStackProfileMetricsProvider::ProvideCurrentSessionData(
for (const ProfilesState& profiles_state : pending_profiles) {
for (const StackSamplingProfiler::CallStackProfile& profile :
- profiles_state.profiles) {
+ profiles_state.profiles) {
SampledProfile* sampled_profile = uma_proto->add_sampled_profile();
- sampled_profile->set_process(ToExecutionContextProcess(
- profiles_state.params.process));
- sampled_profile->set_thread(ToExecutionContextThread(
- profiles_state.params.thread));
- sampled_profile->set_trigger_event(ToSampledProfileTriggerEvent(
- profiles_state.params.trigger));
+ sampled_profile->set_process(
+ ToExecutionContextProcess(profiles_state.params.process));
+ sampled_profile->set_thread(
+ ToExecutionContextThread(profiles_state.params.thread));
+ sampled_profile->set_trigger_event(
+ ToSampledProfileTriggerEvent(profiles_state.params.trigger));
CopyProfileToProto(profile, profiles_state.params.ordering_spec,
sampled_profile->mutable_call_stack_profile());
}
diff --git a/chromium/components/metrics/call_stack_profile_metrics_provider.h b/chromium/components/metrics/call_stack_profile_metrics_provider.h
index 0f6d2a02686..a6a1ca5a222 100644
--- a/chromium/components/metrics/call_stack_profile_metrics_provider.h
+++ b/chromium/components/metrics/call_stack_profile_metrics_provider.h
@@ -54,10 +54,24 @@ class CallStackProfileMetricsProvider : public MetricsProvider {
~CallStackProfileMetricsProvider() override;
// Returns a callback for use with StackSamplingProfiler that sets up
- // parameters for browser process startup sampling. The callback should be
+ // parameters for general browser process sampling. The callback should be
// immediately passed to the StackSamplingProfiler, and should not be reused.
static base::StackSamplingProfiler::CompletedCallback
- GetProfilerCallbackForBrowserProcessStartup();
+ GetProfilerCallbackForBrowserProcess(CallStackProfileParams* params);
+
+ // Returns a callback for use with StackSamplingProfiler that sets up
+ // parameters for UI thread of browser process startup sampling. The callback
+ // should be immediately passed to the StackSamplingProfiler, and should not
+ // be reused.
+ static base::StackSamplingProfiler::CompletedCallback
+ GetProfilerCallbackForBrowserProcessUIThreadStartup();
+
+ // Returns a callback for use with StackSamplingProfiler that sets up
+ // parameters for IO thread of browser process startup sampling. The callback
+ // should be immediately passed to the StackSamplingProfiler, and should not
+ // be reused.
+ static base::StackSamplingProfiler::CompletedCallback
+ GetProfilerCallbackForBrowserProcessIOThreadStartup();
// Provides completed stack profiles to the metrics provider. Intended for use
// when receiving profiles over IPC. In-process StackSamplingProfiler users
diff --git a/chromium/components/metrics/call_stack_profile_params.h b/chromium/components/metrics/call_stack_profile_params.h
index fad211616dc..9c74eedb8d6 100644
--- a/chromium/components/metrics/call_stack_profile_params.h
+++ b/chromium/components/metrics/call_stack_profile_params.h
@@ -30,19 +30,18 @@ struct CallStackProfileParams {
// Browser process threads, some of which occur in other processes as well.
UI_THREAD,
- FILE_THREAD,
- FILE_USER_BLOCKING_THREAD,
PROCESS_LAUNCHER_THREAD,
- CACHE_THREAD,
IO_THREAD,
- DB_THREAD,
// GPU process thread.
GPU_MAIN_THREAD,
// Renderer process threads.
RENDER_THREAD,
- UTILITY_THREAD
+ UTILITY_THREAD,
+
+ // Compositor thread (can be in both renderer and gpu processes).
+ COMPOSITOR_THREAD,
};
// The event that triggered the profile collection.
diff --git a/chromium/components/metrics/child_call_stack_profile_collector.cc b/chromium/components/metrics/child_call_stack_profile_collector.cc
index 09dc6c83eeb..71ed56cae72 100644
--- a/chromium/components/metrics/child_call_stack_profile_collector.cc
+++ b/chromium/components/metrics/child_call_stack_profile_collector.cc
@@ -55,6 +55,8 @@ void ChildCallStackProfileCollector::SetParentProfileCollector(
DCHECK(retain_profiles_);
retain_profiles_ = false;
task_runner_ = base::ThreadTaskRunnerHandle::Get();
+ // This should only be set one time per child process.
+ DCHECK(!parent_collector_);
parent_collector_ = std::move(parent_collector);
if (parent_collector_) {
for (ProfilesState& state : profiles_) {
@@ -89,10 +91,10 @@ void ChildCallStackProfileCollector::CollectImpl(
base::ThreadTaskRunnerHandle::Get() != task_runner_)) {
// Post back to the thread that owns the the parent interface.
task_runner_->PostTask(
- FROM_HERE, base::Bind(&ChildCallStackProfileCollector::CollectImpl,
- // This class has lazy instance lifetime.
- base::Unretained(this), params, start_timestamp,
- base::Passed(std::move(profiles))));
+ FROM_HERE, base::BindOnce(&ChildCallStackProfileCollector::CollectImpl,
+ // This class has lazy instance lifetime.
+ base::Unretained(this), params,
+ start_timestamp, std::move(profiles)));
return;
}
diff --git a/chromium/components/metrics/clean_exit_beacon.cc b/chromium/components/metrics/clean_exit_beacon.cc
index a73ddde1fca..74aefd897ba 100644
--- a/chromium/components/metrics/clean_exit_beacon.cc
+++ b/chromium/components/metrics/clean_exit_beacon.cc
@@ -23,6 +23,8 @@ CleanExitBeacon::CleanExitBeacon(const base::string16& backup_registry_key,
PrefService* local_state)
: local_state_(local_state),
initial_value_(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());
@@ -67,9 +69,13 @@ CleanExitBeacon::~CleanExitBeacon() {
// static
void CleanExitBeacon::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(prefs::kStabilityExitedCleanly, true);
+
+ registry->RegisterTimePref(prefs::kStabilityBrowserLastLiveTimeStamp,
+ base::Time(), PrefRegistry::LOSSY_PREF);
}
void CleanExitBeacon::WriteBeaconValue(bool value) {
+ UpdateLastLiveTimestamp();
local_state_->SetBoolean(prefs::kStabilityExitedCleanly, value);
#if defined(OS_WIN)
@@ -84,4 +90,9 @@ void CleanExitBeacon::WriteBeaconValue(bool value) {
#endif
}
+void CleanExitBeacon::UpdateLastLiveTimestamp() {
+ local_state_->SetTime(prefs::kStabilityBrowserLastLiveTimeStamp,
+ base::Time::Now());
+}
+
} // namespace metrics
diff --git a/chromium/components/metrics/clean_exit_beacon.h b/chromium/components/metrics/clean_exit_beacon.h
index e863e41e295..00435967587 100644
--- a/chromium/components/metrics/clean_exit_beacon.h
+++ b/chromium/components/metrics/clean_exit_beacon.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/strings/string16.h"
+#include "base/time/time.h"
class PrefRegistrySimple;
class PrefService;
@@ -30,15 +31,28 @@ class CleanExitBeacon {
// Returns the original value of the beacon.
bool exited_cleanly() const { return initial_value_; }
- // Writes the provided beacon value.
+ // Returns the original value of the last live timestamp.
+ base::Time browser_last_live_timestamp() const {
+ return initial_browser_last_live_timestamp_;
+ }
+
+ // Writes the provided beacon value and updates the last live timestamp.
void WriteBeaconValue(bool exited_cleanly);
+ // Updates the last live timestamp.
+ void UpdateLastLiveTimestamp();
+
// Registers local state prefs used by this class.
static void RegisterPrefs(PrefRegistrySimple* registry);
private:
PrefService* const local_state_;
const bool initial_value_;
+
+ // 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
+ // session when the browser was known to be alive.
+ const base::Time initial_browser_last_live_timestamp_;
const base::string16 backup_registry_key_;
DISALLOW_COPY_AND_ASSIGN(CleanExitBeacon);
diff --git a/chromium/components/metrics/component_metrics_provider.cc b/chromium/components/metrics/component_metrics_provider.cc
index 7ea0545662a..5ec24e2bf73 100644
--- a/chromium/components/metrics/component_metrics_provider.cc
+++ b/chromium/components/metrics/component_metrics_provider.cc
@@ -17,34 +17,52 @@ namespace {
SystemProfileProto_ComponentId CrxIdToComponentId(const std::string& app_id) {
const static std::map<std::string, SystemProfileProto_ComponentId>
component_map = {
- {"hfnkpimlhhgieaddgfemjhofmfblmnib",
- SystemProfileProto_ComponentId_CRL_SET},
- {"bjbdkfoakgmkndalgpadobhgbhhoanho",
- SystemProfileProto_ComponentId_EPSON_INKJET_PRINTER_ESCPR},
{"khaoiebndkojlmppeemjhbpbandiljpe",
SystemProfileProto_ComponentId_FILE_TYPE_POLICIES},
- {"mimojjlkmoijpicakmndhoigimigcmbb",
- SystemProfileProto_ComponentId_PEPPER_FLASH},
- {"ckjlcfmdbdglblbjglepgnoekdnkoklc",
- SystemProfileProto_ComponentId_PEPPER_FLASH_CHROMEOS},
{"kfoklmclfodeliojeaekpoflbkkhojea",
SystemProfileProto_ComponentId_ORIGIN_TRIALS},
{"llkgjffcdpffmhiakmfcdcblohccpfmo",
SystemProfileProto_ComponentId_ORIGIN_TRIALS}, // Alternate ID
+ {"mimojjlkmoijpicakmndhoigimigcmbb",
+ SystemProfileProto_ComponentId_PEPPER_FLASH},
+ {"ckjlcfmdbdglblbjglepgnoekdnkoklc",
+ SystemProfileProto_ComponentId_PEPPER_FLASH_CHROMEOS},
{"hnimpnehoodheedghdeeijklkeaacbdc",
SystemProfileProto_ComponentId_PNACL},
{"npdjjkjlcidkjlamlmmdelcjbcpdjocm",
SystemProfileProto_ComponentId_RECOVERY},
+ {"giekcmmlnklenlaomppkphknjmnnpneh",
+ SystemProfileProto_ComponentId_SSL_ERROR_ASSISTANT},
{"ojjgnpkioondelmggbekfhllhdaimnho",
SystemProfileProto_ComponentId_STH_SET},
+ {"hfnkpimlhhgieaddgfemjhofmfblmnib",
+ SystemProfileProto_ComponentId_CRL_SET},
{"gcmjkmgdlgnkkcocmoeiminaijmmjnii",
SystemProfileProto_ComponentId_SUBRESOURCE_FILTER},
{"gkmgaooipdjhmangpemjhigmamcehddo",
SystemProfileProto_ComponentId_SW_REPORTER},
- {"giekcmmlnklenlaomppkphknjmnnpneh",
- SystemProfileProto_ComponentId_SSL_ERROR_ASSISTANT},
{"oimompecagnajdejgnnjijobebaeigek",
- SystemProfileProto_ComponentId_WIDEVINE_CDM}};
+ SystemProfileProto_ComponentId_WIDEVINE_CDM},
+ {"bjbdkfoakgmkndalgpadobhgbhhoanho",
+ SystemProfileProto_ComponentId_EPSON_INKJET_PRINTER_ESCPR},
+ {"ojnjgapiepgciobpecnafnoeaegllfld",
+ SystemProfileProto_ComponentId_CROS_TERMINA},
+ {"gncenodapghbnkfkoognegdnjoeegmkp",
+ SystemProfileProto_ComponentId_STAR_CUPS_DRIVER},
+ {"gelhpeofhffbaeegmemklllhfdifagmb",
+ SystemProfileProto_ComponentId_SPEECH_SYNTHESIS_SV_SE},
+ {"lmelglejhemejginpboagddgdfbepgmp",
+ SystemProfileProto_ComponentId_OPTIMIZATION_HINTS},
+ {"fookoiellkocclipolgaceabajejjcnp",
+ SystemProfileProto_ComponentId_DOWNLOADABLE_STRINGS},
+ {"cjfkbpdpjpdldhclahpfgnlhpodlpnba",
+ SystemProfileProto_ComponentId_VR_ASSETS},
+ {"gjpajnddmedjmcklfflllocelehklffm",
+ SystemProfileProto_ComponentId_RTANALYTICS_LIGHT},
+ {"mjdmdobabdmfcbaakcaadileafkmifen",
+ SystemProfileProto_ComponentId_RTANALYTICS_FULL},
+ {"fhbeibbmaepakgdkkmjgldjajgpkkhfj",
+ SystemProfileProto_ComponentId_CELLULAR}};
const auto result = component_map.find(app_id);
if (result == component_map.end())
return SystemProfileProto_ComponentId_UNKNOWN;
diff --git a/chromium/components/metrics/drive_metrics_provider_linux.cc b/chromium/components/metrics/drive_metrics_provider_linux.cc
index 0ba3a9c06ea..149405e5f12 100644
--- a/chromium/components/metrics/drive_metrics_provider_linux.cc
+++ b/chromium/components/metrics/drive_metrics_provider_linux.cc
@@ -15,10 +15,6 @@
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
-#if defined(OS_CHROMEOS)
-#include "base/sys_info.h"
-#endif
-
namespace metrics {
namespace {
@@ -33,19 +29,6 @@ const char kRotationalFormat[] = "/sys/block/sd%c/queue/rotational";
// static
bool DriveMetricsProvider::HasSeekPenalty(const base::FilePath& path,
bool* has_seek_penalty) {
-#if defined(OS_CHROMEOS)
- // TODO(derat): Remove special-casing after October 2017 when parrot (Acer C7
- // Chromebook) is unsupported.
- std::string board = base::SysInfo::GetStrippedReleaseBoard();
- // There are "parrot", "parrot_ivb" and "parrot_freon" boards that have
- // devices with rotating disks. All other ChromeOS devices have SSDs.
- if (board != "unknown" &&
- !base::StartsWith(board, "parrot", base::CompareCase::SENSITIVE)) {
- *has_seek_penalty = false;
- return true;
- }
-#endif
-
base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
if (!file.IsValid())
return false;
diff --git a/chromium/components/metrics/file_metrics_provider.cc b/chromium/components/metrics/file_metrics_provider.cc
index 03f86f720ee..b57d396ec0a 100644
--- a/chromium/components/metrics/file_metrics_provider.cc
+++ b/chromium/components/metrics/file_metrics_provider.cc
@@ -4,6 +4,8 @@
#include "components/metrics/file_metrics_provider.h"
+#include <memory>
+
#include "base/command_line.h"
#include "base/containers/flat_map.h"
#include "base/files/file.h"
@@ -11,7 +13,6 @@
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/persistent_histogram_allocator.h"
@@ -82,30 +83,6 @@ enum EmbeddedProfileResult : int {
EMBEDDED_PROFILE_ACTION_MAX
};
-enum Happening : int {
- ON_DID_CREATE_METRICS_LOG,
- SCHEDULE_SOURCES_CHECK,
- CHECK_AND_MERGE_SOURCES,
- RECORD_SOURCES_CHECKED,
- CHECK_AND_MAP_SOURCE,
- FINISHED_WITH_SOURCE,
- RECORD_SOURCE_AS_READ,
- DELETE_FILE_ASYNC,
- MERGE_HISTOGRAM_DELTAS_FROM_SOURCE,
- RECORD_HISTOGRAM_SNAPSHOTS_FROM_SOURCE,
- PROVIDE_INDEPENDENT_METRICS,
- SCHEDULE_SOURCES_FAILED,
- OLD_DELETE_FILE_FAILED,
- OVER_DELETE_FILE_FAILED,
- ASYNC_DELETE_FILE_FAILED,
- MAX_HAPPENINGS
-};
-
-void RecordHappening(Happening happening) {
- UMA_HISTOGRAM_ENUMERATION("UMA.FileMetricsProvider.Happening", happening,
- MAX_HAPPENINGS);
-}
-
void RecordEmbeddedProfileResult(EmbeddedProfileResult result) {
UMA_HISTOGRAM_ENUMERATION("UMA.FileMetricsProvider.EmbeddedProfileResult",
result, EMBEDDED_PROFILE_ACTION_MAX);
@@ -116,12 +93,8 @@ void DeleteFileWhenPossible(const base::FilePath& path) {
// scope. This is the only cross-platform safe way to delete a file that may
// be open elsewhere, a distinct possibility given the asynchronous nature
// of the delete task.
- {
- base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ |
- base::File::FLAG_DELETE_ON_CLOSE);
- }
- if (base::PathExists(path))
- RecordHappening(ASYNC_DELETE_FILE_FAILED);
+ base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ |
+ base::File::FLAG_DELETE_ON_CLOSE);
}
// A task runner to use for testing.
@@ -154,7 +127,7 @@ struct FileMetricsProvider::SourceInfo {
switch (type) {
case SOURCE_HISTOGRAMS_ACTIVE_FILE:
DCHECK(prefs_key.empty());
- // fall through
+ FALLTHROUGH;
case SOURCE_HISTOGRAMS_ATOMIC_FILE:
path = params.path;
break;
@@ -299,7 +272,7 @@ bool FileMetricsProvider::LocateNextFileInDirectory(SourceInfo* source) {
base::Time now_time = base::Time::Now();
if (!source->found_files) {
- source->found_files = base::MakeUnique<SourceInfo::FoundFiles>();
+ source->found_files = std::make_unique<SourceInfo::FoundFiles>();
base::FileEnumerator file_iter(source->directory, /*recursive=*/false,
base::FileEnumerator::FILES);
SourceInfo::FoundFile found_file;
@@ -343,8 +316,6 @@ bool FileMetricsProvider::LocateNextFileInDirectory(SourceInfo* source) {
// is not removed, it will continue to be ignored bacuse of the older
// modification time.
base::DeleteFile(found_file.path, /*recursive=*/false);
- if (base::PathExists(found_file.path))
- RecordHappening(OLD_DELETE_FILE_FAILED);
++delete_count;
}
}
@@ -369,8 +340,6 @@ bool FileMetricsProvider::LocateNextFileInDirectory(SourceInfo* source) {
now_time - found.info.GetLastModifiedTime() > source->max_age;
if (too_many || too_big || too_old) {
base::DeleteFile(found.path, /*recursive=*/false);
- if (base::PathExists(found.path))
- RecordHappening(OVER_DELETE_FILE_FAILED);
++delete_count;
--file_count;
total_size_kib -= found.info.GetSize() >> 10;
@@ -401,8 +370,6 @@ bool FileMetricsProvider::LocateNextFileInDirectory(SourceInfo* source) {
// static
void FileMetricsProvider::FinishedWithSource(SourceInfo* source,
AccessResult result) {
- RecordHappening(FINISHED_WITH_SOURCE);
-
// Different source types require different post-processing.
switch (source->type) {
case SOURCE_HISTOGRAMS_ATOMIC_FILE:
@@ -429,8 +396,6 @@ void FileMetricsProvider::FinishedWithSource(SourceInfo* source,
// static
void FileMetricsProvider::CheckAndMergeMetricSourcesOnTaskRunner(
SourceInfoList* sources) {
- RecordHappening(CHECK_AND_MERGE_SOURCES);
-
// This method has all state information passed in |sources| and is intended
// to run on a worker thread rather than the UI thread.
for (std::unique_ptr<SourceInfo>& source : *sources) {
@@ -480,8 +445,6 @@ void FileMetricsProvider::CheckAndMergeMetricSourcesOnTaskRunner(
// static
FileMetricsProvider::AccessResult FileMetricsProvider::CheckAndMapMetricSource(
SourceInfo* source) {
- RecordHappening(CHECK_AND_MAP_SOURCE);
-
// If source was read, clean up after it.
if (source->read_complete)
FinishedWithSource(source, ACCESS_RESULT_SUCCESS);
@@ -537,7 +500,7 @@ FileMetricsProvider::AccessResult FileMetricsProvider::CheckAndMapMetricSource(
// Map the file and validate it.
std::unique_ptr<base::PersistentMemoryAllocator> memory_allocator =
- base::MakeUnique<base::FilePersistentMemoryAllocator>(
+ std::make_unique<base::FilePersistentMemoryAllocator>(
std::move(mapped), 0, 0, base::StringPiece(), read_only);
if (memory_allocator->GetMemoryState() ==
base::PersistentMemoryAllocator::MEMORY_DELETED) {
@@ -545,7 +508,7 @@ FileMetricsProvider::AccessResult FileMetricsProvider::CheckAndMapMetricSource(
}
// Create an allocator for the mapped file. Ownership passes to the allocator.
- source->allocator = base::MakeUnique<base::PersistentHistogramAllocator>(
+ source->allocator = std::make_unique<base::PersistentHistogramAllocator>(
std::move(memory_allocator));
// Check that an "independent" file has the necessary information present.
@@ -561,8 +524,6 @@ FileMetricsProvider::AccessResult FileMetricsProvider::CheckAndMapMetricSource(
// static
void FileMetricsProvider::MergeHistogramDeltasFromSource(SourceInfo* source) {
DCHECK(source->allocator);
- RecordHappening(MERGE_HISTOGRAM_DELTAS_FROM_SOURCE);
-
base::PersistentHistogramAllocator::Iterator histogram_iter(
source->allocator.get());
@@ -592,7 +553,6 @@ void FileMetricsProvider::RecordHistogramSnapshotsFromSource(
base::HistogramSnapshotManager* snapshot_manager,
SourceInfo* source) {
DCHECK_NE(SOURCE_HISTOGRAMS_ACTIVE_FILE, source->type);
- RecordHappening(RECORD_HISTOGRAM_SNAPSHOTS_FROM_SOURCE);
base::PersistentHistogramAllocator::Iterator histogram_iter(
source->allocator.get());
@@ -663,7 +623,6 @@ FileMetricsProvider::AccessResult FileMetricsProvider::HandleFilterSource(
void FileMetricsProvider::ScheduleSourcesCheck() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- RecordHappening(SCHEDULE_SOURCES_CHECK);
if (sources_to_check_.empty())
return;
@@ -674,19 +633,16 @@ void FileMetricsProvider::ScheduleSourcesCheck() {
// because that must complete before the reply runs.
SourceInfoList* check_list = new SourceInfoList();
std::swap(sources_to_check_, *check_list);
- bool success = task_runner_->PostTaskAndReply(
+ task_runner_->PostTaskAndReply(
FROM_HERE,
base::Bind(&FileMetricsProvider::CheckAndMergeMetricSourcesOnTaskRunner,
base::Unretained(check_list)),
base::Bind(&FileMetricsProvider::RecordSourcesChecked,
weak_factory_.GetWeakPtr(), base::Owned(check_list)));
- if (!success)
- RecordHappening(SCHEDULE_SOURCES_FAILED);
}
void FileMetricsProvider::RecordSourcesChecked(SourceInfoList* checked) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- RecordHappening(RECORD_SOURCES_CHECKED);
// Sources that still have an allocator at this point are read/write "active"
// files that may need their contents merged on-demand. If there is no
@@ -723,13 +679,11 @@ void FileMetricsProvider::RecordSourcesChecked(SourceInfoList* checked) {
}
void FileMetricsProvider::DeleteFileAsync(const base::FilePath& path) {
- RecordHappening(DELETE_FILE_ASYNC);
task_runner_->PostTask(FROM_HERE, base::Bind(DeleteFileWhenPossible, path));
}
void FileMetricsProvider::RecordSourceAsRead(SourceInfo* source) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- RecordHappening(RECORD_SOURCE_AS_READ);
// Persistently record the "last seen" timestamp of the source file to
// ensure that the file is never read again unless it is modified again.
@@ -742,7 +696,6 @@ void FileMetricsProvider::RecordSourceAsRead(SourceInfo* source) {
void FileMetricsProvider::OnDidCreateMetricsLog() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- RecordHappening(ON_DID_CREATE_METRICS_LOG);
// Schedule a check to see if there are new metrics to load. If so, they will
// be reported during the next collection run after this one. The check is run
@@ -764,7 +717,6 @@ bool FileMetricsProvider::ProvideIndependentMetrics(
SystemProfileProto* system_profile_proto,
base::HistogramSnapshotManager* snapshot_manager) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- RecordHappening(PROVIDE_INDEPENDENT_METRICS);
while (!sources_with_profile_.empty()) {
SourceInfo* source = sources_with_profile_.begin()->get();
diff --git a/chromium/components/metrics/metrics_log.cc b/chromium/components/metrics/metrics_log.cc
index 78012521d7f..6d691f9ef3f 100644
--- a/chromium/components/metrics/metrics_log.cc
+++ b/chromium/components/metrics/metrics_log.cc
@@ -13,6 +13,7 @@
#include "base/cpu.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_flattener.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/histogram_snapshot_manager.h"
@@ -303,6 +304,18 @@ void MetricsLog::TruncateEvents() {
if (uma_proto_.user_action_event_size() > internal::kUserActionEventLimit) {
UMA_HISTOGRAM_COUNTS_100000("UMA.TruncatedEvents.UserAction",
uma_proto_.user_action_event_size());
+ for (int i = internal::kUserActionEventLimit;
+ i < uma_proto_.user_action_event_size(); ++i) {
+ // No histograms.xml entry is added for this histogram because it uses an
+ // enum that is generated from actions.xml in our processing pipelines.
+ // Instead, a histogram description will also be produced in our
+ // pipelines.
+ base::UmaHistogramSparse(
+ "UMA.TruncatedEvents.UserAction.Type",
+ // Truncate the unsigned 64-bit hash to 31 bits, to make it a suitable
+ // histogram sample.
+ uma_proto_.user_action_event(i).name_hash() & 0x7fffffff);
+ }
uma_proto_.mutable_user_action_event()->DeleteSubrange(
internal::kUserActionEventLimit,
uma_proto_.user_action_event_size() - internal::kUserActionEventLimit);
diff --git a/chromium/components/metrics/metrics_pref_names.cc b/chromium/components/metrics/metrics_pref_names.cc
index 15e0b54e11d..5dcb253d711 100644
--- a/chromium/components/metrics/metrics_pref_names.cc
+++ b/chromium/components/metrics/metrics_pref_names.cc
@@ -74,6 +74,13 @@ const char kStabilityBreakpadRegistrationSuccess[] =
const char kStabilityBreakpadRegistrationFail[] =
"user_experience_metrics.stability.breakpad_registration_fail";
+// A time stamp at which time the browser was known to be alive. Used to
+// evaluate whether the browser crash was due to a whole system crash.
+// At minimum this is updated each time the "exited_cleanly" preference is
+// modified, but can also be optionally updated on a slow schedule.
+const char kStabilityBrowserLastLiveTimeStamp[] =
+ "user_experience_metrics.stability.browser_last_live_timestamp";
+
// Total number of child process crashes (other than renderer / extension
// renderer ones, and plugin children, which are counted separately) since the
// last report.
@@ -186,6 +193,12 @@ const char kStabilityStatsBuildTime[] =
const char kStabilityStatsVersion[] =
"user_experience_metrics.stability.stats_version";
+// Number of times the application exited uncleanly and the system session
+// embedding the browser session ended abnormally since the last report.
+// Windows only.
+const char kStabilitySystemCrashCount[] =
+ "user_experience_metrics.stability.system_crash_count";
+
// Number of times the version number stored in prefs did not match the
// serialized system profile version number.
const char kStabilityVersionMismatchCount[] =
diff --git a/chromium/components/metrics/metrics_pref_names.h b/chromium/components/metrics/metrics_pref_names.h
index 8dc9dc2ce1d..2024c49022f 100644
--- a/chromium/components/metrics/metrics_pref_names.h
+++ b/chromium/components/metrics/metrics_pref_names.h
@@ -32,20 +32,21 @@ extern const char kMetricsSessionID[];
extern const char kMetricsLastSeenPrefix[];
// Preferences for recording stability logs.
-extern const char kStabilityBreakpadRegistrationSuccess[];
extern const char kStabilityBreakpadRegistrationFail[];
+extern const char kStabilityBreakpadRegistrationSuccess[];
+extern const char kStabilityBrowserLastLiveTimeStamp[];
extern const char kStabilityChildProcessCrashCount[];
extern const char kStabilityCrashCount[];
extern const char kStabilityCrashCountWithoutGmsCoreUpdate[];
-extern const char kStabilityDebuggerPresent[];
extern const char kStabilityDebuggerNotPresent[];
+extern const char kStabilityDebuggerPresent[];
extern const char kStabilityDeferredCount[];
extern const char kStabilityDiscardCount[];
extern const char kStabilityExecutionPhase[];
+extern const char kStabilityExitedCleanly[];
extern const char kStabilityExtensionRendererCrashCount[];
extern const char kStabilityExtensionRendererFailedLaunchCount[];
extern const char kStabilityExtensionRendererLaunchCount[];
-extern const char kStabilityExitedCleanly[];
extern const char kStabilityGmsCoreVersion[];
extern const char kStabilityIncompleteSessionEndCount[];
extern const char kStabilityLaunchCount[];
@@ -59,6 +60,7 @@ extern const char kStabilitySavedSystemProfileHash[];
extern const char kStabilitySessionEndCompleted[];
extern const char kStabilityStatsBuildTime[];
extern const char kStabilityStatsVersion[];
+extern const char kStabilitySystemCrashCount[];
extern const char kStabilityVersionMismatchCount[];
// Preferences for generating metrics at uninstall time.
diff --git a/chromium/components/metrics/metrics_service.cc b/chromium/components/metrics/metrics_service.cc
index 4a26e60dacb..9b25de326a4 100644
--- a/chromium/components/metrics/metrics_service.cc
+++ b/chromium/components/metrics/metrics_service.cc
@@ -176,6 +176,9 @@ const int kInitializationDelaySeconds = 5;
const int kInitializationDelaySeconds = 30;
#endif
+// 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) {
@@ -227,11 +230,11 @@ MetricsService::MetricsService(MetricsStateManager* state_manager,
DCHECK(local_state_);
RegisterMetricsProvider(
- base::MakeUnique<StabilityMetricsProvider>(local_state_));
+ std::make_unique<StabilityMetricsProvider>(local_state_));
RegisterMetricsProvider(state_manager_->GetProvider());
- RegisterMetricsProvider(base::MakeUnique<variations::FieldTrialsProvider>(
+ RegisterMetricsProvider(std::make_unique<variations::FieldTrialsProvider>(
&synthetic_trial_registry_, base::StringPiece()));
}
@@ -254,6 +257,7 @@ void MetricsService::InitializeMetricsRecordingState() {
base::Bind(&MetricsServiceClient::GetStandardUploadInterval,
base::Unretained(client_))));
+ // Init() has to be called after LogCrash() in order for LogCrash() to work.
delegating_provider_.Init();
}
@@ -269,6 +273,14 @@ void MetricsService::StartRecordingForTests() {
DisableReporting();
}
+void MetricsService::StartUpdatingLastLiveTimestamp() {
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&MetricsService::UpdateLastLiveTimestampTask,
+ self_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(kUpdateAliveTimestampSeconds));
+}
+
void MetricsService::Stop() {
HandleIdleSinceLastTransmission(false);
DisableReporting();
@@ -474,7 +486,8 @@ void MetricsService::InitializeMetricsState() {
StabilityMetricsProvider provider(local_state_);
if (!state_manager_->clean_exit_beacon()->exited_cleanly()) {
- provider.LogCrash();
+ 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);
@@ -811,7 +824,7 @@ void MetricsService::CheckForClonedInstall() {
std::unique_ptr<MetricsLog> MetricsService::CreateLog(
MetricsLog::LogType log_type) {
- return base::MakeUnique<MetricsLog>(state_manager_->client_id(), session_id_,
+ return std::make_unique<MetricsLog>(state_manager_->client_id(), session_id_,
log_type, client_);
}
@@ -836,7 +849,6 @@ void MetricsService::RecordCurrentEnvironment(MetricsLog* log) {
void MetricsService::RecordCurrentHistograms() {
DCHECK(log_manager_.current_log());
- SCOPED_UMA_HISTOGRAM_TIMER("UMA.MetricsService.RecordCurrentHistograms.Time");
// "true" indicates that StatisticsRecorder should include histograms held in
// persistent storage.
@@ -900,4 +912,11 @@ void MetricsService::LogCleanShutdown(bool end_completed) {
StabilityMetricsProvider(local_state_).MarkSessionEndCompleted(end_completed);
}
+void MetricsService::UpdateLastLiveTimestampTask() {
+ state_manager_->clean_exit_beacon()->UpdateLastLiveTimestamp();
+
+ // Schecule the next update.
+ StartUpdatingLastLiveTimestamp();
+}
+
} // namespace metrics
diff --git a/chromium/components/metrics/metrics_service.h b/chromium/components/metrics/metrics_service.h
index 908d9ac1de1..647131422b2 100644
--- a/chromium/components/metrics/metrics_service.h
+++ b/chromium/components/metrics/metrics_service.h
@@ -78,6 +78,9 @@ class MetricsService : public base::HistogramFlattener {
// memory.
void StartRecordingForTests();
+ // Starts updating the "last live" browser timestamp.
+ void StartUpdatingLastLiveTimestamp();
+
// Shuts down the metrics system. Should be called at shutdown, or if metrics
// are turned off.
void Stop();
@@ -314,6 +317,9 @@ class MetricsService : public base::HistogramFlattener {
// check for others. The interval is so as to not adversely impact the UI.
void PrepareProviderMetricsTask();
+ // Updates the "last live" browser timestamp and schedules the next update.
+ void UpdateLastLiveTimestampTask();
+
// Sub-service for uploading logs.
MetricsReportingService reporting_service_;
diff --git a/chromium/components/metrics/metrics_service_accessor.cc b/chromium/components/metrics/metrics_service_accessor.cc
index 467210af09c..f00d2e8523f 100644
--- a/chromium/components/metrics/metrics_service_accessor.cc
+++ b/chromium/components/metrics/metrics_service_accessor.cc
@@ -9,23 +9,34 @@
#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/metrics_service.h"
#include "components/prefs/pref_service.h"
-#include "components/variations/metrics_util.h"
+#include "components/variations/hashing.h"
namespace metrics {
+namespace {
-// static
-bool MetricsServiceAccessor::IsMetricsReportingEnabled(
- PrefService* pref_service) {
-#if defined(GOOGLE_CHROME_BUILD)
+bool g_force_official_enabled_test = false;
+
+bool IsMetricsReportingEnabledForOfficialBuild(PrefService* pref_service) {
// In official builds, disable metrics when reporting field trials are
// forced; otherwise, use the value of the user's preference to determine
// whether to enable metrics reporting.
return !base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kForceFieldTrials) &&
pref_service->GetBoolean(prefs::kMetricsReportingEnabled);
+}
+
+} // namespace
+
+// static
+bool MetricsServiceAccessor::IsMetricsReportingEnabled(
+ PrefService* pref_service) {
+#if defined(GOOGLE_CHROME_BUILD)
+ return IsMetricsReportingEnabledForOfficialBuild(pref_service);
#else
// In non-official builds, disable metrics reporting completely.
- return false;
+ return g_force_official_enabled_test
+ ? IsMetricsReportingEnabledForOfficialBuild(pref_service)
+ : false;
#endif // defined(GOOGLE_CHROME_BUILD)
}
@@ -35,7 +46,8 @@ bool MetricsServiceAccessor::RegisterSyntheticFieldTrial(
base::StringPiece trial_name,
base::StringPiece group_name) {
return RegisterSyntheticFieldTrialWithNameAndGroupHash(
- metrics_service, HashName(trial_name), HashName(group_name));
+ metrics_service, variations::HashName(trial_name),
+ variations::HashName(group_name));
}
// static
@@ -47,7 +59,7 @@ bool MetricsServiceAccessor::RegisterSyntheticMultiGroupFieldTrial(
return false;
metrics_service->synthetic_trial_registry()
- ->RegisterSyntheticMultiGroupFieldTrial(HashName(trial_name),
+ ->RegisterSyntheticMultiGroupFieldTrial(variations::HashName(trial_name),
group_name_hashes);
return true;
}
@@ -58,7 +70,7 @@ bool MetricsServiceAccessor::RegisterSyntheticFieldTrialWithNameHash(
uint32_t trial_name_hash,
base::StringPiece group_name) {
return RegisterSyntheticFieldTrialWithNameAndGroupHash(
- metrics_service, trial_name_hash, HashName(group_name));
+ metrics_service, trial_name_hash, variations::HashName(group_name));
}
// static
@@ -75,4 +87,10 @@ bool MetricsServiceAccessor::RegisterSyntheticFieldTrialWithNameAndGroupHash(
return true;
}
+// static
+void MetricsServiceAccessor::SetForceIsMetricsReportingEnabledPrefLookup(
+ bool value) {
+ g_force_official_enabled_test = value;
+}
+
} // namespace metrics
diff --git a/chromium/components/metrics/metrics_service_accessor.h b/chromium/components/metrics/metrics_service_accessor.h
index 7e1a107778b..3a36278213c 100644
--- a/chromium/components/metrics/metrics_service_accessor.h
+++ b/chromium/components/metrics/metrics_service_accessor.h
@@ -65,6 +65,13 @@ class MetricsServiceAccessor {
uint32_t trial_name_hash,
uint32_t group_name_hash);
+ // IsMetricsReportingEnabled() in non-official builds unconditionally returns
+ // false. This results in different behavior for tests running in official vs
+ // non-official builds. To get consistent behavior call this with true, which
+ // forces non-official builds to look at the prefs value official builds look
+ // at.
+ static void SetForceIsMetricsReportingEnabledPrefLookup(bool value);
+
private:
DISALLOW_COPY_AND_ASSIGN(MetricsServiceAccessor);
};
diff --git a/chromium/components/metrics/metrics_service_client.cc b/chromium/components/metrics/metrics_service_client.cc
index 19f31f7aa48..4c67459df21 100644
--- a/chromium/components/metrics/metrics_service_client.cc
+++ b/chromium/components/metrics/metrics_service_client.cc
@@ -40,6 +40,10 @@ bool MetricsServiceClient::IsHistorySyncEnabledOnAllProfiles() {
return false;
}
+bool MetricsServiceClient::IsExtensionSyncEnabledOnAllProfiles() {
+ return false;
+}
+
void MetricsServiceClient::SetUpdateRunningServicesCallback(
const base::Closure& callback) {
update_running_services_ = callback;
diff --git a/chromium/components/metrics/metrics_service_client.h b/chromium/components/metrics/metrics_service_client.h
index e16498c93c0..989c8f23d8d 100644
--- a/chromium/components/metrics/metrics_service_client.h
+++ b/chromium/components/metrics/metrics_service_client.h
@@ -122,6 +122,9 @@ class MetricsServiceClient {
// Returns if history sync is enabled on all active profiles.
virtual bool IsHistorySyncEnabledOnAllProfiles();
+ // Returns if extensions sync is enabled on all active profiles.
+ virtual bool IsExtensionSyncEnabledOnAllProfiles();
+
// Sets the callback to run MetricsServiceManager::UpdateRunningServices.
void SetUpdateRunningServicesCallback(const base::Closure& callback);
diff --git a/chromium/components/metrics/metrics_service_unittest.cc b/chromium/components/metrics/metrics_service_unittest.cc
index fb6f3b3cc07..ff7fea35ddf 100644
--- a/chromium/components/metrics/metrics_service_unittest.cc
+++ b/chromium/components/metrics/metrics_service_unittest.cc
@@ -39,6 +39,11 @@ namespace metrics {
namespace {
+void YieldUntil(base::Time when) {
+ while (base::Time::Now() <= when)
+ base::PlatformThread::YieldCurrentThread();
+}
+
void StoreNoClientInfoBackup(const ClientInfo& /* client_info */) {
}
@@ -394,4 +399,46 @@ TEST_F(MetricsServiceTest, SplitRotation) {
EXPECT_EQ(1U, task_runner_->NumPendingTasks());
}
+TEST_F(MetricsServiceTest, LastLiveTimestamp) {
+ TestMetricsServiceClient client;
+ TestMetricsService service(GetMetricsStateManager(), &client,
+ GetLocalState());
+
+ base::Time initial_last_live_time =
+ GetLocalState()->GetTime(prefs::kStabilityBrowserLastLiveTimeStamp);
+
+ service.InitializeMetricsRecordingState();
+ service.Start();
+
+ task_runner_->RunPendingTasks();
+ size_t num_pending_tasks = task_runner_->NumPendingTasks();
+
+ service.StartUpdatingLastLiveTimestamp();
+
+ // Starting the update sequence should not write anything, but should
+ // set up for a later write.
+ EXPECT_EQ(
+ initial_last_live_time,
+ GetLocalState()->GetTime(prefs::kStabilityBrowserLastLiveTimeStamp));
+ EXPECT_EQ(num_pending_tasks + 1, task_runner_->NumPendingTasks());
+
+ // To avoid flakiness, yield until we're over a microsecond threshold.
+ YieldUntil(initial_last_live_time + base::TimeDelta::FromMicroseconds(2));
+
+ task_runner_->RunPendingTasks();
+
+ // Verify that the time has updated in local state.
+ base::Time updated_last_live_time =
+ GetLocalState()->GetTime(prefs::kStabilityBrowserLastLiveTimeStamp);
+ EXPECT_LT(initial_last_live_time, updated_last_live_time);
+
+ // Double check that an update schedules again...
+ YieldUntil(updated_last_live_time + base::TimeDelta::FromMicroseconds(2));
+
+ task_runner_->RunPendingTasks();
+ EXPECT_LT(
+ updated_last_live_time,
+ GetLocalState()->GetTime(prefs::kStabilityBrowserLastLiveTimeStamp));
+}
+
} // namespace metrics
diff --git a/chromium/components/metrics/metrics_state_manager.cc b/chromium/components/metrics/metrics_state_manager.cc
index ef15b0bf167..f4515c932e5 100644
--- a/chromium/components/metrics/metrics_state_manager.cc
+++ b/chromium/components/metrics/metrics_state_manager.cc
@@ -7,9 +7,10 @@
#include <stddef.h>
#include <utility>
+#include <memory>
+
#include "base/command_line.h"
#include "base/guid.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
@@ -162,7 +163,7 @@ MetricsStateManager::~MetricsStateManager() {
}
std::unique_ptr<MetricsProvider> MetricsStateManager::GetProvider() {
- return base::MakeUnique<MetricsStateMetricsProvider>(
+ return std::make_unique<MetricsStateMetricsProvider>(
local_state_, metrics_ids_were_reset_, previous_client_id_);
}
@@ -238,7 +239,7 @@ void MetricsStateManager::CheckForClonedInstall() {
if (!MachineIdProvider::HasId())
return;
- cloned_install_detector_ = base::MakeUnique<ClonedInstallDetector>();
+ cloned_install_detector_ = std::make_unique<ClonedInstallDetector>();
cloned_install_detector_->CheckForClonedInstall(local_state_);
}
@@ -258,7 +259,7 @@ MetricsStateManager::CreateDefaultEntropyProvider() {
const std::string high_entropy_source =
client_id_ + base::IntToString(low_entropy_source_value);
return std::unique_ptr<const base::FieldTrial::EntropyProvider>(
- new SHA1EntropyProvider(high_entropy_source));
+ new variations::SHA1EntropyProvider(high_entropy_source));
}
UpdateEntropySourceReturnedValue(ENTROPY_SOURCE_LOW);
@@ -271,12 +272,12 @@ MetricsStateManager::CreateLowEntropyProvider() {
#if defined(OS_ANDROID) || defined(OS_IOS)
return std::unique_ptr<const base::FieldTrial::EntropyProvider>(
- new CachingPermutedEntropyProvider(local_state_, low_entropy_source_value,
- kMaxLowEntropySize));
+ new variations::CachingPermutedEntropyProvider(
+ local_state_, low_entropy_source_value, kMaxLowEntropySize));
#else
return std::unique_ptr<const base::FieldTrial::EntropyProvider>(
- new PermutedEntropyProvider(low_entropy_source_value,
- kMaxLowEntropySize));
+ new variations::PermutedEntropyProvider(low_entropy_source_value,
+ kMaxLowEntropySize));
#endif
}
@@ -307,7 +308,7 @@ void MetricsStateManager::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterInt64Pref(prefs::kInstallDate, 0);
ClonedInstallDetector::RegisterPrefs(registry);
- CachingPermutedEntropyProvider::RegisterPrefs(registry);
+ variations::CachingPermutedEntropyProvider::RegisterPrefs(registry);
}
void MetricsStateManager::BackUpCurrentClientInfo() {
@@ -361,7 +362,7 @@ void MetricsStateManager::UpdateLowEntropySource() {
LogLowEntropyValue(low_entropy_source_);
local_state_->SetInteger(prefs::kMetricsLowEntropySource,
low_entropy_source_);
- CachingPermutedEntropyProvider::ClearCache(local_state_);
+ variations::CachingPermutedEntropyProvider::ClearCache(local_state_);
}
void MetricsStateManager::UpdateEntropySourceReturnedValue(
diff --git a/chromium/components/metrics/metrics_upload_scheduler.cc b/chromium/components/metrics/metrics_upload_scheduler.cc
index 22e1f2d72d8..457a725f412 100644
--- a/chromium/components/metrics/metrics_upload_scheduler.cc
+++ b/chromium/components/metrics/metrics_upload_scheduler.cc
@@ -15,13 +15,6 @@
namespace metrics {
-// This feature moves the upload schedule to a seperate schedule from the
-// log rotation schedule. This may change upload timing slightly, but
-// would allow some compartmentalization of uploader logic to allow more
-// code reuse between different metrics services.
-const base::Feature kUploadSchedulerFeature{"UMAUploadScheduler",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
namespace {
// When uploading metrics to the server fails, we progressively wait longer and
@@ -51,24 +44,16 @@ base::TimeDelta BackOffUploadInterval(base::TimeDelta interval) {
return interval;
}
-// Gets a time interval in seconds from a variations parameter.
-base::TimeDelta GetTimeParameterSeconds(const std::string& param_name,
- int default_seconds) {
- int seconds = base::GetFieldTrialParamByFeatureAsInt(
- kUploadSchedulerFeature, param_name, default_seconds);
- return base::TimeDelta::FromSeconds(seconds);
-}
-
// Time delay after a log is uploaded successfully before attempting another.
// On mobile, keeping the radio on is very expensive, so prefer to keep this
// short and send in bursts.
base::TimeDelta GetUnsentLogsInterval() {
- return GetTimeParameterSeconds("UnsentLogsIntervalSeconds", 3);
+ return base::TimeDelta::FromSeconds(3);
}
// Inital time delay after a log uploaded fails before retrying it.
base::TimeDelta GetInitialBackoffInterval() {
- return GetTimeParameterSeconds("InitialBackoffIntervalSeconds", 15);
+ return base::TimeDelta::FromSeconds(15);
}
} // namespace
diff --git a/chromium/components/metrics/metrics_upload_scheduler.h b/chromium/components/metrics/metrics_upload_scheduler.h
index b1fa958e8a0..a97b7cb1f1a 100644
--- a/chromium/components/metrics/metrics_upload_scheduler.h
+++ b/chromium/components/metrics/metrics_upload_scheduler.h
@@ -13,8 +13,6 @@
namespace metrics {
-extern const base::Feature kUploadSchedulerFeature;
-
// Scheduler task to drive a ReportingService object's uploading.
class MetricsUploadScheduler : public MetricsScheduler {
public:
diff --git a/chromium/components/metrics/net/network_metrics_provider_unittest.cc b/chromium/components/metrics/net/network_metrics_provider_unittest.cc
index a15a3686242..3731bce4cc4 100644
--- a/chromium/components/metrics/net/network_metrics_provider_unittest.cc
+++ b/chromium/components/metrics/net/network_metrics_provider_unittest.cc
@@ -4,6 +4,8 @@
#include "components/metrics/net/network_metrics_provider.h"
+#include <memory>
+
#include "base/callback.h"
#include "base/macros.h"
#include "base/run_loop.h"
@@ -195,7 +197,7 @@ TEST_F(NetworkMetricsProviderTest, ECTNotAmbiguousOnOffline) {
{net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
net::EFFECTIVE_CONNECTION_TYPE_OFFLINE}) {
std::unique_ptr<net::NetworkQualityEstimatorParams> params =
- base::MakeUnique<net::NetworkQualityEstimatorParams>(
+ std::make_unique<net::NetworkQualityEstimatorParams>(
std::map<std::string, std::string>());
net::NetworkQualityEstimatorParams* params_ptr = params.get();
net::TestNetworkQualityEstimator estimator(std::move(params));
@@ -284,4 +286,4 @@ TEST_F(NetworkMetricsProviderTest, ConnectionTypeIsAmbiguous) {
system_profile.network().connection_type());
}
-} // namespace metrics \ No newline at end of file
+} // namespace metrics
diff --git a/chromium/components/metrics/persistent_system_profile_unittest.cc b/chromium/components/metrics/persistent_system_profile_unittest.cc
index 4adaed3fb73..b3a7ec6d1ac 100644
--- a/chromium/components/metrics/persistent_system_profile_unittest.cc
+++ b/chromium/components/metrics/persistent_system_profile_unittest.cc
@@ -4,11 +4,12 @@
#include "components/metrics/persistent_system_profile.h"
+#include <memory>
+
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/persistent_memory_allocator.h"
#include "base/rand_util.h"
-#include "components/variations/metrics_util.h"
+#include "components/variations/hashing.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace metrics {
@@ -21,9 +22,9 @@ class PersistentSystemProfileTest : public testing::Test {
~PersistentSystemProfileTest() override {}
void SetUp() override {
- memory_allocator_ = base::MakeUnique<base::LocalPersistentMemoryAllocator>(
+ memory_allocator_ = std::make_unique<base::LocalPersistentMemoryAllocator>(
kAllocatorMemorySize, 0, "");
- records_ = base::MakeUnique<PersistentSystemProfile::RecordAllocator>(
+ records_ = std::make_unique<PersistentSystemProfile::RecordAllocator>(
memory_allocator_.get());
persistent_profile_.RegisterPersistentAllocator(memory_allocator_.get());
}
@@ -153,8 +154,8 @@ TEST_F(PersistentSystemProfileTest, ProfileExtensions) {
ASSERT_EQ(2, fetched.field_trial_size());
EXPECT_EQ(123U, fetched.field_trial(0).name_id());
EXPECT_EQ(456U, fetched.field_trial(0).group_id());
- EXPECT_EQ(metrics::HashName("sna"), fetched.field_trial(1).name_id());
- EXPECT_EQ(metrics::HashName("foo"), fetched.field_trial(1).group_id());
+ EXPECT_EQ(variations::HashName("sna"), fetched.field_trial(1).name_id());
+ EXPECT_EQ(variations::HashName("foo"), fetched.field_trial(1).group_id());
persistent_profile()->AddFieldTrial("foo", "bar");
ASSERT_TRUE(
@@ -162,10 +163,10 @@ TEST_F(PersistentSystemProfileTest, ProfileExtensions) {
ASSERT_EQ(3, fetched.field_trial_size());
EXPECT_EQ(123U, fetched.field_trial(0).name_id());
EXPECT_EQ(456U, fetched.field_trial(0).group_id());
- EXPECT_EQ(metrics::HashName("sna"), fetched.field_trial(1).name_id());
- EXPECT_EQ(metrics::HashName("foo"), fetched.field_trial(1).group_id());
- EXPECT_EQ(metrics::HashName("foo"), fetched.field_trial(2).name_id());
- EXPECT_EQ(metrics::HashName("bar"), fetched.field_trial(2).group_id());
+ EXPECT_EQ(variations::HashName("sna"), fetched.field_trial(1).name_id());
+ EXPECT_EQ(variations::HashName("foo"), fetched.field_trial(1).group_id());
+ EXPECT_EQ(variations::HashName("foo"), fetched.field_trial(2).name_id());
+ EXPECT_EQ(variations::HashName("bar"), fetched.field_trial(2).group_id());
}
} // namespace metrics
diff --git a/chromium/components/metrics/public/cpp/call_stack_profile_struct_traits.h b/chromium/components/metrics/public/cpp/call_stack_profile_struct_traits.h
index 6a3af7cf363..edea7ce7db0 100644
--- a/chromium/components/metrics/public/cpp/call_stack_profile_struct_traits.h
+++ b/chromium/components/metrics/public/cpp/call_stack_profile_struct_traits.h
@@ -230,24 +230,18 @@ struct EnumTraits<metrics::mojom::Thread,
return metrics::mojom::Thread::UNKNOWN_THREAD;
case metrics::CallStackProfileParams::Thread::UI_THREAD:
return metrics::mojom::Thread::UI_THREAD;
- case metrics::CallStackProfileParams::Thread::FILE_THREAD:
- return metrics::mojom::Thread::FILE_THREAD;
- case metrics::CallStackProfileParams::Thread::FILE_USER_BLOCKING_THREAD:
- return metrics::mojom::Thread::FILE_USER_BLOCKING_THREAD;
case metrics::CallStackProfileParams::Thread::PROCESS_LAUNCHER_THREAD:
return metrics::mojom::Thread::PROCESS_LAUNCHER_THREAD;
- case metrics::CallStackProfileParams::Thread::CACHE_THREAD:
- return metrics::mojom::Thread::CACHE_THREAD;
case metrics::CallStackProfileParams::Thread::IO_THREAD:
return metrics::mojom::Thread::IO_THREAD;
- case metrics::CallStackProfileParams::Thread::DB_THREAD:
- return metrics::mojom::Thread::DB_THREAD;
case metrics::CallStackProfileParams::Thread::GPU_MAIN_THREAD:
return metrics::mojom::Thread::GPU_MAIN_THREAD;
case metrics::CallStackProfileParams::Thread::RENDER_THREAD:
return metrics::mojom::Thread::RENDER_THREAD;
case metrics::CallStackProfileParams::Thread::UTILITY_THREAD:
return metrics::mojom::Thread::UTILITY_THREAD;
+ case metrics::CallStackProfileParams::Thread::COMPOSITOR_THREAD:
+ return metrics::mojom::Thread::COMPOSITOR_THREAD;
}
NOTREACHED();
return metrics::mojom::Thread::UNKNOWN_THREAD;
@@ -262,25 +256,12 @@ struct EnumTraits<metrics::mojom::Thread,
case metrics::mojom::Thread::UI_THREAD:
*out = metrics::CallStackProfileParams::Thread::UI_THREAD;
return true;
- case metrics::mojom::Thread::FILE_THREAD:
- *out = metrics::CallStackProfileParams::Thread::FILE_THREAD;
- return true;
- case metrics::mojom::Thread::FILE_USER_BLOCKING_THREAD:
- *out =
- metrics::CallStackProfileParams::Thread::FILE_USER_BLOCKING_THREAD;
- return true;
case metrics::mojom::Thread::PROCESS_LAUNCHER_THREAD:
*out = metrics::CallStackProfileParams::Thread::PROCESS_LAUNCHER_THREAD;
return true;
- case metrics::mojom::Thread::CACHE_THREAD:
- *out = metrics::CallStackProfileParams::Thread::CACHE_THREAD;
- return true;
case metrics::mojom::Thread::IO_THREAD:
*out = metrics::CallStackProfileParams::Thread::IO_THREAD;
return true;
- case metrics::mojom::Thread::DB_THREAD:
- *out = metrics::CallStackProfileParams::Thread::DB_THREAD;
- return true;
case metrics::mojom::Thread::GPU_MAIN_THREAD:
*out = metrics::CallStackProfileParams::Thread::GPU_MAIN_THREAD;
return true;
@@ -290,6 +271,9 @@ struct EnumTraits<metrics::mojom::Thread,
case metrics::mojom::Thread::UTILITY_THREAD:
*out = metrics::CallStackProfileParams::Thread::UTILITY_THREAD;
return true;
+ case metrics::mojom::Thread::COMPOSITOR_THREAD:
+ *out = metrics::CallStackProfileParams::Thread::COMPOSITOR_THREAD;
+ return true;
}
return false;
}
diff --git a/chromium/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc b/chromium/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc
index b6802d3e0ac..ae4b7c7e121 100644
--- a/chromium/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc
+++ b/chromium/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc
@@ -306,24 +306,12 @@ TEST_F(CallStackProfileStructTraitsTest, Thread) {
EXPECT_TRUE(proxy_->BounceThread(Thread::UI_THREAD, &out));
EXPECT_EQ(Thread::UI_THREAD, out);
- EXPECT_TRUE(proxy_->BounceThread(Thread::FILE_THREAD, &out));
- EXPECT_EQ(Thread::FILE_THREAD, out);
-
- EXPECT_TRUE(proxy_->BounceThread(Thread::FILE_USER_BLOCKING_THREAD, &out));
- EXPECT_EQ(Thread::FILE_USER_BLOCKING_THREAD, out);
-
EXPECT_TRUE(proxy_->BounceThread(Thread::PROCESS_LAUNCHER_THREAD, &out));
EXPECT_EQ(Thread::PROCESS_LAUNCHER_THREAD, out);
- EXPECT_TRUE(proxy_->BounceThread(Thread::CACHE_THREAD, &out));
- EXPECT_EQ(Thread::CACHE_THREAD, out);
-
EXPECT_TRUE(proxy_->BounceThread(Thread::IO_THREAD, &out));
EXPECT_EQ(Thread::IO_THREAD, out);
- EXPECT_TRUE(proxy_->BounceThread(Thread::DB_THREAD, &out));
- EXPECT_EQ(Thread::DB_THREAD, out);
-
EXPECT_TRUE(proxy_->BounceThread(Thread::GPU_MAIN_THREAD, &out));
EXPECT_EQ(Thread::GPU_MAIN_THREAD, out);
@@ -332,6 +320,9 @@ TEST_F(CallStackProfileStructTraitsTest, Thread) {
EXPECT_TRUE(proxy_->BounceThread(Thread::UTILITY_THREAD, &out));
EXPECT_EQ(Thread::UTILITY_THREAD, out);
+
+ EXPECT_TRUE(proxy_->BounceThread(Thread::COMPOSITOR_THREAD, &out));
+ EXPECT_EQ(Thread::COMPOSITOR_THREAD, out);
}
// Checks serialization/deserialization of the trigger, including validation.
diff --git a/chromium/components/metrics/public/interfaces/call_stack_profile_collector.mojom b/chromium/components/metrics/public/interfaces/call_stack_profile_collector.mojom
index 3573f906410..cff0ec4bbcf 100644
--- a/chromium/components/metrics/public/interfaces/call_stack_profile_collector.mojom
+++ b/chromium/components/metrics/public/interfaces/call_stack_profile_collector.mojom
@@ -48,17 +48,15 @@ enum Thread {
UNKNOWN_THREAD,
UI_THREAD,
- FILE_THREAD,
- FILE_USER_BLOCKING_THREAD,
PROCESS_LAUNCHER_THREAD,
- CACHE_THREAD,
IO_THREAD,
- DB_THREAD,
GPU_MAIN_THREAD,
RENDER_THREAD,
UTILITY_THREAD,
+
+ COMPOSITOR_THREAD,
};
enum Trigger {
diff --git a/chromium/components/metrics/single_sample_metrics.cc b/chromium/components/metrics/single_sample_metrics.cc
index 0f16c492ab7..201ef730bd2 100644
--- a/chromium/components/metrics/single_sample_metrics.cc
+++ b/chromium/components/metrics/single_sample_metrics.cc
@@ -4,9 +4,9 @@
#include "components/metrics/single_sample_metrics.h"
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "base/metrics/single_sample_metrics.h"
#include "base/threading/thread_checker.h"
#include "components/metrics/single_sample_metrics_factory_impl.h"
@@ -55,7 +55,7 @@ class MojoSingleSampleMetricsProvider
int32_t flags,
mojom::SingleSampleMetricRequest request) override {
DCHECK(thread_checker_.CalledOnValidThread());
- mojo::MakeStrongBinding(base::MakeUnique<MojoSingleSampleMetric>(
+ mojo::MakeStrongBinding(std::make_unique<MojoSingleSampleMetric>(
histogram_name, min, max, bucket_count, flags),
std::move(request));
}
@@ -71,14 +71,14 @@ class MojoSingleSampleMetricsProvider
// static
void InitializeSingleSampleMetricsFactory(CreateProviderCB create_provider_cb) {
base::SingleSampleMetricsFactory::SetFactory(
- base::MakeUnique<SingleSampleMetricsFactoryImpl>(
+ std::make_unique<SingleSampleMetricsFactoryImpl>(
std::move(create_provider_cb)));
}
// static
void CreateSingleSampleMetricsProvider(
mojom::SingleSampleMetricsProviderRequest request) {
- mojo::MakeStrongBinding(base::MakeUnique<MojoSingleSampleMetricsProvider>(),
+ mojo::MakeStrongBinding(std::make_unique<MojoSingleSampleMetricsProvider>(),
std::move(request));
}
diff --git a/chromium/components/metrics/single_sample_metrics_factory_impl.cc b/chromium/components/metrics/single_sample_metrics_factory_impl.cc
index 677fa8bc1bd..4ab48f8a9f2 100644
--- a/chromium/components/metrics/single_sample_metrics_factory_impl.cc
+++ b/chromium/components/metrics/single_sample_metrics_factory_impl.cc
@@ -4,6 +4,8 @@
#include "components/metrics/single_sample_metrics_factory_impl.h"
+#include <memory>
+
#include "base/threading/thread_checker.h"
namespace metrics {
@@ -65,7 +67,7 @@ SingleSampleMetricsFactoryImpl::CreateMetric(const std::string& histogram_name,
GetProvider()->AcquireSingleSampleMetric(histogram_name, min, max,
bucket_count, flags,
mojo::MakeRequest(&metric));
- return base::MakeUnique<SingleSampleMetricImpl>(std::move(metric));
+ return std::make_unique<SingleSampleMetricImpl>(std::move(metric));
}
mojom::SingleSampleMetricsProvider*
diff --git a/chromium/components/metrics/stability_metrics_provider.cc b/chromium/components/metrics/stability_metrics_provider.cc
index c71af184fbd..7d411d3e896 100644
--- a/chromium/components/metrics/stability_metrics_provider.cc
+++ b/chromium/components/metrics/stability_metrics_provider.cc
@@ -14,29 +14,32 @@
#if defined(OS_ANDROID)
#include "base/android/build_info.h"
#endif
+#if defined(OS_WIN)
+#include "components/metrics/system_session_analyzer_win.h"
+#endif
namespace metrics {
namespace {
#if defined(OS_ANDROID)
-bool UpdateGmsCoreVersionPref(PrefService* local_state) {
+bool HasGmsCoreVersionChanged(PrefService* local_state) {
std::string previous_version =
local_state->GetString(prefs::kStabilityGmsCoreVersion);
std::string current_version =
base::android::BuildInfo::GetInstance()->gms_version_code();
// If the last version is empty, treat it as consistent.
- if (previous_version.empty()) {
- local_state->SetString(prefs::kStabilityGmsCoreVersion, current_version);
- return true;
- }
+ if (previous_version.empty())
+ return false;
- if (previous_version == current_version)
- return true;
+ return previous_version != current_version;
+}
+void UpdateGmsCoreVersionPref(PrefService* local_state) {
+ std::string current_version =
+ base::android::BuildInfo::GetInstance()->gms_version_code();
local_state->SetString(prefs::kStabilityGmsCoreVersion, current_version);
- return false;
}
#endif
@@ -66,6 +69,17 @@ void StabilityMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterIntegerPref(prefs::kStabilityCrashCountWithoutGmsCoreUpdate,
0);
#endif
+#if defined(OS_WIN)
+ registry->RegisterIntegerPref(prefs::kStabilitySystemCrashCount, 0);
+#endif
+}
+
+void StabilityMetricsProvider::Init() {
+#if defined(OS_ANDROID)
+ // This method has to be called after HasGmsCoreVersionChanged() to avoid
+ // overwriting thie result.
+ UpdateGmsCoreVersionPref(local_state_);
+#endif
}
void StabilityMetricsProvider::ClearSavedStabilityMetrics() {
@@ -81,6 +95,9 @@ void StabilityMetricsProvider::ClearSavedStabilityMetrics() {
// Note: kStabilityDiscardCount is not cleared as its intent is to measure
// the number of times data is discarded, even across versions.
local_state_->SetInteger(prefs::kStabilityVersionMismatchCount, 0);
+#if defined(OS_WIN)
+ local_state_->SetInteger(prefs::kStabilitySystemCrashCount, 0);
+#endif
}
void StabilityMetricsProvider::ProvideStabilityMetrics(
@@ -135,6 +152,13 @@ void StabilityMetricsProvider::ProvideStabilityMetrics(
UMA_STABILITY_HISTOGRAM_COUNTS_100(
"Stability.Internals.VersionMismatchCount", pref_value);
}
+
+#if defined(OS_WIN)
+ if (GetPrefValue(prefs::kStabilitySystemCrashCount, &pref_value)) {
+ UMA_STABILITY_HISTOGRAM_COUNTS_100("Stability.Internals.SystemCrashCount",
+ pref_value);
+ }
+#endif
}
void StabilityMetricsProvider::RecordBreakpadRegistration(bool success) {
@@ -163,16 +187,20 @@ void StabilityMetricsProvider::MarkSessionEndCompleted(bool end_completed) {
local_state_->SetBoolean(prefs::kStabilitySessionEndCompleted, end_completed);
}
-void StabilityMetricsProvider::LogCrash() {
+void StabilityMetricsProvider::LogCrash(base::Time last_live_timestamp) {
IncrementPrefValue(prefs::kStabilityCrashCount);
#if defined(OS_ANDROID)
// On Android, if there is an update for GMS core when Chrome is running,
// Chrome will be killed and restart. This is expected and we should only
// report crash if the GMS core version has not been changed.
- if (UpdateGmsCoreVersionPref(local_state_))
+ if (!HasGmsCoreVersionChanged(local_state_))
IncrementPrefValue(prefs::kStabilityCrashCountWithoutGmsCoreUpdate);
#endif
+
+#if defined(OS_WIN)
+ MaybeLogSystemCrash(last_live_timestamp);
+#endif
}
void StabilityMetricsProvider::LogStabilityLogDeferred() {
@@ -191,6 +219,34 @@ void StabilityMetricsProvider::LogStabilityVersionMismatch() {
IncrementPrefValue(prefs::kStabilityVersionMismatchCount);
}
+#if defined(OS_WIN)
+bool StabilityMetricsProvider::IsUncleanSystemSession(
+ base::Time last_live_timestamp) {
+ DCHECK_NE(base::Time(), last_live_timestamp);
+ // There's a non-null last live timestamp, see if this occurred in
+ // a Windows system session that ended uncleanly. The expectation is that
+ // |last_live_timestamp| will have occurred in the immediately previous system
+ // session, but if the system has been restarted many times since Chrome last
+ // ran, that's not necessarily true. Log traversal can be expensive, so we
+ // limit the analyzer to reaching back three previous system sessions to bound
+ // the cost of the traversal.
+ SystemSessionAnalyzer analyzer(3);
+
+ SystemSessionAnalyzer::Status status =
+ analyzer.IsSessionUnclean(last_live_timestamp);
+
+ return status == SystemSessionAnalyzer::UNCLEAN;
+}
+
+void StabilityMetricsProvider::MaybeLogSystemCrash(
+ base::Time last_live_timestamp) {
+ if (last_live_timestamp != base::Time() &&
+ IsUncleanSystemSession(last_live_timestamp)) {
+ IncrementPrefValue(prefs::kStabilitySystemCrashCount);
+ }
+}
+#endif
+
void StabilityMetricsProvider::IncrementPrefValue(const char* path) {
int value = local_state_->GetInteger(path);
local_state_->SetInteger(path, value + 1);
diff --git a/chromium/components/metrics/stability_metrics_provider.h b/chromium/components/metrics/stability_metrics_provider.h
index 51781269093..3aeff6317fb 100644
--- a/chromium/components/metrics/stability_metrics_provider.h
+++ b/chromium/components/metrics/stability_metrics_provider.h
@@ -5,6 +5,8 @@
#ifndef COMPONENTS_METRICS_STABILITY_METRICS_PROVIDER_H_
#define COMPONENTS_METRICS_STABILITY_METRICS_PROVIDER_H_
+#include "base/time/time.h"
+#include "build/build_config.h"
#include "components/metrics/metrics_provider.h"
class PrefService;
@@ -28,13 +30,21 @@ class StabilityMetricsProvider : public MetricsProvider {
void CheckLastSessionEndCompleted();
void MarkSessionEndCompleted(bool end_completed);
- void LogCrash();
+ void LogCrash(base::Time last_live_timestamp);
void LogStabilityLogDeferred();
void LogStabilityDataDiscarded();
void LogLaunch();
void LogStabilityVersionMismatch();
private:
+#if defined(OS_WIN)
+ // This function is virtual for testing. The |last_live_timestamp| is a
+ // time point where the previous browser was known to be alive, and is used
+ // to determine whether the system session embedding that timestamp terminated
+ // uncleanly.
+ virtual bool IsUncleanSystemSession(base::Time last_live_timestamp);
+ void MaybeLogSystemCrash(base::Time last_live_timestamp);
+#endif
// Increments an Integer pref value specified by |path|.
void IncrementPrefValue(const char* path);
@@ -42,6 +52,7 @@ class StabilityMetricsProvider : public MetricsProvider {
int GetPrefValue(const char* path, int* value);
// MetricsProvider:
+ void Init() override;
void ClearSavedStabilityMetrics() override;
void ProvideStabilityMetrics(
SystemProfileProto* system_profile_proto) override;
diff --git a/chromium/components/metrics/stability_metrics_provider_unittest.cc b/chromium/components/metrics/stability_metrics_provider_unittest.cc
index b1f5b41c0b0..3a188ec3f83 100644
--- a/chromium/components/metrics/stability_metrics_provider_unittest.cc
+++ b/chromium/components/metrics/stability_metrics_provider_unittest.cc
@@ -4,6 +4,8 @@
#include "components/metrics/stability_metrics_provider.h"
+#include "base/test/histogram_tester.h"
+#include "build/build_config.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/metrics_proto/system_profile.pb.h"
@@ -46,7 +48,7 @@ TEST_F(StabilityMetricsProviderTest, RecordStabilityMetrics) {
{
StabilityMetricsProvider recorder(&prefs_);
recorder.LogLaunch();
- recorder.LogCrash();
+ recorder.LogCrash(base::Time());
recorder.MarkSessionEndCompleted(false);
recorder.CheckLastSessionEndCompleted();
recorder.RecordBreakpadRegistration(true);
@@ -73,4 +75,58 @@ TEST_F(StabilityMetricsProviderTest, RecordStabilityMetrics) {
}
}
+#if defined(OS_WIN)
+namespace {
+
+class TestingStabilityMetricsProvider : public StabilityMetricsProvider {
+ public:
+ TestingStabilityMetricsProvider(PrefService* local_state,
+ base::Time unclean_session_time)
+ : StabilityMetricsProvider(local_state),
+ unclean_session_time_(unclean_session_time) {}
+
+ bool IsUncleanSystemSession(base::Time last_live_timestamp) override {
+ return last_live_timestamp == unclean_session_time_;
+ }
+
+ private:
+ const base::Time unclean_session_time_;
+};
+
+} // namespace
+
+TEST_F(StabilityMetricsProviderTest, RecordSystemCrashMetrics) {
+ {
+ base::Time unclean_time = base::Time::Now();
+ TestingStabilityMetricsProvider recorder(&prefs_, unclean_time);
+
+ // Any crash with a last_live_timestamp equal to unclean_time will
+ // be logged as a system crash as per the implementation of
+ // TestingStabilityMetricsProvider, so this will log a system crash.
+ recorder.LogCrash(unclean_time);
+
+ // Record a crash with no system crash.
+ recorder.LogCrash(unclean_time - base::TimeDelta::FromMinutes(1));
+ }
+
+ {
+ StabilityMetricsProvider stability_provider(&prefs_);
+ MetricsProvider* provider = &stability_provider;
+ SystemProfileProto system_profile;
+
+ base::HistogramTester histogram_tester;
+
+ provider->ProvideStabilityMetrics(&system_profile);
+
+ const SystemProfileProto_Stability& stability = system_profile.stability();
+ // Two crashes, one system crash.
+ EXPECT_EQ(2, stability.crash_count());
+
+ histogram_tester.ExpectTotalCount("Stability.Internals.SystemCrashCount",
+ 1);
+ }
+}
+
+#endif
+
} // namespace metrics
diff --git a/chromium/components/browser_watcher/system_session_analyzer_win.cc b/chromium/components/metrics/system_session_analyzer_win.cc
index e4882199e58..2f28d4acd1a 100644
--- a/chromium/components/browser_watcher/system_session_analyzer_win.cc
+++ b/chromium/components/metrics/system_session_analyzer_win.cc
@@ -2,17 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/browser_watcher/system_session_analyzer_win.h"
-
-#include <windows.h>
-#include <winevt.h>
-
-#include <utility>
+#include "components/metrics/system_session_analyzer_win.h"
#include "base/macros.h"
#include "base/time/time.h"
-namespace browser_watcher {
+namespace metrics {
namespace {
@@ -44,16 +39,6 @@ const wchar_t kEventTimePath[] = L"Event/System/TimeCreated/@SystemTime";
// The timeout to use for calls to ::EvtNext.
const uint32_t kTimeoutMs = 5000;
-struct EvtHandleCloser {
- using pointer = EVT_HANDLE;
- void operator()(EVT_HANDLE handle) const {
- if (handle)
- ::EvtClose(handle);
- }
-};
-
-using EvtHandle = std::unique_ptr<EVT_HANDLE, EvtHandleCloser>;
-
base::Time ULLFileTimeToTime(ULONGLONG time_ulonglong) {
// Copy low / high parts as FILETIME is not always 64bit aligned.
ULARGE_INTEGER time;
@@ -65,20 +50,6 @@ base::Time ULLFileTimeToTime(ULONGLONG time_ulonglong) {
return base::Time::FromFileTime(ft);
}
-// Create a render context (i.e. specify attributes of interest).
-EvtHandle CreateRenderContext() {
- LPCWSTR value_paths[] = {kEventIdPath, kEventTimePath};
- const DWORD kValueCnt = arraysize(value_paths);
-
- EVT_HANDLE context = NULL;
- context =
- ::EvtCreateRenderContext(kValueCnt, value_paths, EvtRenderContextValues);
- if (!context)
- DLOG(ERROR) << "Failed to create render context.";
-
- return EvtHandle(context);
-}
-
bool GetEventInfo(EVT_HANDLE context,
EVT_HANDLE event,
SystemSessionAnalyzer::EventInfo* info) {
@@ -115,20 +86,28 @@ bool GetEventInfo(EVT_HANDLE context,
} // namespace
-SystemSessionAnalyzer::SystemSessionAnalyzer(uint32_t session_cnt)
- : session_cnt_(session_cnt) {}
+SystemSessionAnalyzer::SystemSessionAnalyzer(uint32_t max_session_cnt)
+ : max_session_cnt_(max_session_cnt), sessions_queried_(0) {}
SystemSessionAnalyzer::~SystemSessionAnalyzer() {}
SystemSessionAnalyzer::Status SystemSessionAnalyzer::IsSessionUnclean(
base::Time timestamp) {
- if (!initialized_) {
- DCHECK(!init_success_);
- init_success_ = Initialize();
- initialized_ = true;
- }
- if (!init_success_)
+ if (!EnsureInitialized())
return FAILED;
+
+ while (timestamp < coverage_start_ && sessions_queried_ < max_session_cnt_) {
+ // Fetch the next session start and end events.
+ std::vector<EventInfo> events;
+ if (!FetchEvents(2U, &events) || events.size() != 2)
+ return FAILED;
+
+ if (!ProcessSession(events[0], events[1]))
+ return FAILED;
+
+ ++sessions_queried_;
+ }
+
if (timestamp < coverage_start_)
return OUTSIDE_RANGE;
@@ -144,26 +123,21 @@ SystemSessionAnalyzer::Status SystemSessionAnalyzer::IsSessionUnclean(
return is_spanned ? UNCLEAN : CLEAN;
}
-bool SystemSessionAnalyzer::FetchEvents(
- std::vector<EventInfo>* event_infos) const {
+bool SystemSessionAnalyzer::FetchEvents(size_t requested_events,
+ std::vector<EventInfo>* event_infos) {
DCHECK(event_infos);
- // Query for the events. Note: requesting events from newest to oldest.
- EVT_HANDLE query_raw =
- ::EvtQuery(nullptr, kChannelName, kSessionEventsQuery,
- EvtQueryChannelPath | EvtQueryReverseDirection);
- if (!query_raw) {
- DLOG(ERROR) << "Event query failed.";
+ if (!EnsureHandlesOpened())
return false;
- }
- EvtHandle query(query_raw);
+
+ DCHECK(query_handle_.get());
// Retrieve events: 2 events per session, plus the current session's start.
- DWORD desired_event_cnt = 2U * session_cnt_ + 1U;
+ DWORD desired_event_cnt = requested_events;
std::vector<EVT_HANDLE> events_raw(desired_event_cnt, NULL);
DWORD event_cnt = 0U;
- BOOL success = ::EvtNext(query.get(), desired_event_cnt, events_raw.data(),
- kTimeoutMs, 0, &event_cnt);
+ BOOL success = ::EvtNext(query_handle_.get(), desired_event_cnt,
+ events_raw.data(), kTimeoutMs, 0, &event_cnt);
// Ensure handles get closed. The MSDN sample seems to imply handles may need
// to be closed event in if EvtNext failed.
@@ -176,17 +150,12 @@ bool SystemSessionAnalyzer::FetchEvents(
return false;
}
- // Extract information from the events.
- EvtHandle render_context = CreateRenderContext();
- if (!render_context.get())
- return false;
-
std::vector<EventInfo> event_infos_tmp;
event_infos_tmp.reserve(event_cnt);
EventInfo info = {};
for (size_t i = 0; i < event_cnt; ++i) {
- if (!GetEventInfo(render_context.get(), events[i].get(), &info))
+ if (!GetEventInfo(render_context_.get(), events[i].get(), &info))
return false;
event_infos_tmp.push_back(info);
}
@@ -195,50 +164,100 @@ bool SystemSessionAnalyzer::FetchEvents(
return true;
}
-bool SystemSessionAnalyzer::Initialize() {
- std::vector<SystemSessionAnalyzer::EventInfo> events;
- if (!FetchEvents(&events))
- return false;
+bool SystemSessionAnalyzer::EnsureInitialized() {
+ if (!initialized_) {
+ DCHECK(!init_success_);
+ init_success_ = Initialize();
+ initialized_ = true;
+ }
+
+ return init_success_;
+}
+
+bool SystemSessionAnalyzer::EnsureHandlesOpened() {
+ // Create the event query.
+ // Note: requesting events from newest to oldest.
+ if (!query_handle_.get()) {
+ query_handle_.reset(
+ ::EvtQuery(nullptr, kChannelName, kSessionEventsQuery,
+ EvtQueryChannelPath | EvtQueryReverseDirection));
+ if (!query_handle_.get()) {
+ DLOG(ERROR) << "Event query failed.";
+ return false;
+ }
+ }
- // Validate the number and ordering of events (newest to oldest). The
- // expectation is a (start / [unclean]shutdown) pair of events for each
- // session, as well as an additional event for the current session's start.
- size_t event_cnt = events.size();
- if ((event_cnt % 2) == 0)
- return false; // Even number is unexpected.
- if (event_cnt < 3)
- return false; // Not enough data for a single session.
- for (size_t i = 1; i < event_cnt; ++i) {
- if (events[i - 1].event_time < events[i].event_time)
+ if (!render_context_.get()) {
+ // Create the render context for extracting information from the events.
+ render_context_ = CreateRenderContext();
+ if (!render_context_.get())
return false;
}
- // Step through (start / shutdown) event pairs, validating the types of events
+ return true;
+}
+
+bool SystemSessionAnalyzer::Initialize() {
+ DCHECK(!initialized_);
+
+ // Fetch the first (current) session start event and the first session,
+ // comprising an end and a start event for a total of 3 events.
+ std::vector<EventInfo> events;
+ if (!FetchEvents(3U, &events))
+ return false;
+
+ // Validate that the initial event is what we expect.
+ if (events.size() != 3 || events[0].event_id != kIdSessionStart)
+ return false;
+
+ // Initialize the coverage start to allow detecting event time inversion.
+ coverage_start_ = events[0].event_time;
+
+ if (!ProcessSession(events[1], events[2]))
+ return false;
+
+ sessions_queried_ = 1;
+
+ return true;
+}
+
+bool SystemSessionAnalyzer::ProcessSession(const EventInfo& end,
+ const EventInfo& start) {
+ // Validate the ordering of events (newest to oldest). The expectation is a
+ // (start / [unclean]shutdown) pair of events for each session.
+ if (coverage_start_ < end.event_time)
+ return false;
+ if (end.event_time < start.event_time)
+ return false;
+
+ // Process a (start / shutdown) event pair, validating the types of events
// and recording unclean sessions.
- std::map<base::Time, base::TimeDelta> unclean_sessions;
- size_t start = 2U;
- size_t end = 1U;
- for (; start < event_cnt && end < event_cnt; start += 2, end += 2) {
- uint16_t start_id = events[start].event_id;
- uint16_t end_id = events[end].event_id;
- if (start_id != kIdSessionStart)
- return false; // Unexpected event type.
- if (end_id != kIdSessionEnd && end_id != kIdSessionEndUnclean)
- return false; // Unexpected event type.
-
- if (end_id == kIdSessionEnd)
- continue; // This is a clean session.
-
- unclean_sessions.insert(
- std::make_pair(events[start].event_time,
- events[end].event_time - events[start].event_time));
+ if (start.event_id != kIdSessionStart)
+ return false; // Unexpected event type.
+ if (end.event_id != kIdSessionEnd && end.event_id != kIdSessionEndUnclean)
+ return false; // Unexpected event type.
+
+ if (end.event_id == kIdSessionEndUnclean) {
+ unclean_sessions_.insert(
+ std::make_pair(start.event_time, end.event_time - start.event_time));
}
- unclean_sessions_.swap(unclean_sessions);
- DCHECK_GT(event_cnt, 0U);
- coverage_start_ = events[event_cnt - 1].event_time;
+ coverage_start_ = start.event_time;
return true;
}
-} // namespace browser_watcher
+SystemSessionAnalyzer::EvtHandle SystemSessionAnalyzer::CreateRenderContext() {
+ LPCWSTR value_paths[] = {kEventIdPath, kEventTimePath};
+ const DWORD kValueCnt = arraysize(value_paths);
+
+ EVT_HANDLE context = NULL;
+ context =
+ ::EvtCreateRenderContext(kValueCnt, value_paths, EvtRenderContextValues);
+ if (!context)
+ DLOG(ERROR) << "Failed to create render context.";
+
+ return EvtHandle(context);
+}
+
+} // namespace metrics
diff --git a/chromium/components/browser_watcher/system_session_analyzer_win.h b/chromium/components/metrics/system_session_analyzer_win.h
index 33162cd8419..2bd83e10e71 100644
--- a/chromium/components/browser_watcher/system_session_analyzer_win.h
+++ b/chromium/components/metrics/system_session_analyzer_win.h
@@ -5,14 +5,18 @@
#ifndef COMPONENTS_BROWSER_WATCHER_SYSTEM_SESSION_ANALYZER_WIN_H_
#define COMPONENTS_BROWSER_WATCHER_SYSTEM_SESSION_ANALYZER_WIN_H_
+#include <windows.h>
+#include <winevt.h>
+
#include <map>
#include <memory>
+#include <utility>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/time/time.h"
-namespace browser_watcher {
+namespace metrics {
// Analyzes system session events for unclean sessions. Initialization is
// expensive and therefore done lazily, as the analyzer is instantiated before
@@ -33,35 +37,58 @@ class SystemSessionAnalyzer {
};
// Creates a SystemSessionAnalyzer that will analyze system sessions based on
- // events pertaining to the last session_cnt system sessions.
- explicit SystemSessionAnalyzer(uint32_t session_cnt);
+ // events pertaining to as many as |max_session_cnt| of the most recent system
+ // sessions.
+ explicit SystemSessionAnalyzer(uint32_t max_session_cnt);
virtual ~SystemSessionAnalyzer();
- // Returns an analysis status for the system session that contains timestamp.
+ // Returns an analysis status for the system session that contains
+ // |timestamp|.
virtual Status IsSessionUnclean(base::Time timestamp);
protected:
- // Queries for events pertaining to the last session_cnt sessions. On success,
- // returns true and event_infos contains events ordered from newest to oldest.
+ // Queries for the next |requested_events|. On success, returns true and
+ // |event_infos| contains up to |requested_events| events ordered from newest
+ // to oldest.
// Returns false otherwise. Virtual for unit testing.
- virtual bool FetchEvents(std::vector<EventInfo>* event_infos) const;
+ virtual bool FetchEvents(size_t requested_events,
+ std::vector<EventInfo>* event_infos);
private:
+ struct EvtHandleCloser {
+ using pointer = EVT_HANDLE;
+ void operator()(EVT_HANDLE handle) const {
+ if (handle)
+ ::EvtClose(handle);
+ }
+ };
+ using EvtHandle = std::unique_ptr<EVT_HANDLE, EvtHandleCloser>;
+
FRIEND_TEST_ALL_PREFIXES(SystemSessionAnalyzerTest, FetchEvents);
+ bool EnsureInitialized();
+ bool EnsureHandlesOpened();
bool Initialize();
+ // Validates that |end| and |start| have sane event IDs and event times.
+ // Updates |coverage_start_| and adds the session to unclean_sessions_
+ // as appropriate.
+ bool ProcessSession(const EventInfo& end, const EventInfo& start);
- // The number of sessions to query events for.
- uint32_t session_cnt_;
+ EvtHandle CreateRenderContext();
+
+ // The maximal number of sessions to query events for.
+ uint32_t max_session_cnt_;
+ uint32_t sessions_queried_;
bool initialized_ = false;
bool init_success_ = false;
- // Information about unclean sessions: start time to duration until the next
- // session start, ie *not* session duration. Note: it's easier to get the
- // delta to the next session start, and changes nothing wrt classifying
- // events that occur during sessions assuming query timestamps fall within
- // system sessions.
+ // A handle to the query, valid after a successful initialize.
+ EvtHandle query_handle_;
+ // A handle to the event render context, valid after a successful initialize.
+ EvtHandle render_context_;
+
+ // Information about unclean sessions: start time to session duration.
std::map<base::Time, base::TimeDelta> unclean_sessions_;
// Timestamp of the oldest event.
@@ -70,6 +97,6 @@ class SystemSessionAnalyzer {
DISALLOW_COPY_AND_ASSIGN(SystemSessionAnalyzer);
};
-} // namespace browser_watcher
+} // namespace metrics
#endif // COMPONENTS_BROWSER_WATCHER_SYSTEM_SESSION_ANALYZER_WIN_H_
diff --git a/chromium/components/browser_watcher/system_session_analyzer_win_unittest.cc b/chromium/components/metrics/system_session_analyzer_win_unittest.cc
index 62c96234b7b..bd7b1f8cebe 100644
--- a/chromium/components/browser_watcher/system_session_analyzer_win_unittest.cc
+++ b/chromium/components/metrics/system_session_analyzer_win_unittest.cc
@@ -2,8 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/browser_watcher/system_session_analyzer_win.h"
+#include "components/metrics/system_session_analyzer_win.h"
+#include <algorithm>
#include <utility>
#include <vector>
@@ -11,7 +12,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace browser_watcher {
+namespace metrics {
namespace {
@@ -22,13 +23,11 @@ const uint16_t kIdSessionEndUnclean = 6008U;
} // namespace
// Ensure the fetcher retrieves events.
-// Note: this test fails if the host system doesn't have at least 1 prior
-// session.
TEST(SystemSessionAnalyzerTest, FetchEvents) {
- SystemSessionAnalyzer analyzer(1U);
+ SystemSessionAnalyzer analyzer(0);
std::vector<SystemSessionAnalyzer::EventInfo> events;
- ASSERT_TRUE(analyzer.FetchEvents(&events));
- EXPECT_EQ(3U, events.size());
+ ASSERT_TRUE(analyzer.FetchEvents(1U, &events));
+ EXPECT_EQ(1U, events.size());
}
// Ensure the fetcher's retrieved events conform to our expectations.
@@ -43,11 +42,20 @@ TEST(SystemSessionAnalyzerTest, ValidateEvents) {
// Stubs FetchEvents.
class StubSystemSessionAnalyzer : public SystemSessionAnalyzer {
public:
- StubSystemSessionAnalyzer() : SystemSessionAnalyzer(10U) {}
+ StubSystemSessionAnalyzer(uint32_t max_session_cnt)
+ : SystemSessionAnalyzer(max_session_cnt) {}
- bool FetchEvents(std::vector<EventInfo>* event_infos) const override {
+ bool FetchEvents(size_t requested_events,
+ std::vector<EventInfo>* event_infos) override {
DCHECK(event_infos);
- *event_infos = events_;
+ size_t num_to_copy = std::min(requested_events, events_.size());
+ if (num_to_copy) {
+ event_infos->clear();
+ event_infos->insert(event_infos->begin(), events_.begin(),
+ events_.begin() + num_to_copy);
+ events_.erase(events_.begin(), events_.begin() + num_to_copy);
+ }
+
return true;
}
@@ -58,7 +66,7 @@ class StubSystemSessionAnalyzer : public SystemSessionAnalyzer {
};
TEST(SystemSessionAnalyzerTest, StandardCase) {
- StubSystemSessionAnalyzer analyzer;
+ StubSystemSessionAnalyzer analyzer(2U);
base::Time time = base::Time::Now();
analyzer.AddEvent({kIdSessionStart, time});
@@ -85,13 +93,13 @@ TEST(SystemSessionAnalyzerTest, StandardCase) {
}
TEST(SystemSessionAnalyzerTest, NoEvent) {
- StubSystemSessionAnalyzer analyzer;
+ StubSystemSessionAnalyzer analyzer(0U);
EXPECT_EQ(SystemSessionAnalyzer::FAILED,
analyzer.IsSessionUnclean(base::Time::Now()));
}
TEST(SystemSessionAnalyzerTest, TimeInversion) {
- StubSystemSessionAnalyzer analyzer;
+ StubSystemSessionAnalyzer analyzer(1U);
base::Time time = base::Time::Now();
analyzer.AddEvent({kIdSessionStart, time});
@@ -103,7 +111,7 @@ TEST(SystemSessionAnalyzerTest, TimeInversion) {
}
TEST(SystemSessionAnalyzerTest, IdInversion) {
- StubSystemSessionAnalyzer analyzer;
+ StubSystemSessionAnalyzer analyzer(1U);
base::Time time = base::Time::Now();
analyzer.AddEvent({kIdSessionStart, time});
@@ -114,4 +122,4 @@ TEST(SystemSessionAnalyzerTest, IdInversion) {
analyzer.IsSessionUnclean(base::Time::Now()));
}
-} // namespace browser_watcher
+} // namespace metrics
diff --git a/chromium/components/metrics_services_manager/metrics_services_manager.cc b/chromium/components/metrics_services_manager/metrics_services_manager.cc
index 03c23eafd6b..19b8b1eca76 100644
--- a/chromium/components/metrics_services_manager/metrics_services_manager.cc
+++ b/chromium/components/metrics_services_manager/metrics_services_manager.cc
@@ -144,7 +144,8 @@ void MetricsServicesManager::UpdateUkmService() {
bool is_incognito = client_->IsIncognitoSessionActive();
if (consent_given_ && sync_enabled & !is_incognito) {
- ukm->EnableRecording();
+ ukm->EnableRecording(
+ metrics_service_client_->IsExtensionSyncEnabledOnAllProfiles());
if (may_upload_)
ukm->EnableReporting();
else
diff --git a/chromium/components/multidevice/BUILD.gn b/chromium/components/multidevice/BUILD.gn
index f41d7bf2c0b..e5a908b0cbb 100644
--- a/chromium/components/multidevice/BUILD.gn
+++ b/chromium/components/multidevice/BUILD.gn
@@ -7,6 +7,7 @@ if (!is_ios && !is_android) {
testonly = true
deps = [
"//components/multidevice/service:multidevice_service_unittest",
+ "//components/multidevice/service:unit_tests",
]
}
}
diff --git a/chromium/components/multidevice/OWNERS b/chromium/components/multidevice/OWNERS
index 88535c42fb4..1d672caacf2 100644
--- a/chromium/components/multidevice/OWNERS
+++ b/chromium/components/multidevice/OWNERS
@@ -1,4 +1,4 @@
khorimoto@chromium.org
-tengs@chromium.org
+jlklein@chromium.org
# COMPONENT: UI>ProximityAuth
diff --git a/chromium/components/multidevice/service/BUILD.gn b/chromium/components/multidevice/service/BUILD.gn
index 3a6fd3109d2..0ed51e0391e 100644
--- a/chromium/components/multidevice/service/BUILD.gn
+++ b/chromium/components/multidevice/service/BUILD.gn
@@ -10,6 +10,12 @@ if (!is_ios && !is_android) {
static_library("service") {
sources = [
+ "cryptauth_client_factory_impl.cc",
+ "cryptauth_client_factory_impl.h",
+ "cryptauth_enroller_factory_impl.cc",
+ "cryptauth_enroller_factory_impl.h",
+ "cryptauth_token_fetcher_impl.cc",
+ "cryptauth_token_fetcher_impl.h",
"device_sync_impl.cc",
"device_sync_impl.h",
"fake_device_sync.cc",
@@ -20,12 +26,14 @@ if (!is_ios && !is_android) {
deps = [
"//base",
+ "//net",
+ "//services/identity/public/cpp",
]
public_deps = [
"//components/cryptauth",
"//components/multidevice/service/public/interfaces",
- "//services/identity/public/interfaces",
+ "//services/identity/public/mojom",
"//services/service_manager/public/cpp",
]
}
@@ -35,6 +43,28 @@ if (!is_ios && !is_android) {
source = "multidevice_service_manifest.json"
}
+ source_set("unit_tests") {
+ testonly = true
+
+ sources = [
+ "cryptauth_token_fetcher_impl_unittest.cc",
+ ]
+
+ deps = [
+ ":service",
+ "//base",
+ "//base/test:test_support",
+ "//components/cryptauth",
+ "//components/cryptauth:test_support",
+ "//components/multidevice/service/public/interfaces",
+ "//mojo/common",
+ "//services/identity/public/cpp:test_support",
+ "//services/service_manager/public/cpp:service_test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+ }
+
service("multidevice") {
sources = [
"test_main.cc",
diff --git a/chromium/components/multidevice/service/DEPS b/chromium/components/multidevice/service/DEPS
index e4018723bb5..b3f8adc0cfe 100644
--- a/chromium/components/multidevice/service/DEPS
+++ b/chromium/components/multidevice/service/DEPS
@@ -1,5 +1,10 @@
include_rules = [
+ "+components/cryptauth",
+ "+components/signin/core/browser",
+ "+google_apis/gaia",
"+mojo/public/cpp",
+ "+net/url_request",
+ "+services/identity",
"+services/service_manager/public/cpp",
"+components/cryptauth"
]
@@ -8,4 +13,4 @@ specific_include_rules = {
"test_main\.cc": [
"+services/service_manager/public",
]
-} \ No newline at end of file
+}
diff --git a/chromium/components/multidevice/service/cryptauth_client_factory_impl.cc b/chromium/components/multidevice/service/cryptauth_client_factory_impl.cc
new file mode 100644
index 00000000000..863a6361abe
--- /dev/null
+++ b/chromium/components/multidevice/service/cryptauth_client_factory_impl.cc
@@ -0,0 +1,30 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/multidevice/service/cryptauth_client_factory_impl.h"
+
+#include "components/cryptauth/cryptauth_client_impl.h"
+#include "components/multidevice/service/cryptauth_token_fetcher_impl.h"
+
+namespace multidevice {
+
+CryptAuthClientFactoryImpl::CryptAuthClientFactoryImpl(
+ identity::IdentityManager* identity_manager,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context,
+ const cryptauth::DeviceClassifier& device_classifier)
+ : identity_manager_(identity_manager),
+ url_request_context_(std::move(url_request_context)),
+ device_classifier_(device_classifier) {}
+
+CryptAuthClientFactoryImpl::~CryptAuthClientFactoryImpl() = default;
+
+std::unique_ptr<cryptauth::CryptAuthClient>
+CryptAuthClientFactoryImpl::CreateInstance() {
+ return std::make_unique<cryptauth::CryptAuthClientImpl>(
+ std::make_unique<cryptauth::CryptAuthApiCallFlow>(),
+ std::make_unique<CryptAuthAccessTokenFetcherImpl>(identity_manager_),
+ url_request_context_, device_classifier_);
+}
+
+} // namespace multidevice
diff --git a/chromium/components/multidevice/service/cryptauth_client_factory_impl.h b/chromium/components/multidevice/service/cryptauth_client_factory_impl.h
new file mode 100644
index 00000000000..236818f3818
--- /dev/null
+++ b/chromium/components/multidevice/service/cryptauth_client_factory_impl.h
@@ -0,0 +1,42 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_MULTIDEVICE_CRYPTAUTH_CLIENT_FACTORY_IMPL
+#define COMPONENTS_MULTIDEVICE_CRYPTAUTH_CLIENT_FACTORY_IMPL
+
+#include "base/memory/ref_counted.h"
+#include "components/cryptauth/cryptauth_client.h"
+#include "components/cryptauth/proto/cryptauth_api.pb.h"
+
+namespace identity {
+class IdentityManager;
+} // namespace identity
+
+namespace net {
+class URLRequestContextGetter;
+} // namespace net
+
+namespace multidevice {
+
+// CryptAuthClientFactory implementation which utilizes IdentityManager.
+class CryptAuthClientFactoryImpl : public cryptauth::CryptAuthClientFactory {
+ public:
+ CryptAuthClientFactoryImpl(
+ identity::IdentityManager* identity_manager,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context,
+ const cryptauth::DeviceClassifier& device_classifier);
+ ~CryptAuthClientFactoryImpl() override;
+
+ // cryptauth::CryptAuthClientFactory:
+ std::unique_ptr<cryptauth::CryptAuthClient> CreateInstance() override;
+
+ private:
+ identity::IdentityManager* identity_manager_;
+ const scoped_refptr<net::URLRequestContextGetter> url_request_context_;
+ const cryptauth::DeviceClassifier device_classifier_;
+};
+
+} // namespace multidevice
+
+#endif // COMPONENTS_MULTIDEVICE_CRYPTAUTH_CLIENT_FACTORY_IMPL
diff --git a/chromium/components/multidevice/service/cryptauth_enroller_factory_impl.cc b/chromium/components/multidevice/service/cryptauth_enroller_factory_impl.cc
new file mode 100644
index 00000000000..92ab84213cd
--- /dev/null
+++ b/chromium/components/multidevice/service/cryptauth_enroller_factory_impl.cc
@@ -0,0 +1,34 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/multidevice/service/cryptauth_enroller_factory_impl.h"
+
+#include <memory>
+
+#include "components/cryptauth/cryptauth_enroller_impl.h"
+#include "components/multidevice/service/cryptauth_client_factory_impl.h"
+
+namespace multidevice {
+
+CryptAuthEnrollerFactoryImpl::CryptAuthEnrollerFactoryImpl(
+ identity::IdentityManager* identity_manager,
+ cryptauth::SecureMessageDelegate::Factory* secure_message_delegate_factory,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context,
+ const cryptauth::DeviceClassifier& device_classifier)
+ : identity_manager_(identity_manager),
+ secure_message_delegate_factory_(secure_message_delegate_factory),
+ url_request_context_(url_request_context),
+ device_classifier_(device_classifier) {}
+
+CryptAuthEnrollerFactoryImpl::~CryptAuthEnrollerFactoryImpl() {}
+
+std::unique_ptr<cryptauth::CryptAuthEnroller>
+CryptAuthEnrollerFactoryImpl::CreateInstance() {
+ return std::make_unique<cryptauth::CryptAuthEnrollerImpl>(
+ std::make_unique<CryptAuthClientFactoryImpl>(
+ identity_manager_, url_request_context_, device_classifier_),
+ secure_message_delegate_factory_->CreateSecureMessageDelegate());
+}
+
+} // namespace multidevice
diff --git a/chromium/components/multidevice/service/cryptauth_enroller_factory_impl.h b/chromium/components/multidevice/service/cryptauth_enroller_factory_impl.h
new file mode 100644
index 00000000000..4a1c1fbaf8a
--- /dev/null
+++ b/chromium/components/multidevice/service/cryptauth_enroller_factory_impl.h
@@ -0,0 +1,48 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_MULTIDEVICE_CRYPTAUTH_ENROLLER_FACTORY_IMPL
+#define COMPONENTS_MULTIDEVICE_CRYPTAUTH_ENROLLER_FACTORY_IMPL
+
+#include "base/memory/ref_counted.h"
+#include "components/cryptauth/cryptauth_enroller.h"
+#include "components/cryptauth/proto/cryptauth_api.pb.h"
+#include "components/cryptauth/secure_message_delegate.h"
+#include "net/url_request/url_request_context_getter.h"
+
+namespace identity {
+class IdentityManager;
+} // namespace identity
+
+namespace net {
+class URLRequestContextGetter;
+} // namespace net
+
+namespace multidevice {
+
+// CryptAuthEnrollerFactory implementation which utilizes IdentityManager.
+class CryptAuthEnrollerFactoryImpl
+ : public cryptauth::CryptAuthEnrollerFactory {
+ public:
+ CryptAuthEnrollerFactoryImpl(
+ identity::IdentityManager* identity_manager,
+ cryptauth::SecureMessageDelegate::Factory*
+ secure_message_delegate_factory,
+ scoped_refptr<net::URLRequestContextGetter> url_request_context,
+ const cryptauth::DeviceClassifier& device_classifier);
+ ~CryptAuthEnrollerFactoryImpl() override;
+
+ // cryptauth::CryptAuthEnrollerFactory:
+ std::unique_ptr<cryptauth::CryptAuthEnroller> CreateInstance() override;
+
+ private:
+ identity::IdentityManager* identity_manager_;
+ cryptauth::SecureMessageDelegate::Factory* secure_message_delegate_factory_;
+ const scoped_refptr<net::URLRequestContextGetter> url_request_context_;
+ const cryptauth::DeviceClassifier device_classifier_;
+};
+
+} // namespace multidevice
+
+#endif // COMPONENTS_MULTIDEVICE_CRYPTAUTH_ENROLLER_FACTORY_IMPL
diff --git a/chromium/components/multidevice/service/cryptauth_token_fetcher_impl.cc b/chromium/components/multidevice/service/cryptauth_token_fetcher_impl.cc
new file mode 100644
index 00000000000..d6eb47a2366
--- /dev/null
+++ b/chromium/components/multidevice/service/cryptauth_token_fetcher_impl.cc
@@ -0,0 +1,71 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/multidevice/service/cryptauth_token_fetcher_impl.h"
+
+#include <set>
+
+#include "services/identity/public/cpp/identity_manager.h"
+
+namespace multidevice {
+
+namespace {
+
+const char kIdentityManagerConsumerName[] = "multi_device_service";
+const char kCryptAuthApiScope[] = "https://www.googleapis.com/auth/cryptauth";
+
+} // namespace
+
+CryptAuthAccessTokenFetcherImpl::CryptAuthAccessTokenFetcherImpl(
+ identity::IdentityManager* identity_manager)
+ : identity_manager_(identity_manager), weak_ptr_factory_(this) {}
+
+CryptAuthAccessTokenFetcherImpl::~CryptAuthAccessTokenFetcherImpl() {
+ // If any callbacks are still pending when the object is deleted, run them
+ // now, passing an empty string to indicate failure. This ensures that no
+ // callbacks are left hanging forever.
+ InvokeThenClearPendingCallbacks(std::string());
+}
+
+void CryptAuthAccessTokenFetcherImpl::FetchAccessToken(
+ const AccessTokenCallback& callback) {
+ pending_callbacks_.emplace_back(callback);
+
+ // If the token is already being fetched, continue waiting for it.
+ if (access_token_fetcher_)
+ return;
+
+ const OAuth2TokenService::ScopeSet kScopes{kCryptAuthApiScope};
+ access_token_fetcher_ =
+ identity_manager_->CreateAccessTokenFetcherForPrimaryAccount(
+ kIdentityManagerConsumerName, kScopes,
+ base::Bind(&CryptAuthAccessTokenFetcherImpl::OnAccessTokenFetched,
+ weak_ptr_factory_.GetWeakPtr()),
+ identity::PrimaryAccountAccessTokenFetcher::Mode::kImmediate);
+}
+
+void CryptAuthAccessTokenFetcherImpl::InvokeThenClearPendingCallbacks(
+ const std::string& access_token) {
+ for (auto& callback : pending_callbacks_)
+ callback.Run(access_token);
+
+ pending_callbacks_.clear();
+}
+
+void CryptAuthAccessTokenFetcherImpl::OnAccessTokenFetched(
+ const GoogleServiceAuthError& error,
+ const std::string& access_token) {
+ // Move |access_token_fetcher_| to a temporary std::unique_ptr so that it is
+ // deleted at the end of this function. This is done instead of deleting
+ // |access_token_fetcher_| at the end of this function to ensure that if any
+ // observers invoke FetchAccessToken(), a new object will be created.
+ std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher>
+ token_fetcher_deleter = std::move(access_token_fetcher_);
+
+ InvokeThenClearPendingCallbacks(
+ error == GoogleServiceAuthError::AuthErrorNone() ? access_token
+ : std::string());
+}
+
+} // namespace multidevice
diff --git a/chromium/components/multidevice/service/cryptauth_token_fetcher_impl.h b/chromium/components/multidevice/service/cryptauth_token_fetcher_impl.h
new file mode 100644
index 00000000000..fee1bb303bc
--- /dev/null
+++ b/chromium/components/multidevice/service/cryptauth_token_fetcher_impl.h
@@ -0,0 +1,49 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_MULTIDEVICE_CRYPTAUTH_ACCESS_TOKEN_FETCHER_IMPL
+#define COMPONENTS_MULTIDEVICE_CRYPTAUTH_ACCESS_TOKEN_FETCHER_IMPL
+
+#include <memory>
+#include <vector>
+
+#include "base/memory/weak_ptr.h"
+#include "components/cryptauth/cryptauth_access_token_fetcher.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+
+namespace identity {
+class IdentityManager;
+class PrimaryAccountAccessTokenFetcher;
+} // namespace identity
+
+namespace multidevice {
+
+// CryptAuthAccessTokenFetcher implementation which utilizes IdentityManager.
+class CryptAuthAccessTokenFetcherImpl
+ : public cryptauth::CryptAuthAccessTokenFetcher {
+ public:
+ CryptAuthAccessTokenFetcherImpl(identity::IdentityManager* identity_manager);
+
+ ~CryptAuthAccessTokenFetcherImpl() override;
+
+ // cryptauth::CryptAuthAccessTokenFetcher:
+ void FetchAccessToken(const AccessTokenCallback& callback) override;
+
+ private:
+ void InvokeThenClearPendingCallbacks(const std::string& access_token);
+ void OnAccessTokenFetched(const GoogleServiceAuthError& error,
+ const std::string& access_token);
+
+ identity::IdentityManager* identity_manager_;
+
+ std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher>
+ access_token_fetcher_;
+ std::vector<AccessTokenCallback> pending_callbacks_;
+
+ base::WeakPtrFactory<CryptAuthAccessTokenFetcherImpl> weak_ptr_factory_;
+};
+
+} // namespace multidevice
+
+#endif // COMPONENTS_MULTIDEVICE_CRYPTAUTH_ACCESS_TOKEN_FETCHER_IMPL
diff --git a/chromium/components/multidevice/service/cryptauth_token_fetcher_impl_unittest.cc b/chromium/components/multidevice/service/cryptauth_token_fetcher_impl_unittest.cc
new file mode 100644
index 00000000000..6fe129e89fd
--- /dev/null
+++ b/chromium/components/multidevice/service/cryptauth_token_fetcher_impl_unittest.cc
@@ -0,0 +1,126 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/multidevice/service/cryptauth_token_fetcher_impl.h"
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "services/identity/public/cpp/identity_test_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace multidevice {
+
+namespace {
+
+const char kAccessToken[] = "access_token";
+const char kTestEmail[] = "example@gmail.com";
+
+} // namespace
+
+class MultiDeviceCryptAuthAccessTokenFetcherImplTest : public testing::Test {
+ protected:
+ MultiDeviceCryptAuthAccessTokenFetcherImplTest() {}
+
+ void SetUp() override {
+ identity_test_environment_ =
+ std::make_unique<identity::IdentityTestEnvironment>();
+ identity_test_environment_->MakePrimaryAccountAvailable(kTestEmail);
+
+ token_fetcher_ = std::make_unique<CryptAuthAccessTokenFetcherImpl>(
+ identity_test_environment_->identity_manager());
+ }
+
+ void TearDown() override {
+ // Deleting the object should not result in any additional tokens provided.
+ token_fetcher_.reset();
+ EXPECT_EQ(nullptr, GetTokenAndReset());
+
+ EXPECT_TRUE(on_access_token_received_callback_.is_null());
+ }
+
+ void set_on_access_token_received_callback(
+ base::OnceClosure on_access_token_received_callback) {
+ EXPECT_TRUE(on_access_token_received_callback_.is_null());
+ on_access_token_received_callback_ =
+ std::move(on_access_token_received_callback);
+ }
+
+ void StartFetchingAccessToken() {
+ token_fetcher_->FetchAccessToken(base::Bind(
+ &MultiDeviceCryptAuthAccessTokenFetcherImplTest::OnAccessTokenFetched,
+ base::Unretained(this)));
+ }
+
+ void OnAccessTokenFetched(const std::string& access_token) {
+ last_access_token_ = std::make_unique<std::string>(access_token);
+ if (!on_access_token_received_callback_.is_null())
+ std::move(on_access_token_received_callback_).Run();
+ }
+
+ std::unique_ptr<std::string> GetTokenAndReset() {
+ return std::move(last_access_token_);
+ }
+
+ const base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ std::unique_ptr<std::string> last_access_token_;
+ base::OnceClosure on_access_token_received_callback_;
+
+ std::unique_ptr<identity::IdentityTestEnvironment> identity_test_environment_;
+ std::unique_ptr<CryptAuthAccessTokenFetcherImpl> token_fetcher_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MultiDeviceCryptAuthAccessTokenFetcherImplTest);
+};
+
+TEST_F(MultiDeviceCryptAuthAccessTokenFetcherImplTest, TestSuccess) {
+ base::RunLoop run_loop;
+ set_on_access_token_received_callback(run_loop.QuitClosure());
+
+ // Start fetching the token. Nothing should be returned yet since the message
+ // loop has not been run.
+ StartFetchingAccessToken();
+ EXPECT_EQ(nullptr, GetTokenAndReset());
+
+ identity_test_environment_->WaitForAccessTokenRequestAndRespondWithToken(
+ kAccessToken, base::Time::Max() /* expiration */);
+
+ // Run the request and confirm that the access token was returned.
+ run_loop.Run();
+ EXPECT_EQ(kAccessToken, *GetTokenAndReset());
+}
+
+TEST_F(MultiDeviceCryptAuthAccessTokenFetcherImplTest, TestFailure) {
+ base::RunLoop run_loop;
+ set_on_access_token_received_callback(run_loop.QuitClosure());
+
+ // Start fetching the token. Nothing should be returned yet since the message
+ // loop has not been run.
+ StartFetchingAccessToken();
+ EXPECT_EQ(nullptr, GetTokenAndReset());
+
+ identity_test_environment_->WaitForAccessTokenRequestAndRespondWithError(
+ GoogleServiceAuthError(
+ GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
+
+ // Run the request and confirm that an empty string was returned, signifying a
+ // failure to fetch the token.
+ run_loop.Run();
+ EXPECT_EQ(std::string(), *GetTokenAndReset());
+}
+
+TEST_F(MultiDeviceCryptAuthAccessTokenFetcherImplTest,
+ TestDeletedBeforeOperationFinished) {
+ StartFetchingAccessToken();
+ EXPECT_EQ(nullptr, GetTokenAndReset());
+
+ // Deleting the object should result in the callback being invoked with an
+ // empty string (indicating failure).
+ token_fetcher_.reset();
+ EXPECT_EQ(std::string(), *GetTokenAndReset());
+}
+
+} // namespace multidevice
diff --git a/chromium/components/multidevice/service/multidevice_service.cc b/chromium/components/multidevice/service/multidevice_service.cc
index 32c94330cba..7ce56cb39b0 100644
--- a/chromium/components/multidevice/service/multidevice_service.cc
+++ b/chromium/components/multidevice/service/multidevice_service.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
+
#include "components/multidevice/service/multidevice_service.h"
#include "components/multidevice/service/device_sync_impl.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -14,9 +16,8 @@ MultiDeviceService::MultiDeviceService() : weak_ptr_factory_(this) {}
MultiDeviceService::~MultiDeviceService() {}
void MultiDeviceService::OnStart() {
- ref_factory_ = base::MakeUnique<service_manager::ServiceContextRefFactory>(
- base::Bind(&service_manager::ServiceContext::RequestQuit,
- base::Unretained(context())));
+ ref_factory_ = std::make_unique<service_manager::ServiceContextRefFactory>(
+ context()->CreateQuitClosure());
registry_.AddInterface<device_sync::mojom::DeviceSync>(
base::Bind(&MultiDeviceService::CreateDeviceSyncImpl,
base::Unretained(this), ref_factory_.get()));
@@ -37,4 +38,4 @@ void MultiDeviceService::CreateDeviceSyncImpl(
std::move(request));
}
-} // namespace multidevice \ No newline at end of file
+} // namespace multidevice
diff --git a/chromium/components/multidevice/service/multidevice_service_unittest.cc b/chromium/components/multidevice/service/multidevice_service_unittest.cc
index 489ae4ca651..fa40e664589 100644
--- a/chromium/components/multidevice/service/multidevice_service_unittest.cc
+++ b/chromium/components/multidevice/service/multidevice_service_unittest.cc
@@ -101,7 +101,7 @@ class MultiDeviceServiceTest : public service_manager::test::ServiceTest {
device_sync::mojom::DeviceSyncObserverPtr device_sync_observer_ptr;
for (int i = 0; i < num; i++) {
device_sync_observer_ptr = device_sync::mojom::DeviceSyncObserverPtr();
- observers_.emplace_back(base::MakeUnique<DeviceSyncObserverImpl>(
+ observers_.emplace_back(std::make_unique<DeviceSyncObserverImpl>(
mojo::MakeRequest(&device_sync_observer_ptr)));
device_sync_ptr_->AddObserver(std::move(device_sync_observer_ptr));
}
diff --git a/chromium/components/multidevice/service/test_main.cc b/chromium/components/multidevice/service/test_main.cc
index 00b05a3bc91..ec532d20683 100644
--- a/chromium/components/multidevice/service/test_main.cc
+++ b/chromium/components/multidevice/service/test_main.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
+
#include "components/multidevice/service/device_sync_impl.h"
#include "components/multidevice/service/fake_device_sync.h"
#include "components/multidevice/service/multidevice_service.h"
@@ -19,7 +21,7 @@ class FakeDeviceSyncFactory : public multidevice::DeviceSyncImpl::Factory {
std::unique_ptr<device_sync::mojom::DeviceSync> BuildInstance(
std::unique_ptr<service_manager::ServiceContextRef> service_ref)
override {
- return base::MakeUnique<multidevice::FakeDeviceSync>();
+ return std::make_unique<multidevice::FakeDeviceSync>();
}
};
diff --git a/chromium/components/nacl/browser/BUILD.gn b/chromium/components/nacl/browser/BUILD.gn
index 512b1f8c813..5a1b5411fe7 100644
--- a/chromium/components/nacl/browser/BUILD.gn
+++ b/chromium/components/nacl/browser/BUILD.gn
@@ -34,8 +34,8 @@ static_library("browser") {
"//base",
"//base/third_party/dynamic_annotations",
"//components/nacl/common",
+ "//components/nacl/common:buildflags",
"//components/nacl/common:debug_exception_handler",
- "//components/nacl/common:features",
"//components/url_formatter",
"//content/public/browser",
"//content/public/common",
@@ -50,7 +50,7 @@ static_library("browser") {
public_deps = [
"//ipc",
- "//services/service_manager/public/interfaces",
+ "//services/service_manager/public/mojom",
]
data_deps = []
diff --git a/chromium/components/nacl/common/BUILD.gn b/chromium/components/nacl/common/BUILD.gn
index cf0cfca9d77..39c38292e0a 100644
--- a/chromium/components/nacl/common/BUILD.gn
+++ b/chromium/components/nacl/common/BUILD.gn
@@ -137,7 +137,7 @@ static_library("switches") {
]
}
-buildflag_header("features") {
- header = "features.h"
+buildflag_header("buildflags") {
+ header = "buildflags.h"
flags = [ "ENABLE_NACL=$enable_nacl" ]
}
diff --git a/chromium/components/nacl/loader/BUILD.gn b/chromium/components/nacl/loader/BUILD.gn
index b88d738084a..4ebb4e901bc 100644
--- a/chromium/components/nacl/loader/BUILD.gn
+++ b/chromium/components/nacl/loader/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("//build/config/compiler/compiler.gni")
import("//build/config/nacl/config.gni")
import("//components/nacl/features.gni")
import("//services/service_manager/public/service_manifest.gni")
@@ -139,6 +140,18 @@ if (is_linux) {
# NaCl is not working with compiler-rt in ChromeOS.
# Force libgcc as a workaround. See https://crbug.com/761103
ldflags += [ "-rtlib=libgcc" ]
+
+ # Nacl crashes when enabling ThinLTO. See https://crbug.com/799642
+ # We haven't triaged down to the root cause yet. For now, disabling
+ # dead function removal from LTO optimization is a workaround, so that
+ # we can enable ThinLTO and CFI.
+ if (use_thin_lto) {
+ if (use_lld) {
+ ldflags += [ "-Wl,-mllvm,-compute-dead=false" ]
+ } else {
+ ldflags += [ "-Wl,-plugin-opt,-compute-dead=false" ]
+ }
+ }
}
data_deps = [
diff --git a/chromium/components/navigation_interception/intercept_navigation_delegate.cc b/chromium/components/navigation_interception/intercept_navigation_delegate.cc
index b6a3b119c7f..d58f484a42b 100644
--- a/chromium/components/navigation_interception/intercept_navigation_delegate.cc
+++ b/chromium/components/navigation_interception/intercept_navigation_delegate.cc
@@ -4,10 +4,11 @@
#include "components/navigation_interception/intercept_navigation_delegate.h"
+#include <memory>
+
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/callback.h"
-#include "base/memory/ptr_util.h"
#include "components/navigation_interception/intercept_navigation_throttle.h"
#include "components/navigation_interception/navigation_params_android.h"
#include "content/public/browser/browser_thread.h"
@@ -88,7 +89,7 @@ InterceptNavigationDelegate* InterceptNavigationDelegate::Get(
std::unique_ptr<content::NavigationThrottle>
InterceptNavigationDelegate::CreateThrottleFor(
content::NavigationHandle* handle) {
- return base::MakeUnique<InterceptNavigationThrottle>(
+ return std::make_unique<InterceptNavigationThrottle>(
handle, base::Bind(&CheckIfShouldIgnoreNavigationOnUIThread));
}
diff --git a/chromium/components/net_log/OWNERS b/chromium/components/net_log/OWNERS
index cadff51d223..b3a1999dc34 100644
--- a/chromium/components/net_log/OWNERS
+++ b/chromium/components/net_log/OWNERS
@@ -1,12 +1,3 @@
-agl@chromium.org
-battre@chromium.org
-cbentzel@chromium.org
-eroman@chromium.org
-mattm@chromium.org
-mef@chromium.org
-mmenke@chromium.org
-rdsmith@chromium.org
-rsleevi@chromium.org
-rtenneti@chromium.org
+file://net/log/OWNERS
# COMPONENT: Internals>Network>Logging
diff --git a/chromium/components/net_log/chrome_net_log.cc b/chromium/components/net_log/chrome_net_log.cc
index 8c84541335b..a799eeed9c3 100644
--- a/chromium/components/net_log/chrome_net_log.cc
+++ b/chromium/components/net_log/chrome_net_log.cc
@@ -4,6 +4,7 @@
#include "components/net_log/chrome_net_log.h"
+#include <memory>
#include <utility>
#include "base/command_line.h"
@@ -62,7 +63,7 @@ std::unique_ptr<base::Value> ChromeNetLog::GetConstants(
// Add a dictionary with the version of the client and its command line
// arguments.
- auto dict = base::MakeUnique<base::DictionaryValue>();
+ auto dict = std::make_unique<base::DictionaryValue>();
// We have everything we need to send the right values.
dict->SetString("name", version_info::GetProductName());
diff --git a/chromium/components/net_log/net_export_file_writer.cc b/chromium/components/net_log/net_export_file_writer.cc
index e18df1cb2bc..c30d2d70476 100644
--- a/chromium/components/net_log/net_export_file_writer.cc
+++ b/chromium/components/net_log/net_export_file_writer.cc
@@ -4,6 +4,7 @@
#include "components/net_log/net_export_file_writer.h"
+#include <memory>
#include <set>
#include <utility>
@@ -12,7 +13,6 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
-#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
#include "base/task_scheduler/post_task.h"
@@ -229,9 +229,9 @@ void NetExportFileWriter::StopNetLog(
if (context_getter) {
base::PostTaskAndReplyWithResult(
net_task_runner_.get(), FROM_HERE,
- base::Bind(&AddNetInfo, context_getter, base::Passed(&polled_data)),
- base::Bind(&NetExportFileWriter::StopNetLogAfterAddNetInfo,
- weak_ptr_factory_.GetWeakPtr()));
+ base::BindOnce(&AddNetInfo, context_getter, std::move(polled_data)),
+ base::BindOnce(&NetExportFileWriter::StopNetLogAfterAddNetInfo,
+ weak_ptr_factory_.GetWeakPtr()));
} else {
StopNetLogAfterAddNetInfo(std::move(polled_data));
}
@@ -240,7 +240,7 @@ void NetExportFileWriter::StopNetLog(
std::unique_ptr<base::DictionaryValue> NetExportFileWriter::GetState() const {
DCHECK(thread_checker_.CalledOnValidThread());
- auto dict = base::MakeUnique<base::DictionaryValue>();
+ auto dict = std::make_unique<base::DictionaryValue>();
dict->SetString("file", log_path_.LossyDisplayName());
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 8817123e708..ebc5cf54b27 100644
--- a/chromium/components/net_log/net_export_file_writer_unittest.cc
+++ b/chromium/components/net_log/net_export_file_writer_unittest.cc
@@ -167,7 +167,7 @@ void SetUpTestContextGetterWithQuicTimeoutInfo(
int quic_idle_connection_timeout_seconds,
scoped_refptr<net::TestURLRequestContextGetter>* context_getter) {
std::unique_ptr<net::TestURLRequestContext> context =
- base::MakeUnique<net::TestURLRequestContext>(true);
+ std::make_unique<net::TestURLRequestContext>(true);
context->set_net_log(net_log);
std::unique_ptr<net::HttpNetworkSession::Params> params(
@@ -188,7 +188,7 @@ void SetUpTestContextGetterWithRequest(
net::URLRequest::Delegate* delegate,
scoped_refptr<net::TestURLRequestContextGetter>* context_getter,
std::unique_ptr<net::URLRequest>* request) {
- auto context = base::MakeUnique<net::TestURLRequestContext>(true);
+ auto context = std::make_unique<net::TestURLRequestContext>(true);
context->set_net_log(net_log);
context->Init();
@@ -654,7 +654,7 @@ TEST_F(NetExportFileWriterTest, StopWithPolledDataAndContextGetter) {
const char kDummyPolledDataPath[] = "dummy_path";
const char kDummyPolledDataString[] = "dummy_info";
std::unique_ptr<base::DictionaryValue> dummy_polled_data =
- base::MakeUnique<base::DictionaryValue>();
+ std::make_unique<base::DictionaryValue>();
dummy_polled_data->SetString(kDummyPolledDataPath, kDummyPolledDataString);
// Create test context getter on |net_thread_| and wait for it to finish.
diff --git a/chromium/components/neterror/resources/offline.js b/chromium/components/neterror/resources/offline.js
index 157365e164e..c4cf84dec29 100644
--- a/chromium/components/neterror/resources/offline.js
+++ b/chromium/components/neterror/resources/offline.js
@@ -94,9 +94,6 @@ var IS_IOS = /iPad|iPhone|iPod/.test(window.navigator.platform);
var IS_MOBILE = /Android/.test(window.navigator.userAgent) || IS_IOS;
/** @const */
-var IS_TOUCH_ENABLED = 'ontouchstart' in window;
-
-/** @const */
var ARCADE_MODE_URL = 'chrome://dino/';
/**
@@ -220,8 +217,8 @@ Runner.events = {
CLICK: 'click',
KEYDOWN: 'keydown',
KEYUP: 'keyup',
- MOUSEDOWN: 'mousedown',
- MOUSEUP: 'mouseup',
+ POINTERDOWN: 'pointerdown',
+ POINTERUP: 'pointerup',
RESIZE: 'resize',
TOUCHEND: 'touchend',
TOUCHSTART: 'touchstart',
@@ -382,10 +379,6 @@ Runner.prototype = {
this.outerContainerEl.appendChild(this.containerEl);
- if (IS_MOBILE) {
- this.createTouchController();
- }
-
this.startListening();
this.update();
@@ -399,6 +392,8 @@ Runner.prototype = {
createTouchController: function() {
this.touchController = document.createElement('div');
this.touchController.className = Runner.classes.TOUCH_CONTROLLER;
+ this.touchController.addEventListener(Runner.events.TOUCHSTART, this);
+ this.touchController.addEventListener(Runner.events.TOUCHEND, this);
},
/**
@@ -615,12 +610,12 @@ Runner.prototype = {
switch (evtType) {
case events.KEYDOWN:
case events.TOUCHSTART:
- case events.MOUSEDOWN:
+ case events.POINTERDOWN:
this.onKeyDown(e);
break;
case events.KEYUP:
case events.TOUCHEND:
- case events.MOUSEUP:
+ case events.POINTERUP:
this.onKeyUp(e);
break;
}
@@ -635,16 +630,10 @@ Runner.prototype = {
document.addEventListener(Runner.events.KEYDOWN, this);
document.addEventListener(Runner.events.KEYUP, this);
- if (IS_MOBILE) {
- // Mobile only touch devices.
- this.touchController.addEventListener(Runner.events.TOUCHSTART, this);
- this.touchController.addEventListener(Runner.events.TOUCHEND, this);
- this.containerEl.addEventListener(Runner.events.TOUCHSTART, this);
- } else {
- // Mouse.
- document.addEventListener(Runner.events.MOUSEDOWN, this);
- document.addEventListener(Runner.events.MOUSEUP, this);
- }
+ // Touch / pointer.
+ this.containerEl.addEventListener(Runner.events.TOUCHSTART, this);
+ document.addEventListener(Runner.events.POINTERDOWN, this);
+ document.addEventListener(Runner.events.POINTERUP, this);
},
/**
@@ -654,14 +643,14 @@ Runner.prototype = {
document.removeEventListener(Runner.events.KEYDOWN, this);
document.removeEventListener(Runner.events.KEYUP, this);
- if (IS_MOBILE) {
+ if (this.touchController) {
this.touchController.removeEventListener(Runner.events.TOUCHSTART, this);
this.touchController.removeEventListener(Runner.events.TOUCHEND, this);
- this.containerEl.removeEventListener(Runner.events.TOUCHSTART, this);
- } else {
- document.removeEventListener(Runner.events.MOUSEDOWN, this);
- document.removeEventListener(Runner.events.MOUSEUP, this);
}
+
+ this.containerEl.removeEventListener(Runner.events.TOUCHSTART, this);
+ document.removeEventListener(Runner.events.POINTERDOWN, this);
+ document.removeEventListener(Runner.events.POINTERUP, this);
},
/**
@@ -680,6 +669,10 @@ Runner.prototype = {
e.preventDefault();
// Starting the game for the first time.
if (!this.playing) {
+ // Started by touch so create a touch controller.
+ if (!this.touchController && e.type == Runner.events.TOUCHSTART) {
+ this.createTouchController();
+ }
this.loadSounds();
this.playing = true;
this.update();
@@ -717,7 +710,7 @@ Runner.prototype = {
var keyCode = String(e.keyCode);
var isjumpKey = Runner.keycodes.JUMP[keyCode] ||
e.type == Runner.events.TOUCHEND ||
- e.type == Runner.events.MOUSEDOWN;
+ e.type == Runner.events.POINTERUP;
if (this.isRunning() && isjumpKey) {
this.tRex.endJump();
@@ -748,7 +741,7 @@ Runner.prototype = {
*/
isLeftClickOnCanvas: function(e) {
return e.button != null && e.button < 2 &&
- e.type == Runner.events.MOUSEUP && e.target == this.canvas;
+ e.type == Runner.events.POINTERUP && e.target == this.canvas;
},
/**
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 4b43a46560b..50e80637dab 100644
--- a/chromium/components/network_session_configurator/browser/network_session_configurator.cc
+++ b/chromium/components/network_session_configurator/browser/network_session_configurator.cc
@@ -6,6 +6,8 @@
#include <map>
#include <unordered_set>
+#include <utility>
+#include <vector>
#include "base/command_line.h"
#include "base/feature_list.h"
@@ -98,13 +100,25 @@ net::SettingsMap GetHttp2Settings(
uint32_t value;
if (!base::StringToUint(key_value.second, &value))
continue;
- http2_settings[static_cast<net::SpdySettingsIds>(key)] = value;
+ http2_settings[static_cast<net::SpdyKnownSettingsId>(key)] = value;
}
return http2_settings;
}
-void ConfigureHttp2Params(base::StringPiece http2_trial_group,
+bool ConfigureWebsocketOverHttp2(
+ const base::CommandLine& command_line,
+ const VariationParameters& http2_trial_params) {
+ if (command_line.HasSwitch(switches::kEnableWebsocketOverHttp2))
+ return true;
+
+ const std::string websocket_value =
+ GetVariationParam(http2_trial_params, "websocket_over_http2");
+ return websocket_value == "true";
+}
+
+void ConfigureHttp2Params(const base::CommandLine& command_line,
+ base::StringPiece http2_trial_group,
const VariationParameters& http2_trial_params,
net::HttpNetworkSession::Params* params) {
if (http2_trial_group.starts_with(kHttp2FieldTrialDisablePrefix)) {
@@ -112,6 +126,8 @@ void ConfigureHttp2Params(base::StringPiece http2_trial_group,
return;
}
params->http2_settings = GetHttp2Settings(http2_trial_params);
+ params->enable_websocket_over_http2 =
+ ConfigureWebsocketOverHttp2(command_line, http2_trial_params);
}
bool ShouldEnableQuic(base::StringPiece quic_trial_group,
@@ -493,7 +509,8 @@ void ParseCommandLineAndFieldTrials(const base::CommandLine& command_line,
if (!variations::GetVariationParams(kHttp2FieldTrialName,
&http2_trial_params))
http2_trial_params.clear();
- ConfigureHttp2Params(http2_trial_group, http2_trial_params, params);
+ ConfigureHttp2Params(command_line, http2_trial_group, http2_trial_params,
+ params);
const std::string tfo_trial_group =
base::FieldTrialList::FindFullName(kTCPFastOpenFieldTrialName);
diff --git a/chromium/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/chromium/components/network_session_configurator/browser/network_session_configurator_unittest.cc
index b8d7dc778f6..8b10309ce49 100644
--- a/chromium/components/network_session_configurator/browser/network_session_configurator_unittest.cc
+++ b/chromium/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -9,7 +9,6 @@
#include <string>
#include "base/command_line.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
#include "base/test/mock_entropy_provider.h"
#include "base/test/scoped_feature_list.h"
@@ -33,7 +32,7 @@ class NetworkSessionConfiguratorTest : public testing::Test {
NetworkSessionConfiguratorTest()
: quic_user_agent_id_("Chrome/52.0.2709.0 Linux x86_64") {
field_trial_list_.reset(new base::FieldTrialList(
- base::MakeUnique<base::MockEntropyProvider>()));
+ std::make_unique<base::MockEntropyProvider>()));
variations::testing::ClearAllVariationParams();
}
@@ -65,6 +64,7 @@ TEST_F(NetworkSessionConfiguratorTest, Defaults) {
EXPECT_TRUE(params_.enable_http2);
EXPECT_TRUE(params_.http2_settings.empty());
+ EXPECT_FALSE(params_.enable_websocket_over_http2);
EXPECT_FALSE(params_.enable_quic);
EXPECT_EQ("Chrome/52.0.2709.0 Linux x86_64", params_.quic_user_agent_id);
@@ -527,8 +527,8 @@ TEST_F(NetworkSessionConfiguratorTest, Http2SettingsFromFieldTrialParams) {
ParseFieldTrials();
net::SettingsMap expected_settings;
- expected_settings[static_cast<net::SpdySettingsIds>(7)] = 1234;
- expected_settings[static_cast<net::SpdySettingsIds>(25)] = 5678;
+ expected_settings[static_cast<net::SpdyKnownSettingsId>(7)] = 1234;
+ expected_settings[static_cast<net::SpdyKnownSettingsId>(25)] = 5678;
EXPECT_EQ(expected_settings, params_.http2_settings);
}
@@ -774,4 +774,26 @@ TEST_F(NetworkSessionConfiguratorTest, QuicHeadersIncludeH2StreamDependency) {
EXPECT_TRUE(params_.quic_headers_include_h2_stream_dependency);
}
+TEST_F(NetworkSessionConfiguratorTest,
+ WebsocketOverHttp2EnabledFromCommandLine) {
+ base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
+ command_line.AppendSwitch(switches::kEnableWebsocketOverHttp2);
+
+ ParseCommandLineAndFieldTrials(command_line);
+
+ EXPECT_TRUE(params_.enable_websocket_over_http2);
+}
+
+TEST_F(NetworkSessionConfiguratorTest,
+ WebsocketOverHttp2EnabledFromFieldTrial) {
+ std::map<std::string, std::string> field_trial_params;
+ field_trial_params["websocket_over_http2"] = "true";
+ variations::AssociateVariationParams("HTTP2", "Enabled", field_trial_params);
+ base::FieldTrialList::CreateFieldTrial("HTTP2", "Enabled");
+
+ ParseFieldTrials();
+
+ EXPECT_TRUE(params_.enable_websocket_over_http2);
+}
+
} // namespace network_session_configurator
diff --git a/chromium/components/network_session_configurator/common/network_features.cc b/chromium/components/network_session_configurator/common/network_features.cc
index abf8b98abde..87dbb7d9456 100644
--- a/chromium/components/network_session_configurator/common/network_features.cc
+++ b/chromium/components/network_session_configurator/common/network_features.cc
@@ -9,4 +9,7 @@ namespace features {
const base::Feature kTokenBinding{"token-binding",
base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kDnsOverHttps{"dns-over-https",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace features
diff --git a/chromium/components/network_session_configurator/common/network_features.h b/chromium/components/network_session_configurator/common/network_features.h
index dbcc98ce712..6d92c7ac673 100644
--- a/chromium/components/network_session_configurator/common/network_features.h
+++ b/chromium/components/network_session_configurator/common/network_features.h
@@ -14,6 +14,10 @@ namespace features {
// (https://www.ietf.org/id/draft-ietf-tokbind-protocol-04.txt).
NETWORK_SESSION_CONFIGURATOR_EXPORT extern const base::Feature kTokenBinding;
+// Enabled DNS over HTTPS
+// (https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-02.txt).
+NETWORK_SESSION_CONFIGURATOR_EXPORT extern const base::Feature kDnsOverHttps;
+
} // namespace features
#endif // COMPONENTS_NETWORK_SESSION_CONFIGURATOR_COMMON_NETWORK_FEATURES_H_
diff --git a/chromium/components/network_session_configurator/common/network_switch_list.h b/chromium/components/network_session_configurator/common/network_switch_list.h
index 723e78db93d..ff5ea22383d 100644
--- a/chromium/components/network_session_configurator/common/network_switch_list.h
+++ b/chromium/components/network_session_configurator/common/network_switch_list.h
@@ -11,6 +11,9 @@ NETWORK_SWITCH(kDisableQuic, "disable-quic")
// Disables the HTTP/2 protocol.
NETWORK_SWITCH(kDisableHttp2, "disable-http2")
+// Enable Websocket over HTTP/2.
+NETWORK_SWITCH(kEnableWebsocketOverHttp2, "enable-websocket-over-http2")
+
// Enables Alternate-Protocol when the port is user controlled (> 1024).
NETWORK_SWITCH(kEnableUserAlternateProtocolPorts,
"enable-user-controlled-alternate-protocol-ports")
diff --git a/chromium/components/network_time/network_time_test_utils.cc b/chromium/components/network_time/network_time_test_utils.cc
index 98182723647..05ade0b2903 100644
--- a/chromium/components/network_time/network_time_test_utils.cc
+++ b/chromium/components/network_time/network_time_test_utils.cc
@@ -4,8 +4,9 @@
#include "components/network_time/network_time_test_utils.h"
+#include <memory>
+
#include "base/feature_list.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/mock_entropy_provider.h"
@@ -104,7 +105,7 @@ void FieldTrialTest::SetNetworkQueriesWithVariationsService(
// one. (See https://crbug.com/684216#c5 for more discussion.)
field_trial_list_.reset();
field_trial_list_.reset(
- new base::FieldTrialList(base::MakeUnique<base::MockEntropyProvider>()));
+ new base::FieldTrialList(std::make_unique<base::MockEntropyProvider>()));
// refcounted, and reference held by the singleton FieldTrialList.
base::FieldTrial* trial = base::FieldTrialList::FactoryGetFieldTrial(
diff --git a/chromium/components/network_time/network_time_tracker.cc b/chromium/components/network_time/network_time_tracker.cc
index 19697a3321b..ac6638770f6 100644
--- a/chromium/components/network_time/network_time_tracker.cc
+++ b/chromium/components/network_time/network_time_tracker.cc
@@ -4,6 +4,7 @@
#include "components/network_time/network_time_tracker.h"
+#include <memory>
#include <stdint.h>
#include <string>
#include <utility>
@@ -11,7 +12,6 @@
#include "base/i18n/time_formatting.h"
#include "base/json/json_reader.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/rand_util.h"
@@ -197,7 +197,7 @@ void RecordFetchValidHistogram(bool valid) {
// static
void NetworkTimeTracker::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(prefs::kNetworkTimeMapping,
- base::MakeUnique<base::DictionaryValue>());
+ std::make_unique<base::DictionaryValue>());
registry->RegisterBooleanPref(prefs::kNetworkTimeQueriesEnabled, true);
}
diff --git a/chromium/components/ntp_snippets/BUILD.gn b/chromium/components/ntp_snippets/BUILD.gn
index 6129de984c8..eb88be97120 100644
--- a/chromium/components/ntp_snippets/BUILD.gn
+++ b/chromium/components/ntp_snippets/BUILD.gn
@@ -128,10 +128,8 @@ static_library("ntp_snippets") {
"//components/leveldb_proto",
"//components/prefs",
"//components/resources",
- "//components/signin/core/browser",
"//components/sync",
"//components/version_info",
- "//google_apis",
"//net",
"//ui/base",
"//url",
@@ -237,11 +235,10 @@ source_set("unit_tests") {
"//components/offline_pages/core/downloads:offline_pages_ui_adapter",
"//components/offline_pages/core/recent_tabs",
"//components/physical_web/data_source:test_support",
+ "//components/prefs:test_support",
"//components/reading_list/core",
"//components/sessions",
"//components/sessions:test_support",
- "//components/signin/core/browser",
- "//components/signin/core/browser:test_support",
"//components/strings",
"//components/sync:test_support_driver",
"//components/sync_preferences:test_support",
@@ -251,6 +248,7 @@ source_set("unit_tests") {
"//google_apis/gcm",
"//net:test_support",
"//services/identity/public/cpp",
+ "//services/identity/public/cpp:test_support",
"//testing/gtest",
"//third_party/icu/",
"//ui/gfx:test_support",
diff --git a/chromium/components/ntp_snippets/OWNERS b/chromium/components/ntp_snippets/OWNERS
index 7d3309a4b5b..3ac3779dd87 100644
--- a/chromium/components/ntp_snippets/OWNERS
+++ b/chromium/components/ntp_snippets/OWNERS
@@ -1,6 +1,7 @@
bauerb@chromium.org
jkrcal@chromium.org
treib@chromium.org
+tschumann@chromium.org
# Unsure who to ask? Choose from the above.
markusheintz@chromium.org
diff --git a/chromium/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc b/chromium/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc
index c339057e57b..b262a3ff873 100644
--- a/chromium/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc
+++ b/chromium/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <string>
+#include "base/bind_helpers.h"
#include "base/json/json_reader.h"
#include "base/message_loop/message_loop.h"
#include "base/test/histogram_tester.h"
@@ -339,9 +340,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
.WillOnce(
InvokeCallbackArgument<3>("token", InstanceID::Result::SUCCESS));
EXPECT_CALL(*mock_instance_id(), ValidateToken(_, _, _, _)).Times(0);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
task_runner->RunUntilIdle();
}
@@ -367,9 +366,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
// Check that handler does not validate the token yet.
EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _)).Times(0);
EXPECT_CALL(*mock_instance_id(), ValidateToken(_, _, _, _)).Times(0);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
task_runner->FastForwardBy(time_to_validation -
base::TimeDelta::FromSeconds(1));
@@ -424,9 +421,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _)).Times(0);
EXPECT_CALL(*mock_instance_id(), ValidateToken(_, _, _, _)).Times(0);
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
handler->StopListening();
task_runner->FastForwardBy(10 * GetTokenValidationPeriod());
}
@@ -451,9 +446,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _))
.WillOnce(
InvokeCallbackArgument<3>("token", InstanceID::Result::SUCCESS));
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
// Check that the validation schedule has changed. "Old validation" should not
// happen because the token was retrieved recently.
@@ -486,9 +479,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
scoped_refptr<TestMockTimeTaskRunner> task_runner(
new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
// Handler validates the token.
EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _))
@@ -525,9 +516,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
scoped_refptr<TestMockTimeTaskRunner> task_runner(
new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
// Check that handler resubscribes with the new token after a validation, if
// old is invalid.
@@ -557,9 +546,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
scoped_refptr<TestMockTimeTaskRunner> task_runner(
new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
// Check that provider does not resubscribe if the old token is still valid
// after validation.
@@ -598,7 +585,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
handler->StartListening(
base::BindRepeating(
[](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::BindRepeating([]() {}));
+ base::DoNothing());
// The client stops listening for the push updates.
handler->StopListening();
@@ -638,7 +625,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
handler->StartListening(
base::BindRepeating(
[](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::BindRepeating([]() {}));
+ base::DoNothing());
task_runner->FastForwardBy(time_to_validation -
base::TimeDelta::FromSeconds(1));
@@ -692,9 +679,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _))
.WillRepeatedly(
InvokeCallbackArgument<3>("token", InstanceID::Result::SUCCESS));
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
EXPECT_TRUE(handler->IsListening());
}
@@ -712,9 +697,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _))
.WillRepeatedly(
InvokeCallbackArgument<3>("token", InstanceID::Result::SUCCESS));
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
ASSERT_TRUE(handler->IsListening());
handler->StopListening();
@@ -735,17 +718,13 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _))
.WillRepeatedly(
InvokeCallbackArgument<3>("token", InstanceID::Result::SUCCESS));
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
ASSERT_TRUE(handler->IsListening());
handler->StopListening();
ASSERT_FALSE(handler->IsListening());
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
EXPECT_TRUE(handler->IsListening());
}
@@ -766,9 +745,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest, ShouldForceSubscribeImmediatelyIfDue) {
new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
EXPECT_CALL(*mock_subscription_manager(), Subscribe("token"));
task_runner->RunUntilIdle();
}
@@ -792,9 +769,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
// Check that handler does not force subscribe yet.
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
// TODO(vitaliii): Consider making FakeSubscriptionManager, because
// IsSubscribed() affects forced subscriptions. Currently we have to carefully
// avoid the initial subscription.
@@ -850,9 +825,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
// Check that handler does not force subscribe after StopListening even
// though a forced subscription is due.
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
handler->StopListening();
EXPECT_CALL(*mock_subscription_manager(), Subscribe("token")).Times(0);
task_runner->FastForwardBy(10 * GetForcedSubscriptionPeriod());
@@ -876,9 +849,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
scoped_refptr<TestMockTimeTaskRunner> task_runner(
new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
// Handler force subscribes.
EXPECT_CALL(*mock_subscription_manager(), Subscribe("token"));
@@ -919,9 +890,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
scoped_refptr<TestMockTimeTaskRunner> task_runner(
new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
// Check that the next validation is scheduled in time.
EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _)).Times(0);
@@ -954,9 +923,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest, ShouldReportMissingAction) {
scoped_refptr<TestMockTimeTaskRunner> task_runner(
new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
handler->OnMessage("com.google.breakingnews.gcm", gcm::IncomingMessage());
@@ -979,9 +946,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest, ShouldReportInvalidAction) {
scoped_refptr<TestMockTimeTaskRunner> task_runner(
new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
gcm::IncomingMessage message;
message.data[kPushedActionKey] = "invalid_action";
@@ -1008,9 +973,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest, ShouldReportPushToRefreshAction) {
scoped_refptr<TestMockTimeTaskRunner> task_runner(
new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
gcm::IncomingMessage message;
message.data[kPushedActionKey] = "push-to-refresh";
@@ -1037,9 +1000,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest, ShouldReportPushByValueAction) {
scoped_refptr<TestMockTimeTaskRunner> task_runner(
new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
gcm::IncomingMessage message;
message.data[kPushedActionKey] = "push-by-value";
@@ -1087,7 +1048,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
MockOnNewRemoteSuggestionCallback mock_on_new_remote_suggestion_callback;
handler->StartListening(mock_on_new_remote_suggestion_callback.Get(),
- base::Bind([]() {}));
+ base::DoNothing());
gcm::IncomingMessage message;
message.data[kPushedActionKey] = "push-by-value";
@@ -1113,9 +1074,8 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
base::MockCallback<BreakingNewsListener::OnRefreshRequestedCallback>
on_refresh_requested_callback;
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- on_refresh_requested_callback.Get());
+ handler->StartListening(base::DoNothing(),
+ on_refresh_requested_callback.Get());
gcm::IncomingMessage message;
message.data[kPushedActionKey] = "push-to-refresh";
@@ -1136,9 +1096,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest, ShouldReportTokenRetrievalResult) {
EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _))
.WillOnce(InvokeCallbackArgument<3>(/*token=*/"",
InstanceID::Result::NETWORK_ERROR));
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
EXPECT_THAT(
histogram_tester.GetAllSamples(
@@ -1167,9 +1125,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
scoped_refptr<TestMockTimeTaskRunner> task_runner(
new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
// Check that handler does not report the metric before the validation.
task_runner->FastForwardBy(time_to_validation -
@@ -1214,9 +1170,7 @@ TEST_F(BreakingNewsGCMAppHandlerTest,
scoped_refptr<TestMockTimeTaskRunner> task_runner(
new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
std::unique_ptr<BreakingNewsGCMAppHandler> handler = MakeHandler(task_runner);
- handler->StartListening(
- base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}),
- base::Bind([]() {}));
+ handler->StartListening(base::DoNothing(), base::DoNothing());
// Check that handler does not report the metric before the validation.
task_runner->FastForwardBy(time_to_validation -
diff --git a/chromium/components/ntp_snippets/breaking_news/subscription_json_request.h b/chromium/components/ntp_snippets/breaking_news/subscription_json_request.h
index e6583309e83..c82162b7880 100644
--- a/chromium/components/ntp_snippets/breaking_news/subscription_json_request.h
+++ b/chromium/components/ntp_snippets/breaking_news/subscription_json_request.h
@@ -14,8 +14,10 @@
#include "base/optional.h"
#include "base/time/time.h"
#include "components/ntp_snippets/status.h"
-#include "google_apis/gaia/oauth2_token_service.h"
#include "net/http/http_request_headers.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "url/gurl.h"
namespace ntp_snippets {
diff --git a/chromium/components/ntp_snippets/breaking_news/subscription_manager_impl.cc b/chromium/components/ntp_snippets/breaking_news/subscription_manager_impl.cc
index 49a84fad3c5..9770ca51ec0 100644
--- a/chromium/components/ntp_snippets/breaking_news/subscription_manager_impl.cc
+++ b/chromium/components/ntp_snippets/breaking_news/subscription_manager_impl.cc
@@ -14,7 +14,6 @@
#include "components/ntp_snippets/pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/signin_manager_base.h"
#include "components/variations/service/variations_service.h"
#include "net/base/url_util.h"
#include "services/identity/public/cpp/primary_account_access_token_fetcher.h"
@@ -30,40 +29,11 @@ const char kAuthorizationRequestHeaderFormat[] = "Bearer %s";
} // namespace
-class SubscriptionManagerImpl::SigninObserver
- : public SigninManagerBase::Observer {
- public:
- SigninObserver(SigninManagerBase* signin_manager,
- const base::Closure& signin_status_changed_callback)
- : signin_manager_(signin_manager),
- signin_status_changed_callback_(signin_status_changed_callback) {
- signin_manager_->AddObserver(this);
- }
-
- ~SigninObserver() override { signin_manager_->RemoveObserver(this); }
-
- private:
- // SigninManagerBase::Observer implementation.
- void GoogleSigninSucceeded(const std::string& account_id,
- const std::string& username) override {
- signin_status_changed_callback_.Run();
- }
-
- void GoogleSignedOut(const std::string& account_id,
- const std::string& username) override {
- signin_status_changed_callback_.Run();
- }
-
- SigninManagerBase* const signin_manager_;
- base::Closure signin_status_changed_callback_;
-};
-
SubscriptionManagerImpl::SubscriptionManagerImpl(
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
PrefService* pref_service,
variations::VariationsService* variations_service,
- SigninManagerBase* signin_manager,
- OAuth2TokenService* access_token_service,
+ identity::IdentityManager* identity_manager,
const std::string& locale,
const std::string& api_key,
const GURL& subscribe_url,
@@ -71,25 +41,24 @@ SubscriptionManagerImpl::SubscriptionManagerImpl(
: url_request_context_getter_(std::move(url_request_context_getter)),
pref_service_(pref_service),
variations_service_(variations_service),
- signin_manager_(signin_manager),
- signin_observer_(std::make_unique<SigninObserver>(
- signin_manager,
- base::Bind(&SubscriptionManagerImpl::SigninStatusChanged,
- base::Unretained(this)))),
- access_token_service_(access_token_service),
+ identity_manager_(identity_manager),
locale_(locale),
api_key_(api_key),
subscribe_url_(subscribe_url),
- unsubscribe_url_(unsubscribe_url) {}
+ unsubscribe_url_(unsubscribe_url) {
+ identity_manager_->AddObserver(this);
+}
-SubscriptionManagerImpl::~SubscriptionManagerImpl() = default;
+SubscriptionManagerImpl::~SubscriptionManagerImpl() {
+ identity_manager_->RemoveObserver(this);
+}
void SubscriptionManagerImpl::Subscribe(const std::string& subscription_token) {
// If there is a request in flight, cancel it.
if (request_) {
request_ = nullptr;
}
- if (signin_manager_->IsAuthenticated()) {
+ if (identity_manager_->HasPrimaryAccount()) {
StartAccessTokenRequest(subscription_token);
} else {
SubscribeInternal(subscription_token, /*access_token=*/std::string());
@@ -132,12 +101,13 @@ void SubscriptionManagerImpl::StartAccessTokenRequest(
}
OAuth2TokenService::ScopeSet scopes = {kContentSuggestionsApiScope};
- access_token_fetcher_ = std::make_unique<
- identity::PrimaryAccountAccessTokenFetcher>(
- "ntp_snippets", signin_manager_, access_token_service_, scopes,
- base::BindOnce(&SubscriptionManagerImpl::AccessTokenFetchFinished,
- base::Unretained(this), subscription_token),
- identity::PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
+ access_token_fetcher_ =
+ identity_manager_->CreateAccessTokenFetcherForPrimaryAccount(
+ "ntp_snippets", scopes,
+ base::BindOnce(&SubscriptionManagerImpl::AccessTokenFetchFinished,
+ base::Unretained(this), subscription_token),
+ identity::PrimaryAccountAccessTokenFetcher::Mode::
+ kWaitUntilAvailable);
}
void SubscriptionManagerImpl::AccessTokenFetchFinished(
@@ -221,7 +191,7 @@ bool SubscriptionManagerImpl::NeedsToResubscribe() {
// Check if authentication state changed after subscription.
bool is_auth_subscribe = pref_service_->GetBoolean(
prefs::kBreakingNewsSubscriptionDataIsAuthenticated);
- bool is_authenticated = signin_manager_->IsAuthenticated();
+ bool is_authenticated = identity_manager_->HasPrimaryAccount();
return is_auth_subscribe != is_authenticated;
}
@@ -263,6 +233,16 @@ void SubscriptionManagerImpl::DidUnsubscribe(const std::string& new_token,
}
}
+void SubscriptionManagerImpl::OnPrimaryAccountSet(
+ const AccountInfo& account_info) {
+ SigninStatusChanged();
+}
+
+void SubscriptionManagerImpl::OnPrimaryAccountCleared(
+ const AccountInfo& account_info) {
+ SigninStatusChanged();
+}
+
void SubscriptionManagerImpl::SigninStatusChanged() {
// If subscribed already, resubscribe.
if (IsSubscribed()) {
diff --git a/chromium/components/ntp_snippets/breaking_news/subscription_manager_impl.h b/chromium/components/ntp_snippets/breaking_news/subscription_manager_impl.h
index fbaf1600d8b..17658d4035a 100644
--- a/chromium/components/ntp_snippets/breaking_news/subscription_manager_impl.h
+++ b/chromium/components/ntp_snippets/breaking_news/subscription_manager_impl.h
@@ -11,11 +11,10 @@
#include "base/memory/ref_counted.h"
#include "components/ntp_snippets/breaking_news/subscription_json_request.h"
#include "components/ntp_snippets/breaking_news/subscription_manager.h"
-#include "components/signin/core/browser/signin_manager_base.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/identity/public/cpp/identity_manager.h"
#include "url/gurl.h"
-class OAuth2TokenService;
class PrefRegistrySimple;
class PrefService;
@@ -34,14 +33,14 @@ namespace ntp_snippets {
// to the content suggestions server and does the bookkeeping for the data used
// for subscription. Bookkeeping is required to detect any change (e.g. the
// token render invalid), and resubscribe accordingly.
-class SubscriptionManagerImpl : public SubscriptionManager {
+class SubscriptionManagerImpl : public SubscriptionManager,
+ public identity::IdentityManager::Observer {
public:
SubscriptionManagerImpl(
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
PrefService* pref_service,
variations::VariationsService* variations_service,
- SigninManagerBase* signin_manager,
- OAuth2TokenService* access_token_service,
+ identity::IdentityManager* identity_manager,
const std::string& locale,
const std::string& api_key,
const GURL& subscribe_url,
@@ -64,7 +63,9 @@ class SubscriptionManagerImpl : public SubscriptionManager {
static void ClearProfilePrefs(PrefService* pref_service);
private:
- class SigninObserver;
+ // identity:IdentityManager::Observer implementation.
+ void OnPrimaryAccountSet(const AccountInfo& account_info) override;
+ void OnPrimaryAccountCleared(const AccountInfo& account_info) override;
void SigninStatusChanged();
@@ -99,9 +100,7 @@ class SubscriptionManagerImpl : public SubscriptionManager {
variations::VariationsService* const variations_service_;
// Authentication for signed-in users.
- SigninManagerBase* signin_manager_;
- std::unique_ptr<SigninObserver> signin_observer_;
- OAuth2TokenService* access_token_service_;
+ identity::IdentityManager* identity_manager_;
const std::string locale_;
diff --git a/chromium/components/ntp_snippets/breaking_news/subscription_manager_impl_unittest.cc b/chromium/components/ntp_snippets/breaking_news/subscription_manager_impl_unittest.cc
index 7c39b7db937..f79296ea258 100644
--- a/chromium/components/ntp_snippets/breaking_news/subscription_manager_impl_unittest.cc
+++ b/chromium/components/ntp_snippets/breaking_news/subscription_manager_impl_unittest.cc
@@ -11,14 +11,10 @@
#include "components/ntp_snippets/pref_names.h"
#include "components/ntp_snippets/remote/test_utils.h"
#include "components/prefs/testing_pref_service.h"
-#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
-#include "components/signin/core/browser/fake_signin_manager.h"
-#include "components/signin/core/browser/profile_management_switches.h"
-#include "components/signin/core/browser/test_signin_client.h"
-#include "google_apis/gaia/fake_oauth2_token_service_delegate.h"
#include "net/base/net_errors.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_test_util.h"
+#include "services/identity/public/cpp/identity_test_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -26,7 +22,10 @@ using testing::ElementsAre;
namespace ntp_snippets {
+#if !defined(OS_CHROMEOS)
const char kTestEmail[] = "test@email.com";
+#endif
+
const char kAPIKey[] = "fakeAPIkey";
const char kSubscriptionUrl[] = "http://valid-url.test/subscribe";
const char kSubscriptionUrlSignedIn[] = "http://valid-url.test/subscribe";
@@ -38,9 +37,7 @@ const char kUnsubscriptionUrlSignedIn[] = "http://valid-url.test/unsubscribe";
const char kUnsubscriptionUrlSignedOut[] =
"http://valid-url.test/unsubscribe?key=fakeAPIkey";
-class SubscriptionManagerImplTest
- : public testing::Test,
- public OAuth2TokenService::DiagnosticsObserver {
+class SubscriptionManagerImplTest : public testing::Test {
public:
SubscriptionManagerImplTest()
: request_context_getter_(
@@ -50,14 +47,6 @@ class SubscriptionManagerImplTest
void SetUp() override {
SubscriptionManagerImpl::RegisterProfilePrefs(
utils_.pref_service()->registry());
- signin::RegisterAccountConsistencyProfilePrefs(
- utils_.pref_service()->registry());
- signin::SetGaiaOriginIsolatedCallback(base::Bind([] { return true; }));
- utils_.token_service()->AddDiagnosticsObserver(this);
- }
-
- void TearDown() override {
- utils_.token_service()->RemoveDiagnosticsObserver(this);
}
scoped_refptr<net::URLRequestContextGetter> GetRequestContext() {
@@ -66,11 +55,18 @@ class SubscriptionManagerImplTest
PrefService* GetPrefService() { return utils_.pref_service(); }
- FakeProfileOAuth2TokenService* GetOAuth2TokenService() {
- return utils_.token_service();
+ identity::IdentityTestEnvironment* GetIdentityTestEnv() {
+ return &identity_test_env_;
}
- SigninManagerBase* GetSigninManager() { return utils_.fake_signin_manager(); }
+ std::unique_ptr<SubscriptionManagerImpl> BuildSubscriptionManager() {
+ return std::make_unique<SubscriptionManagerImpl>(
+ GetRequestContext(), GetPrefService(),
+ /*variations_service=*/nullptr,
+ GetIdentityTestEnv()->identity_manager(),
+ /*locale=*/"", kAPIKey, GURL(kSubscriptionUrl),
+ GURL(kUnsubscriptionUrl));
+ }
net::TestURLFetcher* GetRunningFetcher() {
// All created TestURLFetchers have ID 0 by default.
@@ -125,25 +121,12 @@ class SubscriptionManagerImplTest
#if !defined(OS_CHROMEOS)
void SignIn() {
- utils_.fake_signin_manager()->SignIn(kTestEmail, "user", "pass");
+ GetIdentityTestEnv()->MakePrimaryAccountAvailable(kTestEmail);
}
- void SignOut() { utils_.fake_signin_manager()->ForceSignOut(); }
+ void SignOut() { GetIdentityTestEnv()->ClearPrimaryAccount(); }
#endif // !defined(OS_CHROMEOS)
- void IssueRefreshToken(FakeProfileOAuth2TokenService* auth_token_service) {
- auth_token_service->GetDelegate()->UpdateCredentials(kTestEmail, "token");
- }
-
- void IssueAccessToken(FakeProfileOAuth2TokenService* auth_token_service) {
- auth_token_service->IssueAllTokensForAccount(kTestEmail, "access_token",
- base::Time::Max());
- }
-
- void set_on_access_token_request_callback(base::OnceClosure callback) {
- on_access_token_request_callback_ = std::move(callback);
- }
-
private:
void RespondSuccessfully() {
net::TestURLFetcher* url_fetcher = GetRunningFetcher();
@@ -162,33 +145,19 @@ class SubscriptionManagerImplTest
url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
}
- // OAuth2TokenService::DiagnosticsObserver:
- void OnAccessTokenRequested(
- const std::string& account_id,
- const std::string& consumer_id,
- const OAuth2TokenService::ScopeSet& scopes) override {
- if (on_access_token_request_callback_)
- std::move(on_access_token_request_callback_).Run();
- }
-
base::MessageLoop message_loop_;
test::RemoteSuggestionsTestUtils utils_;
+ identity::IdentityTestEnvironment identity_test_env_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
net::TestURLFetcherFactory url_fetcher_factory_;
- base::OnceClosure on_access_token_request_callback_;
};
TEST_F(SubscriptionManagerImplTest, SubscribeSuccessfully) {
std::string subscription_token = "1234567890";
- // TODO(vitaliii): Add a helper to build the manager.
- SubscriptionManagerImpl manager(
- GetRequestContext(), GetPrefService(),
- /*variations_service=*/nullptr, GetSigninManager(),
- GetOAuth2TokenService(),
- /*locale=*/"", kAPIKey, GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
- manager.Subscribe(subscription_token);
+ std::unique_ptr<SubscriptionManagerImpl> manager = BuildSubscriptionManager();
+ manager->Subscribe(subscription_token);
RespondToSubscriptionRequestSuccessfully(/*is_signed_in=*/false);
- ASSERT_TRUE(manager.IsSubscribed());
+ ASSERT_TRUE(manager->IsSubscribed());
EXPECT_EQ(subscription_token, GetPrefService()->GetString(
prefs::kBreakingNewsSubscriptionDataToken));
EXPECT_FALSE(GetPrefService()->GetBoolean(
@@ -200,33 +169,21 @@ TEST_F(SubscriptionManagerImplTest, SubscribeSuccessfully) {
#if !defined(OS_CHROMEOS)
TEST_F(SubscriptionManagerImplTest,
ShouldSubscribeWithAuthenticationWhenAuthenticated) {
- base::RunLoop run_loop;
- set_on_access_token_request_callback(run_loop.QuitClosure());
-
// Sign in.
- FakeProfileOAuth2TokenService* auth_token_service = GetOAuth2TokenService();
SignIn();
- IssueRefreshToken(auth_token_service);
// Create manager and subscribe.
std::string subscription_token = "1234567890";
- SubscriptionManagerImpl manager(
- GetRequestContext(), GetPrefService(),
- /*variations_service=*/nullptr, GetSigninManager(), auth_token_service,
- /*locale=*/"", kAPIKey, GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
- manager.Subscribe(subscription_token);
+ std::unique_ptr<SubscriptionManagerImpl> manager = BuildSubscriptionManager();
+ manager->Subscribe(subscription_token);
- run_loop.Run();
+ // Wait for the access token request and issue the access token.
+ GetIdentityTestEnv()->WaitForAccessTokenRequestAndRespondWithToken(
+ "access_token", base::Time::Max());
- // Make sure that subscription is pending an access token.
- ASSERT_FALSE(manager.IsSubscribed());
- ASSERT_EQ(1u, auth_token_service->GetPendingRequests().size());
-
- // Issue the access token and respond to the subscription request.
- IssueAccessToken(auth_token_service);
- ASSERT_FALSE(manager.IsSubscribed());
+ ASSERT_FALSE(manager->IsSubscribed());
RespondToSubscriptionRequestSuccessfully(/*is_signed_in=*/true);
- ASSERT_TRUE(manager.IsSubscribed());
+ ASSERT_TRUE(manager->IsSubscribed());
// Check that we are now subscribed correctly with authentication.
EXPECT_EQ(subscription_token, GetPrefService()->GetString(
@@ -238,30 +195,22 @@ TEST_F(SubscriptionManagerImplTest,
TEST_F(SubscriptionManagerImplTest, ShouldNotSubscribeIfError) {
std::string subscription_token = "1234567890";
- SubscriptionManagerImpl manager(
- GetRequestContext(), GetPrefService(),
- /*variations_service=*/nullptr, GetSigninManager(),
- GetOAuth2TokenService(),
- /*locale=*/"", kAPIKey, GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
+ std::unique_ptr<SubscriptionManagerImpl> manager = BuildSubscriptionManager();
- manager.Subscribe(subscription_token);
+ manager->Subscribe(subscription_token);
RespondToSubscriptionWithError(/*is_signed_in=*/false, net::ERR_TIMED_OUT);
- EXPECT_FALSE(manager.IsSubscribed());
+ EXPECT_FALSE(manager->IsSubscribed());
}
TEST_F(SubscriptionManagerImplTest, UnsubscribeSuccessfully) {
std::string subscription_token = "1234567890";
- SubscriptionManagerImpl manager(
- GetRequestContext(), GetPrefService(),
- /*variations_service=*/nullptr, GetSigninManager(),
- GetOAuth2TokenService(),
- /*locale=*/"", kAPIKey, GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
- manager.Subscribe(subscription_token);
+ std::unique_ptr<SubscriptionManagerImpl> manager = BuildSubscriptionManager();
+ manager->Subscribe(subscription_token);
RespondToSubscriptionRequestSuccessfully(/*is_signed_in=*/false);
- ASSERT_TRUE(manager.IsSubscribed());
- manager.Unsubscribe();
+ ASSERT_TRUE(manager->IsSubscribed());
+ manager->Unsubscribe();
RespondToUnsubscriptionRequestSuccessfully(/*is_signed_in=*/false);
- EXPECT_FALSE(manager.IsSubscribed());
+ EXPECT_FALSE(manager->IsSubscribed());
EXPECT_FALSE(
GetPrefService()->HasPrefPath(prefs::kBreakingNewsSubscriptionDataToken));
}
@@ -269,17 +218,13 @@ TEST_F(SubscriptionManagerImplTest, UnsubscribeSuccessfully) {
TEST_F(SubscriptionManagerImplTest,
ShouldRemainSubscribedIfErrorDuringUnsubscribe) {
std::string subscription_token = "1234567890";
- SubscriptionManagerImpl manager(
- GetRequestContext(), GetPrefService(),
- /*variations_service=*/nullptr, GetSigninManager(),
- GetOAuth2TokenService(),
- /*locale=*/"", kAPIKey, GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
- manager.Subscribe(subscription_token);
+ std::unique_ptr<SubscriptionManagerImpl> manager = BuildSubscriptionManager();
+ manager->Subscribe(subscription_token);
RespondToSubscriptionRequestSuccessfully(/*is_signed_in=*/false);
- ASSERT_TRUE(manager.IsSubscribed());
- manager.Unsubscribe();
+ ASSERT_TRUE(manager->IsSubscribed());
+ manager->Unsubscribe();
RespondToUnsubscriptionWithError(/*is_signed_in=*/false, net::ERR_TIMED_OUT);
- ASSERT_TRUE(manager.IsSubscribed());
+ ASSERT_TRUE(manager->IsSubscribed());
EXPECT_EQ(subscription_token, GetPrefService()->GetString(
prefs::kBreakingNewsSubscriptionDataToken));
}
@@ -290,27 +235,21 @@ TEST_F(SubscriptionManagerImplTest,
TEST_F(SubscriptionManagerImplTest,
ShouldResubscribeIfSignInAfterSubscription) {
// Create manager and subscribe.
- FakeProfileOAuth2TokenService* auth_token_service = GetOAuth2TokenService();
std::string subscription_token = "1234567890";
- SubscriptionManagerImpl manager(
- GetRequestContext(), GetPrefService(),
- /*variations_service=*/nullptr, GetSigninManager(), auth_token_service,
- /*locale=*/"", kAPIKey, GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
- manager.Subscribe(subscription_token);
+ std::unique_ptr<SubscriptionManagerImpl> manager = BuildSubscriptionManager();
+ manager->Subscribe(subscription_token);
RespondToSubscriptionRequestSuccessfully(/*is_signed_in=*/false);
- ASSERT_FALSE(manager.NeedsToResubscribe());
-
- base::RunLoop run_loop;
- set_on_access_token_request_callback(run_loop.QuitClosure());
+ ASSERT_FALSE(manager->NeedsToResubscribe());
// Sign in. This should trigger a resubscribe.
SignIn();
- IssueRefreshToken(auth_token_service);
- ASSERT_TRUE(manager.NeedsToResubscribe());
+ ASSERT_TRUE(manager->NeedsToResubscribe());
+
+ // Wait for the access token request that should occur and grant the access
+ // token.
+ GetIdentityTestEnv()->WaitForAccessTokenRequestAndRespondWithToken(
+ "access_token", base::Time::Max());
- run_loop.Run();
- ASSERT_EQ(1u, auth_token_service->GetPendingRequests().size());
- IssueAccessToken(auth_token_service);
RespondToSubscriptionRequestSuccessfully(/*is_signed_in=*/true);
// Check that we are now subscribed with authentication.
@@ -324,27 +263,19 @@ TEST_F(SubscriptionManagerImplTest,
#if !defined(OS_CHROMEOS)
TEST_F(SubscriptionManagerImplTest,
ShouldResubscribeIfSignOutAfterSubscription) {
- base::RunLoop run_loop;
- set_on_access_token_request_callback(run_loop.QuitClosure());
-
// Signin and subscribe.
- FakeProfileOAuth2TokenService* auth_token_service = GetOAuth2TokenService();
SignIn();
- IssueRefreshToken(auth_token_service);
std::string subscription_token = "1234567890";
- SubscriptionManagerImpl manager(
- GetRequestContext(), GetPrefService(),
- /*variations_service=*/nullptr, GetSigninManager(), auth_token_service,
- /*locale=*/"", kAPIKey, GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
- manager.Subscribe(subscription_token);
- run_loop.Run();
- ASSERT_EQ(1u, auth_token_service->GetPendingRequests().size());
- IssueAccessToken(auth_token_service);
+ std::unique_ptr<SubscriptionManagerImpl> manager = BuildSubscriptionManager();
+ manager->Subscribe(subscription_token);
+
+ GetIdentityTestEnv()->WaitForAccessTokenRequestAndRespondWithToken(
+ "access_token", base::Time::Max());
RespondToSubscriptionRequestSuccessfully(/*is_signed_in=*/true);
- // Signout, this should trigger a resubscribe.
+ // Sign out; this should trigger a resubscribe.
SignOut();
- EXPECT_TRUE(manager.NeedsToResubscribe());
+ EXPECT_TRUE(manager->NeedsToResubscribe());
RespondToSubscriptionRequestSuccessfully(/*is_signed_in=*/false);
// Check that we are now subscribed without authentication.
@@ -357,12 +288,8 @@ TEST_F(SubscriptionManagerImplTest,
ShouldUpdateTokenInPrefWhenResubscribeWithChangeInToken) {
// Create manager and subscribe.
std::string old_subscription_token = "1234567890";
- SubscriptionManagerImpl manager(
- GetRequestContext(), GetPrefService(),
- /*variations_service=*/nullptr, GetSigninManager(),
- GetOAuth2TokenService(),
- /*locale=*/"", kAPIKey, GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
- manager.Subscribe(old_subscription_token);
+ std::unique_ptr<SubscriptionManagerImpl> manager = BuildSubscriptionManager();
+ manager->Subscribe(old_subscription_token);
RespondToSubscriptionRequestSuccessfully(/*is_signed_in=*/false);
EXPECT_EQ(
old_subscription_token,
@@ -370,7 +297,7 @@ TEST_F(SubscriptionManagerImplTest,
// Resubscribe with a new token.
std::string new_subscription_token = "0987654321";
- manager.Resubscribe(new_subscription_token);
+ manager->Resubscribe(new_subscription_token);
// Resubscribe with a new token should issue an unsubscribe request before
// subscribing.
RespondToUnsubscriptionRequestSuccessfully(/*is_signed_in=*/false);
@@ -386,12 +313,8 @@ TEST_F(SubscriptionManagerImplTest, ShouldReportSubscriptionResult) {
base::HistogramTester histogram_tester;
// Create manager and subscribe.
const std::string subscription_token = "token";
- SubscriptionManagerImpl manager(
- GetRequestContext(), GetPrefService(),
- /*variations_service=*/nullptr, GetSigninManager(),
- GetOAuth2TokenService(),
- /*locale=*/"", kAPIKey, GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
- manager.Subscribe(subscription_token);
+ std::unique_ptr<SubscriptionManagerImpl> manager = BuildSubscriptionManager();
+ manager->Subscribe(subscription_token);
// TODO(vitaliii): Mock subscription request to avoid this low level errors.
RespondToSubscriptionWithError(/*is_signed_in=*/false,
/*error_code=*/net::ERR_INVALID_RESPONSE);
@@ -408,14 +331,10 @@ TEST_F(SubscriptionManagerImplTest, ShouldReportUnsubscriptionResult) {
base::HistogramTester histogram_tester;
// Create manager and subscribe.
const std::string subscription_token = "token";
- SubscriptionManagerImpl manager(
- GetRequestContext(), GetPrefService(),
- /*variations_service=*/nullptr, GetSigninManager(),
- GetOAuth2TokenService(),
- /*locale=*/"", kAPIKey, GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
- manager.Subscribe(subscription_token);
+ std::unique_ptr<SubscriptionManagerImpl> manager = BuildSubscriptionManager();
+ manager->Subscribe(subscription_token);
RespondToSubscriptionRequestSuccessfully(/*is_signed_in=*/false);
- manager.Unsubscribe();
+ manager->Unsubscribe();
RespondToUnsubscriptionWithError(/*is_signed_in=*/false,
/*error_code=*/net::ERR_INVALID_RESPONSE);
diff --git a/chromium/components/ntp_snippets/content_suggestions_service.cc b/chromium/components/ntp_snippets/content_suggestions_service.cc
index 8acf41e78f7..0cefd1e1cb7 100644
--- a/chromium/components/ntp_snippets/content_suggestions_service.cc
+++ b/chromium/components/ntp_snippets/content_suggestions_service.cc
@@ -55,7 +55,7 @@ void RecordFaviconFetchResult(FaviconFetchResult result) {
ContentSuggestionsService::ContentSuggestionsService(
State state,
- SigninManagerBase* signin_manager,
+ identity::IdentityManager* identity_manager,
history::HistoryService* history_service,
favicon::LargeIconService* large_icon_service,
PrefService* pref_service,
@@ -64,7 +64,7 @@ ContentSuggestionsService::ContentSuggestionsService(
std::unique_ptr<RemoteSuggestionsScheduler> remote_suggestions_scheduler,
std::unique_ptr<Logger> debug_logger)
: state_(state),
- signin_observer_(this),
+ identity_manager_observer_(this),
history_service_observer_(this),
remote_suggestions_provider_(nullptr),
large_icon_service_(large_icon_service),
@@ -74,8 +74,8 @@ ContentSuggestionsService::ContentSuggestionsService(
category_ranker_(std::move(category_ranker)),
debug_logger_(std::move(debug_logger)) {
// Can be null in tests.
- if (signin_manager) {
- signin_observer_.Add(signin_manager);
+ if (identity_manager) {
+ identity_manager_observer_.Add(identity_manager);
}
if (history_service) {
@@ -434,22 +434,6 @@ void ContentSuggestionsService::ReloadSuggestions() {
}
}
-void ContentSuggestionsService::OnChromeHomeStatusChanged(
- bool is_chrome_home_enabled) {
- debug_logger_->Log(
- FROM_HERE, base::StringPrintf("Chrome Home enabled: %s",
- is_chrome_home_enabled ? "true" : "false"));
- if (is_chrome_home_enabled) {
- // TODO(vitaliii): Make this code more general and do not hardcode specific
- // categories.
- DestroyCategoryAndItsProvider(
- Category::FromKnownCategory(KnownCategories::BOOKMARKS));
- DestroyCategoryAndItsProvider(
- Category::FromKnownCategory(KnownCategories::DOWNLOADS));
- }
- // TODO(vitaliii): Recreate providers when Chrome Home is turned off.
-}
-
bool ContentSuggestionsService::AreRemoteSuggestionsEnabled() const {
return remote_suggestions_provider_ &&
!remote_suggestions_provider_->IsDisabled();
@@ -521,16 +505,14 @@ void ContentSuggestionsService::OnSuggestionInvalidated(
observer.OnSuggestionInvalidated(suggestion_id);
}
}
-
-// SigninManagerBase::Observer implementation
-void ContentSuggestionsService::GoogleSigninSucceeded(
- const std::string& account_id,
- const std::string& username) {
+// identity::IdentityManager::Observer implementation
+void ContentSuggestionsService::OnPrimaryAccountSet(
+ const AccountInfo& account_info) {
OnSignInStateChanged(/*has_signed_in=*/true);
}
-void ContentSuggestionsService::GoogleSignedOut(const std::string& account_id,
- const std::string& username) {
+void ContentSuggestionsService::OnPrimaryAccountCleared(
+ const AccountInfo& account_info) {
OnSignInStateChanged(/*has_signed_in=*/false);
}
diff --git a/chromium/components/ntp_snippets/content_suggestions_service.h b/chromium/components/ntp_snippets/content_suggestions_service.h
index 212298b0695..0a0c4c49170 100644
--- a/chromium/components/ntp_snippets/content_suggestions_service.h
+++ b/chromium/components/ntp_snippets/content_suggestions_service.h
@@ -29,7 +29,7 @@
#include "components/ntp_snippets/logger.h"
#include "components/ntp_snippets/remote/remote_suggestions_scheduler.h"
#include "components/ntp_snippets/user_classifier.h"
-#include "components/signin/core/browser/signin_manager.h"
+#include "services/identity/public/cpp/identity_manager.h"
class PrefService;
class PrefRegistrySimple;
@@ -50,7 +50,7 @@ class RemoteSuggestionsProvider;
// them grouped into categories. There can be at most one provider per category.
class ContentSuggestionsService : public KeyedService,
public ContentSuggestionsProvider::Observer,
- public SigninManagerBase::Observer,
+ public identity::IdentityManager::Observer,
public history::HistoryServiceObserver {
public:
class Observer {
@@ -99,7 +99,8 @@ class ContentSuggestionsService : public KeyedService,
ContentSuggestionsService(
State state,
- SigninManagerBase* signin_manager, // Can be nullptr in unittests.
+ identity::IdentityManager*
+ identity_manager, // Can be nullptr in unittests.
history::HistoryService* history_service, // Can be nullptr in unittests.
// Can be nullptr in unittests.
favicon::LargeIconService* large_icon_service,
@@ -186,9 +187,6 @@ class ContentSuggestionsService : public KeyedService,
// meantime).
void ReloadSuggestions();
- // Must be called when Chrome Home is turned on or off.
- void OnChromeHomeStatusChanged(bool is_chrome_home_enabled);
-
// Observer accessors.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
@@ -283,11 +281,9 @@ class ContentSuggestionsService : public KeyedService,
ContentSuggestionsProvider* provider,
const ContentSuggestion::ID& suggestion_id) override;
- // SigninManagerBase::Observer implementation
- void GoogleSigninSucceeded(const std::string& account_id,
- const std::string& username) override;
- void GoogleSignedOut(const std::string& account_id,
- const std::string& username) override;
+ // identity::IdentityManager::Observer implementation.
+ void OnPrimaryAccountSet(const AccountInfo& account_info) override;
+ void OnPrimaryAccountCleared(const AccountInfo& account_info) override;
// history::HistoryServiceObserver implementation.
void OnURLsDeleted(history::HistoryService* history_service,
@@ -384,10 +380,10 @@ class ContentSuggestionsService : public KeyedService,
std::map<Category, std::vector<ContentSuggestion>, Category::CompareByID>
suggestions_by_category_;
- // Observer for the SigninManager. All observers are notified when the signin
- // state changes so that they can refresh their list of suggestions.
- ScopedObserver<SigninManagerBase, SigninManagerBase::Observer>
- signin_observer_;
+ // Observer for the IdentityManager. All observers are notified when the
+ // signin state changes so that they can refresh their list of suggestions.
+ ScopedObserver<identity::IdentityManager, identity::IdentityManager::Observer>
+ identity_manager_observer_;
// Observer for the HistoryService. All providers are notified when history is
// deleted.
diff --git a/chromium/components/ntp_snippets/content_suggestions_service_unittest.cc b/chromium/components/ntp_snippets/content_suggestions_service_unittest.cc
index 53cf0f6be14..9c2246a4e4a 100644
--- a/chromium/components/ntp_snippets/content_suggestions_service_unittest.cc
+++ b/chromium/components/ntp_snippets/content_suggestions_service_unittest.cc
@@ -158,7 +158,7 @@ class ContentSuggestionsServiceTest : public testing::Test {
pref_service_.get(), base::DefaultClock::GetInstance());
service_ = std::make_unique<ContentSuggestionsService>(
- enabled, /*signin_manager=*/nullptr, /*history_service=*/nullptr,
+ enabled, /*identity_manager=*/nullptr, /*history_service=*/nullptr,
/*large_icon_service=*/nullptr, pref_service_.get(),
std::move(category_ranker_), std::move(user_classifier),
/*scheduler=*/nullptr, /*debug_logger=*/std::make_unique<Logger>());
@@ -819,130 +819,4 @@ TEST_F(ContentSuggestionsServiceTest,
service()->DismissCategory(category);
}
-TEST_F(ContentSuggestionsServiceTest,
- ShouldDestroyBookmarksProviderWhenChromeHomeIsEnabled) {
- // Create and register the provider.
- Category bookmarks_category =
- Category::FromKnownCategory(KnownCategories::BOOKMARKS);
- MockContentSuggestionsProvider* bookmarks_provider =
- MakeRegisteredMockProvider(bookmarks_category);
- bookmarks_provider->FireSuggestionsChanged(
- bookmarks_category, CreateSuggestions(bookmarks_category, {1}));
- bookmarks_provider->FireCategoryStatusChangedWithCurrentStatus(
- bookmarks_category);
- ASSERT_THAT(service()->GetCategories(),
- UnorderedElementsAre(bookmarks_category));
- ASSERT_THAT(service()->GetCategoryStatus(bookmarks_category),
- Eq(CategoryStatus::AVAILABLE));
- ASSERT_THAT(service()->GetSuggestionsForCategory(bookmarks_category),
- SizeIs(1));
-
- // Set destructor callback to expect the destruction.
- base::MockCallback<MockContentSuggestionsProvider::DestructorCallback>
- mock_destructor_callback;
- bookmarks_provider->SetDestructorCallback(mock_destructor_callback.Get());
-
- MockServiceObserver observer;
- service()->AddObserver(&observer);
-
- // The provider must be destructed and the category status must change.
- EXPECT_CALL(mock_destructor_callback, Run());
- EXPECT_CALL(observer, OnCategoryStatusChanged(bookmarks_category,
- CategoryStatus::NOT_PROVIDED));
- service()->OnChromeHomeStatusChanged(/*is_chrome_home_enabled=*/true);
-
- EXPECT_THAT(service()->GetCategories(), IsEmpty());
- EXPECT_THAT(service()->GetCategoryStatus(bookmarks_category),
- Eq(CategoryStatus::NOT_PROVIDED));
- EXPECT_THAT(service()->GetSuggestionsForCategory(bookmarks_category),
- IsEmpty());
-
- service()->RemoveObserver(&observer);
-}
-
-TEST_F(ContentSuggestionsServiceTest,
- ShouldDestroyDownloadsProviderWhenChromeHomeIsEnabled) {
- // Create and register the provider.
- Category downloads_category =
- Category::FromKnownCategory(KnownCategories::DOWNLOADS);
- MockContentSuggestionsProvider* downloads_provider =
- MakeRegisteredMockProvider(downloads_category);
- downloads_provider->FireSuggestionsChanged(
- downloads_category, CreateSuggestions(downloads_category, {1}));
- downloads_provider->FireCategoryStatusChangedWithCurrentStatus(
- downloads_category);
- ASSERT_THAT(service()->GetCategories(),
- UnorderedElementsAre(downloads_category));
- ASSERT_THAT(service()->GetCategoryStatus(downloads_category),
- Eq(CategoryStatus::AVAILABLE));
- ASSERT_THAT(service()->GetSuggestionsForCategory(downloads_category),
- SizeIs(1));
-
- // Set destructor callback to expect the destruction.
- base::MockCallback<MockContentSuggestionsProvider::DestructorCallback>
- mock_destructor_callback;
- downloads_provider->SetDestructorCallback(mock_destructor_callback.Get());
-
- MockServiceObserver observer;
- service()->AddObserver(&observer);
-
- // The provider must be destructed and the category status must change.
- EXPECT_CALL(mock_destructor_callback, Run());
- EXPECT_CALL(observer, OnCategoryStatusChanged(downloads_category,
- CategoryStatus::NOT_PROVIDED));
- service()->OnChromeHomeStatusChanged(/*is_chrome_home_enabled=*/true);
-
- EXPECT_THAT(service()->GetCategories(), IsEmpty());
- EXPECT_THAT(service()->GetCategoryStatus(downloads_category),
- Eq(CategoryStatus::NOT_PROVIDED));
- EXPECT_THAT(service()->GetSuggestionsForCategory(downloads_category),
- IsEmpty());
-
- service()->RemoveObserver(&observer);
-}
-
-TEST_F(ContentSuggestionsServiceTest,
- ShouldNotDestroyArticlesProviderWhenChromeHomeIsEnabled) {
- // Create and register the provider.
- Category articles_category =
- Category::FromKnownCategory(KnownCategories::ARTICLES);
- MockContentSuggestionsProvider* articles_provider =
- MakeRegisteredMockProvider(articles_category);
- articles_provider->FireSuggestionsChanged(
- articles_category, CreateSuggestions(articles_category, {1}));
- articles_provider->FireCategoryStatusChangedWithCurrentStatus(
- articles_category);
- ASSERT_THAT(service()->GetCategories(),
- UnorderedElementsAre(articles_category));
- ASSERT_THAT(service()->GetCategoryStatus(articles_category),
- Eq(CategoryStatus::AVAILABLE));
- ASSERT_THAT(service()->GetSuggestionsForCategory(articles_category),
- SizeIs(1));
-
- // Set destructor callback to ensure no destruction.
- base::MockCallback<MockContentSuggestionsProvider::DestructorCallback>
- mock_destructor_callback;
- articles_provider->SetDestructorCallback(mock_destructor_callback.Get());
-
- MockServiceObserver observer;
- service()->AddObserver(&observer);
-
- // The provider must not be destructed and the category status must not
- // change, because Articles are enabled in Chrome Home.
- EXPECT_CALL(mock_destructor_callback, Run()).Times(0);
- EXPECT_CALL(observer, OnCategoryStatusChanged(articles_category, _)).Times(0);
- service()->OnChromeHomeStatusChanged(/*is_chrome_home_enabled=*/true);
-
- EXPECT_THAT(service()->GetCategories(),
- UnorderedElementsAre(articles_category));
- EXPECT_THAT(service()->GetCategoryStatus(articles_category),
- Eq(CategoryStatus::AVAILABLE));
- EXPECT_THAT(service()->GetSuggestionsForCategory(articles_category),
- SizeIs(1));
-
- articles_provider->SetDestructorCallback(
- MockContentSuggestionsProvider::DestructorCallback());
- service()->RemoveObserver(&observer);
-}
-
} // namespace ntp_snippets
diff --git a/chromium/components/ntp_snippets/contextual/contextual_json_request.h b/chromium/components/ntp_snippets/contextual/contextual_json_request.h
index 989880511da..c62ccd203cf 100644
--- a/chromium/components/ntp_snippets/contextual/contextual_json_request.h
+++ b/chromium/components/ntp_snippets/contextual/contextual_json_request.h
@@ -13,7 +13,6 @@
#include "base/memory/weak_ptr.h"
#include "components/ntp_snippets/remote/json_request.h"
#include "components/ntp_snippets/status.h"
-#include "google_apis/gaia/oauth2_token_service.h"
#include "net/http/http_request_headers.h"
namespace base {
diff --git a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc
index cd45f3894b2..7eb6228cb67 100644
--- a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc
+++ b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc
@@ -13,7 +13,7 @@
#include "components/strings/grit/components_strings.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_status.h"
-#include "services/identity/public/cpp/primary_account_access_token_fetcher.h"
+#include "services/identity/public/cpp/identity_manager.h"
#include "ui/base/l10n/l10n_util.h"
using net::HttpRequestHeaders;
@@ -110,13 +110,11 @@ bool AddSuggestionsFromListValue(bool content_suggestions_api,
} // namespace
ContextualSuggestionsFetcherImpl::ContextualSuggestionsFetcherImpl(
- SigninManagerBase* signin_manager,
- OAuth2TokenService* token_service,
+ identity::IdentityManager* identity_manager,
scoped_refptr<URLRequestContextGetter> url_request_context_getter,
PrefService* pref_service,
const ParseJSONCallback& parse_json_callback)
- : signin_manager_(signin_manager),
- token_service_(token_service),
+ : identity_manager_(identity_manager),
url_request_context_getter_(std::move(url_request_context_getter)),
parse_json_callback_(parse_json_callback),
fetch_url_(GetFetchEndpoint()) {}
@@ -152,7 +150,7 @@ void ContextualSuggestionsFetcherImpl::StartRequest(
SuggestionsAvailableCallback callback,
const std::string& oauth_access_token) {
builder.SetUrl(fetch_url_)
- .SetAuthentication(signin_manager_->GetAuthenticatedAccountId(),
+ .SetAuthentication(identity_manager_->GetPrimaryAccountInfo().account_id,
base::StringPrintf(kAuthorizationRequestHeaderFormat,
oauth_access_token.c_str()));
DVLOG(1) << "ContextualSuggestionsFetcherImpl::StartRequest";
@@ -170,8 +168,8 @@ void ContextualSuggestionsFetcherImpl::StartTokenRequest() {
}
OAuth2TokenService::ScopeSet scopes{kContentSuggestionsApiScope};
- token_fetcher_ = std::make_unique<identity::PrimaryAccountAccessTokenFetcher>(
- "ntp_snippets", signin_manager_, token_service_, scopes,
+ token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForPrimaryAccount(
+ "ntp_snippets", scopes,
base::BindOnce(
&ContextualSuggestionsFetcherImpl::AccessTokenFetchFinished,
base::Unretained(this)),
diff --git a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h
index 76bd1c849e6..3a7a7fc236f 100644
--- a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h
+++ b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h
@@ -20,12 +20,12 @@
#include "components/ntp_snippets/contextual/contextual_suggestions_fetcher.h"
#include "components/ntp_snippets/status.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/identity/public/cpp/primary_account_access_token_fetcher.h"
-class OAuth2TokenService;
class PrefService;
-class SigninManagerBase;
namespace identity {
+class IdentityManager;
class PrimaryAccountAccessTokenFetcher;
}
@@ -36,8 +36,7 @@ namespace ntp_snippets {
class ContextualSuggestionsFetcherImpl : public ContextualSuggestionsFetcher {
public:
ContextualSuggestionsFetcherImpl(
- SigninManagerBase* signin_manager,
- OAuth2TokenService* token_service,
+ identity::IdentityManager* identity_manager,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
PrefService* pref_service,
const ParseJSONCallback& parse_json_callback);
@@ -77,8 +76,7 @@ class ContextualSuggestionsFetcherImpl : public ContextualSuggestionsFetcher {
ContextualSuggestion::PtrVector* suggestions);
// Authentication for signed-in users.
- SigninManagerBase* signin_manager_;
- OAuth2TokenService* token_service_;
+ identity::IdentityManager* identity_manager_;
std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher> token_fetcher_;
diff --git a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc
index a9615ec1094..77ba581069d 100644
--- a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc
+++ b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc
@@ -15,11 +15,9 @@
#include "components/ntp_snippets/category.h"
#include "components/ntp_snippets/remote/test_utils.h"
#include "components/prefs/testing_pref_service.h"
-#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
-#include "components/signin/core/browser/fake_signin_manager.h"
-#include "google_apis/gaia/fake_oauth2_token_service_delegate.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_test_util.h"
+#include "services/identity/public/cpp/identity_test_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -104,9 +102,7 @@ void ParseJson(const std::string& json,
} // namespace
-class ContextualSuggestionsFetcherTest
- : public testing::Test,
- public OAuth2TokenService::DiagnosticsObserver {
+class ContextualSuggestionsFetcherTest : public testing::Test {
public:
ContextualSuggestionsFetcherTest()
: fake_url_fetcher_factory_(new net::FakeURLFetcherFactory(nullptr)),
@@ -114,18 +110,13 @@ class ContextualSuggestionsFetcherTest
base::TestMockTimeTaskRunner::Type::kBoundToThread)) {
scoped_refptr<net::TestURLRequestContextGetter> request_context_getter =
new net::TestURLRequestContextGetter(mock_task_runner_.get());
- fake_token_service_ = std::make_unique<FakeProfileOAuth2TokenService>(
- std::make_unique<FakeOAuth2TokenServiceDelegate>(
- request_context_getter.get()));
fetcher_ = std::make_unique<ContextualSuggestionsFetcherImpl>(
- test_utils_.fake_signin_manager(), fake_token_service_.get(),
+ identity_test_env_.identity_manager(),
std::move(request_context_getter), test_utils_.pref_service(),
- base::Bind(&ParseJson));
- fake_token_service_->AddDiagnosticsObserver(this);
+ base::BindRepeating(&ParseJson));
}
~ContextualSuggestionsFetcherTest() override {
- fake_token_service_->RemoveDiagnosticsObserver(this);
}
void FastForwardUntilNoTasksRemain() {
@@ -133,17 +124,7 @@ class ContextualSuggestionsFetcherTest
}
void InitializeFakeCredentials() {
-#if defined(OS_CHROMEOS)
- test_utils_.fake_signin_manager()->SignIn(kTestEmail);
-#else
- test_utils_.fake_signin_manager()->SignIn(kTestEmail, "user", "password");
-#endif
- fake_token_service_->GetDelegate()->UpdateCredentials(kTestEmail, "token");
- }
-
- void IssueOAuth2Token() {
- fake_token_service_->IssueAllTokensForAccount(kTestEmail, "access_token",
- base::Time::Max());
+ identity_test_env()->MakePrimaryAccountAvailable(kTestEmail);
}
void SetFakeResponse(const std::string& response_data,
@@ -165,27 +146,17 @@ class ContextualSuggestionsFetcherTest
return mock_suggestions_available_callback_;
}
- void set_on_access_token_request_callback(base::OnceClosure callback) {
- on_access_token_request_callback_ = std::move(callback);
+ identity::IdentityTestEnvironment* identity_test_env() {
+ return &identity_test_env_;
}
private:
- // OAuth2TokenService::DiagnosticsObserver:
- void OnAccessTokenRequested(
- const std::string& account_id,
- const std::string& consumer_id,
- const OAuth2TokenService::ScopeSet& scopes) override {
- if (on_access_token_request_callback_)
- std::move(on_access_token_request_callback_).Run();
- }
-
- std::unique_ptr<FakeProfileOAuth2TokenService> fake_token_service_;
+ identity::IdentityTestEnvironment identity_test_env_;
std::unique_ptr<net::FakeURLFetcherFactory> fake_url_fetcher_factory_;
std::unique_ptr<ContextualSuggestionsFetcherImpl> fetcher_;
MockSuggestionsAvailableCallback mock_suggestions_available_callback_;
scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_;
test::RemoteSuggestionsTestUtils test_utils_;
- base::OnceClosure on_access_token_request_callback_;
DISALLOW_COPY_AND_ASSIGN(ContextualSuggestionsFetcherTest);
};
@@ -196,9 +167,6 @@ TEST_F(ContextualSuggestionsFetcherTest, ShouldCreateFetcher) {
}
TEST_F(ContextualSuggestionsFetcherTest, ShouldFetchSuggestion) {
- base::RunLoop run_loop;
- set_on_access_token_request_callback(run_loop.QuitClosure());
-
InitializeFakeCredentials();
const std::string kValidResponseData =
"{\"categories\" : [{"
@@ -220,18 +188,15 @@ TEST_F(ContextualSuggestionsFetcherTest, ShouldFetchSuggestion) {
GURL(kValidURL),
ToSuggestionsAvailableCallback(&mock_suggestions_available_callback()));
- run_loop.Run();
+ identity_test_env()->WaitForAccessTokenRequestAndRespondWithToken(
+ "access_token", base::Time::Max());
- IssueOAuth2Token();
FastForwardUntilNoTasksRemain();
EXPECT_THAT(fetcher().GetLastStatusForTesting(), Eq("OK"));
EXPECT_THAT(fetcher().GetLastJsonForTesting(), Eq(kValidResponseData));
}
TEST_F(ContextualSuggestionsFetcherTest, ShouldFetchEmptySuggestionsList) {
- base::RunLoop run_loop;
- set_on_access_token_request_callback(run_loop.QuitClosure());
-
InitializeFakeCredentials();
const std::string kValidEmptyCategoryResponseData =
"{\"categories\" : [{"
@@ -248,9 +213,9 @@ TEST_F(ContextualSuggestionsFetcherTest, ShouldFetchEmptySuggestionsList) {
GURL(kValidURL),
ToSuggestionsAvailableCallback(&mock_suggestions_available_callback()));
- run_loop.Run();
+ identity_test_env()->WaitForAccessTokenRequestAndRespondWithToken(
+ "access_token", base::Time::Max());
- IssueOAuth2Token();
FastForwardUntilNoTasksRemain();
EXPECT_THAT(fetcher().GetLastStatusForTesting(), Eq("OK"));
EXPECT_THAT(fetcher().GetLastJsonForTesting(),
@@ -259,9 +224,6 @@ TEST_F(ContextualSuggestionsFetcherTest, ShouldFetchEmptySuggestionsList) {
TEST_F(ContextualSuggestionsFetcherTest,
ShouldReportErrorForEmptyResponseData) {
- base::RunLoop run_loop;
- set_on_access_token_request_callback(run_loop.QuitClosure());
-
InitializeFakeCredentials();
SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND,
net::URLRequestStatus::SUCCESS);
@@ -272,17 +234,14 @@ TEST_F(ContextualSuggestionsFetcherTest,
GURL(kValidURL),
ToSuggestionsAvailableCallback(&mock_suggestions_available_callback()));
- run_loop.Run();
+ identity_test_env()->WaitForAccessTokenRequestAndRespondWithToken(
+ "access_token", base::Time::Max());
- IssueOAuth2Token();
FastForwardUntilNoTasksRemain();
}
TEST_F(ContextualSuggestionsFetcherTest,
ShouldReportErrorForInvalidResponseData) {
- base::RunLoop run_loop;
- set_on_access_token_request_callback(run_loop.QuitClosure());
-
InitializeFakeCredentials();
const std::string kInvalidResponseData = "{ \"recos\": []";
SetFakeResponse(/*response_data=*/kInvalidResponseData, net::HTTP_OK,
@@ -298,9 +257,9 @@ TEST_F(ContextualSuggestionsFetcherTest,
GURL(kValidURL),
ToSuggestionsAvailableCallback(&mock_suggestions_available_callback()));
- run_loop.Run();
+ identity_test_env()->WaitForAccessTokenRequestAndRespondWithToken(
+ "access_token", base::Time::Max());
- IssueOAuth2Token();
FastForwardUntilNoTasksRemain();
EXPECT_THAT(fetcher().GetLastStatusForTesting(),
StartsWith("Received invalid JSON (error "));
diff --git a/chromium/components/ntp_snippets/features.cc b/chromium/components/ntp_snippets/features.cc
index 371bfb066d7..af71fdc7e65 100644
--- a/chromium/components/ntp_snippets/features.cc
+++ b/chromium/components/ntp_snippets/features.cc
@@ -20,6 +20,7 @@ const base::Feature kRemoteSuggestionsBackendFeature{
// Keep sorted, and keep nullptr at the end.
const base::Feature* const kAllFeatures[] = {
+ &kArticleSuggestionsExpandableHeader,
&kArticleSuggestionsFeature,
&kBookmarkSuggestionsFeature,
&kBreakingNewsPushFeature,
@@ -36,6 +37,9 @@ const base::Feature* const kAllFeatures[] = {
&kRemoteSuggestionsBackendFeature,
nullptr};
+const base::Feature kArticleSuggestionsExpandableHeader{
+ "NTPArticleSuggestionsExpandableHeader", base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kArticleSuggestionsFeature{
"NTPArticleSuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chromium/components/ntp_snippets/features.h b/chromium/components/ntp_snippets/features.h
index 09fa9d3ebb5..5c689e299aa 100644
--- a/chromium/components/ntp_snippets/features.h
+++ b/chromium/components/ntp_snippets/features.h
@@ -40,6 +40,9 @@ extern const base::Feature kForeignSessionsSuggestionsFeature;
////////////////////////////////////////////////////////////////////////////////
// Independent features. Treat as normal
+// Feature to allow show/hide article suggestions by clicking the header.
+extern const base::Feature kArticleSuggestionsExpandableHeader;
+
// TODO(jkrcal): Rename to kRemoteSuggestionsFeature.
extern const base::Feature kArticleSuggestionsFeature;
diff --git a/chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.cc b/chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.cc
index 26ae3c53665..728ca5c95fc 100644
--- a/chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.cc
+++ b/chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.cc
@@ -182,11 +182,6 @@ void RecentTabSuggestionsProvider::RegisterProfilePrefs(
////////////////////////////////////////////////////////////////////////////////
// Private methods
-void RecentTabSuggestionsProvider::OnItemsAvailable(
- OfflineContentProvider* provider) {
- FetchRecentTabs();
-}
-
void RecentTabSuggestionsProvider::OnItemsAdded(
const std::vector<OfflineItem>& items) {
FetchRecentTabs();
diff --git a/chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.h b/chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.h
index 2fb467ffe6b..9aa31ce2a36 100644
--- a/chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.h
+++ b/chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.h
@@ -63,7 +63,6 @@ class RecentTabSuggestionsProvider : public ContentSuggestionsProvider,
friend class RecentTabSuggestionsProviderTestNoLoad;
// OfflineContentProvider::Observer implementation.
- void OnItemsAvailable(OfflineContentProvider* provider) override;
void OnItemsAdded(const std::vector<OfflineItem>& items) override;
void OnItemRemoved(const ContentId& id) override;
void OnItemUpdated(const OfflineItem& item) override;
diff --git a/chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc b/chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc
index e5055d8c3de..504a61fac38 100644
--- a/chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc
+++ b/chromium/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc
@@ -42,6 +42,8 @@ namespace ntp_snippets {
namespace {
+const int64_t kSystemDownloadId = 0;
+
OfflinePageItem CreateDummyRecentTab(int offline_id) {
// This is used to assign unique tab IDs to pages. Since offline IDs are
// typically small integers like 1, 2, 3 etc, we start at 1001 to ensure that
@@ -68,6 +70,8 @@ OfflinePageItem CreateDummyRecentTab(int id, base::Time time) {
return item;
}
+void GetAllItemsDummyCallback(const std::vector<OfflineItem>& items) {}
+
} // namespace
class RecentTabSuggestionsProviderTestNoLoad : public testing::Test {
@@ -89,6 +93,9 @@ class RecentTabSuggestionsProviderTestNoLoad : public testing::Test {
ui_adapter_);
provider_ = std::make_unique<RecentTabSuggestionsProvider>(
&observer_, ui_adapter_, pref_service());
+ // Force adapter to load its cache.
+ ui_adapter_->GetAllItems(base::BindOnce(&GetAllItemsDummyCallback));
+ provider_->FetchRecentTabs();
}
Category recent_tabs_category() {
@@ -119,7 +126,8 @@ class RecentTabSuggestionsProviderTestNoLoad : public testing::Test {
RemoveTab(tab_id);
ui_adapter_->OfflinePageDeleted(
offline_pages::OfflinePageModel::DeletedPageInfo(
- item.offline_id, item.client_id, "" /* request_origin */));
+ item.offline_id, kSystemDownloadId, item.client_id,
+ "" /* request_origin */));
}
std::set<std::string> ReadDismissedIDsFromPrefs() {
diff --git a/chromium/components/ntp_snippets/pref_names.cc b/chromium/components/ntp_snippets/pref_names.cc
index c2611d1e7ca..781e0f2c89d 100644
--- a/chromium/components/ntp_snippets/pref_names.cc
+++ b/chromium/components/ntp_snippets/pref_names.cc
@@ -9,6 +9,8 @@ namespace prefs {
const char kEnableSnippets[] = "ntp_snippets.enable";
+const char kArticlesListVisible[] = "ntp_snippets.list_visible";
+
const char kRemoteSuggestionCategories[] = "ntp_snippets.remote_categories";
const char kSnippetLastFetchAttemptTime[] = "ntp_snippets.last_fetch_attempt";
diff --git a/chromium/components/ntp_snippets/pref_names.h b/chromium/components/ntp_snippets/pref_names.h
index 5523d5ea6a1..e00b7778d29 100644
--- a/chromium/components/ntp_snippets/pref_names.h
+++ b/chromium/components/ntp_snippets/pref_names.h
@@ -12,6 +12,10 @@ namespace prefs {
// an enterprise policy.
extern const char kEnableSnippets[];
+// Whether the list of NTP snippets is visible in UI. This is set to false when
+// the user toggles the list off.
+extern const char kArticlesListVisible[];
+
// The pref name under which remote suggestion categories (including their ID
// and title) are stored.
extern const char kRemoteSuggestionCategories[];
diff --git a/chromium/components/ntp_snippets/remote/json_request.h b/chromium/components/ntp_snippets/remote/json_request.h
index e7770e1376a..d90fb293602 100644
--- a/chromium/components/ntp_snippets/remote/json_request.h
+++ b/chromium/components/ntp_snippets/remote/json_request.h
@@ -16,8 +16,10 @@
#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/oauth2_token_service.h"
#include "net/http/http_request_headers.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "url/gurl.h"
namespace base {
class Value;
@@ -96,6 +98,8 @@ class JsonRequest : public net::URLFetcherDelegate {
return *this;
}
+ bool is_interactive_request() const { return params_.interactive_request; }
+
private:
std::string BuildHeaders() const;
std::string BuildBody() const;
diff --git a/chromium/components/ntp_snippets/remote/prefetched_pages_tracker.h b/chromium/components/ntp_snippets/remote/prefetched_pages_tracker.h
index b81e78c1677..c767761bfe8 100644
--- a/chromium/components/ntp_snippets/remote/prefetched_pages_tracker.h
+++ b/chromium/components/ntp_snippets/remote/prefetched_pages_tracker.h
@@ -21,11 +21,10 @@ class PrefetchedPagesTracker {
// Whether the tracker has finished initialization.
virtual bool IsInitialized() const = 0;
- // Add a callback, which will be called when the initialization is completed.
- // If the tracker has been initialized already, the callback is called
- // immediately.
- virtual void AddInitializationCompletedCallback(
- base::OnceCallback<void()> callback) = 0;
+ // Starts asynchronous initialization. Callback will be called when the
+ // initialization is completed. If the tracker has been initialized already,
+ // the callback is called immediately.
+ virtual void Initialize(base::OnceCallback<void()> callback) = 0;
virtual bool PrefetchedOfflinePageExists(const GURL& url) const = 0;
};
diff --git a/chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl.cc b/chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl.cc
index dc8018c43bc..516e7b904d5 100644
--- a/chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl.cc
+++ b/chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl.cc
@@ -33,12 +33,6 @@ PrefetchedPagesTrackerImpl::PrefetchedPagesTrackerImpl(
offline_page_model_(offline_page_model),
weak_ptr_factory_(this) {
DCHECK(offline_page_model_);
- // If Offline Page model is not loaded yet, it will process our query
- // once it has finished loading.
- offline_page_model_->GetPagesByNamespace(
- offline_pages::kSuggestedArticlesNamespace,
- base::Bind(&PrefetchedPagesTrackerImpl::Initialize,
- weak_ptr_factory_.GetWeakPtr()));
}
PrefetchedPagesTrackerImpl::~PrefetchedPagesTrackerImpl() {
@@ -49,12 +43,22 @@ bool PrefetchedPagesTrackerImpl::IsInitialized() const {
return initialized_;
}
-void PrefetchedPagesTrackerImpl::AddInitializationCompletedCallback(
+void PrefetchedPagesTrackerImpl::Initialize(
base::OnceCallback<void()> callback) {
if (IsInitialized()) {
std::move(callback).Run();
+ } else {
+ initialization_completed_callbacks_.push_back(std::move(callback));
+ // The call to get pages might be already in flight, started by previous
+ // calls to this method. In this case, there is at least one callback
+ // already waiting.
+ if (initialization_completed_callbacks_.size() == 1) {
+ offline_page_model_->GetPagesByNamespace(
+ offline_pages::kSuggestedArticlesNamespace,
+ base::BindRepeating(&PrefetchedPagesTrackerImpl::OfflinePagesLoaded,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
}
- initialization_completed_callbacks_.push_back(std::move(callback));
}
bool PrefetchedPagesTrackerImpl::PrefetchedOfflinePageExists(
@@ -100,7 +104,7 @@ void PrefetchedPagesTrackerImpl::OfflinePageDeleted(
offline_id_to_url_mapping_.erase(offline_id_it);
}
-void PrefetchedPagesTrackerImpl::Initialize(
+void PrefetchedPagesTrackerImpl::OfflinePagesLoaded(
const std::vector<OfflinePageItem>& all_prefetched_offline_pages) {
for (const OfflinePageItem& item : all_prefetched_offline_pages) {
DCHECK(IsOfflineItemPrefetchedPage(item));
@@ -112,6 +116,7 @@ void PrefetchedPagesTrackerImpl::Initialize(
for (auto& callback : initialization_completed_callbacks_) {
std::move(callback).Run();
}
+ initialization_completed_callbacks_.clear();
}
void PrefetchedPagesTrackerImpl::AddOfflinePage(
diff --git a/chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl.h b/chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl.h
index d314a120343..ee5fb2d0ca6 100644
--- a/chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl.h
+++ b/chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl.h
@@ -32,8 +32,7 @@ class PrefetchedPagesTrackerImpl
// PrefetchedPagesTracker implementation
bool IsInitialized() const override;
- void AddInitializationCompletedCallback(
- base::OnceCallback<void()> callback) override;
+ void Initialize(base::OnceCallback<void()> callback) override;
bool PrefetchedOfflinePageExists(const GURL& url) const override;
// OfflinePageModel::Observer implementation.
@@ -46,8 +45,8 @@ class PrefetchedPagesTrackerImpl
override;
private:
- void Initialize(const std::vector<offline_pages::OfflinePageItem>&
- all_prefetched_offline_pages);
+ void OfflinePagesLoaded(const std::vector<offline_pages::OfflinePageItem>&
+ all_prefetched_offline_pages);
void AddOfflinePage(const offline_pages::OfflinePageItem& offline_page_item);
bool initialized_;
diff --git a/chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl_unittest.cc b/chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl_unittest.cc
index 83f29de26d0..4af1ac1c18e 100644
--- a/chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl_unittest.cc
+++ b/chromium/components/ntp_snippets/remote/prefetched_pages_tracker_impl_unittest.cc
@@ -17,7 +17,6 @@
using ntp_snippets::test::FakeOfflinePageModel;
using offline_pages::MultipleOfflinePageItemCallback;
using offline_pages::OfflinePageItem;
-using offline_pages::OfflinePageModelQuery;
using testing::_;
using testing::Eq;
using testing::SaveArg;
@@ -27,6 +26,8 @@ namespace ntp_snippets {
namespace {
+const int64_t kSystemDownloadId = 0;
+
class MockOfflinePageModel : public offline_pages::StubOfflinePageModel {
public:
~MockOfflinePageModel() override = default;
@@ -68,11 +69,12 @@ class PrefetchedPagesTrackerImplTest : public ::testing::Test {
};
TEST_F(PrefetchedPagesTrackerImplTest,
- ShouldRetrievePrefetchedEarlierSuggestionsOnStartup) {
+ ShouldRetrievePrefetchedEarlierSuggestionsOnInitialize) {
(*fake_offline_page_model()->mutable_items()) = {
CreateOfflinePageItem(GURL("http://prefetched.com"),
offline_pages::kSuggestedArticlesNamespace)};
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
+ tracker.Initialize(base::BindOnce([] {}));
ASSERT_FALSE(
tracker.PrefetchedOfflinePageExists(GURL("http://not_added_url.com")));
@@ -84,6 +86,7 @@ TEST_F(PrefetchedPagesTrackerImplTest,
ShouldAddNewPrefetchedPagesWhenNotified) {
fake_offline_page_model()->mutable_items()->clear();
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
+ tracker.Initialize(base::BindOnce([] {}));
ASSERT_FALSE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
@@ -99,6 +102,7 @@ TEST_F(PrefetchedPagesTrackerImplTest,
ShouldIgnoreOtherTypesOfOfflinePagesWhenNotified) {
fake_offline_page_model()->mutable_items()->clear();
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
+ tracker.Initialize(base::BindOnce([] {}));
ASSERT_FALSE(tracker.PrefetchedOfflinePageExists(
GURL("http://manually_downloaded.com")));
@@ -116,6 +120,7 @@ TEST_F(PrefetchedPagesTrackerImplTest,
CreateOfflinePageItem(GURL("http://manually_downloaded.com"),
offline_pages::kNTPSuggestionsNamespace)};
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
+ tracker.Initialize(base::BindOnce([] {}));
ASSERT_FALSE(tracker.PrefetchedOfflinePageExists(
GURL("http://manually_downloaded.com")));
@@ -129,11 +134,13 @@ TEST_F(PrefetchedPagesTrackerImplTest, ShouldDeletePrefetchedURLWhenNotified) {
offline_pages::kSuggestedArticlesNamespace);
(*fake_offline_page_model()->mutable_items()) = {item};
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
+ tracker.Initialize(base::BindOnce([] {}));
ASSERT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
tracker.OfflinePageDeleted(offline_pages::OfflinePageModel::DeletedPageInfo(
- item.offline_id, item.client_id, /*request_origin=*/""));
+ item.offline_id, kSystemDownloadId, item.client_id,
+ /*request_origin=*/""));
EXPECT_FALSE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
}
@@ -149,22 +156,25 @@ TEST_F(PrefetchedPagesTrackerImplTest,
(*fake_offline_page_model()->mutable_items()) = {prefetched_item,
manually_downloaded_item};
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
+ tracker.Initialize(base::BindOnce([] {}));
ASSERT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
tracker.OfflinePageDeleted(offline_pages::OfflinePageModel::DeletedPageInfo(
- manually_downloaded_item.offline_id, manually_downloaded_item.client_id,
+ manually_downloaded_item.offline_id, kSystemDownloadId,
+ manually_downloaded_item.client_id,
/*request_origin=*/""));
EXPECT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
}
TEST_F(PrefetchedPagesTrackerImplTest,
- ShouldReportAsNotInitializedBeforeInitialization) {
+ ShouldReportAsNotInitializedBeforeReceivedArticles) {
EXPECT_CALL(
*mock_offline_page_model(),
GetPagesByNamespace(offline_pages::kSuggestedArticlesNamespace, _));
PrefetchedPagesTrackerImpl tracker(mock_offline_page_model());
+ tracker.Initialize(base::BindOnce([] {}));
EXPECT_FALSE(tracker.IsInitialized());
}
@@ -176,6 +186,7 @@ TEST_F(PrefetchedPagesTrackerImplTest,
GetPagesByNamespace(offline_pages::kSuggestedArticlesNamespace, _))
.WillOnce(SaveArg<1>(&offline_pages_callback));
PrefetchedPagesTrackerImpl tracker(mock_offline_page_model());
+ tracker.Initialize(base::BindOnce([] {}));
ASSERT_FALSE(tracker.IsInitialized());
offline_pages_callback.Run(std::vector<OfflinePageItem>());
@@ -192,8 +203,7 @@ TEST_F(PrefetchedPagesTrackerImplTest, ShouldCallCallbackAfterInitialization) {
base::MockCallback<base::OnceCallback<void()>>
mock_initialization_completed_callback;
- tracker.AddInitializationCompletedCallback(
- mock_initialization_completed_callback.Get());
+ tracker.Initialize(mock_initialization_completed_callback.Get());
EXPECT_CALL(mock_initialization_completed_callback, Run());
offline_pages_callback.Run(std::vector<OfflinePageItem>());
}
@@ -210,10 +220,8 @@ TEST_F(PrefetchedPagesTrackerImplTest,
base::MockCallback<base::OnceCallback<void()>>
first_mock_initialization_completed_callback,
second_mock_initialization_completed_callback;
- tracker.AddInitializationCompletedCallback(
- first_mock_initialization_completed_callback.Get());
- tracker.AddInitializationCompletedCallback(
- second_mock_initialization_completed_callback.Get());
+ tracker.Initialize(first_mock_initialization_completed_callback.Get());
+ tracker.Initialize(second_mock_initialization_completed_callback.Get());
EXPECT_CALL(first_mock_initialization_completed_callback, Run());
EXPECT_CALL(second_mock_initialization_completed_callback, Run());
offline_pages_callback.Run(std::vector<OfflinePageItem>());
@@ -227,13 +235,14 @@ TEST_F(PrefetchedPagesTrackerImplTest,
GetPagesByNamespace(offline_pages::kSuggestedArticlesNamespace, _))
.WillOnce(SaveArg<1>(&offline_pages_callback));
PrefetchedPagesTrackerImpl tracker(mock_offline_page_model());
+ tracker.Initialize(base::BindOnce([] {}));
+
offline_pages_callback.Run(std::vector<OfflinePageItem>());
base::MockCallback<base::OnceCallback<void()>>
mock_initialization_completed_callback;
EXPECT_CALL(mock_initialization_completed_callback, Run());
- tracker.AddInitializationCompletedCallback(
- mock_initialization_completed_callback.Get());
+ tracker.Initialize(mock_initialization_completed_callback.Get());
}
TEST_F(PrefetchedPagesTrackerImplTest,
@@ -246,12 +255,14 @@ TEST_F(PrefetchedPagesTrackerImplTest,
offline_pages::kSuggestedArticlesNamespace);
(*fake_offline_page_model()->mutable_items()) = {first_item, second_item};
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
+ tracker.Initialize(base::BindOnce([] {}));
ASSERT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
tracker.OfflinePageDeleted(offline_pages::OfflinePageModel::DeletedPageInfo(
- first_item.offline_id, first_item.client_id, /*request_origin=*/""));
+ first_item.offline_id, kSystemDownloadId, first_item.client_id,
+ /*request_origin=*/""));
// Only one offline page (out of two) has been removed, the remaining one
// should be reported here.
@@ -269,18 +280,21 @@ TEST_F(PrefetchedPagesTrackerImplTest,
offline_pages::kSuggestedArticlesNamespace);
(*fake_offline_page_model()->mutable_items()) = {first_item, second_item};
PrefetchedPagesTrackerImpl tracker(fake_offline_page_model());
+ tracker.Initialize(base::BindOnce([] {}));
ASSERT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
tracker.OfflinePageDeleted(offline_pages::OfflinePageModel::DeletedPageInfo(
- first_item.offline_id, first_item.client_id, /*request_origin=*/""));
+ first_item.offline_id, kSystemDownloadId, first_item.client_id,
+ /*request_origin=*/""));
ASSERT_TRUE(
tracker.PrefetchedOfflinePageExists(GURL("http://prefetched.com")));
tracker.OfflinePageDeleted(offline_pages::OfflinePageModel::DeletedPageInfo(
- second_item.offline_id, second_item.client_id, /*request_origin=*/""));
+ second_item.offline_id, kSystemDownloadId, second_item.client_id,
+ /*request_origin=*/""));
// All offline pages have been removed, their absence should be reported here.
EXPECT_FALSE(
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_database.cc b/chromium/components/ntp_snippets/remote/remote_suggestions_database.cc
index a126ee24a12..7e317ad9002 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_database.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_database.cc
@@ -178,10 +178,9 @@ void RemoteSuggestionsDatabase::DeleteImages(
void RemoteSuggestionsDatabase::GarbageCollectImages(
std::unique_ptr<std::set<std::string>> alive_snippet_ids) {
DCHECK(image_database_initialized_);
- image_database_->LoadKeys(
- base::Bind(&RemoteSuggestionsDatabase::DeleteUnreferencedImages,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(std::move(alive_snippet_ids))));
+ image_database_->LoadKeys(base::BindOnce(
+ &RemoteSuggestionsDatabase::DeleteUnreferencedImages,
+ weak_ptr_factory_.GetWeakPtr(), std::move(alive_snippet_ids)));
}
void RemoteSuggestionsDatabase::OnDatabaseInited(bool success) {
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher.h b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher.h
index e16dec659f4..805dabd960c 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher.h
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher.h
@@ -49,6 +49,9 @@ class RemoteSuggestionsFetcher {
// Returns the last JSON fetched from the server.
virtual const std::string& GetLastJsonForDebugging() const = 0;
+ // Returns whether the last fetch was authenticated.
+ virtual bool WasLastFetchAuthenticatedForDebugging() const = 0;
+
// Returns the URL endpoint used by the fetcher.
virtual const GURL& GetFetchUrlForDebugging() const = 0;
};
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 1150c058052..62e01526870 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc
@@ -13,12 +13,14 @@
#include "base/values.h"
#include "components/language/core/browser/url_language_histogram.h"
#include "components/ntp_snippets/category.h"
+#include "components/ntp_snippets/features.h"
#include "components/ntp_snippets/ntp_snippets_constants.h"
#include "components/ntp_snippets/user_classifier.h"
-#include "components/signin/core/browser/signin_manager_base.h"
+#include "components/variations/variations_associated_data.h"
+#include "net/base/url_util.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_status.h"
-#include "services/identity/public/cpp/primary_account_access_token_fetcher.h"
+#include "services/identity/public/cpp/identity_manager.h"
using language::UrlLanguageHistogram;
using net::HttpRequestHeaders;
@@ -33,11 +35,38 @@ using internal::JsonRequest;
namespace {
-const char kSnippetsServerNonAuthorizedFormat[] = "%s?key=%s";
+const char kApiKeyQueryParam[] = "key";
+const char kPriorityQueryParam[] = "priority";
+const char kInteractivePriority[] = "user_action";
+const char kNonInteractivePriority[] = "background_prefetch";
const char kAuthorizationRequestHeaderFormat[] = "Bearer %s";
const int kFetchTimeHistogramResolution = 5;
+// Enables appending request priority as a query parameter to the fetch url,
+// when fetching article suggestions.
+const char kAppendRequestPriorityAsQueryParameterParamName[] =
+ "append_request_priority_as_query_parameter";
+const bool kAppendRequestPriorityAsQueryParameterParamDefault = true;
+
+bool IsAppendingRequestPriorityAsQueryParameterEnabled() {
+ return variations::GetVariationParamByFeatureAsBool(
+ ntp_snippets::kArticleSuggestionsFeature,
+ kAppendRequestPriorityAsQueryParameterParamName,
+ kAppendRequestPriorityAsQueryParameterParamDefault);
+}
+
+GURL AppendPriorityQueryParameterIfEnabled(const GURL& url,
+ bool is_interactive_request) {
+ if (IsAppendingRequestPriorityAsQueryParameterEnabled()) {
+ return net::AppendQueryParameter(url, kPriorityQueryParam,
+ is_interactive_request
+ ? kInteractivePriority
+ : kNonInteractivePriority);
+ }
+ return url;
+}
+
std::string FetchResultToString(FetchResult result) {
switch (result) {
case FetchResult::SUCCESS:
@@ -124,8 +153,7 @@ void FilterCategories(FetchedCategoriesVector* categories,
} // namespace
RemoteSuggestionsFetcherImpl::RemoteSuggestionsFetcherImpl(
- SigninManagerBase* signin_manager,
- OAuth2TokenService* token_service,
+ identity::IdentityManager* identity_manager,
scoped_refptr<URLRequestContextGetter> url_request_context_getter,
PrefService* pref_service,
UrlLanguageHistogram* language_histogram,
@@ -133,15 +161,15 @@ RemoteSuggestionsFetcherImpl::RemoteSuggestionsFetcherImpl(
const GURL& api_endpoint,
const std::string& api_key,
const UserClassifier* user_classifier)
- : signin_manager_(signin_manager),
- token_service_(token_service),
+ : identity_manager_(identity_manager),
url_request_context_getter_(std::move(url_request_context_getter)),
language_histogram_(language_histogram),
parse_json_callback_(parse_json_callback),
fetch_url_(api_endpoint),
api_key_(api_key),
clock_(base::DefaultClock::GetInstance()),
- user_classifier_(user_classifier) {}
+ user_classifier_(user_classifier),
+ last_fetch_authenticated_(false) {}
RemoteSuggestionsFetcherImpl::~RemoteSuggestionsFetcherImpl() = default;
@@ -153,6 +181,10 @@ const std::string& RemoteSuggestionsFetcherImpl::GetLastJsonForDebugging()
const {
return last_fetch_json_;
}
+bool RemoteSuggestionsFetcherImpl::WasLastFetchAuthenticatedForDebugging()
+ const {
+ return last_fetch_authenticated_;
+}
const GURL& RemoteSuggestionsFetcherImpl::GetFetchUrlForDebugging() const {
return fetch_url_;
}
@@ -179,7 +211,7 @@ void RemoteSuggestionsFetcherImpl::FetchSnippets(
.SetUrlRequestContextGetter(url_request_context_getter_)
.SetUserClassifier(*user_classifier_);
- if (signin_manager_->IsAuthenticated()) {
+ if (identity_manager_->HasPrimaryAccount()) {
// Signed-in: get OAuth token --> fetch suggestions.
pending_requests_.emplace(std::move(builder), std::move(callback));
StartTokenRequest();
@@ -195,36 +227,44 @@ void RemoteSuggestionsFetcherImpl::FetchSnippetsNonAuthenticated(
if (api_key_.empty()) {
// If we don't have an API key, don't even try.
FetchFinished(OptionalFetchedCategories(), std::move(callback),
- FetchResult::MISSING_API_KEY, std::string());
+ FetchResult::MISSING_API_KEY, std::string(),
+ /*is_authenticated=*/false);
return;
}
// When not providing OAuth token, we need to pass the Google API key.
- builder.SetUrl(
- GURL(base::StringPrintf(kSnippetsServerNonAuthorizedFormat,
- fetch_url_.spec().c_str(), api_key_.c_str())));
- StartRequest(std::move(builder), std::move(callback));
+ GURL url = net::AppendQueryParameter(fetch_url_, kApiKeyQueryParam, api_key_);
+ url = AppendPriorityQueryParameterIfEnabled(url,
+ builder.is_interactive_request());
+
+ builder.SetUrl(url);
+ StartRequest(std::move(builder), std::move(callback),
+ /*is_authenticated=*/false);
}
void RemoteSuggestionsFetcherImpl::FetchSnippetsAuthenticated(
JsonRequest::Builder builder,
SnippetsAvailableCallback callback,
const std::string& oauth_access_token) {
- // TODO(jkrcal, treib): Add unit-tests for authenticated fetches.
- builder.SetUrl(fetch_url_)
- .SetAuthentication(signin_manager_->GetAuthenticatedAccountId(),
- base::StringPrintf(kAuthorizationRequestHeaderFormat,
- oauth_access_token.c_str()));
- StartRequest(std::move(builder), std::move(callback));
+ GURL url = AppendPriorityQueryParameterIfEnabled(
+ fetch_url_, builder.is_interactive_request());
+
+ builder.SetUrl(url).SetAuthentication(
+ identity_manager_->GetPrimaryAccountInfo().account_id,
+ base::StringPrintf(kAuthorizationRequestHeaderFormat,
+ oauth_access_token.c_str()));
+ StartRequest(std::move(builder), std::move(callback),
+ /*is_authenticated=*/true);
}
void RemoteSuggestionsFetcherImpl::StartRequest(
JsonRequest::Builder builder,
- SnippetsAvailableCallback callback) {
+ SnippetsAvailableCallback callback,
+ bool is_authenticated) {
std::unique_ptr<JsonRequest> request = builder.Build();
JsonRequest* raw_request = request.get();
raw_request->Start(base::BindOnce(
&RemoteSuggestionsFetcherImpl::JsonRequestDone, base::Unretained(this),
- std::move(request), std::move(callback)));
+ std::move(request), std::move(callback), is_authenticated));
}
void RemoteSuggestionsFetcherImpl::StartTokenRequest() {
@@ -234,8 +274,8 @@ void RemoteSuggestionsFetcherImpl::StartTokenRequest() {
}
OAuth2TokenService::ScopeSet scopes{kContentSuggestionsApiScope};
- token_fetcher_ = std::make_unique<identity::PrimaryAccountAccessTokenFetcher>(
- "ntp_snippets", signin_manager_, token_service_, scopes,
+ token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForPrimaryAccount(
+ "ntp_snippets", scopes,
base::BindOnce(&RemoteSuggestionsFetcherImpl::AccessTokenFetchFinished,
base::Unretained(this)),
identity::PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
@@ -281,7 +321,8 @@ void RemoteSuggestionsFetcherImpl::AccessTokenError(
std::move(builder_and_callback.second),
FetchResult::OAUTH_TOKEN_ERROR,
/*error_details=*/
- base::StringPrintf(" (%s)", error.ToString().c_str()));
+ base::StringPrintf(" (%s)", error.ToString().c_str()),
+ /*is_authenticated=*/true);
pending_requests_.pop();
}
}
@@ -289,6 +330,7 @@ void RemoteSuggestionsFetcherImpl::AccessTokenError(
void RemoteSuggestionsFetcherImpl::JsonRequestDone(
std::unique_ptr<JsonRequest> request,
SnippetsAvailableCallback callback,
+ bool is_authenticated,
std::unique_ptr<base::Value> result,
FetchResult status_code,
const std::string& error_details) {
@@ -303,7 +345,7 @@ void RemoteSuggestionsFetcherImpl::JsonRequestDone(
if (!result) {
FetchFinished(OptionalFetchedCategories(), std::move(callback), status_code,
- error_details);
+ error_details, is_authenticated);
return;
}
@@ -311,7 +353,8 @@ void RemoteSuggestionsFetcherImpl::JsonRequestDone(
if (!JsonToCategories(*result, &categories, fetch_time)) {
LOG(WARNING) << "Received invalid snippets: " << last_fetch_json_;
FetchFinished(OptionalFetchedCategories(), std::move(callback),
- FetchResult::INVALID_SNIPPET_CONTENT_ERROR, std::string());
+ FetchResult::INVALID_SNIPPET_CONTENT_ERROR, std::string(),
+ is_authenticated);
return;
}
// Filter out unwanted categories if necessary.
@@ -320,17 +363,19 @@ void RemoteSuggestionsFetcherImpl::JsonRequestDone(
FilterCategories(&categories, request->exclusive_category());
FetchFinished(std::move(categories), std::move(callback),
- FetchResult::SUCCESS, std::string());
+ FetchResult::SUCCESS, std::string(), is_authenticated);
}
void RemoteSuggestionsFetcherImpl::FetchFinished(
OptionalFetchedCategories categories,
SnippetsAvailableCallback callback,
FetchResult fetch_result,
- const std::string& error_details) {
+ const std::string& error_details,
+ bool is_authenticated) {
DCHECK(fetch_result == FetchResult::SUCCESS || !categories.has_value());
last_status_ = FetchResultToString(fetch_result) + error_details;
+ last_fetch_authenticated_ = is_authenticated;
UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult",
static_cast<int>(fetch_result),
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 0d95ca461e0..ca495747e18 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h
@@ -19,16 +19,16 @@
#include "components/ntp_snippets/remote/remote_suggestions_fetcher.h"
#include "components/ntp_snippets/remote/request_params.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/identity/public/cpp/primary_account_access_token_fetcher.h"
-class OAuth2TokenService;
class PrefService;
-class SigninManagerBase;
namespace base {
class Value;
} // namespace base
namespace identity {
+class IdentityManager;
class PrimaryAccountAccessTokenFetcher;
}
@@ -43,8 +43,7 @@ class UserClassifier;
class RemoteSuggestionsFetcherImpl : public RemoteSuggestionsFetcher {
public:
RemoteSuggestionsFetcherImpl(
- SigninManagerBase* signin_manager,
- OAuth2TokenService* token_service,
+ identity::IdentityManager* identity_manager,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
PrefService* pref_service,
language::UrlLanguageHistogram* language_histogram,
@@ -59,6 +58,7 @@ class RemoteSuggestionsFetcherImpl : public RemoteSuggestionsFetcher {
const std::string& GetLastStatusForDebugging() const override;
const std::string& GetLastJsonForDebugging() const override;
+ bool WasLastFetchAuthenticatedForDebugging() const override;
const GURL& GetFetchUrlForDebugging() const override;
// Overrides internal clock for testing purposes.
@@ -71,7 +71,8 @@ class RemoteSuggestionsFetcherImpl : public RemoteSuggestionsFetcher {
SnippetsAvailableCallback callback,
const std::string& oauth_access_token);
void StartRequest(internal::JsonRequest::Builder builder,
- SnippetsAvailableCallback callback);
+ SnippetsAvailableCallback callback,
+ bool is_authenticated);
void StartTokenRequest();
@@ -81,17 +82,18 @@ class RemoteSuggestionsFetcherImpl : public RemoteSuggestionsFetcher {
void JsonRequestDone(std::unique_ptr<internal::JsonRequest> request,
SnippetsAvailableCallback callback,
+ bool is_authenticated,
std::unique_ptr<base::Value> result,
internal::FetchResult status_code,
const std::string& error_details);
void FetchFinished(OptionalFetchedCategories categories,
SnippetsAvailableCallback callback,
internal::FetchResult status_code,
- const std::string& error_details);
+ const std::string& error_details,
+ bool is_authenticated);
// Authentication for signed-in users.
- SigninManagerBase* signin_manager_;
- OAuth2TokenService* token_service_;
+ identity::IdentityManager* identity_manager_;
std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher> token_fetcher_;
@@ -123,6 +125,7 @@ class RemoteSuggestionsFetcherImpl : public RemoteSuggestionsFetcher {
// Info on the last finished fetch.
std::string last_status_;
std::string last_fetch_json_;
+ bool last_fetch_authenticated_;
DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsFetcherImpl);
};
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 67d205ba0a5..f748abd2d6c 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
@@ -10,7 +10,9 @@
#include "base/containers/circular_deque.h"
#include "base/json/json_reader.h"
+#include "base/message_loop/message_loop.h"
#include "base/optional.h"
+#include "base/strings/stringprintf.h"
#include "base/test/histogram_tester.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -26,14 +28,12 @@
#include "components/ntp_snippets/remote/test_utils.h"
#include "components/ntp_snippets/user_classifier.h"
#include "components/prefs/testing_pref_service.h"
-#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
-#include "components/signin/core/browser/fake_signin_manager.h"
#include "components/variations/entropy_provider.h"
#include "components/variations/variations_params_manager.h"
-#include "google_apis/gaia/fake_oauth2_token_service_delegate.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_test_util.h"
+#include "services/identity/public/cpp/identity_test_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -53,12 +53,6 @@ using testing::Property;
using testing::StartsWith;
const char kAPIKey[] = "fakeAPIkey";
-const char kTestChromeContentSuggestionsSignedOutUrl[] =
- "https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
- "fetch?key=fakeAPIkey";
-const char kTestChromeContentSuggestionsSignedInUrl[] =
- "https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/fetch";
-
const char kTestEmail[] = "foo@bar.com";
// Artificial time delay for JSON parsing.
@@ -259,19 +253,18 @@ void ParseJsonDelayed(const std::string& json,
} // namespace
-class RemoteSuggestionsFetcherImplTestBase
- : public testing::Test,
- public OAuth2TokenService::DiagnosticsObserver {
+class RemoteSuggestionsFetcherImplTest : public testing::Test {
public:
- explicit RemoteSuggestionsFetcherImplTestBase(const GURL& gurl)
+ RemoteSuggestionsFetcherImplTest()
: default_variation_params_(
- {{"send_top_languages", "true"}, {"send_user_class", "true"}}),
+ {{"send_top_languages", "true"},
+ {"send_user_class", "true"},
+ {"append_request_priority_as_query_parameter", "true"}}),
params_manager_(ntp_snippets::kArticleSuggestionsFeature.name,
default_variation_params_,
{ntp_snippets::kArticleSuggestionsFeature.name}),
mock_task_runner_(new base::TestMockTimeTaskRunner(
- base::TestMockTimeTaskRunner::Type::kBoundToThread)),
- test_url_(gurl) {
+ base::TestMockTimeTaskRunner::Type::kBoundToThread)) {
UserClassifier::RegisterProfilePrefs(utils_.pref_service()->registry());
user_classifier_ = std::make_unique<UserClassifier>(
utils_.pref_service(), base::DefaultClock::GetInstance());
@@ -280,10 +273,7 @@ class RemoteSuggestionsFetcherImplTestBase
ResetFetcher();
}
- ~RemoteSuggestionsFetcherImplTestBase() override {
- if (fake_token_service_)
- fake_token_service_->RemoveDiagnosticsObserver(this);
- }
+ ~RemoteSuggestionsFetcherImplTest() override {}
void ResetFetcher() { ResetFetcherWithAPIKey(kAPIKey); }
@@ -291,16 +281,8 @@ class RemoteSuggestionsFetcherImplTestBase
scoped_refptr<net::TestURLRequestContextGetter> request_context_getter =
new net::TestURLRequestContextGetter(mock_task_runner_.get());
- if (fake_token_service_)
- fake_token_service_->RemoveDiagnosticsObserver(this);
- fake_token_service_ = std::make_unique<FakeProfileOAuth2TokenService>(
- std::make_unique<FakeOAuth2TokenServiceDelegate>(
- request_context_getter.get()));
-
- fake_token_service_->AddDiagnosticsObserver(this);
-
fetcher_ = std::make_unique<RemoteSuggestionsFetcherImpl>(
- utils_.fake_signin_manager(), fake_token_service_.get(),
+ identity_test_env_.identity_manager(),
std::move(request_context_getter), utils_.pref_service(), nullptr,
base::BindRepeating(&ParseJsonDelayed),
GetFetchEndpoint(version_info::Channel::STABLE), api_key,
@@ -310,28 +292,7 @@ class RemoteSuggestionsFetcherImplTestBase
fetcher_->SetClockForTesting(clock_.get());
}
- void SignIn() {
-#if defined(OS_CHROMEOS)
- utils_.fake_signin_manager()->SignIn(kTestEmail);
-#else
- utils_.fake_signin_manager()->SignIn(kTestEmail, "user", "password");
-#endif
- }
-
- void IssueRefreshToken() {
- fake_token_service_->GetDelegate()->UpdateCredentials(kTestEmail, "token");
- }
-
- void IssueOAuth2Token() {
- fake_token_service_->IssueAllTokensForAccount(kTestEmail, "access_token",
- base::Time::Max());
- }
-
- void CancelOAuth2TokenRequests() {
- fake_token_service_->IssueErrorForAllPendingRequestsForAccount(
- kTestEmail, GoogleServiceAuthError(
- GoogleServiceAuthError::State::REQUEST_CANCELED));
- }
+ void SignIn() { identity_test_env_.MakePrimaryAccountAvailable(kTestEmail); }
RemoteSuggestionsFetcher::SnippetsAvailableCallback
ToSnippetsAvailableCallback(MockSnippetsAvailableCallback* callback) {
@@ -373,30 +334,20 @@ class RemoteSuggestionsFetcherImplTestBase
{ntp_snippets::kArticleSuggestionsFeature.name});
}
- void SetFakeResponse(const std::string& response_data,
+ void SetFakeResponse(const GURL& request_url,
+ const std::string& response_data,
net::HttpStatusCode response_code,
net::URLRequestStatus::Status status) {
InitFakeURLFetcherFactory();
- fake_url_fetcher_factory_->SetFakeResponse(test_url_, response_data,
+ fake_url_fetcher_factory_->SetFakeResponse(request_url, response_data,
response_code, status);
}
- void set_on_access_token_request_callback(base::OnceClosure callback) {
- on_access_token_request_callback_ = std::move(callback);
- }
protected:
std::map<std::string, std::string> default_variation_params_;
+ identity::IdentityTestEnvironment identity_test_env_;
private:
- // OAuth2TokenService::DiagnosticsObserver:
- void OnAccessTokenRequested(
- const std::string& account_id,
- const std::string& consumer_id,
- const OAuth2TokenService::ScopeSet& scopes) override {
- if (on_access_token_request_callback_)
- std::move(on_access_token_request_callback_).Run();
- }
-
// TODO(tzik): Remove |clock_| after updating GetMockTickClock to own the
// instance. http://crbug.com/789079
std::unique_ptr<base::Clock> clock_;
@@ -407,39 +358,16 @@ class RemoteSuggestionsFetcherImplTestBase
FailingFakeURLFetcherFactory failing_url_fetcher_factory_;
// Initialized lazily in SetFakeResponse().
std::unique_ptr<net::FakeURLFetcherFactory> fake_url_fetcher_factory_;
- std::unique_ptr<FakeProfileOAuth2TokenService> fake_token_service_;
std::unique_ptr<RemoteSuggestionsFetcherImpl> fetcher_;
std::unique_ptr<UserClassifier> user_classifier_;
MockSnippetsAvailableCallback mock_callback_;
- const GURL test_url_;
+ GURL test_url_;
base::HistogramTester histogram_tester_;
- base::OnceClosure on_access_token_request_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsFetcherImplTestBase);
-};
-
-class RemoteSuggestionsSignedOutFetcherTest
- : public RemoteSuggestionsFetcherImplTestBase {
- public:
- RemoteSuggestionsSignedOutFetcherTest()
- : RemoteSuggestionsFetcherImplTestBase(
- GURL(kTestChromeContentSuggestionsSignedOutUrl)) {}
-};
-// TODO(jkrcal): Investigate whether the "authentication in progress" case can
-// ever happen (see discussion on https://codereview.chromium.org/2582573002),
-// and if so, add unit-tests for it. This will require more changes (instead of
-// FakeSigninManagerBase use FakeSigninManager which does not exist on
-// ChromeOS). crbug.com/688310
-class RemoteSuggestionsSignedInFetcherTest
- : public RemoteSuggestionsFetcherImplTestBase {
- public:
- RemoteSuggestionsSignedInFetcherTest()
- : RemoteSuggestionsFetcherImplTestBase(
- GURL(kTestChromeContentSuggestionsSignedInUrl)) {}
+ DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsFetcherImplTest);
};
-TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldNotFetchOnCreation) {
+TEST_F(RemoteSuggestionsFetcherImplTest, ShouldNotFetchOnCreation) {
// The lack of registered baked in responses would cause any fetch to fail.
FastForwardUntilNoTasksRemain();
EXPECT_THAT(histogram_tester().GetAllSamples(
@@ -450,7 +378,7 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldNotFetchOnCreation) {
EXPECT_THAT(fetcher().GetLastStatusForDebugging(), IsEmpty());
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldFetchSuccessfully) {
+TEST_F(RemoteSuggestionsFetcherImplTest, ShouldFetchSuccessfully) {
const std::string kJsonStr =
"{\"categories\" : [{"
" \"id\": 1,"
@@ -468,8 +396,10 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldFetchSuccessfully) {
" \"faviconUrl\" : \"http://localhost/favicon.ico\" "
" }]"
"}]}";
- SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS);
EXPECT_CALL(mock_callback(),
Run(Property(&Status::IsSuccess, true),
/*fetched_categories=*/AllOf(
@@ -488,12 +418,51 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldFetchSuccessfully) {
/*count=*/1)));
}
-TEST_F(RemoteSuggestionsSignedInFetcherTest, ShouldFetchSuccessfully) {
- base::RunLoop run_loop;
- set_on_access_token_request_callback(run_loop.QuitClosure());
+TEST_F(RemoteSuggestionsFetcherImplTest, ShouldExposeRequestPriorityInUrl) {
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=background_prefetch"),
+ /*response_data=*/"{\"categories\" : []}", net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
+ EXPECT_CALL(mock_callback(), Run(Property(&Status::IsSuccess, true),
+ /*fetched_categories=*/_));
+
+ RequestParams params = test_params();
+ params.interactive_request = false;
+ fetcher().FetchSnippets(params,
+ ToSnippetsAvailableCallback(&mock_callback()));
+
+ // Wait for the fake response.
+ FastForwardUntilNoTasksRemain();
+
+ EXPECT_THAT(fetcher().GetLastStatusForDebugging(), Eq("OK"));
+}
+
+TEST_F(RemoteSuggestionsFetcherImplTest,
+ ShouldNotExposeRequestPriorityInUrlWhenDisabled) {
+ SetVariationParam("append_request_priority_as_query_parameter", "false");
+
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey"),
+ /*response_data=*/"{\"categories\" : []}", net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
+ EXPECT_CALL(mock_callback(), Run(Property(&Status::IsSuccess, true),
+ /*fetched_categories=*/_));
+
+ RequestParams params = test_params();
+ params.interactive_request = false;
+ fetcher().FetchSnippets(params,
+ ToSnippetsAvailableCallback(&mock_callback()));
+
+ // Wait for the fake response.
+ FastForwardUntilNoTasksRemain();
+
+ EXPECT_THAT(fetcher().GetLastStatusForDebugging(), Eq("OK"));
+}
+TEST_F(RemoteSuggestionsFetcherImplTest, ShouldFetchSuccessfullyWhenSignedIn) {
SignIn();
- IssueRefreshToken();
const std::string kJsonStr =
"{\"categories\" : [{"
@@ -512,8 +481,10 @@ TEST_F(RemoteSuggestionsSignedInFetcherTest, ShouldFetchSuccessfully) {
" \"faviconUrl\" : \"http://localhost/favicon.ico\" "
" }]"
"}]}";
- SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?priority=user_action"),
+ /*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS);
EXPECT_CALL(mock_callback(),
Run(Property(&Status::IsSuccess, true),
/*fetched_categories=*/AllOf(
@@ -523,9 +494,9 @@ TEST_F(RemoteSuggestionsSignedInFetcherTest, ShouldFetchSuccessfully) {
fetcher().FetchSnippets(test_params(),
ToSnippetsAvailableCallback(&mock_callback()));
- run_loop.Run();
+ identity_test_env_.WaitForAccessTokenRequestAndRespondWithToken(
+ "access_token", base::Time::Max());
- IssueOAuth2Token();
// Wait for the fake response.
FastForwardUntilNoTasksRemain();
@@ -539,12 +510,63 @@ TEST_F(RemoteSuggestionsSignedInFetcherTest, ShouldFetchSuccessfully) {
/*count=*/1)));
}
-TEST_F(RemoteSuggestionsSignedInFetcherTest, ShouldRetryWhenOAuthCancelled) {
- base::RunLoop run_loop;
- set_on_access_token_request_callback(run_loop.QuitClosure());
+TEST_F(RemoteSuggestionsFetcherImplTest,
+ ShouldExposeRequestPriorityInUrlWhenSignedIn) {
+ SignIn();
+
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?priority=background_prefetch"),
+ /*response_data=*/"{\"categories\" : []}", net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
+ EXPECT_CALL(mock_callback(), Run(Property(&Status::IsSuccess, true),
+ /*fetched_categories=*/_));
+
+ RequestParams params = test_params();
+ params.interactive_request = false;
+ fetcher().FetchSnippets(params,
+ ToSnippetsAvailableCallback(&mock_callback()));
+
+ identity_test_env_.WaitForAccessTokenRequestAndRespondWithToken(
+ "access_token", base::Time::Max());
+
+ // Wait for the fake response.
+ FastForwardUntilNoTasksRemain();
+
+ EXPECT_THAT(fetcher().GetLastStatusForDebugging(), Eq("OK"));
+}
+
+TEST_F(RemoteSuggestionsFetcherImplTest,
+ ShouldNotExposeRequestPriorityInUrlWhenDisabledWhenSignedIn) {
+ SetVariationParam("append_request_priority_as_query_parameter", "false");
SignIn();
- IssueRefreshToken();
+
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch"),
+ /*response_data=*/"{\"categories\" : []}", net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
+ EXPECT_CALL(mock_callback(), Run(Property(&Status::IsSuccess, true),
+ /*fetched_categories=*/_));
+
+ RequestParams params = test_params();
+ params.interactive_request = false;
+ fetcher().FetchSnippets(params,
+ ToSnippetsAvailableCallback(&mock_callback()));
+
+ identity_test_env_.WaitForAccessTokenRequestAndRespondWithToken(
+ "access_token", base::Time::Max());
+
+ // Wait for the fake response.
+ FastForwardUntilNoTasksRemain();
+
+ EXPECT_THAT(fetcher().GetLastStatusForDebugging(), Eq("OK"));
+}
+
+TEST_F(RemoteSuggestionsFetcherImplTest,
+ ShouldRetryWhenOAuthCancelledWhenSignedIn) {
+ SignIn();
const std::string kJsonStr =
"{\"categories\" : [{"
@@ -563,8 +585,10 @@ TEST_F(RemoteSuggestionsSignedInFetcherTest, ShouldRetryWhenOAuthCancelled) {
" \"faviconUrl\" : \"http://localhost/favicon.ico\" "
" }]"
"}]}";
- SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?priority=user_action"),
+ /*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS);
EXPECT_CALL(mock_callback(),
Run(Property(&Status::IsSuccess, true),
/*fetched_categories=*/AllOf(
@@ -574,20 +598,15 @@ TEST_F(RemoteSuggestionsSignedInFetcherTest, ShouldRetryWhenOAuthCancelled) {
fetcher().FetchSnippets(test_params(),
ToSnippetsAvailableCallback(&mock_callback()));
- // Wait for the first access token request to be made.
- run_loop.Run();
-
- // Before cancelling the outstanding access token request, prepare to wait for
- // the second access token request to be made in response to the cancellation.
- base::RunLoop run_loop2;
- set_on_access_token_request_callback(run_loop2.QuitClosure());
-
- CancelOAuth2TokenRequests();
+ // Cancel the first access token request that's made.
+ identity_test_env_.WaitForAccessTokenRequestAndRespondWithError(
+ GoogleServiceAuthError(GoogleServiceAuthError::State::REQUEST_CANCELED));
- // Wait for the second access token request to be made.
- run_loop2.Run();
+ // RemoteSuggestionsFetcher should retry fetching an access token if the first
+ // attempt is cancelled. Respond with a valid access token on the retry.
+ identity_test_env_.WaitForAccessTokenRequestAndRespondWithToken(
+ "access_token", base::Time::Max());
- IssueOAuth2Token();
// Wait for the fake response.
FastForwardUntilNoTasksRemain();
@@ -601,14 +620,16 @@ TEST_F(RemoteSuggestionsSignedInFetcherTest, ShouldRetryWhenOAuthCancelled) {
/*count=*/1)));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest, EmptyCategoryIsOK) {
+TEST_F(RemoteSuggestionsFetcherImplTest, EmptyCategoryIsOK) {
const std::string kJsonStr =
"{\"categories\" : [{"
" \"id\": 1,"
" \"localizedTitle\": \"Articles for You\""
"}]}";
- SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS);
EXPECT_CALL(mock_callback(),
Run(Property(&Status::IsSuccess, true),
/*fetched_categories=*/IsEmptyArticleList()));
@@ -625,7 +646,7 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, EmptyCategoryIsOK) {
/*count=*/1)));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest, ServerCategories) {
+TEST_F(RemoteSuggestionsFetcherImplTest, ServerCategories) {
const std::string kJsonStr =
"{\"categories\" : [{"
" \"id\": 1,"
@@ -659,8 +680,10 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, ServerCategories) {
" \"faviconUrl\" : \"http://localhost/favicon.ico\" "
" }]"
"}]}";
- SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS);
RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories;
EXPECT_CALL(mock_callback(),
Run(Property(&Status::IsSuccess, true), /*fetched_categories=*/_))
@@ -698,7 +721,7 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, ServerCategories) {
/*count=*/1)));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest,
+TEST_F(RemoteSuggestionsFetcherImplTest,
SupportMissingAllowFetchingMoreResultsOption) {
// This tests makes sure we handle the missing option although it's required
// by the interface. It's just that the Service doesn't follow that
@@ -721,8 +744,10 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
" \"faviconUrl\" : \"http://localhost/favicon.ico\" "
" }]"
"}]}";
- SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS);
RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories;
EXPECT_CALL(mock_callback(),
Run(Property(&Status::IsSuccess, true), /*fetched_categories=*/_))
@@ -739,7 +764,7 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
Eq(base::UTF8ToUTF16("Articles for Me")));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest, ExclusiveCategoryOnly) {
+TEST_F(RemoteSuggestionsFetcherImplTest, ExclusiveCategoryOnly) {
const std::string kJsonStr =
"{\"categories\" : [{"
" \"id\": 1,"
@@ -787,8 +812,10 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, ExclusiveCategoryOnly) {
" \"faviconUrl\" : \"http://localhost/favicon.ico\" "
" }]"
"}]}";
- SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS);
RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories;
EXPECT_CALL(mock_callback(),
Run(Property(&Status::IsSuccess, true), /*fetched_categories=*/_))
@@ -811,7 +838,7 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, ExclusiveCategoryOnly) {
Eq("http://localhost/foo2"));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldNotFetchWithoutApiKey) {
+TEST_F(RemoteSuggestionsFetcherImplTest, ShouldNotFetchWithoutApiKey) {
ResetFetcherWithAPIKey(std::string());
EXPECT_CALL(
@@ -833,11 +860,12 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldNotFetchWithoutApiKey) {
IsEmpty());
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest,
- ShouldFetchSuccessfullyEmptyList) {
+TEST_F(RemoteSuggestionsFetcherImplTest, ShouldFetchSuccessfullyEmptyList) {
const std::string kJsonStr = "{\"categories\": []}";
- SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS);
EXPECT_CALL(mock_callback(),
Run(Property(&Status::IsSuccess, true),
/*fetched_categories=*/IsEmptyCategoriesList()));
@@ -854,7 +882,7 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
ElementsAre(base::Bucket(/*min=*/200, /*count=*/1)));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest, RetryOnInteractiveRequests) {
+TEST_F(RemoteSuggestionsFetcherImplTest, RetryOnInteractiveRequests) {
DelegateCallingTestURLFetcherFactory fetcher_factory;
RequestParams params = test_params();
params.interactive_request = true;
@@ -867,7 +895,7 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, RetryOnInteractiveRequests) {
EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(2));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest,
+TEST_F(RemoteSuggestionsFetcherImplTest,
RetriesConfigurableOnNonInteractiveRequests) {
struct ExpectationForVariationParam {
std::string param_value;
@@ -897,9 +925,12 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
}
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldReportUrlStatusError) {
- SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND,
- net::URLRequestStatus::FAILED);
+TEST_F(RemoteSuggestionsFetcherImplTest, ShouldReportUrlStatusError) {
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/std::string(), net::HTTP_NOT_FOUND,
+ net::URLRequestStatus::FAILED);
EXPECT_CALL(
mock_callback(),
Run(Field(&Status::code, StatusCode::TEMPORARY_ERROR),
@@ -922,9 +953,12 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldReportUrlStatusError) {
Not(IsEmpty()));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldReportHttpError) {
- SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND,
- net::URLRequestStatus::SUCCESS);
+TEST_F(RemoteSuggestionsFetcherImplTest, ShouldReportHttpError) {
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/std::string(), net::HTTP_NOT_FOUND,
+ net::URLRequestStatus::SUCCESS);
EXPECT_CALL(
mock_callback(),
Run(Field(&Status::code, StatusCode::TEMPORARY_ERROR),
@@ -945,10 +979,13 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldReportHttpError) {
Not(IsEmpty()));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldReportJsonError) {
+TEST_F(RemoteSuggestionsFetcherImplTest, ShouldReportJsonError) {
const std::string kInvalidJsonStr = "{ \"recos\": []";
- SetFakeResponse(/*response_data=*/kInvalidJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/kInvalidJsonStr, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
EXPECT_CALL(
mock_callback(),
Run(Field(&Status::code, StatusCode::TEMPORARY_ERROR),
@@ -972,10 +1009,13 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldReportJsonError) {
/*count=*/1)));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest,
+TEST_F(RemoteSuggestionsFetcherImplTest,
ShouldReportJsonErrorForEmptyResponse) {
- SetFakeResponse(/*response_data=*/std::string(), net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/std::string(), net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
EXPECT_CALL(
mock_callback(),
Run(Field(&Status::code, StatusCode::TEMPORARY_ERROR),
@@ -994,11 +1034,13 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
ElementsAre(base::Bucket(/*min=*/200, /*count=*/1)));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldReportInvalidListError) {
+TEST_F(RemoteSuggestionsFetcherImplTest, ShouldReportInvalidListError) {
const std::string kJsonStr =
"{\"recos\": [{ \"contentInfo\": { \"foo\" : \"bar\" }}]}";
- SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS);
EXPECT_CALL(
mock_callback(),
Run(Field(&Status::code, StatusCode::TEMPORARY_ERROR),
@@ -1021,7 +1063,7 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldReportInvalidListError) {
Not(IsEmpty()));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest,
+TEST_F(RemoteSuggestionsFetcherImplTest,
ShouldReportInvalidListErrorForIncompleteSuggestionButValidJson) {
// This is valid json, but it does not represent a valid suggestion
// (fullPageUrl is missing).
@@ -1042,8 +1084,11 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
" \"faviconUrl\" : \"http://localhost/favicon.ico\" "
" }]"
"}]}";
- SetFakeResponse(/*response_data=*/kValidJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/kValidJsonStr, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
EXPECT_CALL(
mock_callback(),
Run(Field(&Status::code, StatusCode::TEMPORARY_ERROR),
@@ -1065,7 +1110,7 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
Not(IsEmpty()));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest,
+TEST_F(RemoteSuggestionsFetcherImplTest,
ShouldReportInvalidListErrorForInvalidTimestampButValidJson) {
// This is valid json, but it does not represent a valid suggestion
// (creationTime is invalid).
@@ -1086,8 +1131,11 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
" \"faviconUrl\" : \"http://localhost/favicon.ico\" "
" }]"
"}]}";
- SetFakeResponse(/*response_data=*/kValidJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/kValidJsonStr, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
EXPECT_CALL(
mock_callback(),
Run(Field(&Status::code, StatusCode::TEMPORARY_ERROR),
@@ -1101,7 +1149,7 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
StartsWith("Invalid / empty list"));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest,
+TEST_F(RemoteSuggestionsFetcherImplTest,
ShouldReportInvalidListErrorForInvalidUrlButValidJson) {
// This is valid json, but it does not represent a valid suggestion
// (URL is invalid).
@@ -1122,8 +1170,11 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
" \"faviconUrl\" : \"http://localhost/favicon.ico\" "
" }]"
"}]}";
- SetFakeResponse(/*response_data=*/kValidJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/kValidJsonStr, net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
EXPECT_CALL(
mock_callback(),
Run(Field(&Status::code, StatusCode::TEMPORARY_ERROR),
@@ -1137,10 +1188,13 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
StartsWith("Invalid / empty list"));
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest,
+TEST_F(RemoteSuggestionsFetcherImplTest,
ShouldReportRequestFailureAsTemporaryError) {
- SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND,
- net::URLRequestStatus::FAILED);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/std::string(), net::HTTP_NOT_FOUND,
+ net::URLRequestStatus::FAILED);
EXPECT_CALL(
mock_callback(),
Run(Field(&Status::code, StatusCode::TEMPORARY_ERROR),
@@ -1154,7 +1208,7 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
// This test actually verifies that the test setup itself is sane, to prevent
// hard-to-reproduce test failures.
-TEST_F(RemoteSuggestionsSignedOutFetcherTest,
+TEST_F(RemoteSuggestionsFetcherImplTest,
ShouldReportHttpErrorForMissingBakedResponse) {
InitFakeURLFetcherFactory();
EXPECT_CALL(
@@ -1168,10 +1222,12 @@ TEST_F(RemoteSuggestionsSignedOutFetcherTest,
FastForwardUntilNoTasksRemain();
}
-TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldProcessConcurrentFetches) {
+TEST_F(RemoteSuggestionsFetcherImplTest, ShouldProcessConcurrentFetches) {
const std::string kJsonStr = "{ \"categories\": [] }";
- SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
- net::URLRequestStatus::SUCCESS);
+ SetFakeResponse(
+ GURL("https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/"
+ "fetch?key=fakeAPIkey&priority=user_action"),
+ /*response_data=*/kJsonStr, net::HTTP_OK, net::URLRequestStatus::SUCCESS);
EXPECT_CALL(mock_callback(),
Run(Property(&Status::IsSuccess, true),
/*fetched_categories=*/IsEmptyCategoriesList()))
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 4b922596626..0035b61911b 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
@@ -390,7 +390,8 @@ RemoteSuggestionsProviderImpl::RemoteSuggestionsProviderImpl(
breaking_news_raw_data_provider_(
std::move(breaking_news_raw_data_provider)),
debug_logger_(debug_logger),
- fetch_timeout_timer_(std::move(fetch_timeout_timer)) {
+ fetch_timeout_timer_(std::move(fetch_timeout_timer)),
+ request_status_(FetchRequestStatus::NONE) {
DCHECK(debug_logger_);
DCHECK(fetch_timeout_timer_);
RestoreCategoriesFromPrefs();
@@ -572,6 +573,14 @@ void RemoteSuggestionsProviderImpl::FetchSuggestions(
}
return;
}
+ if (request_status_ == FetchRequestStatus::NONE) {
+ // We cannot rule out concurrent requests although they are rare as the user
+ // has to trigger ReloadSuggestions() while the scheduler decides for a
+ // background fetch. Although preventing concurrent fetches would be
+ // desireable, it's not worth the effort (also see TODO() in
+ // OnFetchFinished()).
+ request_status_ = FetchRequestStatus::IN_PROGRESS;
+ }
// |count_to_fetch| is actually ignored, because the server does not support
// this functionality.
@@ -683,7 +692,8 @@ void RemoteSuggestionsProviderImpl::
auto articles_it = category_contents_.find(articles_category_);
DCHECK(articles_it != category_contents_.end());
CategoryContent& content = articles_it->second;
- DCHECK_EQ(content.status, CategoryStatus::AVAILABLE_LOADING);
+ DCHECK(content.status == CategoryStatus::AVAILABLE_LOADING ||
+ content.status == CategoryStatus::CATEGORY_EXPLICITLY_DISABLED);
UpdateCategoryStatus(articles_it->first, CategoryStatus::AVAILABLE);
// TODO(jkrcal): Technically, we have no new suggestions; we should not
// notify. This is a work-around before crbug.com/768410 gets fixed.
@@ -724,6 +734,19 @@ void RemoteSuggestionsProviderImpl::ClearHistory(
// because it is not known which history entries were used for the suggestions
// personalization.
ClearHistoryDependentState();
+ if (request_status_ == FetchRequestStatus::IN_PROGRESS ||
+ request_status_ == FetchRequestStatus::IN_PROGRESS_NEEDS_REFETCH) {
+ request_status_ = FetchRequestStatus::IN_PROGRESS_CANCELED;
+ }
+}
+
+void RemoteSuggestionsProviderImpl::ClearCachedSuggestions() {
+ ClearCachedSuggestionsImpl();
+ if (request_status_ == FetchRequestStatus::IN_PROGRESS) {
+ // Called by external cache-cleared trigger. As this can be caused by
+ // language change, we need to refetch a potentiall ongoing fetch.
+ request_status_ = FetchRequestStatus::IN_PROGRESS_NEEDS_REFETCH;
+ }
}
void RemoteSuggestionsProviderImpl::OnSignInStateChanged(bool has_signed_in) {
@@ -897,12 +920,31 @@ void RemoteSuggestionsProviderImpl::OnFetchFinished(
RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories) {
debug_logger_->Log(FROM_HERE, /*message=*/std::string());
+ FetchRequestStatus request_status = request_status_;
+ // TODO(jkrcal): This is potentially incorrect if there is another concurrent
+ // request in progress; when it finishes we will treat it as a standard
+ // request even though it may need to be refetched/disregarded. Even though
+ // the scheduler never triggers two concurrent requests, the user can trigger
+ // the second request via the UI. If cache/history gets cleared before neither
+ // of the two finishes, we can get outdated results afterwards. Low chance &
+ // low risk, feels safe to ignore.
+ request_status_ = FetchRequestStatus::NONE;
+
if (!ready()) {
// TODO(tschumann): What happens if this was a user-triggered, interactive
// request? Is the UI waiting indefinitely now?
return;
}
+ if (request_status == FetchRequestStatus::IN_PROGRESS_NEEDS_REFETCH) {
+ // Disregard the results and start a fetch again.
+ FetchSuggestions(interactive_request, std::move(callback));
+ return;
+ } else if (request_status == FetchRequestStatus::IN_PROGRESS_CANCELED) {
+ // Disregard the results.
+ return;
+ }
+
if (!status.IsSuccess()) {
if (callback) {
std::move(callback).Run(status);
@@ -913,11 +955,10 @@ void RemoteSuggestionsProviderImpl::OnFetchFinished(
if (IsKeepingPrefetchedSuggestionsEnabled() && prefetched_pages_tracker_ &&
!prefetched_pages_tracker_->IsInitialized()) {
// Wait until the tracker is initialized.
- prefetched_pages_tracker_->AddInitializationCompletedCallback(
- base::BindOnce(&RemoteSuggestionsProviderImpl::OnFetchFinished,
- base::Unretained(this), std::move(callback),
- interactive_request, status,
- std::move(fetched_categories)));
+ prefetched_pages_tracker_->Initialize(base::BindOnce(
+ &RemoteSuggestionsProviderImpl::OnFetchFinished, base::Unretained(this),
+ std::move(callback), interactive_request, status,
+ std::move(fetched_categories)));
return;
}
@@ -1333,16 +1374,18 @@ void RemoteSuggestionsProviderImpl::ClearHistoryDependentState() {
return;
}
+ debug_logger_->Log(FROM_HERE, /*message=*/std::string());
NukeAllSuggestions();
remote_suggestions_scheduler_->OnHistoryCleared();
}
-void RemoteSuggestionsProviderImpl::ClearCachedSuggestions() {
+void RemoteSuggestionsProviderImpl::ClearCachedSuggestionsImpl() {
if (!initialized()) {
clear_cached_suggestions_when_initialized_ = true;
return;
}
+ debug_logger_->Log(FROM_HERE, /*message=*/std::string());
NukeAllSuggestions();
remote_suggestions_scheduler_->OnSuggestionsCleared();
}
@@ -1469,7 +1512,10 @@ void RemoteSuggestionsProviderImpl::OnStatusChanged(
DCHECK(state_ == State::READY);
// Clear nonpersonalized suggestions (and notify the scheduler there are
// no suggestions).
- ClearCachedSuggestions();
+ ClearCachedSuggestionsImpl();
+ if (request_status_ == FetchRequestStatus::IN_PROGRESS) {
+ request_status_ = FetchRequestStatus::IN_PROGRESS_NEEDS_REFETCH;
+ }
} else {
EnterState(State::READY);
}
@@ -1480,7 +1526,10 @@ void RemoteSuggestionsProviderImpl::OnStatusChanged(
DCHECK(state_ == State::READY);
// Clear personalized suggestions (and notify the scheduler there are
// no suggestions).
- ClearCachedSuggestions();
+ ClearCachedSuggestionsImpl();
+ if (request_status_ == FetchRequestStatus::IN_PROGRESS) {
+ request_status_ = FetchRequestStatus::IN_PROGRESS_NEEDS_REFETCH;
+ }
} else {
EnterState(State::READY);
}
@@ -1521,7 +1570,7 @@ void RemoteSuggestionsProviderImpl::EnterState(State state) {
UpdateAllCategoryStatus(CategoryStatus::AVAILABLE);
if (clear_cached_suggestions_when_initialized_) {
- ClearCachedSuggestions();
+ ClearCachedSuggestionsImpl();
clear_cached_suggestions_when_initialized_ = false;
}
if (clear_history_dependent_state_when_initialized_) {
@@ -1547,7 +1596,7 @@ void RemoteSuggestionsProviderImpl::EnterState(State state) {
clear_history_dependent_state_when_initialized_ = false;
ClearHistoryDependentState();
}
- ClearCachedSuggestions();
+ ClearCachedSuggestionsImpl();
clear_cached_suggestions_when_initialized_ = false;
if (breaking_news_raw_data_provider_ &&
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 a8e67b8aa31..46a367e7ead 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.h
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.h
@@ -161,6 +161,10 @@ class RemoteSuggestionsProviderImpl final : public RemoteSuggestionsProvider {
CallsSchedulerWhenSignedIn);
FRIEND_TEST_ALL_PREFIXES(RemoteSuggestionsProviderImplTest,
CallsSchedulerWhenSignedOut);
+ FRIEND_TEST_ALL_PREFIXES(RemoteSuggestionsProviderImplTest,
+ RestartsFetchWhenSignedInWhileFetching);
+ FRIEND_TEST_ALL_PREFIXES(RemoteSuggestionsProviderImplTest,
+ ShouldHandleCategoryDisabledBeforeTimeout);
FRIEND_TEST_ALL_PREFIXES(
RemoteSuggestionsProviderImplTest,
ShouldNotSetExclusiveCategoryWhenFetchingSuggestions);
@@ -206,6 +210,25 @@ class RemoteSuggestionsProviderImpl final : public RemoteSuggestionsProvider {
COUNT
};
+ // Documents the status of the ongoing request and what action should be taken
+ // on completion.
+ enum class FetchRequestStatus {
+ // There is no request in progress for remote suggestions.
+ NONE,
+
+ // There is a valid request in progress that should be treated normally on
+ // completion.
+ IN_PROGRESS,
+
+ // There is a canceled request in progress. The response should be ignored
+ // when it arrives.
+ IN_PROGRESS_CANCELED,
+
+ // There is an invalidated request in progress. On completion, we should
+ // ignore the response and initiate a new fetch (with updated parameters).
+ IN_PROGRESS_NEEDS_REFETCH
+ };
+
struct CategoryContent {
// The current status of the category.
CategoryStatus status = CategoryStatus::INITIALIZING;
@@ -333,6 +356,9 @@ class RemoteSuggestionsProviderImpl final : public RemoteSuggestionsProvider {
// Clears suggestions because any history item has been removed.
void ClearHistoryDependentState();
+ // Clears the cached suggestions
+ void ClearCachedSuggestionsImpl();
+
// Clears all stored suggestions and updates the observer.
void NukeAllSuggestions();
@@ -448,6 +474,12 @@ class RemoteSuggestionsProviderImpl final : public RemoteSuggestionsProvider {
// A Timer for canceling too long fetches.
std::unique_ptr<base::OneShotTimer> fetch_timeout_timer_;
+ // Keeps track of the status of the ongoing request(s) and what action should
+ // be taken on completion. Requests via Fetch() (fetching more) are _not_
+ // tracked by this variable (as they do not need any special actions on
+ // completion).
+ FetchRequestStatus request_status_;
+
DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsProviderImpl);
};
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 78fccc3d984..6e55a78f265 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
@@ -58,8 +58,6 @@
#include "components/ntp_snippets/time_serialization.h"
#include "components/ntp_snippets/user_classifier.h"
#include "components/prefs/testing_pref_service.h"
-#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
-#include "components/signin/core/browser/fake_signin_manager.h"
#include "components/variations/variations_params_manager.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -260,6 +258,7 @@ class MockRemoteSuggestionsFetcher : public RemoteSuggestionsFetcher {
SnippetsAvailableCallback* callback));
MOCK_CONST_METHOD0(GetLastStatusForDebugging, const std::string&());
MOCK_CONST_METHOD0(GetLastJsonForDebugging, const std::string&());
+ MOCK_CONST_METHOD0(WasLastFetchAuthenticatedForDebugging, bool());
MOCK_CONST_METHOD0(GetFetchUrlForDebugging, const GURL&());
};
@@ -269,13 +268,10 @@ class MockPrefetchedPagesTracker : public PrefetchedPagesTracker {
// GMock does not support movable-only types (e.g. OnceCallback), therefore,
// the call is redirected to a mock method with a pointer to the callback.
- void AddInitializationCompletedCallback(
- base::OnceCallback<void()> callback) override {
- AddInitializationCompletedCallback(&callback);
+ void Initialize(base::OnceCallback<void()> callback) override {
+ Initialize(&callback);
}
- MOCK_METHOD1(AddInitializationCompletedCallback,
- void(base::OnceCallback<void()>* callback));
-
+ MOCK_METHOD1(Initialize, void(base::OnceCallback<void()>* callback));
MOCK_CONST_METHOD1(PrefetchedOfflinePageExists, bool(const GURL& url));
};
@@ -317,6 +313,7 @@ class MockRemoteSuggestionsStatusService
MOCK_METHOD1(Init, void(const StatusChangeCallback& callback));
MOCK_METHOD1(OnSignInStateChanged, void(bool));
+ MOCK_METHOD1(OnListVisibilityToggled, void(bool));
};
std::string BoolToString(bool value) {
@@ -377,7 +374,6 @@ class RemoteSuggestionsProviderImplTest : public ::testing::Test {
bool use_mock_prefetched_pages_tracker,
bool use_fake_breaking_news_listener,
bool use_mock_remote_suggestions_status_service) {
- utils_.ResetSigninManager();
auto mock_suggestions_fetcher =
std::make_unique<StrictMock<MockRemoteSuggestionsFetcher>>();
mock_suggestions_fetcher_ = mock_suggestions_fetcher.get();
@@ -568,6 +564,19 @@ class RemoteSuggestionsProviderImplTest : public ::testing::Test {
}
RemoteSuggestionsFetcher::SnippetsAvailableCallback
+ FetchSuggestionsAndGetResponseCallback(
+ RemoteSuggestionsProviderImpl* provider,
+ bool interactive_request) {
+ RemoteSuggestionsFetcher::SnippetsAvailableCallback snippets_callback;
+ EXPECT_CALL(*mock_suggestions_fetcher(), FetchSnippets(_, _))
+ .WillOnce(MoveSecondArgumentPointeeTo(&snippets_callback))
+ .RetiresOnSaturation();
+ provider->FetchSuggestions(
+ interactive_request, RemoteSuggestionsProvider::FetchStatusCallback());
+ return snippets_callback;
+ }
+
+ RemoteSuggestionsFetcher::SnippetsAvailableCallback
RefetchWhileDisplayingAndGetResponseCallback(
RemoteSuggestionsProviderImpl* provider) {
RemoteSuggestionsFetcher::SnippetsAvailableCallback snippets_callback;
@@ -2452,6 +2461,65 @@ TEST_F(RemoteSuggestionsProviderImplTest, CallsSchedulerWhenSignedOut) {
}
TEST_F(RemoteSuggestionsProviderImplTest,
+ RestartsFetchWhenSignedInWhileFetching) {
+ auto provider =
+ MakeSuggestionsProviderWithoutInitializationWithStrictScheduler();
+ // Initiate the provider so that it is already READY.
+ EXPECT_CALL(*scheduler(), OnProviderActivated());
+ WaitForSuggestionsProviderInitialization(provider.get());
+
+ // Initiate the fetch.
+ RemoteSuggestionsFetcher::SnippetsAvailableCallback snippets_callback;
+ EXPECT_CALL(*mock_suggestions_fetcher(), FetchSnippets(_, _))
+ .WillOnce(MoveSecondArgumentPointeeTo(&snippets_callback))
+ .RetiresOnSaturation();
+ provider->FetchSuggestions(/*interactive_request=*/false,
+ RemoteSuggestionsProvider::FetchStatusCallback());
+
+ // The scheduler should be notified of clearing the suggestions.
+ EXPECT_CALL(*scheduler(), OnSuggestionsCleared());
+ provider->OnStatusChanged(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT,
+ RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN);
+
+ // Once we signal the first fetch to be finished (calling snippets_callback
+ // below), a new fetch should get triggered.
+ EXPECT_CALL(*mock_suggestions_fetcher(), FetchSnippets(_, _)).Times(1);
+ std::move(snippets_callback)
+ .Run(Status::Success(), std::vector<FetchedCategory>());
+}
+
+TEST_F(RemoteSuggestionsProviderImplTest,
+ IgnoresResultsWhenHistoryClearedWhileFetching) {
+ auto provider =
+ MakeSuggestionsProviderWithoutInitializationWithStrictScheduler();
+ // Initiate the provider so that it is already READY.
+ EXPECT_CALL(*scheduler(), OnProviderActivated());
+ WaitForSuggestionsProviderInitialization(provider.get());
+
+ // Initiate the fetch.
+ RemoteSuggestionsFetcher::SnippetsAvailableCallback snippets_callback =
+ FetchSuggestionsAndGetResponseCallback(provider.get(),
+ /*interactive_request=*/false);
+
+ // The scheduler should be notified of clearing the history.
+ EXPECT_CALL(*scheduler(), OnHistoryCleared());
+ provider->ClearHistory(GetDefaultCreationTime(), GetDefaultExpirationTime(),
+ base::RepeatingCallback<bool(const GURL& url)>());
+
+ // Once the fetch finishes, the returned suggestions are ignored.
+ FetchedCategoryBuilder category_builder;
+ category_builder.SetCategory(articles_category());
+ category_builder.AddSuggestionViaBuilder(
+ RemoteSuggestionBuilder().AddId(base::StringPrintf("http://abc.com")));
+ std::vector<FetchedCategory> fetched_categories;
+ fetched_categories.push_back(category_builder.Build());
+ std::move(snippets_callback)
+ .Run(Status::Success(), std::move(fetched_categories));
+ EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
+ SizeIs(0));
+}
+
+TEST_F(RemoteSuggestionsProviderImplTest,
ShouldExcludeKnownSuggestionsWithoutTruncatingWhenFetchingMore) {
auto provider = MakeSuggestionsProvider(
/*use_mock_prefetched_pages_tracker=*/false,
@@ -3212,7 +3280,7 @@ TEST_F(RemoteSuggestionsProviderImplTest,
base::OnceCallback<void()> initialization_completed_callback;
EXPECT_CALL(*mock_tracker, IsInitialized()).WillRepeatedly(Return(false));
- EXPECT_CALL(*mock_tracker, AddInitializationCompletedCallback(_))
+ EXPECT_CALL(*mock_tracker, Initialize(_))
.WillOnce(MoveFirstArgumentPointeeTo(&initialization_completed_callback));
std::vector<FetchedCategory> fetched_categories;
fetched_categories.push_back(
@@ -4502,6 +4570,48 @@ TEST_F(RemoteSuggestionsProviderImplTest,
}
TEST_F(RemoteSuggestionsProviderImplTest,
+ ShouldHandleCategoryDisabledBeforeTimeout) {
+ auto provider = MakeSuggestionsProvider(
+ /*use_mock_prefetched_pages_tracker=*/false,
+ /*use_fake_breaking_news_listener=*/false,
+ /*use_mock_remote_suggestions_status_service=*/false);
+ std::vector<FetchedCategory> fetched_categories;
+ const FetchedCategoryBuilder articles_category_builder =
+ FetchedCategoryBuilder()
+ .SetCategory(articles_category())
+ .AddSuggestionViaBuilder(
+ RemoteSuggestionBuilder().SetUrl("http://articles.com"));
+ fetched_categories.push_back(articles_category_builder.Build());
+ FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
+ Status::Success(), std::move(fetched_categories));
+ fetched_categories.clear();
+
+ ASSERT_EQ(CategoryStatus::AVAILABLE,
+ observer().StatusForCategory(articles_category()));
+
+ // No need to finish the fetch, we ignore the response callback.
+ RefetchWhileDisplayingAndGetResponseCallback(provider.get());
+
+ FastForwardBy(
+ base::TimeDelta::FromSeconds(kTimeoutForRefetchWhileDisplayingSeconds) -
+ base::TimeDelta::FromMilliseconds(1));
+
+ // Before the timeout, the status is flipped to AVAILABLE_LOADING.
+ ASSERT_EQ(CategoryStatus::AVAILABLE_LOADING,
+ observer().StatusForCategory(articles_category()));
+
+ // Disable the provider; this will put the category into the
+ // CATEGORY_EXPLICITLY_DISABLED status.
+ provider->EnterState(RemoteSuggestionsProviderImpl::State::DISABLED);
+ ASSERT_EQ(CategoryStatus::CATEGORY_EXPLICITLY_DISABLED,
+ observer().StatusForCategory(articles_category()));
+
+ // Trigger the timeout. The provider should gracefully handle(i.e. not crash
+ // because of) the category being disabled in the interim.
+ FastForwardBy(base::TimeDelta::FromMilliseconds(2));
+}
+
+TEST_F(RemoteSuggestionsProviderImplTest,
ShouldNotUpdateTimeoutIfRefetchWhileDisplayingCalledAgain) {
auto provider = MakeSuggestionsProvider(
/*use_mock_prefetched_pages_tracker=*/false,
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 ea8bf5bf208..fa2af3de5ac 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
@@ -6,6 +6,7 @@
#include <string>
+#include "base/feature_list.h"
#include "components/ntp_snippets/content_suggestions_metrics.h"
#include "components/ntp_snippets/features.h"
#include "components/ntp_snippets/pref_names.h"
@@ -22,6 +23,7 @@ RemoteSuggestionsStatusServiceImpl::RemoteSuggestionsStatusServiceImpl(
: status_(RemoteSuggestionsStatus::EXPLICITLY_DISABLED),
additional_toggle_pref_(additional_toggle_pref),
is_signed_in_(is_signed_in),
+ list_visible_during_session_(true),
pref_service_(pref_service) {
ntp_snippets::metrics::RecordRemoteSuggestionsProviderState(
!IsExplicitlyDisabled());
@@ -34,6 +36,7 @@ RemoteSuggestionsStatusServiceImpl::~RemoteSuggestionsStatusServiceImpl() =
void RemoteSuggestionsStatusServiceImpl::RegisterProfilePrefs(
PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(prefs::kEnableSnippets, true);
+ registry->RegisterBooleanPref(prefs::kArticlesListVisible, true);
}
void RemoteSuggestionsStatusServiceImpl::Init(
@@ -42,6 +45,9 @@ void RemoteSuggestionsStatusServiceImpl::Init(
status_change_callback_ = callback;
+ list_visible_during_session_ =
+ pref_service_->GetBoolean(prefs::kArticlesListVisible);
+
// Notify about the current state before registering the observer, to make
// sure we don't get a double notification due to an undefined start state.
RemoteSuggestionsStatus old_status = status_;
@@ -51,13 +57,19 @@ void RemoteSuggestionsStatusServiceImpl::Init(
pref_change_registrar_.Init(pref_service_);
pref_change_registrar_.Add(
prefs::kEnableSnippets,
- base::Bind(&RemoteSuggestionsStatusServiceImpl::OnSnippetsEnabledChanged,
- base::Unretained(this)));
+ base::BindRepeating(
+ &RemoteSuggestionsStatusServiceImpl::OnSnippetsEnabledChanged,
+ base::Unretained(this)));
+ pref_change_registrar_.Add(
+ prefs::kArticlesListVisible,
+ base::BindRepeating(
+ &RemoteSuggestionsStatusServiceImpl::OnListVisibilityChanged,
+ base::Unretained(this)));
if (!additional_toggle_pref_.empty()) {
pref_change_registrar_.Add(
additional_toggle_pref_,
- base::Bind(
+ base::BindRepeating(
&RemoteSuggestionsStatusServiceImpl::OnSnippetsEnabledChanged,
base::Unretained(this)));
}
@@ -87,12 +99,28 @@ void RemoteSuggestionsStatusServiceImpl::OnSignInStateChanged(
OnStateChanged(GetStatusFromDeps());
}
+void RemoteSuggestionsStatusServiceImpl::OnListVisibilityChanged() {
+ if (pref_service_->GetBoolean(prefs::kArticlesListVisible)) {
+ list_visible_during_session_ = true;
+ }
+ OnStateChanged(GetStatusFromDeps());
+}
+
bool RemoteSuggestionsStatusServiceImpl::IsExplicitlyDisabled() const {
if (!pref_service_->GetBoolean(prefs::kEnableSnippets)) {
- DVLOG(1) << "[GetStatusFromDeps] Disabled via pref";
+ DVLOG(1) << "[GetStatusFromDeps] Disabled via pref.";
+ return true;
+ }
+
+ if (base::FeatureList::IsEnabled(
+ ntp_snippets::kArticleSuggestionsExpandableHeader) &&
+ !list_visible_during_session_) {
+ DVLOG(1) << "[GetStatusFromDeps] Disabled because articles list hidden.";
return true;
}
+ // |additional_toggle_pref_| will always be empty when
+ // kArticleSuggestionsExpandableHeader is enabled.
if (!additional_toggle_pref_.empty()) {
if (!pref_service_->GetBoolean(additional_toggle_pref_)) {
DVLOG(1) << "[GetStatusFromDeps] Disabled via additional pref";
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 fcf2a9a1cee..ed0234bdac2 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
@@ -6,7 +6,6 @@
#define COMPONENTS_NTP_SNIPPETS_REMOTE_REMOTE_SUGGESTIONS_STATUS_SERVICE_IMPL_H_
#include "base/callback.h"
-#include "base/gtest_prod_util.h"
#include "base/scoped_observer.h"
#include "components/ntp_snippets/remote/remote_suggestions_status_service.h"
#include "components/prefs/pref_change_registrar.h"
@@ -32,17 +31,9 @@ class RemoteSuggestionsStatusServiceImpl
void OnSignInStateChanged(bool has_signed_in) override;
private:
- // TODO(jkrcal): Rewrite the tests using the public API - observing status
- // changes instead of calling private GetStatusFromDeps() directly.
- FRIEND_TEST_ALL_PREFIXES(RemoteSuggestionsStatusServiceImplTest,
- SigninNeededIfSpecifiedByParam);
- FRIEND_TEST_ALL_PREFIXES(RemoteSuggestionsStatusServiceImplTest,
- NoSigninNeeded);
- FRIEND_TEST_ALL_PREFIXES(RemoteSuggestionsStatusServiceImplTest,
- DisabledViaPref);
-
- // Callback for the PrefChangeRegistrar.
+ // Callbacks for the PrefChangeRegistrar.
void OnSnippetsEnabledChanged();
+ void OnListVisibilityChanged();
void OnStateChanged(RemoteSuggestionsStatus new_status);
@@ -60,8 +51,12 @@ class RemoteSuggestionsStatusServiceImpl
// Name of a preference to be used as an additional toggle to guard the
// remote suggestions provider.
std::string additional_toggle_pref_;
-
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
+ // disabled on the next startup of browser, provided that the list is still
+ // hidden then.
+ bool list_visible_during_session_;
PrefService* pref_service_;
PrefChangeRegistrar pref_change_registrar_;
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 ab55963ca32..829b2c0c470 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
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "components/ntp_snippets/features.h"
#include "components/ntp_snippets/ntp_snippets_constants.h"
@@ -20,60 +21,172 @@
namespace ntp_snippets {
namespace {
-
-void OnStatusChange(RemoteSuggestionsStatus old_status,
- RemoteSuggestionsStatus new_status) {}
+const char kTestPrefName[] = "search_suggestions.test_name";
} // namespace
class RemoteSuggestionsStatusServiceImplTest : public ::testing::Test {
public:
- RemoteSuggestionsStatusServiceImplTest() {
+ RemoteSuggestionsStatusServiceImplTest()
+ : last_status_(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN) {
RemoteSuggestionsStatusServiceImpl::RegisterProfilePrefs(
utils_.pref_service()->registry());
+
+ // Registering additional test preference for testing serch suggestion based
+ // feature disabling.
+ utils_.pref_service()->registry()->RegisterBooleanPref(kTestPrefName, true);
}
- std::unique_ptr<RemoteSuggestionsStatusServiceImpl> MakeService() {
+ // |list_hiding_enabled| indicates whether kArticleSuggestionsExpandableHeader
+ // is enabled.
+ std::unique_ptr<RemoteSuggestionsStatusServiceImpl> MakeService(
+ bool list_hiding_enabled) {
+ // Enabling/disabling the feature.
+ if (list_hiding_enabled) {
+ feature_list_.InitAndEnableFeature(
+ ntp_snippets::kArticleSuggestionsExpandableHeader);
+ } else {
+ feature_list_.InitAndDisableFeature(
+ ntp_snippets::kArticleSuggestionsExpandableHeader);
+ }
+
auto service = std::make_unique<RemoteSuggestionsStatusServiceImpl>(
- false, utils_.pref_service(), std::string());
- service->Init(base::BindRepeating(&OnStatusChange));
+ false, utils_.pref_service(),
+ list_hiding_enabled ? std::string() : kTestPrefName);
+ service->Init(base::BindRepeating(
+ &RemoteSuggestionsStatusServiceImplTest::OnStatusChange,
+ base::Unretained(this)));
return service;
}
+ RemoteSuggestionsStatus last_status() const { return last_status_; }
+
protected:
+ void OnStatusChange(RemoteSuggestionsStatus old_status,
+ RemoteSuggestionsStatus new_status) {
+ last_status_ = new_status;
+ }
+
+ base::test::ScopedFeatureList feature_list_;
+ RemoteSuggestionsStatus last_status_;
test::RemoteSuggestionsTestUtils utils_;
variations::testing::VariationParamsManager params_manager_;
};
TEST_F(RemoteSuggestionsStatusServiceImplTest, NoSigninNeeded) {
- auto service = MakeService();
+ auto service = MakeService(/*list_hiding_enabled=*/false);
// By default, no signin is required.
- EXPECT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT,
- service->GetStatusFromDeps());
+ EXPECT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT, last_status());
// Signin should cause a state change.
service->OnSignInStateChanged(/*has_signed_in=*/true);
- EXPECT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN,
- service->GetStatusFromDeps());
+ EXPECT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN, last_status());
}
TEST_F(RemoteSuggestionsStatusServiceImplTest, DisabledViaPref) {
- auto service = MakeService();
+ auto service = MakeService(/*list_hiding_enabled=*/false);
// The default test setup is signed out. The service is enabled.
- ASSERT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT,
- service->GetStatusFromDeps());
+ ASSERT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT, last_status());
// Once the enabled pref is set to false, we should be disabled.
utils_.pref_service()->SetBoolean(prefs::kEnableSnippets, false);
- EXPECT_EQ(RemoteSuggestionsStatus::EXPLICITLY_DISABLED,
- service->GetStatusFromDeps());
+ EXPECT_EQ(RemoteSuggestionsStatus::EXPLICITLY_DISABLED, last_status());
+
+ // The state should not change, even though a signin has occurred.
+ service->OnSignInStateChanged(/*has_signed_in=*/true);
+ EXPECT_EQ(RemoteSuggestionsStatus::EXPLICITLY_DISABLED, last_status());
+}
+
+TEST_F(RemoteSuggestionsStatusServiceImplTest, DisabledViaAdditionalPref) {
+ auto service = MakeService(/*list_hiding_enabled=*/false);
+
+ // The default test setup is signed out. The service is enabled.
+ ASSERT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT, last_status());
+
+ // Once the additional pref is set to false, we should be disabled.
+ utils_.pref_service()->SetBoolean(kTestPrefName, false);
+ EXPECT_EQ(RemoteSuggestionsStatus::EXPLICITLY_DISABLED, last_status());
+
+ // The state should not change, even though a signin has occurred.
+ service->OnSignInStateChanged(/*has_signed_in=*/true);
+ EXPECT_EQ(RemoteSuggestionsStatus::EXPLICITLY_DISABLED, last_status());
+}
+
+TEST_F(RemoteSuggestionsStatusServiceImplTest, EnabledAfterListFolded) {
+ auto service = MakeService(/*list_hiding_enabled="*/ true);
+ // By default, the articles list should be visible.
+ EXPECT_TRUE(utils_.pref_service()->GetBoolean(prefs::kArticlesListVisible));
+
+ // The default test setup is signed out. The service is enabled.
+ ASSERT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT, last_status());
+
+ // When the user toggles the visibility of articles list in UI off the service
+ // should still be enabled until the end of the session.
+ utils_.pref_service()->SetBoolean(prefs::kArticlesListVisible, false);
+ EXPECT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT, last_status());
+
+ // Signin should cause a state change.
+ service->OnSignInStateChanged(/*has_signed_in=*/true);
+ EXPECT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN, last_status());
+}
+
+TEST_F(RemoteSuggestionsStatusServiceImplTest, DisabledWhenListFoldedOnStart) {
+ utils_.pref_service()->SetBoolean(prefs::kArticlesListVisible, false);
+ auto service = MakeService(/*list_hiding_enabled="*/ true);
+
+ // The state should be disabled when starting with no list shown.
+ EXPECT_EQ(RemoteSuggestionsStatus::EXPLICITLY_DISABLED, last_status());
// The state should not change, even though a signin has occurred.
service->OnSignInStateChanged(/*has_signed_in=*/true);
- EXPECT_EQ(RemoteSuggestionsStatus::EXPLICITLY_DISABLED,
- service->GetStatusFromDeps());
+ EXPECT_EQ(RemoteSuggestionsStatus::EXPLICITLY_DISABLED, last_status());
+}
+
+TEST_F(RemoteSuggestionsStatusServiceImplTest, EnablingAfterFoldedStart) {
+ utils_.pref_service()->SetBoolean(prefs::kArticlesListVisible, false);
+ auto service = MakeService(/*list_hiding_enabled="*/ true);
+
+ // The state should be disabled when starting with no list shown.
+ EXPECT_EQ(RemoteSuggestionsStatus::EXPLICITLY_DISABLED, last_status());
+
+ // When the user toggles the visibility of articles list in UI on, the service
+ // should get enabled.
+ utils_.pref_service()->SetBoolean(prefs::kArticlesListVisible, true);
+ EXPECT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT, last_status());
+
+ // Signin should cause a state change.
+ service->OnSignInStateChanged(/*has_signed_in=*/true);
+ EXPECT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN, last_status());
+}
+
+TEST_F(RemoteSuggestionsStatusServiceImplTest,
+ EnablingAfterFoldedStartSignedIn) {
+ utils_.pref_service()->SetBoolean(prefs::kArticlesListVisible, false);
+ auto service = MakeService(/*list_hiding_enabled="*/ true);
+
+ // Signin should not cause a state change, because UI is not visible.
+ service->OnSignInStateChanged(/*has_signed_in=*/true);
+ EXPECT_EQ(RemoteSuggestionsStatus::EXPLICITLY_DISABLED, last_status());
+
+ // When the user toggles the visibility of articles list in UI on, the service
+ // should get enabled.
+ utils_.pref_service()->SetBoolean(prefs::kArticlesListVisible, true);
+ EXPECT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN, last_status());
+}
+
+TEST_F(RemoteSuggestionsStatusServiceImplTest,
+ DisablingHidingFeatureWhenFolder) {
+ utils_.pref_service()->SetBoolean(prefs::kArticlesListVisible, false);
+ auto service = MakeService(/*list_hiding_enabled="*/ false);
+
+ // The state should be enabled when hiding is disabled.
+ EXPECT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT, last_status());
+
+ // Signin should cause a state change.
+ service->OnSignInStateChanged(/*has_signed_in=*/true);
+ EXPECT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN, last_status());
}
} // namespace ntp_snippets
diff --git a/chromium/components/ntp_snippets/remote/test_utils.cc b/chromium/components/ntp_snippets/remote/test_utils.cc
index 0048f5d5944..ea48f1eea00 100644
--- a/chromium/components/ntp_snippets/remote/test_utils.cc
+++ b/chromium/components/ntp_snippets/remote/test_utils.cc
@@ -7,10 +7,6 @@
#include <memory>
#include "components/prefs/testing_pref_service.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_pref_names.h"
-#include "components/signin/core/browser/test_signin_client.h"
#include "components/sync/driver/fake_sync_service.h"
namespace ntp_snippets {
@@ -48,38 +44,11 @@ syncer::ModelTypeSet FakeSyncService::GetActiveDataTypes() const {
RemoteSuggestionsTestUtils::RemoteSuggestionsTestUtils()
: pref_service_(std::make_unique<TestingPrefServiceSyncable>()) {
- AccountTrackerService::RegisterPrefs(pref_service_->registry());
-
-#if defined(OS_CHROMEOS)
- SigninManagerBase::RegisterProfilePrefs(pref_service_->registry());
- SigninManagerBase::RegisterPrefs(pref_service_->registry());
-#else
- SigninManager::RegisterProfilePrefs(pref_service_->registry());
- SigninManager::RegisterPrefs(pref_service_->registry());
-#endif // OS_CHROMEOS
-
- token_service_ = std::make_unique<FakeProfileOAuth2TokenService>();
- signin_client_ = std::make_unique<TestSigninClient>(pref_service_.get());
- account_tracker_ = std::make_unique<AccountTrackerService>();
- account_tracker_->Initialize(signin_client_.get());
fake_sync_service_ = std::make_unique<FakeSyncService>();
-
- ResetSigninManager();
}
RemoteSuggestionsTestUtils::~RemoteSuggestionsTestUtils() = default;
-void RemoteSuggestionsTestUtils::ResetSigninManager() {
-#if defined(OS_CHROMEOS)
- fake_signin_manager_ = std::make_unique<FakeSigninManagerBase>(
- signin_client_.get(), account_tracker_.get());
-#else
- fake_signin_manager_ = std::make_unique<FakeSigninManager>(
- signin_client_.get(), token_service_.get(), account_tracker_.get(),
- /*cookie_manager_service=*/nullptr);
-#endif
-}
-
} // namespace test
} // namespace ntp_snippets
diff --git a/chromium/components/ntp_snippets/remote/test_utils.h b/chromium/components/ntp_snippets/remote/test_utils.h
index d956011596a..f72f52c021d 100644
--- a/chromium/components/ntp_snippets/remote/test_utils.h
+++ b/chromium/components/ntp_snippets/remote/test_utils.h
@@ -10,23 +10,11 @@
#include <vector>
#include "build/build_config.h"
-#include "components/signin/core/browser/fake_signin_manager.h"
#include "components/sync/driver/fake_sync_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
-class AccountTrackerService;
-class FakeProfileOAuth2TokenService;
-class TestSigninClient;
-
using sync_preferences::TestingPrefServiceSyncable;
-#if defined(OS_CHROMEOS)
-// ChromeOS doesn't have SigninManager.
-using SigninManagerForTest = FakeSigninManagerBase;
-#else
-using SigninManagerForTest = FakeSigninManager;
-#endif // OS_CHROMEOS
-
namespace ntp_snippets {
namespace test {
@@ -59,21 +47,11 @@ class RemoteSuggestionsTestUtils {
void ResetSigninManager();
FakeSyncService* fake_sync_service() { return fake_sync_service_.get(); }
- SigninManagerForTest* fake_signin_manager() {
- return fake_signin_manager_.get();
- }
TestingPrefServiceSyncable* pref_service() { return pref_service_.get(); }
- FakeProfileOAuth2TokenService* token_service() {
- return token_service_.get();
- }
private:
- std::unique_ptr<SigninManagerForTest> fake_signin_manager_;
std::unique_ptr<FakeSyncService> fake_sync_service_;
std::unique_ptr<TestingPrefServiceSyncable> pref_service_;
- std::unique_ptr<FakeProfileOAuth2TokenService> token_service_;
- std::unique_ptr<TestSigninClient> signin_client_;
- std::unique_ptr<AccountTrackerService> account_tracker_;
};
} // namespace test
diff --git a/chromium/components/ntp_tiles/BUILD.gn b/chromium/components/ntp_tiles/BUILD.gn
index 0d740f607b6..099466d83e9 100644
--- a/chromium/components/ntp_tiles/BUILD.gn
+++ b/chromium/components/ntp_tiles/BUILD.gn
@@ -12,8 +12,6 @@ static_library("ntp_tiles") {
"constants.h",
"country_code_ios.h",
"country_code_ios.mm",
- "field_trial.cc",
- "field_trial.h",
"icon_cacher.h",
"icon_cacher_impl.cc",
"icon_cacher_impl.h",
@@ -63,10 +61,6 @@ static_library("ntp_tiles") {
"//components/variations/service",
"//ui/base",
]
-
- if (is_android) {
- deps += [ "android:ntp_tiles_jni_headers" ]
- }
}
# If you want to use this, let us (ntp-dev@chromium.org) know. In that case, it
diff --git a/chromium/components/ntp_tiles/android/BUILD.gn b/chromium/components/ntp_tiles/android/BUILD.gn
deleted file mode 100644
index e125f19af9b..00000000000
--- a/chromium/components/ntp_tiles/android/BUILD.gn
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/android/rules.gni")
-
-_jni_sources =
- [ "java/src/org/chromium/components/ntptiles/MostVisitedSites.java" ]
-
-generate_jni("ntp_tiles_jni_headers") {
- sources = _jni_sources
- jni_package = "ntp_tiles"
-}
-
-android_library("ntp_tiles_java") {
- deps = [
- "//base:base_java",
- ]
- java_files = [] + _jni_sources
-}
diff --git a/chromium/components/ntp_tiles/constants.cc b/chromium/components/ntp_tiles/constants.cc
index e70d5d9650c..5cec78488ec 100644
--- a/chromium/components/ntp_tiles/constants.cc
+++ b/chromium/components/ntp_tiles/constants.cc
@@ -19,4 +19,7 @@ const base::Feature kNtpMostLikelyFaviconsFromServerFeature{
const base::Feature kSiteExplorationUiFeature{
"SiteExplorationUi", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kUsePopularSitesSuggestions{
+ "UsePopularSitesSuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
+
} // namespace ntp_tiles
diff --git a/chromium/components/ntp_tiles/constants.h b/chromium/components/ntp_tiles/constants.h
index 1789ba4c086..7395995f975 100644
--- a/chromium/components/ntp_tiles/constants.h
+++ b/chromium/components/ntp_tiles/constants.h
@@ -26,6 +26,9 @@ extern const base::Feature kNtpMostLikelyFaviconsFromServerFeature;
// Feature to provide site exploration tiles in addition to personal tiles.
extern const base::Feature kSiteExplorationUiFeature;
+// If this feature is enabled, we enable popular sites in the suggestions UI.
+extern const base::Feature kUsePopularSitesSuggestions;
+
} // namespace ntp_tiles
#endif // COMPONENTS_NTP_TILES_CONSTANTS_H_
diff --git a/chromium/components/ntp_tiles/field_trial.cc b/chromium/components/ntp_tiles/field_trial.cc
deleted file mode 100644
index 60ed1b61dc7..00000000000
--- a/chromium/components/ntp_tiles/field_trial.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/ntp_tiles/field_trial.h"
-
-#if defined(OS_ANDROID)
-#include <jni.h>
-#endif
-#include <string>
-
-#include "base/command_line.h"
-#include "base/metrics/field_trial.h"
-#include "base/strings/string_util.h"
-#include "components/ntp_tiles/constants.h"
-#include "components/ntp_tiles/switches.h"
-
-#if defined(OS_ANDROID)
-#include "base/android/jni_android.h"
-#include "jni/MostVisitedSites_jni.h"
-#endif
-
-namespace ntp_tiles {
-
-bool ShouldShowPopularSites() {
- // Note: It's important to query the field trial state first, to ensure that
- // UMA reports the correct group.
- const std::string group_name =
- base::FieldTrialList::FindFullName(kPopularSitesFieldTrialName);
-
- base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
- if (cmd_line->HasSwitch(switches::kDisableNTPPopularSites))
- return false;
-
- if (cmd_line->HasSwitch(switches::kEnableNTPPopularSites))
- return true;
-
-#if defined(OS_ANDROID)
- if (Java_MostVisitedSites_isPopularSitesForceEnabled(
- base::android::AttachCurrentThread())) {
- return true;
- }
-#endif
-
- // Until any configuration is fetched, the default is to enable popular sites.
- if (group_name.empty()) {
- return true;
- }
-
- return base::StartsWith(group_name, "Enabled",
- base::CompareCase::INSENSITIVE_ASCII);
-}
-
-} // namespace ntp_tiles
diff --git a/chromium/components/ntp_tiles/field_trial.h b/chromium/components/ntp_tiles/field_trial.h
deleted file mode 100644
index 8915f699d34..00000000000
--- a/chromium/components/ntp_tiles/field_trial.h
+++ /dev/null
@@ -1,14 +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_NTP_TILES_FIELD_TRIAL_H_
-#define COMPONENTS_NTP_TILES_FIELD_TRIAL_H_
-
-namespace ntp_tiles {
-
-bool ShouldShowPopularSites();
-
-} // namespace ntp_tiles
-
-#endif // COMPONENTS_NTP_TILES_FIELD_TRIAL_H_
diff --git a/chromium/components/ntp_tiles/icon_cacher_impl_unittest.cc b/chromium/components/ntp_tiles/icon_cacher_impl_unittest.cc
index 77560803168..cc318665c78 100644
--- a/chromium/components/ntp_tiles/icon_cacher_impl_unittest.cc
+++ b/chromium/components/ntp_tiles/icon_cacher_impl_unittest.cc
@@ -4,11 +4,11 @@
#include "components/ntp_tiles/icon_cacher_impl.h"
+#include <memory>
#include <utility>
#include "base/containers/flat_set.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/memory/ptr_util.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/histogram_tester.h"
@@ -441,9 +441,9 @@ class IconCacherTestMostLikely : public IconCacherTestBase {
protected:
IconCacherTestMostLikely()
: fetcher_for_large_icon_service_(
- base::MakeUnique<::testing::StrictMock<MockImageFetcher>>()),
+ std::make_unique<::testing::StrictMock<MockImageFetcher>>()),
fetcher_for_icon_cacher_(
- base::MakeUnique<::testing::StrictMock<MockImageFetcher>>()) {
+ std::make_unique<::testing::StrictMock<MockImageFetcher>>()) {
// Expect uninteresting calls here, |fetcher_for_icon_cacher_| is not
// related to these tests. Keep it strict to make sure we do not use it in
// any other way.
diff --git a/chromium/components/ntp_tiles/most_visited_sites.cc b/chromium/components/ntp_tiles/most_visited_sites.cc
index 1fcfc627d33..ba46b4140ab 100644
--- a/chromium/components/ntp_tiles/most_visited_sites.cc
+++ b/chromium/components/ntp_tiles/most_visited_sites.cc
@@ -16,7 +16,6 @@
#include "base/strings/utf_string_conversions.h"
#include "components/history/core/browser/top_sites.h"
#include "components/ntp_tiles/constants.h"
-#include "components/ntp_tiles/field_trial.h"
#include "components/ntp_tiles/icon_cacher.h"
#include "components/ntp_tiles/pref_names.h"
#include "components/ntp_tiles/switches.h"
@@ -82,6 +81,10 @@ std::string StripFirstGenericPrefix(const std::string& host) {
return host;
}
+bool ShouldShowPopularSites() {
+ return base::FeatureList::IsEnabled(kUsePopularSitesSuggestions);
+}
+
} // namespace
MostVisitedSites::MostVisitedSites(
diff --git a/chromium/components/ntp_tiles/most_visited_sites_unittest.cc b/chromium/components/ntp_tiles/most_visited_sites_unittest.cc
index f6f3e9b2d6a..d8a4aaad81b 100644
--- a/chromium/components/ntp_tiles/most_visited_sites_unittest.cc
+++ b/chromium/components/ntp_tiles/most_visited_sites_unittest.cc
@@ -16,7 +16,6 @@
#include "base/callback_list.h"
#include "base/command_line.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
@@ -274,100 +273,101 @@ class MockIconCacher : public IconCacher {
class PopularSitesFactoryForTest {
public:
PopularSitesFactoryForTest(
- bool enabled,
sync_preferences::TestingPrefServiceSyncable* pref_service)
: prefs_(pref_service),
url_fetcher_factory_(/*default_factory=*/nullptr),
url_request_context_(new net::TestURLRequestContextGetter(
base::ThreadTaskRunnerHandle::Get())) {
PopularSitesImpl::RegisterProfilePrefs(pref_service->registry());
- if (enabled) {
- prefs_->SetString(prefs::kPopularSitesOverrideCountry, "IN");
- prefs_->SetString(prefs::kPopularSitesOverrideVersion, "5");
-
- url_fetcher_factory_.SetFakeResponse(
- GURL("https://www.gstatic.com/chrome/ntp/suggested_sites_IN_5.json"),
- R"([{
- "title": "PopularSite1",
- "url": "http://popularsite1/",
- "favicon_url": "http://popularsite1/favicon.ico"
- },
- {
- "title": "PopularSite2",
- "url": "http://popularsite2/",
- "favicon_url": "http://popularsite2/favicon.ico"
- },
- ])",
- net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-
- url_fetcher_factory_.SetFakeResponse(
- GURL("https://www.gstatic.com/chrome/ntp/suggested_sites_US_5.json"),
- R"([{
- "title": "ESPN",
- "url": "http://www.espn.com",
- "favicon_url": "http://www.espn.com/favicon.ico"
- }, {
- "title": "Mobile",
- "url": "http://www.mobile.de",
- "favicon_url": "http://www.mobile.de/favicon.ico"
- }, {
- "title": "Google News",
- "url": "http://news.google.com",
- "favicon_url": "http://news.google.com/favicon.ico"
- },
- ])",
- net::HTTP_OK, net::URLRequestStatus::SUCCESS);
+ }
- url_fetcher_factory_.SetFakeResponse(
- GURL("https://www.gstatic.com/chrome/ntp/suggested_sites_IN_6.json"),
- R"([{
- "section": 1, // PERSONALIZED
+ void SeedWithSampleData() {
+ prefs_->SetString(prefs::kPopularSitesOverrideCountry, "IN");
+ prefs_->SetString(prefs::kPopularSitesOverrideVersion, "5");
+
+ url_fetcher_factory_.ClearFakeResponses();
+ url_fetcher_factory_.SetFakeResponse(
+ GURL("https://www.gstatic.com/chrome/ntp/suggested_sites_IN_5.json"),
+ R"([{
+ "title": "PopularSite1",
+ "url": "http://popularsite1/",
+ "favicon_url": "http://popularsite1/favicon.ico"
+ },
+ {
+ "title": "PopularSite2",
+ "url": "http://popularsite2/",
+ "favicon_url": "http://popularsite2/favicon.ico"
+ },
+ ])",
+ net::HTTP_OK, net::URLRequestStatus::SUCCESS);
+
+ url_fetcher_factory_.SetFakeResponse(
+ GURL("https://www.gstatic.com/chrome/ntp/suggested_sites_US_5.json"),
+ R"([{
+ "title": "ESPN",
+ "url": "http://www.espn.com",
+ "favicon_url": "http://www.espn.com/favicon.ico"
+ }, {
+ "title": "Mobile",
+ "url": "http://www.mobile.de",
+ "favicon_url": "http://www.mobile.de/favicon.ico"
+ }, {
+ "title": "Google News",
+ "url": "http://news.google.com",
+ "favicon_url": "http://news.google.com/favicon.ico"
+ },
+ ])",
+ net::HTTP_OK, net::URLRequestStatus::SUCCESS);
+
+ url_fetcher_factory_.SetFakeResponse(
+ GURL("https://www.gstatic.com/chrome/ntp/suggested_sites_IN_6.json"),
+ R"([{
+ "section": 1, // PERSONALIZED
+ "sites": [{
+ "title": "PopularSite1",
+ "url": "http://popularsite1/",
+ "favicon_url": "http://popularsite1/favicon.ico"
+ },
+ {
+ "title": "PopularSite2",
+ "url": "http://popularsite2/",
+ "favicon_url": "http://popularsite2/favicon.ico"
+ },
+ ]
+ },
+ {
+ "section": 4, // NEWS
"sites": [{
- "title": "PopularSite1",
- "url": "http://popularsite1/",
- "favicon_url": "http://popularsite1/favicon.ico"
- },
- {
- "title": "PopularSite2",
- "url": "http://popularsite2/",
- "favicon_url": "http://popularsite2/favicon.ico"
- },
- ]
- },
- {
- "section": 4, // NEWS
- "sites": [{
- "large_icon_url": "https://news.google.com/icon.ico",
- "title": "Google News",
- "url": "https://news.google.com/"
- },
- {
- "favicon_url": "https://news.google.com/icon.ico",
- "title": "Google News Germany",
- "url": "https://news.google.de/"
- }]
- },
- {
- "section": 2, // SOCIAL
- "sites": [{
- "large_icon_url": "https://ssl.gstatic.com/icon.png",
- "title": "Google+",
- "url": "https://plus.google.com/"
- }]
- },
- {
- "section": 3, // ENTERTAINMENT
- "sites": [
- // Intentionally empty site list.
- ]
- }
- ])",
- net::HTTP_OK, net::URLRequestStatus::SUCCESS);
- }
+ "large_icon_url": "https://news.google.com/icon.ico",
+ "title": "Google News",
+ "url": "https://news.google.com/"
+ },
+ {
+ "favicon_url": "https://news.google.com/icon.ico",
+ "title": "Google News Germany",
+ "url": "https://news.google.de/"
+ }]
+ },
+ {
+ "section": 2, // SOCIAL
+ "sites": [{
+ "large_icon_url": "https://ssl.gstatic.com/icon.png",
+ "title": "Google+",
+ "url": "https://plus.google.com/"
+ }]
+ },
+ {
+ "section": 3, // ENTERTAINMENT
+ "sites": [
+ // Intentionally empty site list.
+ ]
+ }
+ ])",
+ net::HTTP_OK, net::URLRequestStatus::SUCCESS);
}
std::unique_ptr<PopularSites> New() {
- return base::MakeUnique<PopularSitesImpl>(
+ return std::make_unique<PopularSitesImpl>(
prefs_,
/*template_url_service=*/nullptr,
/*variations_service=*/nullptr, url_request_context_.get(),
@@ -410,32 +410,33 @@ class TopSitesCallbackList {
class MostVisitedSitesTest : public ::testing::TestWithParam<bool> {
protected:
MostVisitedSitesTest()
- : popular_sites_factory_(/*enabled=*/GetParam(), &pref_service_),
+ : popular_sites_factory_(&pref_service_),
mock_top_sites_(new StrictMock<MockTopSites>()) {
MostVisitedSites::RegisterProfilePrefs(pref_service_.registry());
- if (IsPopularSitesEnabledViaVariations()) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableNTPPopularSites);
+ // Disable FaviconServer in most tests and override in specific tests.
+ if (IsPopularSitesFeatureEnabled()) {
+ feature_list_.InitWithFeatures(
+ /*enabled_features=*/{kUsePopularSitesSuggestions},
+ /*disabled_features=*/{kNtpMostLikelyFaviconsFromServerFeature});
+ popular_sites_factory_.SeedWithSampleData();
} else {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kDisableNTPPopularSites);
+ feature_list_.InitWithFeatures(
+ /*enabled_features=*/{},
+ /*disabled_features=*/{kUsePopularSitesSuggestions,
+ kNtpMostLikelyFaviconsFromServerFeature});
}
- // Disable in most tests, this is overriden in a specific test.
- feature_list_.InitAndDisableFeature(
- kNtpMostLikelyFaviconsFromServerFeature);
-
RecreateMostVisitedSites();
}
void RecreateMostVisitedSites() {
// We use StrictMock to make sure the object is not used unless Popular
// Sites is enabled.
- auto icon_cacher = base::MakeUnique<StrictMock<MockIconCacher>>();
+ auto icon_cacher = std::make_unique<StrictMock<MockIconCacher>>();
icon_cacher_ = icon_cacher.get();
- if (IsPopularSitesEnabledViaVariations()) {
+ if (IsPopularSitesFeatureEnabled()) {
// Populate Popular Sites' internal cache by mimicking a past usage of
// PopularSitesImpl.
auto tmp_popular_sites = popular_sites_factory_.New();
@@ -463,13 +464,13 @@ class MostVisitedSitesTest : public ::testing::TestWithParam<bool> {
EXPECT_CALL(*icon_cacher, StartFetchMostLikely(_, _)).Times(AtLeast(0));
- most_visited_sites_ = base::MakeUnique<MostVisitedSites>(
+ most_visited_sites_ = std::make_unique<MostVisitedSites>(
&pref_service_, mock_top_sites_, &mock_suggestions_service_,
popular_sites_factory_.New(), std::move(icon_cacher),
/*supervisor=*/nullptr);
}
- bool IsPopularSitesEnabledViaVariations() const { return GetParam(); }
+ bool IsPopularSitesFeatureEnabled() const { return GetParam(); }
bool VerifyAndClearExpectations() {
base::RunLoop().RunUntilIdle();
@@ -478,7 +479,7 @@ class MostVisitedSitesTest : public ::testing::TestWithParam<bool> {
Mock::VerifyAndClearExpectations(&mock_suggestions_service_) &&
Mock::VerifyAndClearExpectations(&mock_observer_);
// For convenience, restore the expectations for IsBlacklisted().
- if (IsPopularSitesEnabledViaVariations()) {
+ if (IsPopularSitesFeatureEnabled()) {
EXPECT_CALL(*mock_top_sites_, IsBlacklisted(_))
.WillRepeatedly(Return(false));
}
@@ -486,7 +487,7 @@ class MostVisitedSitesTest : public ::testing::TestWithParam<bool> {
}
FakeHomePageClient* RegisterNewHomePageClient() {
- auto home_page_client = base::MakeUnique<FakeHomePageClient>();
+ auto home_page_client = std::make_unique<FakeHomePageClient>();
FakeHomePageClient* raw_client_ptr = home_page_client.get();
most_visited_sites_->SetHomePageClient(std::move(home_page_client));
return raw_client_ptr;
@@ -908,7 +909,7 @@ TEST_P(MostVisitedSitesTest, ShouldContainSiteExplorationsWhenFeatureEnabled) {
/*num_sites=*/3);
base::RunLoop().RunUntilIdle();
- if (!IsPopularSitesEnabledViaVariations()) {
+ if (!IsPopularSitesFeatureEnabled()) {
EXPECT_THAT(
sections,
Contains(Pair(SectionType::PERSONALIZED,
@@ -957,7 +958,7 @@ TEST_P(MostVisitedSitesTest,
EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
Contains(MatchesTile("Google", "http://www.google.com/",
TileSource::TOP_SITES)));
- if (IsPopularSitesEnabledViaVariations()) {
+ if (IsPopularSitesFeatureEnabled()) {
EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
Contains(MatchesTile("Google News", "http://news.google.com/",
TileSource::POPULAR)));
@@ -986,7 +987,7 @@ TEST_P(MostVisitedSitesTest, ShouldHandleTopSitesCacheHit) {
&SuggestionsService::ResponseCallbackList::Add));
EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
.WillOnce(Return(SuggestionsProfile())); // Empty cache.
- if (IsPopularSitesEnabledViaVariations()) {
+ if (IsPopularSitesFeatureEnabled()) {
EXPECT_CALL(
mock_observer_,
OnURLsAvailable(Contains(Pair(
@@ -1018,7 +1019,7 @@ TEST_P(MostVisitedSitesTest, ShouldHandleTopSitesCacheHit) {
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_, false))
.WillOnce(InvokeCallbackArgument<0>(
MostVisitedURLList{MakeMostVisitedURL("Site 2", "http://site2/")}));
- if (IsPopularSitesEnabledViaVariations()) {
+ if (IsPopularSitesFeatureEnabled()) {
EXPECT_CALL(*mock_top_sites_, IsBlacklisted(_))
.WillRepeatedly(Return(false));
}
@@ -1083,7 +1084,7 @@ class MostVisitedSitesWithCacheHitTest : public MostVisitedSitesTest {
MakeSuggestion("Site 3", "http://site3/"),
})));
- if (IsPopularSitesEnabledViaVariations()) {
+ if (IsPopularSitesFeatureEnabled()) {
EXPECT_CALL(
mock_observer_,
OnURLsAvailable(Contains(Pair(
@@ -1161,7 +1162,7 @@ TEST_P(MostVisitedSitesWithCacheHitTest, ShouldTruncateList) {
TEST_P(MostVisitedSitesWithCacheHitTest,
ShouldCompleteWithPopularSitesIffEnabled) {
- if (IsPopularSitesEnabledViaVariations()) {
+ if (IsPopularSitesFeatureEnabled()) {
EXPECT_CALL(
mock_observer_,
OnURLsAvailable(Contains(
@@ -1259,7 +1260,7 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest,
TEST_P(MostVisitedSitesWithEmptyCacheTest,
ShouldCompleteWithPopularSitesIffEnabled) {
- if (IsPopularSitesEnabledViaVariations()) {
+ if (IsPopularSitesFeatureEnabled()) {
EXPECT_CALL(
mock_observer_,
OnURLsAvailable(Contains(
@@ -1438,7 +1439,7 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest, ShouldPropagateUpdateByTopSites) {
TEST_P(MostVisitedSitesWithEmptyCacheTest,
ShouldSendEmptyListIfBothTopSitesAndSuggestionsServiceEmpty) {
- if (IsPopularSitesEnabledViaVariations()) {
+ if (IsPopularSitesFeatureEnabled()) {
EXPECT_CALL(
mock_observer_,
OnURLsAvailable(Contains(
diff --git a/chromium/components/ntp_tiles/popular_sites_impl.cc b/chromium/components/ntp_tiles/popular_sites_impl.cc
index 91971de6ad2..b0fb9273834 100644
--- a/chromium/components/ntp_tiles/popular_sites_impl.cc
+++ b/chromium/components/ntp_tiles/popular_sites_impl.cc
@@ -6,6 +6,7 @@
#include <stddef.h>
#include <map>
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -21,7 +22,6 @@
#include "components/data_use_measurement/core/data_use_user_data.h"
#include "components/google/core/browser/google_util.h"
#include "components/ntp_tiles/constants.h"
-#include "components/ntp_tiles/field_trial.h"
#include "components/ntp_tiles/pref_names.h"
#include "components/ntp_tiles/switches.h"
#include "components/pref_registry/pref_registry_syncable.h"
@@ -216,10 +216,10 @@ void SetDefaultResourceForSite(int index,
// Creates the list of popular sites based on a snapshot available for mobile.
std::unique_ptr<base::ListValue> DefaultPopularSites() {
#if !defined(OS_ANDROID) && !defined(OS_IOS)
- return base::MakeUnique<base::ListValue>();
+ return std::make_unique<base::ListValue>();
#else
if (!base::FeatureList::IsEnabled(kPopularSitesBakedInContentFeature)) {
- return base::MakeUnique<base::ListValue>();
+ return std::make_unique<base::ListValue>();
}
std::unique_ptr<base::ListValue> sites =
base::ListValue::From(base::JSONReader::Read(
diff --git a/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc b/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc
index c8adc8cee26..20fb333fb36 100644
--- a/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc
+++ b/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc
@@ -5,6 +5,7 @@
#include "components/ntp_tiles/popular_sites_impl.h"
#include <map>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -12,7 +13,6 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/json/json_writer.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/optional.h"
#include "base/run_loop.h"
@@ -24,7 +24,6 @@
#include "components/ntp_tiles/constants.h"
#include "components/ntp_tiles/json_unsafe_parser.h"
#include "components/ntp_tiles/pref_names.h"
-#include "components/ntp_tiles/switches.h"
#include "components/ntp_tiles/tile_source.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
@@ -100,8 +99,6 @@ class PopularSitesTest : public ::testing::Test {
},
prefs_(new sync_preferences::TestingPrefServiceSyncable()),
url_fetcher_factory_(nullptr) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableNTPPopularSites);
PopularSitesImpl::RegisterProfilePrefs(prefs_->registry());
}
@@ -113,9 +110,9 @@ class PopularSitesTest : public ::testing::Test {
std::unique_ptr<base::ListValue> CreateListFromTestSites(
const TestPopularSiteVector& sites) {
- auto sites_value = base::MakeUnique<base::ListValue>();
+ auto sites_value = std::make_unique<base::ListValue>();
for (const TestPopularSite& site : sites) {
- auto site_value = base::MakeUnique<base::DictionaryValue>();
+ auto site_value = std::make_unique<base::DictionaryValue>();
for (const std::pair<std::string, std::string>& kv : site) {
if (kv.first == kTitleSource) {
int source;
@@ -143,7 +140,7 @@ class PopularSitesTest : public ::testing::Test {
const TestPopularSectionVector& sections) {
base::ListValue sections_value;
for (const TestPopularSection& section : sections) {
- auto section_value = base::MakeUnique<base::DictionaryValue>();
+ auto section_value = std::make_unique<base::DictionaryValue>();
section_value->SetInteger(kSection, static_cast<int>(section.first));
section_value->SetList(kSites, CreateListFromTestSites(section.second));
sections_value.Append(std::move(section_value));
@@ -165,7 +162,7 @@ class PopularSitesTest : public ::testing::Test {
}
void ReregisterProfilePrefs() {
- prefs_ = base::MakeUnique<sync_preferences::TestingPrefServiceSyncable>();
+ prefs_ = std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
PopularSitesImpl::RegisterProfilePrefs(prefs_->registry());
}
@@ -209,7 +206,7 @@ class PopularSitesTest : public ::testing::Test {
std::unique_ptr<PopularSites> CreatePopularSites(
net::URLRequestContextGetter* context) {
- return base::MakeUnique<PopularSitesImpl>(
+ return std::make_unique<PopularSitesImpl>(
prefs_.get(),
/*template_url_service=*/nullptr,
/*variations_service=*/nullptr, context,
diff --git a/chromium/components/ntp_tiles/switches.cc b/chromium/components/ntp_tiles/switches.cc
index 9ae60506c5d..9481e524b1b 100644
--- a/chromium/components/ntp_tiles/switches.cc
+++ b/chromium/components/ntp_tiles/switches.cc
@@ -12,11 +12,5 @@ namespace switches {
const char kEnableNTPSearchEngineCountryDetection[] =
"enable-ntp-search-engine-country-detection";
-// Enables showing popular sites on the NTP.
-const char kEnableNTPPopularSites[] = "enable-ntp-popular-sites";
-
-// Disables showing popular sites on the NTP.
-const char kDisableNTPPopularSites[] = "disable-ntp-popular-sites";
-
} // namespace switches
} // namespace ntp_tiles
diff --git a/chromium/components/ntp_tiles/switches.h b/chromium/components/ntp_tiles/switches.h
index 2405e7d185a..8541b97960a 100644
--- a/chromium/components/ntp_tiles/switches.h
+++ b/chromium/components/ntp_tiles/switches.h
@@ -10,9 +10,6 @@ namespace switches {
extern const char kEnableNTPSearchEngineCountryDetection[];
-extern const char kEnableNTPPopularSites[];
-extern const char kDisableNTPPopularSites[];
-
} // namespace switches
} // namespace ntp_tiles
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 180aa2602ab..d0060697d39 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
@@ -5,6 +5,7 @@
#include "components/ntp_tiles/webui/ntp_tiles_internals_message_handler.h"
#include <array>
+#include <memory>
#include <utility>
#include <vector>
@@ -14,7 +15,6 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/task_runner_util.h"
#include "base/values.h"
#include "components/favicon/core/favicon_service.h"
@@ -243,23 +243,23 @@ void NTPTilesInternalsMessageHandler::SendSourceInfo() {
void NTPTilesInternalsMessageHandler::SendTiles(
const NTPTilesVector& tiles,
const FaviconResultMap& result_map) {
- auto sites_list = base::MakeUnique<base::ListValue>();
+ auto sites_list = std::make_unique<base::ListValue>();
for (const NTPTile& tile : tiles) {
- auto entry = base::MakeUnique<base::DictionaryValue>();
+ auto entry = std::make_unique<base::DictionaryValue>();
entry->SetString("title", tile.title);
entry->SetString("url", tile.url.spec());
entry->SetInteger("source", static_cast<int>(tile.source));
entry->SetString("whitelistIconPath",
tile.whitelist_icon_path.LossyDisplayName());
- auto icon_list = base::MakeUnique<base::ListValue>();
+ auto icon_list = std::make_unique<base::ListValue>();
for (const auto& entry : kIconTypesAndNames) {
FaviconResultMap::const_iterator it = result_map.find(
FaviconResultMap::key_type(tile.url, entry.type_enum));
if (it != result_map.end()) {
const favicon_base::FaviconRawBitmapResult& result = it->second;
- auto icon = base::MakeUnique<base::DictionaryValue>();
+ auto icon = std::make_unique<base::DictionaryValue>();
icon->SetString("url", result.icon_url.spec());
icon->SetString("type", entry.type_name);
icon->SetBoolean("onDemand", !result.fetched_because_of_page_visit);
diff --git a/chromium/components/offline_items_collection/core/BUILD.gn b/chromium/components/offline_items_collection/core/BUILD.gn
index b2ef4a55c3d..ab83bd1dbd0 100644
--- a/chromium/components/offline_items_collection/core/BUILD.gn
+++ b/chromium/components/offline_items_collection/core/BUILD.gn
@@ -16,6 +16,7 @@ static_library("core") {
"offline_item.h",
"offline_item_filter.h",
"offline_item_state.h",
+ "pending_state.h",
"throttled_offline_content_provider.cc",
"throttled_offline_content_provider.h",
]
@@ -101,6 +102,7 @@ if (is_android) {
"offline_item.h",
"offline_item_filter.h",
"offline_item_state.h",
+ "pending_state.h",
]
}
}
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 8f50f18edaa..e0a713fd989 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
@@ -4,6 +4,8 @@
#include "components/offline_items_collection/core/android/offline_content_aggregator_bridge.h"
+#include <memory>
+
#include "base/android/callback_android.h"
#include "base/android/jni_string.h"
#include "base/bind.h"
@@ -81,7 +83,7 @@ OfflineContentAggregatorBridge::GetBridgeForOfflineContentAggregator(
OfflineContentAggregatorBridge::OfflineContentAggregatorBridge(
OfflineContentAggregator* aggregator)
- : provider_(base::MakeUnique<ThrottledOfflineContentProvider>(aggregator)) {
+ : provider_(std::make_unique<ThrottledOfflineContentProvider>(aggregator)) {
JNIEnv* env = AttachCurrentThread();
java_ref_.Reset(Java_OfflineContentAggregatorBridge_create(
env, reinterpret_cast<intptr_t>(this)));
@@ -98,12 +100,6 @@ OfflineContentAggregatorBridge::~OfflineContentAggregatorBridge() {
java_ref_);
}
-jboolean OfflineContentAggregatorBridge::AreItemsAvailable(
- JNIEnv* env,
- const JavaParamRef<jobject>& jobj) {
- return provider_->AreItemsAvailable();
-}
-
void OfflineContentAggregatorBridge::OpenItem(
JNIEnv* env,
const JavaParamRef<jobject>& jobj,
@@ -189,15 +185,6 @@ void OfflineContentAggregatorBridge::GetVisualsForItem(
ScopedJavaGlobalRef<jobject>(env, j_callback)));
}
-void OfflineContentAggregatorBridge::OnItemsAvailable(
- OfflineContentProvider* provider) {
- if (java_ref_.is_null())
- return;
-
- JNIEnv* env = AttachCurrentThread();
- Java_OfflineContentAggregatorBridge_onItemsAvailable(env, java_ref_);
-}
-
void OfflineContentAggregatorBridge::OnItemsAdded(
const OfflineContentProvider::OfflineItemList& items) {
if (java_ref_.is_null())
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 f9463b817d7..e55f3376760 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
@@ -37,8 +37,6 @@ class OfflineContentAggregatorBridge : public OfflineContentProvider::Observer,
~OfflineContentAggregatorBridge() override;
// Methods called from Java via JNI.
- jboolean AreItemsAvailable(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& jobj);
void OpenItem(JNIEnv* env,
const base::android::JavaParamRef<jobject>& jobj,
const base::android::JavaParamRef<jstring>& j_namespace,
@@ -79,7 +77,6 @@ class OfflineContentAggregatorBridge : public OfflineContentProvider::Observer,
OfflineContentAggregatorBridge(OfflineContentAggregator* aggregator);
// OfflineContentProvider::Observer implementation.
- void OnItemsAvailable(OfflineContentProvider* provider) override;
void OnItemsAdded(
const OfflineContentProvider::OfflineItemList& items) override;
void OnItemRemoved(const ContentId& id) override;
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 96cf418690e..58a42173ca9 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
@@ -39,7 +39,8 @@ JNI_OfflineItemBridge_createOfflineItemAndMaybeAddToList(
ConvertUTF8ToJavaString(env, item.mime_type),
ConvertUTF8ToJavaString(env, item.page_url.spec()),
ConvertUTF8ToJavaString(env, item.original_url.spec()),
- item.is_off_the_record, static_cast<jint>(item.state), item.is_resumable,
+ item.is_off_the_record, static_cast<jint>(item.state),
+ static_cast<jint>(item.pendingState), item.is_resumable,
item.allow_metered, item.received_bytes, item.progress.value,
item.progress.max.value_or(-1), static_cast<jint>(item.progress.unit),
item.time_remaining_ms);
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 2e6c1f50558..d548e8b606a 100644
--- a/chromium/components/offline_items_collection/core/offline_content_aggregator.cc
+++ b/chromium/components/offline_items_collection/core/offline_content_aggregator.cc
@@ -29,7 +29,7 @@ bool MapContainsValue(const std::map<T, U>& map, U value) {
} // namespace
OfflineContentAggregator::OfflineContentAggregator()
- : sent_on_items_available_(false), weak_ptr_factory_(this) {}
+ : weak_ptr_factory_(this) {}
OfflineContentAggregator::~OfflineContentAggregator() = default;
@@ -60,22 +60,16 @@ void OfflineContentAggregator::UnregisterProvider(
// associated with any other namespace.
if (!MapContainsValue(providers_, provider)) {
provider->RemoveObserver(this);
- pending_actions_.erase(provider);
}
}
-bool OfflineContentAggregator::AreItemsAvailable() {
- return sent_on_items_available_;
-}
-
void OfflineContentAggregator::OpenItem(const ContentId& id) {
auto it = providers_.find(id.name_space);
if (it == providers_.end())
return;
- RunIfReady(it->second, base::Bind(&OfflineContentProvider::OpenItem,
- base::Unretained(it->second), id));
+ it->second->OpenItem(id);
}
void OfflineContentAggregator::RemoveItem(const ContentId& id) {
@@ -84,8 +78,7 @@ void OfflineContentAggregator::RemoveItem(const ContentId& id) {
if (it == providers_.end())
return;
- RunIfReady(it->second, base::Bind(&OfflineContentProvider::RemoveItem,
- base::Unretained(it->second), id));
+ it->second->RemoveItem(id);
}
void OfflineContentAggregator::CancelDownload(const ContentId& id) {
@@ -94,8 +87,7 @@ void OfflineContentAggregator::CancelDownload(const ContentId& id) {
if (it == providers_.end())
return;
- RunIfReady(it->second, base::Bind(&OfflineContentProvider::CancelDownload,
- base::Unretained(it->second), id));
+ it->second->CancelDownload(id);
}
void OfflineContentAggregator::PauseDownload(const ContentId& id) {
@@ -104,8 +96,7 @@ void OfflineContentAggregator::PauseDownload(const ContentId& id) {
if (it == providers_.end())
return;
- RunIfReady(it->second, base::Bind(&OfflineContentProvider::PauseDownload,
- base::Unretained(it->second), id));
+ it->second->PauseDownload(id);
}
void OfflineContentAggregator::ResumeDownload(const ContentId& id,
@@ -115,15 +106,13 @@ void OfflineContentAggregator::ResumeDownload(const ContentId& id,
if (it == providers_.end())
return;
- RunIfReady(it->second,
- base::Bind(&OfflineContentProvider::ResumeDownload,
- base::Unretained(it->second), id, has_user_gesture));
+ it->second->ResumeDownload(id, has_user_gesture);
}
void OfflineContentAggregator::GetItemById(const ContentId& id,
SingleItemCallback callback) {
auto it = providers_.find(id.name_space);
- if (it == providers_.end() || !it->second->AreItemsAvailable()) {
+ if (it == providers_.end()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
return;
@@ -151,8 +140,6 @@ void OfflineContentAggregator::GetAllItems(MultipleItemCallback callback) {
DCHECK(aggregated_items_.empty());
for (auto provider_it : providers_) {
auto* provider = provider_it.second;
- if (!provider->AreItemsAvailable())
- continue;
provider->GetAllItems(
base::BindOnce(&OfflineContentAggregator::OnGetAllItemsDone,
@@ -206,13 +193,6 @@ void OfflineContentAggregator::AddObserver(
return;
observers_.AddObserver(observer);
-
- if (sent_on_items_available_ || providers_.empty()) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&OfflineContentAggregator::CheckAndNotifyItemsAvailable,
- weak_ptr_factory_.GetWeakPtr()));
- }
}
void OfflineContentAggregator::RemoveObserver(
@@ -221,37 +201,9 @@ void OfflineContentAggregator::RemoveObserver(
if (!observers_.HasObserver(observer))
return;
- signaled_observers_.erase(observer);
observers_.RemoveObserver(observer);
}
-void OfflineContentAggregator::NotifyItemsAdded(const OfflineItemList& items) {
- if (items.empty())
- return;
-
- for (auto* observer : signaled_observers_)
- observer->OnItemsAdded(items);
-}
-
-void OfflineContentAggregator::OnItemsAvailable(
- OfflineContentProvider* provider) {
- // Flush any pending actions that should be mirrored to the provider.
- FlushPendingActionsIfReady(provider);
-
- // Some observers might already be under the impression that this class was
- // initialized. Just treat this as an OnItemsAdded and notify those observers
- // of the new items.
- if (signaled_observers_.size() > 0) {
- provider->GetAllItems(
- base::BindOnce(&OfflineContentAggregator::NotifyItemsAdded,
- weak_ptr_factory_.GetWeakPtr()));
- }
-
- // Check if there were any observers who haven't been told that this class is
- // initialized yet. If so, notify them now.
- CheckAndNotifyItemsAvailable();
-}
-
void OfflineContentAggregator::OnItemsAdded(const OfflineItemList& items) {
for (auto& observer : observers_)
observer.OnItemsAdded(items);
@@ -267,54 +219,4 @@ void OfflineContentAggregator::OnItemUpdated(const OfflineItem& item) {
observer.OnItemUpdated(item);
}
-void OfflineContentAggregator::CheckAndNotifyItemsAvailable() {
- // If we haven't sent out the initialization message yet, make sure all
- // underlying OfflineContentProviders are ready before notifying observers
- // that we're ready to send items.
- if (!sent_on_items_available_) {
- for (auto& it : providers_) {
- if (!it.second->AreItemsAvailable())
- return;
- }
- }
-
- // Notify all observers who haven't been told about the initialization that we
- // are initialized. Track the observers so that we don't notify them again.
- for (auto& observer : observers_) {
- if (!base::ContainsKey(signaled_observers_, &observer)) {
- observer.OnItemsAvailable(this);
- signaled_observers_.insert(&observer);
- }
- }
-
- // Track that we've told the world that we are initialized.
- sent_on_items_available_ = true;
-}
-
-void OfflineContentAggregator::FlushPendingActionsIfReady(
- OfflineContentProvider* provider) {
- DCHECK(MapContainsValue(providers_, provider));
-
- if (!provider->AreItemsAvailable())
- return;
-
- CallbackList actions = std::move(pending_actions_[provider]);
- for (auto& action : actions) {
- action.Run();
-
- // Check to see if the OfflineContentProvider was removed during the call to
- // |action|. If so stop the loop.
- if (pending_actions_.find(provider) == pending_actions_.end())
- return;
- }
-}
-
-void OfflineContentAggregator::RunIfReady(OfflineContentProvider* provider,
- const base::Closure& action) {
- if (provider->AreItemsAvailable())
- action.Run();
- else
- pending_actions_[provider].push_back(action);
-}
-
} // namespace offline_items_collection
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 dce7ffab37b..144ac00ae3b 100644
--- a/chromium/components/offline_items_collection/core/offline_content_aggregator.h
+++ b/chromium/components/offline_items_collection/core/offline_content_aggregator.h
@@ -24,21 +24,7 @@ struct OfflineItem;
// An implementation of OfflineContentProvider that aggregates multiple other
// providers into a single set of data. See the OfflineContentProvider header
-// for comments on expected behavior of the interface. This implementation has
-// a few caveats:
-// - Once all currently registered providers are initialized this provider will
-// trigger OnItemsAvailable on all observers. Until then the provider will
-// not be initialized.
-// - If a provider is added after OnItemsAvailable was sent, it's initialization
-// will act as a notification for OnItemsAdded. This provider will still be
-// in the initialized state.
-// - Calling any modification method on this provider (Open, Update, Delete,
-// etc.) on an OfflineItem belonging to an uninitialized
-// OfflineContentProvider will be queued until that provider is initialized.
-// NOTE: Any actions taken will be propagated to the provider *before* the
-// observers are notified that the provider is initialized. This is meant to
-// try to guarantee that the data set incorporates the results of those
-// actions.
+// for comments on expected behavior of the interface.
//
// Routing to the correct provider:
// - Providers must be registered with a unique namespace. The OfflineItems
@@ -58,16 +44,8 @@ class OfflineContentAggregator : public OfflineContentProvider,
// routed to |provider|. |provider| is expected to only expose OfflineItems
// with |name_space| set.
// It is okay to register the same provider with multiple unique namespaces.
- // The class will work as expected with a few caveats. These are fixable if
- // they are necessary for proper operation. Contact dtrainor@ if changes to
- // this behavior is needed.
- // 1. Unregistering the first namespace won't remove any pending actions
- // that are queued for this provider. That means the provider might
- // still get actions for the removed namespace once it is done
- // initializing itself. This case must be handled by the individual
- // provider for now.
- // 2. The provider needs to handle calls to GetAllItems properly (not return
- // any items for a namespace that it didn't register).
+ // A provider needs to handle calls to GetAllItems properly (not return
+ // any items for a namespace that it didn't register).
void RegisterProvider(const std::string& name_space,
OfflineContentProvider* provider);
@@ -76,7 +54,6 @@ class OfflineContentAggregator : public OfflineContentProvider,
void UnregisterProvider(const std::string& name_space);
// OfflineContentProvider implementation.
- bool AreItemsAvailable() override;
void OpenItem(const ContentId& id) override;
void RemoveItem(const ContentId& id) override;
void CancelDownload(const ContentId& id) override;
@@ -91,28 +68,10 @@ class OfflineContentAggregator : public OfflineContentProvider,
private:
// OfflineContentProvider::Observer implementation.
- void OnItemsAvailable(OfflineContentProvider* provider) override;
void OnItemsAdded(const OfflineItemList& items) override;
void OnItemRemoved(const ContentId& id) override;
void OnItemUpdated(const OfflineItem& item) override;
- // Checks if the underlying OfflineContentProviders are available. If so,
- // it calls OnItemsAvailable on all observers that haven't yet been notified
- // of this.
- void CheckAndNotifyItemsAvailable();
-
- // Checks to see if |provider| is initialized. If so, this flushes any
- // pending actions taken on OfflineItems that belong to |provider|.
- void FlushPendingActionsIfReady(OfflineContentProvider* provider);
-
- // Checks if |provider| is initialized. If so, runs |action|, otherwise
- // queues it to run once |provider| triggers that it is ready.
- // NOTE: It is expected that |provider| is the same as the
- // OfflineContentProvider bound in |action|. The class provides safety checks
- // for that scenario only.
- void RunIfReady(OfflineContentProvider* provider,
- const base::Closure& action);
-
void OnGetAllItemsDone(OfflineContentProvider* provider,
const OfflineItemList& items);
void OnGetItemByIdDone(SingleItemCallback callback,
@@ -125,13 +84,6 @@ class OfflineContentAggregator : public OfflineContentProvider,
using OfflineProviderMap = std::map<std::string, OfflineContentProvider*>;
OfflineProviderMap providers_;
- // Stores a map of OfflineContentProvider -> list of closures that represent
- // all actions that need to be taken on the associated OfflineContentProvider
- // when it becomes initialized.
- using CallbackList = std::vector<base::Closure>;
- using PendingActionMap = std::map<OfflineContentProvider*, CallbackList>;
- PendingActionMap pending_actions_;
-
// Used by GetAllItems and the corresponding callback.
std::vector<MultipleItemCallback> multiple_item_get_callbacks_;
OfflineItemList aggregated_items_;
@@ -140,16 +92,6 @@ class OfflineContentAggregator : public OfflineContentProvider,
// A list of all currently registered observers.
base::ObserverList<OfflineContentProvider::Observer> observers_;
- // A set of observers that have been notified that this class is initialized.
- // We do not want to notify them of this initialization more than once, so
- // we track them here.
- using ObserverSet = std::set<OfflineContentProvider::Observer*>;
- ObserverSet signaled_observers_;
-
- // Whether or not this class currently identifies itself as available and has
- // notified the observers.
- bool sent_on_items_available_;
-
base::WeakPtrFactory<OfflineContentAggregator> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(OfflineContentAggregator);
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 152af275e6a..1efa4571405 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
@@ -114,89 +114,9 @@ void OfflineContentAggregatorTest::GetSingleItemAndVerify(
task_runner_->RunUntilIdle();
}
-TEST_F(OfflineContentAggregatorTest, ObserversAddedBeforeProvidersAvailable) {
+TEST_F(OfflineContentAggregatorTest, QueryingItemsWith2Providers) {
ScopedMockOfflineContentProvider provider1("1", &aggregator_);
ScopedMockOfflineContentProvider provider2("2", &aggregator_);
- EXPECT_FALSE(aggregator_.AreItemsAvailable());
- EXPECT_TRUE(provider1.HasObserver(&aggregator_));
- EXPECT_TRUE(provider2.HasObserver(&aggregator_));
-
- ScopedMockOfflineContentProvider::ScopedMockObserver observer1(&aggregator_);
- ScopedMockOfflineContentProvider::ScopedMockObserver observer2(&aggregator_);
- task_runner_->RunUntilIdle();
-
- {
- EXPECT_CALL(observer1, OnItemsAvailable(&aggregator_)).Times(0);
- EXPECT_CALL(observer2, OnItemsAvailable(&aggregator_)).Times(0);
- provider1.NotifyOnItemsAvailable();
- }
-
- {
- EXPECT_CALL(observer1, OnItemsAvailable(&aggregator_)).Times(1);
- EXPECT_CALL(observer2, OnItemsAvailable(&aggregator_)).Times(1);
- provider2.NotifyOnItemsAvailable();
- }
-}
-
-TEST_F(OfflineContentAggregatorTest, ObserversAddedAfterProvidersAvailable) {
- ScopedMockOfflineContentProvider provider1("1", &aggregator_);
- ScopedMockOfflineContentProvider provider2("2", &aggregator_);
- EXPECT_FALSE(aggregator_.AreItemsAvailable());
- EXPECT_TRUE(provider1.HasObserver(&aggregator_));
- EXPECT_TRUE(provider2.HasObserver(&aggregator_));
-
- provider1.NotifyOnItemsAvailable();
- provider2.NotifyOnItemsAvailable();
-
- {
- ScopedMockOfflineContentProvider::ScopedMockObserver observer1(
- &aggregator_);
- ScopedMockOfflineContentProvider::ScopedMockObserver observer2(
- &aggregator_);
- EXPECT_CALL(observer1, OnItemsAvailable(&aggregator_)).Times(1);
- EXPECT_CALL(observer2, OnItemsAvailable(&aggregator_)).Times(1);
- task_runner_->RunUntilIdle();
- }
-}
-
-TEST_F(OfflineContentAggregatorTest,
- ProvidersAddedAfterObserversNotifiedAvailable) {
- ScopedMockOfflineContentProvider provider1("1", &aggregator_);
- EXPECT_FALSE(aggregator_.AreItemsAvailable());
- EXPECT_TRUE(provider1.HasObserver(&aggregator_));
-
- ScopedMockOfflineContentProvider::ScopedMockObserver observer1(&aggregator_);
- ScopedMockOfflineContentProvider::ScopedMockObserver observer2(&aggregator_);
- task_runner_->RunUntilIdle();
-
- {
- EXPECT_CALL(observer1, OnItemsAvailable(&aggregator_)).Times(1);
- EXPECT_CALL(observer2, OnItemsAvailable(&aggregator_)).Times(1);
- provider1.NotifyOnItemsAvailable();
- }
-
- {
- OfflineContentProvider::OfflineItemList items;
- items.push_back(OfflineItem());
-
- ScopedMockOfflineContentProvider provider2("2", &aggregator_);
- provider2.SetItems(items);
- EXPECT_TRUE(provider2.HasObserver(&aggregator_));
- GetAllItemsAndVerify(&provider2, items);
-
- EXPECT_CALL(observer1, OnItemsAvailable(&aggregator_)).Times(0);
- EXPECT_CALL(observer2, OnItemsAvailable(&aggregator_)).Times(0);
- EXPECT_CALL(observer1, OnItemsAdded(items)).Times(1);
- EXPECT_CALL(observer2, OnItemsAdded(items)).Times(1);
- provider2.NotifyOnItemsAvailable();
- task_runner_->RunUntilIdle();
- }
-}
-
-TEST_F(OfflineContentAggregatorTest, QueryingItemsWithProviderThatIsntReady) {
- ScopedMockOfflineContentProvider provider1("1", &aggregator_);
- ScopedMockOfflineContentProvider provider2("2", &aggregator_);
- EXPECT_FALSE(aggregator_.AreItemsAvailable());
OfflineContentProvider::OfflineItemList empty;
OfflineContentProvider::OfflineItemList items1;
@@ -212,14 +132,8 @@ TEST_F(OfflineContentAggregatorTest, QueryingItemsWithProviderThatIsntReady) {
GetAllItemsAndVerify(&provider1, items1);
GetAllItemsAndVerify(&provider2, items2);
- GetAllItemsAndVerify(&aggregator_, empty);
-
- provider1.NotifyOnItemsAvailable();
- GetAllItemsAndVerify(&aggregator_, items1);
-
OfflineContentProvider::OfflineItemList combined_items(items1);
combined_items.insert(combined_items.end(), items2.begin(), items2.end());
- provider2.NotifyOnItemsAvailable();
GetAllItemsAndVerify(&aggregator_, combined_items);
}
@@ -229,9 +143,6 @@ TEST_F(OfflineContentAggregatorTest, QueryingItemFromRemovedProvider) {
{
ScopedMockOfflineContentProvider provider("1", &aggregator_);
- provider.NotifyOnItemsAvailable();
- EXPECT_TRUE(aggregator_.AreItemsAvailable());
-
provider.SetItems({item});
GetSingleItemAndVerify(&aggregator_, id, item);
}
@@ -239,41 +150,9 @@ TEST_F(OfflineContentAggregatorTest, QueryingItemFromRemovedProvider) {
GetSingleItemAndVerify(&aggregator_, id, base::nullopt);
}
-TEST_F(OfflineContentAggregatorTest, QueryingItemWithProviderThatIsntReady) {
- ScopedMockOfflineContentProvider provider1("1", &aggregator_);
- ScopedMockOfflineContentProvider provider2("2", &aggregator_);
- EXPECT_FALSE(aggregator_.AreItemsAvailable());
-
- ContentId id1("1", "A");
- ContentId id2("2", "B");
- ContentId id3("3", "C");
-
- OfflineItem item1(id1);
- OfflineItem item2(id2);
-
- provider1.SetItems({item1});
- provider2.SetItems({item2});
-
- GetSingleItemAndVerify(&aggregator_, id1, base::nullopt);
- GetSingleItemAndVerify(&aggregator_, id2, base::nullopt);
- GetSingleItemAndVerify(&aggregator_, id3, base::nullopt);
-
- provider1.NotifyOnItemsAvailable();
- GetSingleItemAndVerify(&aggregator_, id1, item1);
- GetSingleItemAndVerify(&aggregator_, id2, base::nullopt);
- GetSingleItemAndVerify(&aggregator_, id3, base::nullopt);
-
- provider2.NotifyOnItemsAvailable();
- GetSingleItemAndVerify(&aggregator_, id1, item1);
- GetSingleItemAndVerify(&aggregator_, id2, item2);
- GetSingleItemAndVerify(&aggregator_, id3, base::nullopt);
-}
-
TEST_F(OfflineContentAggregatorTest, GetItemByIdPropagatesToRightProvider) {
ScopedMockOfflineContentProvider provider1("1", &aggregator_);
ScopedMockOfflineContentProvider provider2("2", &aggregator_);
- provider1.NotifyOnItemsAvailable();
- provider2.NotifyOnItemsAvailable();
ContentId id1("1", "A");
ContentId id2("2", "B");
@@ -290,40 +169,9 @@ TEST_F(OfflineContentAggregatorTest, GetItemByIdPropagatesToRightProvider) {
GetSingleItemAndVerify(&aggregator_, id4, base::nullopt);
}
-TEST_F(OfflineContentAggregatorTest, AreItemsAvailable) {
- ScopedMockOfflineContentProvider provider1("1", &aggregator_);
- ScopedMockOfflineContentProvider provider2("2", &aggregator_);
-
- ScopedMockOfflineContentProvider::ScopedMockObserver observer1(&aggregator_);
- ScopedMockOfflineContentProvider::ScopedMockObserver observer2(&aggregator_);
- task_runner_->RunUntilIdle();
-
- EXPECT_FALSE(aggregator_.AreItemsAvailable());
-
- {
- EXPECT_CALL(observer1, OnItemsAvailable(&aggregator_)).Times(0);
- EXPECT_CALL(observer2, OnItemsAvailable(&aggregator_)).Times(0);
-
- provider1.NotifyOnItemsAvailable();
- }
-
- EXPECT_FALSE(aggregator_.AreItemsAvailable());
-
- {
- EXPECT_CALL(observer1, OnItemsAvailable(&aggregator_)).Times(1);
- EXPECT_CALL(observer2, OnItemsAvailable(&aggregator_)).Times(1);
-
- provider2.NotifyOnItemsAvailable();
- }
-
- EXPECT_TRUE(aggregator_.AreItemsAvailable());
-}
-
TEST_F(OfflineContentAggregatorTest, ActionPropagatesToRightProvider) {
ScopedMockOfflineContentProvider provider1("1", &aggregator_);
ScopedMockOfflineContentProvider provider2("2", &aggregator_);
- provider1.NotifyOnItemsAvailable();
- provider2.NotifyOnItemsAvailable();
testing::InSequence sequence;
ContentId id1("1", "A");
@@ -354,7 +202,7 @@ TEST_F(OfflineContentAggregatorTest, ActionPropagatesToRightProvider) {
aggregator_.GetVisualsForItem(id2, OfflineContentProvider::VisualsCallback());
}
-TEST_F(OfflineContentAggregatorTest, ActionPropagatesAfterInitialize) {
+TEST_F(OfflineContentAggregatorTest, ActionPropagatesImmediately) {
ScopedMockOfflineContentProvider provider1("1", &aggregator_);
ScopedMockOfflineContentProvider provider2("2", &aggregator_);
@@ -362,44 +210,27 @@ TEST_F(OfflineContentAggregatorTest, ActionPropagatesAfterInitialize) {
ContentId id2("2", "B");
ContentId id3("2", "C");
- {
- EXPECT_CALL(provider1, PauseDownload(id1)).Times(0);
- aggregator_.PauseDownload(id1);
- }
-
- {
- testing::InSequence sequence;
- EXPECT_CALL(provider1, PauseDownload(id1)).Times(1);
- EXPECT_CALL(provider1, ResumeDownload(id1, true)).Times(1);
- EXPECT_CALL(provider1, OpenItem(id1)).Times(1);
- EXPECT_CALL(provider2, OpenItem(id2)).Times(0);
-
- aggregator_.ResumeDownload(id1, true);
- aggregator_.OpenItem(id1);
- provider1.NotifyOnItemsAvailable();
- aggregator_.OpenItem(id2);
- }
+ testing::InSequence sequence;
+ EXPECT_CALL(provider1, PauseDownload(id1)).Times(1);
+ EXPECT_CALL(provider1, ResumeDownload(id1, true)).Times(1);
+ EXPECT_CALL(provider1, OpenItem(id1)).Times(1);
+ EXPECT_CALL(provider2, OpenItem(id2)).Times(1);
+ EXPECT_CALL(provider2, RemoveItem(id3)).Times(1);
- {
- testing::InSequence sequence;
- EXPECT_CALL(provider2, OpenItem(id2)).Times(1);
- EXPECT_CALL(provider2, RemoveItem(id3)).Times(1);
- aggregator_.RemoveItem(id3);
- provider2.NotifyOnItemsAvailable();
- }
+ aggregator_.PauseDownload(id1);
+ aggregator_.ResumeDownload(id1, true);
+ aggregator_.OpenItem(id1);
+ aggregator_.OpenItem(id2);
+ aggregator_.RemoveItem(id3);
}
TEST_F(OfflineContentAggregatorTest, OnItemsAddedPropagatedToObservers) {
ScopedMockOfflineContentProvider provider1("1", &aggregator_);
ScopedMockOfflineContentProvider provider2("2", &aggregator_);
- provider1.NotifyOnItemsAvailable();
- provider2.NotifyOnItemsAvailable();
ScopedMockOfflineContentProvider::ScopedMockObserver observer1(&aggregator_);
ScopedMockOfflineContentProvider::ScopedMockObserver observer2(&aggregator_);
- EXPECT_CALL(observer1, OnItemsAvailable(&aggregator_)).Times(1);
- EXPECT_CALL(observer2, OnItemsAvailable(&aggregator_)).Times(1);
task_runner_->RunUntilIdle();
OfflineContentProvider::OfflineItemList items1;
@@ -421,14 +252,10 @@ TEST_F(OfflineContentAggregatorTest, OnItemsAddedPropagatedToObservers) {
TEST_F(OfflineContentAggregatorTest, OnItemRemovedPropagatedToObservers) {
ScopedMockOfflineContentProvider provider1("1", &aggregator_);
ScopedMockOfflineContentProvider provider2("2", &aggregator_);
- provider1.NotifyOnItemsAvailable();
- provider2.NotifyOnItemsAvailable();
ScopedMockOfflineContentProvider::ScopedMockObserver observer1(&aggregator_);
ScopedMockOfflineContentProvider::ScopedMockObserver observer2(&aggregator_);
- EXPECT_CALL(observer1, OnItemsAvailable(&aggregator_)).Times(1);
- EXPECT_CALL(observer2, OnItemsAvailable(&aggregator_)).Times(1);
task_runner_->RunUntilIdle();
ContentId id1("1", "A");
@@ -445,14 +272,10 @@ TEST_F(OfflineContentAggregatorTest, OnItemRemovedPropagatedToObservers) {
TEST_F(OfflineContentAggregatorTest, OnItemUpdatedPropagatedToObservers) {
ScopedMockOfflineContentProvider provider1("1", &aggregator_);
ScopedMockOfflineContentProvider provider2("2", &aggregator_);
- provider1.NotifyOnItemsAvailable();
- provider2.NotifyOnItemsAvailable();
ScopedMockOfflineContentProvider::ScopedMockObserver observer1(&aggregator_);
ScopedMockOfflineContentProvider::ScopedMockObserver observer2(&aggregator_);
- EXPECT_CALL(observer1, OnItemsAvailable(&aggregator_)).Times(1);
- EXPECT_CALL(observer2, OnItemsAvailable(&aggregator_)).Times(1);
task_runner_->RunUntilIdle();
OfflineItem item1(ContentId("1", "A"));
@@ -471,13 +294,13 @@ TEST_F(OfflineContentAggregatorTest, ProviderRemovedDuringCallbackFlush) {
ContentId id1("1", "A");
ContentId id2("1", "B");
- aggregator_.OpenItem(id1);
- aggregator_.OpenItem(id2);
- aggregator_.RemoveItem(id2);
EXPECT_CALL(provider1, OpenItem(id1)).Times(1);
EXPECT_CALL(provider1, RemoveItem(id2)).Times(0);
- provider1.NotifyOnItemsAvailable();
+
+ aggregator_.OpenItem(id1);
+ aggregator_.OpenItem(id2);
+ aggregator_.RemoveItem(id2);
}
TEST_F(OfflineContentAggregatorTest, SameProviderWithMultipleNamespaces) {
@@ -497,9 +320,6 @@ TEST_F(OfflineContentAggregatorTest, SameProviderWithMultipleNamespaces) {
aggregator_.RegisterProvider("2", &provider);
EXPECT_TRUE(provider.HasObserver(&aggregator_));
- EXPECT_CALL(observer, OnItemsAvailable(&aggregator_)).Times(1);
- provider.NotifyOnItemsAvailable();
-
GetAllItemsAndVerify(&aggregator_, items);
GetSingleItemAndVerify(&aggregator_, id1, item1);
GetSingleItemAndVerify(&aggregator_, id2, item2);
@@ -513,14 +333,5 @@ TEST_F(OfflineContentAggregatorTest, SameProviderWithMultipleNamespaces) {
EXPECT_FALSE(provider.HasObserver(&aggregator_));
}
-// Test that ensures if no provider is registered, the observer can get an
-// initialization signal.
-TEST_F(OfflineContentAggregatorTest, NoProviderWithObserver) {
- ScopedMockOfflineContentProvider::ScopedMockObserver observer;
- EXPECT_CALL(observer, OnItemsAvailable(&aggregator_)).Times(1);
- observer.AddProvider(&aggregator_);
- task_runner_->RunUntilIdle();
-}
-
} // namespace
} // namespace offline_items_collection
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 848142a524f..d2a37c7caf7 100644
--- a/chromium/components/offline_items_collection/core/offline_content_provider.h
+++ b/chromium/components/offline_items_collection/core/offline_content_provider.h
@@ -20,9 +20,6 @@ struct OfflineItem;
struct OfflineItemVisuals;
// A provider of a set of OfflineItems that are meant to be exposed to the UI.
-// The provider is required to notify all observers of OnItemsAvailable when the
-// underlying data set is initialized. Without that call it should not expect
-// nor have to support any other calls to this provider.
class OfflineContentProvider {
public:
using OfflineItemList = std::vector<OfflineItem>;
@@ -34,37 +31,35 @@ class OfflineContentProvider {
// An observer class that should be notified of relevant changes to the
// underlying data source.
+ // For the Observer that maintains its own cache of items, populated via
+ // GetAllItems method, it is possible to receive notifications that are
+ // out-of-sync with the cache content. See notes on the methods.
class Observer {
public:
- // Called when the underlying data source for the provider has been
- // initialized and the contents are able to be queried and interacted with.
- // |provider| should be a reference to this OfflineContentProvider that is
- // initialized.
- virtual void OnItemsAvailable(OfflineContentProvider* provider) = 0;
-
// Called when one or more OfflineItems have been added and should be shown
// in the UI.
+ // If Observer maintains a cache of items, the specified items may already
+ // be in the cache, in which case this call has to be ignored.
virtual void OnItemsAdded(const OfflineItemList& items) = 0;
// Called when the OfflineItem represented by |id| should be removed from
// the UI.
+ // If Observer maintains a cache of items, item with the specified id may
+ // not be present in the cache, in which case this call should be ignored.
virtual void OnItemRemoved(const ContentId& id) = 0;
// Called when the contents of |item| have been updated and the UI should be
// refreshed for that item.
// TODO(dtrainor): Make this take a list of OfflineItems.
+ // If Observer maintains a cache of items, the changes may already be
+ // applied to the items in the cache, so there is no difference between
+ // items. In this case, this call should be ignored.
virtual void OnItemUpdated(const OfflineItem& item) = 0;
protected:
virtual ~Observer() = default;
};
- // Returns whether or not the underlying data source for this provider has
- // been initialized and is ready to start returning content. This provider
- // should not need to support handling the other data query/manipulation
- // methods if this returns false.
- virtual bool AreItemsAvailable() = 0;
-
// Called to trigger opening an OfflineItem represented by |id|.
virtual void OpenItem(const ContentId& id) = 0;
@@ -100,9 +95,6 @@ class OfflineContentProvider {
const VisualsCallback& callback) = 0;
// Adds an observer that should be notified of OfflineItem list modifications.
- // If the provider is already initialized OnItemsAvailable should be scheduled
- // on this observer (suggested over calling the method directly to avoid
- // reentrancy).
virtual void AddObserver(Observer* observer) = 0;
// Removes an observer. No further notifications should be sent to it.
diff --git a/chromium/components/offline_items_collection/core/offline_item.h b/chromium/components/offline_items_collection/core/offline_item.h
index 7e876cf47ea..f12d8a88e8f 100644
--- a/chromium/components/offline_items_collection/core/offline_item.h
+++ b/chromium/components/offline_items_collection/core/offline_item.h
@@ -12,6 +12,7 @@
#include "base/time/time.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 "ui/gfx/image/image.h"
#include "url/gurl.h"
@@ -149,6 +150,9 @@ struct OfflineItem {
// The current state of the OfflineItem.
OfflineItemState state;
+ // Reason OfflineItem is pending.
+ PendingState pendingState;
+
// Whether or not the offlining of this content can be resumed if it was
// paused or interrupted.
bool is_resumable;
diff --git a/chromium/components/offline_items_collection/core/pending_state.h b/chromium/components/offline_items_collection/core/pending_state.h
new file mode 100644
index 00000000000..5e83a229a3e
--- /dev/null
+++ b/chromium/components/offline_items_collection/core/pending_state.h
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_PENDING_STATE_H_
+#define COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_PENDING_STATE_H_
+
+namespace offline_items_collection {
+
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.offline_items_collection
+enum class PendingState {
+ // Enum for reason OfflineItem is pending, if any.
+ NOT_PENDING, // Download is not pending.
+ PENDING_NETWORK, // Download is pending due to no network connection.
+ PENDING_ANOTHER_DOWNLOAD, // Download is pending because another download
+ // is currently being downloaded.
+};
+
+} // namespace offline_items_collection
+
+#endif // COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_PENDING_STATE_H_
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 9b0898cd27d..8fe7556aaa0 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
@@ -12,8 +12,7 @@ namespace offline_items_collection {
MockOfflineContentProvider::MockObserver::MockObserver() = default;
MockOfflineContentProvider::MockObserver::~MockObserver() = default;
-MockOfflineContentProvider::MockOfflineContentProvider()
- : items_available_(false) {}
+MockOfflineContentProvider::MockOfflineContentProvider() {}
MockOfflineContentProvider::~MockOfflineContentProvider() = default;
bool MockOfflineContentProvider::HasObserver(Observer* observer) {
@@ -24,12 +23,6 @@ void MockOfflineContentProvider::SetItems(const OfflineItemList& items) {
items_ = items;
}
-void MockOfflineContentProvider::NotifyOnItemsAvailable() {
- items_available_ = true;
- for (auto& observer : observers_)
- observer.OnItemsAvailable(this);
-}
-
void MockOfflineContentProvider::NotifyOnItemsAdded(
const OfflineItemList& items) {
for (auto& observer : observers_)
@@ -46,10 +39,6 @@ void MockOfflineContentProvider::NotifyOnItemUpdated(const OfflineItem& item) {
observer.OnItemUpdated(item);
}
-bool MockOfflineContentProvider::AreItemsAvailable() {
- return items_available_;
-}
-
void MockOfflineContentProvider::GetAllItems(MultipleItemCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), items_));
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 5724c7e3eb9..f4c427eb0e6 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
@@ -21,7 +21,6 @@ class MockOfflineContentProvider : public OfflineContentProvider {
~MockObserver() override;
// OfflineContentProvider::Observer implementation.
- MOCK_METHOD1(OnItemsAvailable, void(OfflineContentProvider*));
MOCK_METHOD1(OnItemsAdded, void(const OfflineItemList&));
MOCK_METHOD1(OnItemRemoved, void(const ContentId&));
MOCK_METHOD1(OnItemUpdated, void(const OfflineItem&));
@@ -32,13 +31,11 @@ class MockOfflineContentProvider : public OfflineContentProvider {
bool HasObserver(Observer* observer);
void SetItems(const OfflineItemList& items);
- void NotifyOnItemsAvailable();
void NotifyOnItemsAdded(const OfflineItemList& items);
void NotifyOnItemRemoved(const ContentId& id);
void NotifyOnItemUpdated(const OfflineItem& item);
// OfflineContentProvider implementation.
- bool AreItemsAvailable() override;
MOCK_METHOD1(OpenItem, void(const ContentId&));
MOCK_METHOD1(RemoveItem, void(const ContentId&));
MOCK_METHOD1(CancelDownload, void(const ContentId&));
@@ -53,7 +50,6 @@ class MockOfflineContentProvider : public OfflineContentProvider {
private:
base::ObserverList<Observer> observers_;
- bool items_available_;
OfflineItemList items_;
};
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 4fb558d88d8..95a22d9d31d 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
@@ -38,10 +38,6 @@ ThrottledOfflineContentProvider::~ThrottledOfflineContentProvider() {
wrapped_provider_->RemoveObserver(this);
}
-bool ThrottledOfflineContentProvider::AreItemsAvailable() {
- return wrapped_provider_->AreItemsAvailable();
-}
-
void ThrottledOfflineContentProvider::OpenItem(const ContentId& id) {
wrapped_provider_->OpenItem(id);
FlushUpdates();
@@ -108,13 +104,6 @@ void ThrottledOfflineContentProvider::AddObserver(
OfflineContentProvider::Observer* observer) {
DCHECK(observer);
observers_.AddObserver(observer);
- if (!wrapped_provider_->AreItemsAvailable())
- return;
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&ThrottledOfflineContentProvider::NotifyItemsAvailable,
- weak_ptr_factory_.GetWeakPtr(), base::Unretained(observer)));
}
void ThrottledOfflineContentProvider::RemoveObserver(
@@ -122,13 +111,6 @@ void ThrottledOfflineContentProvider::RemoveObserver(
observers_.RemoveObserver(observer);
}
-void ThrottledOfflineContentProvider::OnItemsAvailable(
- OfflineContentProvider* provider) {
- DCHECK_EQ(provider, wrapped_provider_);
- for (auto& observer : observers_)
- observer.OnItemsAvailable(this);
-}
-
void ThrottledOfflineContentProvider::OnItemsAdded(
const OfflineItemList& items) {
for (auto& observer : observers_)
@@ -166,13 +148,6 @@ void ThrottledOfflineContentProvider::OnItemUpdated(const OfflineItem& item) {
delay_between_updates_ - current_delay);
}
-void ThrottledOfflineContentProvider::NotifyItemsAvailable(
- OfflineContentProvider::Observer* observer) {
- if (!observers_.HasObserver(observer))
- return;
- observer->OnItemsAvailable(this);
-}
-
void ThrottledOfflineContentProvider::UpdateItemIfPresent(
const OfflineItem& item) {
OfflineItemMap::iterator it = updates_.find(item.id);
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 d2150073561..1558128e7cd 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
@@ -30,9 +30,6 @@ class ThrottledOfflineContentProvider
OfflineContentProvider* provider);
~ThrottledOfflineContentProvider() override;
- // OfflineContentProvider implementation.
- bool AreItemsAvailable() override;
-
// Taking actions on the OfflineContentProvider will flush any queued updates
// immediately after performing the action. This is to make sure item updates
// in response to the update are immediately reflected back to the caller.
@@ -58,7 +55,6 @@ class ThrottledOfflineContentProvider
private:
// OfflineContentProvider::Observer implementation.
- void OnItemsAvailable(OfflineContentProvider* provider) override;
void OnItemsAdded(const OfflineItemList& items) override;
void OnItemRemoved(const ContentId& id) override;
void OnItemUpdated(const OfflineItem& item) override;
@@ -68,10 +64,6 @@ class ThrottledOfflineContentProvider
void OnGetItemByIdDone(SingleItemCallback callback,
const base::Optional<OfflineItem>& item);
- // Used to notify |observer| that the underying OfflineContentProvider has
- // called OfflineContentProvider::Observer::OnItemsAvailable().
- void NotifyItemsAvailable(OfflineContentProvider::Observer* observer);
-
// Checks if |item| already has an update pending. If so, replaces the content
// of the update with |item|.
void UpdateItemIfPresent(const OfflineItem& item);
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 9d4c5fd8a7b..c7038da6011 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
@@ -83,28 +83,6 @@ class ThrottledOfflineContentProviderTest : public testing::Test {
base::WeakPtrFactory<ThrottledOfflineContentProviderTest> weak_ptr_factory_;
};
-TEST_F(ThrottledOfflineContentProviderTest, TestReadyBeforeObserver) {
- EXPECT_FALSE(provider_.AreItemsAvailable());
- wrapped_provider_.NotifyOnItemsAvailable();
- EXPECT_TRUE(provider_.AreItemsAvailable());
-
- ScopedMockOfflineContentProvider::ScopedMockObserver observer1(&provider_);
- ScopedMockOfflineContentProvider::ScopedMockObserver observer2(&provider_);
-
- EXPECT_CALL(observer1, OnItemsAvailable(&provider_));
- EXPECT_CALL(observer2, OnItemsAvailable(&provider_));
- task_runner_->RunUntilIdle();
-}
-
-TEST_F(ThrottledOfflineContentProviderTest, TestReadyAfterObserver) {
- ScopedMockOfflineContentProvider::ScopedMockObserver observer(&provider_);
-
- EXPECT_CALL(observer, OnItemsAvailable(&provider_));
- EXPECT_FALSE(provider_.AreItemsAvailable());
- wrapped_provider_.NotifyOnItemsAvailable();
- EXPECT_TRUE(provider_.AreItemsAvailable());
-}
-
TEST_F(ThrottledOfflineContentProviderTest, TestBasicPassthrough) {
ScopedMockOfflineContentProvider::ScopedMockObserver observer(&provider_);
@@ -115,7 +93,6 @@ TEST_F(ThrottledOfflineContentProviderTest, TestBasicPassthrough) {
items.push_back(item);
testing::InSequence sequence;
- EXPECT_CALL(observer, OnItemsAvailable(&provider_));
EXPECT_CALL(wrapped_provider_, OpenItem(id));
EXPECT_CALL(wrapped_provider_, RemoveItem(id));
EXPECT_CALL(wrapped_provider_, CancelDownload(id));
@@ -123,7 +100,6 @@ TEST_F(ThrottledOfflineContentProviderTest, TestBasicPassthrough) {
EXPECT_CALL(wrapped_provider_, ResumeDownload(id, true));
EXPECT_CALL(wrapped_provider_, GetVisualsForItem(id, _));
wrapped_provider_.SetItems(items);
- wrapped_provider_.NotifyOnItemsAvailable();
provider_.OpenItem(id);
provider_.RemoveItem(id);
provider_.CancelDownload(id);
@@ -150,11 +126,9 @@ TEST_F(ThrottledOfflineContentProviderTest, TestRemoveCancelsUpdate) {
ContentId id("1", "A");
OfflineItem item(id);
- EXPECT_CALL(observer, OnItemsAvailable(&provider_)).Times(1);
EXPECT_CALL(observer, OnItemUpdated(item)).Times(0);
EXPECT_CALL(observer, OnItemRemoved(id)).Times(1);
- wrapped_provider_.NotifyOnItemsAvailable();
provider_.set_last_update_time(base::TimeTicks::Now());
wrapped_provider_.NotifyOnItemUpdated(item);
wrapped_provider_.NotifyOnItemRemoved(id);
@@ -175,11 +149,9 @@ TEST_F(ThrottledOfflineContentProviderTest, TestOnItemUpdatedSquashed) {
OfflineItem updated_item2(id2);
updated_item2.title = "updated2";
- EXPECT_CALL(observer, OnItemsAvailable(&provider_)).Times(1);
EXPECT_CALL(observer, OnItemUpdated(updated_item1)).Times(1);
EXPECT_CALL(observer, OnItemUpdated(updated_item2)).Times(1);
- wrapped_provider_.NotifyOnItemsAvailable();
provider_.set_last_update_time(base::TimeTicks::Now());
wrapped_provider_.NotifyOnItemUpdated(item1);
wrapped_provider_.NotifyOnItemUpdated(item2);
@@ -204,11 +176,9 @@ TEST_F(ThrottledOfflineContentProviderTest, TestGetItemByIdOverridesUpdate) {
std::vector<OfflineItem> items = {item1, item2};
wrapped_provider_.SetItems(items);
- EXPECT_CALL(observer, OnItemsAvailable(&provider_)).Times(1);
EXPECT_CALL(observer, OnItemUpdated(updated_item1)).Times(1);
EXPECT_CALL(observer, OnItemUpdated(item2)).Times(1);
- wrapped_provider_.NotifyOnItemsAvailable();
provider_.set_last_update_time(base::TimeTicks::Now());
wrapped_provider_.NotifyOnItemUpdated(item1);
wrapped_provider_.NotifyOnItemUpdated(item2);
@@ -241,12 +211,10 @@ TEST_F(ThrottledOfflineContentProviderTest, TestGetAllItemsOverridesUpdate) {
items.push_back(updated_item1);
items.push_back(item2);
- EXPECT_CALL(observer, OnItemsAvailable(&provider_)).Times(1);
EXPECT_CALL(observer, OnItemUpdated(updated_item1)).Times(1);
EXPECT_CALL(observer, OnItemUpdated(item2)).Times(1);
wrapped_provider_.SetItems(items);
- wrapped_provider_.NotifyOnItemsAvailable();
provider_.set_last_update_time(base::TimeTicks::Now());
wrapped_provider_.NotifyOnItemUpdated(item1);
wrapped_provider_.NotifyOnItemUpdated(item2);
@@ -273,9 +241,6 @@ TEST_F(ThrottledOfflineContentProviderTest, TestThrottleWorksProperly) {
OfflineItem item4(id1);
item4.title = "updated3";
- EXPECT_CALL(observer, OnItemsAvailable(&provider_)).Times(1);
- wrapped_provider_.NotifyOnItemsAvailable();
-
{
EXPECT_CALL(observer, OnItemUpdated(item1)).Times(1);
provider_.set_last_update_time(GetTimeThatWillAllowAnUpdate());
@@ -308,9 +273,6 @@ TEST_F(ThrottledOfflineContentProviderTest, TestInitialRequestGoesThrough) {
OfflineItem item1_updated(id1);
item1_updated.title = "updated1";
- EXPECT_CALL(observer, OnItemsAvailable(&provider_)).Times(1);
- wrapped_provider_.NotifyOnItemsAvailable();
-
{
EXPECT_CALL(observer, OnItemUpdated(item1)).Times(1);
provider_.set_last_update_time(GetTimeThatWillAllowAnUpdate());
@@ -338,10 +300,6 @@ TEST_F(ThrottledOfflineContentProviderTest, TestReentrantUpdatesGetQueued) {
TriggerSingleReentrantUpdateHelper observer(&provider_, &wrapped_provider_,
updated_item);
-
- EXPECT_CALL(observer, OnItemsAvailable(&provider_)).Times(1);
- wrapped_provider_.NotifyOnItemsAvailable();
-
{
wrapped_provider_.NotifyOnItemUpdated(item);
EXPECT_CALL(observer, OnItemUpdated(item)).Times(1);
@@ -357,9 +315,6 @@ TEST_F(ThrottledOfflineContentProviderTest, TestReentrantUpdatesGetQueued) {
TEST_F(ThrottledOfflineContentProviderTest, TestPokingProviderFlushesQueue) {
ScopedMockOfflineContentProvider::ScopedMockObserver observer(&provider_);
- EXPECT_CALL(observer, OnItemsAvailable(&provider_)).Times(1);
- wrapped_provider_.NotifyOnItemsAvailable();
-
ContentId id1("1", "A");
OfflineItem item1(id1);
diff --git a/chromium/components/offline_pages/BUILD.gn b/chromium/components/offline_pages/BUILD.gn
index 0b190dca40e..2e980508098 100644
--- a/chromium/components/offline_pages/BUILD.gn
+++ b/chromium/components/offline_pages/BUILD.gn
@@ -23,6 +23,7 @@ if (!is_ios) {
# for renovations.
deps += [
"//content/shell/android:content_shell_assets",
+ "//net/android:net_java",
"//ui/android:ui_java",
]
}
diff --git a/chromium/components/offline_pages/features/BUILD.gn b/chromium/components/offline_pages/buildflags/BUILD.gn
index fdf4451198a..beb68c5bac9 100644
--- a/chromium/components/offline_pages/features/BUILD.gn
+++ b/chromium/components/offline_pages/buildflags/BUILD.gn
@@ -3,15 +3,15 @@
# found in the LICENSE file.
import("//build/buildflag_header.gni")
-import("//components/offline_pages/features/features.gni")
+import("//components/offline_pages/buildflags/features.gni")
# This file is in a separate directory so all targets in the build can refer to
# the buildflag header to get the necessary preprocessor defines without
# bringing in all of offline_pages. Other targets can depend on this target
# regardless of whether extensions are enabled.
-buildflag_header("features") {
- header = "features.h"
+buildflag_header("buildflags") {
+ header = "buildflags.h"
flags = [
"ENABLE_OFFLINE_PAGES=$enable_offline_pages",
"ENABLE_OFFLINE_PAGES_HARNESS=$enable_offline_pages_harness",
diff --git a/chromium/components/offline_pages/features/features.gni b/chromium/components/offline_pages/buildflags/features.gni
index 2c8c75b1f4f..2c8c75b1f4f 100644
--- a/chromium/components/offline_pages/features/features.gni
+++ b/chromium/components/offline_pages/buildflags/features.gni
diff --git a/chromium/components/offline_pages/content/background_loader/background_loader_contents.cc b/chromium/components/offline_pages/content/background_loader/background_loader_contents.cc
index 3a08f96525a..5b84360bb0e 100644
--- a/chromium/components/offline_pages/content/background_loader/background_loader_contents.cc
+++ b/chromium/components/offline_pages/content/background_loader/background_loader_contents.cc
@@ -31,6 +31,10 @@ void BackgroundLoaderContents::Cancel() {
web_contents_->Close();
}
+void BackgroundLoaderContents::SetDelegate(Delegate* delegate) {
+ delegate_ = delegate;
+}
+
bool BackgroundLoaderContents::IsNeverVisible(
content::WebContents* web_contents) {
// Background, so not visible.
@@ -57,8 +61,12 @@ void BackgroundLoaderContents::CanDownload(
const GURL& url,
const std::string& request_method,
const base::Callback<void(bool)>& callback) {
- // Do not download anything.
- callback.Run(false);
+ if (delegate_) {
+ delegate_->CanDownload(callback);
+ } else {
+ // Do not download anything if there's no delegate.
+ callback.Run(false);
+ }
}
bool BackgroundLoaderContents::ShouldCreateWebContents(
diff --git a/chromium/components/offline_pages/content/background_loader/background_loader_contents.h b/chromium/components/offline_pages/content/background_loader/background_loader_contents.h
index ceb0641d39e..141afa28cbe 100644
--- a/chromium/components/offline_pages/content/background_loader/background_loader_contents.h
+++ b/chromium/components/offline_pages/content/background_loader/background_loader_contents.h
@@ -21,6 +21,16 @@ namespace background_loader {
// a renderer but does not have any visible display.
class BackgroundLoaderContents : public content::WebContentsDelegate {
public:
+ // Delegate to help with decision making.
+ class Delegate {
+ public:
+ // Decide whether single-file (e.g. pdf) downloads should be allowed to
+ // start if a page initiates it. Callback can be called
+ // synchronously. Returning true to the callback will initiate
+ // the single file download. Assumes delegate will appropriately clean up.
+ virtual void CanDownload(const base::Callback<void(bool)>& callback) = 0;
+ };
+
// Creates BackgroundLoaderContents with specified |browser_context|. Uses
// default session storage space.
explicit BackgroundLoaderContents(content::BrowserContext* browser_context);
@@ -31,6 +41,9 @@ class BackgroundLoaderContents : public content::WebContentsDelegate {
virtual void LoadPage(const GURL& url);
// Cancels loading of the current page. Calls Close() on internal WebContents.
virtual void Cancel();
+ // Sets the delegate for this BackgroundLoaderContents; The delegate should
+ // outlive the contents, therefore, raw pointers are allowed.
+ void SetDelegate(Delegate* delegate);
// Returns the inner web contents.
content::WebContents* web_contents() { return web_contents_.get(); }
@@ -87,6 +100,7 @@ class BackgroundLoaderContents : public content::WebContentsDelegate {
std::unique_ptr<content::WebContents> web_contents_;
content::BrowserContext* browser_context_;
+ Delegate* delegate_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(BackgroundLoaderContents);
};
diff --git a/chromium/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc b/chromium/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc
index ddfe43a3e5b..7f45500ede0 100644
--- a/chromium/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc
+++ b/chromium/components/offline_pages/content/background_loader/background_loader_contents_unittest.cc
@@ -10,7 +10,8 @@
namespace background_loader {
-class BackgroundLoaderContentsTest : public testing::Test {
+class BackgroundLoaderContentsTest : public testing::Test,
+ public BackgroundLoaderContents::Delegate {
public:
BackgroundLoaderContentsTest();
~BackgroundLoaderContentsTest() override;
@@ -18,11 +19,16 @@ class BackgroundLoaderContentsTest : public testing::Test {
void SetUp() override;
void TearDown() override;
+ void CanDownload(const base::Callback<void(bool)>& callback) override;
+
BackgroundLoaderContents* contents() { return contents_.get(); }
void DownloadCallback(bool download);
+ // Sets "this" as delegate to the background loader contents.
+ void SetDelegate();
bool download() { return download_; }
+ bool can_download_delegate_called() { return delegate_called_; }
void MediaAccessCallback(const content::MediaStreamDevices& devices,
content::MediaStreamRequestResult result,
@@ -36,6 +42,7 @@ class BackgroundLoaderContentsTest : public testing::Test {
private:
std::unique_ptr<BackgroundLoaderContents> contents_;
bool download_;
+ bool delegate_called_;
content::MediaStreamDevices devices_;
content::MediaStreamRequestResult request_result_;
std::unique_ptr<content::MediaStreamUI> media_stream_ui_;
@@ -44,6 +51,7 @@ class BackgroundLoaderContentsTest : public testing::Test {
BackgroundLoaderContentsTest::BackgroundLoaderContentsTest()
: download_(false),
+ delegate_called_(false),
waiter_(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED){};
@@ -52,17 +60,28 @@ BackgroundLoaderContentsTest::~BackgroundLoaderContentsTest(){};
void BackgroundLoaderContentsTest::SetUp() {
contents_.reset(new BackgroundLoaderContents());
download_ = false;
+ waiter_.Reset();
}
void BackgroundLoaderContentsTest::TearDown() {
contents_.reset();
}
+void BackgroundLoaderContentsTest::CanDownload(
+ const base::Callback<void(bool)>& callback) {
+ delegate_called_ = true;
+ callback.Run(true);
+}
+
void BackgroundLoaderContentsTest::DownloadCallback(bool download) {
download_ = download;
waiter_.Signal();
}
+void BackgroundLoaderContentsTest::SetDelegate() {
+ contents_->SetDelegate(this);
+}
+
void BackgroundLoaderContentsTest::MediaAccessCallback(
const content::MediaStreamDevices& devices,
content::MediaStreamRequestResult result,
@@ -85,13 +104,25 @@ TEST_F(BackgroundLoaderContentsTest, DoesNotFocusAfterCrash) {
ASSERT_FALSE(contents()->ShouldFocusPageAfterCrash());
}
-TEST_F(BackgroundLoaderContentsTest, CannotDownload) {
+TEST_F(BackgroundLoaderContentsTest, CannotDownloadNoDelegate) {
contents()->CanDownload(
GURL::EmptyGURL(), std::string(),
base::Bind(&BackgroundLoaderContentsTest::DownloadCallback,
base::Unretained(this)));
WaitForSignal();
ASSERT_FALSE(download());
+ ASSERT_FALSE(can_download_delegate_called());
+}
+
+TEST_F(BackgroundLoaderContentsTest, CanDownload_DelegateCalledWhenSet) {
+ SetDelegate();
+ contents()->CanDownload(
+ GURL::EmptyGURL(), std::string(),
+ base::Bind(&BackgroundLoaderContentsTest::DownloadCallback,
+ base::Unretained(this)));
+ WaitForSignal();
+ ASSERT_TRUE(download());
+ ASSERT_TRUE(can_download_delegate_called());
}
TEST_F(BackgroundLoaderContentsTest, ShouldNotCreateWebContents) {
diff --git a/chromium/components/offline_pages/core/BUILD.gn b/chromium/components/offline_pages/core/BUILD.gn
index ec6b65d41ac..331769d5688 100644
--- a/chromium/components/offline_pages/core/BUILD.gn
+++ b/chromium/components/offline_pages/core/BUILD.gn
@@ -51,6 +51,7 @@ static_library("core") {
"model/temporary_pages_consistency_check_task.h",
"offline_event_logger.cc",
"offline_event_logger.h",
+ "offline_page_archiver.cc",
"offline_page_archiver.h",
"offline_page_client_policy.h",
"offline_page_item.cc",
@@ -62,12 +63,6 @@ static_library("core") {
"offline_page_model.h",
"offline_page_model_event_logger.cc",
"offline_page_model_event_logger.h",
- "offline_page_model_impl.cc",
- "offline_page_model_impl.h",
- "offline_page_model_query.cc",
- "offline_page_model_query.h",
- "offline_page_storage_manager.cc",
- "offline_page_storage_manager.h",
"offline_page_types.h",
"offline_pages_ukm_reporter.cc",
"offline_pages_ukm_reporter.h",
@@ -88,6 +83,7 @@ static_library("core") {
deps = [
":switches",
"//base",
+ "//components/filename_generation",
"//components/keyed_service/core",
"//crypto",
"//net",
@@ -113,6 +109,8 @@ static_library("test_support") {
"offline_page_test_store.h",
"stub_offline_page_model.cc",
"stub_offline_page_model.h",
+ "system_download_manager_stub.cc",
+ "system_download_manager_stub.h",
"task_test_base.cc",
"task_test_base.h",
"test_task.cc",
@@ -167,16 +165,12 @@ source_set("unit_tests") {
"model/start_offline_page_upgrade_task_unittest.cc",
"model/temporary_pages_consistency_check_task_unittest.cc",
"offline_event_logger_unittest.cc",
+ "offline_page_archiver_unittest.cc",
"offline_page_feature_unittest.cc",
"offline_page_metadata_store_unittest.cc",
"offline_page_model_event_logger_unittest.cc",
- "offline_page_model_impl_unittest.cc",
- "offline_page_model_query_unittest.cc",
- "offline_page_storage_manager_unittest.cc",
"offline_pages_ukm_reporter_unittest.cc",
"snapshot_controller_unittest.cc",
- "system_download_manager_stub.cc",
- "system_download_manager_stub.h",
"task_queue_unittest.cc",
"task_unittest.cc",
]
diff --git a/chromium/components/offline_pages/core/DEPS b/chromium/components/offline_pages/core/DEPS
index 52fe62965d7..c7dc9dc8e88 100644
--- a/chromium/components/offline_pages/core/DEPS
+++ b/chromium/components/offline_pages/core/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+components/filename_generation",
"+components/keyed_service",
"+components/offline_items_collection",
"+components/ukm",
diff --git a/chromium/components/offline_pages/core/archive_validator.cc b/chromium/components/offline_pages/core/archive_validator.cc
index b0ad3fc65a6..621831affa5 100644
--- a/chromium/components/offline_pages/core/archive_validator.cc
+++ b/chromium/components/offline_pages/core/archive_validator.cc
@@ -14,14 +14,29 @@
namespace offline_pages {
+ArchiveValidator::ArchiveValidator() {
+ secure_hash_ = crypto::SecureHash::Create(crypto::SecureHash::SHA256);
+}
+
+ArchiveValidator::~ArchiveValidator() = default;
+
+void ArchiveValidator::Update(const char* input, size_t len) {
+ secure_hash_->Update(input, len);
+}
+
+std::string ArchiveValidator::Finish() {
+ std::string digest(crypto::kSHA256Length, 0);
+ secure_hash_->Finish(&(digest[0]), digest.size());
+ return digest;
+}
+
// static
std::string ArchiveValidator::ComputeDigest(const base::FilePath& file_path) {
base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
if (!file.IsValid())
return std::string();
- std::unique_ptr<crypto::SecureHash> secure_hash(
- crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+ ArchiveValidator archive_validator;
const int kMaxBufferSize = 1024;
std::vector<char> buffer(kMaxBufferSize);
@@ -29,14 +44,12 @@ std::string ArchiveValidator::ComputeDigest(const base::FilePath& file_path) {
do {
bytes_read = file.ReadAtCurrentPos(buffer.data(), kMaxBufferSize);
if (bytes_read > 0)
- secure_hash->Update(buffer.data(), bytes_read);
+ archive_validator.Update(buffer.data(), bytes_read);
} while (bytes_read > 0);
if (bytes_read < 0)
return std::string();
- std::string result_bytes(crypto::kSHA256Length, 0);
- secure_hash->Finish(&result_bytes[0], result_bytes.size());
- return result_bytes;
+ return archive_validator.Finish();
}
// static
diff --git a/chromium/components/offline_pages/core/archive_validator.h b/chromium/components/offline_pages/core/archive_validator.h
index e5cf2d065b9..e99aab3795b 100644
--- a/chromium/components/offline_pages/core/archive_validator.h
+++ b/chromium/components/offline_pages/core/archive_validator.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_OFFLINE_PAGES_CORE_ARCHIVE_VALIDATOR_H_
#define COMPONENTS_OFFLINE_PAGES_CORE_ARCHIVE_VALIDATOR_H_
+#include <memory>
#include <string>
#include "base/macros.h"
@@ -13,11 +14,21 @@ namespace base {
class FilePath;
}
+namespace crypto {
+class SecureHash;
+}
+
namespace offline_pages {
-// Contains all helper functions to validate an archive file.
+// Used to validate an archive file.
class ArchiveValidator {
public:
+ ArchiveValidator();
+ virtual ~ArchiveValidator();
+
+ void Update(const char* input, size_t len);
+ std::string Finish();
+
// Computes a SHA256 digest of the specified file. Empty string will be
// returned if the digest cannot be computed.
static std::string ComputeDigest(const base::FilePath& file_path);
@@ -29,7 +40,9 @@ class ArchiveValidator {
const std::string& expected_digest);
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(ArchiveValidator);
+ std::unique_ptr<crypto::SecureHash> secure_hash_;
+
+ DISALLOW_COPY_AND_ASSIGN(ArchiveValidator);
};
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/background/BUILD.gn b/chromium/components/offline_pages/core/background/BUILD.gn
index 17f84ebe5cd..757ea0ce4d0 100644
--- a/chromium/components/offline_pages/core/background/BUILD.gn
+++ b/chromium/components/offline_pages/core/background/BUILD.gn
@@ -34,6 +34,8 @@ static_library("background_offliner") {
"offliner_policy.h",
"offliner_policy_utils.cc",
"offliner_policy_utils.h",
+ "pending_state_updater.cc",
+ "pending_state_updater.h",
"pick_request_task.cc",
"pick_request_task.h",
"reconcile_task.cc",
@@ -61,6 +63,7 @@ static_library("background_offliner") {
deps = [
"//base",
"//components/keyed_service/core",
+ "//components/offline_items_collection/core",
"//components/offline_pages/core",
"//components/offline_pages/core:switches",
"//net",
@@ -118,6 +121,7 @@ source_set("unit_tests") {
":test_support",
"//base",
"//base/test:test_support",
+ "//components/offline_items_collection/core",
"//components/offline_pages/core",
"//components/offline_pages/core:switches",
"//sql:sql",
diff --git a/chromium/components/offline_pages/core/background/offliner.h b/chromium/components/offline_pages/core/background/offliner.h
index 20a953f5ae1..fffa3fea829 100644
--- a/chromium/components/offline_pages/core/background/offliner.h
+++ b/chromium/components/offline_pages/core/background/offliner.h
@@ -66,6 +66,10 @@ class Offliner {
// We detect the situation in ReconcileTask after starting
// RequestCoordinator.
BROWSER_KILLED = 16,
+ // The page initiated a download, we denied the downloads.
+ LOADING_FAILED_DOWNLOAD = 17,
+ // The page initiated a download, and we passed it on to downloads.
+ DOWNLOAD_THROTTLED = 18,
// NOTE: insert new values above this line and update histogram enum too.
STATUS_COUNT
};
diff --git a/chromium/components/offline_pages/core/background/pending_state_updater.cc b/chromium/components/offline_pages/core/background/pending_state_updater.cc
new file mode 100644
index 00000000000..a2c8ef18d3f
--- /dev/null
+++ b/chromium/components/offline_pages/core/background/pending_state_updater.cc
@@ -0,0 +1,65 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/offline_pages/core/background/pending_state_updater.h"
+
+#include "components/offline_items_collection/core/pending_state.h"
+#include "components/offline_pages/core/background/request_coordinator.h"
+
+namespace offline_pages {
+
+PendingStateUpdater::PendingStateUpdater(
+ RequestCoordinator* request_coordinator)
+ : request_coordinator_(request_coordinator),
+ requests_pending_another_download_(false),
+ weak_ptr_factory_(this) {}
+
+PendingStateUpdater::~PendingStateUpdater() {}
+
+void PendingStateUpdater::UpdateRequestsOnLossOfNetwork() {
+ requests_pending_another_download_ = false;
+ request_coordinator_->GetAllRequests(
+ base::Bind(&PendingStateUpdater::SetPendingStatesAndNotifyChanged,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void PendingStateUpdater::UpdateRequestsOnRequestPicked(
+ const int64_t picked_request_id,
+ std::unique_ptr<std::vector<SavePageRequest>> available_requests) {
+ // Requests do not need to be updated.
+ if (requests_pending_another_download_)
+ return;
+
+ // All available requests expect for the picked request changed to waiting
+ // for another download to complete.
+ for (auto& request : *available_requests) {
+ if (request.request_id() != picked_request_id) {
+ request.set_pending_state(PendingState::PENDING_ANOTHER_DOWNLOAD);
+ request_coordinator_->NotifyChanged(request);
+ }
+ }
+ requests_pending_another_download_ = true;
+}
+
+void PendingStateUpdater::SetPendingState(SavePageRequest& request) {
+ if (request.request_state() == SavePageRequest::RequestState::AVAILABLE) {
+ if (request_coordinator_->state() ==
+ RequestCoordinator::RequestCoordinatorState::OFFLINING) {
+ request.set_pending_state(PendingState::PENDING_ANOTHER_DOWNLOAD);
+ } else {
+ requests_pending_another_download_ = false;
+ request.set_pending_state(PendingState::PENDING_NETWORK);
+ }
+ }
+}
+
+void PendingStateUpdater::SetPendingStatesAndNotifyChanged(
+ std::vector<std::unique_ptr<SavePageRequest>> requests) {
+ for (auto& request : requests) {
+ SetPendingState(*request.get());
+ request_coordinator_->NotifyChanged(*request);
+ }
+}
+
+} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/background/pending_state_updater.h b/chromium/components/offline_pages/core/background/pending_state_updater.h
new file mode 100644
index 00000000000..55cc278dc1e
--- /dev/null
+++ b/chromium/components/offline_pages/core/background/pending_state_updater.h
@@ -0,0 +1,56 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_PENDING_STATE_UPDATER_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_PENDING_STATE_UPDATER_H_
+
+#include <vector>
+
+#include "base/memory/weak_ptr.h"
+#include "components/offline_pages/core/background/save_page_request.h"
+
+namespace offline_pages {
+
+class RequestCoordinator;
+
+// Class for updating the PendingState of requests.
+class PendingStateUpdater {
+ public:
+ PendingStateUpdater(RequestCoordinator* request_coordinator);
+ ~PendingStateUpdater();
+
+ // Set PendingState for available requests when network is lost and notify
+ // RequestCoordinator::Observers.
+ void UpdateRequestsOnLossOfNetwork();
+
+ // Set PendingState for the available requests not picked for offlining and
+ // notify RequestCoordinator::Observers.
+ void UpdateRequestsOnRequestPicked(
+ const int64_t picked_request_id,
+ std::unique_ptr<std::vector<SavePageRequest>> available_requests);
+
+ // Set PendingState for a request.
+ void SetPendingState(SavePageRequest& request);
+
+ private:
+ // Set PendingState for multiple requests and notify
+ // RequestCoordinator::Observers. Callback for
+ // RequestCoordinator::GetAllRequests.
+ void SetPendingStatesAndNotifyChanged(
+ std::vector<std::unique_ptr<SavePageRequest>> requests);
+
+ // Unowned pointer.
+ RequestCoordinator* request_coordinator_;
+
+ // Used to determine if available requests need to be updated after a request
+ // is picked for offlining. True if requests are currently pending another
+ // download to complete. False otherwise.
+ bool requests_pending_another_download_;
+
+ base::WeakPtrFactory<PendingStateUpdater> weak_ptr_factory_;
+};
+
+} // namespace offline_pages
+
+#endif // COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_PENDING_STATE_UPDATER_H_
diff --git a/chromium/components/offline_pages/core/background/pick_request_task.cc b/chromium/components/offline_pages/core/background/pick_request_task.cc
index 59f338a21c4..6dfe09770d2 100644
--- a/chromium/components/offline_pages/core/background/pick_request_task.cc
+++ b/chromium/components/offline_pages/core/background/pick_request_task.cc
@@ -74,6 +74,10 @@ void PickRequestTask::Choose(
return;
}
+ // All available requests
+ std::unique_ptr<std::vector<SavePageRequest>> available_requests =
+ std::make_unique<std::vector<SavePageRequest>>();
+
// Pick the most deserving request for our conditions.
const SavePageRequest* picked_request = nullptr;
@@ -88,7 +92,7 @@ void PickRequestTask::Choose(
bool non_user_requested_tasks_remaining = false;
bool cleanup_needed = false;
- size_t available_request_count = 0;
+ size_t total_request_count = requests.size();
// Request ids which are available for picking.
std::unordered_set<int64_t> available_request_ids;
@@ -115,15 +119,14 @@ void PickRequestTask::Choose(
// non-user-requested items, which have different network and power needs.
if (!request->user_requested())
non_user_requested_tasks_remaining = true;
- if (request->request_state() == SavePageRequest::RequestState::AVAILABLE) {
- available_request_count++;
- }
+ if (request->request_state() == SavePageRequest::RequestState::AVAILABLE)
+ available_requests->push_back(*request);
if (!RequestConditionsSatisfied(request.get()))
continue;
available_request_ids.insert(request->request_id());
}
// Report the request queue counts.
- request_count_callback_.Run(requests.size(), available_request_count);
+ request_count_callback_.Run(total_request_count, available_requests->size());
// Search for and pick the prioritized request which is available for picking
// from |available_request_ids|, the closer to the end means higher priority.
@@ -134,9 +137,9 @@ void PickRequestTask::Choose(
// request, or there's a request being poped from |prioritized_requests_|.
while (!picked_request && !prioritized_requests_.empty()) {
if (available_request_ids.count(prioritized_requests_.back()) > 0) {
- for (const auto& request : requests) {
- if (request->request_id() == prioritized_requests_.back()) {
- picked_request = request.get();
+ for (const auto& request : *available_requests) {
+ if (request.request_id() == prioritized_requests_.back()) {
+ picked_request = &request;
break;
}
}
@@ -149,10 +152,10 @@ void PickRequestTask::Choose(
// If no request was found from the priority list, find the best request
// according to current policies.
if (!picked_request) {
- for (const auto& request : requests) {
- if ((available_request_ids.count(request->request_id()) > 0) &&
- (IsNewRequestBetter(picked_request, request.get(), comparator))) {
- picked_request = request.get();
+ for (const auto& request : *available_requests) {
+ if ((available_request_ids.count(request.request_id()) > 0) &&
+ (IsNewRequestBetter(picked_request, &request, comparator))) {
+ picked_request = &request;
}
}
}
@@ -160,7 +163,8 @@ void PickRequestTask::Choose(
// If we have a best request to try next, get the request coodinator to
// start it. Otherwise return that we have no candidates.
if (picked_request != nullptr) {
- picked_callback_.Run(*picked_request, cleanup_needed);
+ picked_callback_.Run(*picked_request, std::move(available_requests),
+ cleanup_needed);
} else {
not_picked_callback_.Run(non_user_requested_tasks_remaining,
cleanup_needed);
diff --git a/chromium/components/offline_pages/core/background/pick_request_task.h b/chromium/components/offline_pages/core/background/pick_request_task.h
index 3c25615d708..14c22ceb07f 100644
--- a/chromium/components/offline_pages/core/background/pick_request_task.h
+++ b/chromium/components/offline_pages/core/background/pick_request_task.h
@@ -27,8 +27,10 @@ typedef bool (PickRequestTask::*RequestCompareFunction)(
class PickRequestTask : public Task {
public:
// Callback to report when a request was available.
- typedef base::Callback<void(const SavePageRequest& request,
- bool cleanup_needed)>
+ typedef base::Callback<void(
+ const SavePageRequest& request,
+ std::unique_ptr<std::vector<SavePageRequest>> available_requests,
+ bool cleanup_needed)>
RequestPickedCallback;
// Callback to report when no request was available.
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 c43a3637d08..4a67fd5c65a 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
@@ -100,7 +100,10 @@ class PickRequestTaskTest : public testing::Test {
void AddRequestDone(ItemActionStatus status);
- void RequestPicked(const SavePageRequest& request, bool cleanup_needed);
+ void RequestPicked(
+ const SavePageRequest& request,
+ const std::unique_ptr<std::vector<SavePageRequest>> available_requests,
+ bool cleanup_needed);
void RequestNotPicked(const bool non_user_requested_tasks_remaining,
bool cleanup_needed);
@@ -175,8 +178,10 @@ void PickRequestTaskTest::TaskCompletionCallback(Task* completed_task) {
void PickRequestTaskTest::AddRequestDone(ItemActionStatus status) {}
-void PickRequestTaskTest::RequestPicked(const SavePageRequest& request,
- const bool cleanup_needed) {
+void PickRequestTaskTest::RequestPicked(
+ const SavePageRequest& request,
+ std::unique_ptr<std::vector<SavePageRequest>> available_requests,
+ const bool cleanup_needed) {
last_picked_.reset(new SavePageRequest(request));
cleanup_needed_ = cleanup_needed;
}
diff --git a/chromium/components/offline_pages/core/background/request_coordinator.cc b/chromium/components/offline_pages/core/background/request_coordinator.cc
index 469c1993f40..78a883fa201 100644
--- a/chromium/components/offline_pages/core/background/request_coordinator.cc
+++ b/chromium/components/offline_pages/core/background/request_coordinator.cc
@@ -186,10 +186,6 @@ void RecordNetworkQualityAtRequestStartForFailedRequest(
histogram->Add(effective_connection);
}
-// In case we start processing from SavePageLater, we need a callback, but there
-// is nothing for it to do.
-void EmptySchedulerCallback(bool started) {}
-
// Returns whether |result| is a successful result for a single request.
bool IsSingleSuccessResult(const UpdateRequestsResult* result) {
return result->store_state == StoreState::LOADED &&
@@ -237,8 +233,9 @@ RequestCoordinator::RequestCoordinator(
network_quality_at_request_start_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
active_request_id_(0),
last_offlining_status_(Offliner::RequestStatus::UNKNOWN),
- scheduler_callback_(base::Bind(&EmptySchedulerCallback)),
- internal_start_processing_callback_(base::Bind(&EmptySchedulerCallback)),
+ scheduler_callback_(base::DoNothing()),
+ internal_start_processing_callback_(base::DoNothing()),
+ pending_state_updater_(this),
weak_ptr_factory_(this) {
DCHECK(policy_ != nullptr);
std::unique_ptr<CleanupTaskFactory> cleanup_factory(
@@ -278,6 +275,7 @@ int64_t RequestCoordinator::SavePageLater(
base::Time::Now(), save_page_later_params.user_requested);
request.set_original_url(save_page_later_params.original_url);
request.set_request_origin(save_page_later_params.request_origin);
+ pending_state_updater_.SetPendingState(request);
// If the download manager is not done with the request, put it on the
// disabled list.
@@ -526,8 +524,10 @@ void RequestCoordinator::AddRequestResultCallback(
void RequestCoordinator::UpdateMultipleRequestsCallback(
std::unique_ptr<UpdateRequestsResult> result) {
- for (const auto& request : result->updated_items)
+ for (auto& request : result->updated_items) {
+ pending_state_updater_.SetPendingState(request);
NotifyChanged(request);
+ }
bool available_user_request = false;
for (const auto& request : result->updated_items) {
@@ -543,8 +543,9 @@ void RequestCoordinator::UpdateMultipleRequestsCallback(
void RequestCoordinator::ReconcileCallback(
std::unique_ptr<UpdateRequestsResult> result) {
- for (const auto& request : result->updated_items) {
+ for (auto& request : result->updated_items) {
RecordOfflinerResult(request, Offliner::RequestStatus::BROWSER_KILLED);
+ pending_state_updater_.SetPendingState(request);
NotifyChanged(request);
}
}
@@ -737,6 +738,10 @@ void RequestCoordinator::UpdateCurrentConditionsFromAndroid() {
void RequestCoordinator::TryNextRequest(bool is_start_of_processing) {
state_ = RequestCoordinatorState::PICKING;
+ // Connection type at previous check.
+ net::NetworkChangeNotifier::ConnectionType previous_connection_type =
+ current_conditions_->GetNetConnectionType();
+
// If this is the first call, the device conditions are current, no need to
// update them.
if (!is_start_of_processing) {
@@ -747,6 +752,18 @@ void RequestCoordinator::TryNextRequest(bool is_start_of_processing) {
UpdateCurrentConditionsFromAndroid();
}
+ // Current connection type.
+ net::NetworkChangeNotifier::ConnectionType connection_type =
+ current_conditions_->GetNetConnectionType();
+
+ // If there was loss of network, update all available requests to waiting for
+ // network connection.
+ if (connection_type != previous_connection_type &&
+ connection_type ==
+ net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE) {
+ pending_state_updater_.UpdateRequestsOnLossOfNetwork();
+ }
+
base::TimeDelta processing_time_budget;
if (processing_state_ == ProcessingWindowState::SCHEDULED_WINDOW) {
processing_time_budget = base::TimeDelta::FromSeconds(
@@ -757,9 +774,6 @@ void RequestCoordinator::TryNextRequest(bool is_start_of_processing) {
policy_->GetProcessingTimeBudgetForImmediateLoadInSeconds());
}
- net::NetworkChangeNotifier::ConnectionType connection_type =
- current_conditions_->GetNetConnectionType();
-
// If there is no network or no time left in the budget, return to the
// scheduler. We do not remove the pending scheduler task that was set
// up earlier in case we run out of time, so the background scheduler
@@ -795,16 +809,22 @@ void RequestCoordinator::TryNextRequest(bool is_start_of_processing) {
}
// Called by the request picker when a request has been picked.
-void RequestCoordinator::RequestPicked(const SavePageRequest& request,
- bool cleanup_needed) {
- DVLOG(2) << request.url() << " " << __func__;
+void RequestCoordinator::RequestPicked(
+ const SavePageRequest& picked_request,
+ std::unique_ptr<std::vector<SavePageRequest>> available_requests,
+ bool cleanup_needed) {
+ DVLOG(2) << picked_request.url() << " " << __func__;
// Make sure we were not stopped while picking, since any kind of cancel/stop
// will reset the state back to IDLE.
if (state_ == RequestCoordinatorState::PICKING) {
state_ = RequestCoordinatorState::OFFLINING;
// Send the request on to the offliner.
- SendRequestToOffliner(request);
+ SendRequestToOffliner(picked_request);
+
+ // Update the pending state for available requests if needed.
+ pending_state_updater_.UpdateRequestsOnRequestPicked(
+ picked_request.request_id(), std::move(available_requests));
}
// Schedule a queue cleanup if needed.
@@ -1004,12 +1024,16 @@ void RequestCoordinator::UpdateRequestForCompletedAttempt(
UpdateRequestForAbortedAttempt(request);
} else if (status == Offliner::RequestStatus::SAVED ||
status == Offliner::RequestStatus::SAVED_ON_LAST_RETRY) {
- // Remove the request from the queue if it succeeded.
+ // Remove the request from the queue if it succeeded
RemoveAttemptedRequest(request,
RequestNotifier::BackgroundSavePageResult::SUCCESS);
- } else if (status == Offliner::RequestStatus::LOADING_FAILED_NO_RETRY) {
+ } else if (status == Offliner::RequestStatus::LOADING_FAILED_NO_RETRY ||
+ status == Offliner::RequestStatus::LOADING_FAILED_DOWNLOAD) {
RemoveAttemptedRequest(
request, RequestNotifier::BackgroundSavePageResult::LOADING_FAILURE);
+ } else if (status == Offliner::RequestStatus::DOWNLOAD_THROTTLED) {
+ RemoveAttemptedRequest(
+ request, RequestNotifier::BackgroundSavePageResult::DOWNLOAD_THROTTLED);
} else if (request.completed_attempt_count() + 1 >=
policy_->GetMaxCompletedTries()) {
// Remove from the request queue if we exceeded max retries. The +1
@@ -1040,6 +1064,8 @@ bool RequestCoordinator::ShouldTryNextRequest(
case Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED:
case Offliner::RequestStatus::LOADING_FAILED:
case Offliner::RequestStatus::LOADING_FAILED_NO_RETRY:
+ case Offliner::RequestStatus::LOADING_FAILED_DOWNLOAD:
+ case Offliner::RequestStatus::DOWNLOAD_THROTTLED:
return true;
case Offliner::RequestStatus::FOREGROUND_CANCELED:
case Offliner::RequestStatus::LOADING_CANCELED:
diff --git a/chromium/components/offline_pages/core/background/request_coordinator.h b/chromium/components/offline_pages/core/background/request_coordinator.h
index adf2adbea6e..866ba2ad37e 100644
--- a/chromium/components/offline_pages/core/background/request_coordinator.h
+++ b/chromium/components/offline_pages/core/background/request_coordinator.h
@@ -21,6 +21,7 @@
#include "components/keyed_service/core/keyed_service.h"
#include "components/offline_pages/core/background/connection_notifier.h"
#include "components/offline_pages/core/background/device_conditions.h"
+#include "components/offline_pages/core/background/pending_state_updater.h"
#include "components/offline_pages/core/background/request_coordinator_event_logger.h"
#include "components/offline_pages/core/background/request_notifier.h"
#include "components/offline_pages/core/background/request_queue.h"
@@ -332,7 +333,10 @@ class RequestCoordinator : public KeyedService,
void ScheduleAsNeeded();
// Callback from the request picker when it has chosen our next request.
- void RequestPicked(const SavePageRequest& request, bool cleanup_needed);
+ void RequestPicked(
+ const SavePageRequest& request,
+ std::unique_ptr<std::vector<SavePageRequest>> available_requests,
+ bool cleanup_needed);
// Callback from the request picker when no more requests are in the queue.
// The parameter is a signal for what (if any) conditions to schedule future
@@ -491,6 +495,8 @@ class RequestCoordinator : public KeyedService,
// Currently it's used as LIFO.
// TODO(romax): see if LIFO is a good idea or change to FIFO. crbug.com/705106
base::circular_deque<int64_t> prioritized_requests_;
+ // Updates a request's PendingState.
+ PendingStateUpdater pending_state_updater_;
// Allows us to pass a weak pointer to callbacks.
base::WeakPtrFactory<RequestCoordinator> weak_ptr_factory_;
diff --git a/chromium/components/offline_pages/core/background/request_coordinator_event_logger.cc b/chromium/components/offline_pages/core/background/request_coordinator_event_logger.cc
index df90ec6bda9..2708d2e3c89 100644
--- a/chromium/components/offline_pages/core/background/request_coordinator_event_logger.cc
+++ b/chromium/components/offline_pages/core/background/request_coordinator_event_logger.cc
@@ -45,6 +45,10 @@ static std::string OfflinerRequestStatusToString(
return "SAVED_ON_LAST_RETRY";
case Offliner::BROWSER_KILLED:
return "BROWSER_KILLED";
+ case Offliner::LOADING_FAILED_DOWNLOAD:
+ return "LOADING_FAILED_DOWNLOAD";
+ case Offliner::DOWNLOAD_THROTTLED:
+ return "DOWNLOAD_THROTTLED";
default:
NOTREACHED();
return std::to_string(static_cast<int>(request_status));
@@ -72,6 +76,8 @@ static std::string BackgroundSavePageResultToString(
return "START_COUNT_EXCEEDED";
case RequestNotifier::BackgroundSavePageResult::USER_CANCELED:
return "REMOVED";
+ case RequestNotifier::BackgroundSavePageResult::DOWNLOAD_THROTTLED:
+ return "DOWNLOAD_THROTTLED";
default:
NOTREACHED();
return std::to_string(static_cast<int>(result));
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 9e50875a5a2..f0232fa19a3 100644
--- a/chromium/components/offline_pages/core/background/request_coordinator_unittest.cc
+++ b/chromium/components/offline_pages/core/background/request_coordinator_unittest.cc
@@ -20,6 +20,7 @@
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "components/offline_items_collection/core/pending_state.h"
#include "components/offline_pages/core/background/device_conditions.h"
#include "components/offline_pages/core/background/network_quality_provider_stub.h"
#include "components/offline_pages/core/background/offliner.h"
@@ -79,6 +80,8 @@ class ObserverStub : public RequestCoordinator::Observer {
void OnAdded(const SavePageRequest& request) override {
added_called_ = true;
+ state_ = request.request_state();
+ pending_state_ = request.pending_state();
}
void OnCompleted(
@@ -91,6 +94,7 @@ class ObserverStub : public RequestCoordinator::Observer {
void OnChanged(const SavePageRequest& request) override {
changed_called_ = true;
state_ = request.request_state();
+ pending_state_ = request.pending_state();
}
void OnNetworkProgress(const SavePageRequest& request,
@@ -108,6 +112,7 @@ class ObserverStub : public RequestCoordinator::Observer {
return last_status_;
}
SavePageRequest::RequestState state() { return state_; }
+ PendingState pending_state() { return pending_state_; }
private:
bool added_called_;
@@ -117,6 +122,7 @@ class ObserverStub : public RequestCoordinator::Observer {
int64_t network_progress_bytes_;
RequestCoordinator::BackgroundSavePageResult last_status_;
SavePageRequest::RequestState state_;
+ PendingState pending_state_;
};
class RequestCoordinatorTest : public testing::Test {
@@ -1615,4 +1621,91 @@ TEST_F(RequestCoordinatorTest, SnapshotOnLastTryForImmediateProcessing) {
EXPECT_TRUE(observer().completed_called());
}
+TEST_F(RequestCoordinatorTest, RequestPendingNetworkOnResumeWithNoNetwork) {
+ // Add a request to the queue.
+ AddRequest1();
+ PumpLoop();
+
+ // Pause the request.
+ std::vector<int64_t> request_ids;
+ request_ids.push_back(kRequestId1);
+ coordinator()->PauseRequests(request_ids);
+ PumpLoop();
+
+ SetNetworkConnected(false);
+
+ // Resume the request.
+ coordinator()->ResumeRequests(request_ids);
+ PumpLoop();
+
+ // Verify the request is waiting for network.
+ EXPECT_TRUE(observer().changed_called());
+ EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state());
+ EXPECT_EQ(PendingState::PENDING_NETWORK, observer().pending_state());
+}
+
+TEST_F(RequestCoordinatorTest,
+ RequestPendingDownloadOnResumeWithOffliningDownload) {
+ // Add a request to the queue.
+ AddRequest1();
+ PumpLoop();
+
+ // Pause the request.
+ std::vector<int64_t> request_ids;
+ request_ids.push_back(kRequestId1);
+ coordinator()->PauseRequests(request_ids);
+ PumpLoop();
+
+ // Add a second request to the queue for offlining.
+ AddRequest2();
+ EnableOfflinerCallback(false);
+ EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
+ processing_callback()));
+ PumpLoop();
+
+ // Resume the first request.
+ coordinator()->ResumeRequests(request_ids);
+ PumpLoop();
+
+ // Verify the request is waiting for another download to complete.
+ EXPECT_TRUE(observer().changed_called());
+ EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state());
+ EXPECT_EQ(PendingState::PENDING_ANOTHER_DOWNLOAD, observer().pending_state());
+}
+
+TEST_F(RequestCoordinatorTest, RequestPendingNetworkOnAddWithNoNetwork) {
+ SetNetworkConnected(false);
+
+ EXPECT_NE(0, SavePageLater());
+ PumpLoop();
+
+ // Verify the request is waiting for network.
+ EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state());
+ EXPECT_EQ(PendingState::PENDING_NETWORK, observer().pending_state());
+}
+
+TEST_F(RequestCoordinatorTest,
+ RequestPendingDownloadOnAddedWithOffliningDownload) {
+ // Make an offlining request.
+ EnableOfflinerCallback(false);
+ EXPECT_NE(0, SavePageLater());
+ PumpLoop();
+
+ // Make a second request.
+ RequestCoordinator::SavePageLaterParams params;
+ params.url = kUrl2;
+ params.client_id = kClientId2;
+ params.user_requested = kUserRequested;
+ EXPECT_NE(0, coordinator()->SavePageLater(
+ params,
+ base::Bind(&RequestCoordinatorTest::SavePageRequestCallback,
+ base::Unretained(this))));
+ PumpLoop();
+
+ // Verify second request is waiting for another download to complete.
+ EXPECT_TRUE(observer().added_called());
+ EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state());
+ EXPECT_EQ(PendingState::PENDING_ANOTHER_DOWNLOAD, observer().pending_state());
+}
+
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/background/request_notifier.h b/chromium/components/offline_pages/core/background/request_notifier.h
index 12534dfecec..10643a64f41 100644
--- a/chromium/components/offline_pages/core/background/request_notifier.h
+++ b/chromium/components/offline_pages/core/background/request_notifier.h
@@ -27,6 +27,7 @@ class RequestNotifier {
RETRY_COUNT_EXCEEDED = 6,
START_COUNT_EXCEEDED = 7,
USER_CANCELED = 8,
+ DOWNLOAD_THROTTLED = 9,
// NOTE: insert new values above this line and update histogram enum too.
STATUS_COUNT
};
diff --git a/chromium/components/offline_pages/core/background/request_queue_in_memory_store.cc b/chromium/components/offline_pages/core/background/request_queue_in_memory_store.cc
index 69e06b8cada..ee7145181e0 100644
--- a/chromium/components/offline_pages/core/background/request_queue_in_memory_store.cc
+++ b/chromium/components/offline_pages/core/background/request_queue_in_memory_store.cc
@@ -5,6 +5,7 @@
#include "components/offline_pages/core/background/request_queue_in_memory_store.h"
#include <unordered_set>
+#include <utility>
#include "base/bind.h"
#include "base/location.h"
@@ -40,8 +41,7 @@ void RequestQueueInMemoryStore::GetRequests(
result_requests.push_back(std::move(request));
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(callback, true, base::Passed(std::move(result_requests))));
+ FROM_HERE, base::BindOnce(callback, true, std::move(result_requests)));
}
void RequestQueueInMemoryStore::GetRequestsByIds(
@@ -69,7 +69,7 @@ void RequestQueueInMemoryStore::GetRequestsByIds(
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, base::Passed(&result)));
+ FROM_HERE, base::BindOnce(callback, std::move(result)));
}
void RequestQueueInMemoryStore::AddRequest(const SavePageRequest& request,
@@ -110,7 +110,7 @@ void RequestQueueInMemoryStore::UpdateRequests(
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, base::Passed(&result)));
+ FROM_HERE, base::BindOnce(callback, std::move(result)));
}
void RequestQueueInMemoryStore::RemoveRequests(
@@ -136,7 +136,7 @@ void RequestQueueInMemoryStore::RemoveRequests(
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, base::Passed(&result)));
+ FROM_HERE, base::BindOnce(callback, std::move(result)));
}
void RequestQueueInMemoryStore::Reset(const ResetCallback& callback) {
diff --git a/chromium/components/offline_pages/core/background/request_queue_store_sql.cc b/chromium/components/offline_pages/core/background/request_queue_store_sql.cc
index 2b944f9594e..0920e9025de 100644
--- a/chromium/components/offline_pages/core/background/request_queue_store_sql.cc
+++ b/chromium/components/offline_pages/core/background/request_queue_store_sql.cc
@@ -5,6 +5,7 @@
#include "components/offline_pages/core/background/request_queue_store_sql.h"
#include <unordered_set>
+#include <utility>
#include "base/bind.h"
#include "base/files/file_path.h"
@@ -260,7 +261,7 @@ void PostStoreUpdateResultForIds(
new UpdateRequestsResult(store_state));
for (const auto& item_id : item_ids)
result->item_statuses.push_back(std::make_pair(item_id, action_status));
- runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result)));
+ runner->PostTask(FROM_HERE, base::BindOnce(callback, std::move(result)));
}
void PostStoreErrorForAllRequests(
@@ -313,8 +314,8 @@ void GetRequestsSync(sql::Connection* db,
while (statement.Step())
requests.push_back(MakeSavePageRequest(statement));
- runner->PostTask(FROM_HERE, base::Bind(callback, statement.Succeeded(),
- base::Passed(&requests)));
+ runner->PostTask(FROM_HERE, base::BindOnce(callback, statement.Succeeded(),
+ std::move(requests)));
}
void GetRequestsByIdsSync(sql::Connection* db,
@@ -351,7 +352,7 @@ void GetRequestsByIdsSync(sql::Connection* db,
return;
}
- runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result)));
+ runner->PostTask(FROM_HERE, base::BindOnce(callback, std::move(result)));
}
void AddRequestSync(sql::Connection* db,
@@ -388,7 +389,7 @@ void UpdateRequestsSync(sql::Connection* db,
return;
}
- runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result)));
+ runner->PostTask(FROM_HERE, base::BindOnce(callback, std::move(result)));
}
void RemoveRequestsSync(sql::Connection* db,
@@ -421,7 +422,7 @@ void RemoveRequestsSync(sql::Connection* db,
return;
}
- runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result)));
+ runner->PostTask(FROM_HERE, base::BindOnce(callback, std::move(result)));
}
void OpenConnectionSync(sql::Connection* db,
@@ -477,7 +478,7 @@ void RequestQueueStoreSQL::GetRequests(const GetRequestsCallback& callback) {
if (!CheckDb()) {
std::vector<std::unique_ptr<SavePageRequest>> requests;
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, false, base::Passed(&requests)));
+ FROM_HERE, base::BindOnce(callback, false, std::move(requests)));
return;
}
diff --git a/chromium/components/offline_pages/core/background/save_page_request.cc b/chromium/components/offline_pages/core/background/save_page_request.cc
index ff8bdc2f3ef..f80769a2ad8 100644
--- a/chromium/components/offline_pages/core/background/save_page_request.cc
+++ b/chromium/components/offline_pages/core/background/save_page_request.cc
@@ -30,6 +30,7 @@ SavePageRequest::SavePageRequest(const SavePageRequest& other)
last_attempt_time_(other.last_attempt_time_),
user_requested_(other.user_requested_),
state_(other.state_),
+ pending_state_(other.pending_state_),
original_url_(other.original_url_),
request_origin_(other.request_origin_) {}
diff --git a/chromium/components/offline_pages/core/background/save_page_request.h b/chromium/components/offline_pages/core/background/save_page_request.h
index 86b737011da..0ef6d41c9d7 100644
--- a/chromium/components/offline_pages/core/background/save_page_request.h
+++ b/chromium/components/offline_pages/core/background/save_page_request.h
@@ -8,9 +8,12 @@
#include <stdint.h>
#include "base/time/time.h"
+#include "components/offline_items_collection/core/pending_state.h"
#include "components/offline_pages/core/offline_page_item.h"
#include "url/gurl.h"
+using offline_items_collection::PendingState;
+
namespace offline_pages {
// Class representing a request to save page.
@@ -56,6 +59,9 @@ class SavePageRequest {
RequestState request_state() const { return state_; }
void set_request_state(RequestState new_state) { state_ = new_state; }
+ PendingState pending_state() const { return pending_state_; }
+ void set_pending_state(PendingState new_state) { pending_state_ = new_state; }
+
const base::Time& creation_time() const { return creation_time_; }
int64_t started_attempt_count() const { return started_attempt_count_; }
@@ -116,9 +122,12 @@ class SavePageRequest {
// like AGSA or Now.)
bool user_requested_;
- // The current state of this request
+ // The current state of this request.
RequestState state_;
+ // The reason the request is available.
+ PendingState pending_state_;
+
// The original URL of the page to be offlined. Empty if no redirect occurs.
GURL original_url_;
diff --git a/chromium/components/offline_pages/core/client_policy_controller.cc b/chromium/components/offline_pages/core/client_policy_controller.cc
index 4f7b57baebb..efa68c88795 100644
--- a/chromium/components/offline_pages/core/client_policy_controller.cc
+++ b/chromium/components/offline_pages/core/client_policy_controller.cc
@@ -34,6 +34,7 @@ ClientPolicyController::ClientPolicyController() {
OfflinePageClientPolicyBuilder(kAsyncNamespace, LifetimeType::PERSISTENT,
kUnlimitedPages, kUnlimitedPages)
.SetIsSupportedByDownload(true)
+ .SetIsUserRequestedDownload(true)
.SetIsRemovedOnCacheReset(false)
.Build()));
policies_.insert(std::make_pair(
@@ -49,6 +50,7 @@ ClientPolicyController::ClientPolicyController() {
kUnlimitedPages, kUnlimitedPages)
.SetIsRemovedOnCacheReset(false)
.SetIsSupportedByDownload(true)
+ .SetIsUserRequestedDownload(true)
.Build()));
policies_.insert(std::make_pair(
kNTPSuggestionsNamespace,
@@ -56,6 +58,7 @@ ClientPolicyController::ClientPolicyController() {
LifetimeType::PERSISTENT, kUnlimitedPages,
kUnlimitedPages)
.SetIsSupportedByDownload(true)
+ .SetIsUserRequestedDownload(true)
.SetIsRemovedOnCacheReset(false)
.Build()));
policies_.insert(std::make_pair(
@@ -76,6 +79,7 @@ ClientPolicyController::ClientPolicyController() {
kUnlimitedPages)
.SetIsRemovedOnCacheReset(false)
.SetIsSupportedByDownload(true)
+ .SetShouldAllowDownload(true)
.Build()));
// Fallback policy.
@@ -126,6 +130,11 @@ bool ClientPolicyController::IsSupportedByDownload(
return GetPolicy(name_space).feature_policy.is_supported_by_download;
}
+bool ClientPolicyController::IsUserRequestedDownload(
+ const std::string& name_space) const {
+ return GetPolicy(name_space).feature_policy.is_user_requested_download;
+}
+
const std::vector<std::string>&
ClientPolicyController::GetNamespacesRemovedOnCacheReset() const {
if (cache_reset_namespace_cache_)
@@ -152,6 +161,20 @@ ClientPolicyController::GetNamespacesSupportedByDownload() const {
return *download_namespace_cache_;
}
+const std::vector<std::string>&
+ClientPolicyController::GetNamespacesForUserRequestedDownload() const {
+ if (user_requested_download_namespace_cache_)
+ return *user_requested_download_namespace_cache_;
+
+ user_requested_download_namespace_cache_ =
+ std::make_unique<std::vector<std::string>>();
+ for (const auto& policy_item : policies_) {
+ if (policy_item.second.feature_policy.is_user_requested_download)
+ user_requested_download_namespace_cache_->emplace_back(policy_item.first);
+ }
+ return *user_requested_download_namespace_cache_;
+}
+
bool ClientPolicyController::IsShownAsRecentlyVisitedSite(
const std::string& name_space) const {
return GetPolicy(name_space).feature_policy.is_supported_by_recent_tabs;
@@ -214,6 +237,11 @@ bool ClientPolicyController::IsSuggested(const std::string& name_space) const {
return GetPolicy(name_space).feature_policy.is_suggested;
}
+bool ClientPolicyController::ShouldAllowDownloads(
+ const std::string& name_space) const {
+ return GetPolicy(name_space).feature_policy.should_allow_download;
+}
+
void ClientPolicyController::AddPolicyForTest(
const std::string& name_space,
const OfflinePageClientPolicyBuilder& builder) {
diff --git a/chromium/components/offline_pages/core/client_policy_controller.h b/chromium/components/offline_pages/core/client_policy_controller.h
index a3d969a74fa..9084d9bec1b 100644
--- a/chromium/components/offline_pages/core/client_policy_controller.h
+++ b/chromium/components/offline_pages/core/client_policy_controller.h
@@ -46,6 +46,11 @@ class ClientPolicyController {
bool IsSupportedByDownload(const std::string& name_space) const;
const std::vector<std::string>& GetNamespacesSupportedByDownload() const;
+ // Returns whether pages for |name_space| are explicitly offlined due to user
+ // action.
+ bool IsUserRequestedDownload(const std::string& name_space) const;
+ const std::vector<std::string>& GetNamespacesForUserRequestedDownload() const;
+
// Returns whether pages for |name_space| are shown in recent tabs UI,
// currently only available on NTP.
bool IsShownAsRecentlyVisitedSite(const std::string& name_space) const;
@@ -65,6 +70,10 @@ class ClientPolicyController {
// are downloaded on behalf of user.
bool IsSuggested(const std::string& name_space) const;
+ // Returns whether we should allow pages for |name_space| to trigger
+ // downloads.
+ bool ShouldAllowDownloads(const std::string& name_space) const;
+
void AddPolicyForTest(const std::string& name_space,
const OfflinePageClientPolicyBuilder& builder);
@@ -77,6 +86,8 @@ class ClientPolicyController {
mutable std::unique_ptr<std::vector<std::string>>
cache_reset_namespace_cache_;
mutable std::unique_ptr<std::vector<std::string>> download_namespace_cache_;
+ mutable std::unique_ptr<std::vector<std::string>>
+ user_requested_download_namespace_cache_;
mutable std::unique_ptr<std::vector<std::string>> recent_tab_namespace_cache_;
mutable std::unique_ptr<std::vector<std::string>> show_in_original_tab_cache_;
mutable std::unique_ptr<std::vector<std::string>>
diff --git a/chromium/components/offline_pages/core/client_policy_controller_unittest.cc b/chromium/components/offline_pages/core/client_policy_controller_unittest.cc
index ba4b58fae6b..85ad560db87 100644
--- a/chromium/components/offline_pages/core/client_policy_controller_unittest.cc
+++ b/chromium/components/offline_pages/core/client_policy_controller_unittest.cc
@@ -32,6 +32,8 @@ class ClientPolicyControllerTest : public testing::Test {
protected:
void ExpectRemovedOnCacheReset(std::string name_space, bool expectation);
void ExpectDownloadSupport(std::string name_space, bool expectation);
+ void ExpectUserRequestedDownloadSupport(std::string name_space,
+ bool expectation);
void ExpectRecentTab(std::string name_space, bool expectation);
void ExpectOnlyOriginalTab(std::string name_space, bool expectation);
void ExpectDisabledWhenPrefetchDisabled(std::string name_space,
@@ -73,6 +75,22 @@ void ClientPolicyControllerTest::ExpectDownloadSupport(std::string name_space,
" by download.";
}
+void ClientPolicyControllerTest::ExpectUserRequestedDownloadSupport(
+ std::string name_space,
+ bool expectation) {
+ std::vector<std::string> cache =
+ controller()->GetNamespacesForUserRequestedDownload();
+ auto result = std::find(cache.begin(), cache.end(), name_space);
+ EXPECT_EQ(expectation, result != cache.end())
+ << "Namespace " << name_space
+ << " had incorrect user generated download support when getting"
+ " namespaces supported by user generaged download.";
+ EXPECT_EQ(expectation, controller()->IsUserRequestedDownload(name_space))
+ << "Namespace " << name_space
+ << " had incorrect user generated download support when directly checking"
+ " if supported by user generated download.";
+}
+
void ClientPolicyControllerTest::ExpectRecentTab(std::string name_space,
bool expectation) {
std::vector<std::string> cache =
@@ -127,6 +145,7 @@ TEST_F(ClientPolicyControllerTest, FallbackTest) {
EXPECT_TRUE(controller()->IsRemovedOnCacheReset(kUndefinedNamespace));
ExpectRemovedOnCacheReset(kUndefinedNamespace, true);
ExpectDownloadSupport(kUndefinedNamespace, false);
+ ExpectUserRequestedDownloadSupport(kUndefinedNamespace, false);
ExpectRecentTab(kUndefinedNamespace, false);
ExpectOnlyOriginalTab(kUndefinedNamespace, false);
ExpectDisabledWhenPrefetchDisabled(kUndefinedNamespace, false);
@@ -139,6 +158,7 @@ TEST_F(ClientPolicyControllerTest, CheckBookmarkDefined) {
EXPECT_TRUE(controller()->IsRemovedOnCacheReset(kBookmarkNamespace));
ExpectRemovedOnCacheReset(kBookmarkNamespace, true);
ExpectDownloadSupport(kBookmarkNamespace, false);
+ ExpectUserRequestedDownloadSupport(kBookmarkNamespace, false);
ExpectRecentTab(kBookmarkNamespace, false);
ExpectOnlyOriginalTab(kBookmarkNamespace, false);
ExpectDisabledWhenPrefetchDisabled(kBookmarkNamespace, false);
@@ -151,6 +171,7 @@ TEST_F(ClientPolicyControllerTest, CheckLastNDefined) {
EXPECT_TRUE(controller()->IsRemovedOnCacheReset(kLastNNamespace));
ExpectRemovedOnCacheReset(kLastNNamespace, true);
ExpectDownloadSupport(kLastNNamespace, false);
+ ExpectUserRequestedDownloadSupport(kLastNNamespace, false);
ExpectRecentTab(kLastNNamespace, true);
ExpectOnlyOriginalTab(kLastNNamespace, true);
ExpectDisabledWhenPrefetchDisabled(kLastNNamespace, false);
@@ -163,6 +184,7 @@ TEST_F(ClientPolicyControllerTest, CheckAsyncDefined) {
EXPECT_FALSE(controller()->IsRemovedOnCacheReset(kAsyncNamespace));
ExpectRemovedOnCacheReset(kAsyncNamespace, false);
ExpectDownloadSupport(kAsyncNamespace, true);
+ ExpectUserRequestedDownloadSupport(kAsyncNamespace, true);
ExpectRecentTab(kAsyncNamespace, false);
ExpectOnlyOriginalTab(kAsyncNamespace, false);
ExpectDisabledWhenPrefetchDisabled(kAsyncNamespace, false);
@@ -175,6 +197,7 @@ TEST_F(ClientPolicyControllerTest, CheckCCTDefined) {
EXPECT_TRUE(controller()->IsRemovedOnCacheReset(kCCTNamespace));
ExpectRemovedOnCacheReset(kCCTNamespace, true);
ExpectDownloadSupport(kCCTNamespace, false);
+ ExpectUserRequestedDownloadSupport(kCCTNamespace, false);
ExpectRecentTab(kCCTNamespace, false);
ExpectOnlyOriginalTab(kCCTNamespace, false);
ExpectDisabledWhenPrefetchDisabled(kCCTNamespace, true);
@@ -187,6 +210,7 @@ TEST_F(ClientPolicyControllerTest, CheckDownloadDefined) {
EXPECT_FALSE(controller()->IsRemovedOnCacheReset(kDownloadNamespace));
ExpectRemovedOnCacheReset(kDownloadNamespace, false);
ExpectDownloadSupport(kDownloadNamespace, true);
+ ExpectUserRequestedDownloadSupport(kDownloadNamespace, true);
ExpectRecentTab(kDownloadNamespace, false);
ExpectOnlyOriginalTab(kDownloadNamespace, false);
ExpectDisabledWhenPrefetchDisabled(kDownloadNamespace, false);
@@ -200,6 +224,7 @@ TEST_F(ClientPolicyControllerTest, CheckNTPSuggestionsDefined) {
EXPECT_FALSE(controller()->IsRemovedOnCacheReset(kNTPSuggestionsNamespace));
ExpectRemovedOnCacheReset(kNTPSuggestionsNamespace, false);
ExpectDownloadSupport(kNTPSuggestionsNamespace, true);
+ ExpectUserRequestedDownloadSupport(kNTPSuggestionsNamespace, true);
ExpectRecentTab(kNTPSuggestionsNamespace, false);
ExpectOnlyOriginalTab(kNTPSuggestionsNamespace, false);
ExpectDisabledWhenPrefetchDisabled(kNTPSuggestionsNamespace, false);
@@ -213,6 +238,7 @@ TEST_F(ClientPolicyControllerTest, CheckSuggestedArticlesDefined) {
EXPECT_TRUE(controller()->IsRemovedOnCacheReset(kSuggestedArticlesNamespace));
ExpectRemovedOnCacheReset(kSuggestedArticlesNamespace, true);
ExpectDownloadSupport(kSuggestedArticlesNamespace, false);
+ ExpectUserRequestedDownloadSupport(kSuggestedArticlesNamespace, false);
ExpectRecentTab(kSuggestedArticlesNamespace, false);
ExpectOnlyOriginalTab(kSuggestedArticlesNamespace, false);
ExpectDisabledWhenPrefetchDisabled(kSuggestedArticlesNamespace, true);
diff --git a/chromium/components/offline_pages/core/downloads/BUILD.gn b/chromium/components/offline_pages/core/downloads/BUILD.gn
index 13e83c40dc3..7fddee420bf 100644
--- a/chromium/components/offline_pages/core/downloads/BUILD.gn
+++ b/chromium/components/offline_pages/core/downloads/BUILD.gn
@@ -21,6 +21,7 @@ static_library("offline_pages_ui_adapter") {
"//base",
"//components/offline_items_collection/core",
"//components/offline_pages/core",
+ "//components/offline_pages/core:switches",
"//components/offline_pages/core/background:background_offliner",
"//url",
]
@@ -40,6 +41,7 @@ source_set("unit_tests") {
"//base/test:test_support",
"//components/offline_items_collection/core",
"//components/offline_pages/core",
+ "//components/offline_pages/core:switches",
"//components/offline_pages/core:test_support",
"//components/offline_pages/core/background:background_offliner",
"//components/offline_pages/core/background:test_support",
diff --git a/chromium/components/offline_pages/core/downloads/download_notifying_observer.cc b/chromium/components/offline_pages/core/downloads/download_notifying_observer.cc
index 3481668d70a..f70fe6024b9 100644
--- a/chromium/components/offline_pages/core/downloads/download_notifying_observer.cc
+++ b/chromium/components/offline_pages/core/downloads/download_notifying_observer.cc
@@ -84,7 +84,9 @@ void DownloadNotifyingObserver::OnCompleted(
notifier_->NotifyDownloadSuccessful(
OfflineItemConversions::CreateOfflineItem(request));
else if (status ==
- RequestCoordinator::BackgroundSavePageResult::USER_CANCELED)
+ RequestCoordinator::BackgroundSavePageResult::USER_CANCELED ||
+ status ==
+ RequestCoordinator::BackgroundSavePageResult::DOWNLOAD_THROTTLED)
notifier_->NotifyDownloadCanceled(
OfflineItemConversions::CreateOfflineItem(request));
else
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 3d9be479e21..d0c07bea79f 100644
--- a/chromium/components/offline_pages/core/downloads/download_ui_adapter.cc
+++ b/chromium/components/offline_pages/core/downloads/download_ui_adapter.cc
@@ -5,9 +5,11 @@
#include "components/offline_pages/core/downloads/download_ui_adapter.h"
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/guid.h"
#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
#include "components/offline_pages/core/background/request_coordinator.h"
#include "components/offline_pages/core/background/save_page_request.h"
#include "components/offline_pages/core/client_namespace_constants.h"
@@ -88,7 +90,6 @@ DownloadUIAdapter::DownloadUIAdapter(OfflineContentAggregator* aggregator,
request_coordinator_(request_coordinator),
delegate_(std::move(delegate)),
state_(State::NOT_LOADED),
- observers_count_(0),
weak_ptr_factory_(this) {
delegate_->SetUIAdapter(this);
if (aggregator_)
@@ -105,18 +106,7 @@ void DownloadUIAdapter::AddObserver(
DCHECK(observer);
if (observers_.HasObserver(observer))
return;
- if (observers_count_ == 0)
- LoadCache();
observers_.AddObserver(observer);
- ++observers_count_;
- // If the items are already loaded, post the notification right away.
- // Don't just invoke it from here to avoid reentrancy in the client.
- if (state_ == State::LOADED) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&DownloadUIAdapter::NotifyItemsLoaded,
- weak_ptr_factory_.GetWeakPtr(), base::Unretained(observer)));
- }
}
void DownloadUIAdapter::RemoveObserver(
@@ -125,10 +115,6 @@ void DownloadUIAdapter::RemoveObserver(
if (!observers_.HasObserver(observer))
return;
observers_.RemoveObserver(observer);
- --observers_count_;
- // Once the last observer is gone, clear cached data.
- if (observers_count_ == 0)
- ClearCache();
}
void DownloadUIAdapter::OfflinePageModelLoaded(OfflinePageModel* model) {
@@ -209,6 +195,9 @@ void DownloadUIAdapter::OnChanged(const SavePageRequest& request) {
void DownloadUIAdapter::OnNetworkProgress(const SavePageRequest& request,
int64_t received_bytes) {
+ if (state_ != State::LOADED)
+ return;
+
for (auto& item : items_) {
if (item.second->is_request &&
item.second->offline_id == request.request_id()) {
@@ -225,6 +214,9 @@ void DownloadUIAdapter::OnNetworkProgress(const SavePageRequest& request,
void DownloadUIAdapter::TemporaryHiddenStatusChanged(
const ClientId& client_id) {
+ if (state_ != State::LOADED)
+ return;
+
bool hidden = delegate_->IsTemporarilyHiddenInUI(client_id);
for (const auto& item : items_) {
@@ -246,60 +238,61 @@ void DownloadUIAdapter::TemporaryHiddenStatusChanged(
void DownloadUIAdapter::GetAllItems(
OfflineContentProvider::MultipleItemCallback callback) {
- std::vector<OfflineItem> items;
- for (const auto& item : items_) {
- if (delegate_->IsTemporarilyHiddenInUI(item.second->client_id))
- continue;
- items.push_back(*(item.second->ui_item));
+ if (state_ == State::LOADED) {
+ ReplyWithAllItems(std::move(callback));
+ return;
}
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), items));
+ postponed_callbacks_.emplace_back(std::move(callback));
+ LoadCache();
}
+// TODO(dimich): Remove this method since it is not used currently. If needed,
+// it has to be updated to fault in the initial load of items. Currently it
+// simply returns nullopt if the cache is not loaded.
void DownloadUIAdapter::GetItemById(
const ContentId& id,
OfflineContentProvider::SingleItemCallback callback) {
base::Optional<OfflineItem> offline_item;
- OfflineItems::const_iterator it = items_.find(id.id);
- if (it != items_.end() && it->second->ui_item &&
- !delegate_->IsTemporarilyHiddenInUI(it->second->client_id)) {
- offline_item = *it->second->ui_item.get();
+ if (state_ == State::LOADED) {
+ OfflineItems::const_iterator it = items_.find(id.id);
+ if (it != items_.end() && it->second->ui_item &&
+ !delegate_->IsTemporarilyHiddenInUI(it->second->client_id)) {
+ offline_item = *it->second->ui_item.get();
+ }
}
-
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), offline_item));
}
-bool DownloadUIAdapter::AreItemsAvailable() {
- return state_ == State::LOADED;
-}
-
void DownloadUIAdapter::OpenItem(const ContentId& id) {
- OfflineItems::const_iterator it = items_.find(id.id);
- if (it == items_.end())
- return;
-
- const OfflineItem* item = it->second->ui_item.get();
- if (!item)
+ if (state_ == State::LOADED) {
+ OpenItemByGuid(id.id);
return;
+ }
- delegate_->OpenItem(*item, GetOfflineIdByGuid(id.id));
+ postponed_operations_.push_back(
+ base::BindOnce(&DownloadUIAdapter::OpenItemByGuid,
+ weak_ptr_factory_.GetWeakPtr(), id.id));
+ LoadCache();
}
void DownloadUIAdapter::RemoveItem(const ContentId& id) {
- OfflineItems::const_iterator it = items_.find(id.id);
- if (it == items_.end())
+ if (state_ == State::LOADED) {
+ RemoveItemByGuid(id.id);
return;
+ }
- std::vector<int64_t> page_ids;
- page_ids.push_back(it->second->offline_id);
- model_->DeletePagesByOfflineId(
- page_ids, base::Bind(&DownloadUIAdapter::OnDeletePagesDone,
- weak_ptr_factory_.GetWeakPtr()));
+ postponed_operations_.push_back(
+ base::BindOnce(&DownloadUIAdapter::RemoveItemByGuid,
+ weak_ptr_factory_.GetWeakPtr(), id.id));
+ LoadCache();
}
int64_t DownloadUIAdapter::GetOfflineIdByGuid(const std::string& guid) const {
+ if (state_ != State::LOADED)
+ return 0;
+
if (deleting_item_ && deleting_item_->ui_item->id.id == guid)
return deleting_item_->offline_id;
@@ -322,8 +315,7 @@ void DownloadUIAdapter::CancelDownloadContinuation(
std::vector<std::unique_ptr<SavePageRequest>> requests) {
std::vector<int64_t> request_ids = FilterRequestsByGuid(
std::move(requests), guid, request_coordinator_->GetPolicyController());
- request_coordinator_->RemoveRequests(
- request_ids, base::Bind([](const MultipleItemStatuses&) {}));
+ request_coordinator_->RemoveRequests(request_ids, base::DoNothing());
}
void DownloadUIAdapter::PauseDownload(const ContentId& id) {
@@ -350,8 +342,7 @@ void DownloadUIAdapter::ResumeDownload(const ContentId& id,
base::Bind(&DownloadUIAdapter::ResumeDownloadContinuation,
weak_ptr_factory_.GetWeakPtr(), id.id));
} else {
- request_coordinator_->StartImmediateProcessing(
- base::Bind([](bool result) {}));
+ request_coordinator_->StartImmediateProcessing(base::DoNothing());
}
}
@@ -365,11 +356,15 @@ void DownloadUIAdapter::ResumeDownloadContinuation(
// Note that several LoadCache calls may be issued before the async GetAllPages
// comes back.
void DownloadUIAdapter::LoadCache() {
+ if (state_ != State::NOT_LOADED)
+ return;
state_ = State::LOADING_PAGES;
model_->GetAllPages(base::Bind(&DownloadUIAdapter::OnOfflinePagesLoaded,
weak_ptr_factory_.GetWeakPtr()));
}
+// TODO(dimich): Start clearing this cache on UI close. Also, after OpenItem can
+// done without loading all items from database.
void DownloadUIAdapter::ClearCache() {
// Once loaded, this class starts to observe the model. Only remove observer
// if it was added.
@@ -379,6 +374,8 @@ void DownloadUIAdapter::ClearCache() {
}
items_.clear();
state_ = State::NOT_LOADED;
+ TRACE_EVENT_ASYNC_END0("offline_pages", "DownloadUIAdapter: items cached",
+ this);
}
void DownloadUIAdapter::OnOfflinePagesLoaded(
@@ -430,16 +427,22 @@ void DownloadUIAdapter::OnRequestsLoaded(
request_coordinator_->AddObserver(this);
state_ = State::LOADED;
- for (auto& observer : observers_)
- observer.OnItemsAvailable(this);
-}
+ TRACE_EVENT_ASYNC_BEGIN1("offline_pages", "DownloadUIAdapter: items cached",
+ this, "initial count", items_.size());
-void DownloadUIAdapter::NotifyItemsLoaded(
- OfflineContentProvider::Observer* observer) {
- if (observer && observers_.HasObserver(observer))
- observer->OnItemsAvailable(this);
-}
+ // If there are callers waiting for GetAllItems callback, call them.
+ for (auto& callback : postponed_callbacks_) {
+ ReplyWithAllItems(std::move(callback));
+ }
+ postponed_callbacks_.clear();
+ // If there were requests to perform operations on items before cache was
+ // loaded, perform them now.
+ for (auto& operation : postponed_operations_) {
+ std::move(operation).Run();
+ }
+ postponed_operations_.clear();
+}
void DownloadUIAdapter::OnDeletePagesDone(DeletePageResult result) {
// TODO(dimich): Consider adding UMA to record user actions.
@@ -497,4 +500,50 @@ void DownloadUIAdapter::DeleteItemHelper(const std::string& guid) {
deleting_item_.reset();
}
+void DownloadUIAdapter::ReplyWithAllItems(
+ OfflineContentProvider::MultipleItemCallback callback) {
+ std::vector<OfflineItem> items;
+ for (const auto& item : items_) {
+ if (delegate_->IsTemporarilyHiddenInUI(item.second->client_id))
+ continue;
+ items.push_back(*(item.second->ui_item));
+ }
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), items));
+}
+
+void DownloadUIAdapter::OpenItemByGuid(const std::string& guid) {
+ if (state_ != State::LOADED) {
+ return;
+ }
+
+ OfflineItems::const_iterator it = items_.find(guid);
+ if (it == items_.end())
+ return;
+
+ const OfflineItem* item = it->second->ui_item.get();
+ if (!item)
+ return;
+
+ delegate_->OpenItem(*item, GetOfflineIdByGuid(guid));
+}
+
+void DownloadUIAdapter::RemoveItemByGuid(const std::string& guid) {
+ if (state_ != State::LOADED) {
+ return;
+ }
+
+ OfflineItems::const_iterator it = items_.find(guid);
+ if (it == items_.end())
+ return;
+
+ std::vector<int64_t> page_ids;
+ page_ids.push_back(it->second->offline_id);
+
+ model_->DeletePagesByOfflineId(
+ page_ids, base::BindRepeating(&DownloadUIAdapter::OnDeletePagesDone,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
} // namespace offline_pages
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 657c1504247..37b3185ba51 100644
--- a/chromium/components/offline_pages/core/downloads/download_ui_adapter.h
+++ b/chromium/components/offline_pages/core/downloads/download_ui_adapter.h
@@ -78,7 +78,6 @@ class DownloadUIAdapter : public OfflineContentProvider,
int64_t GetOfflineIdByGuid(const std::string& guid) const;
// OfflineContentProvider implmentation.
- bool AreItemsAvailable() override;
void OpenItem(const ContentId& id) override;
void RemoveItem(const ContentId& id) override;
void CancelDownload(const ContentId& id) override;
@@ -115,6 +114,9 @@ class DownloadUIAdapter : public OfflineContentProvider,
Delegate* delegate() { return delegate_.get(); }
+ // Test method, to verify the internal cache is not loaded too early.
+ bool IsCacheLoadedForTest() { return (state_ != State::NOT_LOADED); }
+
private:
enum class State { NOT_LOADED, LOADING_PAGES, LOADING_REQUESTS, LOADED };
@@ -167,7 +169,6 @@ class DownloadUIAdapter : public OfflineContentProvider,
void OnOfflinePagesLoaded(const MultipleOfflinePageItemResult& pages);
void OnRequestsLoaded(std::vector<std::unique_ptr<SavePageRequest>> requests);
- void NotifyItemsLoaded(OfflineContentProvider::Observer* observer);
void OnDeletePagesDone(DeletePageResult result);
void AddItemHelper(std::unique_ptr<ItemInfo> item_info);
@@ -176,6 +177,11 @@ class DownloadUIAdapter : public OfflineContentProvider,
// during the |ItemDeleted| callback.
void DeleteItemHelper(const std::string& guid);
+ void ReplyWithAllItems(OfflineContentProvider::MultipleItemCallback callback);
+
+ void OpenItemByGuid(const std::string& guid);
+ void RemoveItemByGuid(const std::string& guid);
+
// A valid offline content aggregator, supplied at construction.
OfflineContentAggregator* aggregator_;
@@ -193,11 +199,18 @@ class DownloadUIAdapter : public OfflineContentProvider,
// The cache of UI items. The key is OfflineItem.guid.
OfflineItems items_;
+ // The callbacks for GetAllItems waiting for cache initialization.
+ std::vector<OfflineContentProvider::MultipleItemCallback>
+ postponed_callbacks_;
+
+ // The requests for operations with items waiting for cache initialization.
+ // std::vector<base::OnceCallback<const std::string&>> postponed_operations_;
+ std::vector<base::OnceClosure> postponed_operations_;
+
std::unique_ptr<ItemInfo> deleting_item_;
// The observers.
base::ObserverList<OfflineContentProvider::Observer> observers_;
- int observers_count_;
base::WeakPtrFactory<DownloadUIAdapter> weak_ptr_factory_;
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 0ad63ef7b08..10f9c460780 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
@@ -38,6 +38,7 @@ namespace {
// Constants for a test OfflinePageItem.
static const int kTestOfflineId1 = 1;
static const int kTestOfflineId2 = 2;
+static const int64_t kSystemDownloadId = 0;
static const char kTestUrl[] = "http://foo.com/bar.mhtml";
static const char kTestGuid1[] = "cccccccc-cccc-4ccc-0ccc-ccccccccccc1";
static const char kTestGuid2[] = "cccccccc-cccc-4ccc-0ccc-ccccccccccc2";
@@ -63,6 +64,10 @@ void GetItemAndVerify(const base::Optional<OfflineItem>& expected,
EXPECT_EQ(expected.value().state, actual.value().state);
}
+void GetAllItemsAndIgnoreResult(const std::vector<OfflineItem>& actual) {
+ // Do nothing.
+}
+
void GetAllItemsAndVerify(size_t expected_size,
const std::vector<OfflineItem>& actual) {
EXPECT_EQ(expected_size, actual.size());
@@ -134,8 +139,8 @@ class MockOfflinePageModel : public StubOfflinePageModel {
void DeletePageAndNotifyAdapter(const std::string& guid) {
for (const auto& page : pages) {
if (page.second.client_id.id == guid) {
- DeletedPageInfo info(page.second.offline_id, page.second.client_id,
- page.second.request_origin);
+ DeletedPageInfo info(page.second.offline_id, kSystemDownloadId,
+ page.second.client_id, page.second.request_origin);
observer_->OfflinePageDeleted(info);
pages.erase(page.first);
return;
@@ -179,7 +184,6 @@ class DownloadUIAdapterTest : public testing::Test,
void SetUp() override;
// DownloadUIAdapter::Observer
- void OnItemsAvailable(OfflineContentProvider* provider) override;
void OnItemsAdded(const std::vector<OfflineItem>& items) override;
void OnItemUpdated(const OfflineItem& item) override;
void OnItemRemoved(const ContentId& id) override;
@@ -193,8 +197,10 @@ class DownloadUIAdapterTest : public testing::Test,
RequestCoordinator* request_coordinator() {
return request_coordinator_taco_->request_coordinator();
}
+ bool items_loaded() { return adapter->IsCacheLoadedForTest(); }
+ void AddInitialPage();
+ int64_t AddInitialRequest(const GURL& url, const ClientId& client_id);
- bool items_loaded;
std::vector<std::string> added_guids, updated_guids, deleted_guids;
int64_t download_progress_bytes;
std::unique_ptr<MockOfflinePageModel> model;
@@ -209,8 +215,7 @@ class DownloadUIAdapterTest : public testing::Test,
};
DownloadUIAdapterTest::DownloadUIAdapterTest()
- : items_loaded(false),
- task_runner_(new base::TestMockTimeTaskRunner),
+ : task_runner_(new base::TestMockTimeTaskRunner),
task_runner_handle_(task_runner_) {}
DownloadUIAdapterTest::~DownloadUIAdapterTest() {}
@@ -234,10 +239,6 @@ void DownloadUIAdapterTest::SetUp() {
adapter->AddObserver(this);
}
-void DownloadUIAdapterTest::OnItemsAvailable(OfflineContentProvider* provider) {
- items_loaded = true;
-}
-
void DownloadUIAdapterTest::OnItemsAdded(
const std::vector<OfflineItem>& items) {
for (const OfflineItem& item : items) {
@@ -269,12 +270,27 @@ int64_t DownloadUIAdapterTest::AddRequest(const GURL& url,
params, base::Bind(&SavePageLaterCallback));
}
-TEST_F(DownloadUIAdapterTest, InitialLoad) {
- EXPECT_NE(nullptr, adapter.get());
+void DownloadUIAdapterTest::AddInitialPage() {
model->AddInitialPage();
- EXPECT_FALSE(items_loaded);
+ // Trigger cache load in the adapter.
+ adapter->GetAllItems(base::BindOnce(&GetAllItemsAndIgnoreResult));
PumpLoop();
- EXPECT_TRUE(items_loaded);
+}
+
+int64_t DownloadUIAdapterTest::AddInitialRequest(const GURL& url,
+ const ClientId& client_id) {
+ int64_t id = AddRequest(url, client_id);
+ // Trigger cache load in the adapter.
+ adapter->GetAllItems(base::BindOnce(&GetAllItemsAndIgnoreResult));
+ PumpLoop();
+ return id;
+}
+
+TEST_F(DownloadUIAdapterTest, InitialLoad) {
+ EXPECT_NE(nullptr, adapter.get());
+ EXPECT_FALSE(items_loaded());
+ AddInitialPage();
+ EXPECT_TRUE(items_loaded());
OfflineItem item(kTestContentId1);
adapter->GetItemById(kTestContentId1,
base::BindOnce(&GetItemAndVerify, item));
@@ -282,10 +298,9 @@ TEST_F(DownloadUIAdapterTest, InitialLoad) {
}
TEST_F(DownloadUIAdapterTest, InitialItemConversion) {
- model->AddInitialPage();
+ AddInitialPage();
EXPECT_EQ(1UL, model->pages.size());
EXPECT_EQ(kTestGuid1, model->pages[kTestOfflineId1].client_id.id);
- PumpLoop();
auto callback = [](const base::Optional<OfflineItem>& item) {
EXPECT_EQ(kTestGuid1, item.value().id.id);
@@ -303,8 +318,7 @@ TEST_F(DownloadUIAdapterTest, InitialItemConversion) {
}
TEST_F(DownloadUIAdapterTest, ItemDeletedAdded) {
- model->AddInitialPage();
- PumpLoop();
+ AddInitialPage();
// Add page, notify adapter.
OfflinePageItem page(GURL(kTestUrl), kTestOfflineId2, kTestClientId2,
base::FilePath(kTestFilePath), kFileSize,
@@ -323,8 +337,7 @@ TEST_F(DownloadUIAdapterTest, ItemDeletedAdded) {
}
TEST_F(DownloadUIAdapterTest, NotVisibleItem) {
- model->AddInitialPage();
- PumpLoop();
+ AddInitialPage();
adapter_delegate->is_visible = false;
OfflinePageItem page1(
GURL(kTestUrl), kTestOfflineId2, kTestClientIdOtherNamespace,
@@ -337,8 +350,7 @@ TEST_F(DownloadUIAdapterTest, NotVisibleItem) {
TEST_F(DownloadUIAdapterTest, TemporarilyNotVisibleItem) {
adapter_delegate->is_temporarily_hidden = true;
- model->AddInitialPage();
- PumpLoop();
+ AddInitialPage();
// Initial Item should be invisible in the collection now.
adapter->GetItemById(kTestContentId1,
base::BindOnce(&GetItemAndVerify, base::nullopt));
@@ -377,8 +389,7 @@ TEST_F(DownloadUIAdapterTest, TemporarilyNotVisibleItem) {
}
TEST_F(DownloadUIAdapterTest, ItemAdded) {
- model->AddInitialPage();
- PumpLoop();
+ AddInitialPage();
// Clear the initial page and replace it with updated one.
model->pages.clear();
// Add a new page which did not exist before.
@@ -395,24 +406,9 @@ TEST_F(DownloadUIAdapterTest, ItemAdded) {
EXPECT_EQ(0UL, updated_guids.size());
}
-TEST_F(DownloadUIAdapterTest, NoHangingLoad) {
- model->AddInitialPage();
- EXPECT_NE(nullptr, adapter.get());
- EXPECT_FALSE(items_loaded);
- // Removal of last observer causes cache unload of not-yet-loaded cache.
- adapter->RemoveObserver(this);
- // This will complete async fetch of items, but...
- PumpLoop();
- // items should not be loaded when there is no observers!
- EXPECT_FALSE(items_loaded);
- // This should not crash.
- adapter->AddObserver(this);
-}
-
TEST_F(DownloadUIAdapterTest, LoadExistingRequest) {
- AddRequest(GURL(kTestUrl), kTestClientId1);
- PumpLoop();
- EXPECT_TRUE(items_loaded);
+ AddInitialRequest(GURL(kTestUrl), kTestClientId1);
+ EXPECT_TRUE(items_loaded());
OfflineItem item(kTestContentId1);
item.state = OfflineItemState::IN_PROGRESS;
adapter->GetItemById(kTestContentId1,
@@ -421,8 +417,8 @@ TEST_F(DownloadUIAdapterTest, LoadExistingRequest) {
}
TEST_F(DownloadUIAdapterTest, AddRequest) {
- PumpLoop();
- EXPECT_TRUE(items_loaded);
+ AddInitialPage();
+ EXPECT_TRUE(items_loaded());
EXPECT_EQ(0UL, added_guids.size());
AddRequest(GURL(kTestUrl), kTestClientId1);
PumpLoop();
@@ -436,8 +432,7 @@ TEST_F(DownloadUIAdapterTest, AddRequest) {
}
TEST_F(DownloadUIAdapterTest, RemoveRequest) {
- int64_t id = AddRequest(GURL(kTestUrl), kTestClientId1);
- PumpLoop();
+ int64_t id = AddInitialRequest(GURL(kTestUrl), kTestClientId1);
// No added requests, the initial one is loaded.
EXPECT_EQ(0UL, added_guids.size());
OfflineItem item(kTestContentId1);
@@ -467,8 +462,8 @@ TEST_F(DownloadUIAdapterTest, RemoveRequest) {
}
TEST_F(DownloadUIAdapterTest, PauseAndResume) {
- PumpLoop();
- EXPECT_TRUE(items_loaded);
+ AddInitialPage();
+ EXPECT_TRUE(items_loaded());
AddRequest(GURL(kTestUrl), kTestClientId1);
PumpLoop();
@@ -503,8 +498,7 @@ TEST_F(DownloadUIAdapterTest, PauseAndResume) {
}
TEST_F(DownloadUIAdapterTest, OnChangedReceivedAfterPageAdded) {
- AddRequest(GURL(kTestUrl), kTestClientId1);
- PumpLoop();
+ AddInitialRequest(GURL(kTestUrl), kTestClientId1);
OfflineItem item(kTestContentId1);
item.state = OfflineItemState::IN_PROGRESS;
adapter->GetItemById(kTestContentId1,
@@ -537,8 +531,7 @@ TEST_F(DownloadUIAdapterTest, OnChangedReceivedAfterPageAdded) {
TEST_F(DownloadUIAdapterTest, RequestBecomesPage) {
// This will cause requests to be 'offlined' all the way and removed.
offliner_stub->enable_callback(true);
- AddRequest(GURL(kTestUrl), kTestClientId1);
- PumpLoop();
+ AddInitialRequest(GURL(kTestUrl), kTestClientId1);
OfflineItem item(kTestContentId1);
@@ -572,26 +565,9 @@ TEST_F(DownloadUIAdapterTest, RequestBecomesPage) {
PumpLoop();
}
-TEST_F(DownloadUIAdapterTest, RemoveObserversWhenClearingCache) {
- PumpLoop();
- EXPECT_TRUE(items_loaded);
-
- // Remove this from the adapter's observer list. This should cause the cache
- // to be cleared.
- adapter->RemoveObserver(this);
- items_loaded = false;
-
- PumpLoop();
-
- adapter->AddObserver(this);
- PumpLoop();
- EXPECT_TRUE(items_loaded);
-}
-
TEST_F(DownloadUIAdapterTest, UpdateProgress) {
offliner_stub->enable_callback(true);
- AddRequest(GURL(kTestUrl), kTestClientId1);
- PumpLoop();
+ AddInitialRequest(GURL(kTestUrl), kTestClientId1);
auto callback = [](const base::Optional<OfflineItem>& item) {
ASSERT_TRUE(item.has_value());
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 417962a647c..1b29444c721 100644
--- a/chromium/components/offline_pages/core/downloads/offline_item_conversions.cc
+++ b/chromium/components/offline_pages/core/downloads/offline_item_conversions.cc
@@ -5,13 +5,25 @@
#include "components/offline_pages/core/downloads/offline_item_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/offline_items_collection/core/pending_state.h"
#include "components/offline_pages/core/background/save_page_request.h"
+#include "components/offline_pages/core/offline_page_feature.h"
#include "components/offline_pages/core/offline_page_item.h"
using OfflineItemFilter = offline_items_collection::OfflineItemFilter;
using OfflineItemState = offline_items_collection::OfflineItemState;
using OfflineItemProgressUnit =
offline_items_collection::OfflineItemProgressUnit;
+using PendingState = offline_items_collection::PendingState;
+
+namespace {
+
+const std::string GetMimeType() {
+ return offline_pages::IsOfflinePagesSharingEnabled() ? "multipart/related"
+ : "text/html";
+}
+
+} // namespace
namespace offline_pages {
@@ -27,7 +39,7 @@ OfflineItem OfflineItemConversions::CreateOfflineItem(
item.creation_time = page.creation_time;
item.last_accessed_time = page.last_access_time;
item.file_path = page.file_path;
- item.mime_type = "text/html";
+ item.mime_type = GetMimeType();
item.page_url = page.url;
item.original_url = page.original_url;
item.progress.value = 100;
@@ -46,12 +58,13 @@ OfflineItem OfflineItemConversions::CreateOfflineItem(
item.creation_time = request.creation_time();
item.total_size_bytes = -1L;
item.received_bytes = 0;
- item.mime_type = "text/html";
+ item.mime_type = GetMimeType();
item.page_url = request.url();
item.original_url = request.original_url();
switch (request.request_state()) {
case SavePageRequest::RequestState::AVAILABLE:
item.state = OfflineItemState::PENDING;
+ item.pendingState = request.pending_state();
break;
case SavePageRequest::RequestState::OFFLINING:
item.state = OfflineItemState::IN_PROGRESS;
diff --git a/chromium/components/offline_pages/core/downloads/offline_item_conversions.h b/chromium/components/offline_pages/core/downloads/offline_item_conversions.h
index 47742b78b22..db8740a74b2 100644
--- a/chromium/components/offline_pages/core/downloads/offline_item_conversions.h
+++ b/chromium/components/offline_pages/core/downloads/offline_item_conversions.h
@@ -7,8 +7,6 @@
#include "components/offline_items_collection/core/offline_item.h"
-const char kOfflinePageNamespace[] = "LEGACY_OFFLINE_PAGE";
-
using ContentId = offline_items_collection::ContentId;
using OfflineItem = offline_items_collection::OfflineItem;
@@ -17,6 +15,8 @@ namespace offline_pages {
struct OfflinePageItem;
class SavePageRequest;
+const char kOfflinePageNamespace[] = "LEGACY_OFFLINE_PAGE";
+
// Allows to convert between internal offline pages types and their offline item
// collection representation (for displaying in UI).
class OfflineItemConversions {
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 ab974578808..910cbc6f26e 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
@@ -5,7 +5,9 @@
#include "components/offline_pages/core/downloads/offline_item_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
#include "components/offline_pages/core/background/save_page_request.h"
+#include "components/offline_pages/core/offline_page_feature.h"
#include "components/offline_pages/core/offline_page_item.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -53,6 +55,21 @@ TEST(OfflineItemConversionsTest, OfflinePageItemConversion) {
EXPECT_EQ(100, offline_item.progress.max.value());
EXPECT_EQ(OfflineItemProgressUnit::PERCENTAGE, offline_item.progress.unit);
EXPECT_TRUE(offline_item.is_suggested);
+
+ // Enabled P2P sharing and flag the item as suggested when creating the
+ // OfflineItem. Then check that only the mime type is and is_suggested
+ // information changed.
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(kOfflinePagesSharingFeature);
+ OfflineItem offline_item_p2p =
+ OfflineItemConversions::CreateOfflineItem(offline_page_item, false);
+ EXPECT_EQ("multipart/related", offline_item_p2p.mime_type);
+ EXPECT_FALSE(offline_item_p2p.is_suggested);
+
+ // Change offline_item_p2p to match offline_item and check that it does.
+ offline_item_p2p.mime_type = "text/html";
+ offline_item_p2p.is_suggested = true;
+ EXPECT_EQ(offline_item, offline_item_p2p);
}
TEST(OfflineItemConversionsTest, SavePageRequestConversion) {
@@ -83,6 +100,18 @@ TEST(OfflineItemConversionsTest, SavePageRequestConversion) {
EXPECT_FALSE(offline_item.progress.max.has_value());
EXPECT_EQ(OfflineItemProgressUnit::PERCENTAGE, offline_item.progress.unit);
EXPECT_FALSE(offline_item.is_suggested);
+
+ // Enabled P2P sharing of offline pages and check that only the mime type is
+ // different.
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(kOfflinePagesSharingFeature);
+ OfflineItem offline_item_p2p =
+ OfflineItemConversions::CreateOfflineItem(save_page_request);
+ EXPECT_EQ("multipart/related", offline_item_p2p.mime_type);
+
+ // Change offline_item_p2p to match offline_item and check that it does.
+ offline_item_p2p.mime_type = "text/html";
+ EXPECT_EQ(offline_item, offline_item_p2p);
}
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/model/add_page_to_download_manager_task_unittest.cc b/chromium/components/offline_pages/core/model/add_page_to_download_manager_task_unittest.cc
index 5d9ed71fb18..63677b2dc6a 100644
--- a/chromium/components/offline_pages/core/model/add_page_to_download_manager_task_unittest.cc
+++ b/chromium/components/offline_pages/core/model/add_page_to_download_manager_task_unittest.cc
@@ -4,7 +4,8 @@
#include "components/offline_pages/core/model/add_page_to_download_manager_task.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/offline_pages/core/model/offline_page_item_generator.h"
@@ -102,7 +103,7 @@ TEST_F(AddPageToDownloadManagerTaskTest, AddSimpleId) {
OfflinePageItem page = generator()->CreateItem();
store_test_util()->InsertItem(page);
- auto task = base::MakeUnique<AddPageToDownloadManagerTask>(
+ auto task = std::make_unique<AddPageToDownloadManagerTask>(
store(), download_manager(), page.offline_id, kTitle, kDescription, kPath,
kTestLength, kUri, kReferer);
SetTaskCompletionCallbackForTesting(task.get());
@@ -133,7 +134,7 @@ TEST_F(AddPageToDownloadManagerTaskTest, NoADM) {
OfflinePageItem page = generator()->CreateItem();
store_test_util()->InsertItem(page);
- auto task = base::MakeUnique<AddPageToDownloadManagerTask>(
+ auto task = std::make_unique<AddPageToDownloadManagerTask>(
store(), download_manager(), page.offline_id, kTitle, kDescription, kPath,
kTestLength, kUri, kReferer);
SetTaskCompletionCallbackForTesting(task.get());
@@ -157,7 +158,7 @@ TEST_F(AddPageToDownloadManagerTaskTest, AddDownloadFailed) {
page.system_download_id = kDefaultDownloadId;
store_test_util()->InsertItem(page);
- auto task = base::MakeUnique<AddPageToDownloadManagerTask>(
+ auto task = std::make_unique<AddPageToDownloadManagerTask>(
store(), download_manager(), page.offline_id, kTitle, kDescription, kPath,
kTestLength, kUri, kReferer);
SetTaskCompletionCallbackForTesting(task.get());
diff --git a/chromium/components/offline_pages/core/model/clear_legacy_temporary_pages_task.cc b/chromium/components/offline_pages/core/model/clear_legacy_temporary_pages_task.cc
index b2802c85a42..bea3cb60de5 100644
--- a/chromium/components/offline_pages/core/model/clear_legacy_temporary_pages_task.cc
+++ b/chromium/components/offline_pages/core/model/clear_legacy_temporary_pages_task.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/files/file_util.h"
+#include "base/trace_event/trace_event.h"
#include "components/offline_pages/core/client_policy_controller.h"
#include "components/offline_pages/core/offline_page_metadata_store_sql.h"
#include "components/offline_pages/core/offline_store_utils.h"
@@ -128,6 +129,8 @@ ClearLegacyTemporaryPagesTask::ClearLegacyTemporaryPagesTask(
ClearLegacyTemporaryPagesTask::~ClearLegacyTemporaryPagesTask() {}
void ClearLegacyTemporaryPagesTask::Run() {
+ TRACE_EVENT_ASYNC_BEGIN0("offline_pages",
+ "ClearLegacyTemporaryPagesTask running", this);
std::vector<std::string> temp_namespaces =
policy_controller_->GetNamespacesRemovedOnCacheReset();
store_->Execute(
@@ -145,6 +148,9 @@ void ClearLegacyTemporaryPagesTask::OnClearLegacyTemporaryPagesDone(
// indicating which part failed.
DVLOG(1) << "ClearLegacyTemporaryPagesTask returns with result: " << result;
TaskComplete();
+ TRACE_EVENT_ASYNC_END1("offline_pages",
+ "ClearLegacyTemporaryPagesTask running", this,
+ "result", result);
}
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/model/clear_storage_task.cc b/chromium/components/offline_pages/core/model/clear_storage_task.cc
index a494369cc4d..8f72bd8fee7 100644
--- a/chromium/components/offline_pages/core/model/clear_storage_task.cc
+++ b/chromium/components/offline_pages/core/model/clear_storage_task.cc
@@ -13,9 +13,9 @@
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
-#include "base/time/clock.h"
-#include "base/time/default_clock.h"
+#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "components/offline_pages/core/client_policy_controller.h"
#include "components/offline_pages/core/offline_page_client_policy.h"
#include "components/offline_pages/core/offline_page_metadata_store_sql.h"
@@ -31,9 +31,9 @@ using ClearStorageResult = ClearStorageTask::ClearStorageResult;
namespace {
-#define PAGE_INFO_PROJECTION \
- " offline_id, client_namespace, client_id, file_size, last_access_time," \
- " file_path"
+#define PAGE_INFO_PROJECTION \
+ " offline_id, client_namespace, client_id, file_size, creation_time," \
+ " last_access_time, file_path "
// This struct needs to be in sync with |PAGE_INFO_PROJECTION|.
struct PageInfo {
@@ -42,6 +42,7 @@ struct PageInfo {
int64_t offline_id;
ClientId client_id;
int64_t file_size;
+ base::Time creation_time;
base::Time last_access_time;
base::FilePath file_path;
};
@@ -62,10 +63,12 @@ PageInfo MakePageInfo(sql::Statement* statement) {
page_info.client_id =
ClientId(statement->ColumnString(1), statement->ColumnString(2));
page_info.file_size = statement->ColumnInt64(3);
- page_info.last_access_time =
+ page_info.creation_time =
store_utils::FromDatabaseTime(statement->ColumnInt64(4));
+ page_info.last_access_time =
+ store_utils::FromDatabaseTime(statement->ColumnInt64(5));
page_info.file_path =
- store_utils::FromDatabaseFilePath(statement->ColumnString(5));
+ store_utils::FromDatabaseFilePath(statement->ColumnString(6));
return page_info;
}
@@ -77,9 +80,6 @@ std::unique_ptr<std::vector<PageInfo>> GetAllTemporaryPageInfos(
const char kSql[] = "SELECT " PAGE_INFO_PROJECTION
" FROM offlinepages_v1"
" WHERE client_namespace = ?";
- sql::Transaction transaction(db);
- if (!transaction.Begin())
- return result;
for (const auto& temp_namespace_policy : temp_namespace_policy_map) {
std::string name_space = temp_namespace_policy.first;
@@ -87,10 +87,12 @@ std::unique_ptr<std::vector<PageInfo>> GetAllTemporaryPageInfos(
statement.BindString(0, name_space);
while (statement.Step())
result->emplace_back(MakePageInfo(&statement));
+ if (!statement.Succeeded()) {
+ result->clear();
+ break;
+ }
}
- if (!transaction.Commit())
- result->clear();
return result;
}
@@ -186,25 +188,29 @@ std::pair<size_t, DeletePageResult> ClearPagesSync(
if (!db)
return std::make_pair(0, DeletePageResult::STORE_FAILURE);
- DeletePageResult result = DeletePageResult::SUCCESS;
- size_t pages_cleared = 0;
-
- auto page_infos =
+ std::unique_ptr<std::vector<PageInfo>> page_infos =
GetPageInfosToClear(temp_namespace_policy_map, start_time, stats, db);
- if (page_infos->empty())
- return std::make_pair(pages_cleared, result);
-
+ size_t pages_cleared = 0;
for (const auto& page_info : *page_infos) {
if (!base::PathExists(page_info.file_path) ||
DeleteArchiveSync(page_info.file_path)) {
- if (DeletePageEntryByOfflineIdSync(db, page_info.offline_id))
+ if (DeletePageEntryByOfflineIdSync(db, page_info.offline_id)) {
pages_cleared++;
+ // Reports the time since creation in minutes.
+ base::TimeDelta time_since_creation =
+ start_time - page_info.creation_time;
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation",
+ time_since_creation.InMinutes(), 1,
+ base::TimeDelta::FromDays(30).InMinutes(), 50);
+ }
}
}
- if (pages_cleared != page_infos->size())
- result = DeletePageResult::STORE_FAILURE;
- return std::make_pair(pages_cleared, result);
+
+ return std::make_pair(pages_cleared, pages_cleared == page_infos->size()
+ ? DeletePageResult::SUCCESS
+ : DeletePageResult::STORE_FAILURE);
}
std::map<std::string, LifetimePolicy> GetTempNamespacePolicyMap(
@@ -240,6 +246,7 @@ ClearStorageTask::ClearStorageTask(OfflinePageMetadataStoreSQL* store,
ClearStorageTask::~ClearStorageTask() {}
void ClearStorageTask::Run() {
+ TRACE_EVENT_ASYNC_BEGIN0("offline_pages", "ClearStorageTask running", this);
archive_manager_->GetStorageStats(
base::Bind(&ClearStorageTask::OnGetStorageStatsDone,
weak_ptr_factory_.GetWeakPtr()));
@@ -272,6 +279,9 @@ void ClearStorageTask::InformClearStorageDone(size_t pages_cleared,
ClearStorageResult result) {
std::move(callback_).Run(pages_cleared, result);
TaskComplete();
+ TRACE_EVENT_ASYNC_END2("offline_pages", "ClearStorageTask running", this,
+ "result", static_cast<int>(result), "pages_cleared",
+ pages_cleared);
}
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/model/clear_storage_task_unittest.cc b/chromium/components/offline_pages/core/model/clear_storage_task_unittest.cc
index d129e7fa292..c412c86463e 100644
--- a/chromium/components/offline_pages/core/model/clear_storage_task_unittest.cc
+++ b/chromium/components/offline_pages/core/model/clear_storage_task_unittest.cc
@@ -9,10 +9,10 @@
#include "base/bind.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
+#include "base/test/histogram_tester.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"
-#include "base/time/clock.h"
#include "base/time/time.h"
#include "components/offline_pages/core/client_namespace_constants.h"
#include "components/offline_pages/core/client_policy_controller.h"
@@ -76,10 +76,9 @@ class ClearStorageTaskTest
void TearDown() override;
void Initialize(const std::vector<PageSettings>& settings,
- base::SimpleTestClock* clock,
TestOptions options = TestOptions::DEFAULT);
void OnClearStorageDone(size_t cleared_page_count, ClearStorageResult result);
- void AddPages(const PageSettings& setting, base::SimpleTestClock* clock_ptr);
+ void AddPages(const PageSettings& setting);
void RunClearStorageTask(const base::Time& start_time);
void SetFreeSpace(int64_t free_space) {
@@ -97,12 +96,13 @@ class ClearStorageTaskTest
}
ArchiveManager* archive_manager() { return archive_manager_.get(); }
const base::FilePath& temp_dir_path() { return temp_dir_.GetPath(); }
- base::SimpleTestClock* clock() { return clock_; }
+ base::SimpleTestClock* clock() { return &clock_; }
size_t last_cleared_page_count() { return last_cleared_page_count_; }
int total_cleared_times() { return total_cleared_times_; }
ClearStorageResult last_clear_storage_result() {
return last_clear_storage_result_;
}
+ base::HistogramTester* histogram_tester() { return histogram_tester_.get(); }
private:
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
@@ -114,11 +114,12 @@ class ClearStorageTaskTest
std::unique_ptr<ClientPolicyController> policy_controller_;
std::unique_ptr<TestArchiveManager> archive_manager_;
base::ScopedTempDir temp_dir_;
- base::SimpleTestClock* clock_;
+ base::SimpleTestClock clock_;
size_t last_cleared_page_count_;
int total_cleared_times_;
ClearStorageResult last_clear_storage_result_;
+ std::unique_ptr<base::HistogramTester> histogram_tester_;
};
ClearStorageTaskTest::ClearStorageTaskTest()
@@ -137,6 +138,8 @@ void ClearStorageTaskTest::SetUp() {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
// Setting up policies for testing.
policy_controller_ = std::make_unique<ClientPolicyController>();
+ clock_.SetNow(base::Time::Now());
+ histogram_tester_ = std::make_unique<base::HistogramTester>();
}
void ClearStorageTaskTest::TearDown() {
@@ -150,13 +153,12 @@ void ClearStorageTaskTest::TearDown() {
void ClearStorageTaskTest::Initialize(
const std::vector<PageSettings>& page_settings,
- base::SimpleTestClock* clock,
TestOptions options) {
generator()->SetFileSize(kTestFileSize);
// Adding pages based on |page_settings|.
for (const auto& setting : page_settings)
- AddPages(setting, clock);
+ AddPages(setting);
archive_manager_.reset(new TestArchiveManager(store_test_util()));
}
@@ -167,20 +169,26 @@ void ClearStorageTaskTest::OnClearStorageDone(size_t cleared_page_count,
total_cleared_times_++;
}
-void ClearStorageTaskTest::AddPages(const PageSettings& setting,
- base::SimpleTestClock* clock_ptr) {
+void ClearStorageTaskTest::AddPages(const PageSettings& setting) {
+ // Note: even though the creation time set below is inconsistent with the last
+ // access time set further down, these values are used independently and
+ // this choice allows for easier testing of the TimeSinceCreation metric. This
+ // way we can work directly with the times used to advance the testing clock
+ // during each test.
+ generator()->SetCreationTime(clock()->Now());
generator()->SetNamespace(setting.name_space);
generator()->SetArchiveDirectory(temp_dir_path());
+
for (int i = 0; i < setting.fresh_page_count; ++i) {
- generator()->SetLastAccessTime(clock_ptr->Now());
+ generator()->SetLastAccessTime(clock_.Now());
OfflinePageItem page = generator()->CreateItemWithTempFile();
store_test_util()->InsertItem(page);
}
for (int i = 0; i < setting.expired_page_count; ++i) {
// Make the pages expired.
generator()->SetLastAccessTime(
- clock_ptr->Now() - policy_controller_->GetPolicy(setting.name_space)
- .lifetime_policy.expiration_period);
+ clock_.Now() - policy_controller_->GetPolicy(setting.name_space)
+ .lifetime_policy.expiration_period);
OfflinePageItem page = generator()->CreateItemWithTempFile();
store_test_util()->InsertItem(page);
}
@@ -195,15 +203,10 @@ void ClearStorageTaskTest::RunClearStorageTask(const base::Time& start_time) {
}
TEST_F(ClearStorageTaskTest, ClearPagesLessThanLimit) {
- auto clock = std::make_unique<base::SimpleTestClock>();
- clock->SetNow(base::Time::Now());
- Initialize({{kBookmarkNamespace, 1, 1}, {kLastNNamespace, 1, 1}},
- clock.get());
-
- clock->Advance(base::TimeDelta::FromMinutes(5));
- base::Time start_time = clock->Now();
+ Initialize({{kBookmarkNamespace, 1, 1}, {kLastNNamespace, 1, 1}});
- RunClearStorageTask(start_time);
+ clock()->Advance(base::TimeDelta::FromMinutes(5));
+ RunClearStorageTask(clock()->Now());
// In total there're 2 expired pages so they'll be cleared successfully.
// There will be 2 pages remaining in the store, and make sure their files
@@ -213,18 +216,15 @@ TEST_F(ClearStorageTaskTest, ClearPagesLessThanLimit) {
EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
EXPECT_EQ(2LL, store_test_util()->GetPageCount());
EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(temp_dir_path()));
+ histogram_tester()->ExpectUniqueSample(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation", 5, 2);
}
TEST_F(ClearStorageTaskTest, ClearPagesMoreFreshPages) {
- auto clock = std::make_unique<base::SimpleTestClock>();
- clock->SetNow(base::Time::Now());
- Initialize({{kBookmarkNamespace, 30, 0}, {kLastNNamespace, 100, 1}},
- clock.get());
-
- clock->Advance(base::TimeDelta::FromMinutes(5));
- base::Time start_time = clock->Now();
+ Initialize({{kBookmarkNamespace, 30, 0}, {kLastNNamespace, 100, 1}});
- RunClearStorageTask(start_time);
+ clock()->Advance(base::TimeDelta::FromMinutes(5));
+ RunClearStorageTask(clock()->Now());
// In total there's 1 expired page so it'll be cleared successfully.
// There will be (30 + 100) pages remaining in the store, and make sure their
@@ -234,17 +234,15 @@ TEST_F(ClearStorageTaskTest, ClearPagesMoreFreshPages) {
EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
EXPECT_EQ(130LL, store_test_util()->GetPageCount());
EXPECT_EQ(130UL, test_utils::GetFileCountInDirectory(temp_dir_path()));
+ histogram_tester()->ExpectUniqueSample(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation", 5, 1);
}
TEST_F(ClearStorageTaskTest, TryClearPersistentPages) {
- auto clock = std::make_unique<base::SimpleTestClock>();
- clock->SetNow(base::Time::Now());
- Initialize({{kDownloadNamespace, 20, 0}}, clock.get());
+ Initialize({{kDownloadNamespace, 20, 0}});
- clock->Advance(base::TimeDelta::FromDays(367));
- base::Time start_time = clock->Now();
-
- RunClearStorageTask(start_time);
+ clock()->Advance(base::TimeDelta::FromDays(367));
+ RunClearStorageTask(clock()->Now());
// There's 20 pages and the clock advances for more than a year.
// No pages should be deleted since they're all persistent pages.
@@ -253,19 +251,17 @@ TEST_F(ClearStorageTaskTest, TryClearPersistentPages) {
EXPECT_EQ(ClearStorageResult::UNNECESSARY, last_clear_storage_result());
EXPECT_EQ(20LL, store_test_util()->GetPageCount());
EXPECT_EQ(20UL, test_utils::GetFileCountInDirectory(temp_dir_path()));
+ histogram_tester()->ExpectTotalCount(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation", 0);
}
TEST_F(ClearStorageTaskTest, TryClearPersistentPagesWithStoragePressure) {
- auto clock = std::make_unique<base::SimpleTestClock>();
- clock->SetNow(base::Time::Now());
// Sets the free space with 1KB.
- Initialize({{kDownloadNamespace, 20, 0}}, clock.get());
+ Initialize({{kDownloadNamespace, 20, 0}});
SetFreeSpace(1024);
- clock->Advance(base::TimeDelta::FromDays(367));
- base::Time start_time = clock->Now();
-
- RunClearStorageTask(start_time);
+ clock()->Advance(base::TimeDelta::FromDays(367));
+ RunClearStorageTask(clock()->Now());
// There're 20 pages and the clock advances for more than a year.
// No pages should be deleted since they're all persistent pages.
@@ -277,15 +273,12 @@ TEST_F(ClearStorageTaskTest, TryClearPersistentPagesWithStoragePressure) {
}
TEST_F(ClearStorageTaskTest, ClearMultipleTimes) {
- auto clock = std::make_unique<base::SimpleTestClock>();
- clock->SetNow(base::Time::Now());
// Initializing with 20 unexpired and 0 expired pages in bookmark namespace,
// 30 unexpired and 1 expired pages in last_n namespace, and 40 persistent
// pages in download namespace. Free space on the disk is 200MB.
Initialize({{kBookmarkNamespace, 20, 0},
{kLastNNamespace, 30, 1},
- {kDownloadNamespace, 40, 0}},
- clock.get());
+ {kDownloadNamespace, 40, 0}});
// Check preconditions, especially that last_n expiration is longer than
// bookmark's.
@@ -304,8 +297,8 @@ TEST_F(ClearStorageTaskTest, ClearMultipleTimes) {
ASSERT_GT(last_n_policy.expiration_period, bookmark_policy.expiration_period);
// Advance 30 minutes from initial pages creation time.
- clock->Advance(base::TimeDelta::FromMinutes(30));
- RunClearStorageTask(clock->Now());
+ clock()->Advance(base::TimeDelta::FromMinutes(30));
+ RunClearStorageTask(clock()->Now());
// There's only 1 expired pages, so it will be cleared. There will be (30 +
// 20 + 40) pages remaining.
@@ -314,11 +307,13 @@ TEST_F(ClearStorageTaskTest, ClearMultipleTimes) {
EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
EXPECT_EQ(90LL, store_test_util()->GetPageCount());
EXPECT_EQ(90UL, test_utils::GetFileCountInDirectory(temp_dir_path()));
+ histogram_tester()->ExpectUniqueSample(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation", 30, 1);
// Advance the clock by the expiration period of bookmark namespace so that
// all pages left in that namespace should be expired.
- clock->Advance(bookmark_policy.expiration_period);
- RunClearStorageTask(clock->Now());
+ clock()->Advance(bookmark_policy.expiration_period);
+ RunClearStorageTask(clock()->Now());
// All pages in bookmark namespace should be cleared. And only 70 pages
// remaining after the clearing.
@@ -327,11 +322,16 @@ TEST_F(ClearStorageTaskTest, ClearMultipleTimes) {
EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
EXPECT_EQ(70LL, store_test_util()->GetPageCount());
EXPECT_EQ(70UL, test_utils::GetFileCountInDirectory(temp_dir_path()));
+ histogram_tester()->ExpectTotalCount(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation", 21);
+ histogram_tester()->ExpectBucketCount(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation",
+ 30 + bookmark_policy.expiration_period.InMinutes(), 20);
// Advance the clock by 1 ms, there's no change in pages so the attempt to
// clear storage should be unnecessary.
- clock->Advance(base::TimeDelta::FromMilliseconds(1));
- RunClearStorageTask(clock->Now());
+ clock()->Advance(base::TimeDelta::FromMilliseconds(1));
+ RunClearStorageTask(clock()->Now());
// The clearing attempt is unnecessary.
EXPECT_EQ(0UL, last_cleared_page_count());
@@ -339,6 +339,8 @@ TEST_F(ClearStorageTaskTest, ClearMultipleTimes) {
EXPECT_EQ(ClearStorageResult::UNNECESSARY, last_clear_storage_result());
EXPECT_EQ(70LL, store_test_util()->GetPageCount());
EXPECT_EQ(70UL, test_utils::GetFileCountInDirectory(temp_dir_path()));
+ histogram_tester()->ExpectTotalCount(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation", 21);
// Adding more fresh pages in last_n namespace to make storage usage exceed
// limit, so even if only 5 minutes passed from last clearing, this will still
@@ -348,10 +350,10 @@ TEST_F(ClearStorageTaskTest, ClearMultipleTimes) {
// * 0.3 = 100.5MB. In order to bring the storage usage down to (135MB +
// 200MB) * 0.1 = 33.5MB, (115MB - 33.5MB) needs to be released, which is 163
// temporary pages to be cleared.
- AddPages({kLastNNamespace, 200, 0}, clock.get());
+ AddPages({kLastNNamespace, 200, 0});
SetFreeSpace(200 * (1 << 20));
- clock->Advance(base::TimeDelta::FromMinutes(5));
- RunClearStorageTask(clock->Now());
+ clock()->Advance(base::TimeDelta::FromMinutes(5));
+ RunClearStorageTask(clock()->Now());
// There should be 107 pages remaining after the clearing.
EXPECT_EQ(163UL, last_cleared_page_count());
@@ -359,11 +361,21 @@ TEST_F(ClearStorageTaskTest, ClearMultipleTimes) {
EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
EXPECT_EQ(107LL, store_test_util()->GetPageCount());
EXPECT_EQ(107UL, test_utils::GetFileCountInDirectory(temp_dir_path()));
+ histogram_tester()->ExpectTotalCount(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation", 184);
+ // The 30 original ones last_n pages are cleared (and they fall into the same
+ // bucket as the 20 from bookmarks)...
+ histogram_tester()->ExpectBucketCount(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation",
+ 30 + bookmark_policy.expiration_period.InMinutes() + 5, 20 + 30);
+ // ... As well as 133 from this latest round.
+ histogram_tester()->ExpectBucketCount(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation", 5, 133);
// Advance the clock by 300 days, in order to expire all temporary pages. Only
// 67 temporary pages are left from the last clearing.
- clock->Advance(base::TimeDelta::FromDays(300));
- RunClearStorageTask(clock->Now());
+ clock()->Advance(base::TimeDelta::FromDays(300));
+ RunClearStorageTask(clock()->Now());
// All temporary pages should be cleared by now.
EXPECT_EQ(67UL, last_cleared_page_count());
@@ -371,6 +383,11 @@ TEST_F(ClearStorageTaskTest, ClearMultipleTimes) {
EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
EXPECT_EQ(40LL, store_test_util()->GetPageCount());
EXPECT_EQ(40UL, test_utils::GetFileCountInDirectory(temp_dir_path()));
+ histogram_tester()->ExpectTotalCount(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation", 251);
+ histogram_tester()->ExpectBucketCount(
+ "OfflinePages.ClearTemporaryPages.TimeSinceCreation",
+ base::TimeDelta::FromDays(300).InMinutes() + 5, 67);
}
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/model/delete_page_task.cc b/chromium/components/offline_pages/core/model/delete_page_task.cc
index 36a487c0955..43bbfe8a543 100644
--- a/chromium/components/offline_pages/core/model/delete_page_task.cc
+++ b/chromium/components/offline_pages/core/model/delete_page_task.cc
@@ -40,15 +40,16 @@ namespace {
// in the SQL query and the result of it can be simply fetched by calling
// statement.Column*(INFO_WRAPPER_COUNT), as it's the last column. For example,
// please take a look at GetCachedDeletedPageInfoWrappersByUrlPredicateSync.
-#define INFO_WRAPPER_FIELDS \
- "offline_id, client_namespace, client_id, file_path, request_origin, " \
- "access_count, creation_time"
-#define INFO_WRAPPER_FIELD_COUNT 7
+#define INFO_WRAPPER_FIELDS \
+ "offline_id, system_download_id, client_namespace, client_id, file_path, " \
+ "request_origin, access_count, creation_time"
+#define INFO_WRAPPER_FIELD_COUNT 8
struct DeletedPageInfoWrapper {
DeletedPageInfoWrapper();
DeletedPageInfoWrapper(const DeletedPageInfoWrapper& other);
int64_t offline_id;
+ int64_t system_download_id;
ClientId client_id;
base::FilePath file_path;
std::string request_origin;
@@ -60,14 +61,15 @@ struct DeletedPageInfoWrapper {
DeletedPageInfoWrapper CreateInfoWrapper(const sql::Statement& statement) {
DeletedPageInfoWrapper info_wrapper;
info_wrapper.offline_id = statement.ColumnInt64(0);
- info_wrapper.client_id.name_space = statement.ColumnString(1);
- info_wrapper.client_id.id = statement.ColumnString(2);
+ info_wrapper.system_download_id = statement.ColumnInt64(1);
+ info_wrapper.client_id.name_space = statement.ColumnString(2);
+ info_wrapper.client_id.id = statement.ColumnString(3);
info_wrapper.file_path =
- store_utils::FromDatabaseFilePath(statement.ColumnString(3));
- info_wrapper.request_origin = statement.ColumnString(4);
- info_wrapper.access_count = statement.ColumnInt(5);
+ store_utils::FromDatabaseFilePath(statement.ColumnString(4));
+ info_wrapper.request_origin = statement.ColumnString(5);
+ info_wrapper.access_count = statement.ColumnInt(6);
info_wrapper.creation_time =
- store_utils::FromDatabaseTime(statement.ColumnInt64(6));
+ store_utils::FromDatabaseTime(statement.ColumnInt64(7));
return info_wrapper;
}
@@ -130,9 +132,9 @@ DeletePageTaskResult DeletePagesByDeletedPageInfoWrappersSync(
if (DeleteArchiveSync(info_wrapper.file_path)) {
any_archive_deleted = true;
if (DeletePageEntryByOfflineIdSync(db, info_wrapper.offline_id)) {
- deleted_page_infos.emplace_back(info_wrapper.offline_id,
- info_wrapper.client_id,
- info_wrapper.request_origin);
+ deleted_page_infos.emplace_back(
+ info_wrapper.offline_id, info_wrapper.system_download_id,
+ info_wrapper.client_id, info_wrapper.request_origin);
}
}
}
@@ -240,6 +242,59 @@ DeletePageTaskResult DeletePagesByClientIdsSync(
return result;
}
+// Gets page infos for |client_id|, returning a vector of
+// DeletedPageInfoWrappers because ClientId can refer to multiple pages.
+std::vector<DeletedPageInfoWrapper>
+GetDeletedPageInfoWrappersByClientIdAndOriginSync(sql::Connection* db,
+ ClientId client_id,
+ const std::string& origin) {
+ std::vector<DeletedPageInfoWrapper> info_wrappers;
+ static const char kSql[] =
+ "SELECT " INFO_WRAPPER_FIELDS " FROM " OFFLINE_PAGES_TABLE_NAME
+ " WHERE client_namespace = ? AND client_id = ? AND request_origin = ?";
+ sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindString(0, client_id.name_space);
+ statement.BindString(1, client_id.id);
+ statement.BindString(2, origin);
+
+ while (statement.Step())
+ info_wrappers.emplace_back(CreateInfoWrapper(statement));
+
+ return info_wrappers;
+}
+
+DeletePageTaskResult DeletePagesByClientIdsAndOriginSync(
+ const std::vector<ClientId> client_ids,
+ const std::string& origin,
+ sql::Connection* db) {
+ std::vector<DeletedPageInfoWrapper> infos;
+
+ if (!db)
+ return DeletePageTaskResult(DeletePageResult::STORE_FAILURE, {});
+ if (client_ids.empty())
+ return DeletePageTaskResult(DeletePageResult::SUCCESS, {});
+
+ // If you create a transaction but dont Commit() it is automatically
+ // rolled back by its destructor when it falls out of scope.
+ sql::Transaction transaction(db);
+ if (!transaction.Begin())
+ return DeletePageTaskResult(DeletePageResult::STORE_FAILURE, {});
+
+ for (ClientId client_id : client_ids) {
+ std::vector<DeletedPageInfoWrapper> temp_infos =
+ GetDeletedPageInfoWrappersByClientIdAndOriginSync(db, client_id,
+ origin);
+ infos.insert(infos.end(), temp_infos.begin(), temp_infos.end());
+ }
+
+ DeletePageTaskResult result =
+ DeletePagesByDeletedPageInfoWrappersSync(db, infos);
+
+ if (!transaction.Commit())
+ return DeletePageTaskResult(DeletePageResult::STORE_FAILURE, {});
+ return result;
+}
+
// Gets the page information of pages that are within the provided temporary
// namespaces and satisfy the provided URL predicate.
std::vector<DeletedPageInfoWrapper>
@@ -387,6 +442,19 @@ std::unique_ptr<DeletePageTask> DeletePageTask::CreateTaskMatchingClientIds(
// static
std::unique_ptr<DeletePageTask>
+DeletePageTask::CreateTaskMatchingClientIdsAndOrigin(
+ OfflinePageMetadataStoreSQL* store,
+ DeletePageTask::DeletePageTaskCallback callback,
+ const std::vector<ClientId>& client_ids,
+ const std::string& origin) {
+ return std::unique_ptr<DeletePageTask>(new DeletePageTask(
+ store,
+ base::BindOnce(&DeletePagesByClientIdsAndOriginSync, client_ids, origin),
+ std::move(callback)));
+}
+
+// static
+std::unique_ptr<DeletePageTask>
DeletePageTask::CreateTaskMatchingUrlPredicateForCachedPages(
OfflinePageMetadataStoreSQL* store,
DeletePageTask::DeletePageTaskCallback callback,
diff --git a/chromium/components/offline_pages/core/model/delete_page_task.h b/chromium/components/offline_pages/core/model/delete_page_task.h
index 94bb86c028a..adb3af784ff 100644
--- a/chromium/components/offline_pages/core/model/delete_page_task.h
+++ b/chromium/components/offline_pages/core/model/delete_page_task.h
@@ -61,6 +61,14 @@ class DeletePageTask : public Task {
DeletePageTask::DeletePageTaskCallback callback,
const std::vector<ClientId>& client_ids);
+ // Creates a task to delete pages with the client ids in |client_ids|
+ // provided they also have origin |origin|.
+ static std::unique_ptr<DeletePageTask> CreateTaskMatchingClientIdsAndOrigin(
+ OfflinePageMetadataStoreSQL* store,
+ DeletePageTask::DeletePageTaskCallback callback,
+ const std::vector<ClientId>& client_ids,
+ const std::string& origin);
+
// Creates a task to delete pages which satisfy |predicate|.
static std::unique_ptr<DeletePageTask>
CreateTaskMatchingUrlPredicateForCachedPages(
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 b357d6fc449..4e9102cc995 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
@@ -270,7 +270,6 @@ TEST_F(DeletePageTaskTest, DeletePageByClientId) {
}
TEST_F(DeletePageTaskTest, DeletePageByClientIdNotFound) {
- // Add 3 pages and try to delete 2 of them using client id.
generator()->SetNamespace(kTestNamespace);
OfflinePageItem page1 = generator()->CreateItemWithTempFile();
OfflinePageItem page2 = generator()->CreateItemWithTempFile();
@@ -302,6 +301,77 @@ TEST_F(DeletePageTaskTest, DeletePageByClientIdNotFound) {
0);
}
+TEST_F(DeletePageTaskTest, DeletePageByClientIdAndOrigin) {
+ // Add 3 pages and try to delete 2 of them using client id and origin
+ // Page1: {test namespace, random id, abc.xyz}
+ // Page2: {test namespace, foo, abc.xyz}
+ // Page3: {test namespace, foo, <none>}
+ generator()->SetNamespace(kTestNamespace);
+ generator()->SetRequestOrigin("abc.xyz");
+ OfflinePageItem page1 = generator()->CreateItemWithTempFile();
+ generator()->SetId("foo");
+ OfflinePageItem page2 = generator()->CreateItemWithTempFile();
+ generator()->SetRequestOrigin("");
+ OfflinePageItem page3 = generator()->CreateItemWithTempFile();
+ store_test_util()->InsertItem(page1);
+ store_test_util()->InsertItem(page2);
+ store_test_util()->InsertItem(page3);
+
+ std::vector<ClientId> client_ids({page1.client_id, page2.client_id});
+ auto task = DeletePageTask::CreateTaskMatchingClientIdsAndOrigin(
+ store(), delete_page_callback(), client_ids, "abc.xyz");
+ runner()->RunTask(std::move(task));
+
+ EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_page_result());
+ EXPECT_EQ(2UL, last_deleted_page_infos().size());
+ EXPECT_EQ(1LL, store_test_util()->GetPageCount());
+ EXPECT_TRUE(CheckPageDeleted(page1));
+ EXPECT_TRUE(CheckPageDeleted(page2));
+ EXPECT_FALSE(CheckPageDeleted(page3));
+ histogram_tester()->ExpectTotalCount(
+ model_utils::AddHistogramSuffix(page1.client_id.name_space,
+ "OfflinePages.PageLifetime"),
+ 2);
+ histogram_tester()->ExpectTotalCount(
+ model_utils::AddHistogramSuffix(page1.client_id.name_space,
+ "OfflinePages.AccessCount"),
+ 2);
+}
+
+TEST_F(DeletePageTaskTest, DeletePageByClientIdAndOriginNotFound) {
+ generator()->SetNamespace(kTestNamespace);
+ OfflinePageItem page1 = generator()->CreateItemWithTempFile();
+ OfflinePageItem page2 = generator()->CreateItemWithTempFile();
+ OfflinePageItem page3 = generator()->CreateItemWithTempFile();
+ store_test_util()->InsertItem(page1);
+ store_test_util()->InsertItem(page2);
+ store_test_util()->InsertItem(page3);
+
+ EXPECT_EQ(3LL, store_test_util()->GetPageCount());
+
+ // The pages with the client ids will be removed from the store given that
+ // their origin matches. But since the origin isn't in the store, there will
+ // be no pages deleted and the result will be success since there's no
+ // NOT_FOUND anymore.
+ std::vector<ClientId> client_ids(
+ {page1.client_id, page2.client_id, page3.client_id});
+ auto task = DeletePageTask::CreateTaskMatchingClientIdsAndOrigin(
+ store(), delete_page_callback(), client_ids, "abc.xyz");
+ runner()->RunTask(std::move(task));
+
+ EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_page_result());
+ EXPECT_EQ(0UL, last_deleted_page_infos().size());
+ EXPECT_EQ(3LL, store_test_util()->GetPageCount());
+ histogram_tester()->ExpectTotalCount(
+ model_utils::AddHistogramSuffix(page1.client_id.name_space,
+ "OfflinePages.PageLifetime"),
+ 0);
+ histogram_tester()->ExpectTotalCount(
+ model_utils::AddHistogramSuffix(page1.client_id.name_space,
+ "OfflinePages.AccessCount"),
+ 0);
+}
+
TEST_F(DeletePageTaskTest, DeletePageByUrlPredicate) {
// Add 3 pages and try to delete 2 of them using url predicate.
generator()->SetNamespace(kTestNamespace);
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 4c34d28021c..ef58bf5d581 100644
--- a/chromium/components/offline_pages/core/model/get_pages_task.cc
+++ b/chromium/components/offline_pages/core/model/get_pages_task.cc
@@ -235,6 +235,28 @@ ReadResult ReadPagesByOfflineId(int64_t offline_id, sql::Connection* db) {
return result;
}
+ReadResult ReadPagesBySizeAndDigest(int64_t file_size,
+ const std::string& digest,
+ sql::Connection* db) {
+ ReadResult result;
+ if (!db) {
+ result.success = false;
+ return result;
+ }
+
+ static const char kSql[] = "SELECT " OFFLINE_PAGE_PROJECTION
+ " FROM offlinepages_v1"
+ " WHERE file_size = ? AND digest = ?";
+ sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, file_size);
+ statement.BindString(1, digest);
+ while (statement.Step())
+ result.pages.emplace_back(MakeOfflinePageItem(&statement));
+
+ result.success = true;
+ return result;
+}
+
void WrapInMultipleItemsCallback(const SingleOfflinePageItemCallback& callback,
const std::vector<OfflinePageItem>& pages) {
if (pages.size() == 0)
@@ -358,6 +380,17 @@ std::unique_ptr<GetPagesTask> GetPagesTask::CreateTaskMatchingOfflineId(
}
// static
+std::unique_ptr<GetPagesTask> GetPagesTask::CreateTaskMatchingSizeAndDigest(
+ OfflinePageMetadataStoreSQL* store,
+ const SingleOfflinePageItemCallback& callback,
+ int64_t file_size,
+ const std::string& digest) {
+ return std::unique_ptr<GetPagesTask>(new GetPagesTask(
+ store, base::BindOnce(&ReadPagesBySizeAndDigest, file_size, digest),
+ base::Bind(&WrapInMultipleItemsCallback, callback)));
+}
+
+// static
std::unique_ptr<GetPagesTask>
GetPagesTask::CreateTaskSelectingItemsMarkedForUpgrade(
OfflinePageMetadataStoreSQL* store,
diff --git a/chromium/components/offline_pages/core/model/get_pages_task.h b/chromium/components/offline_pages/core/model/get_pages_task.h
index 2c1b443d96f..e405ae517bc 100644
--- a/chromium/components/offline_pages/core/model/get_pages_task.h
+++ b/chromium/components/offline_pages/core/model/get_pages_task.h
@@ -92,6 +92,14 @@ class GetPagesTask : public Task {
const SingleOfflinePageItemCallback& callback,
int64_t offline_id);
+ // Creates |GetPagesTask| reading a single page matching provided |file_size|
+ // and |digest| from DB.
+ static std::unique_ptr<GetPagesTask> CreateTaskMatchingSizeAndDigest(
+ OfflinePageMetadataStoreSQL* store,
+ const SingleOfflinePageItemCallback& callback,
+ int64_t file_size,
+ const std::string& digest);
+
// Creates |GetPagesTask| selecting persistent items having a non-zero
// remaining upgrade attempts.
// Order of items is determined by number of remaining attempts (descending)
diff --git a/chromium/components/offline_pages/core/model/get_pages_task_unittest.cc b/chromium/components/offline_pages/core/model/get_pages_task_unittest.cc
index 9908be71ed3..4fc775e2856 100644
--- a/chromium/components/offline_pages/core/model/get_pages_task_unittest.cc
+++ b/chromium/components/offline_pages/core/model/get_pages_task_unittest.cc
@@ -263,6 +263,35 @@ TEST_F(GetPagesTaskTest, GetPageByOfflineId) {
EXPECT_EQ(item_1, single_page_result());
}
+TEST_F(GetPagesTaskTest, GetPageBySizeAndDigest) {
+ static const int64_t kFileSize1 = 123LL;
+ static const int64_t kFileSize2 = 999999LL;
+ static const char kDigest1[] = "digest 1";
+ static const char kDigest2[] = "digest 2";
+ generator()->SetFileSize(kFileSize1);
+ generator()->SetDigest(kDigest1);
+ OfflinePageItem item_1 = generator()->CreateItem();
+ store_util()->InsertItem(item_1);
+ generator()->SetDigest(kDigest2);
+ OfflinePageItem item_2 = generator()->CreateItem();
+ store_util()->InsertItem(item_2);
+ generator()->SetFileSize(kFileSize2);
+ OfflinePageItem item_3 = generator()->CreateItem();
+ store_util()->InsertItem(item_3);
+
+ runner()->RunTask(GetPagesTask::CreateTaskMatchingSizeAndDigest(
+ store(), get_single_page_callback(), kFileSize1, "mismatched digest"));
+ EXPECT_EQ(OfflinePageItem(), single_page_result());
+
+ runner()->RunTask(GetPagesTask::CreateTaskMatchingSizeAndDigest(
+ store(), get_single_page_callback(), 0LL, kDigest1));
+ EXPECT_EQ(OfflinePageItem(), single_page_result());
+
+ runner()->RunTask(GetPagesTask::CreateTaskMatchingSizeAndDigest(
+ store(), get_single_page_callback(), kFileSize2, kDigest2));
+ EXPECT_EQ(item_3, single_page_result());
+}
+
TEST_F(GetPagesTaskTest, GetPagesSupportedByDownloads) {
ClientPolicyController policy_controller;
generator()->SetNamespace(kCCTNamespace);
diff --git a/chromium/components/offline_pages/core/model/offline_page_item_generator.cc b/chromium/components/offline_pages/core/model/offline_page_item_generator.cc
index 94a04dccb3f..b6a936a4fd1 100644
--- a/chromium/components/offline_pages/core/model/offline_page_item_generator.cc
+++ b/chromium/components/offline_pages/core/model/offline_page_item_generator.cc
@@ -28,8 +28,10 @@ OfflinePageItem OfflinePageItemGenerator::CreateItem() {
item.url = url_;
item.original_url = original_url_;
item.file_size = file_size_;
+ item.creation_time = creation_time_;
item.last_access_time = last_access_time_;
item.access_count = access_count_;
+ item.digest = digest_;
return item;
}
@@ -72,6 +74,10 @@ void OfflinePageItemGenerator::SetFileSize(int64_t file_size) {
file_size_ = file_size;
}
+void OfflinePageItemGenerator::SetCreationTime(base::Time creation_time) {
+ creation_time_ = creation_time;
+}
+
void OfflinePageItemGenerator::SetLastAccessTime(base::Time last_access_time) {
last_access_time_ = last_access_time;
}
@@ -85,4 +91,8 @@ void OfflinePageItemGenerator::SetArchiveDirectory(
archive_dir_ = archive_dir;
}
+void OfflinePageItemGenerator::SetDigest(const std::string& digest) {
+ digest_ = digest;
+}
+
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/model/offline_page_item_generator.h b/chromium/components/offline_pages/core/model/offline_page_item_generator.h
index 70274c797e1..c9095b3019d 100644
--- a/chromium/components/offline_pages/core/model/offline_page_item_generator.h
+++ b/chromium/components/offline_pages/core/model/offline_page_item_generator.h
@@ -31,9 +31,11 @@ class OfflinePageItemGenerator {
void SetUrl(const GURL& url);
void SetOriginalUrl(const GURL& url);
void SetFileSize(int64_t file_size);
+ void SetCreationTime(base::Time time);
void SetLastAccessTime(base::Time time);
void SetAccessCount(int access_count);
void SetArchiveDirectory(const base::FilePath& archive_dir);
+ void SetDigest(const std::string& digest);
private:
std::string namespace_ = kDefaultNamespace;
@@ -42,9 +44,11 @@ class OfflinePageItemGenerator {
GURL url_;
GURL original_url_;
int64_t file_size_ = 0;
+ base::Time creation_time_;
base::Time last_access_time_;
int access_count_ = 0;
base::FilePath archive_dir_;
+ std::string digest_;
};
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/model/offline_page_model_taskified.cc b/chromium/components/offline_pages/core/model/offline_page_model_taskified.cc
index f7510a214be..49a98d06ea4 100644
--- a/chromium/components/offline_pages/core/model/offline_page_model_taskified.cc
+++ b/chromium/components/offline_pages/core/model/offline_page_model_taskified.cc
@@ -8,11 +8,15 @@
#include <vector>
#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_path.h"
#include "base/location.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string16.h"
+#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "components/offline_pages/core/archive_manager.h"
@@ -30,6 +34,7 @@
#include "components/offline_pages/core/offline_page_metadata_store_sql.h"
#include "components/offline_pages/core/offline_page_model.h"
#include "components/offline_pages/core/offline_store_utils.h"
+#include "components/offline_pages/core/system_download_manager.h"
#include "url/gurl.h"
namespace offline_pages {
@@ -105,6 +110,13 @@ void ReportPageHistogramAfterSuccessfulSaving(
offline_page.file_size / 1024, 1, 10000, 50);
}
+void ReportSavedPagesCount(const MultipleOfflinePageItemCallback& callback,
+ const MultipleOfflinePageItemResult& all_items) {
+ UMA_HISTOGRAM_COUNTS_10000("OfflinePages.SavedPageCountUponQuery",
+ all_items.size());
+ callback.Run(all_items);
+}
+
} // namespace
// static
@@ -112,7 +124,7 @@ constexpr base::TimeDelta
OfflinePageModelTaskified::kInitialUpgradeSelectionDelay;
// static
-constexpr base::TimeDelta OfflinePageModelTaskified::kInitializingTaskDelay;
+constexpr base::TimeDelta OfflinePageModelTaskified::kMaintenanceTasksDelay;
// static
constexpr base::TimeDelta OfflinePageModelTaskified::kClearStorageInterval;
@@ -120,19 +132,20 @@ constexpr base::TimeDelta OfflinePageModelTaskified::kClearStorageInterval;
OfflinePageModelTaskified::OfflinePageModelTaskified(
std::unique_ptr<OfflinePageMetadataStoreSQL> store,
std::unique_ptr<ArchiveManager> archive_manager,
+ std::unique_ptr<SystemDownloadManager> download_manager,
const scoped_refptr<base::SequencedTaskRunner>& task_runner,
std::unique_ptr<base::Clock> clock)
: store_(std::move(store)),
archive_manager_(std::move(archive_manager)),
+ download_manager_(std::move(download_manager)),
policy_controller_(new ClientPolicyController()),
clock_(std::move(clock)),
task_queue_(this),
skip_clearing_original_url_for_testing_(false),
+ task_runner_(task_runner),
weak_ptr_factory_(this) {
+ DCHECK_LT(kMaintenanceTasksDelay, OfflinePageMetadataStoreSQL::kClosingDelay);
CreateArchivesDirectoryIfNeeded();
- PostClearLegacyTemporaryPagesTask();
- PostClearCachedPagesTask(true /* is_initializing */);
- PostCheckMetadataConsistencyTask(true /* is_initializing */);
// TODO(fgorski): Call from here, when upgrade task is available:
// PostSelectItemsMarkedForUpgrade();
}
@@ -225,6 +238,18 @@ void OfflinePageModelTaskified::DeletePagesByClientIds(
task_queue_.AddTask(std::move(task));
}
+void OfflinePageModelTaskified::DeletePagesByClientIdsAndOrigin(
+ const std::vector<ClientId>& client_ids,
+ const std::string& origin,
+ const DeletePageCallback& callback) {
+ auto task = DeletePageTask::CreateTaskMatchingClientIdsAndOrigin(
+ store_.get(),
+ base::BindOnce(&OfflinePageModelTaskified::OnDeleteDone,
+ weak_ptr_factory_.GetWeakPtr(), callback),
+ client_ids, origin);
+ task_queue_.AddTask(std::move(task));
+}
+
void OfflinePageModelTaskified::DeleteCachedPagesByURLPredicate(
const UrlPredicate& predicate,
const DeletePageCallback& callback) {
@@ -238,8 +263,10 @@ void OfflinePageModelTaskified::DeleteCachedPagesByURLPredicate(
void OfflinePageModelTaskified::GetAllPages(
const MultipleOfflinePageItemCallback& callback) {
- auto task = GetPagesTask::CreateTaskMatchingAllPages(store_.get(), callback);
+ auto task = GetPagesTask::CreateTaskMatchingAllPages(
+ store_.get(), base::BindRepeating(&ReportSavedPagesCount, callback));
task_queue_.AddTask(std::move(task));
+ ScheduleMaintenanceTasks();
}
void OfflinePageModelTaskified::GetPageByOfflineId(
@@ -296,6 +323,17 @@ void OfflinePageModelTaskified::GetPagesByRequestOrigin(
task_queue_.AddTask(std::move(task));
}
+void OfflinePageModelTaskified::GetPageBySizeAndDigest(
+ int64_t file_size,
+ const std::string& digest,
+ const SingleOfflinePageItemCallback& callback) {
+ DCHECK_GT(file_size, 0);
+ DCHECK(!digest.empty());
+ auto task = GetPagesTask::CreateTaskMatchingSizeAndDigest(
+ store_.get(), callback, file_size, digest);
+ task_queue_.AddTask(std::move(task));
+}
+
void OfflinePageModelTaskified::GetOfflineIdsForClientId(
const ClientId& client_id,
const MultipleOfflineIdCallback& callback) {
@@ -364,23 +402,18 @@ void OfflinePageModelTaskified::OnCreateArchiveDone(
const base::string16& title,
int64_t file_size,
const std::string& file_hash) {
- // Remove the |archiver| from the pending list once it completes creation.
- pending_archivers_.erase(
- std::find_if(pending_archivers_.begin(), pending_archivers_.end(),
- [archiver](const std::unique_ptr<OfflinePageArchiver>& a) {
- return a.get() == archiver;
- }));
-
if (archiver_result != ArchiverResult::SUCCESSFULLY_CREATED) {
SavePageResult result = ArchiverResultToSavePageResult(archiver_result);
InformSavePageDone(callback, result, save_page_params.client_id,
offline_id);
+ ErasePendingArchiver(archiver);
return;
}
if (save_page_params.url != saved_url) {
DVLOG(1) << "Saved URL does not match requested URL.";
InformSavePageDone(callback, SavePageResult::ARCHIVE_CREATION_FAILED,
save_page_params.client_id, offline_id);
+ ErasePendingArchiver(archiver);
return;
}
@@ -398,9 +431,57 @@ void OfflinePageModelTaskified::OnCreateArchiveDone(
offline_page.original_url = save_page_params.original_url;
}
- AddPage(offline_page,
+ if (IsOfflinePagesSharingEnabled() &&
+ policy_controller_->IsUserRequestedDownload(
+ offline_page.client_id.name_space)) {
+ // If the user intentionally downloaded the page, move it to a public place.
+ PublishArchive(offline_page, callback, archiver);
+ } else {
+ // For pages that we download on the user's behalf, we keep them in an
+ // internal chrome directory, and add them here to the OfflinePageModel
+ // database.
+ AddPage(offline_page,
+ base::Bind(&OfflinePageModelTaskified::OnAddPageForSavePageDone,
+ weak_ptr_factory_.GetWeakPtr(), callback, offline_page));
+ }
+ ErasePendingArchiver(archiver);
+}
+
+void OfflinePageModelTaskified::ErasePendingArchiver(
+ OfflinePageArchiver* archiver) {
+ pending_archivers_.erase(
+ std::find_if(pending_archivers_.begin(), pending_archivers_.end(),
+ [archiver](const std::unique_ptr<OfflinePageArchiver>& a) {
+ return a.get() == archiver;
+ }));
+}
+
+void OfflinePageModelTaskified::PublishArchive(
+ const OfflinePageItem& offline_page,
+ const SavePageCallback& save_page_callback,
+ OfflinePageArchiver* archiver) {
+ archiver->PublishArchive(
+ offline_page, task_runner_, archive_manager_->GetPublicArchivesDir(),
+ download_manager_.get(),
+ base::BindOnce(&OfflinePageModelTaskified::PublishArchiveDone,
+ weak_ptr_factory_.GetWeakPtr(), save_page_callback));
+}
+
+void OfflinePageModelTaskified::PublishArchiveDone(
+ const SavePageCallback& save_page_callback,
+ const OfflinePageItem& offline_page,
+ PublishArchiveResult* move_results) {
+ if (move_results->move_result != SavePageResult::SUCCESS) {
+ save_page_callback.Run(move_results->move_result, 0LL);
+ return;
+ }
+ OfflinePageItem page = offline_page;
+ page.file_path = move_results->new_file_path;
+ page.system_download_id = move_results->download_id;
+
+ AddPage(page,
base::Bind(&OfflinePageModelTaskified::OnAddPageForSavePageDone,
- weak_ptr_factory_.GetWeakPtr(), callback, offline_page));
+ weak_ptr_factory_.GetWeakPtr(), save_page_callback, page));
}
void OfflinePageModelTaskified::OnAddPageForSavePageDone(
@@ -419,11 +500,9 @@ void OfflinePageModelTaskified::OnAddPageForSavePageDone(
if (policy_controller_->GetPolicy(page_attempted.client_id.name_space)
.pages_allowed_per_url != kUnlimitedPages) {
RemovePagesMatchingUrlAndNamespace(page_attempted);
- PostClearCachedPagesTask(false /* is_initializing */);
}
- } else {
- PostClearCachedPagesTask(false /* is_initializing */);
}
+ ScheduleMaintenanceTasks();
}
void OfflinePageModelTaskified::OnAddPageDone(const OfflinePageItem& page,
@@ -442,6 +521,7 @@ void OfflinePageModelTaskified::OnDeleteDone(
const std::vector<OfflinePageModel::DeletedPageInfo>& infos) {
UMA_HISTOGRAM_ENUMERATION("OfflinePages.DeletePageResult", result,
DeletePageResult::RESULT_COUNT);
+ std::vector<int64_t> system_download_ids;
// Notify observers and run callback.
for (const auto& info : infos) {
@@ -451,57 +531,70 @@ void OfflinePageModelTaskified::OnDeleteDone(
OfflinePagesNamespaceEnumeration::RESULT_COUNT);
for (Observer& observer : observers_)
observer.OfflinePageDeleted(info);
+ if (info.system_download_id != 0)
+ system_download_ids.push_back(info.system_download_id);
}
- if (!callback.is_null())
- callback.Run(result);
-}
-void OfflinePageModelTaskified::PostClearLegacyTemporaryPagesTask() {
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ // Remove the page from the system download manager. We don't need to wait for
+ // completion before calling the delete page callback.
+ task_runner_->PostTask(
FROM_HERE,
- base::Bind(&OfflinePageModelTaskified::ClearLegacyTemporaryPages,
- weak_ptr_factory_.GetWeakPtr()),
- kInitializingTaskDelay);
-}
+ base::BindOnce(&OfflinePageModelTaskified::RemoveFromDownloadManager,
+ download_manager_.get(), system_download_ids));
-void OfflinePageModelTaskified::ClearLegacyTemporaryPages() {
- // TODO(romax): When we have external directory, adding the support of getting
- // 'legacy' directory and replace the persistent one here.
- auto task = std::make_unique<ClearLegacyTemporaryPagesTask>(
- store_.get(), policy_controller_.get(),
- archive_manager_->GetPrivateArchivesDir());
- task_queue_.AddTask(std::move(task));
+ if (!callback.is_null())
+ callback.Run(result);
}
-void OfflinePageModelTaskified::PostClearCachedPagesTask(bool is_initializing) {
- if (is_initializing) {
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&OfflinePageModelTaskified::PostClearCachedPagesTask,
- weak_ptr_factory_.GetWeakPtr(), false),
- kInitializingTaskDelay);
- }
+void OfflinePageModelTaskified::RemoveFromDownloadManager(
+ SystemDownloadManager* download_manager,
+ const std::vector<int64_t>& system_download_ids) {
+ if (system_download_ids.size() > 0)
+ download_manager->Remove(system_download_ids);
+}
- // If not enough time has passed, do not post the task.
- if (GetCurrentTime() - last_clear_cached_pages_time_ <
- kClearStorageInterval) {
+void OfflinePageModelTaskified::ScheduleMaintenanceTasks() {
+ // If not enough time has passed, don't queue maintenance tasks.
+ base::Time now = GetCurrentTime();
+ if (now - last_maintenance_tasks_schedule_time_ < kClearStorageInterval)
return;
- }
- ClearCachedPages();
-}
+ bool first_run = last_maintenance_tasks_schedule_time_.is_null();
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&OfflinePageModelTaskified::RunMaintenanceTasks,
+ weak_ptr_factory_.GetWeakPtr(), now, first_run),
+ kMaintenanceTasksDelay);
+
+ last_maintenance_tasks_schedule_time_ = now;
+}
+
+void OfflinePageModelTaskified::RunMaintenanceTasks(const base::Time now,
+ bool first_run) {
+ // If this is the first run of this session, enqueue the run-once tasks.
+ if (first_run) {
+ // TODO(romax): When we have external directory, adding the support of
+ // getting 'legacy' directory and replace the persistent one here.
+ // TODO(carlosk): these tasks implementations look very similar so we should
+ // probably consolidate them all into a single one.
+ task_queue_.AddTask(std::make_unique<ClearLegacyTemporaryPagesTask>(
+ store_.get(), policy_controller_.get(),
+ archive_manager_->GetPrivateArchivesDir()));
+ task_queue_.AddTask(std::make_unique<TemporaryPagesConsistencyCheckTask>(
+ store_.get(), policy_controller_.get(),
+ archive_manager_->GetTemporaryArchivesDir()));
+ task_queue_.AddTask(std::make_unique<PersistentPagesConsistencyCheckTask>(
+ store_.get(), policy_controller_.get(),
+ archive_manager_->GetPrivateArchivesDir()));
+ }
-void OfflinePageModelTaskified::ClearCachedPages() {
- auto task = std::make_unique<ClearStorageTask>(
- store_.get(), archive_manager_.get(), policy_controller_.get(),
- GetCurrentTime(),
+ task_queue_.AddTask(std::make_unique<ClearStorageTask>(
+ store_.get(), archive_manager_.get(), policy_controller_.get(), now,
base::BindOnce(&OfflinePageModelTaskified::OnClearCachedPagesDone,
- weak_ptr_factory_.GetWeakPtr(), GetCurrentTime()));
- task_queue_.AddTask(std::move(task));
+ weak_ptr_factory_.GetWeakPtr())));
}
void OfflinePageModelTaskified::OnClearCachedPagesDone(
- base::Time start_time,
size_t deleted_page_count,
ClearStorageResult result) {
UMA_HISTOGRAM_ENUMERATION("OfflinePages.ClearTemporaryPages.Result", result,
@@ -510,36 +603,6 @@ void OfflinePageModelTaskified::OnClearCachedPagesDone(
UMA_HISTOGRAM_COUNTS("OfflinePages.ClearTemporaryPages.BatchSize",
deleted_page_count);
}
- last_clear_cached_pages_time_ = start_time;
-}
-
-void OfflinePageModelTaskified::PostCheckMetadataConsistencyTask(
- bool is_initializing) {
- if (is_initializing) {
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&OfflinePageModelTaskified::PostCheckMetadataConsistencyTask,
- weak_ptr_factory_.GetWeakPtr(), false),
- kInitializingTaskDelay);
- return;
- }
-
- CheckTemporaryPagesConsistency();
- CheckPersistentPagesConsistency();
-}
-
-void OfflinePageModelTaskified::CheckTemporaryPagesConsistency() {
- auto task = std::make_unique<TemporaryPagesConsistencyCheckTask>(
- store_.get(), policy_controller_.get(),
- archive_manager_->GetTemporaryArchivesDir());
- task_queue_.AddTask(std::move(task));
-}
-
-void OfflinePageModelTaskified::CheckPersistentPagesConsistency() {
- auto task = std::make_unique<PersistentPagesConsistencyCheckTask>(
- store_.get(), policy_controller_.get(),
- archive_manager_->GetPrivateArchivesDir());
- task_queue_.AddTask(std::move(task));
}
void OfflinePageModelTaskified::PostSelectItemsMarkedForUpgrade() {
@@ -577,8 +640,7 @@ void OfflinePageModelTaskified::RemovePagesMatchingUrlAndNamespace(
auto task = DeletePageTask::CreateTaskDeletingForPageLimit(
store_.get(),
base::BindOnce(&OfflinePageModelTaskified::OnDeleteDone,
- weak_ptr_factory_.GetWeakPtr(),
- base::Bind([](DeletePageResult result) {})),
+ weak_ptr_factory_.GetWeakPtr(), base::DoNothing()),
policy_controller_.get(), page);
task_queue_.AddTask(std::move(task));
}
@@ -587,7 +649,7 @@ void OfflinePageModelTaskified::CreateArchivesDirectoryIfNeeded() {
// No callback is required here.
// TODO(romax): Remove the callback from the interface once the other
// consumers of this API can also drop the callback.
- archive_manager_->EnsureArchivesDirCreated(base::Bind([]() {}));
+ archive_manager_->EnsureArchivesDirCreated(base::DoNothing());
}
base::Time OfflinePageModelTaskified::GetCurrentTime() {
diff --git a/chromium/components/offline_pages/core/model/offline_page_model_taskified.h b/chromium/components/offline_pages/core/model/offline_page_model_taskified.h
index 0045ee29473..169029aae5a 100644
--- a/chromium/components/offline_pages/core/model/offline_page_model_taskified.h
+++ b/chromium/components/offline_pages/core/model/offline_page_model_taskified.h
@@ -14,6 +14,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
+#include "base/time/clock.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/offline_pages/core/model/clear_storage_task.h"
#include "components/offline_pages/core/offline_page_archiver.h"
@@ -38,6 +39,7 @@ class ArchiveManager;
class ClientPolicyController;
class OfflinePageArchiver;
class OfflinePageMetadataStoreSQL;
+class SystemDownloadManager;
// Implementaion of OfflinePageModel, which is a service for saving pages
// offline. It's an entry point to get information about Offline Pages and the
@@ -49,24 +51,23 @@ class OfflinePageModelTaskified : public OfflinePageModel,
public TaskQueue::Delegate {
public:
// Initial delay after which a list of items for upgrade will be generated.
- // TODO(fgorski): We need to measure the cost of opening and closing the DB,
- // before we split |kInitializingTaskDelay| and
- // |kInitialUpgradeSelectionDelay| further apart, than 20 seconds.
static constexpr base::TimeDelta kInitialUpgradeSelectionDelay =
base::TimeDelta::FromSeconds(45);
- // Initial delay of other tasks triggered at the startup.
- static constexpr base::TimeDelta kInitializingTaskDelay =
- base::TimeDelta::FromSeconds(30);
+ // Delay between the scheduling and actual running of maintenance tasks. To
+ // not cause the re-opening of the metadata store this delay should be kept
+ // smaller than OfflinePageMetadataStoreSQL::kClosingDelay.
+ static constexpr base::TimeDelta kMaintenanceTasksDelay =
+ base::TimeDelta::FromSeconds(10);
- // The time that the storage cleanup will be triggered again since the last
- // one.
+ // Minimum delay between runs of maintenance tasks during a Chrome session.
static constexpr base::TimeDelta kClearStorageInterval =
base::TimeDelta::FromMinutes(30);
OfflinePageModelTaskified(
std::unique_ptr<OfflinePageMetadataStoreSQL> store,
std::unique_ptr<ArchiveManager> archive_manager,
+ std::unique_ptr<SystemDownloadManager> download_manager,
const scoped_refptr<base::SequencedTaskRunner>& task_runner,
std::unique_ptr<base::Clock> clock);
~OfflinePageModelTaskified() override;
@@ -89,6 +90,10 @@ class OfflinePageModelTaskified : public OfflinePageModel,
const DeletePageCallback& callback) override;
void DeletePagesByClientIds(const std::vector<ClientId>& client_ids,
const DeletePageCallback& callback) override;
+ void DeletePagesByClientIdsAndOrigin(
+ const std::vector<ClientId>& client_ids,
+ const std::string& origin,
+ const DeletePageCallback& callback) override;
void DeleteCachedPagesByURLPredicate(
const UrlPredicate& predicate,
const DeletePageCallback& callback) override;
@@ -115,6 +120,10 @@ class OfflinePageModelTaskified : public OfflinePageModel,
void GetPagesByRequestOrigin(
const std::string& request_origin,
const MultipleOfflinePageItemCallback& callback) override;
+ void GetPageBySizeAndDigest(
+ int64_t file_size,
+ const std::string& digest,
+ const SingleOfflinePageItemCallback& callback) override;
void GetOfflineIdsForClientId(
const ClientId& client_id,
@@ -173,28 +182,37 @@ class OfflinePageModelTaskified : public OfflinePageModel,
DeletePageResult result,
const std::vector<OfflinePageModel::DeletedPageInfo>& infos);
- // Methods for clearing temporary pages.
- void PostClearLegacyTemporaryPagesTask();
- void ClearLegacyTemporaryPages();
- void PostClearCachedPagesTask(bool is_initializing);
- void ClearCachedPages();
- void OnClearCachedPagesDone(base::Time start_time,
- size_t deleted_page_count,
+ // Methods for clearing temporary pages and performing consistency checks. The
+ // latter are executed only once per Chrome session.
+ void ScheduleMaintenanceTasks();
+ void RunMaintenanceTasks(const base::Time now, bool first_run);
+ void OnClearCachedPagesDone(size_t deleted_page_count,
ClearStorageTask::ClearStorageResult result);
- // Methods for consistency check.
- void PostCheckMetadataConsistencyTask(bool is_initializing);
- void CheckTemporaryPagesConsistency();
- void CheckPersistentPagesConsistency();
-
// Method for upgrade to public storage.
void PostSelectItemsMarkedForUpgrade();
void SelectItemsMarkedForUpgrade();
void OnSelectItemsMarkedForUpgradeDone(
const MultipleOfflinePageItemResult& pages_for_upgrade);
+ // Methods for publishing the page to the public directory.
+ void PublishArchive(const OfflinePageItem& offline_page,
+ const SavePageCallback& callback,
+ OfflinePageArchiver* archiver);
+
+ // Callback for when PublishArchive has completd.
+ void PublishArchiveDone(const SavePageCallback& save_page_callback,
+ const OfflinePageItem& offline_page,
+ PublishArchiveResult* archive_result);
+
+ // Method for unpublishing the page from the system download manager.
+ static void RemoveFromDownloadManager(
+ SystemDownloadManager* download_manager,
+ const std::vector<int64_t>& system_download_ids);
+
// Other utility methods.
void RemovePagesMatchingUrlAndNamespace(const OfflinePageItem& page);
+ void ErasePendingArchiver(OfflinePageArchiver* archiver);
void CreateArchivesDirectoryIfNeeded();
base::Time GetCurrentTime();
@@ -204,6 +222,9 @@ class OfflinePageModelTaskified : public OfflinePageModel,
// Manager for the offline archive files and directory.
std::unique_ptr<ArchiveManager> archive_manager_;
+ // Manages interaction with the OS download manager, if present.
+ std::unique_ptr<SystemDownloadManager> download_manager_;
+
// Controller of the client policies.
std::unique_ptr<ClientPolicyController> policy_controller_;
@@ -225,15 +246,17 @@ class OfflinePageModelTaskified : public OfflinePageModel,
// The task queue used for executing various tasks.
TaskQueue task_queue_;
- // Time of when the most recent cached pages clearing happened. The value will
- // not persist across Chrome restarts.
- base::Time last_clear_cached_pages_time_;
+ // The last scheduling timestamp of the model maintenance tasks that took
+ // place during the current Chrome session.
+ base::Time last_maintenance_tasks_schedule_time_;
// For testing only.
// This value will be affecting the CreateArchiveTasks that are created by the
// model to skip saving original_urls.
bool skip_clearing_original_url_for_testing_;
+ const scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
base::WeakPtrFactory<OfflinePageModelTaskified> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(OfflinePageModelTaskified);
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 c60f792718f..4ea02382c6c 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
@@ -14,14 +14,15 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/histogram_tester.h"
#include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/test_mock_time_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/offline_pages/core/client_namespace_constants.h"
#include "components/offline_pages/core/model/clear_storage_task.h"
#include "components/offline_pages/core/model/offline_page_item_generator.h"
#include "components/offline_pages/core/model/offline_page_model_utils.h"
#include "components/offline_pages/core/model/offline_page_test_utils.h"
+#include "components/offline_pages/core/offline_page_feature.h"
#include "components/offline_pages/core/offline_page_item.h"
#include "components/offline_pages/core/offline_page_metadata_store_sql.h"
#include "components/offline_pages/core/offline_page_metadata_store_test_util.h"
@@ -29,6 +30,7 @@
#include "components/offline_pages/core/offline_page_test_archiver.h"
#include "components/offline_pages/core/offline_page_test_store.h"
#include "components/offline_pages/core/offline_page_types.h"
+#include "components/offline_pages/core/system_download_manager_stub.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -58,11 +60,13 @@ const GURL kFileUrl("file:///foo");
const ClientId kTestClientId1(kDefaultNamespace, "1234");
const ClientId kTestClientId2(kDefaultNamespace, "5678");
const ClientId kTestUserRequestedClientId(kDownloadNamespace, "714");
+const ClientId kTestBrowserActionsClientId(kBrowserActionsNamespace, "999");
const int64_t kTestFileSize = 876543LL;
const base::string16 kTestTitle = base::UTF8ToUTF16("a title");
const std::string kTestRequestOrigin("abc.xyz");
const std::string kEmptyRequestOrigin("");
const std::string kTestDigest("test digest");
+const int64_t kDownloadId = 42LL;
} // namespace
@@ -126,6 +130,9 @@ class OfflinePageModelTaskifiedTest
OfflinePageMetadataStoreTestUtil* store_test_util() {
return &store_test_util_;
}
+ SystemDownloadManagerStub* download_manager_stub() {
+ return download_manager_stub_;
+ }
OfflinePageItemGenerator* page_generator() { return &generator_; }
TaskQueue* task_queue() { return &model_->task_queue_; }
base::HistogramTester* histogram_tester() { return histogram_tester_.get(); }
@@ -148,8 +155,8 @@ class OfflinePageModelTaskifiedTest
const OfflinePageModel::DeletedPageInfo& last_deleted_page_info() {
return last_deleted_page_info_;
}
- base::Time last_clear_page_time() {
- return model_->last_clear_cached_pages_time_;
+ base::Time last_maintenance_tasks_schedule_time() {
+ return model_->last_maintenance_tasks_schedule_time_;
}
private:
@@ -157,6 +164,7 @@ class OfflinePageModelTaskifiedTest
base::ThreadTaskRunnerHandle task_runner_handle_;
std::unique_ptr<OfflinePageModelTaskified> model_;
OfflinePageMetadataStoreTestUtil store_test_util_;
+ SystemDownloadManagerStub* download_manager_stub_;
OfflinePageItemGenerator generator_;
std::unique_ptr<base::HistogramTester> histogram_tester_;
base::ScopedTempDir temporary_dir_;
@@ -216,12 +224,17 @@ void OfflinePageModelTaskifiedTest::BuildStore() {
void OfflinePageModelTaskifiedTest::BuildModel() {
ASSERT_TRUE(store_test_util_.store());
+ // Keep a copy of the system download manager stub to test against.
+ download_manager_stub_ = new SystemDownloadManagerStub(kDownloadId, true);
auto archive_manager = std::make_unique<ArchiveManager>(
temporary_dir_path(), private_archive_dir_path(),
public_archive_dir_path(), base::ThreadTaskRunnerHandle::Get());
+ std::unique_ptr<SystemDownloadManager> download_manager(
+ download_manager_stub_);
model_ = std::make_unique<OfflinePageModelTaskified>(
store_test_util()->ReleaseStore(), std::move(archive_manager),
- base::ThreadTaskRunnerHandle::Get(), task_runner_->GetMockClock());
+ std::move(download_manager), base::ThreadTaskRunnerHandle::Get(),
+ task_runner_->GetMockClock());
model_->AddObserver(this);
histogram_tester_ = std::make_unique<base::HistogramTester>();
ResetResults();
@@ -743,6 +756,9 @@ TEST_F(OfflinePageModelTaskifiedTest, GetAllPagesWhenStoreEmpty) {
EXPECT_TRUE(task_queue()->HasRunningTask());
PumpLoop();
+
+ histogram_tester()->ExpectUniqueSample("OfflinePages.SavedPageCountUponQuery",
+ 0, 1);
}
// TODO(romax): remove these 'indicators for newly added tests' when migration
@@ -776,6 +792,7 @@ TEST_F(OfflinePageModelTaskifiedTest, DeletePagesByOfflineId) {
page_generator()->SetNamespace(kDefaultNamespace);
OfflinePageItem page1 = page_generator()->CreateItemWithTempFile();
OfflinePageItem page2 = page_generator()->CreateItemWithTempFile();
+ page1.system_download_id = kDownloadId;
InsertPageIntoStore(page1);
InsertPageIntoStore(page2);
EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(temporary_dir_path()));
@@ -793,6 +810,8 @@ TEST_F(OfflinePageModelTaskifiedTest, DeletePagesByOfflineId) {
EXPECT_EQ(last_deleted_page_info().offline_id, page1.offline_id);
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path()));
EXPECT_EQ(1LL, store_test_util()->GetPageCount());
+ EXPECT_EQ(page1.system_download_id,
+ download_manager_stub()->last_removed_id());
histogram_tester()->ExpectUniqueSample(
"OfflinePages.DeletePageCount",
static_cast<int>(
@@ -1019,6 +1038,28 @@ TEST_F(OfflinePageModelTaskifiedTest, GetPagesByRequestOrigin) {
PumpLoop();
}
+TEST_F(OfflinePageModelTaskifiedTest, GetPageBySizeAndDigest) {
+ static const int64_t kFileSize1 = 123LL;
+ static const int64_t kFileSize2 = 999999LL;
+ static const char kDigest1[] = "digest 1";
+ page_generator()->SetFileSize(kFileSize1);
+ page_generator()->SetDigest(kDigest1);
+ OfflinePageItem page1 = page_generator()->CreateItem();
+ page_generator()->SetFileSize(kFileSize2);
+ page_generator()->SetDigest(kDigest1);
+ OfflinePageItem page2 = page_generator()->CreateItem();
+ InsertPageIntoStore(page1);
+ InsertPageIntoStore(page2);
+
+ base::MockCallback<SingleOfflinePageItemCallback> callback;
+ EXPECT_CALL(callback, Run(Pointee(Eq(page2))));
+
+ model()->GetPageBySizeAndDigest(kFileSize2, kDigest1, callback.Get());
+ EXPECT_TRUE(task_queue()->HasRunningTask());
+
+ PumpLoop();
+}
+
TEST_F(OfflinePageModelTaskifiedTest, DeletePagesByClientIds) {
page_generator()->SetArchiveDirectory(temporary_dir_path());
page_generator()->SetNamespace(kTestClientId1.name_space);
@@ -1121,22 +1162,24 @@ TEST_F(OfflinePageModelTaskifiedTest, GetPagesSupportedByDownloads) {
// This test is affected by https://crbug.com/725685, which only affects windows
// platform.
#if defined(OS_WIN)
-#define MAYBE_CheckPagesSavedInSeparateDirs \
- DISABLED_CheckPagesSavedInSeparateDirs
+#define MAYBE_CheckPagesSavedInSeparateDirsPrivate \
+ DISABLED_CheckPagesSavedInSeparateDirsPrivate
#else
-#define MAYBE_CheckPagesSavedInSeparateDirs CheckPagesSavedInSeparateDirs
+#define MAYBE_CheckPagesSavedInSeparateDirsPrivate \
+ CheckPagesSavedInSeparateDirsPrivate
#endif
-TEST_F(OfflinePageModelTaskifiedTest, MAYBE_CheckPagesSavedInSeparateDirs) {
+TEST_F(OfflinePageModelTaskifiedTest,
+ MAYBE_CheckPagesSavedInSeparateDirsPrivate) {
// Save a temporary page.
auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
int64_t temporary_id = SavePageWithExpectedResult(
kTestUrl, kTestClientId1, GURL(), kEmptyRequestOrigin,
std::move(archiver), SavePageResult::SUCCESS);
- // Save a persistent page.
+ // Save a persistent page that will not be published
archiver = BuildArchiver(kTestUrl2, ArchiverResult::SUCCESSFULLY_CREATED);
int64_t persistent_id = SavePageWithExpectedResult(
- kTestUrl2, kTestUserRequestedClientId, GURL(), kEmptyRequestOrigin,
+ kTestUrl2, kTestBrowserActionsClientId, GURL(), kEmptyRequestOrigin,
std::move(archiver), SavePageResult::SUCCESS);
std::unique_ptr<OfflinePageItem> temporary_page =
@@ -1151,10 +1194,56 @@ TEST_F(OfflinePageModelTaskifiedTest, MAYBE_CheckPagesSavedInSeparateDirs) {
base::FilePath persistent_page_path = persistent_page->file_path;
EXPECT_TRUE(temporary_dir_path().IsParent(temporary_page_path));
+ // For a page in the prefetch namespace, it gets moved to the
+ // a private internal directory inside chromium.
EXPECT_TRUE(private_archive_dir_path().IsParent(persistent_page_path));
EXPECT_NE(temporary_page_path.DirName(), persistent_page_path.DirName());
}
+// This test is affected by https://crbug.com/725685, which only affects windows
+// platform.
+#if defined(OS_WIN)
+#define MAYBE_CheckPagesSavedInSeparateDirsPublic \
+ DISABLED_CheckPagesSavedInSeparateDirsPublic
+#else
+#define MAYBE_CheckPagesSavedInSeparateDirsPublic \
+ CheckPagesSavedInSeparateDirsPublic
+#endif
+TEST_F(OfflinePageModelTaskifiedTest,
+ MAYBE_CheckPagesSavedInSeparateDirsPublic) {
+ auto feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ feature_list->InitAndEnableFeature(
+ offline_pages::kOfflinePagesSharingFeature);
+ // Save a temporary page.
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
+ int64_t temporary_id = SavePageWithExpectedResult(
+ kTestUrl, kTestClientId1, GURL(), kEmptyRequestOrigin,
+ std::move(archiver), SavePageResult::SUCCESS);
+
+ // Save a persistent page that will be published.
+ archiver = BuildArchiver(kTestUrl2, ArchiverResult::SUCCESSFULLY_CREATED);
+ int64_t persistent_id = SavePageWithExpectedResult(
+ kTestUrl2, kTestUserRequestedClientId, GURL(), kEmptyRequestOrigin,
+ std::move(archiver), SavePageResult::SUCCESS);
+
+ std::unique_ptr<OfflinePageItem> temporary_page =
+ store_test_util()->GetPageByOfflineId(temporary_id);
+ std::unique_ptr<OfflinePageItem> persistent_page =
+ store_test_util()->GetPageByOfflineId(persistent_id);
+
+ ASSERT_TRUE(temporary_page);
+ ASSERT_TRUE(persistent_page);
+
+ base::FilePath temporary_page_path = temporary_page->file_path;
+ base::FilePath persistent_page_path = persistent_page->file_path;
+
+ EXPECT_TRUE(temporary_dir_path().IsParent(temporary_page_path));
+ // TODO(petewil): It might be better to replace the check below with a check
+ // that the file ended up in the correct place instead of just not the wrong
+ // place.
+ EXPECT_NE(temporary_page_path.DirName(), persistent_page_path.DirName());
+}
+
// This test is disabled since it's lacking the ability of mocking store failure
// in store_test_utils. https://crbug.com/781023
// TODO(romax): reenable the test once the above issue is resolved.
@@ -1234,21 +1323,19 @@ TEST_F(OfflinePageModelTaskifiedTest, GetAllPages) {
EXPECT_CALL(callback, Run(UnorderedElementsAre(page1, page2)));
model()->GetAllPages(callback.Get());
PumpLoop();
+
+ histogram_tester()->ExpectUniqueSample("OfflinePages.SavedPageCountUponQuery",
+ 2, 1);
}
// This test is affected by https://crbug.com/725685, which only affects windows
// platform.
#if defined(OS_WIN)
-#define MAYBE_StartUp_ConsistencyCheckExecuted \
- DISABLED_StartUp_ConsistencyCheckExecuted
+#define MAYBE_ConsistencyCheckExecuted DISABLED_ConsistencyCheckExecuted
#else
-#define MAYBE_StartUp_ConsistencyCheckExecuted StartUp_ConsistencyCheckExecuted
+#define MAYBE_ConsistencyCheckExecuted ConsistencyCheckExecuted
#endif
-TEST_F(OfflinePageModelTaskifiedTest, MAYBE_StartUp_ConsistencyCheckExecuted) {
- // Rebuild the store so that we can insert pages before the model constructs.
- ResetModel();
- BuildStore();
-
+TEST_F(OfflinePageModelTaskifiedTest, MAYBE_ConsistencyCheckExecuted) {
// Insert temporary pages
page_generator()->SetArchiveDirectory(temporary_dir_path());
page_generator()->SetNamespace(kDefaultNamespace);
@@ -1282,10 +1369,14 @@ TEST_F(OfflinePageModelTaskifiedTest, MAYBE_StartUp_ConsistencyCheckExecuted) {
EXPECT_EQ(3UL,
test_utils::GetFileCountInDirectory(private_archive_dir_path()));
- // Rebuild the model in order to trigger consistency check.
- BuildModel();
+ // Execute GetAllPages and move the clock forward to cover the delay, in order
+ // to trigger consistency checks.
+ base::MockCallback<MultipleOfflinePageItemCallback> callback;
+ model()->GetAllPages(callback.Get());
task_runner()->FastForwardBy(
- OfflinePageModelTaskified::kInitializingTaskDelay);
+ OfflinePageModelTaskified::kMaintenanceTasksDelay +
+ base::TimeDelta::FromMilliseconds(1));
+ PumpLoop();
EXPECT_EQ(1LL, store_test_util()->GetPageCount());
EXPECT_EQ(0UL, test_utils::GetFileCountInDirectory(temporary_dir_path()));
@@ -1294,34 +1385,64 @@ TEST_F(OfflinePageModelTaskifiedTest, MAYBE_StartUp_ConsistencyCheckExecuted) {
}
TEST_F(OfflinePageModelTaskifiedTest, ClearStorage) {
- // Rebuilding store and model in order to set clock before executing the clear
- // storage during model initialization so that we can check the time.
- ResetModel();
- BuildStore();
- BuildModel();
+ // The ClearStorage task should not be executed based on time delays after
+ // launch (aka the model being built).
+ task_runner()->FastForwardBy(base::TimeDelta::FromDays(1));
+ PumpLoop();
+ EXPECT_EQ(base::Time(), last_maintenance_tasks_schedule_time());
+ // GetAllPages should schedule a delayed task that will eventually run
+ // ClearStorage.
+ base::MockCallback<MultipleOfflinePageItemCallback> callback;
+ model()->GetAllPages(callback.Get());
+ PumpLoop();
+ EXPECT_EQ(task_runner()->Now(), last_maintenance_tasks_schedule_time());
+ base::Time last_scheduling_time = task_runner()->Now();
+ // Confirm no runs so far.
+ histogram_tester()->ExpectTotalCount(
+ "OfflinePages.ClearTemporaryPages.Result", 0);
+
+ // After the delay (plus 1 millisecond just in case) ClearStorage should be
+ // enqueued and executed.
+ const base::TimeDelta run_delay =
+ OfflinePageModelTaskified::kMaintenanceTasksDelay +
+ base::TimeDelta::FromMilliseconds(1);
+ task_runner()->FastForwardBy(run_delay);
PumpLoop();
- EXPECT_EQ(task_runner()->Now(), last_clear_page_time());
+ EXPECT_EQ(last_scheduling_time, last_maintenance_tasks_schedule_time());
- // Only 5 minutes passed and the last clear page time should not be changed
- // since the clear page will not be triggered.
- const base::TimeDelta short_delta = base::TimeDelta::FromMinutes(5);
- task_runner()->FastForwardBy(short_delta);
- auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
- int64_t offline_id = SavePageWithExpectedResult(
- kTestUrl, kTestClientId1, kTestUrl2, kEmptyRequestOrigin,
- std::move(archiver), SavePageResult::SUCCESS);
+ // Calling GetAllPages after only half of the enforced interval between
+ // ClearStorage runs should not schedule ClearStorage.
+ // Note: The previous elapsed delay is discounted from the clock advance here.
+ task_runner()->FastForwardBy(
+ OfflinePageModelTaskified::kClearStorageInterval / 2 - run_delay);
+ ASSERT_GT(task_runner()->Now(), last_scheduling_time);
+ model()->GetAllPages(callback.Get());
+ // And advance the delay too.
+ task_runner()->FastForwardBy(run_delay);
PumpLoop();
- EXPECT_EQ(task_runner()->Now() - short_delta, last_clear_page_time());
+ EXPECT_EQ(last_scheduling_time, last_maintenance_tasks_schedule_time());
+ // Confirm a single run happened so far.
+ histogram_tester()->ExpectUniqueSample(
+ "OfflinePages.ClearTemporaryPages.Result",
+ static_cast<int>(ClearStorageResult::UNNECESSARY), 1);
+ // Forwarding by the full interval (plus 1 second just in case) should allow
+ // the task to be enqueued again.
task_runner()->FastForwardBy(
- OfflinePageModelTaskified::kClearStorageInterval);
- archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
- offline_id = SavePageWithExpectedResult(
- kTestUrl, kTestClientId1, kTestUrl2, kEmptyRequestOrigin,
- std::move(archiver), SavePageResult::SUCCESS);
+ OfflinePageModelTaskified::kClearStorageInterval / 2 +
+ base::TimeDelta::FromSeconds(1));
+ // Saving a page should also immediately enqueue the ClearStorage task.
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
+ SavePageWithExpectedResult(kTestUrl, kTestClientId1, kTestUrl2,
+ kEmptyRequestOrigin, std::move(archiver),
+ SavePageResult::SUCCESS);
+ last_scheduling_time = task_runner()->Now();
+ // Advance the delay again.
+ task_runner()->FastForwardBy(run_delay);
PumpLoop();
- EXPECT_EQ(task_runner()->Now(), last_clear_page_time());
+ EXPECT_EQ(last_scheduling_time, last_maintenance_tasks_schedule_time());
+ // Confirm that two runs happened.
histogram_tester()->ExpectUniqueSample(
"OfflinePages.ClearTemporaryPages.Result",
static_cast<int>(ClearStorageResult::UNNECESSARY), 2);
diff --git a/chromium/components/offline_pages/core/model/offline_page_model_utils.cc b/chromium/components/offline_pages/core/model/offline_page_model_utils.cc
index 2ef665aa5e7..08632c6d335 100644
--- a/chromium/components/offline_pages/core/model/offline_page_model_utils.cc
+++ b/chromium/components/offline_pages/core/model/offline_page_model_utils.cc
@@ -6,7 +6,14 @@
#include <string>
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "build/build_config.h"
+#include "components/filename_generation/filename_generation.h"
#include "components/offline_pages/core/client_namespace_constants.h"
#include "components/offline_pages/core/offline_page_item.h"
@@ -51,6 +58,46 @@ std::string AddHistogramSuffix(const std::string& name_space,
return adjusted_histogram_name;
}
+base::FilePath GenerateUniqueFilenameForOfflinePage(
+ const base::string16& title,
+ const GURL& url,
+ const base::FilePath& target_dir) {
+ std::string kMHTMLMimeType = "multipart/related";
+
+ // Get the suggested file name based on title and url.
+ base::FilePath suggested_path =
+ target_dir.Append(filename_generation::GenerateFilename(
+ title, url, false /* can_save_as_complete */, kMHTMLMimeType));
+
+ // Find a unique name based on |suggested_path|.
+ int uniquifier =
+ base::GetUniquePathNumber(suggested_path, base::FilePath::StringType());
+ base::FilePath::StringType suffix;
+ if (uniquifier > 0)
+#if defined(OS_WIN)
+ suffix = base::StringPrintf(L" (%d)", uniquifier);
+#else // defined(OS_WIN)
+ suffix = base::StringPrintf(" (%d)", uniquifier);
+#endif // defined(OS_WIN)
+
+ // Truncation.
+ int max_path_component_length =
+ base::GetMaximumPathComponentLength(target_dir);
+ if (max_path_component_length != -1) {
+ int limit = max_path_component_length -
+ suggested_path.Extension().length() - suffix.length();
+ if (limit <= 0 ||
+ !filename_generation::TruncateFilename(&suggested_path, limit))
+ return base::FilePath();
+ }
+
+ // Adding uniquifier suffix if needed.
+ if (uniquifier > 0)
+ suggested_path = suggested_path.InsertBeforeExtension(suffix);
+
+ return suggested_path;
+}
+
} // namespace model_utils
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/model/offline_page_model_utils.h b/chromium/components/offline_pages/core/model/offline_page_model_utils.h
index 17c145bb54e..2ff5f7b5993 100644
--- a/chromium/components/offline_pages/core/model/offline_page_model_utils.h
+++ b/chromium/components/offline_pages/core/model/offline_page_model_utils.h
@@ -7,6 +7,14 @@
#include <string>
+#include "base/strings/string16.h"
+
+class GURL;
+
+namespace base {
+class FilePath;
+} // namespace base
+
namespace offline_pages {
enum class OfflinePagesNamespaceEnumeration;
@@ -20,6 +28,11 @@ OfflinePagesNamespaceEnumeration ToNamespaceEnum(const std::string& name_space);
std::string AddHistogramSuffix(const std::string& name_space,
const char* histogram_name);
+base::FilePath GenerateUniqueFilenameForOfflinePage(
+ const base::string16& title,
+ const GURL& url,
+ const base::FilePath& target_dir);
+
} // namespace model_utils
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/model/offline_page_model_utils_unittest.cc b/chromium/components/offline_pages/core/model/offline_page_model_utils_unittest.cc
index b5b306b1c8d..da92148cf7a 100644
--- a/chromium/components/offline_pages/core/model/offline_page_model_utils_unittest.cc
+++ b/chromium/components/offline_pages/core/model/offline_page_model_utils_unittest.cc
@@ -4,8 +4,15 @@
#include "components/offline_pages/core/model/offline_page_model_utils.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
#include "components/offline_pages/core/client_namespace_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
namespace offline_pages {
@@ -30,4 +37,62 @@ TEST(OfflinePageModelUtilsTest, ToNamespaceEnum) {
OfflinePagesNamespaceEnumeration::BROWSER_ACTIONS);
}
+static const struct GenerateUniqueFilenameTestCase {
+ const base::string16 page_title;
+ const GURL page_url;
+ const base::FilePath::CharType* expected_basename;
+} kGenerateUniqueFilenameCases[] = {
+ {base::ASCIIToUTF16("wikipedia.org-Main_Page"),
+ GURL("http://www.wikipedia.org/Main_Page"),
+ FILE_PATH_LITERAL("wikipedia.org-Main_Page.mhtml")},
+ {base::ASCIIToUTF16("wikipedia.org-Main_Page"),
+ GURL("http://www.wikipedia.org/Main_Page"),
+ FILE_PATH_LITERAL("wikipedia.org-Main_Page (1).mhtml")},
+ {base::ASCIIToUTF16("wikipedia.org-Main_Page"),
+ GURL("http://www.wikipedia.org/Main_Page"),
+ FILE_PATH_LITERAL("wikipedia.org-Main_Page (2).mhtml")},
+ {base::ASCIIToUTF16("wikipedia.org-Main_Page.mhtml"),
+ GURL("http://www.wikipedia.org/Main_Page"),
+ FILE_PATH_LITERAL("wikipedia.org-Main_Page (3).mhtml")},
+ {base::ASCIIToUTF16("wikipedia.org-Main_Page"),
+ GURL("http://www.wikipedia.org/Main_Page"),
+ FILE_PATH_LITERAL("wikipedia.org-Main_Page (4).mhtml")},
+ {base::ASCIIToUTF16("wikipedia.org"),
+ GURL("http://www.wikipedia.org/Main_Page"),
+ FILE_PATH_LITERAL("wikipedia.org.mhtml")},
+ {base::ASCIIToUTF16("wikipedia.org"),
+ GURL("http://www.wikipedia.org/Main_Page"),
+ FILE_PATH_LITERAL("wikipedia.org (1).mhtml")},
+ {base::UTF8ToUTF16("bücher.com"), GURL("http://xn--bcher-kva.com"),
+ FILE_PATH_LITERAL("bücher.com.mhtml")},
+ {base::ASCIIToUTF16("http://foo.com/path/title.html"),
+ GURL("http://foo.com"),
+ FILE_PATH_LITERAL("http___foo.com_path_title.html.mhtml")},
+ {base::ASCIIToUTF16("foo.com/foo-%40.html"),
+ GURL("http://foo.com/foo-%40.html"),
+ FILE_PATH_LITERAL("foo-@.html.mhtml")},
+ {base::ASCIIToUTF16("Viva%40%40%40-TestTitle"),
+ GURL("http://foo.com/%40.html"),
+ FILE_PATH_LITERAL("Viva%40%40%40-TestTitle.mhtml")},
+};
+
+// Crashing on Windows, see http://crbug.com/79365
+#if defined(OS_WIN)
+#define MAYBE_TestGenerateUniqueFilename DISABLED_TestGenerateUniqueFilename
+#else
+#define MAYBE_TestGenerateUniqueFilename TestGenerateUniqueFilename
+#endif
+TEST(OfflinePageModelUtilsTest, MAYBE_TestGenerateUniqueFilename) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+ for (const auto& test_case : kGenerateUniqueFilenameCases) {
+ base::FilePath path = model_utils::GenerateUniqueFilenameForOfflinePage(
+ test_case.page_title, test_case.page_url, temp_dir.GetPath());
+ // Writing a dummy file so the uniquifier can increase.
+ base::WriteFile(path, nullptr, 0);
+ EXPECT_EQ(path.BaseName().value(), test_case.expected_basename);
+ }
+}
+
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/model/persistent_pages_consistency_check_task.cc b/chromium/components/offline_pages/core/model/persistent_pages_consistency_check_task.cc
index 5b7b383bcb6..45395d7e31a 100644
--- a/chromium/components/offline_pages/core/model/persistent_pages_consistency_check_task.cc
+++ b/chromium/components/offline_pages/core/model/persistent_pages_consistency_check_task.cc
@@ -14,6 +14,7 @@
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/metrics/histogram_macros.h"
+#include "base/trace_event/trace_event.h"
#include "components/offline_pages/core/client_policy_controller.h"
#include "components/offline_pages/core/offline_page_metadata_store_sql.h"
#include "components/offline_pages/core/offline_page_types.h"
@@ -116,14 +117,14 @@ SyncOperationResult CheckConsistencySync(
// faster matching later.
persistent_page_info_paths.insert(page_info.file_path);
}
- // Try to delete the pages by offline ids collected above.
- // If there's any database related errors, the function will return false,
- // and the database operations will be rolled back since the transaction will
- // not be committed.
- if (!DeletePagesByOfflineIds(offline_ids_to_delete, db))
- return SyncOperationResult::DB_OPERATION_ERROR;
if (offline_ids_to_delete.size() > 0) {
+ // Try to delete the pages by offline ids collected above. If there's any
+ // database related errors, the function will return false, and the database
+ // operations will be rolled back since the transaction will not be
+ // committed.
+ if (!DeletePagesByOfflineIds(offline_ids_to_delete, db))
+ return SyncOperationResult::DB_OPERATION_ERROR;
UMA_HISTOGRAM_COUNTS(
"OfflinePages.ConsistencyCheck.Persistent.PagesMissingArchiveFileCount",
static_cast<int32_t>(offline_ids_to_delete.size()));
@@ -144,14 +145,13 @@ SyncOperationResult CheckConsistencySync(
}
if (files_to_delete.size() > 0) {
+ if (!DeleteFiles(files_to_delete))
+ return SyncOperationResult::FILE_OPERATION_ERROR;
UMA_HISTOGRAM_COUNTS(
"OfflinePages.ConsistencyCheck.Persistent.PagesMissingDbEntryCount",
static_cast<int32_t>(files_to_delete.size()));
}
- if (!DeleteFiles(files_to_delete))
- return SyncOperationResult::FILE_OPERATION_ERROR;
-
return SyncOperationResult::SUCCESS;
}
@@ -172,6 +172,8 @@ PersistentPagesConsistencyCheckTask::PersistentPagesConsistencyCheckTask(
PersistentPagesConsistencyCheckTask::~PersistentPagesConsistencyCheckTask() {}
void PersistentPagesConsistencyCheckTask::Run() {
+ TRACE_EVENT_ASYNC_BEGIN0("offline_pages",
+ "PersistentPagesConsistencyCheckTask running", this);
std::vector<std::string> namespaces = policy_controller_->GetAllNamespaces();
std::vector<std::string> persistent_namespace_names;
for (const auto& name_space : namespaces) {
@@ -191,6 +193,9 @@ void PersistentPagesConsistencyCheckTask::OnCheckConsistencyDone(
UMA_HISTOGRAM_ENUMERATION("OfflinePages.ConsistencyCheck.Persistent.Result",
result, SyncOperationResult::RESULT_COUNT);
TaskComplete();
+ TRACE_EVENT_ASYNC_END1("offline_pages",
+ "PersistentPagesConsistencyCheckTask running", this,
+ "result", static_cast<int>(result));
}
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/model/temporary_pages_consistency_check_task.cc b/chromium/components/offline_pages/core/model/temporary_pages_consistency_check_task.cc
index 7f8e83b0a61..99e274b6046 100644
--- a/chromium/components/offline_pages/core/model/temporary_pages_consistency_check_task.cc
+++ b/chromium/components/offline_pages/core/model/temporary_pages_consistency_check_task.cc
@@ -14,6 +14,7 @@
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/metrics/histogram_macros.h"
+#include "base/trace_event/trace_event.h"
#include "components/offline_pages/core/client_policy_controller.h"
#include "components/offline_pages/core/offline_page_metadata_store_sql.h"
#include "components/offline_pages/core/offline_page_types.h"
@@ -117,14 +118,14 @@ SyncOperationResult CheckConsistencySync(
// faster matching later.
temp_page_info_paths.insert(page_info.file_path);
}
- // Try to delete the pages by offline ids collected above.
- // If there's any database related errors, the function will return false,
- // and the database operations will be rolled back since the transaction will
- // not be committed.
- if (!DeletePagesByOfflineIds(offline_ids_to_delete, db))
- return SyncOperationResult::DB_OPERATION_ERROR;
if (offline_ids_to_delete.size() > 0) {
+ // Try to delete the pages by offline ids collected above. If there's any
+ // database related errors, the function will return false, and the database
+ // operations will be rolled back since the transaction will not be
+ // committed.
+ if (!DeletePagesByOfflineIds(offline_ids_to_delete, db))
+ return SyncOperationResult::DB_OPERATION_ERROR;
UMA_HISTOGRAM_COUNTS(
"OfflinePages.ConsistencyCheck.Temporary.PagesMissingArchiveFileCount",
static_cast<int32_t>(offline_ids_to_delete.size()));
@@ -143,14 +144,13 @@ SyncOperationResult CheckConsistencySync(
}
if (files_to_delete.size() > 0) {
+ if (!DeleteFiles(files_to_delete))
+ return SyncOperationResult::FILE_OPERATION_ERROR;
UMA_HISTOGRAM_COUNTS(
"OfflinePages.ConsistencyCheck.Temporary.PagesMissingDbEntryCount",
static_cast<int32_t>(files_to_delete.size()));
}
- if (!DeleteFiles(files_to_delete))
- return SyncOperationResult::FILE_OPERATION_ERROR;
-
return SyncOperationResult::SUCCESS;
}
@@ -171,6 +171,8 @@ TemporaryPagesConsistencyCheckTask::TemporaryPagesConsistencyCheckTask(
TemporaryPagesConsistencyCheckTask::~TemporaryPagesConsistencyCheckTask() {}
void TemporaryPagesConsistencyCheckTask::Run() {
+ TRACE_EVENT_ASYNC_BEGIN0("offline_pages",
+ "TemporaryPagesConsistencyCheckTask running", this);
std::vector<std::string> temp_namespaces =
policy_controller_->GetNamespacesRemovedOnCacheReset();
store_->Execute(
@@ -185,6 +187,9 @@ void TemporaryPagesConsistencyCheckTask::OnCheckConsistencyDone(
UMA_HISTOGRAM_ENUMERATION("OfflinePages.ConsistencyCheck.Temporary.Result",
result, SyncOperationResult::RESULT_COUNT);
TaskComplete();
+ TRACE_EVENT_ASYNC_END1("offline_pages",
+ "TemporaryPagesConsistencyCheckTask running", this,
+ "result", static_cast<int>(result));
}
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/offline_page_archiver.cc b/chromium/components/offline_pages/core/offline_page_archiver.cc
new file mode 100644
index 00000000000..e77af89c01f
--- /dev/null
+++ b/chromium/components/offline_pages/core/offline_page_archiver.cc
@@ -0,0 +1,87 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/offline_pages/core/offline_page_archiver.h"
+
+#include "base/strings/utf_string_conversions.h"
+
+#include "base/bind_helpers.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "components/offline_pages/core/model/offline_page_model_taskified.h"
+#include "components/offline_pages/core/model/offline_page_model_utils.h"
+#include "components/offline_pages/core/offline_store_utils.h"
+#include "components/offline_pages/core/system_download_manager.h"
+
+namespace {
+
+// Helper function to do the move and register synchronously. Make sure this is
+// called from a background thread.
+void MoveAndRegisterArchive(
+ const offline_pages::OfflinePageItem& offline_page,
+ const base::FilePath& publish_directory,
+ offline_pages::SystemDownloadManager* download_manager,
+ offline_pages::PublishArchiveResult* archive_result) {
+ // Calculate the new file name.
+ base::FilePath new_file_path =
+ offline_pages::model_utils::GenerateUniqueFilenameForOfflinePage(
+ offline_page.title, offline_page.url, publish_directory);
+
+ // Move the file.
+ bool moved = base::Move(offline_page.file_path, new_file_path);
+ if (!moved) {
+ archive_result->move_result =
+ offline_pages::SavePageResult::FILE_MOVE_FAILED;
+ return;
+ }
+
+ // Tell the download manager about our file, get back an id.
+ if (!download_manager->IsDownloadManagerInstalled()) {
+ archive_result->move_result =
+ offline_pages::SavePageResult::ADD_TO_DOWNLOAD_MANAGER_FAILED;
+ return;
+ }
+
+ // TODO(petewil): Handle empty page title.
+ std::string page_title = base::UTF16ToUTF8(offline_page.title);
+ // We use the title for a description, since the add to the download manager
+ // fails without a description, and we don't have anything better to use.
+ int64_t download_id = download_manager->AddCompletedDownload(
+ page_title, page_title,
+ offline_pages::store_utils::ToDatabaseFilePath(new_file_path),
+ offline_page.file_size, offline_page.url.spec(), std::string());
+ if (download_id == 0LL) {
+ archive_result->move_result =
+ offline_pages::SavePageResult::ADD_TO_DOWNLOAD_MANAGER_FAILED;
+ return;
+ }
+
+ // Put results into the result object.
+ archive_result->move_result = offline_pages::SavePageResult::SUCCESS;
+ archive_result->new_file_path = new_file_path;
+ archive_result->download_id = download_id;
+
+ return;
+}
+
+} // namespace
+
+namespace offline_pages {
+
+void OfflinePageArchiver::PublishArchive(
+ const OfflinePageItem& offline_page,
+ const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+ const base::FilePath& publish_directory,
+ SystemDownloadManager* download_manager,
+ PublishArchiveDoneCallback archive_done_callback) {
+ PublishArchiveResult* archive_results = new PublishArchiveResult();
+ background_task_runner->PostTaskAndReply(
+ FROM_HERE,
+ base::BindOnce(&MoveAndRegisterArchive, offline_page, publish_directory,
+ download_manager, base::Unretained(archive_results)),
+ base::BindOnce(std::move(archive_done_callback), offline_page,
+ base::Owned(archive_results)));
+}
+
+} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/offline_page_archiver.h b/chromium/components/offline_pages/core/offline_page_archiver.h
index e0346134338..b03e8b2c9b8 100644
--- a/chromium/components/offline_pages/core/offline_page_archiver.h
+++ b/chromium/components/offline_pages/core/offline_page_archiver.h
@@ -9,11 +9,32 @@
#include "base/callback.h"
#include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
+#include "base/task_scheduler/post_task.h"
+#include "components/offline_pages/core/offline_page_item.h"
+#include "components/offline_pages/core/offline_page_types.h"
#include "url/gurl.h"
+namespace base {
+class SequencedTaskRunner;
+} // namespace base
+
namespace offline_pages {
+class SystemDownloadManager;
+
+// The results of attempting to move the offline page to a public directory, and
+// registering it with the system download manager.
+struct PublishArchiveResult {
+ SavePageResult move_result;
+ base::FilePath new_file_path;
+ int64_t download_id;
+};
+
+using PublishArchiveDoneCallback =
+ base::OnceCallback<void(const OfflinePageItem&, PublishArchiveResult*)>;
+
// Interface of a class responsible for creation of the archive for offline use.
//
// Archiver will be implemented by embedder and may have additional methods that
@@ -86,6 +107,15 @@ class OfflinePageArchiver {
virtual void CreateArchive(const base::FilePath& archives_dir,
const CreateArchiveParams& create_archive_params,
const CreateArchiveCallback& callback) = 0;
+
+ // Publishes the page on a background thread, then returns to the
+ // OfflinePageModelTaskified's done callback.
+ virtual void PublishArchive(
+ const OfflinePageItem& offline_page,
+ const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+ const base::FilePath& publish_directory,
+ SystemDownloadManager* download_manager,
+ PublishArchiveDoneCallback publish_done_callback);
};
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/offline_page_archiver_unittest.cc b/chromium/components/offline_pages/core/offline_page_archiver_unittest.cc
new file mode 100644
index 00000000000..6ef23d66744
--- /dev/null
+++ b/chromium/components/offline_pages/core/offline_page_archiver_unittest.cc
@@ -0,0 +1,128 @@
+// Copyright 2018 The Chromium Authors. All 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_archiver.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/weak_ptr.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/offline_pages/core/model/offline_page_item_generator.h"
+#include "components/offline_pages/core/system_download_manager_stub.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+const int64_t kDownloadId = 42LL;
+} // namespace
+
+namespace offline_pages {
+
+class TestOfflinePageArchiver : public OfflinePageArchiver {
+ public:
+ void CreateArchive(const base::FilePath& archives_dir,
+ const CreateArchiveParams& create_archive_params,
+ const CreateArchiveCallback& callback) override {}
+};
+
+class OfflinePageArchiverTest
+ : public testing::Test,
+ public base::SupportsWeakPtr<OfflinePageArchiverTest> {
+ public:
+ OfflinePageArchiverTest()
+ : task_runner_(new base::TestSimpleTaskRunner),
+ task_runner_handle_(task_runner_),
+ weak_ptr_factory_(this) {}
+ ~OfflinePageArchiverTest() override {}
+
+ SavePageCallback save_page_callback;
+
+ void SetUp() override;
+ void PumpLoop();
+
+ OfflinePageItemGenerator* page_generator() { return &page_generator_; }
+
+ const base::FilePath& temporary_dir_path() {
+ return temporary_dir_.GetPath();
+ }
+ const base::FilePath& private_archive_dir_path() {
+ return private_archive_dir_.GetPath();
+ }
+ const base::FilePath& public_archive_dir_path() {
+ return public_archive_dir_.GetPath();
+ }
+ const PublishArchiveResult& publish_archive_result() {
+ return publish_archive_result_;
+ }
+ scoped_refptr<base::SequencedTaskRunner> task_runner() {
+ return task_runner_;
+ }
+ base::WeakPtr<OfflinePageArchiverTest> get_weak_ptr() {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
+
+ void PublishArchiveDone(const SavePageCallback& save_page_callback,
+ const OfflinePageItem& offline_page,
+ PublishArchiveResult* archive_result);
+
+ private:
+ base::ScopedTempDir temporary_dir_;
+ base::ScopedTempDir private_archive_dir_;
+ base::ScopedTempDir public_archive_dir_;
+ OfflinePageItemGenerator page_generator_;
+ PublishArchiveResult publish_archive_result_;
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+ base::ThreadTaskRunnerHandle task_runner_handle_;
+ base::WeakPtrFactory<OfflinePageArchiverTest> weak_ptr_factory_;
+};
+
+void OfflinePageArchiverTest::SetUp() {
+ ASSERT_TRUE(temporary_dir_.CreateUniqueTempDir());
+ ASSERT_TRUE(private_archive_dir_.CreateUniqueTempDir());
+ ASSERT_TRUE(public_archive_dir_.CreateUniqueTempDir());
+}
+
+void OfflinePageArchiverTest::PublishArchiveDone(
+ const SavePageCallback& save_page_callback,
+ const OfflinePageItem& offline_page,
+ PublishArchiveResult* archive_result) {
+ publish_archive_result_ = *archive_result;
+}
+
+void OfflinePageArchiverTest::PumpLoop() {
+ task_runner_->RunUntilIdle();
+}
+
+TEST_F(OfflinePageArchiverTest, PublishArchive) {
+ TestOfflinePageArchiver archiver;
+ // Put an offline page into the private dir, adjust the FilePath.
+ page_generator()->SetArchiveDirectory(temporary_dir_path());
+ OfflinePageItem offline_page = page_generator()->CreateItemWithTempFile();
+ base::FilePath old_file_path = offline_page.file_path;
+ base::FilePath new_file_path =
+ public_archive_dir_path().Append(offline_page.file_path.BaseName());
+ std::unique_ptr<SystemDownloadManager> download_manager(
+ new SystemDownloadManagerStub(kDownloadId, true));
+
+ archiver.PublishArchive(
+ offline_page, base::ThreadTaskRunnerHandle::Get(),
+ public_archive_dir_path(), download_manager.get(),
+ base::BindOnce(&OfflinePageArchiverTest::PublishArchiveDone,
+ get_weak_ptr(), save_page_callback));
+ PumpLoop();
+
+ EXPECT_EQ(SavePageResult::SUCCESS, publish_archive_result().move_result);
+ EXPECT_EQ(kDownloadId, publish_archive_result().download_id);
+ // Check there is a file in the new location.
+ EXPECT_TRUE(public_archive_dir_path().IsParent(
+ publish_archive_result().new_file_path));
+ EXPECT_TRUE(base::PathExists(publish_archive_result().new_file_path));
+ // Check there is no longer a file in the old location.
+ EXPECT_FALSE(base::PathExists(old_file_path));
+}
+
+// TODO(petewil): Add test cases for move failed, and adding to ADM failed.
+
+} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/offline_page_client_policy.h b/chromium/components/offline_pages/core/offline_page_client_policy.h
index 07e800c9e4f..33e8a2381fb 100644
--- a/chromium/components/offline_pages/core/offline_page_client_policy.h
+++ b/chromium/components/offline_pages/core/offline_page_client_policy.h
@@ -49,6 +49,8 @@ struct LifetimePolicy {
struct FeaturePolicy {
// Whether pages are shown in download ui.
bool is_supported_by_download;
+ // Whether a download was initiated in response to user action.
+ bool is_user_requested_download;
// Whether pages are shown in recent tabs ui.
bool is_supported_by_recent_tabs;
// Whether pages should only be viewed in the tab they were generated in.
@@ -60,14 +62,18 @@ struct FeaturePolicy {
bool disabled_when_prefetch_disabled;
// Whether the pages originated from suggestions by zine or elsewhere.
bool is_suggested;
+ // whether we should allow pages to trigger downloads.
+ bool should_allow_download;
FeaturePolicy()
: is_supported_by_download(false),
+ is_user_requested_download(false),
is_supported_by_recent_tabs(false),
only_shown_in_original_tab(false),
is_removed_on_cache_reset(true),
disabled_when_prefetch_disabled(false),
- is_suggested(false) {}
+ is_suggested(false),
+ should_allow_download(false) {}
};
// The struct describing policies for various namespaces (Bookmark, Last-N etc.)
@@ -132,6 +138,13 @@ class OfflinePageClientPolicyBuilder {
return *this;
}
+ OfflinePageClientPolicyBuilder& SetIsUserRequestedDownload(
+ const bool is_user_requested_download) {
+ policy_.feature_policy.is_user_requested_download =
+ is_user_requested_download;
+ return *this;
+ }
+
OfflinePageClientPolicyBuilder& SetIsSupportedByRecentTabs(
const bool is_recent_tabs) {
policy_.feature_policy.is_supported_by_recent_tabs = is_recent_tabs;
@@ -163,6 +176,12 @@ class OfflinePageClientPolicyBuilder {
return *this;
}
+ OfflinePageClientPolicyBuilder& SetShouldAllowDownload(
+ const bool should_allow_download) {
+ policy_.feature_policy.should_allow_download = should_allow_download;
+ return *this;
+ }
+
private:
OfflinePageClientPolicy policy_;
diff --git a/chromium/components/offline_pages/core/offline_page_metadata_store_sql.h b/chromium/components/offline_pages/core/offline_page_metadata_store_sql.h
index 3b7dadd8373..4cfc96c82a2 100644
--- a/chromium/components/offline_pages/core/offline_page_metadata_store_sql.h
+++ b/chromium/components/offline_pages/core/offline_page_metadata_store_sql.h
@@ -123,9 +123,9 @@ class OfflinePageMetadataStoreSQL : public OfflinePageMetadataStore {
return;
}
- TRACE_EVENT_ASYNC_BEGIN1("offline_pages",
- "Metadata Store: Command execution", this,
- "is store loaded", state_ == StoreState::LOADED);
+ TRACE_EVENT_ASYNC_BEGIN1("offline_pages", "Metadata Store: task execution",
+ this, "is store loaded",
+ state_ == StoreState::LOADED);
// This if allows to run commands later, after store was given a chance to
// initialize. They would be failing immediately otherwise.
if (state_ == StoreState::INITIALIZING) {
@@ -133,9 +133,8 @@ class OfflinePageMetadataStoreSQL : public OfflinePageMetadataStore {
base::BindOnce(&OfflinePageMetadataStoreSQL::Execute<T>,
weak_ptr_factory_.GetWeakPtr(),
std::move(run_callback), std::move(result_callback)));
- TRACE_EVENT_ASYNC_END1("offline_pages",
- "Metadata Store: Command execution", this,
- "postponed", true);
+ TRACE_EVENT_ASYNC_END1("offline_pages", "Metadata Store: task execution",
+ this, "postponed", true);
return;
}
@@ -172,10 +171,16 @@ class OfflinePageMetadataStoreSQL : public OfflinePageMetadataStore {
base::BindOnce(&OfflinePageMetadataStoreSQL::CloseInternal,
closing_weak_ptr_factory_.GetWeakPtr()),
kClosingDelay);
- TRACE_EVENT_ASYNC_END0("offline_pages", "Metadata Store: Command execution",
- this);
+ // Note: the time recorded for this trace step will include thread hop wait
+ // times to the background thread and back.
+ TRACE_EVENT_ASYNC_STEP_PAST0(
+ "offline_pages", "Metadata Store: task execution", this, "Task");
std::move(result_callback).Run(std::move(result));
+ TRACE_EVENT_ASYNC_STEP_PAST0(
+ "offline_pages", "Metadata Store: task execution", this, "Callback");
+ TRACE_EVENT_ASYNC_END0("offline_pages", "Metadata Store: task execution",
+ this);
}
// Internal function initiating the closing.
diff --git a/chromium/components/offline_pages/core/offline_page_model.cc b/chromium/components/offline_pages/core/offline_page_model.cc
index e9a810f3184..08d81b29367 100644
--- a/chromium/components/offline_pages/core/offline_page_model.cc
+++ b/chromium/components/offline_pages/core/offline_page_model.cc
@@ -25,9 +25,11 @@ OfflinePageModel::DeletedPageInfo::DeletedPageInfo(
OfflinePageModel::DeletedPageInfo::~DeletedPageInfo() = default;
OfflinePageModel::DeletedPageInfo::DeletedPageInfo(
int64_t offline_id,
+ int64_t system_download_id,
const ClientId& client_id,
const std::string& request_origin)
: offline_id(offline_id),
+ system_download_id(system_download_id),
client_id(client_id),
request_origin(request_origin) {}
diff --git a/chromium/components/offline_pages/core/offline_page_model.h b/chromium/components/offline_pages/core/offline_page_model.h
index d50ee959fd1..37a73d0ca5e 100644
--- a/chromium/components/offline_pages/core/offline_page_model.h
+++ b/chromium/components/offline_pages/core/offline_page_model.h
@@ -14,10 +14,9 @@
#include "base/supports_user_data.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "components/offline_pages/core/client_policy_controller.h"
#include "components/offline_pages/core/offline_event_logger.h"
#include "components/offline_pages/core/offline_page_archiver.h"
-#include "components/offline_pages/core/offline_page_model_query.h"
-#include "components/offline_pages/core/offline_page_storage_manager.h"
#include "components/offline_pages/core/offline_page_types.h"
class GURL;
@@ -80,10 +79,14 @@ class OfflinePageModel : public base::SupportsUserData, public KeyedService {
DeletedPageInfo(const DeletedPageInfo& other);
~DeletedPageInfo();
DeletedPageInfo(int64_t offline_id,
+ int64_t system_download_id,
const ClientId& client_id,
const std::string& request_origin);
// The ID of the deleted page.
int64_t offline_id;
+ // The system download manager id of the deleted page. This will be 0 if
+ // there is no system download manager assigned id.
+ int64_t system_download_id;
// Client ID of the deleted page.
ClientId client_id;
// The origin that the page was saved on behalf of.
@@ -147,6 +150,13 @@ class OfflinePageModel : public base::SupportsUserData, public KeyedService {
virtual void DeletePagesByClientIds(const std::vector<ClientId>& client_ids,
const DeletePageCallback& callback) = 0;
+ // Deletes all pages associated with any of the |client_ids| provided the page
+ // also was created by origin.
+ virtual void DeletePagesByClientIdsAndOrigin(
+ const std::vector<ClientId>& client_ids,
+ const std::string& origin,
+ const DeletePageCallback& callback) = 0;
+
// Deletes cached offline pages matching the URL predicate.
virtual void DeleteCachedPagesByURLPredicate(
const UrlPredicate& predicate,
@@ -190,6 +200,12 @@ class OfflinePageModel : public base::SupportsUserData, public KeyedService {
const std::string& request_origin,
const MultipleOfflinePageItemCallback& callback) = 0;
+ // Returns zero or one offline pages associated with a specified |digest|.
+ virtual void GetPageBySizeAndDigest(
+ int64_t file_size,
+ const std::string& digest,
+ const SingleOfflinePageItemCallback& callback) = 0;
+
// Gets all offline ids where the offline page has the matching client id.
virtual void GetOfflineIdsForClientId(
const ClientId& client_id,
diff --git a/chromium/components/offline_pages/core/offline_page_model_impl.cc b/chromium/components/offline_pages/core/offline_page_model_impl.cc
deleted file mode 100644
index b71d1c72520..00000000000
--- a/chromium/components/offline_pages/core/offline_page_model_impl.cc
+++ /dev/null
@@ -1,1189 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/offline_pages/core/offline_page_model_impl.h"
-
-#include <algorithm>
-#include <limits>
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/rand_util.h"
-#include "base/sequenced_task_runner.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/clock.h"
-#include "base/time/time.h"
-#include "components/offline_pages/core/archive_manager.h"
-#include "components/offline_pages/core/client_namespace_constants.h"
-#include "components/offline_pages/core/client_policy_controller.h"
-#include "components/offline_pages/core/offline_page_item.h"
-#include "components/offline_pages/core/offline_page_model_query.h"
-#include "components/offline_pages/core/offline_page_storage_manager.h"
-#include "url/gurl.h"
-
-using ArchiverResult = offline_pages::OfflinePageArchiver::ArchiverResult;
-using ClearStorageCallback =
- offline_pages::OfflinePageStorageManager::ClearStorageCallback;
-using ClearStorageResult =
- offline_pages::OfflinePageStorageManager::ClearStorageResult;
-
-namespace offline_pages {
-
-namespace {
-
-// The delay used to schedule the first clear storage request for storage
-// manager after the model is loaded.
-const base::TimeDelta kStorageManagerStartingDelay =
- base::TimeDelta::FromSeconds(20);
-
-// Number of times to try to initialize the underlying database.
-// TODO(dimich): Replace with a schema that eventually obliterates the database
-// if it has permanent damage. Note this DB contains data saved by user, so
-// need to be gentle.
-const int kInitializeAttemptsMax = 3;
-
-int64_t GenerateOfflineId() {
- return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1;
-}
-
-// The maximum histogram size for the metrics that measure time between views of
-// a given page.
-const base::TimeDelta kMaxOpenedPageHistogramBucket =
- base::TimeDelta::FromDays(90);
-
-SavePageResult ToSavePageResult(ArchiverResult archiver_result) {
- SavePageResult result;
- switch (archiver_result) {
- case ArchiverResult::SUCCESSFULLY_CREATED:
- result = SavePageResult::SUCCESS;
- break;
- case ArchiverResult::ERROR_DEVICE_FULL:
- result = SavePageResult::DEVICE_FULL;
- break;
- case ArchiverResult::ERROR_CONTENT_UNAVAILABLE:
- result = SavePageResult::CONTENT_UNAVAILABLE;
- break;
- case ArchiverResult::ERROR_ARCHIVE_CREATION_FAILED:
- result = SavePageResult::ARCHIVE_CREATION_FAILED;
- break;
- case ArchiverResult::ERROR_CANCELED:
- result = SavePageResult::CANCELLED;
- break;
- case ArchiverResult::ERROR_SECURITY_CERTIFICATE:
- result = SavePageResult::SECURITY_CERTIFICATE_ERROR;
- break;
- case ArchiverResult::ERROR_ERROR_PAGE:
- result = SavePageResult::ERROR_PAGE;
- break;
- case ArchiverResult::ERROR_INTERSTITIAL_PAGE:
- result = SavePageResult::INTERSTITIAL_PAGE;
- break;
- case ArchiverResult::ERROR_DIGEST_CALCULATION_FAILED:
- result = SavePageResult::DIGEST_CALCULATION_FAILED;
- break;
- default:
- NOTREACHED();
- result = SavePageResult::CONTENT_UNAVAILABLE;
- }
- return result;
-}
-
-// TODO(carlosk): Canonicalize this suffix adding logic which is already
-// duplicated in many different places around the codebase.
-std::string AddHistogramSuffix(const ClientId& client_id,
- const char* histogram_name) {
- if (client_id.name_space.empty()) {
- NOTREACHED();
- return histogram_name;
- }
- std::string adjusted_histogram_name(histogram_name);
- adjusted_histogram_name += ".";
- adjusted_histogram_name += client_id.name_space;
- return adjusted_histogram_name;
-}
-
-void ReportStorageHistogramsAfterSave(
- const ArchiveManager::StorageStats& storage_stats) {
- const int kMB = 1024 * 1024;
- int free_disk_space_mb =
- static_cast<int>(storage_stats.free_disk_space / kMB);
- UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.SavePage.FreeSpaceMB",
- free_disk_space_mb, 1, 500000, 50);
-
- int total_page_size_mb =
- static_cast<int>(storage_stats.total_archives_size() / kMB);
- UMA_HISTOGRAM_COUNTS_10000("OfflinePages.TotalPageSize", total_page_size_mb);
-}
-
-void ReportStorageHistogramsAfterDelete(
- const ArchiveManager::StorageStats& storage_stats) {
- const int kMB = 1024 * 1024;
- int free_disk_space_mb =
- static_cast<int>(storage_stats.free_disk_space / kMB);
- UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.DeletePage.FreeSpaceMB",
- free_disk_space_mb, 1, 500000, 50);
-
- int total_page_size_mb =
- static_cast<int>(storage_stats.total_archives_size() / kMB);
- UMA_HISTOGRAM_COUNTS_10000("OfflinePages.TotalPageSize", total_page_size_mb);
-
- if (storage_stats.free_disk_space > 0) {
- int percentage_of_free = static_cast<int>(
- 1.0 * storage_stats.total_archives_size() /
- (storage_stats.total_archives_size() + storage_stats.free_disk_space) *
- 100);
- UMA_HISTOGRAM_PERCENTAGE(
- "OfflinePages.DeletePage.TotalPageSizeAsPercentageOfFreeSpace",
- percentage_of_free);
- }
-}
-
-void ReportSavePageResultHistogramAfterSave(const ClientId& client_id,
- SavePageResult result) {
- // The histogram below is an expansion of the UMA_HISTOGRAM_ENUMERATION
- // macro adapted to allow for a dynamically suffixed histogram name.
- // Note: The factory creates and owns the histogram.
- base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
- AddHistogramSuffix(client_id, "OfflinePages.SavePageResult"), 1,
- static_cast<int>(SavePageResult::RESULT_COUNT),
- static_cast<int>(SavePageResult::RESULT_COUNT) + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(static_cast<int>(result));
-}
-
-// Goes through the list of offline pages, compiling the following two metrics:
-// - a count of the pages with the same URL
-// - The difference between the |created_before| time and the creation time of
-// the page with the closest creation time before |created_before|.
-// Returns true if there was a page that was saved before |created_before| with
-// a matching URL.
-bool GetMatchingURLCountAndMostRecentCreationTime(
- const std::map<int64_t, OfflinePageItem>& offline_pages,
- std::string name_space,
- const GURL& url,
- base::Time created_before,
- int* matching_url_count,
- base::TimeDelta* most_recent_creation_time) {
- int count = 0;
-
- // Create a time that is very old, so that any valid time will be newer than
- // it.
- base::Time latest_time;
- bool matching_page = false;
-
- for (auto& id_page_pair : offline_pages) {
- if (id_page_pair.second.client_id.name_space == name_space &&
- url == id_page_pair.second.url) {
- count++;
- base::Time page_creation_time = id_page_pair.second.creation_time;
- if (page_creation_time < created_before &&
- page_creation_time > latest_time) {
- latest_time = page_creation_time;
- matching_page = true;
- }
- }
- }
-
- if (matching_url_count != nullptr)
- *matching_url_count = count;
- if (most_recent_creation_time != nullptr && latest_time != base::Time())
- *most_recent_creation_time = created_before - latest_time;
-
- return matching_page;
-}
-
-void ReportPageHistogramAfterSave(
- ClientPolicyController* policy_controller_,
- const std::map<int64_t, OfflinePageItem>& offline_pages,
- const OfflinePageItem& offline_page,
- const base::Time& save_time) {
- DCHECK(policy_controller_);
- // The histogram below is an expansion of the UMA_HISTOGRAM_TIMES
- // macro adapted to allow for a dynamically suffixed histogram name.
- // Note: The factory creates and owns the histogram.
- base::HistogramBase* histogram = base::Histogram::FactoryTimeGet(
- AddHistogramSuffix(offline_page.client_id, "OfflinePages.SavePageTime"),
- base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromSeconds(10),
- 50, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->AddTime(save_time - offline_page.creation_time);
-
- // The histogram below is an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS
- // macro adapted to allow for a dynamically suffixed histogram name.
- // Note: The factory creates and owns the histogram.
- // Reported as Kb between 1Kb and 10Mb.
- histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(offline_page.client_id, "OfflinePages.PageSize"), 1,
- 10000, 50, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(offline_page.file_size / 1024);
-
- if (policy_controller_->IsSupportedByDownload(
- offline_page.client_id.name_space)) {
- int matching_url_count;
- base::TimeDelta time_since_most_recent_duplicate;
- if (GetMatchingURLCountAndMostRecentCreationTime(
- offline_pages, offline_page.client_id.name_space, offline_page.url,
- offline_page.creation_time, &matching_url_count,
- &time_since_most_recent_duplicate)) {
- // Using CUSTOM_COUNTS instead of time-oriented histogram to record
- // samples in seconds rather than milliseconds.
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "OfflinePages.DownloadSavedPageTimeSinceDuplicateSaved",
- time_since_most_recent_duplicate.InSeconds(),
- base::TimeDelta::FromSeconds(1).InSeconds(),
- base::TimeDelta::FromDays(7).InSeconds(), 50);
- }
- UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.DownloadSavedPageDuplicateCount",
- matching_url_count, 1, 20, 10);
- }
-}
-
-void ReportPageHistogramsAfterDelete(
- const std::map<int64_t, OfflinePageItem>& offline_pages,
- const std::vector<OfflinePageItem>& deleted_pages,
- const base::Time& delete_time) {
- const int max_minutes = base::TimeDelta::FromDays(365).InMinutes();
- int64_t total_size = 0;
-
- for (const auto& page : deleted_pages) {
- total_size += page.file_size;
- ClientId client_id = page.client_id;
-
- if (client_id.name_space == kDownloadNamespace) {
- int remaining_pages_with_url;
- GetMatchingURLCountAndMostRecentCreationTime(
- offline_pages, page.client_id.name_space, page.url, base::Time::Max(),
- &remaining_pages_with_url, nullptr);
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "OfflinePages.DownloadDeletedPageDuplicateCount",
- remaining_pages_with_url, 1, 20, 10);
- }
-
- // The histograms below are an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS
- // macro adapted to allow for a dynamically suffixed histogram name.
- // Note: The factory creates and owns the histogram.
- base::HistogramBase* histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(client_id, "OfflinePages.PageLifetime"), 1,
- max_minutes, 100, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add((delete_time - page.creation_time).InMinutes());
-
- histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(client_id,
- "OfflinePages.DeletePage.TimeSinceLastOpen"),
- 1, max_minutes, 100, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add((delete_time - page.last_access_time).InMinutes());
-
- histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(client_id,
- "OfflinePages.DeletePage.LastOpenToCreated"),
- 1, max_minutes, 100, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add((page.last_access_time - page.creation_time).InMinutes());
-
- // Reported as Kb between 1Kb and 10Mb.
- histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(client_id, "OfflinePages.DeletePage.PageSize"), 1,
- 10000, 50, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(page.file_size / 1024);
-
- histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(client_id, "OfflinePages.DeletePage.AccessCount"), 1,
- 1000000, 50, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(page.access_count);
- }
-
- if (deleted_pages.size() > 1) {
- UMA_HISTOGRAM_COUNTS("OfflinePages.BatchDelete.Count",
- static_cast<int32_t>(deleted_pages.size()));
- UMA_HISTOGRAM_MEMORY_KB("OfflinePages.BatchDelete.TotalPageSize",
- total_size / 1024);
- }
-}
-
-void ReportPageHistogramsAfterAccess(const OfflinePageItem& offline_page_item,
- const base::Time& access_time) {
- // The histogram below is an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS
- // macro adapted to allow for a dynamically suffixed histogram name.
- // Note: The factory creates and owns the histogram.
- base::HistogramBase* histogram = base::Histogram::FactoryGet(
- AddHistogramSuffix(offline_page_item.client_id,
- offline_page_item.access_count == 0
- ? "OfflinePages.FirstOpenSinceCreated"
- : "OfflinePages.OpenSinceLastOpen"),
- 1, kMaxOpenedPageHistogramBucket.InMinutes(), 50,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(
- (access_time - offline_page_item.last_access_time).InMinutes());
-}
-
-void ReportInitializationAttemptsSpent(int attempts_spent) {
- UMA_HISTOGRAM_EXACT_LINEAR("OfflinePages.Model.InitAttemptsSpent",
- attempts_spent, kInitializeAttemptsMax);
-}
-
-} // namespace
-
-// protected
-OfflinePageModelImpl::OfflinePageModelImpl()
- : OfflinePageModel(),
- is_loaded_(false),
- testing_clock_(nullptr),
- skip_clearing_original_url_for_testing_(false),
- weak_ptr_factory_(this) {}
-
-OfflinePageModelImpl::OfflinePageModelImpl(
- std::unique_ptr<OfflinePageMetadataStore> store,
- std::unique_ptr<ArchiveManager> archive_manager,
- const scoped_refptr<base::SequencedTaskRunner>& task_runner)
- : store_(std::move(store)),
- is_loaded_(false),
- policy_controller_(new ClientPolicyController()),
- archive_manager_(std::move(archive_manager)),
- testing_clock_(nullptr),
- skip_clearing_original_url_for_testing_(false),
- weak_ptr_factory_(this) {
- archive_manager_->EnsureArchivesDirCreated(
- base::Bind(&OfflinePageModelImpl::OnEnsureArchivesDirCreatedDone,
- weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()));
-}
-
-OfflinePageModelImpl::~OfflinePageModelImpl() {}
-
-void OfflinePageModelImpl::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
-
-void OfflinePageModelImpl::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
-
-void OfflinePageModelImpl::SavePage(
- const SavePageParams& save_page_params,
- std::unique_ptr<OfflinePageArchiver> archiver,
- const SavePageCallback& callback) {
- DCHECK(is_loaded_);
-
- // Skip saving the page that is not intended to be saved, like local file
- // page.
- if (!OfflinePageModel::CanSaveURL(save_page_params.url)) {
- InformSavePageDone(callback, SavePageResult::SKIPPED,
- save_page_params.client_id, kInvalidOfflineId);
- return;
- }
-
- // The web contents is not available if archiver is not created and passed.
- if (!archiver.get()) {
- InformSavePageDone(callback, SavePageResult::CONTENT_UNAVAILABLE,
- save_page_params.client_id, kInvalidOfflineId);
- return;
- }
-
- // If we already have an offline id, use it. If not, generate one.
- int64_t offline_id = save_page_params.proposed_offline_id;
- if (offline_id == kInvalidOfflineId)
- offline_id = GenerateOfflineId();
-
- OfflinePageArchiver::CreateArchiveParams create_archive_params;
- // If the page is being saved in the background, we should try to remove the
- // popup overlay that obstructs viewing the normal content.
- create_archive_params.remove_popup_overlay = save_page_params.is_background;
- create_archive_params.use_page_problem_detectors =
- save_page_params.use_page_problem_detectors;
- archiver->CreateArchive(
- GetInternalArchiveDirectory(save_page_params.client_id.name_space),
- create_archive_params,
- base::Bind(&OfflinePageModelImpl::OnCreateArchiveDone,
- weak_ptr_factory_.GetWeakPtr(), save_page_params, offline_id,
- GetCurrentTime(), callback));
- pending_archivers_.push_back(std::move(archiver));
-}
-
-void OfflinePageModelImpl::AddPage(const OfflinePageItem& page,
- const AddPageCallback& callback) {
- RunWhenLoaded(base::Bind(&OfflinePageModelImpl::AddPageWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(), page, callback));
-}
-
-void OfflinePageModelImpl::AddPageWhenLoadDone(
- const OfflinePageItem& page,
- const AddPageCallback& callback) {
- store_->AddOfflinePage(
- page, base::Bind(&OfflinePageModelImpl::OnAddPageDone,
- weak_ptr_factory_.GetWeakPtr(), page, callback));
-}
-
-void OfflinePageModelImpl::MarkPageAccessed(int64_t offline_id) {
- RunWhenLoaded(base::Bind(&OfflinePageModelImpl::MarkPageAccessedWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(), offline_id));
-}
-
-void OfflinePageModelImpl::MarkPageAccessedWhenLoadDone(int64_t offline_id) {
- DCHECK(is_loaded_);
-
- auto iter = offline_pages_.find(offline_id);
- if (iter == offline_pages_.end())
- return;
-
- // Make a copy of the cached item and update it. The cached item should only
- // be updated upon the successful store operation.
- OfflinePageItem offline_page_item = iter->second;
-
- ReportPageHistogramsAfterAccess(offline_page_item, GetCurrentTime());
-
- offline_page_item.last_access_time = GetCurrentTime();
- offline_page_item.access_count++;
-
- std::vector<OfflinePageItem> items = {offline_page_item};
- store_->UpdateOfflinePages(
- items, base::Bind(&OfflinePageModelImpl::OnMarkPageAccesseDone,
- weak_ptr_factory_.GetWeakPtr(), offline_page_item));
-}
-
-void OfflinePageModelImpl::DeletePagesByOfflineId(
- const std::vector<int64_t>& offline_ids,
- const DeletePageCallback& callback) {
- RunWhenLoaded(base::Bind(&OfflinePageModelImpl::DoDeletePagesByOfflineId,
- weak_ptr_factory_.GetWeakPtr(), offline_ids,
- callback));
-}
-
-void OfflinePageModelImpl::DoDeletePagesByOfflineId(
- const std::vector<int64_t>& offline_ids,
- const DeletePageCallback& callback) {
- DCHECK(is_loaded_);
-
- std::vector<base::FilePath> paths_to_delete;
- for (const auto& offline_id : offline_ids) {
- auto iter = offline_pages_.find(offline_id);
- if (iter != offline_pages_.end()) {
- paths_to_delete.push_back(iter->second.file_path);
- }
- }
-
- // If there're no pages to delete, return early.
- if (paths_to_delete.empty()) {
- InformDeletePageDone(callback, DeletePageResult::SUCCESS);
- return;
- }
-
- archive_manager_->DeleteMultipleArchives(
- paths_to_delete,
- base::Bind(&OfflinePageModelImpl::OnDeleteArchiveFilesDone,
- weak_ptr_factory_.GetWeakPtr(), offline_ids, callback));
-}
-
-void OfflinePageModelImpl::DeletePagesByClientIds(
- const std::vector<ClientId>& client_ids,
- const DeletePageCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- builder.SetClientIds(OfflinePageModelQuery::Requirement::INCLUDE_MATCHING,
- client_ids);
- auto delete_pages = base::Bind(&OfflinePageModelImpl::DeletePages,
- weak_ptr_factory_.GetWeakPtr(), callback);
- RunWhenLoaded(base::Bind(
- &OfflinePageModelImpl::GetPagesMatchingQueryWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())), delete_pages));
-}
-
-void OfflinePageModelImpl::DeletePages(
- const DeletePageCallback& callback,
- const MultipleOfflinePageItemResult& pages) {
- DCHECK(is_loaded_);
-
- std::vector<int64_t> offline_ids;
- for (auto& page : pages)
- offline_ids.emplace_back(page.offline_id);
-
- DoDeletePagesByOfflineId(offline_ids, callback);
-}
-
-void OfflinePageModelImpl::GetPagesMatchingQueryWhenLoadDone(
- std::unique_ptr<OfflinePageModelQuery> query,
- const MultipleOfflinePageItemCallback& callback) {
- DCHECK(query);
- DCHECK(is_loaded_);
-
- MultipleOfflinePageItemResult offline_pages_result;
-
- for (const auto& id_page_pair : offline_pages_) {
- if (query->Matches(id_page_pair.second))
- offline_pages_result.emplace_back(id_page_pair.second);
- }
-
- callback.Run(offline_pages_result);
-}
-
-void OfflinePageModelImpl::GetPagesByClientIds(
- const std::vector<ClientId>& client_ids,
- const MultipleOfflinePageItemCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- builder.SetClientIds(OfflinePageModelQuery::Requirement::INCLUDE_MATCHING,
- client_ids);
- RunWhenLoaded(
- base::Bind(&OfflinePageModelImpl::GetPagesMatchingQueryWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())), callback));
-}
-
-void OfflinePageModelImpl::GetPagesByRequestOrigin(
- const std::string& request_origin,
- const MultipleOfflinePageItemCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- builder.SetRequestOrigin(OfflinePageModelQuery::Requirement::INCLUDE_MATCHING,
- request_origin);
- RunWhenLoaded(
- base::Bind(&OfflinePageModelImpl::GetPagesMatchingQueryWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())), callback));
-}
-
-void OfflinePageModelImpl::DeleteCachedPagesByURLPredicate(
- const UrlPredicate& predicate,
- const DeletePageCallback& callback) {
- RunWhenLoaded(
- base::Bind(&OfflinePageModelImpl::DoDeleteCachedPagesByURLPredicate,
- weak_ptr_factory_.GetWeakPtr(), predicate, callback));
-}
-
-void OfflinePageModelImpl::DoDeleteCachedPagesByURLPredicate(
- const UrlPredicate& predicate,
- const DeletePageCallback& callback) {
- DCHECK(is_loaded_);
-
- std::vector<int64_t> offline_ids;
- for (const auto& id_page_pair : offline_pages_) {
- if (policy_controller_->IsRemovedOnCacheReset(
- id_page_pair.second.client_id.name_space) &&
- predicate.Run(id_page_pair.second.url)) {
- offline_ids.push_back(id_page_pair.first);
- }
- }
- DoDeletePagesByOfflineId(offline_ids, callback);
-}
-
-void OfflinePageModelImpl::GetAllPages(
- const MultipleOfflinePageItemCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- RunWhenLoaded(
- base::Bind(&OfflinePageModelImpl::GetPagesMatchingQueryWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())), callback));
-}
-
-void OfflinePageModelImpl::GetOfflineIdsForClientId(
- const ClientId& client_id,
- const MultipleOfflineIdCallback& callback) {
- RunWhenLoaded(
- base::Bind(&OfflinePageModelImpl::GetOfflineIdsForClientIdWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(), client_id, callback));
-}
-
-void OfflinePageModelImpl::GetOfflineIdsForClientIdWhenLoadDone(
- const ClientId& client_id,
- const MultipleOfflineIdCallback& callback) const {
- DCHECK(is_loaded_);
- callback.Run(MaybeGetOfflineIdsForClientId(client_id));
-}
-
-const std::vector<int64_t> OfflinePageModelImpl::MaybeGetOfflineIdsForClientId(
- const ClientId& client_id) const {
- DCHECK(is_loaded_);
- std::vector<int64_t> results;
-
- // We want only all pages, including those marked for deletion.
- for (const auto& id_page_pair : offline_pages_) {
- if (id_page_pair.second.client_id == client_id)
- results.push_back(id_page_pair.second.offline_id);
- }
- return results;
-}
-
-void OfflinePageModelImpl::GetPageByOfflineId(
- int64_t offline_id,
- const SingleOfflinePageItemCallback& callback) {
- std::vector<int64_t> query_ids;
- query_ids.emplace_back(offline_id);
-
- OfflinePageModelQueryBuilder builder;
- builder.SetOfflinePageIds(
- OfflinePageModelQuery::Requirement::INCLUDE_MATCHING, query_ids);
-
- auto multiple_callback = base::Bind(
- [](const SingleOfflinePageItemCallback& callback,
- const MultipleOfflinePageItemResult& result) {
- DCHECK_LE(result.size(), 1U);
- if (result.empty()) {
- callback.Run(nullptr);
- } else {
- callback.Run(&result[0]);
- }
- },
- callback);
-
- RunWhenLoaded(base::Bind(
- &OfflinePageModelImpl::GetPagesMatchingQueryWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())), multiple_callback));
-}
-
-void OfflinePageModelImpl::GetPagesByURL(
- const GURL& url,
- URLSearchMode url_search_mode,
- const MultipleOfflinePageItemCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- builder.SetUrls(OfflinePageModelQuery::Requirement::INCLUDE_MATCHING,
- std::vector<GURL>({url}), url_search_mode,
- true /* strip_fragment */);
- RunWhenLoaded(
- base::Bind(&OfflinePageModelImpl::GetPagesMatchingQueryWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())), callback));
-}
-
-void OfflinePageModelImpl::GetPagesRemovedOnCacheReset(
- const MultipleOfflinePageItemCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- builder.RequireRemovedOnCacheReset(
- OfflinePageModelQuery::Requirement::INCLUDE_MATCHING);
- RunWhenLoaded(
- base::Bind(&OfflinePageModelImpl::GetPagesMatchingQueryWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())), callback));
-}
-
-void OfflinePageModelImpl::GetPagesByNamespace(
- const std::string& name_space,
- const MultipleOfflinePageItemCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- builder.RequireNamespace(name_space);
- RunWhenLoaded(
- base::Bind(&OfflinePageModelImpl::GetPagesMatchingQueryWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())), callback));
-}
-
-void OfflinePageModelImpl::GetPagesSupportedByDownloads(
- const MultipleOfflinePageItemCallback& callback) {
- OfflinePageModelQueryBuilder builder;
- builder.RequireSupportedByDownload(
- OfflinePageModelQuery::Requirement::INCLUDE_MATCHING);
- RunWhenLoaded(
- base::Bind(&OfflinePageModelImpl::GetPagesMatchingQueryWhenLoadDone,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(builder.Build(GetPolicyController())), callback));
-}
-
-const base::FilePath& OfflinePageModelImpl::GetInternalArchiveDirectory(
- const std::string& name_space) const {
- if (policy_controller_->IsRemovedOnCacheReset(name_space))
- return archive_manager_->GetTemporaryArchivesDir();
- return archive_manager_->GetPrivateArchivesDir();
-}
-
-bool OfflinePageModelImpl::IsArchiveInInternalDir(
- const base::FilePath& file_path) const {
- DCHECK(!file_path.empty());
-
- // TODO(jianli): Update this once persistent archives are moved into the
- // public directory.
- return archive_manager_->GetTemporaryArchivesDir().IsParent(file_path) ||
- archive_manager_->GetPrivateArchivesDir().IsParent(file_path);
-}
-
-void OfflinePageModelImpl::CheckMetadataConsistency() {
- DCHECK(is_loaded_);
-
- // Avoid consistency check if disk store couldn't load.
- if (store_->state() != StoreState::LOADED)
- return;
-
- archive_manager_->GetAllArchives(
- base::Bind(&OfflinePageModelImpl::CheckMetadataConsistencyForArchivePaths,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-ClientPolicyController* OfflinePageModelImpl::GetPolicyController() {
- return policy_controller_.get();
-}
-
-OfflinePageMetadataStore* OfflinePageModelImpl::GetStoreForTesting() {
- return store_.get();
-}
-
-OfflinePageStorageManager* OfflinePageModelImpl::GetStorageManager() {
- return storage_manager_.get();
-}
-
-OfflineEventLogger* OfflinePageModelImpl::GetLogger() {
- return &offline_event_logger_;
-}
-
-void OfflinePageModelImpl::OnCreateArchiveDone(
- const SavePageParams& save_page_params,
- int64_t offline_id,
- const base::Time& start_time,
- const SavePageCallback& callback,
- OfflinePageArchiver* archiver,
- ArchiverResult archiver_result,
- const GURL& saved_url,
- const base::FilePath& file_path,
- const base::string16& title,
- int64_t file_size,
- const std::string& file_hash) {
- DeletePendingArchiver(archiver);
-
- if (archiver_result != ArchiverResult::SUCCESSFULLY_CREATED) {
- SavePageResult result = ToSavePageResult(archiver_result);
- InformSavePageDone(
- callback, result, save_page_params.client_id, offline_id);
- return;
- }
-
- if (save_page_params.url != saved_url) {
- DVLOG(1) << "Saved URL does not match requested URL.";
- InformSavePageDone(callback, SavePageResult::ARCHIVE_CREATION_FAILED,
- save_page_params.client_id, offline_id);
- return;
- }
-
- OfflinePageItem offline_page(saved_url, offline_id,
- save_page_params.client_id, file_path, file_size,
- start_time);
- offline_page.title = title;
- // Don't record the original URL if it is identical to the final URL. This is
- // because some websites might route the redirect finally back to itself upon
- // the completion of certain action, i.e., authentication, in the middle.
- if (skip_clearing_original_url_for_testing_ ||
- save_page_params.original_url != offline_page.url) {
- offline_page.original_url = save_page_params.original_url;
- }
- offline_page.request_origin = save_page_params.request_origin;
- AddPageWhenLoadDone(
- offline_page,
- base::Bind(&OfflinePageModelImpl::OnAddSavedPageDone,
- weak_ptr_factory_.GetWeakPtr(), offline_page, callback));
-}
-
-void OfflinePageModelImpl::OnAddPageDone(const OfflinePageItem& offline_page,
- const AddPageCallback& callback,
- ItemActionStatus status) {
- AddPageResult result;
- if (status == ItemActionStatus::SUCCESS) {
- offline_pages_[offline_page.offline_id] = offline_page;
- result = AddPageResult::SUCCESS;
- ReportPageHistogramAfterSave(policy_controller_.get(), offline_pages_,
- offline_page, GetCurrentTime());
- offline_event_logger_.RecordPageSaved(offline_page.client_id.name_space,
- offline_page.url.spec(),
- offline_page.offline_id);
- } else if (status == ItemActionStatus::ALREADY_EXISTS) {
- // Remove the orphaned archive. No callback necessary.
- archive_manager_->DeleteArchive(offline_page.file_path,
- base::Bind([](bool) {}));
- result = AddPageResult::ALREADY_EXISTS;
- } else {
- result = AddPageResult::STORE_FAILURE;
- }
-
- callback.Run(result, offline_page.offline_id);
-
- // We don't want to notify observers if the add failed.
- if (status == ItemActionStatus::SUCCESS) {
- for (Observer& observer : observers_)
- observer.OfflinePageAdded(this, offline_page);
- }
-}
-
-void OfflinePageModelImpl::OnAddSavedPageDone(
- const OfflinePageItem& offline_page,
- const SavePageCallback& callback,
- AddPageResult add_result,
- int64_t offline_id) {
- SavePageResult save_result;
- if (add_result == AddPageResult::SUCCESS) {
- save_result = SavePageResult::SUCCESS;
- } else if (add_result == AddPageResult::ALREADY_EXISTS) {
- save_result = SavePageResult::ALREADY_EXISTS;
- } else if (add_result == AddPageResult::STORE_FAILURE) {
- save_result = SavePageResult::STORE_FAILURE;
- } else {
- NOTREACHED();
- save_result = SavePageResult::STORE_FAILURE;
- }
- InformSavePageDone(callback, save_result, offline_page.client_id, offline_id);
- if (save_result == SavePageResult::SUCCESS) {
- DeleteExistingPagesWithSameURL(offline_page);
- } else {
- PostClearStorageIfNeededTask(false /* delayed */);
- }
-}
-
-void OfflinePageModelImpl::OnMarkPageAccesseDone(
- const OfflinePageItem& offline_page_item,
- std::unique_ptr<OfflinePagesUpdateResult> result) {
- // Update the item in the cache only upon success.
- if (result->updated_items.size() > 0)
- offline_pages_[offline_page_item.offline_id] = offline_page_item;
-
- // No need to fire OfflinePageModelChanged event since updating access info
- // should not have any impact to the UI.
-}
-
-void OfflinePageModelImpl::OnEnsureArchivesDirCreatedDone(
- const base::TimeTicks& start_time) {
- UMA_HISTOGRAM_TIMES("OfflinePages.Model.ArchiveDirCreationTime",
- base::TimeTicks::Now() - start_time);
-
- store_->Initialize(base::Bind(&OfflinePageModelImpl::OnStoreInitialized,
- weak_ptr_factory_.GetWeakPtr(), start_time, 0));
-}
-
-void OfflinePageModelImpl::OnStoreInitialized(const base::TimeTicks& start_time,
- int init_attempts_spent,
- bool success) {
- init_attempts_spent++;
-
- if (success) {
- DCHECK_EQ(store_->state(), StoreState::LOADED);
- ReportInitializationAttemptsSpent(init_attempts_spent);
- store_->GetOfflinePages(
- base::Bind(&OfflinePageModelImpl::OnInitialGetOfflinePagesDone,
- weak_ptr_factory_.GetWeakPtr(), start_time));
- return;
- }
-
- DCHECK_EQ(store_->state(), StoreState::FAILED_LOADING);
- // If there are no more init attempts left, stop here.
- if (init_attempts_spent >= kInitializeAttemptsMax) {
- FinalizeModelLoad();
- return;
- }
-
- // The DB failed to load. If this is a transient condition (locks not
- // yet released etc) chances are that a retry with a delay will succeed.
- const base::TimeDelta delay = base::TimeDelta::FromMilliseconds(100);
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&OfflinePageModelImpl::RetryDbInitialization,
- weak_ptr_factory_.GetWeakPtr(), start_time,
- init_attempts_spent),
- delay);
-}
-
-void OfflinePageModelImpl::RetryDbInitialization(
- const base::TimeTicks& start_time,
- int init_attempts_spent) {
- store_->Initialize(base::Bind(&OfflinePageModelImpl::OnStoreInitialized,
- weak_ptr_factory_.GetWeakPtr(), start_time,
- init_attempts_spent));
-}
-
-void OfflinePageModelImpl::OnInitialGetOfflinePagesDone(
- const base::TimeTicks& start_time,
- std::vector<OfflinePageItem> offline_pages) {
- DCHECK(!is_loaded_);
-
- UMA_HISTOGRAM_TIMES("OfflinePages.Model.ConstructionToLoadedEventTime",
- base::TimeTicks::Now() - start_time);
-
- CacheLoadedData(offline_pages);
- FinalizeModelLoad();
-
- // Ensure necessary cleanup operations are started.
- CheckMetadataConsistency();
-}
-
-void OfflinePageModelImpl::FinalizeModelLoad() {
- is_loaded_ = true;
-
- // All actions below are meant to be taken regardless of successful load of
- // the store.
-
- UMA_HISTOGRAM_BOOLEAN("OfflinePages.Model.FinalLoadSuccessful",
- store_->state() == StoreState::LOADED);
-
- // Inform observers the load is done.
- for (Observer& observer : observers_)
- observer.OfflinePageModelLoaded(this);
-
- // Run all the delayed tasks.
- for (const auto& delayed_task : delayed_tasks_)
- delayed_task.Run();
- delayed_tasks_.clear();
-
- // Clear storage.
- PostClearStorageIfNeededTask(true /* delayed */);
-}
-
-void OfflinePageModelImpl::InformSavePageDone(const SavePageCallback& callback,
- SavePageResult result,
- const ClientId& client_id,
- int64_t offline_id) {
- ReportSavePageResultHistogramAfterSave(client_id, result);
- archive_manager_->GetStorageStats(
- base::Bind(&ReportStorageHistogramsAfterSave));
- // No need to pass in a callback, since if the archive manager fails every
- // time when creating an archive directory, there's nothing else to do other
- // than fail every attempt to save a page.
- if (result == SavePageResult::ARCHIVE_CREATION_FAILED)
- archive_manager_->EnsureArchivesDirCreated(base::Bind([]() {}));
- callback.Run(result, offline_id);
-}
-
-void OfflinePageModelImpl::DeleteExistingPagesWithSameURL(
- const OfflinePageItem& offline_page) {
- // Remove existing pages generated by the same policy and with same url.
- size_t pages_allowed =
- policy_controller_->GetPolicy(offline_page.client_id.name_space)
- .pages_allowed_per_url;
- if (pages_allowed == kUnlimitedPages)
- return;
- GetPagesByURL(
- offline_page.url,
- URLSearchMode::SEARCH_BY_FINAL_URL_ONLY,
- base::Bind(&OfflinePageModelImpl::OnPagesFoundWithSameURL,
- weak_ptr_factory_.GetWeakPtr(), offline_page, pages_allowed));
-}
-
-void OfflinePageModelImpl::OnPagesFoundWithSameURL(
- const OfflinePageItem& offline_page,
- size_t pages_allowed,
- const MultipleOfflinePageItemResult& items) {
- std::vector<OfflinePageItem> pages_to_delete;
- for (const auto& item : items) {
- if (item.offline_id != offline_page.offline_id &&
- item.client_id.name_space == offline_page.client_id.name_space) {
- pages_to_delete.push_back(item);
- }
- }
- // Only keep |pages_allowed|-1 of most fresh pages and delete others, by
- // sorting pages with the oldest ones first and resize the vector.
- if (pages_to_delete.size() >= pages_allowed) {
- sort(pages_to_delete.begin(), pages_to_delete.end(),
- [](const OfflinePageItem& a, const OfflinePageItem& b) -> bool {
- return a.last_access_time < b.last_access_time;
- });
- pages_to_delete.resize(pages_to_delete.size() - pages_allowed + 1);
- }
- std::vector<int64_t> page_ids_to_delete;
- for (const auto& item : pages_to_delete)
- page_ids_to_delete.push_back(item.offline_id);
- DeletePagesByOfflineId(
- page_ids_to_delete,
- base::Bind(&OfflinePageModelImpl::OnDeleteOldPagesWithSameURL,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void OfflinePageModelImpl::OnDeleteOldPagesWithSameURL(
- DeletePageResult result) {
- PostClearStorageIfNeededTask(false /* delayed */);
-}
-
-void OfflinePageModelImpl::DeletePendingArchiver(
- OfflinePageArchiver* archiver) {
- pending_archivers_.erase(
- std::find_if(pending_archivers_.begin(), pending_archivers_.end(),
- [archiver](const std::unique_ptr<OfflinePageArchiver>& a) {
- return a.get() == archiver;
- }));
-}
-
-void OfflinePageModelImpl::OnDeleteArchiveFilesDone(
- const std::vector<int64_t>& offline_ids,
- const DeletePageCallback& callback,
- bool success) {
- if (!success) {
- InformDeletePageDone(callback, DeletePageResult::DEVICE_FAILURE);
- return;
- }
-
- store_->RemoveOfflinePages(
- offline_ids, base::Bind(&OfflinePageModelImpl::OnRemoveOfflinePagesDone,
- weak_ptr_factory_.GetWeakPtr(), callback));
-}
-
-void OfflinePageModelImpl::OnRemoveOfflinePagesDone(
- const DeletePageCallback& callback,
- std::unique_ptr<OfflinePagesUpdateResult> result) {
- ReportPageHistogramsAfterDelete(offline_pages_, result->updated_items,
- GetCurrentTime());
-
- // This part of the loop is explicitly broken out, as it should be gone in
- // fully asynchronous code.
- for (const auto& page : result->updated_items) {
- int64_t offline_id = page.offline_id;
- offline_event_logger_.RecordPageDeleted(offline_id);
- auto iter = offline_pages_.find(offline_id);
- if (iter == offline_pages_.end())
- continue;
- offline_pages_.erase(iter);
- }
-
- for (const auto& page : result->updated_items) {
- DeletedPageInfo info(page.offline_id, page.client_id, page.request_origin);
- for (Observer& observer : observers_)
- observer.OfflinePageDeleted(info);
- }
-
- DeletePageResult delete_result;
- if (result->store_state == StoreState::LOADED)
- delete_result = DeletePageResult::SUCCESS;
- else
- delete_result = DeletePageResult::STORE_FAILURE;
-
- InformDeletePageDone(callback, delete_result);
-}
-
-void OfflinePageModelImpl::InformDeletePageDone(
- const DeletePageCallback& callback,
- DeletePageResult result) {
- UMA_HISTOGRAM_ENUMERATION("OfflinePages.DeletePageResult",
- static_cast<int>(result),
- static_cast<int>(DeletePageResult::RESULT_COUNT));
- archive_manager_->GetStorageStats(
- base::Bind(&ReportStorageHistogramsAfterDelete));
- if (!callback.is_null())
- callback.Run(result);
-}
-
-void OfflinePageModelImpl::CheckMetadataConsistencyForArchivePaths(
- const std::set<base::FilePath>& archive_paths) {
- DeleteTemporaryPagesInAbandonedCacheDir();
- DeletePagesMissingArchiveFile(archive_paths);
- DeleteOrphanedArchives(archive_paths);
-}
-
-void OfflinePageModelImpl::DeleteTemporaryPagesInAbandonedCacheDir() {
- std::vector<int64_t> offline_page_ids;
- for (const auto& id_page_pair : offline_pages_) {
- const OfflinePageItem& page = id_page_pair.second;
- if (policy_controller_->IsRemovedOnCacheReset(page.client_id.name_space) &&
- !archive_manager_->GetTemporaryArchivesDir().IsParent(page.file_path))
- offline_page_ids.push_back(id_page_pair.first);
- }
-
- if (offline_page_ids.empty())
- return;
-
- // This operation fails silently. If it fails, the pages will be deleted
- // during next consistency check.
- DeletePagesByOfflineId(offline_page_ids,
- base::Bind([](const std::vector<int64_t>& offline_ids,
- DeletePageResult result) {},
- offline_page_ids));
-}
-
-void OfflinePageModelImpl::DeletePagesMissingArchiveFile(
- const std::set<base::FilePath>& archive_paths) {
- std::vector<int64_t> ids_of_pages_missing_archive_file;
- for (const auto& id_page_pair : offline_pages_) {
- if (archive_paths.count(id_page_pair.second.file_path) == 0UL)
- ids_of_pages_missing_archive_file.push_back(id_page_pair.first);
- }
-
- if (ids_of_pages_missing_archive_file.empty())
- return;
-
- DeletePagesByOfflineId(
- ids_of_pages_missing_archive_file,
- base::Bind(&OfflinePageModelImpl::OnDeletePagesMissingArchiveFileDone,
- weak_ptr_factory_.GetWeakPtr(),
- ids_of_pages_missing_archive_file));
-}
-
-void OfflinePageModelImpl::OnDeletePagesMissingArchiveFileDone(
- const std::vector<int64_t>& offline_ids,
- DeletePageResult result) {
- UMA_HISTOGRAM_COUNTS("OfflinePages.Consistency.PagesMissingArchiveFileCount",
- static_cast<int32_t>(offline_ids.size()));
- UMA_HISTOGRAM_ENUMERATION(
- "OfflinePages.Consistency.DeletePagesMissingArchiveFileResult",
- static_cast<int>(result),
- static_cast<int>(DeletePageResult::RESULT_COUNT));
-}
-
-void OfflinePageModelImpl::DeleteOrphanedArchives(
- const std::set<base::FilePath>& archive_paths) {
- // Archives are considered orphaned unless they are pointed to by some pages.
- std::set<base::FilePath> orphaned_archive_set(archive_paths);
- for (const auto& id_page_pair : offline_pages_)
- orphaned_archive_set.erase(id_page_pair.second.file_path);
-
- if (orphaned_archive_set.empty())
- return;
-
- std::vector<base::FilePath> orphaned_archives(orphaned_archive_set.begin(),
- orphaned_archive_set.end());
- archive_manager_->DeleteMultipleArchives(
- orphaned_archives,
- base::Bind(&OfflinePageModelImpl::OnDeleteOrphanedArchivesDone,
- weak_ptr_factory_.GetWeakPtr(), orphaned_archives));
-}
-
-void OfflinePageModelImpl::OnDeleteOrphanedArchivesDone(
- const std::vector<base::FilePath>& archives,
- bool success) {
- UMA_HISTOGRAM_COUNTS("OfflinePages.Consistency.OrphanedArchivesCount",
- static_cast<int32_t>(archives.size()));
- UMA_HISTOGRAM_BOOLEAN("OfflinePages.Consistency.DeleteOrphanedArchivesResult",
- success);
-}
-
-void OfflinePageModelImpl::CacheLoadedData(
- const std::vector<OfflinePageItem>& offline_pages) {
- offline_pages_.clear();
- for (const auto& offline_page : offline_pages)
- offline_pages_[offline_page.offline_id] = offline_page;
-}
-
-void OfflinePageModelImpl::ClearStorageIfNeeded(
- const ClearStorageCallback& callback) {
- // Create Storage Manager if necessary.
- if (!storage_manager_) {
- storage_manager_.reset(new OfflinePageStorageManager(
- this, GetPolicyController(), archive_manager_.get()));
- }
- storage_manager_->ClearPagesIfNeeded(callback);
-}
-
-void OfflinePageModelImpl::OnStorageCleared(size_t deleted_page_count,
- ClearStorageResult result) {
- UMA_HISTOGRAM_ENUMERATION("OfflinePages.ClearStorageResult",
- static_cast<int>(result),
- static_cast<int>(ClearStorageResult::RESULT_COUNT));
- if (deleted_page_count > 0) {
- UMA_HISTOGRAM_COUNTS("OfflinePages.ClearStorageBatchSize",
- static_cast<int32_t>(deleted_page_count));
- }
-}
-
-void OfflinePageModelImpl::PostClearStorageIfNeededTask(bool delayed) {
- base::TimeDelta delay =
- delayed ? kStorageManagerStartingDelay : base::TimeDelta();
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&OfflinePageModelImpl::ClearStorageIfNeeded,
- weak_ptr_factory_.GetWeakPtr(),
- base::Bind(&OfflinePageModelImpl::OnStorageCleared,
- weak_ptr_factory_.GetWeakPtr())),
- delay);
-}
-
-void OfflinePageModelImpl::RunWhenLoaded(const base::Closure& task) {
- if (!is_loaded_) {
- delayed_tasks_.push_back(task);
- return;
- }
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
-}
-
-base::Time OfflinePageModelImpl::GetCurrentTime() const {
- return testing_clock_ ? testing_clock_->Now() : base::Time::Now();
-}
-
-} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/offline_page_model_impl.h b/chromium/components/offline_pages/core/offline_page_model_impl.h
deleted file mode 100644
index d4fb7779eb5..00000000000
--- a/chromium/components/offline_pages/core/offline_page_model_impl.h
+++ /dev/null
@@ -1,314 +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_OFFLINE_PAGES_CORE_OFFLINE_PAGE_MODEL_IMPL_H_
-#define COMPONENTS_OFFLINE_PAGES_CORE_OFFLINE_PAGE_MODEL_IMPL_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/files/file_path.h"
-#include "base/gtest_prod_util.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/strings/string16.h"
-#include "base/time/time.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "components/offline_pages/core/offline_page_archiver.h"
-#include "components/offline_pages/core/offline_page_metadata_store.h"
-#include "components/offline_pages/core/offline_page_model.h"
-#include "components/offline_pages/core/offline_page_model_event_logger.h"
-#include "components/offline_pages/core/offline_page_storage_manager.h"
-#include "components/offline_pages/core/offline_page_types.h"
-#include "components/offline_pages/core/offline_store_types.h"
-
-class GURL;
-namespace base {
-class Clock;
-class SequencedTaskRunner;
-class TimeTicks;
-} // namespace base
-
-namespace offline_pages {
-
-struct ClientId;
-struct OfflinePageItem;
-
-class ArchiveManager;
-class ClientPolicyController;
-class OfflinePageModelQuery;
-class OfflinePageStorageManager;
-
-// Implementation of service for saving pages offline, storing the offline
-// copy and metadata, and retrieving them upon request.
-class OfflinePageModelImpl : public OfflinePageModel {
- public:
- // All blocking calls/disk access will happen on the provided |task_runner|.
- OfflinePageModelImpl(
- std::unique_ptr<OfflinePageMetadataStore> store,
- std::unique_ptr<ArchiveManager> archive_manager,
- const scoped_refptr<base::SequencedTaskRunner>& task_runner);
- ~OfflinePageModelImpl() override;
-
- // Implemented methods:
- void AddObserver(Observer* observer) override;
- void RemoveObserver(Observer* observer) override;
- void SavePage(const SavePageParams& save_page_params,
- std::unique_ptr<OfflinePageArchiver> archiver,
- const SavePageCallback& callback) override;
- void AddPage(const OfflinePageItem& page,
- const AddPageCallback& callback) override;
- void MarkPageAccessed(int64_t offline_id) override;
- void DeletePagesByOfflineId(const std::vector<int64_t>& offline_ids,
- const DeletePageCallback& callback) override;
- void DeletePagesByClientIds(const std::vector<ClientId>& client_ids,
- const DeletePageCallback& callback) override;
-
- void GetPagesByClientIds(
- const std::vector<ClientId>& client_ids,
- const MultipleOfflinePageItemCallback& callback) override;
-
- void GetPagesByRequestOrigin(
- const std::string& request_origin,
- const MultipleOfflinePageItemCallback& callback) override;
-
- void DeleteCachedPagesByURLPredicate(
- const UrlPredicate& predicate,
- const DeletePageCallback& callback) override;
- void GetAllPages(const MultipleOfflinePageItemCallback& callback) override;
- void GetOfflineIdsForClientId(
- const ClientId& client_id,
- const MultipleOfflineIdCallback& callback) override;
- void GetPageByOfflineId(
- int64_t offline_id,
- const SingleOfflinePageItemCallback& callback) override;
- void GetPagesByURL(
- const GURL& url,
- URLSearchMode url_search_mode,
- const MultipleOfflinePageItemCallback& callback) override;
- void GetPagesRemovedOnCacheReset(
- const MultipleOfflinePageItemCallback& callback) override;
- void GetPagesByNamespace(
- const std::string& name_space,
- const MultipleOfflinePageItemCallback& callback) override;
- void GetPagesSupportedByDownloads(
- const MultipleOfflinePageItemCallback& callback) override;
- const base::FilePath& GetInternalArchiveDirectory(
- const std::string& name_space) const override;
- bool IsArchiveInInternalDir(const base::FilePath& file_path) const override;
-
- ClientPolicyController* GetPolicyController() override;
-
- // Methods for testing only:
- OfflinePageMetadataStore* GetStoreForTesting();
- void set_testing_clock(base::Clock* clock) { testing_clock_ = clock; }
-
- OfflinePageStorageManager* GetStorageManager();
-
- OfflineEventLogger* GetLogger() override;
-
- void set_skip_clearing_original_url_for_testing() {
- skip_clearing_original_url_for_testing_ = true;
- }
-
- protected:
- // Adding a protected constructor for testing-only purposes in
- // offline_page_storage_manager_unittest.cc
- OfflinePageModelImpl();
-
- private:
- FRIEND_TEST_ALL_PREFIXES(OfflinePageModelImplTest, MarkPageForDeletion);
- FRIEND_TEST_ALL_PREFIXES(OfflinePageModelImplTest, StoreLoadFailurePersists);
-
- typedef std::vector<std::unique_ptr<OfflinePageArchiver>> PendingArchivers;
-
- // Callback for ensuring archive directory is created.
- void OnEnsureArchivesDirCreatedDone(const base::TimeTicks& start_time);
-
- void GetPagesMatchingQueryWhenLoadDone(
- std::unique_ptr<OfflinePageModelQuery> query,
- const MultipleOfflinePageItemCallback& callback);
- void GetOfflineIdsForClientIdWhenLoadDone(
- const ClientId& client_id,
- const MultipleOfflineIdCallback& callback) const;
- const std::vector<int64_t> MaybeGetOfflineIdsForClientId(
- const ClientId& client_id) const;
- void GetPagesByURLWhenLoadDone(
- const GURL& url,
- URLSearchMode url_search_mode,
- const MultipleOfflinePageItemCallback& callback) const;
- void MarkPageAccessedWhenLoadDone(int64_t offline_id);
-
- // Check the consistency between metadata store and archives on disk,
- // would delete the metadata entries which don't have an associated
- // archive and the archives which doesn't have a metadata in the store.
- // The expired pages (from previous versions) would also be cleared
- // during this process.
- void CheckMetadataConsistency();
-
- // Callback for loading pages from the offline page metadata store.
- void OnStoreInitialized(const base::TimeTicks& start_time,
- int init_attempts_spent,
- bool success);
- void RetryDbInitialization(const base::TimeTicks& start_time,
- int init_attempts_spent);
- void OnInitialGetOfflinePagesDone(const base::TimeTicks& start_time,
- std::vector<OfflinePageItem> offline_pages);
- void FinalizeModelLoad();
-
- // Steps for saving a page offline.
- void OnCreateArchiveDone(const SavePageParams& save_page_params,
- int64_t offline_id,
- const base::Time& start_time,
- const SavePageCallback& callback,
- OfflinePageArchiver* archiver,
- OfflinePageArchiver::ArchiverResult result,
- const GURL& saved_url,
- const base::FilePath& file_path,
- const base::string16& title,
- int64_t file_size,
- const std::string& file_hash);
- void OnAddSavedPageDone(const OfflinePageItem& offline_page,
- const SavePageCallback& callback,
- AddPageResult add_result,
- int64_t offline_id);
- void InformSavePageDone(const SavePageCallback& callback,
- SavePageResult result,
- const ClientId& client_id,
- int64_t offline_id);
- void DeletePendingArchiver(OfflinePageArchiver* archiver);
-
- // Steps for adding a page entry to metadata store.
- void AddPageWhenLoadDone(const OfflinePageItem& page,
- const AddPageCallback& callback);
- void OnAddPageDone(const OfflinePageItem& offline_page,
- const AddPageCallback& callback,
- ItemActionStatus status);
-
- // Steps for deleting files and data for an offline page.
- void OnDeleteArchiveFilesDone(const std::vector<int64_t>& offline_ids,
- const DeletePageCallback& callback,
- bool success);
- void OnRemoveOfflinePagesDone(
- const DeletePageCallback& callback,
- std::unique_ptr<OfflinePagesUpdateResult> result);
- void InformDeletePageDone(const DeletePageCallback& callback,
- DeletePageResult result);
-
- void OnMarkPageAccesseDone(const OfflinePageItem& offline_page_item,
- std::unique_ptr<OfflinePagesUpdateResult> result);
-
- // Callbacks for checking metadata consistency.
- void CheckMetadataConsistencyForArchivePaths(
- const std::set<base::FilePath>& archive_paths);
- // Methods that are executed during consistency check, including:
- // 1. Delete temporary pages which are in the abandoned cache directory.
- // 2. Delete pages without associated archive file from metadata store.
- // 3. Delete orphaned archive files without associated metadata from the disk.
- // And their corresponding callbacks after deletion finishes.
- void DeleteTemporaryPagesInAbandonedCacheDir();
- void DeletePagesMissingArchiveFile(
- const std::set<base::FilePath>& archive_paths);
- void OnDeletePagesMissingArchiveFileDone(
- const std::vector<int64_t>& offline_ids,
- DeletePageResult result);
- void DeleteOrphanedArchives(const std::set<base::FilePath>& archive_paths);
- void OnDeleteOrphanedArchivesDone(const std::vector<base::FilePath>& archives,
- bool success);
-
- // Callbacks for deleting pages with same URL when saving pages.
- void DeleteExistingPagesWithSameURL(const OfflinePageItem& offline_page);
- void OnPagesFoundWithSameURL(const OfflinePageItem& offline_page,
- size_t pages_allowed,
- const MultipleOfflinePageItemResult& items);
- void OnDeleteOldPagesWithSameURL(DeletePageResult result);
-
- void CacheLoadedData(const std::vector<OfflinePageItem>& offline_pages);
-
- // Actually does the work of deleting, requires the model is loaded.
- void DoDeletePagesByOfflineId(const std::vector<int64_t>& offline_ids,
- const DeletePageCallback& callback);
-
- // Actually does the work of deleting, requires the model is loaded.
- void DeletePages(const DeletePageCallback& callback,
- const MultipleOfflinePageItemResult& items);
-
- void DoGetPagesByClientIds(const std::vector<ClientId>& client_ids,
- const MultipleOfflinePageItemCallback& callback);
-
- // Similar to DoDeletePagesByOfflineId, does actual work of deleting, and
- // requires that the model is loaded.
- void DoDeleteCachedPagesByURLPredicate(const UrlPredicate& predicate,
- const DeletePageCallback& callback);
-
- // Clears expired pages if there are any or we're running out of storage.
- void ClearStorageIfNeeded(
- const OfflinePageStorageManager::ClearStorageCallback& callback);
-
- // Callback completing storage clearing.
- void OnStorageCleared(size_t cleared_page_count,
- OfflinePageStorageManager::ClearStorageResult result);
-
- // Post task to clear storage.
- void PostClearStorageIfNeededTask(bool delayed);
-
- void RunWhenLoaded(const base::Closure& job);
-
- base::Time GetCurrentTime() const;
-
- // Persistent store for offline page metadata.
- std::unique_ptr<OfflinePageMetadataStore> store_;
-
- // The observers.
- base::ObserverList<Observer> observers_;
-
- bool is_loaded_;
-
- // In memory copy of the offline page metadata, keyed by offline IDs.
- std::map<int64_t, OfflinePageItem> offline_pages_;
-
- // Pending archivers owned by this model.
- PendingArchivers pending_archivers_;
-
- // Delayed tasks that should be invoked after the loading is done.
- std::vector<base::Closure> delayed_tasks_;
-
- // Controller of the client policies.
- std::unique_ptr<ClientPolicyController> policy_controller_;
-
- // Manager for the storage consumed by archives and responsible for
- // automatic page clearing.
- std::unique_ptr<OfflinePageStorageManager> storage_manager_;
-
- // Manager for the offline archive files and directory.
- std::unique_ptr<ArchiveManager> archive_manager_;
-
- // Logger to facilitate recording of events.
- OfflinePageModelEventLogger offline_event_logger_;
-
- // Clock for getting time in testing code. The setter is responsible to reset
- // it once it is not longer needed.
- base::Clock* testing_clock_;
-
- // Don't clear original URL if it is same as final URL. For testing only.
- bool skip_clearing_original_url_for_testing_;
-
- base::WeakPtrFactory<OfflinePageModelImpl> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(OfflinePageModelImpl);
-};
-
-} // namespace offline_pages
-
-#endif // COMPONENTS_OFFLINE_PAGES_CORE_OFFLINE_PAGE_MODEL_IMPL_H_
diff --git a/chromium/components/offline_pages/core/offline_page_model_impl_unittest.cc b/chromium/components/offline_pages/core/offline_page_model_impl_unittest.cc
deleted file mode 100644
index 10afea94e97..00000000000
--- a/chromium/components/offline_pages/core/offline_page_model_impl_unittest.cc
+++ /dev/null
@@ -1,1617 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/offline_pages/core/offline_page_model_impl.h"
-
-#include <stdint.h>
-#include <algorithm>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/feature_list.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/metrics/statistics_recorder.h"
-#include "base/rand_util.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/test_mock_time_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "components/offline_pages/core/client_namespace_constants.h"
-#include "components/offline_pages/core/client_policy_controller.h"
-#include "components/offline_pages/core/offline_page_client_policy.h"
-#include "components/offline_pages/core/offline_page_feature.h"
-#include "components/offline_pages/core/offline_page_item.h"
-#include "components/offline_pages/core/offline_page_storage_manager.h"
-#include "components/offline_pages/core/offline_page_test_archiver.h"
-#include "components/offline_pages/core/offline_page_test_store.h"
-#include "components/offline_pages/core/offline_page_types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace offline_pages {
-
-namespace {
-const char kOriginalTabNamespace[] = "original_tab_testing_namespace";
-const char kTestClientNamespace[] = "default";
-const char kUserRequestedNamespace[] = "download";
-const GURL kTestUrl("http://example.com");
-const GURL kTestUrl2("http://other.page.com");
-const GURL kTestUrl3("http://test.xyz");
-const GURL kTestUrl4("http://page.net");
-const GURL kFileUrl("file:///foo");
-const GURL kTestUrlWithFragment("http://example.com#frag");
-const GURL kTestUrl2WithFragment("http://other.page.com#frag");
-const GURL kTestUrl2WithFragment2("http://other.page.com#frag2");
-const ClientId kTestClientId1(kTestClientNamespace, "1234");
-const ClientId kTestClientId2(kTestClientNamespace, "5678");
-const ClientId kTestClientId3(kTestClientNamespace, "42");
-const ClientId kTestUserRequestedClientId(kUserRequestedNamespace, "714");
-const int64_t kTestFileSize = 876543LL;
-const base::string16 kTestTitle = base::UTF8ToUTF16("a title");
-const std::string kRequestOrigin("abc.xyz");
-
-bool URLSpecContains(std::string contains_value, const GURL& url) {
- std::string spec = url.spec();
- return spec.find(contains_value) != std::string::npos;
-}
-
-} // namespace
-
-class OfflinePageModelImplTest
- : public testing::Test,
- public OfflinePageModel::Observer,
- public OfflinePageTestArchiver::Observer,
- public base::SupportsWeakPtr<OfflinePageModelImplTest> {
- public:
- OfflinePageModelImplTest();
- ~OfflinePageModelImplTest() override;
-
- void SetUp() override;
- void TearDown() override;
-
- // OfflinePageModel::Observer implementation.
- void OfflinePageModelLoaded(OfflinePageModel* model) override;
- void OfflinePageAdded(OfflinePageModel* model,
- const OfflinePageItem& added_page) override;
- void OfflinePageDeleted(
- const OfflinePageModel::DeletedPageInfo& pageInfo) override;
-
- // OfflinePageTestArchiver::Observer implementation.
- void SetLastPathCreatedByArchiver(const base::FilePath& file_path) override;
-
- // OfflinePageModel callbacks.
- void OnSavePageDone(SavePageResult result, int64_t offline_id);
- void OnAddPageDone(AddPageResult result, int64_t offline_id);
- void OnDeletePageDone(DeletePageResult result);
- void OnGetOfflineIdsForClientIdDone(MultipleOfflineIdResult* storage,
- const MultipleOfflineIdResult& result);
- void OnGetSingleOfflinePageItemResult(
- std::unique_ptr<OfflinePageItem>* storage,
- const OfflinePageItem* result);
- void OnGetMultipleOfflinePageItemsResult(
- MultipleOfflinePageItemResult* storage,
- const MultipleOfflinePageItemResult& result);
- void OnPagesExpired(bool result);
-
- // OfflinePageMetadataStore callbacks.
- void OnStoreUpdateDone(bool /* success */);
-
- std::unique_ptr<OfflinePageTestArchiver> BuildArchiver(
- const GURL& url,
- OfflinePageArchiver::ArchiverResult result);
- std::unique_ptr<OfflinePageMetadataStore> BuildStore();
- std::unique_ptr<OfflinePageModelImpl> BuildModel(
- std::unique_ptr<OfflinePageMetadataStore> store);
- void ResetModel();
-
- // Utility methods.
- // Runs until all of the tasks that are not delayed are gone from the task
- // queue.
- void PumpLoop();
- // Fast-forwards virtual time by |delta|, causing tasks with a remaining
- // delay less than or equal to |delta| to be executed.
- void FastForwardBy(base::TimeDelta delta);
- // Runs tasks and moves time forward until no tasks remain in the queue.
- void FastForwardUntilNoTasksRemain();
-
- void ResetResults();
-
- OfflinePageTestStore* GetStore();
-
- MultipleOfflinePageItemResult GetAllPages();
- MultipleOfflinePageItemResult GetPagesByClientIds(
- const std::vector<ClientId>& client_ids);
- MultipleOfflinePageItemResult GetPagesByRequestOrigin(
- const std::string& origin);
- void DeletePagesByClientIds(const std::vector<ClientId>& client_ids);
-
- // Saves the page without waiting for it to finish.
- void SavePageWithParamsAsync(
- const OfflinePageModel::SavePageParams& save_page_params,
- std::unique_ptr<OfflinePageArchiver> archiver);
-
- // Saves the page without waiting for it to finish.
- void SavePageWithArchiverAsync(const GURL& url,
- const ClientId& client_id,
- const GURL& original_url,
- const std::string& request_origin,
- std::unique_ptr<OfflinePageArchiver> archiver);
-
- // All 3 methods below will wait for the save to finish.
- void SavePageWithArchiver(
- const GURL& url,
- const ClientId& client_id,
- std::unique_ptr<OfflinePageArchiver> archiver);
- void SavePageWithArchiverResult(const GURL& url,
- const ClientId& client_id,
- OfflinePageArchiver::ArchiverResult result);
- // Returns the offline ID of the saved page.
- std::pair<SavePageResult, int64_t> SavePage(const GURL& url,
- const ClientId& client_id);
- std::pair<SavePageResult, int64_t> SavePage(
- const GURL& url,
- const ClientId& client_id,
- const std::string& request_origin);
-
- void AddPage(const OfflinePageItem& offline_page);
-
- void DeletePage(int64_t offline_id, const DeletePageCallback& callback) {
- std::vector<int64_t> offline_ids;
- offline_ids.push_back(offline_id);
- model()->DeletePagesByOfflineId(offline_ids, callback);
- }
-
- void SetTemporaryDirSameWithPersistent(bool is_same) {
- temporary_dir_same_with_persistent_ = is_same;
- }
-
- bool HasPages(std::string name_space);
-
- MultipleOfflineIdResult GetOfflineIdsForClientId(const ClientId& client_id);
-
- std::unique_ptr<OfflinePageItem> GetPageByOfflineId(int64_t offline_id);
-
- MultipleOfflinePageItemResult GetPagesByFinalURL(const GURL& url);
- MultipleOfflinePageItemResult GetPagesByAllURLS(const GURL& url);
-
- OfflinePageModelImpl* model() { return model_.get(); }
-
- int64_t last_save_offline_id() const { return last_save_offline_id_; }
-
- SavePageResult last_save_result() const { return last_save_result_; }
-
- AddPageResult last_add_result() const { return last_add_result_; }
-
- int64_t last_add_offline_id() const { return last_add_offline_id_; }
-
- DeletePageResult last_delete_result() const { return last_delete_result_; }
-
- int64_t last_deleted_offline_id() const { return last_deleted_offline_id_; }
-
- ClientId last_deleted_client_id() const { return last_deleted_client_id_; }
-
- std::string last_deleted_request_origin() const {
- return last_deleted_request_origin_;
- }
-
- const base::FilePath& last_archiver_path() { return last_archiver_path_; }
-
- int last_cleared_pages_count() const { return last_cleared_pages_count_; }
-
- DeletePageResult last_clear_page_result() const {
- return last_clear_page_result_;
- }
-
- bool last_expire_page_result() const { return last_expire_page_result_; }
-
- const base::HistogramTester& histograms() const { return histogram_tester_; }
-
- const base::FilePath& temporary_dir_path() const {
- if (temporary_dir_same_with_persistent_)
- return private_archive_dir_.GetPath();
- return temporary_dir_.GetPath();
- }
-
- const base::FilePath& private_archive_dir_path() const {
- return private_archive_dir_.GetPath();
- }
-
- const base::FilePath& public_archive_dir_path() const {
- return public_archive_dir_.GetPath();
- }
-
- private:
- scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
- base::ThreadTaskRunnerHandle task_runner_handle_;
- base::ScopedTempDir temporary_dir_;
- base::ScopedTempDir private_archive_dir_;
- base::ScopedTempDir public_archive_dir_;
-
- std::unique_ptr<OfflinePageModelImpl> model_;
- SavePageResult last_save_result_;
- int64_t last_save_offline_id_;
- AddPageResult last_add_result_;
- int64_t last_add_offline_id_;
- DeletePageResult last_delete_result_;
- base::FilePath last_archiver_path_;
- int64_t last_deleted_offline_id_;
- ClientId last_deleted_client_id_;
- std::string last_deleted_request_origin_;
- int last_cleared_pages_count_;
- DeletePageResult last_clear_page_result_;
- bool last_expire_page_result_;
- bool temporary_dir_same_with_persistent_;
-
- base::HistogramTester histogram_tester_;
-};
-
-OfflinePageModelImplTest::OfflinePageModelImplTest()
- : task_runner_(new base::TestMockTimeTaskRunner),
- task_runner_handle_(task_runner_),
- last_save_result_(SavePageResult::CANCELLED),
- last_save_offline_id_(-1),
- last_add_result_(AddPageResult::STORE_FAILURE),
- last_add_offline_id_(-1),
- last_delete_result_(DeletePageResult::CANCELLED),
- last_deleted_offline_id_(-1),
- temporary_dir_same_with_persistent_(false) {}
-
-OfflinePageModelImplTest::~OfflinePageModelImplTest() {}
-
-void OfflinePageModelImplTest::SetUp() {
- ASSERT_TRUE(temporary_dir_.CreateUniqueTempDir());
- ASSERT_TRUE(private_archive_dir_.CreateUniqueTempDir());
- ASSERT_TRUE(public_archive_dir_.CreateUniqueTempDir());
- model_ = BuildModel(BuildStore());
- model_->GetPolicyController()->AddPolicyForTest(
- kOriginalTabNamespace,
- OfflinePageClientPolicyBuilder(
- kOriginalTabNamespace,
- offline_pages::LifetimePolicy::LifetimeType::TEMPORARY,
- kUnlimitedPages, kUnlimitedPages)
- .SetIsOnlyShownInOriginalTab(true));
-
- model_->AddObserver(this);
- PumpLoop();
-}
-
-void OfflinePageModelImplTest::TearDown() {
- model_->RemoveObserver(this);
- model_.reset();
- PumpLoop();
-}
-
-void OfflinePageModelImplTest::OfflinePageModelLoaded(OfflinePageModel* model) {
- ASSERT_EQ(model_.get(), model);
-}
-
-void OfflinePageModelImplTest::OfflinePageDeleted(
- const OfflinePageModel::DeletedPageInfo& info) {
- last_deleted_offline_id_ = info.offline_id;
- last_deleted_client_id_ = info.client_id;
- last_deleted_request_origin_ = info.request_origin;
-}
-
-void OfflinePageModelImplTest::OfflinePageAdded(
- OfflinePageModel* model,
- const OfflinePageItem& added_page) {
- ASSERT_EQ(model_.get(), model);
-}
-
-void OfflinePageModelImplTest::SetLastPathCreatedByArchiver(
- const base::FilePath& file_path) {
- last_archiver_path_ = file_path;
-}
-
-void OfflinePageModelImplTest::OnSavePageDone(SavePageResult result,
- int64_t offline_id) {
- last_save_result_ = result;
- last_save_offline_id_ = offline_id;
-}
-
-void OfflinePageModelImplTest::OnAddPageDone(AddPageResult result,
- int64_t offline_id) {
- last_add_result_ = result;
- last_add_offline_id_ = offline_id;
-}
-
-void OfflinePageModelImplTest::OnDeletePageDone(DeletePageResult result) {
- last_delete_result_ = result;
-}
-
-void OfflinePageModelImplTest::OnStoreUpdateDone(bool /* success - ignored */) {
-}
-
-std::unique_ptr<OfflinePageTestArchiver>
-OfflinePageModelImplTest::BuildArchiver(
- const GURL& url,
- OfflinePageArchiver::ArchiverResult result) {
- return std::unique_ptr<OfflinePageTestArchiver>(new OfflinePageTestArchiver(
- this, url, result, kTestTitle, kTestFileSize, std::string(),
- base::ThreadTaskRunnerHandle::Get()));
-}
-
-std::unique_ptr<OfflinePageMetadataStore>
-OfflinePageModelImplTest::BuildStore() {
- return std::unique_ptr<OfflinePageMetadataStore>(
- new OfflinePageTestStore(base::ThreadTaskRunnerHandle::Get()));
-}
-
-std::unique_ptr<OfflinePageModelImpl> OfflinePageModelImplTest::BuildModel(
- std::unique_ptr<OfflinePageMetadataStore> store) {
- std::unique_ptr<ArchiveManager> archive_manager = nullptr;
- archive_manager = std::make_unique<ArchiveManager>(
- temporary_dir_path(), private_archive_dir_path(),
- public_archive_dir_path(), base::ThreadTaskRunnerHandle::Get());
- return std::unique_ptr<OfflinePageModelImpl>(
- new OfflinePageModelImpl(std::move(store), std::move(archive_manager),
- base::ThreadTaskRunnerHandle::Get()));
-}
-
-void OfflinePageModelImplTest::ResetModel() {
- model_->RemoveObserver(this);
- OfflinePageTestStore* old_store = GetStore();
- std::unique_ptr<OfflinePageMetadataStore> new_store(
- new OfflinePageTestStore(*old_store));
- model_ = BuildModel(std::move(new_store));
- model_->AddObserver(this);
- PumpLoop();
-}
-
-void OfflinePageModelImplTest::PumpLoop() {
- task_runner_->RunUntilIdle();
-}
-
-void OfflinePageModelImplTest::FastForwardBy(base::TimeDelta delta) {
- task_runner_->FastForwardBy(delta);
-}
-
-void OfflinePageModelImplTest::FastForwardUntilNoTasksRemain() {
- task_runner_->FastForwardUntilNoTasksRemain();
-}
-
-void OfflinePageModelImplTest::ResetResults() {
- last_save_result_ = SavePageResult::CANCELLED;
- last_delete_result_ = DeletePageResult::CANCELLED;
- last_archiver_path_.clear();
- last_cleared_pages_count_ = 0;
-}
-
-OfflinePageTestStore* OfflinePageModelImplTest::GetStore() {
- return static_cast<OfflinePageTestStore*>(model()->GetStoreForTesting());
-}
-
-void OfflinePageModelImplTest::SavePageWithParamsAsync(
- const OfflinePageModel::SavePageParams& save_page_params,
- std::unique_ptr<OfflinePageArchiver> archiver) {
- model()->SavePage(
- save_page_params,
- std::move(archiver),
- base::Bind(&OfflinePageModelImplTest::OnSavePageDone, AsWeakPtr()));
-}
-
-void OfflinePageModelImplTest::SavePageWithArchiverAsync(
- const GURL& url,
- const ClientId& client_id,
- const GURL& original_url,
- const std::string& request_origin,
- std::unique_ptr<OfflinePageArchiver> archiver) {
- OfflinePageModel::SavePageParams save_page_params;
- save_page_params.url = url;
- save_page_params.client_id = client_id;
- save_page_params.original_url = original_url;
- save_page_params.is_background = false;
- save_page_params.request_origin = request_origin;
- SavePageWithParamsAsync(save_page_params, std::move(archiver));
-}
-
-void OfflinePageModelImplTest::SavePageWithArchiver(
- const GURL& url,
- const ClientId& client_id,
- std::unique_ptr<OfflinePageArchiver> archiver) {
- SavePageWithArchiverAsync(url, client_id, GURL(), "", std::move(archiver));
- PumpLoop();
-}
-
-void OfflinePageModelImplTest::SavePageWithArchiverResult(
- const GURL& url,
- const ClientId& client_id,
- OfflinePageArchiver::ArchiverResult result) {
- std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver(url, result));
- SavePageWithArchiverAsync(url, client_id, GURL(), "", std::move(archiver));
- PumpLoop();
-}
-
-std::pair<SavePageResult, int64_t>
-OfflinePageModelImplTest::SavePage(const GURL& url, const ClientId& client_id) {
- return SavePage(url, client_id, "");
-}
-
-std::pair<SavePageResult, int64_t> OfflinePageModelImplTest::SavePage(
- const GURL& url,
- const ClientId& client_id,
- const std::string& request_origin) {
- std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver(
- url, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED));
- SavePageWithArchiverAsync(url, client_id, GURL(), request_origin,
- std::move(archiver));
- PumpLoop();
- return std::make_pair(last_save_result_, last_save_offline_id_);
-}
-
-void OfflinePageModelImplTest::AddPage(const OfflinePageItem& offline_page) {
- model()->AddPage(
- offline_page,
- base::Bind(&OfflinePageModelImplTest::OnAddPageDone, AsWeakPtr()));
- PumpLoop();
-}
-
-MultipleOfflinePageItemResult OfflinePageModelImplTest::GetAllPages() {
- MultipleOfflinePageItemResult result;
- model()->GetAllPages(
- base::Bind(&OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult,
- AsWeakPtr(), base::Unretained(&result)));
- PumpLoop();
- return result;
-}
-
-MultipleOfflinePageItemResult OfflinePageModelImplTest::GetPagesByClientIds(
- const std::vector<ClientId>& client_ids) {
- MultipleOfflinePageItemResult result;
- model()->GetPagesByClientIds(
- client_ids,
- base::Bind(&OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult,
- AsWeakPtr(), base::Unretained(&result)));
- PumpLoop();
- return result;
-}
-
-MultipleOfflinePageItemResult OfflinePageModelImplTest::GetPagesByRequestOrigin(
- const std::string& origin) {
- MultipleOfflinePageItemResult result;
- model()->GetPagesByRequestOrigin(
- origin,
- base::Bind(&OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult,
- AsWeakPtr(), base::Unretained(&result)));
- PumpLoop();
- return result;
-}
-
-void OfflinePageModelImplTest::DeletePagesByClientIds(
- const std::vector<ClientId>& client_ids) {
- model()->DeletePagesByClientIds(
- client_ids,
- base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, AsWeakPtr()));
- PumpLoop();
-}
-
-MultipleOfflineIdResult OfflinePageModelImplTest::GetOfflineIdsForClientId(
- const ClientId& client_id) {
- MultipleOfflineIdResult result;
- model()->GetOfflineIdsForClientId(
- client_id,
- base::Bind(&OfflinePageModelImplTest::OnGetOfflineIdsForClientIdDone,
- AsWeakPtr(), base::Unretained(&result)));
- PumpLoop();
- return result;
-}
-
-void OfflinePageModelImplTest::OnGetOfflineIdsForClientIdDone(
- MultipleOfflineIdResult* storage,
- const MultipleOfflineIdResult& result) {
- *storage = result;
-}
-
-std::unique_ptr<OfflinePageItem> OfflinePageModelImplTest::GetPageByOfflineId(
- int64_t offline_id) {
- std::unique_ptr<OfflinePageItem> result = nullptr;
- model()->GetPageByOfflineId(
- offline_id,
- base::Bind(&OfflinePageModelImplTest::OnGetSingleOfflinePageItemResult,
- AsWeakPtr(), base::Unretained(&result)));
- PumpLoop();
- return result;
-}
-
-void OfflinePageModelImplTest::OnGetSingleOfflinePageItemResult(
- std::unique_ptr<OfflinePageItem>* storage,
- const OfflinePageItem* result) {
- if (result == nullptr) {
- storage->reset(nullptr);
- return;
- }
-
- *storage = std::make_unique<OfflinePageItem>(*result);
-}
-
-void OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult(
- MultipleOfflinePageItemResult* storage,
- const MultipleOfflinePageItemResult& result) {
- *storage = result;
-}
-
-void OfflinePageModelImplTest::OnPagesExpired(bool result) {
- last_expire_page_result_ = result;
-}
-
-MultipleOfflinePageItemResult OfflinePageModelImplTest::GetPagesByFinalURL(
- const GURL& url) {
- MultipleOfflinePageItemResult result;
- model()->GetPagesByURL(
- url, URLSearchMode::SEARCH_BY_FINAL_URL_ONLY,
- base::Bind(&OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult,
- AsWeakPtr(), base::Unretained(&result)));
- PumpLoop();
- return result;
-}
-
-MultipleOfflinePageItemResult OfflinePageModelImplTest::GetPagesByAllURLS(
- const GURL& url) {
- MultipleOfflinePageItemResult result;
- model()->GetPagesByURL(
- url, URLSearchMode::SEARCH_BY_ALL_URLS,
- base::Bind(&OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult,
- AsWeakPtr(), base::Unretained(&result)));
- PumpLoop();
- return result;
-}
-
-bool OfflinePageModelImplTest::HasPages(std::string name_space) {
- MultipleOfflinePageItemResult all_pages = GetAllPages();
- for (const auto& page : all_pages) {
- if (page.client_id.name_space == name_space)
- return true;
- }
-
- return false;
-}
-
-TEST_F(OfflinePageModelImplTest, SavePageSuccessful) {
- EXPECT_FALSE(HasPages(kTestClientNamespace));
-
- std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver(
- kTestUrl, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED));
- SavePageWithArchiverAsync(kTestUrl, kTestClientId1, kTestUrl2, "",
- std::move(archiver));
- PumpLoop();
- EXPECT_TRUE(HasPages(kTestClientNamespace));
-
- OfflinePageTestStore* store = GetStore();
- EXPECT_EQ(kTestUrl, store->last_saved_page().url);
- EXPECT_EQ(kTestClientId1.id, store->last_saved_page().client_id.id);
- EXPECT_EQ(kTestClientId1.name_space,
- store->last_saved_page().client_id.name_space);
- // Save last_archiver_path since it will be referred to later.
- base::FilePath archiver_path = last_archiver_path();
- EXPECT_EQ(archiver_path, store->last_saved_page().file_path);
- EXPECT_EQ(kTestFileSize, store->last_saved_page().file_size);
- EXPECT_EQ(SavePageResult::SUCCESS, last_save_result());
- ResetResults();
-
- const std::vector<OfflinePageItem>& offline_pages = GetAllPages();
-
- ASSERT_EQ(1UL, offline_pages.size());
- EXPECT_EQ(kTestUrl, offline_pages[0].url);
- EXPECT_EQ(kTestClientId1.id, offline_pages[0].client_id.id);
- EXPECT_EQ(kTestClientId1.name_space, offline_pages[0].client_id.name_space);
- EXPECT_EQ(archiver_path, offline_pages[0].file_path);
- EXPECT_EQ(kTestFileSize, offline_pages[0].file_size);
- EXPECT_EQ(0, offline_pages[0].access_count);
- EXPECT_EQ(0, offline_pages[0].flags);
- EXPECT_EQ(kTestTitle, offline_pages[0].title);
- EXPECT_EQ(kTestUrl2, offline_pages[0].original_url);
- EXPECT_EQ("", offline_pages[0].request_origin);
-}
-
-TEST_F(OfflinePageModelImplTest, SavePageSuccessfulWithSameOriginalURL) {
- std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver(
- kTestUrl, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED));
- // Pass the original URL same as the final URL.
- SavePageWithArchiverAsync(kTestUrl, kTestClientId1, kTestUrl, "",
- std::move(archiver));
- PumpLoop();
-
- EXPECT_EQ(SavePageResult::SUCCESS, last_save_result());
- ResetResults();
-
- const std::vector<OfflinePageItem>& offline_pages = GetAllPages();
-
- ASSERT_EQ(1UL, offline_pages.size());
- EXPECT_EQ(kTestUrl, offline_pages[0].url);
- // The original URL should be empty.
- EXPECT_TRUE(offline_pages[0].original_url.is_empty());
-}
-
-TEST_F(OfflinePageModelImplTest, SavePageSuccessfulWithRequestOrigin) {
- EXPECT_FALSE(HasPages(kTestClientNamespace));
-
- std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver(
- kTestUrl, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED));
- SavePageWithArchiverAsync(kTestUrl, kTestClientId1, kTestUrl2, kRequestOrigin,
- std::move(archiver));
- PumpLoop();
- EXPECT_TRUE(HasPages(kTestClientNamespace));
-
- OfflinePageTestStore* store = GetStore();
- EXPECT_EQ(kTestUrl, store->last_saved_page().url);
- EXPECT_EQ(kTestClientId1.id, store->last_saved_page().client_id.id);
- EXPECT_EQ(kTestClientId1.name_space,
- store->last_saved_page().client_id.name_space);
- // Save last_archiver_path since it will be referred to later.
- base::FilePath archiver_path = last_archiver_path();
- EXPECT_EQ(archiver_path, store->last_saved_page().file_path);
- EXPECT_EQ(kTestFileSize, store->last_saved_page().file_size);
- EXPECT_EQ(SavePageResult::SUCCESS, last_save_result());
- ResetResults();
-
- const std::vector<OfflinePageItem>& offline_pages = GetAllPages();
-
- ASSERT_EQ(1UL, offline_pages.size());
- EXPECT_EQ(kTestUrl, offline_pages[0].url);
- EXPECT_EQ(kTestClientId1.id, offline_pages[0].client_id.id);
- EXPECT_EQ(kTestClientId1.name_space, offline_pages[0].client_id.name_space);
- EXPECT_EQ(archiver_path, offline_pages[0].file_path);
- EXPECT_EQ(kTestFileSize, offline_pages[0].file_size);
- EXPECT_EQ(0, offline_pages[0].access_count);
- EXPECT_EQ(0, offline_pages[0].flags);
- EXPECT_EQ(kTestTitle, offline_pages[0].title);
- EXPECT_EQ(kTestUrl2, offline_pages[0].original_url);
- EXPECT_EQ(kRequestOrigin, offline_pages[0].request_origin);
-}
-
-TEST_F(OfflinePageModelImplTest, SavePageOfflineArchiverCancelled) {
- SavePageWithArchiverResult(
- kTestUrl, kTestClientId1,
- OfflinePageArchiver::ArchiverResult::ERROR_CANCELED);
- EXPECT_EQ(SavePageResult::CANCELLED, last_save_result());
-}
-
-TEST_F(OfflinePageModelImplTest, SavePageOfflineArchiverDeviceFull) {
- SavePageWithArchiverResult(
- kTestUrl, kTestClientId1,
- OfflinePageArchiver::ArchiverResult::ERROR_DEVICE_FULL);
- EXPECT_EQ(SavePageResult::DEVICE_FULL, last_save_result());
-}
-
-TEST_F(OfflinePageModelImplTest, SavePageOfflineArchiverContentUnavailable) {
- SavePageWithArchiverResult(
- kTestUrl, kTestClientId1,
- OfflinePageArchiver::ArchiverResult::ERROR_CONTENT_UNAVAILABLE);
- EXPECT_EQ(SavePageResult::CONTENT_UNAVAILABLE, last_save_result());
-}
-
-TEST_F(OfflinePageModelImplTest, SavePageOfflineCreationFailed) {
- SavePageWithArchiverResult(
- kTestUrl, kTestClientId1,
- OfflinePageArchiver::ArchiverResult::ERROR_ARCHIVE_CREATION_FAILED);
- EXPECT_EQ(SavePageResult::ARCHIVE_CREATION_FAILED, last_save_result());
-}
-
-TEST_F(OfflinePageModelImplTest, SavePageOfflineArchiverReturnedWrongUrl) {
- std::unique_ptr<OfflinePageTestArchiver> archiver(
- BuildArchiver(GURL("http://other.random.url.com"),
- OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED));
- SavePageWithArchiver(kTestUrl, kTestClientId1, std::move(archiver));
- EXPECT_EQ(SavePageResult::ARCHIVE_CREATION_FAILED, last_save_result());
-}
-
-TEST_F(OfflinePageModelImplTest, SavePageOfflineCreationStoreWriteFailure) {
- GetStore()->set_test_scenario(
- OfflinePageTestStore::TestScenario::WRITE_FAILED);
- SavePageWithArchiverResult(
- kTestUrl, kTestClientId1,
- OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED);
- EXPECT_EQ(SavePageResult::STORE_FAILURE, last_save_result());
-}
-
-TEST_F(OfflinePageModelImplTest, SavePageLocalFileFailed) {
- // Don't create archiver since it will not be needed for pages that are not
- // going to be saved.
- SavePageWithArchiver(kFileUrl, kTestClientId1,
- std::unique_ptr<OfflinePageTestArchiver>());
- EXPECT_EQ(SavePageResult::SKIPPED, last_save_result());
-}
-
-TEST_F(OfflinePageModelImplTest, SavePageOfflineArchiverTwoPages) {
- std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver(
- kTestUrl, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED));
- // archiver_ptr will be valid until after first PumpLoop() call after
- // CompleteCreateArchive() is called.
- OfflinePageTestArchiver* archiver_ptr = archiver.get();
- archiver_ptr->set_delayed(true);
- // First page has no request origin.
- SavePageWithArchiverAsync(kTestUrl, kTestClientId1, GURL(), "",
- std::move(archiver));
- EXPECT_TRUE(archiver_ptr->create_archive_called());
- // |remove_popup_overlay| should not be turned on on foreground mode.
- EXPECT_FALSE(archiver_ptr->create_archive_params().remove_popup_overlay);
-
- // Request to save another page, with request origin.
- SavePage(kTestUrl2, kTestClientId2, kRequestOrigin);
-
- OfflinePageTestStore* store = GetStore();
-
- EXPECT_EQ(kTestUrl2, store->last_saved_page().url);
- EXPECT_EQ(kTestClientId2, store->last_saved_page().client_id);
- base::FilePath archiver_path2 = last_archiver_path();
- EXPECT_EQ(archiver_path2, store->last_saved_page().file_path);
- EXPECT_EQ(kTestFileSize, store->last_saved_page().file_size);
- EXPECT_EQ(kRequestOrigin, store->last_saved_page().request_origin);
- EXPECT_EQ(SavePageResult::SUCCESS, last_save_result());
-
- ResetResults();
-
- archiver_ptr->CompleteCreateArchive();
- // After this pump loop archiver_ptr is invalid.
- PumpLoop();
-
- EXPECT_EQ(kTestUrl, store->last_saved_page().url);
- EXPECT_EQ(kTestClientId1, store->last_saved_page().client_id);
- base::FilePath archiver_path = last_archiver_path();
- EXPECT_EQ(archiver_path, store->last_saved_page().file_path);
- EXPECT_EQ(kTestFileSize, store->last_saved_page().file_size);
- EXPECT_EQ("", store->last_saved_page().request_origin);
- EXPECT_EQ(SavePageResult::SUCCESS, last_save_result());
-
- ResetResults();
-
- const std::vector<OfflinePageItem>& offline_pages = GetAllPages();
-
- EXPECT_EQ(2UL, offline_pages.size());
- // Offline IDs are random, so the order of the pages is also random
- // So load in the right page for the validation below.
- const OfflinePageItem* page1 = nullptr;
- const OfflinePageItem* page2 = nullptr;
- if (offline_pages[0].client_id == kTestClientId1) {
- page1 = &offline_pages[0];
- page2 = &offline_pages[1];
- } else {
- page1 = &offline_pages[1];
- page2 = &offline_pages[0];
- }
-
- EXPECT_EQ(kTestUrl, page1->url);
- EXPECT_EQ(kTestClientId1, page1->client_id);
- EXPECT_EQ(archiver_path, page1->file_path);
- EXPECT_EQ(kTestFileSize, page1->file_size);
- EXPECT_EQ(0, page1->access_count);
- EXPECT_EQ(0, page1->flags);
- EXPECT_EQ("", page1->request_origin);
- EXPECT_EQ(kTestUrl2, page2->url);
- EXPECT_EQ(kTestClientId2, page2->client_id);
- EXPECT_EQ(archiver_path2, page2->file_path);
- EXPECT_EQ(kTestFileSize, page2->file_size);
- EXPECT_EQ(0, page2->access_count);
- EXPECT_EQ(0, page2->flags);
- EXPECT_EQ(kRequestOrigin, page2->request_origin);
-}
-
-TEST_F(OfflinePageModelImplTest, SavePageOnBackground) {
- std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver(
- kTestUrl, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED));
- // archiver_ptr will be valid until after first PumpLoop() is called.
- OfflinePageTestArchiver* archiver_ptr = archiver.get();
-
- OfflinePageModel::SavePageParams save_page_params;
- save_page_params.url = kTestUrl;
- save_page_params.client_id = kTestClientId1;
- save_page_params.is_background = true;
- save_page_params.use_page_problem_detectors = false;
- SavePageWithParamsAsync(save_page_params, std::move(archiver));
- EXPECT_TRUE(archiver_ptr->create_archive_called());
- // |remove_popup_overlay| should be turned on on background mode.
- EXPECT_TRUE(archiver_ptr->create_archive_params().remove_popup_overlay);
-
- PumpLoop();
-}
-
-TEST_F(OfflinePageModelImplTest, AddPage) {
- base::FilePath file_path;
- ASSERT_TRUE(base::CreateTemporaryFileInDir(temporary_dir_path(), &file_path));
- int64_t offline_id =
- base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1;
-
- // Adds a fresh page.
- OfflinePageItem offline_page(kTestUrl, offline_id, kTestClientId1, file_path,
- kTestFileSize);
- offline_page.title = kTestTitle;
- offline_page.original_url = kTestUrl2;
- offline_page.request_origin = kRequestOrigin;
- AddPage(offline_page);
-
- EXPECT_EQ(AddPageResult::SUCCESS, last_add_result());
-
- const std::vector<OfflinePageItem>& offline_pages = GetAllPages();
- ASSERT_EQ(1UL, offline_pages.size());
- EXPECT_EQ(kTestUrl, offline_pages[0].url);
- EXPECT_EQ(kTestClientId1, offline_pages[0].client_id);
- EXPECT_EQ(kTestUrl2, offline_pages[0].original_url);
- EXPECT_EQ(kTestTitle, offline_pages[0].title);
- EXPECT_EQ(file_path, offline_pages[0].file_path);
- EXPECT_EQ(kTestFileSize, offline_pages[0].file_size);
- EXPECT_EQ(kRequestOrigin, offline_pages[0].request_origin);
-
- // Trying to adding a same page should result in ALREADY_EXISTS error.
- AddPage(offline_page);
- EXPECT_EQ(AddPageResult::ALREADY_EXISTS, last_add_result());
-
- //
- GetStore()->set_test_scenario(
- OfflinePageTestStore::TestScenario::WRITE_FAILED);
- AddPage(offline_page);
- EXPECT_EQ(AddPageResult::STORE_FAILURE, last_add_result());
-}
-
-TEST_F(OfflinePageModelImplTest, MarkPageAccessed) {
- SavePage(kTestUrl, kTestClientId1);
-
- // This will increase access_count by one.
- model()->MarkPageAccessed(last_save_offline_id());
- PumpLoop();
-
- const std::vector<OfflinePageItem>& offline_pages = GetAllPages();
-
- EXPECT_EQ(1UL, offline_pages.size());
- EXPECT_EQ(kTestUrl, offline_pages[0].url);
- EXPECT_EQ(kTestClientId1, offline_pages[0].client_id);
- EXPECT_EQ(kTestFileSize, offline_pages[0].file_size);
- EXPECT_EQ(1, offline_pages[0].access_count);
-}
-
-TEST_F(OfflinePageModelImplTest, GetAllPagesStoreEmpty) {
- const std::vector<OfflinePageItem>& offline_pages = GetAllPages();
-
- EXPECT_EQ(0UL, offline_pages.size());
-}
-
-TEST_F(OfflinePageModelImplTest, DeletePageSuccessful) {
- OfflinePageTestStore* store = GetStore();
-
- // Save one page with request origin.
- SavePage(kTestUrl, kTestClientId1, kRequestOrigin);
- int64_t offline1 = last_save_offline_id();
- EXPECT_EQ(SavePageResult::SUCCESS, last_save_result());
- EXPECT_EQ(1u, store->GetAllPages().size());
-
- ResetResults();
-
- // Save another page, no request origin.
- SavePage(kTestUrl2, kTestClientId2);
- int64_t offline2 = last_save_offline_id();
- EXPECT_EQ(SavePageResult::SUCCESS, last_save_result());
- EXPECT_EQ(2u, store->GetAllPages().size());
-
- ResetResults();
-
- // Delete one page.
- DeletePage(offline1, base::Bind(&OfflinePageModelImplTest::OnDeletePageDone,
- AsWeakPtr()));
-
- PumpLoop();
-
- EXPECT_EQ(last_deleted_offline_id(), offline1);
- EXPECT_EQ(last_deleted_client_id(), kTestClientId1);
- EXPECT_EQ(last_deleted_request_origin(), kRequestOrigin);
- EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result());
- ASSERT_EQ(1u, store->GetAllPages().size());
- EXPECT_EQ(kTestUrl2, store->GetAllPages()[0].url);
-
- // Delete another page.
- DeletePage(offline2, base::Bind(&OfflinePageModelImplTest::OnDeletePageDone,
- AsWeakPtr()));
-
- ResetResults();
-
- PumpLoop();
-
- EXPECT_EQ(last_deleted_offline_id(), offline2);
- EXPECT_EQ(last_deleted_client_id(), kTestClientId2);
- EXPECT_EQ(last_deleted_request_origin(), "");
- EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result());
- EXPECT_EQ(0u, store->GetAllPages().size());
-}
-
-TEST_F(OfflinePageModelImplTest, DeleteCachedPageByPredicateUserRequested) {
- OfflinePageTestStore* store = GetStore();
-
- // Save one page.
- SavePage(kTestUrl, kTestClientId1);
- int64_t offline1 = last_save_offline_id();
- EXPECT_EQ(SavePageResult::SUCCESS, last_save_result());
- EXPECT_EQ(1u, store->GetAllPages().size());
-
- ResetResults();
-
- // Save an user-requested page in same domain.
- SavePage(kTestUrl, kTestUserRequestedClientId);
- int64_t offline2 = last_save_offline_id();
- EXPECT_EQ(SavePageResult::SUCCESS, last_save_result());
- EXPECT_EQ(2u, store->GetAllPages().size());
-
- ResetResults();
-
- // Delete the second page.
- model()->DeleteCachedPagesByURLPredicate(
- base::Bind(&URLSpecContains, "example.com"),
- base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, AsWeakPtr()));
-
- PumpLoop();
-
- EXPECT_EQ(last_deleted_offline_id(), offline1);
- EXPECT_EQ(last_deleted_client_id(), kTestClientId1);
- EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result());
- ASSERT_EQ(1u, store->GetAllPages().size());
- EXPECT_EQ(kTestUrl, store->GetAllPages()[0].url);
- EXPECT_EQ(offline2, store->GetAllPages()[0].offline_id);
-}
-
-TEST_F(OfflinePageModelImplTest, DeleteCachedPageByPredicate) {
- OfflinePageTestStore* store = GetStore();
-
- // Save one page.
- SavePage(kTestUrl, kTestClientId1);
- int64_t offline1 = last_save_offline_id();
- EXPECT_EQ(SavePageResult::SUCCESS, last_save_result());
- EXPECT_EQ(1u, store->GetAllPages().size());
-
- ResetResults();
-
- // Save another page.
- SavePage(kTestUrl2, kTestClientId2);
- int64_t offline2 = last_save_offline_id();
- EXPECT_EQ(SavePageResult::SUCCESS, last_save_result());
- EXPECT_EQ(2u, store->GetAllPages().size());
-
- ResetResults();
-
- // Delete the second page.
- model()->DeleteCachedPagesByURLPredicate(
- base::Bind(&URLSpecContains, "page.com"),
- base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, AsWeakPtr()));
-
- PumpLoop();
-
- EXPECT_EQ(last_deleted_offline_id(), offline2);
- EXPECT_EQ(last_deleted_client_id(), kTestClientId2);
- EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result());
- ASSERT_EQ(1u, store->GetAllPages().size());
- EXPECT_EQ(kTestUrl, store->GetAllPages()[0].url);
-
- ResetResults();
-
- // Delete the first page.
- model()->DeleteCachedPagesByURLPredicate(
- base::Bind(&URLSpecContains, "example.com"),
- base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, AsWeakPtr()));
-
- PumpLoop();
-
- EXPECT_EQ(last_deleted_offline_id(), offline1);
- EXPECT_EQ(last_deleted_client_id(), kTestClientId1);
- EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result());
- EXPECT_EQ(0u, store->GetAllPages().size());
-}
-
-TEST_F(OfflinePageModelImplTest, DeletePageNotFound) {
- DeletePage(1234LL, base::Bind(&OfflinePageModelImplTest::OnDeletePageDone,
- AsWeakPtr()));
- PumpLoop();
-
- EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result());
-
- ResetResults();
-
- model()->DeleteCachedPagesByURLPredicate(
- base::Bind(&URLSpecContains, "page.com"),
- base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, AsWeakPtr()));
- PumpLoop();
-
- EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result());
-}
-
-TEST_F(OfflinePageModelImplTest, DeletePageStoreFailureOnRemove) {
- // Save a page.
- SavePage(kTestUrl, kTestClientId1);
- int64_t offline_id = last_save_offline_id();
- ResetResults();
-
- // Try to delete this page.
- GetStore()->set_test_scenario(
- OfflinePageTestStore::TestScenario::REMOVE_FAILED);
- DeletePage(offline_id, base::Bind(&OfflinePageModelImplTest::OnDeletePageDone,
- AsWeakPtr()));
- PumpLoop();
- EXPECT_EQ(DeletePageResult::STORE_FAILURE, last_delete_result());
-}
-
-TEST_F(OfflinePageModelImplTest, DetectThatOfflineCopyIsMissing) {
- // Save a page.
- SavePage(kTestUrl, kTestClientId1);
- int64_t offline_id = last_save_offline_id();
-
- ResetResults();
-
- std::unique_ptr<OfflinePageItem> page = GetPageByOfflineId(offline_id);
-
- // Delete the offline copy of the page.
- base::DeleteFile(page->file_path, false);
-
- // Resetting the model will cause a consistency check.
- ResetModel();
-
- PumpLoop();
-
- // Check if the page has been expired.
- EXPECT_EQ(0UL, GetAllPages().size());
-}
-
-TEST_F(OfflinePageModelImplTest, DetectThatOfflineCopyIsMissingAfterLoad) {
- // Save a page.
- SavePage(kTestUrl, kTestClientId1);
- int64_t offline_id = last_save_offline_id();
-
- ResetResults();
-
- std::unique_ptr<OfflinePageItem> page = GetPageByOfflineId(offline_id);
- // Delete the offline copy of the page and check the metadata.
- base::DeleteFile(page->file_path, false);
- // Reseting the model should trigger the metadata consistency check as well.
- ResetModel();
- PumpLoop();
-
- // Check if the page has been expired.
- EXPECT_EQ(0UL, GetAllPages().size());
-}
-
-TEST_F(OfflinePageModelImplTest, DetectThatHeadlessPageIsDeleted) {
- // Save a page.
- SavePage(kTestUrl, kTestClientId1);
- int64_t offline_id = last_save_offline_id();
-
- ResetResults();
- std::unique_ptr<OfflinePageItem> page = GetPageByOfflineId(offline_id);
- base::FilePath path = page->file_path;
- EXPECT_TRUE(base::PathExists(path));
- GetStore()->ClearAllPages();
-
- EXPECT_TRUE(base::PathExists(path));
- // Since we've manually changed the store, we have to reload the model to
- // actually refresh the in-memory copy in model. Otherwise GetAllPages()
- // would still have the page we saved above.
- ResetModel();
- PumpLoop();
-
- EXPECT_EQ(0UL, GetAllPages().size());
- EXPECT_FALSE(base::PathExists(path));
-}
-
-// This test is affected by https://crbug.com/725685, which only affects windows
-// platform.
-#if defined(OS_WIN)
-#define MAYBE_DeleteTemporaryPagesInWrongDir \
- DISABLED_DeleteTemporaryPagesInWrongDir
-#else
-#define MAYBE_DeleteTemporaryPagesInWrongDir DeleteTemporaryPagesInWrongDir
-#endif
-TEST_F(OfflinePageModelImplTest, MAYBE_DeleteTemporaryPagesInWrongDir) {
- // Set temporary directory same with persistent one.
- SetTemporaryDirSameWithPersistent(true);
- ResetModel();
- PumpLoop();
-
- // Save a temporary page.
- SavePage(kTestUrl, kTestClientId1);
- int64_t temporary_id = last_save_offline_id();
- // Save a persistent page.
- SavePage(kTestUrl2, kTestUserRequestedClientId);
- int64_t persistent_id = last_save_offline_id();
-
- EXPECT_EQ(2UL, GetAllPages().size());
- std::unique_ptr<OfflinePageItem> temporary_page =
- GetPageByOfflineId(temporary_id);
- std::unique_ptr<OfflinePageItem> persistent_page =
- GetPageByOfflineId(persistent_id);
-
- EXPECT_EQ(temporary_page->file_path.DirName(),
- persistent_page->file_path.DirName());
-
- // Reset model to trigger consistency check, and let temporary directory be
- // different with the persistent one. The previously saved temporary page will
- // be treated as 'saved in persistent location'.
- SetTemporaryDirSameWithPersistent(false);
- ResetModel();
- PumpLoop();
-
- // Check the temporary page is deleted.
- EXPECT_EQ(1UL, GetAllPages().size());
- EXPECT_EQ(persistent_id, GetAllPages()[0].offline_id);
-}
-
-TEST_F(OfflinePageModelImplTest, DeleteMultiplePages) {
- OfflinePageTestStore* store = GetStore();
-
- // Save 3 pages.
- SavePage(kTestUrl, kTestClientId1);
- int64_t offline1 = last_save_offline_id();
-
- SavePage(kTestUrl2, kTestClientId2);
- int64_t offline2 = last_save_offline_id();
-
- SavePage(kTestUrl3, kTestClientId3);
- PumpLoop();
-
- EXPECT_EQ(3u, store->GetAllPages().size());
-
- // Delete multiple pages.
- std::vector<int64_t> ids_to_delete;
- ids_to_delete.push_back(offline2);
- ids_to_delete.push_back(offline1);
- ids_to_delete.push_back(23434LL); // Non-existent ID.
- model()->DeletePagesByOfflineId(
- ids_to_delete,
- base::Bind(&OfflinePageModelImplTest::OnDeletePageDone, AsWeakPtr()));
- PumpLoop();
-
- // Success is expected if at least one page is deleted successfully.
- EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_result());
- EXPECT_EQ(1u, store->GetAllPages().size());
-}
-
-TEST_F(OfflinePageModelImplTest, GetPageByOfflineId) {
- SavePage(kTestUrl, kTestClientId1);
- int64_t offline1 = last_save_offline_id();
- SavePage(kTestUrl2, kTestClientId2);
- int64_t offline2 = last_save_offline_id();
-
- std::unique_ptr<OfflinePageItem> page = GetPageByOfflineId(offline1);
- ASSERT_TRUE(page);
- EXPECT_EQ(kTestUrl, page->url);
- EXPECT_EQ(kTestClientId1, page->client_id);
- EXPECT_EQ(kTestFileSize, page->file_size);
-
- page = GetPageByOfflineId(offline2);
- ASSERT_TRUE(page);
- EXPECT_EQ(kTestUrl2, page->url);
- EXPECT_EQ(kTestClientId2, page->client_id);
- EXPECT_EQ(kTestFileSize, page->file_size);
-
- page = GetPageByOfflineId(-42);
- EXPECT_FALSE(page);
-}
-
-TEST_F(OfflinePageModelImplTest, GetPagesByFinalURL) {
- SavePage(kTestUrl, kTestClientId1);
- SavePage(kTestUrl2, kTestClientId2);
-
- MultipleOfflinePageItemResult pages = GetPagesByFinalURL(kTestUrl2);
- EXPECT_EQ(1U, pages.size());
- EXPECT_EQ(kTestUrl2, pages[0].url);
- EXPECT_EQ(kTestClientId2, pages[0].client_id);
-
- pages = GetPagesByFinalURL(kTestUrl);
- EXPECT_EQ(1U, pages.size());
- EXPECT_EQ(kTestUrl, pages[0].url);
- EXPECT_EQ(kTestClientId1, pages[0].client_id);
-
- pages = GetPagesByFinalURL(GURL("http://foo"));
- EXPECT_EQ(0U, pages.size());
-}
-
-TEST_F(OfflinePageModelImplTest, GetPagesByFinalURLWithFragmentStripped) {
- SavePage(kTestUrl, kTestClientId1);
- SavePage(kTestUrl2WithFragment, kTestClientId2);
-
- MultipleOfflinePageItemResult pages =
- GetPagesByFinalURL(kTestUrlWithFragment);
- EXPECT_EQ(1U, pages.size());
- EXPECT_EQ(kTestUrl, pages[0].url);
- EXPECT_EQ(kTestClientId1, pages[0].client_id);
-
- pages = GetPagesByFinalURL(kTestUrl2);
- EXPECT_EQ(1U, pages.size());
- EXPECT_EQ(kTestUrl2WithFragment, pages[0].url);
- EXPECT_EQ(kTestClientId2, pages[0].client_id);
-
- pages = GetPagesByFinalURL(kTestUrl2WithFragment2);
- EXPECT_EQ(1U, pages.size());
- EXPECT_EQ(kTestUrl2WithFragment, pages[0].url);
- EXPECT_EQ(kTestClientId2, pages[0].client_id);
-}
-
-TEST_F(OfflinePageModelImplTest, GetPagesByAllURLS) {
- std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver(
- kTestUrl, OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED));
- SavePageWithArchiverAsync(kTestUrl, kTestClientId1, kTestUrl2, "",
- std::move(archiver));
- PumpLoop();
-
- SavePage(kTestUrl2, kTestClientId2);
-
- MultipleOfflinePageItemResult pages = GetPagesByAllURLS(kTestUrl2);
- ASSERT_EQ(2U, pages.size());
- // Validates the items regardless their order.
- int i = -1;
- if (pages[0].url == kTestUrl2)
- i = 0;
- else if (pages[1].url == kTestUrl2)
- i = 1;
- ASSERT_NE(-1, i);
- EXPECT_EQ(kTestUrl2, pages[i].url);
- EXPECT_EQ(kTestClientId2, pages[i].client_id);
- EXPECT_EQ(GURL(), pages[i].original_url);
- EXPECT_EQ(kTestUrl, pages[1 - i].url);
- EXPECT_EQ(kTestClientId1, pages[1 - i].client_id);
- EXPECT_EQ(kTestUrl2, pages[1 - i].original_url);
-}
-
-TEST_F(OfflinePageModelImplTest, CanSaveURL) {
- EXPECT_TRUE(OfflinePageModel::CanSaveURL(GURL("http://foo")));
- EXPECT_TRUE(OfflinePageModel::CanSaveURL(GURL("https://foo")));
- EXPECT_FALSE(OfflinePageModel::CanSaveURL(GURL("file:///foo")));
- EXPECT_FALSE(OfflinePageModel::CanSaveURL(GURL("data:image/png;base64,ab")));
- EXPECT_FALSE(OfflinePageModel::CanSaveURL(GURL("chrome://version")));
- EXPECT_FALSE(OfflinePageModel::CanSaveURL(GURL("chrome-native://newtab/")));
- EXPECT_FALSE(OfflinePageModel::CanSaveURL(GURL("/invalid/url.mhtml")));
-}
-
-TEST_F(OfflinePageModelImplTest, SaveRetrieveMultipleClientIds) {
- EXPECT_FALSE(HasPages(kTestClientNamespace));
- SavePage(kTestUrl, kTestClientId1);
- int64_t offline1 = last_save_offline_id();
- EXPECT_TRUE(HasPages(kTestClientNamespace));
-
- SavePage(kTestUrl2, kTestClientId1);
- int64_t offline2 = last_save_offline_id();
-
- EXPECT_NE(offline1, offline2);
-
- const std::vector<int64_t> ids = GetOfflineIdsForClientId(kTestClientId1);
-
- EXPECT_EQ(2UL, ids.size());
-
- std::set<int64_t> id_set;
- for (size_t i = 0; i < ids.size(); i++) {
- id_set.insert(ids[i]);
- }
-
- EXPECT_TRUE(id_set.find(offline1) != id_set.end());
- EXPECT_TRUE(id_set.find(offline2) != id_set.end());
-}
-
-TEST_F(OfflinePageModelImplTest, SaveMultiplePagesWithSameURLBySameClientId) {
- EXPECT_FALSE(HasPages(kTestClientNamespace));
- SavePage(kTestUrl, kTestClientId1);
- int64_t offline1 = last_save_offline_id();
- EXPECT_TRUE(HasPages(kTestClientNamespace));
-
- SavePage(kTestUrl, kTestClientId1);
- int64_t offline2 = last_save_offline_id();
-
- EXPECT_NE(offline1, offline2);
-
- const std::vector<int64_t> ids = GetOfflineIdsForClientId(kTestClientId1);
-
- EXPECT_EQ(1UL, ids.size());
-
- std::set<int64_t> id_set;
- for (size_t i = 0; i < ids.size(); i++) {
- id_set.insert(ids[i]);
- }
-
- EXPECT_TRUE(id_set.find(offline2) != id_set.end());
-}
-
-TEST_F(OfflinePageModelImplTest, DownloadMetrics) {
- EXPECT_FALSE(HasPages(kUserRequestedNamespace));
- SavePage(kTestUrl, kTestUserRequestedClientId);
- histograms().ExpectUniqueSample(
- "OfflinePages.DownloadSavedPageDuplicateCount", 1, 1);
- FastForwardBy(base::TimeDelta::FromMinutes(1));
- histograms().ExpectTotalCount(
- "OfflinePages.DownloadSavedPageTimeSinceDuplicateSaved", 0);
- SavePage(kTestUrl, kTestUserRequestedClientId);
- histograms().ExpectTotalCount("OfflinePages.DownloadSavedPageDuplicateCount",
- 2);
- histograms().ExpectBucketCount("OfflinePages.DownloadSavedPageDuplicateCount",
- 2, 1);
- histograms().ExpectBucketCount("OfflinePages.DownloadSavedPageDuplicateCount",
- 1, 1);
- histograms().ExpectTotalCount(
- "OfflinePages.DownloadSavedPageTimeSinceDuplicateSaved", 1);
- histograms().ExpectTotalCount(
- "OfflinePages.DownloadDeletedPageDuplicateCount", 0);
-
- // void DeletePage(int64_t offline_id, const DeletePageCallback& callback) {
- const std::vector<int64_t> ids =
- GetOfflineIdsForClientId(kTestUserRequestedClientId);
- ASSERT_EQ(2U, ids.size());
-
- DeletePage(ids[0], base::Bind(&OfflinePageModelImplTest::OnDeletePageDone,
- AsWeakPtr()));
- PumpLoop();
- histograms().ExpectUniqueSample(
- "OfflinePages.DownloadDeletedPageDuplicateCount", 2, 1);
- DeletePage(ids[1], base::Bind(&OfflinePageModelImplTest::OnDeletePageDone,
- AsWeakPtr()));
- PumpLoop();
- // No change when we delete the last page.
- histograms().ExpectTotalCount(
- "OfflinePages.DownloadDeletedPageDuplicateCount", 2);
- histograms().ExpectBucketCount(
- "OfflinePages.DownloadDeletedPageDuplicateCount", 1, 1);
- histograms().ExpectBucketCount(
- "OfflinePages.DownloadDeletedPageDuplicateCount", 2, 1);
-}
-
-TEST_F(OfflinePageModelImplTest, GetPagesByClientIds) {
- // We will save 2 pages.
- std::pair<SavePageResult, int64_t> saved_pages[3];
- saved_pages[0] = SavePage(kTestUrl, kTestClientId1);
- saved_pages[1] = SavePage(kTestUrl2, kTestClientId2);
-
- for (const auto& save_result : saved_pages) {
- ASSERT_EQ(OfflinePageModel::SavePageResult::SUCCESS,
- std::get<0>(save_result));
- }
-
- std::vector<ClientId> client_ids = {kTestClientId2};
- std::vector<OfflinePageItem> offline_pages = GetPagesByClientIds(client_ids);
- EXPECT_EQ(1U, offline_pages.size());
-
- const OfflinePageItem& item = offline_pages[0];
- EXPECT_EQ(kTestClientId2.name_space, item.client_id.name_space);
- EXPECT_EQ(kTestClientId2.id, item.client_id.id);
- EXPECT_EQ(kTestUrl2, item.url);
-}
-
-TEST_F(OfflinePageModelImplTest, GetPagesByRequestOrigin) {
- // We will save 3 pages.
- std::string origin1("abc.xyz");
- std::string origin2("abc");
- std::pair<SavePageResult, int64_t> save_pages[3];
- save_pages[0] = SavePage(kTestUrl, kTestClientId1, origin1);
- save_pages[1] = SavePage(kTestUrl2, kTestClientId2, origin2);
- save_pages[2] = SavePage(kTestUrl3, kTestClientId3, origin1);
-
- for (const auto& save_result : save_pages) {
- ASSERT_EQ(OfflinePageModel::SavePageResult::SUCCESS,
- std::get<0>(save_result));
- }
-
- std::vector<OfflinePageItem> offline_pages = GetPagesByRequestOrigin(origin2);
- EXPECT_EQ(1U, offline_pages.size());
-
- const OfflinePageItem& item = offline_pages[0];
- EXPECT_EQ(kTestUrl2, item.url);
- EXPECT_EQ(origin2, item.request_origin);
- EXPECT_EQ(kTestClientId2.name_space, item.client_id.name_space);
- EXPECT_EQ(kTestClientId2.id, item.client_id.id);
-}
-
-TEST_F(OfflinePageModelImplTest, DeletePagesByClientIds) {
- // We will save 3 pages.
- std::pair<SavePageResult, int64_t> saved_pages[3];
- saved_pages[0] = SavePage(kTestUrl, kTestClientId1);
- saved_pages[1] = SavePage(kTestUrl2, kTestClientId2);
- saved_pages[2] = SavePage(kTestUrl3, kTestClientId3);
-
- for (const auto& save_result : saved_pages) {
- ASSERT_EQ(OfflinePageModel::SavePageResult::SUCCESS,
- std::get<0>(save_result));
- }
-
- std::vector<ClientId> client_ids = {kTestClientId1, kTestClientId2};
- DeletePagesByClientIds(client_ids);
- std::vector<OfflinePageItem> offline_pages = GetAllPages();
- ASSERT_EQ(1U, offline_pages.size());
-
- const OfflinePageItem& item = offline_pages[0];
- EXPECT_EQ(kTestClientId3.name_space, item.client_id.name_space);
- EXPECT_EQ(kTestClientId3.id, item.client_id.id);
- EXPECT_EQ(kTestUrl3, item.url);
-}
-
-TEST_F(OfflinePageModelImplTest, CustomTabsNamespace) {
- SavePage(kTestUrl, ClientId(kCCTNamespace, "123"));
- std::string histogram_name = "OfflinePages.SavePageResult.";
- histogram_name += kCCTNamespace;
-
- histograms().ExpectUniqueSample(histogram_name,
- static_cast<int>(SavePageResult::SUCCESS), 1);
-}
-
-TEST_F(OfflinePageModelImplTest, DownloadNamespace) {
- SavePage(kTestUrl, ClientId(kDownloadNamespace, "123"));
- std::string histogram_name = "OfflinePages.SavePageResult.";
- histogram_name += kDownloadNamespace;
-
- histograms().ExpectUniqueSample(histogram_name,
- static_cast<int>(SavePageResult::SUCCESS), 1);
-}
-
-TEST_F(OfflinePageModelImplTest, NewTabPageNamespace) {
- SavePage(kTestUrl, ClientId(kNTPSuggestionsNamespace, "123"));
- std::string histogram_name = "OfflinePages.SavePageResult.";
- histogram_name += kNTPSuggestionsNamespace;
-
- histograms().ExpectUniqueSample(histogram_name,
- static_cast<int>(SavePageResult::SUCCESS), 1);
-}
-
-TEST_F(OfflinePageModelImplTest, StoreLoadFailurePersists) {
- // Initial database load is successful. Only takes 1 attempt.
- EXPECT_EQ(1, GetStore()->initialize_attempts_count());
- histograms().ExpectUniqueSample("OfflinePages.Model.FinalLoadSuccessful",
- true, 1);
- histograms().ExpectUniqueSample("OfflinePages.Model.InitAttemptsSpent", 1, 1);
-
- GetStore()->set_test_scenario(
- OfflinePageTestStore::TestScenario::LOAD_FAILED_RESET_SUCCESS);
- ResetModel();
- // Skip all the retries with delays.
- FastForwardUntilNoTasksRemain();
- // All available attempts were spent.
- EXPECT_EQ(3, GetStore()->initialize_attempts_count());
-
- // Should record failure to load.
- histograms().ExpectBucketCount("OfflinePages.Model.FinalLoadSuccessful",
- false, 1);
- // Should show the previous count since no attempts are recorded for
- // failure. In case of failure, all attempts are assumed spent.
- histograms().ExpectUniqueSample("OfflinePages.Model.InitAttemptsSpent", 1, 1);
-
- const std::vector<OfflinePageItem>& offline_pages = GetAllPages();
-
- // Model will 'load' but the store underneath it is not functional and
- // will silently fail all sql operations.
- EXPECT_TRUE(model()->is_loaded_);
- EXPECT_EQ(StoreState::FAILED_LOADING, GetStore()->state());
- EXPECT_EQ(0UL, offline_pages.size());
-
- // The pages can still be saved, they will not be persisted to disk.
- // Verify no crashes and error code returned.
- std::pair<SavePageResult, int64_t> result =
- SavePage(kTestUrl, ClientId(kDownloadNamespace, "123"));
- EXPECT_EQ(SavePageResult::STORE_FAILURE, result.first);
-}
-
-TEST_F(OfflinePageModelImplTest, GetPagesByNamespace) {
- SavePage(kTestUrl, ClientId(kCCTNamespace, "123"));
- SavePage(kTestUrl, ClientId(kDownloadNamespace, "456"));
- base::FilePath archive_path(last_archiver_path());
- SavePage(kTestUrl, ClientId(kNTPSuggestionsNamespace, "789"));
-
- MultipleOfflinePageItemResult offline_pages;
- model()->GetPagesByNamespace(
- kDownloadNamespace,
- base::Bind(&OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult,
- AsWeakPtr(), base::Unretained(&offline_pages)));
- PumpLoop();
-
- ASSERT_EQ(1UL, offline_pages.size());
- EXPECT_EQ(kTestUrl, offline_pages[0].url);
- EXPECT_EQ("456", offline_pages[0].client_id.id);
- EXPECT_EQ(kDownloadNamespace, offline_pages[0].client_id.name_space);
- EXPECT_EQ(archive_path, offline_pages[0].file_path);
- EXPECT_EQ(kTestFileSize, offline_pages[0].file_size);
- EXPECT_EQ(0, offline_pages[0].access_count);
- EXPECT_EQ(0, offline_pages[0].flags);
- EXPECT_EQ(kTestTitle, offline_pages[0].title);
- EXPECT_EQ(GURL(), offline_pages[0].original_url);
- EXPECT_EQ("", offline_pages[0].request_origin);
-}
-
-TEST_F(OfflinePageModelImplTest, GetPagesRemovedOnCacheReset) {
- SavePage(kTestUrl, ClientId(kCCTNamespace, "123"));
- base::FilePath archive_path(last_archiver_path());
- SavePage(kTestUrl, ClientId(kDownloadNamespace, "456"));
- SavePage(kTestUrl, ClientId(kNTPSuggestionsNamespace, "789"));
-
- MultipleOfflinePageItemResult offline_pages;
- model()->GetPagesRemovedOnCacheReset(
- base::Bind(&OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult,
- AsWeakPtr(), base::Unretained(&offline_pages)));
- PumpLoop();
-
- ASSERT_EQ(1UL, offline_pages.size());
- EXPECT_EQ(kTestUrl, offline_pages[0].url);
- EXPECT_EQ("123", offline_pages[0].client_id.id);
- EXPECT_EQ(kCCTNamespace, offline_pages[0].client_id.name_space);
- EXPECT_EQ(archive_path, offline_pages[0].file_path);
- EXPECT_EQ(kTestFileSize, offline_pages[0].file_size);
- EXPECT_EQ(0, offline_pages[0].access_count);
- EXPECT_EQ(0, offline_pages[0].flags);
- EXPECT_EQ(kTestTitle, offline_pages[0].title);
- EXPECT_EQ(GURL(), offline_pages[0].original_url);
- EXPECT_EQ("", offline_pages[0].request_origin);
-}
-
-TEST_F(OfflinePageModelImplTest, GetPagesSupportedByDownloads) {
- SavePage(kTestUrl, ClientId(kCCTNamespace, "123"));
- SavePage(kTestUrl, ClientId(kDownloadNamespace, "456"));
- base::FilePath download_archive_path(last_archiver_path());
- SavePage(kTestUrl, ClientId(kNTPSuggestionsNamespace, "789"));
- base::FilePath ntp_suggestions_archive_path(last_archiver_path());
-
- MultipleOfflinePageItemResult offline_pages;
- model()->GetPagesSupportedByDownloads(
- base::Bind(&OfflinePageModelImplTest::OnGetMultipleOfflinePageItemsResult,
- AsWeakPtr(), base::Unretained(&offline_pages)));
- PumpLoop();
-
- ASSERT_EQ(2UL, offline_pages.size());
- int download_index = 0;
- int ntp_suggestions_index = 1;
- if (offline_pages[0].client_id.name_space != kDownloadNamespace) {
- download_index = 1;
- ntp_suggestions_index = 0;
- }
-
- EXPECT_EQ(kTestUrl, offline_pages[download_index].url);
- EXPECT_EQ("456", offline_pages[download_index].client_id.id);
- EXPECT_EQ(kDownloadNamespace,
- offline_pages[download_index].client_id.name_space);
- EXPECT_EQ(download_archive_path, offline_pages[download_index].file_path);
- EXPECT_EQ(kTestFileSize, offline_pages[download_index].file_size);
- EXPECT_EQ(0, offline_pages[download_index].access_count);
- EXPECT_EQ(0, offline_pages[download_index].flags);
- EXPECT_EQ(kTestTitle, offline_pages[download_index].title);
- EXPECT_EQ(GURL(), offline_pages[download_index].original_url);
- EXPECT_EQ("", offline_pages[download_index].request_origin);
-
- EXPECT_EQ(kTestUrl, offline_pages[ntp_suggestions_index].url);
- EXPECT_EQ("789", offline_pages[ntp_suggestions_index].client_id.id);
- EXPECT_EQ(kNTPSuggestionsNamespace,
- offline_pages[ntp_suggestions_index].client_id.name_space);
- EXPECT_EQ(ntp_suggestions_archive_path,
- offline_pages[ntp_suggestions_index].file_path);
- EXPECT_EQ(kTestFileSize, offline_pages[ntp_suggestions_index].file_size);
- EXPECT_EQ(0, offline_pages[ntp_suggestions_index].access_count);
- EXPECT_EQ(0, offline_pages[ntp_suggestions_index].flags);
- EXPECT_EQ(kTestTitle, offline_pages[ntp_suggestions_index].title);
- EXPECT_EQ(GURL(), offline_pages[ntp_suggestions_index].original_url);
- EXPECT_EQ("", offline_pages[ntp_suggestions_index].request_origin);
-}
-
-// This test is affected by https://crbug.com/725685, which only affects windows
-// platform.
-#if defined(OS_WIN)
-#define MAYBE_CheckPagesSavedInSeparateDirs \
- DISABLED_CheckPagesSavedInSeparateDirs
-#else
-#define MAYBE_CheckPagesSavedInSeparateDirs CheckPagesSavedInSeparateDirs
-#endif
-TEST_F(OfflinePageModelImplTest, MAYBE_CheckPagesSavedInSeparateDirs) {
- // Save a temporary page.
- SavePage(kTestUrl, kTestClientId1);
- int64_t temporary_id = last_save_offline_id();
- // Save a persistent page.
- SavePage(kTestUrl2, kTestUserRequestedClientId);
- int64_t persistent_id = last_save_offline_id();
-
- std::unique_ptr<OfflinePageItem> temporary_page =
- GetPageByOfflineId(temporary_id);
- std::unique_ptr<OfflinePageItem> persistent_page =
- GetPageByOfflineId(persistent_id);
-
- ASSERT_TRUE(temporary_page);
- ASSERT_TRUE(persistent_page);
-
- base::FilePath temporary_page_path = temporary_page->file_path;
- base::FilePath private_archive_page_path = persistent_page->file_path;
-
- EXPECT_TRUE(temporary_dir_path().IsParent(temporary_page_path));
- EXPECT_TRUE(private_archive_dir_path().IsParent(private_archive_page_path));
- EXPECT_NE(temporary_page_path.DirName(), private_archive_page_path.DirName());
-}
-
-} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/offline_page_model_query.cc b/chromium/components/offline_pages/core/offline_page_model_query.cc
deleted file mode 100644
index a7b0ab4a0ef..00000000000
--- a/chromium/components/offline_pages/core/offline_page_model_query.cc
+++ /dev/null
@@ -1,314 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/offline_pages/core/offline_page_model_query.h"
-
-#include <algorithm>
-#include <memory>
-#include <unordered_set>
-
-namespace offline_pages {
-
-namespace {
-
-int CountMatchingUrls(const GURL& url_pattern,
- const std::set<GURL>& urls,
- bool strip_fragment) {
- int count = 0;
-
- // If |strip_fragment| is true, all urls will be compared after fragments
- // stripped. Otherwise just do exact matching.
- if (strip_fragment) {
- for (const auto& url : urls) {
- GURL::Replacements remove_params;
- remove_params.ClearRef();
- GURL url_without_fragment = url.ReplaceComponents(remove_params);
- if (url_without_fragment == url_pattern.ReplaceComponents(remove_params))
- count++;
- }
- } else {
- count = urls.count(url_pattern);
- }
- return count;
-}
-
-} // namespace
-
-using Requirement = OfflinePageModelQuery::Requirement;
-
-OfflinePageModelQuery::URLSearchParams::URLSearchParams() = default;
-
-OfflinePageModelQuery::URLSearchParams::URLSearchParams(
- std::set<GURL> url_set,
- URLSearchMode search_mode,
- bool strip_frag)
- : urls(url_set), mode(search_mode), strip_fragment(strip_frag) {}
-
-OfflinePageModelQuery::URLSearchParams::URLSearchParams(
- const URLSearchParams& params) = default;
-OfflinePageModelQuery::URLSearchParams::~URLSearchParams() = default;
-
-OfflinePageModelQueryBuilder::OfflinePageModelQueryBuilder()
- : offline_ids_(std::make_pair(Requirement::UNSET, std::vector<int64_t>())) {
-}
-
-OfflinePageModelQueryBuilder::~OfflinePageModelQueryBuilder() = default;
-
-OfflinePageModelQueryBuilder& OfflinePageModelQueryBuilder::SetOfflinePageIds(
- Requirement requirement,
- const std::vector<int64_t>& ids) {
- offline_ids_ = std::make_pair(requirement, ids);
- return *this;
-}
-
-OfflinePageModelQueryBuilder& OfflinePageModelQueryBuilder::SetClientIds(
- Requirement requirement,
- const std::vector<ClientId>& ids) {
- client_ids_ = std::make_pair(requirement, ids);
- return *this;
-}
-
-OfflinePageModelQueryBuilder& OfflinePageModelQueryBuilder::SetRequestOrigin(
- Requirement requirement,
- const std::string& request_origin) {
- request_origin_ = std::make_pair(requirement, request_origin);
- return *this;
-}
-
-OfflinePageModelQueryBuilder& OfflinePageModelQueryBuilder::SetUrls(
- Requirement requirement,
- const std::vector<GURL>& urls,
- URLSearchMode search_mode,
- bool defrag) {
- urls_ = std::make_pair(
- requirement,
- OfflinePageModelQuery::URLSearchParams(
- std::set<GURL>(urls.begin(), urls.end()), search_mode, defrag));
- return *this;
-}
-
-OfflinePageModelQueryBuilder&
-OfflinePageModelQueryBuilder::RequireRemovedOnCacheReset(
- Requirement removed_on_cache_reset) {
- removed_on_cache_reset_ = removed_on_cache_reset;
- return *this;
-}
-
-OfflinePageModelQueryBuilder&
-OfflinePageModelQueryBuilder::RequireSupportedByDownload(
- Requirement supported_by_download) {
- supported_by_download_ = supported_by_download;
- return *this;
-}
-
-OfflinePageModelQueryBuilder&
-OfflinePageModelQueryBuilder::RequireShownAsRecentlyVisitedSite(
- Requirement recently_visited) {
- shown_as_recently_visited_site_ = recently_visited;
- return *this;
-}
-
-OfflinePageModelQueryBuilder&
-OfflinePageModelQueryBuilder::RequireRestrictedToOriginalTab(
- Requirement original_tab) {
- restricted_to_original_tab_ = original_tab;
- return *this;
-}
-
-OfflinePageModelQueryBuilder& OfflinePageModelQueryBuilder::RequireNamespace(
- const std::string& name_space) {
- name_space_ = std::make_unique<std::string>(name_space);
- return *this;
-}
-
-std::unique_ptr<OfflinePageModelQuery> OfflinePageModelQueryBuilder::Build(
- ClientPolicyController* controller) {
- DCHECK(controller);
-
- auto query = std::make_unique<OfflinePageModelQuery>();
-
- query->urls_ = urls_;
- urls_ = std::make_pair(
- Requirement::UNSET,
- OfflinePageModelQuery::URLSearchParams(
- std::set<GURL>(), URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, false));
- query->offline_ids_ = std::make_pair(
- offline_ids_.first, std::set<int64_t>(offline_ids_.second.begin(),
- offline_ids_.second.end()));
- offline_ids_ = std::make_pair(Requirement::UNSET, std::vector<int64_t>());
- query->client_ids_ = std::make_pair(
- client_ids_.first,
- std::set<ClientId>(client_ids_.second.begin(), client_ids_.second.end()));
- client_ids_ = std::make_pair(Requirement::UNSET, std::vector<ClientId>());
-
- query->request_origin_ =
- std::make_pair(request_origin_.first, request_origin_.second);
- request_origin_ = std::make_pair(Requirement::UNSET, std::string());
-
- std::vector<std::string> allowed_namespaces;
- bool uses_namespace_restrictions = false;
-
- std::vector<std::string> namespaces;
- if (name_space_) {
- uses_namespace_restrictions = true;
- namespaces.push_back(*name_space_);
- } else {
- namespaces = controller->GetAllNamespaces();
- }
-
- for (auto& name_space : namespaces) {
- // If any exclusion requirements exist, and the namespace matches one of
- // those excluded by policy, skip adding it to |allowed_namespaces|.
- if ((removed_on_cache_reset_ == Requirement::EXCLUDE_MATCHING &&
- controller->IsRemovedOnCacheReset(name_space)) ||
- (supported_by_download_ == Requirement::EXCLUDE_MATCHING &&
- controller->IsSupportedByDownload(name_space)) ||
- (shown_as_recently_visited_site_ == Requirement::EXCLUDE_MATCHING &&
- controller->IsShownAsRecentlyVisitedSite(name_space)) ||
- (restricted_to_original_tab_ == Requirement::EXCLUDE_MATCHING &&
- controller->IsRestrictedToOriginalTab(name_space))) {
- // Skip namespaces that meet exclusion requirements.
- uses_namespace_restrictions = true;
- continue;
- }
-
- if ((removed_on_cache_reset_ == Requirement::INCLUDE_MATCHING &&
- !controller->IsRemovedOnCacheReset(name_space)) ||
- (supported_by_download_ == Requirement::INCLUDE_MATCHING &&
- !controller->IsSupportedByDownload(name_space)) ||
- (shown_as_recently_visited_site_ == Requirement::INCLUDE_MATCHING &&
- !controller->IsShownAsRecentlyVisitedSite(name_space)) ||
- (restricted_to_original_tab_ == Requirement::INCLUDE_MATCHING &&
- !controller->IsRestrictedToOriginalTab(name_space))) {
- // Skip namespaces that don't meet inclusion requirement.
- uses_namespace_restrictions = true;
- continue;
- }
-
- // Add namespace otherwise.
- allowed_namespaces.emplace_back(name_space);
- }
-
- removed_on_cache_reset_ = Requirement::UNSET;
- supported_by_download_ = Requirement::UNSET;
- shown_as_recently_visited_site_ = Requirement::UNSET;
- restricted_to_original_tab_ = Requirement::UNSET;
-
- if (uses_namespace_restrictions) {
- query->restricted_to_namespaces_ = std::make_unique<std::set<std::string>>(
- allowed_namespaces.begin(), allowed_namespaces.end());
- }
-
- return query;
-}
-
-OfflinePageModelQuery::OfflinePageModelQuery() = default;
-OfflinePageModelQuery::~OfflinePageModelQuery() = default;
-
-std::pair<bool, std::set<std::string>>
-OfflinePageModelQuery::GetRestrictedToNamespaces() const {
- if (!restricted_to_namespaces_)
- return std::make_pair(false, std::set<std::string>());
-
- return std::make_pair(true, *restricted_to_namespaces_);
-}
-
-std::pair<Requirement, std::set<int64_t>>
-OfflinePageModelQuery::GetRestrictedToOfflineIds() const {
- if (offline_ids_.first == Requirement::UNSET)
- return std::make_pair(Requirement::UNSET, std::set<int64_t>());
-
- return offline_ids_;
-}
-
-std::pair<Requirement, std::set<ClientId>>
-OfflinePageModelQuery::GetRestrictedToClientIds() const {
- if (client_ids_.first == Requirement::UNSET)
- return std::make_pair(Requirement::UNSET, std::set<ClientId>());
-
- return client_ids_;
-}
-
-std::pair<Requirement, OfflinePageModelQuery::URLSearchParams>
-OfflinePageModelQuery::GetRestrictedToUrls() const {
- if (std::get<0>(urls_) == Requirement::UNSET) {
- URLSearchParams unset_params;
- unset_params.urls = std::set<GURL>();
- unset_params.mode = URLSearchMode::SEARCH_BY_FINAL_URL_ONLY;
- unset_params.strip_fragment = false;
- return std::make_pair(Requirement::UNSET, unset_params);
- }
- return urls_;
-}
-
-std::pair<Requirement, std::string> OfflinePageModelQuery::GetRequestOrigin()
- const {
- if (request_origin_.first == Requirement::UNSET)
- return std::make_pair(Requirement::UNSET, std::string());
- return request_origin_;
-}
-
-bool OfflinePageModelQuery::Matches(const OfflinePageItem& item) const {
- switch (offline_ids_.first) {
- case Requirement::UNSET:
- break;
- case Requirement::INCLUDE_MATCHING:
- if (offline_ids_.second.count(item.offline_id) == 0)
- return false;
- break;
- case Requirement::EXCLUDE_MATCHING:
- if (offline_ids_.second.count(item.offline_id) > 0)
- return false;
- break;
- }
-
- Requirement url_requirement = urls_.first;
- URLSearchParams params = urls_.second;
- if (url_requirement != Requirement::UNSET) {
- int count = CountMatchingUrls(item.url, params.urls, params.strip_fragment);
- if (params.mode == URLSearchMode::SEARCH_BY_ALL_URLS)
- count += CountMatchingUrls(item.original_url, params.urls,
- false /* strip_fragment */);
- if ((url_requirement == Requirement::INCLUDE_MATCHING && count == 0) ||
- (url_requirement == Requirement::EXCLUDE_MATCHING && count > 0)) {
- return false;
- }
- }
-
- const ClientId& client_id = item.client_id;
- if (restricted_to_namespaces_ &&
- restricted_to_namespaces_->count(client_id.name_space) == 0) {
- return false;
- }
-
- switch (client_ids_.first) {
- case Requirement::UNSET:
- break;
- case Requirement::INCLUDE_MATCHING:
- if (client_ids_.second.count(client_id) == 0)
- return false;
- break;
- case Requirement::EXCLUDE_MATCHING:
- if (client_ids_.second.count(client_id) > 0)
- return false;
- break;
- }
-
- switch (request_origin_.first) {
- case Requirement::UNSET:
- break;
- case Requirement::INCLUDE_MATCHING:
- if (request_origin_.second != item.request_origin)
- return false;
- break;
- case Requirement::EXCLUDE_MATCHING:
- if (request_origin_.second == item.request_origin)
- return false;
- break;
- }
-
- return true;
-}
-
-} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/offline_page_model_query.h b/chromium/components/offline_pages/core/offline_page_model_query.h
deleted file mode 100644
index b20ebb297d0..00000000000
--- a/chromium/components/offline_pages/core/offline_page_model_query.h
+++ /dev/null
@@ -1,185 +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_OFFLINE_PAGES_CORE_OFFLINE_PAGE_MODEL_QUERY_H_
-#define COMPONENTS_OFFLINE_PAGES_CORE_OFFLINE_PAGE_MODEL_QUERY_H_
-
-#include <set>
-#include <vector>
-
-#include "base/memory/ptr_util.h"
-#include "components/offline_pages/core/client_policy_controller.h"
-#include "components/offline_pages/core/offline_page_item.h"
-#include "components/offline_pages/core/offline_page_types.h"
-
-namespace offline_pages {
-
-// Can be used by OfflinePageModel instances to direct a query of the model.
-class OfflinePageModelQuery {
- public:
- // A query can be constrained by several fields. This constraint can be
- // either a positive or negative one (or no constraint): a page MUST have
- // something, or a page MUST NOT have something to match a query.
- enum class Requirement {
- // No requirement.
- UNSET,
- // All returned pages will have one of the values specified in the query
- // requirement.
- INCLUDE_MATCHING,
- // All returned pages will not have any of the values specified in the query
- // requirement.
- EXCLUDE_MATCHING,
- };
-
- struct URLSearchParams {
- URLSearchParams();
- URLSearchParams(const URLSearchParams& params);
- URLSearchParams(std::set<GURL> url_set,
- URLSearchMode search_mode,
- bool strip_frag);
- ~URLSearchParams();
-
- // The set of urls for matching.
- std::set<GURL> urls;
- // The mode for searching. By final url only or both final and original
- // urls.
- URLSearchMode mode;
- // Whether fragments should be stripped. It will *not* work on
- // *|original_url|*.
- // TODO(crbug.com/753609): Try to make this also available when matching for
- // |original_url|.
- bool strip_fragment;
- };
-
- OfflinePageModelQuery();
- virtual ~OfflinePageModelQuery();
-
- std::pair<bool, std::set<std::string>> GetRestrictedToNamespaces() const;
- std::pair<Requirement, std::set<int64_t>> GetRestrictedToOfflineIds() const;
- std::pair<Requirement, std::set<ClientId>> GetRestrictedToClientIds() const;
- std::pair<Requirement, URLSearchParams> GetRestrictedToUrls() const;
- std::pair<Requirement, std::string> GetRequestOrigin() const;
-
- // This is the workhorse function that is used by the in-memory offline page
- // model, given a page it will find out whether that page matches the query.
- bool Matches(const OfflinePageItem& page) const;
-
- private:
- friend class OfflinePageModelQueryBuilder;
-
- std::unique_ptr<std::set<std::string>> restricted_to_namespaces_;
-
- std::pair<Requirement, std::set<int64_t>> offline_ids_;
- std::pair<Requirement, std::set<ClientId>> client_ids_;
- std::pair<Requirement, URLSearchParams> urls_;
- std::pair<Requirement, std::string> request_origin_;
-
- DISALLOW_COPY_AND_ASSIGN(OfflinePageModelQuery);
-};
-
-// Used to create an offline page model query. QueryBuilders without
-// modifications create queries that allow all pages.
-// Can restrict results by policies provided by |ClientPolicyController|, or by
-// individual features of pages. Each restriction comes with a |Requirement|
-// that can be used to specify whether the input restriction should include or
-// exclude matching pages.
-class OfflinePageModelQueryBuilder {
- public:
- using Requirement = OfflinePageModelQuery::Requirement;
-
- OfflinePageModelQueryBuilder();
- ~OfflinePageModelQueryBuilder();
-
- // Sets the offline page IDs that are valid for this request. If called
- // multiple times, overwrites previous offline page ID restrictions.
- OfflinePageModelQueryBuilder& SetOfflinePageIds(
- Requirement requirement,
- const std::vector<int64_t>& ids);
-
- // Sets the client IDs that are valid for this request. If called multiple
- // times, overwrites previous client ID restrictions.
- OfflinePageModelQueryBuilder& SetClientIds(Requirement requirement,
- const std::vector<ClientId>& ids);
-
- // Sets the request origin that are valid for this request. If called
- // multiple times, overwrites the previous request origin restrictions.
- OfflinePageModelQueryBuilder& SetRequestOrigin(
- Requirement requirement,
- const std::string& request_origin);
-
- // Sets the URLs that are valid for this request. If called multiple times,
- // overwrites previous URL restrictions.
- // |search_mode| is used to control if the URL will be matched with final
- // URL only or both final URL and original URL.
- // If |strip_fragment| is true, *only final* urls will be matched without
- // fragment.
- // TODO(crbug.com/753609): Try to unify fragment handling for original and
- // final urls.
- OfflinePageModelQueryBuilder& SetUrls(Requirement requirement,
- const std::vector<GURL>& urls,
- URLSearchMode search_mode,
- bool strip_fragment);
-
- // Only include pages whose namespaces satisfy
- // ClientPolicyController::IsRemovedOnCacheReset(|namespace|) ==
- // |removed_on_cache_reset|
- // Multiple calls overwrite previous ones.
- OfflinePageModelQueryBuilder& RequireRemovedOnCacheReset(
- Requirement removed_on_cache_reset);
-
- // Only include pages whose namespaces satisfy
- // ClientPolicyController::IsSupportedByDownload(|namespace|) ==
- // |supported_by_download|
- // Multiple calls overwrite previous ones.
- OfflinePageModelQueryBuilder& RequireSupportedByDownload(
- Requirement supported_by_download);
-
- // Only include pages whose namespaces satisfy
- // ClientPolicyController::IsShownAsRecentlyVisitedSite(|namespace|) ==
- // |recently_visited|
- // Multiple calls overwrite previous ones.
- OfflinePageModelQueryBuilder& RequireShownAsRecentlyVisitedSite(
- Requirement recently_visited);
-
- // Only include pages whose namespaces satisfy
- // ClientPolicyController::IsRestrictedToOriginalTab(|namespace|) ==
- // |original_tab|
- // Multiple calls overwrite previous ones.
- OfflinePageModelQueryBuilder& RequireRestrictedToOriginalTab(
- Requirement original_tab);
-
- // Only include results from a single namespace.
- OfflinePageModelQueryBuilder& RequireNamespace(const std::string& name_space);
-
- // Builds the query using the namespace policies provided by |controller|
- // This resets the internal state. |controller| should not be |nullptr|.
- std::unique_ptr<OfflinePageModelQuery> Build(
- ClientPolicyController* controller);
-
- private:
- // Intersects the allowed namespaces in query_ with |namespaces|. If
- // |inverted| is true, intersects the allowed namespaces with all namespaces
- // except those provided in |namespaces|.
- void IntersectWithNamespaces(ClientPolicyController* controller,
- const std::vector<std::string>& namespaces,
- Requirement match_requirement);
-
- std::pair<Requirement, std::vector<int64_t>> offline_ids_;
- std::pair<Requirement, std::vector<ClientId>> client_ids_;
- std::pair<Requirement, OfflinePageModelQuery::URLSearchParams> urls_;
- std::pair<Requirement, std::string> request_origin_;
-
- Requirement removed_on_cache_reset_ = Requirement::UNSET;
- Requirement supported_by_download_ = Requirement::UNSET;
- Requirement shown_as_recently_visited_site_ = Requirement::UNSET;
- Requirement restricted_to_original_tab_ = Requirement::UNSET;
-
- std::unique_ptr<std::string> name_space_;
-
- DISALLOW_COPY_AND_ASSIGN(OfflinePageModelQueryBuilder);
-};
-
-} // namespace offline_pages
-
-#endif // COMPONENTS_OFFLINE_PAGES_CORE_OFFLINE_PAGE_MODEL_QUERY_H_
diff --git a/chromium/components/offline_pages/core/offline_page_model_query_unittest.cc b/chromium/components/offline_pages/core/offline_page_model_query_unittest.cc
deleted file mode 100644
index 2e0145a6d8b..00000000000
--- a/chromium/components/offline_pages/core/offline_page_model_query_unittest.cc
+++ /dev/null
@@ -1,742 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/offline_pages/core/offline_page_model_query.h"
-
-#include "base/time/time.h"
-#include "components/offline_pages/core/client_namespace_constants.h"
-#include "components/offline_pages/core/client_policy_controller.h"
-#include "components/offline_pages/core/offline_page_client_policy.h"
-#include "components/offline_pages/core/offline_page_item.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace offline_pages {
-
-using Requirement = OfflinePageModelQueryBuilder::Requirement;
-using URLSearchParams = OfflinePageModelQuery::URLSearchParams;
-
-namespace {
-
-const ClientId kClientId1 = {kDefaultNamespace, "id1"};
-const GURL kUrl1 = GURL("https://ktestitem1.com");
-const OfflinePageItem kTestItem1(kUrl1, 1, kClientId1, base::FilePath(), 1);
-
-const ClientId kClientId2 = {kDefaultNamespace, "id2"};
-const GURL kUrl2 = GURL("https://ktestitem2.com");
-const OfflinePageItem kTestItem2(kUrl2, 2, kClientId2, base::FilePath(), 2);
-
-const char kTestNamespace[] = "test_namespace";
-const GURL kTempUrl = GURL("https://temp.temp");
-const GURL kTempFragUrl = GURL("https://temp.temp#frag1");
-const GURL kFragUrl1 = GURL("https://ktestitem1.com#frag");
-} // namespace
-
-class OfflinePageModelQueryTest : public testing::Test {
- public:
- OfflinePageModelQueryTest();
- ~OfflinePageModelQueryTest() override;
-
- protected:
- ClientPolicyController policy_;
- OfflinePageModelQueryBuilder builder_;
-
- const OfflinePageItem cache_page() {
- return OfflinePageItem(GURL("https://download.com"), 3,
- {kBookmarkNamespace, "id1"}, base::FilePath(), 3);
- }
- const OfflinePageItem download_page() {
- return OfflinePageItem(GURL("https://download.com"), 4,
- {kDownloadNamespace, "id1"}, base::FilePath(), 4);
- }
-
- const OfflinePageItem original_tab_page() {
- return OfflinePageItem(GURL("https://download.com"), 5,
- {kLastNNamespace, "id1"}, base::FilePath(), 5);
- }
-
- const OfflinePageItem test_namespace_page() {
- return OfflinePageItem(GURL("https://download.com"), 6,
- {kTestNamespace, "id1"}, base::FilePath(), 6);
- }
-
- const OfflinePageItem recent_page() {
- return OfflinePageItem(GURL("https://download.com"), 7,
- {kLastNNamespace, "id1"}, base::FilePath(), 7);
- }
-
- const OfflinePageItem cct_page() {
- OfflinePageItem page = kTestItem1;
- page.request_origin = "[\"abc.xyz\",[\"12345\"]]";
- return page;
- }
- const OfflinePageItem CreatePageWithUrls(const GURL& url,
- const GURL& original_url) {
- OfflinePageItem page = kTestItem1;
- page.url = url;
- page.original_url = original_url;
- return page;
- }
-};
-
-OfflinePageModelQueryTest::OfflinePageModelQueryTest() {
- policy_.AddPolicyForTest(
- kTestNamespace,
- OfflinePageClientPolicyBuilder(kTestNamespace,
- LifetimePolicy::LifetimeType::TEMPORARY,
- kUnlimitedPages, kUnlimitedPages)
- .SetIsOnlyShownInOriginalTab(true));
-}
-
-OfflinePageModelQueryTest::~OfflinePageModelQueryTest() {}
-
-TEST_F(OfflinePageModelQueryTest, DefaultValues) {
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- EXPECT_NE(nullptr, query.get());
- EXPECT_EQ(Requirement::UNSET, query->GetRestrictedToOfflineIds().first);
- EXPECT_FALSE(query->GetRestrictedToNamespaces().first);
-
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(kTestItem2));
-}
-
-TEST_F(OfflinePageModelQueryTest, OfflinePageIdsSet_Exclude) {
- std::vector<int64_t> ids = {1, 4, 9, 16};
- builder_.SetOfflinePageIds(Requirement::EXCLUDE_MATCHING, ids);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
- std::pair<Requirement, std::set<int64_t>> offline_id_restriction =
- query->GetRestrictedToOfflineIds();
- EXPECT_EQ(Requirement::EXCLUDE_MATCHING, offline_id_restriction.first);
-
- ASSERT_EQ(ids.size(), offline_id_restriction.second.size());
- for (auto id : ids) {
- EXPECT_EQ(1U, offline_id_restriction.second.count(id))
- << "Did not find " << id << "in query restrictions.";
- }
-
- EXPECT_FALSE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(kTestItem2));
-}
-
-TEST_F(OfflinePageModelQueryTest, OfflinePageIdsSet) {
- std::vector<int64_t> ids = {1, 4, 9, 16};
- builder_.SetOfflinePageIds(Requirement::INCLUDE_MATCHING, ids);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
- std::pair<Requirement, std::set<int64_t>> offline_id_restriction =
- query->GetRestrictedToOfflineIds();
- EXPECT_EQ(Requirement::INCLUDE_MATCHING, offline_id_restriction.first);
-
- ASSERT_EQ(ids.size(), offline_id_restriction.second.size());
- for (auto id : ids) {
- EXPECT_EQ(1U, offline_id_restriction.second.count(id))
- << "Did not find " << id << "in query restrictions.";
- }
-
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(kTestItem2));
-}
-
-TEST_F(OfflinePageModelQueryTest, OfflinePageIdsReplace) {
- std::vector<int64_t> ids = {1, 4, 9, 16};
- std::vector<int64_t> ids2 = {1, 2, 3, 4};
-
- builder_.SetOfflinePageIds(Requirement::INCLUDE_MATCHING, ids);
- builder_.SetOfflinePageIds(Requirement::INCLUDE_MATCHING, ids2);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
- std::pair<Requirement, std::set<int64_t>> offline_id_restriction =
- query->GetRestrictedToOfflineIds();
- EXPECT_EQ(Requirement::INCLUDE_MATCHING, offline_id_restriction.first);
-
- ASSERT_EQ(ids2.size(), offline_id_restriction.second.size());
- for (auto id : ids2) {
- EXPECT_EQ(1U, offline_id_restriction.second.count(id))
- << "Did not find " << id << "in query restrictions.";
- }
-
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(kTestItem2));
-}
-
-TEST_F(OfflinePageModelQueryTest, ClientIdsSet) {
- std::vector<ClientId> ids = {kClientId2, {"invalid", "client id"}};
- builder_.SetClientIds(Requirement::INCLUDE_MATCHING, ids);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToClientIds();
- const Requirement& requirement = restriction.first;
- const std::set<ClientId>& ids_out = restriction.second;
-
- EXPECT_EQ(Requirement::INCLUDE_MATCHING, requirement);
-
- ASSERT_EQ(ids.size(), ids_out.size());
- for (auto id : ids) {
- EXPECT_EQ(1U, ids_out.count(id)) << "Did not find " << id.name_space << "."
- << id.id << "in query restrictions.";
- }
-
- EXPECT_TRUE(query->Matches(kTestItem2));
- EXPECT_FALSE(query->Matches(kTestItem1));
-}
-
-TEST_F(OfflinePageModelQueryTest, ClientIdsSet_Exclude) {
- std::vector<ClientId> ids = {kClientId2, {"invalid", "client id"}};
- builder_.SetClientIds(Requirement::EXCLUDE_MATCHING, ids);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToClientIds();
- const Requirement& requirement = restriction.first;
- const std::set<ClientId>& ids_out = restriction.second;
-
- EXPECT_EQ(Requirement::EXCLUDE_MATCHING, requirement);
-
- ASSERT_EQ(ids.size(), ids_out.size());
- for (auto id : ids) {
- EXPECT_EQ(1U, ids_out.count(id)) << "Did not find " << id.name_space << "."
- << id.id << "in query restrictions.";
- }
-
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(kTestItem2));
-}
-
-TEST_F(OfflinePageModelQueryTest, ClientIdsReplace) {
- std::vector<ClientId> ids = {kClientId2, {"invalid", "client id"}};
- std::vector<ClientId> ids2 = {kClientId1, {"invalid", "client id"}};
-
- builder_.SetClientIds(Requirement::INCLUDE_MATCHING, ids);
- builder_.SetClientIds(Requirement::INCLUDE_MATCHING, ids2);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToClientIds();
- const Requirement& requirement = restriction.first;
- const std::set<ClientId>& ids_out = restriction.second;
-
- EXPECT_EQ(Requirement::INCLUDE_MATCHING, requirement);
-
- ASSERT_EQ(ids2.size(), ids_out.size());
- for (auto id : ids2) {
- EXPECT_EQ(1U, ids_out.count(id)) << "Did not find " << id.name_space << "."
- << id.id << "in query restrictions.";
- }
-
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(kTestItem2));
-}
-
-TEST_F(OfflinePageModelQueryTest, UrlsSet) {
- std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")};
- builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls,
- URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, false);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToUrls();
- const Requirement& requirement = restriction.first;
- const URLSearchParams& params = restriction.second;
-
- EXPECT_EQ(Requirement::INCLUDE_MATCHING, requirement);
- EXPECT_EQ(URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, params.mode);
- EXPECT_FALSE(params.strip_fragment);
-
- ASSERT_EQ(urls.size(), params.urls.size());
- for (auto url : urls) {
- EXPECT_EQ(1U, params.urls.count(url))
- << "Did not find " << url << "in query restrictions.";
- }
-
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(kTestItem2));
- EXPECT_TRUE(query->Matches(CreatePageWithUrls(kUrl1, kTempUrl)));
- EXPECT_FALSE(query->Matches(CreatePageWithUrls(kTempUrl, kUrl1)));
- EXPECT_FALSE(
- query->Matches(CreatePageWithUrls(GURL(""), GURL("https://abc.def"))));
-}
-
-TEST_F(OfflinePageModelQueryTest, UrlsSet_Exclude) {
- std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")};
- builder_.SetUrls(Requirement::EXCLUDE_MATCHING, urls,
- URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, false);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToUrls();
- const Requirement& requirement = restriction.first;
- const URLSearchParams& params = restriction.second;
-
- EXPECT_EQ(Requirement::EXCLUDE_MATCHING, requirement);
- EXPECT_EQ(URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, params.mode);
- EXPECT_FALSE(params.strip_fragment);
-
- ASSERT_EQ(urls.size(), params.urls.size());
- for (auto url : urls) {
- EXPECT_EQ(1U, params.urls.count(url))
- << "Did not find " << url << "in query restrictions.";
- }
-
- EXPECT_FALSE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(kTestItem2));
- EXPECT_FALSE(query->Matches(CreatePageWithUrls(kUrl1, kTempUrl)));
- EXPECT_TRUE(query->Matches(CreatePageWithUrls(kTempUrl, kUrl1)));
- EXPECT_TRUE(
- query->Matches(CreatePageWithUrls(GURL(""), GURL("https://abc.def"))));
-}
-
-TEST_F(OfflinePageModelQueryTest, UrlsReplace) {
- std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")};
- std::vector<GURL> urls2 = {kUrl2, GURL("https://abc.def")};
-
- builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls,
- URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, false);
- builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls2,
- URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, false);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToUrls();
- const Requirement& requirement = restriction.first;
- const URLSearchParams& params = restriction.second;
-
- EXPECT_EQ(Requirement::INCLUDE_MATCHING, requirement);
- EXPECT_EQ(URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, params.mode);
- EXPECT_FALSE(params.strip_fragment);
-
- ASSERT_EQ(urls2.size(), params.urls.size());
- for (auto url : urls2) {
- EXPECT_EQ(1U, params.urls.count(url))
- << "Did not find " << url << "in query restrictions.";
- }
-
- EXPECT_FALSE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(kTestItem2));
-}
-
-TEST_F(OfflinePageModelQueryTest, RequireRemovedOnCacheReset_Only) {
- builder_.RequireRemovedOnCacheReset(Requirement::INCLUDE_MATCHING);
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToNamespaces();
- std::set<std::string> namespaces_allowed = restriction.second;
- bool restricted_to_namespaces = restriction.first;
- EXPECT_TRUE(restricted_to_namespaces);
-
- for (const std::string& name_space : namespaces_allowed) {
- EXPECT_TRUE(policy_.IsRemovedOnCacheReset(name_space))
- << "Namespace: " << name_space;
- }
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(cache_page()));
- EXPECT_FALSE(query->Matches(download_page()));
-}
-
-TEST_F(OfflinePageModelQueryTest, RequireRemovedOnCacheReset_Except) {
- builder_.RequireRemovedOnCacheReset(Requirement::EXCLUDE_MATCHING);
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToNamespaces();
- std::set<std::string> namespaces_allowed = restriction.second;
- bool restricted_to_namespaces = restriction.first;
- EXPECT_TRUE(restricted_to_namespaces);
-
- for (const std::string& name_space : namespaces_allowed) {
- EXPECT_FALSE(policy_.IsRemovedOnCacheReset(name_space))
- << "Namespace: " << name_space;
- }
-
- EXPECT_FALSE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(cache_page()));
- EXPECT_TRUE(query->Matches(download_page()));
-}
-
-TEST_F(OfflinePageModelQueryTest, RequireSupportedByDownload_Only) {
- builder_.RequireSupportedByDownload(Requirement::INCLUDE_MATCHING);
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToNamespaces();
- std::set<std::string> namespaces_allowed = restriction.second;
- bool restricted_to_namespaces = restriction.first;
- EXPECT_TRUE(restricted_to_namespaces);
-
- for (const std::string& name_space : namespaces_allowed) {
- EXPECT_TRUE(policy_.IsSupportedByDownload(name_space)) << "Namespace: "
- << name_space;
- }
- EXPECT_FALSE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(download_page()));
-}
-
-TEST_F(OfflinePageModelQueryTest, RequireSupportedByDownload_Except) {
- builder_.RequireSupportedByDownload(Requirement::EXCLUDE_MATCHING);
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToNamespaces();
- std::set<std::string> namespaces_allowed = restriction.second;
- bool restricted_to_namespaces = restriction.first;
- EXPECT_TRUE(restricted_to_namespaces);
-
- for (const std::string& name_space : namespaces_allowed) {
- EXPECT_FALSE(policy_.IsSupportedByDownload(name_space)) << "Namespace: "
- << name_space;
- }
-
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(download_page()));
-}
-
-TEST_F(OfflinePageModelQueryTest, RequireShownAsRecentlyVisitedSite_Only) {
- builder_.RequireShownAsRecentlyVisitedSite(Requirement::INCLUDE_MATCHING);
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToNamespaces();
- std::set<std::string> namespaces_allowed = restriction.second;
- bool restricted_to_namespaces = restriction.first;
- EXPECT_TRUE(restricted_to_namespaces);
-
- for (const std::string& name_space : namespaces_allowed) {
- EXPECT_TRUE(policy_.IsShownAsRecentlyVisitedSite(name_space))
- << "Namespace: " << name_space;
- }
- EXPECT_FALSE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(recent_page()));
-}
-
-TEST_F(OfflinePageModelQueryTest, RequireShownAsRecentlyVisitedSite_Except) {
- builder_.RequireShownAsRecentlyVisitedSite(Requirement::EXCLUDE_MATCHING);
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToNamespaces();
- std::set<std::string> namespaces_allowed = restriction.second;
- bool restricted_to_namespaces = restriction.first;
- EXPECT_TRUE(restricted_to_namespaces);
-
- for (const std::string& name_space : namespaces_allowed) {
- EXPECT_FALSE(policy_.IsShownAsRecentlyVisitedSite(name_space))
- << "Namespace: " << name_space;
- }
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(recent_page()));
-}
-
-TEST_F(OfflinePageModelQueryTest, RequireRestrictedToOriginalTab_Only) {
- builder_.RequireRestrictedToOriginalTab(Requirement::INCLUDE_MATCHING);
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToNamespaces();
- std::set<std::string> namespaces_allowed = restriction.second;
- bool restricted_to_namespaces = restriction.first;
- EXPECT_TRUE(restricted_to_namespaces);
-
- for (const std::string& name_space : namespaces_allowed) {
- EXPECT_TRUE(policy_.IsRestrictedToOriginalTab(name_space)) << "Namespace: "
- << name_space;
- }
- EXPECT_FALSE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(original_tab_page()));
-}
-
-TEST_F(OfflinePageModelQueryTest, RequireRestrictedToOriginalTab_Except) {
- builder_.RequireRestrictedToOriginalTab(Requirement::EXCLUDE_MATCHING);
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToNamespaces();
- std::set<std::string> namespaces_allowed = restriction.second;
- bool restricted_to_namespaces = restriction.first;
- EXPECT_TRUE(restricted_to_namespaces);
-
- for (const std::string& name_space : namespaces_allowed) {
- EXPECT_FALSE(policy_.IsRestrictedToOriginalTab(name_space)) << "Namespace: "
- << name_space;
- }
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(original_tab_page()));
-}
-
-TEST_F(OfflinePageModelQueryTest, IntersectNamespaces) {
- // This should exclude last N, but include |kTestNamespace|.
- builder_.RequireRestrictedToOriginalTab(Requirement::INCLUDE_MATCHING)
- .RequireShownAsRecentlyVisitedSite(Requirement::EXCLUDE_MATCHING);
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToNamespaces();
- std::set<std::string> namespaces_allowed = restriction.second;
- bool restricted_to_namespaces = restriction.first;
- EXPECT_TRUE(restricted_to_namespaces);
-
- EXPECT_TRUE(namespaces_allowed.count(kTestNamespace) == 1);
- EXPECT_FALSE(query->Matches(recent_page()));
-}
-
-TEST_F(OfflinePageModelQueryTest, RequireNamespace) {
- builder_.RequireNamespace(kDefaultNamespace);
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
- auto restriction = query->GetRestrictedToNamespaces();
- std::set<std::string> namespaces_allowed = restriction.second;
- bool restricted_to_namespaces = restriction.first;
- EXPECT_TRUE(restricted_to_namespaces);
- EXPECT_EQ(1U, namespaces_allowed.size());
- EXPECT_TRUE(namespaces_allowed.find(kDefaultNamespace) !=
- namespaces_allowed.end());
-
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(test_namespace_page()));
-}
-
-TEST_F(OfflinePageModelQueryTest, UrlsSet_SearchByAll) {
- std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")};
- builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls,
- URLSearchMode::SEARCH_BY_ALL_URLS, false);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToUrls();
- const Requirement& requirement = restriction.first;
- const URLSearchParams& params = restriction.second;
-
- EXPECT_EQ(Requirement::INCLUDE_MATCHING, requirement);
- EXPECT_EQ(URLSearchMode::SEARCH_BY_ALL_URLS, params.mode);
- EXPECT_FALSE(params.strip_fragment);
-
- ASSERT_EQ(urls.size(), params.urls.size());
- for (auto url : urls) {
- EXPECT_EQ(1U, params.urls.count(url))
- << "Did not find " << url << "in query restrictions.";
- }
-
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(kTestItem2));
- EXPECT_TRUE(query->Matches(CreatePageWithUrls(kUrl1, kTempUrl)));
- EXPECT_TRUE(query->Matches(CreatePageWithUrls(kTempUrl, kUrl1)));
- EXPECT_TRUE(
- query->Matches(CreatePageWithUrls(kUrl1, GURL("https://abc.def"))));
- EXPECT_TRUE(
- query->Matches(CreatePageWithUrls(kTempUrl, GURL("https://abc.def"))));
- EXPECT_TRUE(
- query->Matches(CreatePageWithUrls(GURL("https://abc.def"), GURL(""))));
- EXPECT_FALSE(query->Matches(CreatePageWithUrls(kTempUrl, GURL(""))));
-}
-
-TEST_F(OfflinePageModelQueryTest, UrlsSet_Exclude_SearchByAll) {
- std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")};
- builder_.SetUrls(Requirement::EXCLUDE_MATCHING, urls,
- URLSearchMode::SEARCH_BY_ALL_URLS, false);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToUrls();
- const Requirement& requirement = restriction.first;
- const URLSearchParams& params = restriction.second;
-
- EXPECT_EQ(Requirement::EXCLUDE_MATCHING, requirement);
- EXPECT_EQ(URLSearchMode::SEARCH_BY_ALL_URLS, params.mode);
- EXPECT_FALSE(params.strip_fragment);
-
- ASSERT_EQ(urls.size(), params.urls.size());
- for (auto url : urls) {
- EXPECT_EQ(1U, params.urls.count(url))
- << "Did not find " << url << "in query restrictions.";
- }
-
- EXPECT_FALSE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(kTestItem2));
- EXPECT_FALSE(query->Matches(CreatePageWithUrls(kUrl1, kTempUrl)));
- EXPECT_FALSE(query->Matches(CreatePageWithUrls(kTempUrl, kUrl1)));
- EXPECT_FALSE(
- query->Matches(CreatePageWithUrls(kUrl1, GURL("https://abc.def"))));
- EXPECT_FALSE(
- query->Matches(CreatePageWithUrls(kTempUrl, GURL("https://abc.def"))));
- EXPECT_FALSE(
- query->Matches(CreatePageWithUrls(GURL("https://abc.def"), GURL(""))));
- EXPECT_TRUE(query->Matches(CreatePageWithUrls(kTempUrl, GURL(""))));
-}
-
-TEST_F(OfflinePageModelQueryTest, UrlsSet_Defrag) {
- std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")};
- builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls,
- URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, true);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToUrls();
- const Requirement& requirement = restriction.first;
- const URLSearchParams& params = restriction.second;
-
- EXPECT_EQ(Requirement::INCLUDE_MATCHING, requirement);
- EXPECT_EQ(URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, params.mode);
- EXPECT_TRUE(params.strip_fragment);
-
- ASSERT_EQ(urls.size(), params.urls.size());
- for (auto url : urls) {
- EXPECT_EQ(1U, params.urls.count(url))
- << "Did not find " << url << "in query restrictions.";
- }
-
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(kTestItem2));
- EXPECT_TRUE(query->Matches(CreatePageWithUrls(kFragUrl1, kTempUrl)));
- EXPECT_FALSE(query->Matches(CreatePageWithUrls(kTempUrl, kUrl1)));
- EXPECT_TRUE(
- query->Matches(CreatePageWithUrls(kFragUrl1, GURL("https://abc.def"))));
- EXPECT_FALSE(
- query->Matches(CreatePageWithUrls(kTempUrl, GURL("https://abc.def"))));
- EXPECT_TRUE(
- query->Matches(CreatePageWithUrls(GURL("https://abc.def"), GURL(""))));
- EXPECT_TRUE(query->Matches(
- CreatePageWithUrls(GURL("https://abc.def#frag2"), GURL(""))));
-}
-
-TEST_F(OfflinePageModelQueryTest, UrlsSet_Exclude_Defrag) {
- std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")};
- builder_.SetUrls(Requirement::EXCLUDE_MATCHING, urls,
- URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, true);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToUrls();
- const Requirement& requirement = restriction.first;
- const URLSearchParams& params = restriction.second;
-
- EXPECT_EQ(Requirement::EXCLUDE_MATCHING, requirement);
- EXPECT_EQ(URLSearchMode::SEARCH_BY_FINAL_URL_ONLY, params.mode);
- EXPECT_TRUE(params.strip_fragment);
-
- ASSERT_EQ(urls.size(), params.urls.size());
- for (auto url : urls) {
- EXPECT_EQ(1U, params.urls.count(url))
- << "Did not find " << url << "in query restrictions.";
- }
-
- EXPECT_FALSE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(kTestItem2));
- EXPECT_FALSE(query->Matches(CreatePageWithUrls(kFragUrl1, kTempUrl)));
- EXPECT_TRUE(query->Matches(CreatePageWithUrls(kTempUrl, kUrl1)));
- EXPECT_FALSE(
- query->Matches(CreatePageWithUrls(kFragUrl1, GURL("https://abc.def"))));
- EXPECT_TRUE(
- query->Matches(CreatePageWithUrls(kTempUrl, GURL("https://abc.def"))));
- EXPECT_FALSE(
- query->Matches(CreatePageWithUrls(GURL("https://abc.def"), GURL(""))));
- EXPECT_FALSE(query->Matches(
- CreatePageWithUrls(GURL("https://abc.def#frag2"), GURL(""))));
-}
-
-TEST_F(OfflinePageModelQueryTest, UrlsSet_SearchByAll_Defrag) {
- std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")};
- builder_.SetUrls(Requirement::INCLUDE_MATCHING, urls,
- URLSearchMode::SEARCH_BY_ALL_URLS, true);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToUrls();
- const Requirement& requirement = restriction.first;
- const URLSearchParams& params = restriction.second;
-
- EXPECT_EQ(Requirement::INCLUDE_MATCHING, requirement);
- EXPECT_EQ(URLSearchMode::SEARCH_BY_ALL_URLS, params.mode);
- EXPECT_TRUE(params.strip_fragment);
-
- ASSERT_EQ(urls.size(), params.urls.size());
- for (auto url : urls) {
- EXPECT_EQ(1U, params.urls.count(url))
- << "Did not find " << url << "in query restrictions.";
- }
-
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(kTestItem2));
- EXPECT_TRUE(query->Matches(CreatePageWithUrls(kFragUrl1, kTempUrl)));
- EXPECT_FALSE(query->Matches(CreatePageWithUrls(kTempUrl, kFragUrl1)));
- EXPECT_TRUE(
- query->Matches(CreatePageWithUrls(kFragUrl1, GURL("https://abc.def"))));
- EXPECT_FALSE(query->Matches(
- CreatePageWithUrls(kTempUrl, GURL("https://abc.def#frag2"))));
- EXPECT_TRUE(
- query->Matches(CreatePageWithUrls(GURL("https://abc.def"), GURL(""))));
- EXPECT_FALSE(query->Matches(CreatePageWithUrls(kTempFragUrl, GURL(""))));
-}
-
-TEST_F(OfflinePageModelQueryTest, UrlsSet_Exclude_SearchByAll_Defrag) {
- std::vector<GURL> urls = {kUrl1, GURL("https://abc.def")};
- builder_.SetUrls(Requirement::EXCLUDE_MATCHING, urls,
- URLSearchMode::SEARCH_BY_ALL_URLS, true);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
-
- auto restriction = query->GetRestrictedToUrls();
- const Requirement& requirement = restriction.first;
- const URLSearchParams& params = restriction.second;
-
- EXPECT_EQ(Requirement::EXCLUDE_MATCHING, requirement);
- EXPECT_EQ(URLSearchMode::SEARCH_BY_ALL_URLS, params.mode);
- EXPECT_TRUE(params.strip_fragment);
-
- ASSERT_EQ(urls.size(), params.urls.size());
- for (auto url : urls) {
- EXPECT_EQ(1U, params.urls.count(url))
- << "Did not find " << url << "in query restrictions.";
- }
-
- EXPECT_FALSE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(kTestItem2));
- EXPECT_FALSE(query->Matches(CreatePageWithUrls(kFragUrl1, kTempFragUrl)));
- EXPECT_TRUE(query->Matches(CreatePageWithUrls(kTempUrl, kFragUrl1)));
- EXPECT_FALSE(
- query->Matches(CreatePageWithUrls(kUrl1, GURL("https://abc.def#frag2"))));
- EXPECT_TRUE(query->Matches(
- CreatePageWithUrls(kTempUrl, GURL("https://abc.def#frag2"))));
- EXPECT_FALSE(
- query->Matches(CreatePageWithUrls(GURL("https://abc.def"), GURL(""))));
- EXPECT_TRUE(query->Matches(CreatePageWithUrls(kTempFragUrl, GURL(""))));
-}
-
-TEST_F(OfflinePageModelQueryTest, RequestOrigin_Exclude) {
- builder_.SetRequestOrigin(Requirement::EXCLUDE_MATCHING, "");
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
- std::pair<Requirement, std::string> offline_origin_restriction =
- query->GetRequestOrigin();
- EXPECT_EQ(Requirement::EXCLUDE_MATCHING, offline_origin_restriction.first);
-
- ASSERT_EQ("", offline_origin_restriction.second);
-
- EXPECT_FALSE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(cct_page()));
-}
-
-TEST_F(OfflinePageModelQueryTest, RequestOrigin_Include) {
- builder_.SetRequestOrigin(Requirement::INCLUDE_MATCHING, "");
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
- std::pair<Requirement, std::string> offline_origin_restriction =
- query->GetRequestOrigin();
- EXPECT_EQ(Requirement::INCLUDE_MATCHING, offline_origin_restriction.first);
-
- ASSERT_EQ("", offline_origin_restriction.second);
-
- EXPECT_TRUE(query->Matches(kTestItem1));
- EXPECT_FALSE(query->Matches(cct_page()));
-}
-
-TEST_F(OfflinePageModelQueryTest, RequestOrigin_Replace) {
- std::string origin1 = "";
- std::string origin2 = "[\"abc.xyz\",[\"12345\"]]";
-
- builder_.SetRequestOrigin(Requirement::INCLUDE_MATCHING, origin1);
- builder_.SetRequestOrigin(Requirement::INCLUDE_MATCHING, origin2);
-
- std::unique_ptr<OfflinePageModelQuery> query = builder_.Build(&policy_);
- std::pair<Requirement, std::string> offline_origin_restriction =
- query->GetRequestOrigin();
- EXPECT_EQ(Requirement::INCLUDE_MATCHING, offline_origin_restriction.first);
-
- ASSERT_EQ(origin2, offline_origin_restriction.second);
-
- EXPECT_FALSE(query->Matches(kTestItem1));
- EXPECT_TRUE(query->Matches(cct_page()));
-}
-
-} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/offline_page_storage_manager.cc b/chromium/components/offline_pages/core/offline_page_storage_manager.cc
deleted file mode 100644
index 0ea306b3bb0..00000000000
--- a/chromium/components/offline_pages/core/offline_page_storage_manager.cc
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/offline_pages/core/offline_page_storage_manager.h"
-
-#include <algorithm>
-#include <map>
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/time/clock.h"
-#include "base/time/default_clock.h"
-#include "components/offline_pages/core/client_namespace_constants.h"
-#include "components/offline_pages/core/client_policy_controller.h"
-#include "components/offline_pages/core/offline_page_client_policy.h"
-#include "components/offline_pages/core/offline_page_item.h"
-#include "components/offline_pages/core/offline_page_model.h"
-
-using LifetimeType = offline_pages::LifetimePolicy::LifetimeType;
-
-namespace offline_pages {
-
-constexpr double constants::kOfflinePageStorageLimit;
-constexpr double constants::kOfflinePageStorageClearThreshold;
-constexpr base::TimeDelta constants::kClearStorageInterval;
-constexpr base::TimeDelta constants::kRemovePageItemInterval;
-
-OfflinePageStorageManager::OfflinePageStorageManager(
- OfflinePageModel* model,
- ClientPolicyController* policy_controller,
- ArchiveManager* archive_manager)
- : model_(model),
- policy_controller_(policy_controller),
- archive_manager_(archive_manager),
- clock_(new base::DefaultClock()),
- reported_usage_this_launch_(false),
- weak_ptr_factory_(this) {}
-
-OfflinePageStorageManager::~OfflinePageStorageManager() {}
-
-void OfflinePageStorageManager::ClearPagesIfNeeded(
- const ClearStorageCallback& callback) {
- if (IsInProgress())
- return;
- clear_time_ = clock_->Now();
- archive_manager_->GetStorageStats(base::Bind(
- &OfflinePageStorageManager::OnGetStorageStatsDoneForClearingPages,
- weak_ptr_factory_.GetWeakPtr(), callback));
-}
-
-void OfflinePageStorageManager::SetClockForTesting(
- std::unique_ptr<base::Clock> clock) {
- clock_ = std::move(clock);
-}
-
-void OfflinePageStorageManager::ResetUsageReportingFlagForTesting() {
- reported_usage_this_launch_ = false;
-}
-
-void OfflinePageStorageManager::OnGetStorageStatsDoneForClearingPages(
- const ClearStorageCallback& callback,
- const ArchiveManager::StorageStats& stats) {
- DCHECK(IsInProgress());
- ClearMode mode = ShouldClearPages(stats);
- if (mode == ClearMode::NOT_NEEDED) {
- last_clear_time_ = clear_time_;
- callback.Run(0, ClearStorageResult::UNNECESSARY);
- return;
- }
- model_->GetAllPages(
- base::Bind(&OfflinePageStorageManager::OnGetAllPagesDoneForClearingPages,
- weak_ptr_factory_.GetWeakPtr(), callback, stats));
-}
-
-void OfflinePageStorageManager::OnGetAllPagesDoneForClearingPages(
- const ClearStorageCallback& callback,
- const ArchiveManager::StorageStats& stats,
- const MultipleOfflinePageItemResult& pages) {
- ReportStorageUsageUMA(pages);
- std::vector<int64_t> page_ids_to_clear;
- GetPageIdsToClear(pages, stats, &page_ids_to_clear);
- model_->DeletePagesByOfflineId(
- page_ids_to_clear,
- base::Bind(&OfflinePageStorageManager::OnExpiredPagesCleared,
- weak_ptr_factory_.GetWeakPtr(), callback,
- page_ids_to_clear.size()));
-}
-
-void OfflinePageStorageManager::OnExpiredPagesCleared(
- const ClearStorageCallback& callback,
- size_t pages_cleared,
- DeletePageResult result) {
- last_clear_time_ = clear_time_;
- ClearStorageResult clear_result = ClearStorageResult::SUCCESS;
- if (result != DeletePageResult::SUCCESS)
- clear_result = ClearStorageResult::DELETE_FAILURE;
- callback.Run(pages_cleared, clear_result);
-}
-
-void OfflinePageStorageManager::GetPageIdsToClear(
- const MultipleOfflinePageItemResult& pages,
- const ArchiveManager::StorageStats& stats,
- std::vector<int64_t>* page_ids_to_clear) {
- // Creating a map from namespace to a vector of page items.
- // Sort each vector based on last accessed time and all pages after index
- // min{size(), page_limit} should be deleted.
- std::map<std::string, std::vector<OfflinePageItem>> pages_map;
- std::vector<OfflinePageItem> kept_pages;
- int64_t kept_pages_size = 0;
-
- for (const auto& page : pages) {
- if (IsExpired(page))
- page_ids_to_clear->push_back(page.offline_id);
- else
- pages_map[page.client_id.name_space].push_back(page);
- }
-
- for (auto& iter : pages_map) {
- std::string name_space = iter.first;
- std::vector<OfflinePageItem>& page_list = iter.second;
-
- LifetimePolicy policy =
- policy_controller_->GetPolicy(name_space).lifetime_policy;
- // Storage manager only manages temporary offlined pages, so we shouldn't
- // clear any persistent pages here.
- if (policy.lifetime_type == LifetimeType::PERSISTENT)
- continue;
-
- std::sort(page_list.begin(), page_list.end(),
- [](const OfflinePageItem& a, const OfflinePageItem& b) -> bool {
- return a.last_access_time > b.last_access_time;
- });
-
- size_t page_list_size = page_list.size();
- size_t pos = 0;
- while (pos < page_list_size &&
- (policy.page_limit == kUnlimitedPages || pos < policy.page_limit)) {
- kept_pages_size += page_list.at(pos).file_size;
- kept_pages.push_back(page_list.at(pos));
- pos++;
- }
-
- for (; pos < page_list_size; pos++)
- page_ids_to_clear->push_back(page_list.at(pos).offline_id);
- }
-
- // If we're still over the clear threshold, we're going to clear remaining
- // pages from oldest last access time.
- int64_t free_space = stats.free_disk_space;
- int64_t total_size = stats.temporary_archives_size;
- int64_t space_to_release =
- kept_pages_size -
- (total_size + free_space) * constants::kOfflinePageStorageClearThreshold;
- if (space_to_release > 0) {
- // Here we're sorting the |kept_pages| with oldest first.
- std::sort(kept_pages.begin(), kept_pages.end(),
- [](const OfflinePageItem& a, const OfflinePageItem& b) -> bool {
- return a.last_access_time < b.last_access_time;
- });
- size_t kept_pages_size = kept_pages.size();
- size_t pos = 0;
- while (pos < kept_pages_size && space_to_release > 0) {
- space_to_release -= kept_pages.at(pos).file_size;
- page_ids_to_clear->push_back(kept_pages.at(pos).offline_id);
- pos++;
- }
- }
-}
-
-OfflinePageStorageManager::ClearMode
-OfflinePageStorageManager::ShouldClearPages(
- const ArchiveManager::StorageStats& storage_stats) {
- int64_t total_size = storage_stats.temporary_archives_size;
- int64_t free_space = storage_stats.free_disk_space;
- if (total_size == 0)
- return ClearMode::NOT_NEEDED;
-
- // If the size of all offline pages is more than limit, or it's larger than a
- // specified percentage of all available storage space on the disk we'll clear
- // all offline pages.
- if (total_size >=
- (total_size + free_space) * constants::kOfflinePageStorageLimit)
- return ClearMode::DEFAULT;
- // If it's been more than the pre-defined interval since the last time we
- // clear the storage, we should clear pages.
- if (last_clear_time_ == base::Time() ||
- clear_time_ - last_clear_time_ >= constants::kClearStorageInterval) {
- return ClearMode::DEFAULT;
- }
- // Otherwise there's no need to clear storage right now.
- return ClearMode::NOT_NEEDED;
-}
-
-void OfflinePageStorageManager::ReportStorageUsageUMA(
- const MultipleOfflinePageItemResult& pages) {
- // Only run once per app launch to make the data less noisy.
- // TODO(petewil): Once per day might be better, but would need a new field in
- // the database, and a new async task to get it.
- if (reported_usage_this_launch_)
- return;
- reported_usage_this_launch_ = true;
-
- // Iterate through all the pages, getting their size, and adding to the proper
- // namespace accumulator.
- std::map<std::string, int64_t> page_sizes;
- for (const OfflinePageItem& item : pages) {
- const std::string& name_space = item.client_id.name_space;
- // Note: if |name_space| is not yet a key in the map a new entry will be
- // properly initialized with the value 0 because |int| is
- // default-constructible (int() == 0).
- page_sizes[name_space] += item.file_size;
- }
-
- // Report usages for all namespaces known to ClientPolicyController and only
- // for those.
- std::string base_histogram_name = "OfflinePages.ClearStoragePreRunUsage2.";
- for (const std::string name_space : policy_controller_->GetAllNamespaces()) {
- int size_in_kib = base::saturated_cast<int>(page_sizes[name_space] / 1024);
- base::UmaHistogramCustomCounts(base_histogram_name + name_space,
- size_in_kib, 1, 10000000, 50);
- }
-}
-
-bool OfflinePageStorageManager::IsExpired(const OfflinePageItem& page) const {
- const LifetimePolicy& policy =
- policy_controller_->GetPolicy(page.client_id.name_space).lifetime_policy;
- return policy.lifetime_type == LifetimeType::TEMPORARY &&
- clear_time_ - page.last_access_time >= policy.expiration_period;
-}
-
-bool OfflinePageStorageManager::IsInProgress() const {
- return clear_time_ > last_clear_time_;
-}
-
-} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/offline_page_storage_manager.h b/chromium/components/offline_pages/core/offline_page_storage_manager.h
deleted file mode 100644
index a29f73f0ad3..00000000000
--- a/chromium/components/offline_pages/core/offline_page_storage_manager.h
+++ /dev/null
@@ -1,166 +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_OFFLINE_PAGES_CORE_OFFLINE_PAGE_STORAGE_MANAGER_H_
-#define COMPONENTS_OFFLINE_PAGES_CORE_OFFLINE_PAGE_STORAGE_MANAGER_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "components/offline_pages/core/archive_manager.h"
-#include "components/offline_pages/core/offline_page_types.h"
-
-namespace base {
-class Clock;
-} // namespace base
-
-namespace offline_pages {
-
-// Maximum % of total available storage that will be occupied by offline pages
-// before a storage clearup.
-struct constants {
- static constexpr double kOfflinePageStorageLimit = 0.3;
- // The target % of storage usage we try to reach below when expiring pages.
- static constexpr double kOfflinePageStorageClearThreshold = 0.1;
- // The time that the storage cleanup will be triggered again since the last
- // one.
- static constexpr base::TimeDelta kClearStorageInterval =
- base::TimeDelta::FromMinutes(10);
- // The time that the page record will be removed from the store since the page
- // has been expired.
- static constexpr base::TimeDelta kRemovePageItemInterval =
- base::TimeDelta::FromDays(21);
-};
-
-class ClientPolicyController;
-class OfflinePageModel;
-
-// This class is used for storage management of offline pages. It provides
-// a ClearPagesIfNeeded method which is used to clear outdated offline pages
-// based on last_access_time and lifetime policy of its namespace.
-// It has its own throttle mechanism so calling the method would not be
-// guaranteed to clear the pages immediately.
-//
-// OfflinePageModel should own and control the lifecycle of this manager.
-// And this manager would use OfflinePageModel to get/remove pages.
-class OfflinePageStorageManager {
- public:
- enum class ClearStorageResult {
- SUCCESS, // Cleared successfully.
- UNNECESSARY, // No expired pages.
- DEPRECATED_EXPIRE_FAILURE, // Expiration failed. (DEPRECATED)
- DELETE_FAILURE, // Deletion failed.
- DEPRECATED_EXPIRE_AND_DELETE_FAILURES, // Both expiration and deletion
- // failed. (DEPRECATED)
- // NOTE: always keep this entry at the end. Add new result types only
- // immediately above this line. Make sure to update the corresponding
- // histogram enum accordingly.
- RESULT_COUNT,
- };
-
- // Callback used when calling ClearPagesIfNeeded.
- // size_t: the number of cleared pages.
- // ClearStorageResult: result of clearing pages in storage.
- typedef base::Callback<void(size_t, ClearStorageResult)> ClearStorageCallback;
-
- explicit OfflinePageStorageManager(OfflinePageModel* model,
- ClientPolicyController* policy_controller,
- ArchiveManager* archive_manager);
-
- ~OfflinePageStorageManager();
-
- // The manager would *try* to clear pages when called. It may not delete any
- // pages (if clearing condition wasn't satisfied).
- // It clears the storage (expire pages) when it's using more disk space than a
- // certain limit, or the time elapsed from last time clearing is longer than a
- // certain interval. Both values are defined above.
- void ClearPagesIfNeeded(const ClearStorageCallback& callback);
-
- // Sets the clock for testing.
- void SetClockForTesting(std::unique_ptr<base::Clock> clock);
-
- // Resets the flag for storage usage reporting for testing purposes.
- void ResetUsageReportingFlagForTesting();
-
- private:
- // Enum indicating how to clear the pages.
- enum class ClearMode {
- // Using normal expiration logic to clear pages. Will reduce the storage
- // usage down below the threshold.
- DEFAULT,
- // No need to clear any page (no pages in the model or no expired pages and
- // we're not exceeding the storage limit.)
- NOT_NEEDED,
- };
-
- // Callback called after getting storage stats from archive manager.
- void OnGetStorageStatsDoneForClearingPages(
- const ClearStorageCallback& callback,
- const ArchiveManager::StorageStats& pages);
-
- // Callback called after getting all pages from model.
- void OnGetAllPagesDoneForClearingPages(
- const ClearStorageCallback& callback,
- const ArchiveManager::StorageStats& storage_stats,
- const MultipleOfflinePageItemResult& pages);
-
- // Callback called after clearing expired pages from model.
- void OnExpiredPagesCleared(const ClearStorageCallback& callback,
- size_t pages_cleared,
- DeletePageResult result);
-
- // Gets offline IDs of pages that should be cleared based on current |stats|
- // and return the IDs in |page_ids_to_clear|.
- void GetPageIdsToClear(const MultipleOfflinePageItemResult& pages,
- const ArchiveManager::StorageStats& stats,
- std::vector<int64_t>* page_ids_to_clear);
-
- // Reports how much storage each namespace of page is using.
- void ReportStorageUsageUMA(const MultipleOfflinePageItemResult& pages);
-
- // Determines if manager should clear pages.
- ClearMode ShouldClearPages(const ArchiveManager::StorageStats& storage_stats);
-
- // Returns true if |page| is should be cleared based on |clear_time_|.
- bool IsExpired(const OfflinePageItem& page) const;
-
- // Returns true if we're currently doing a cleanup.
- bool IsInProgress() const;
-
- // Not owned.
- OfflinePageModel* model_;
-
- // Not owned.
- ClientPolicyController* policy_controller_;
-
- // Not owned.
- ArchiveManager* archive_manager_;
-
- // Starting time of the current storage cleanup. If this time is later than
- // |last_clear_time_| it means we're doing a cleanup.
- base::Time clear_time_;
-
- // Timestamp of last storage cleanup.
- base::Time last_clear_time_;
-
- // Clock for getting time.
- std::unique_ptr<base::Clock> clock_;
-
- // We only report usage once per launch, keep track here.
- bool reported_usage_this_launch_;
-
- base::WeakPtrFactory<OfflinePageStorageManager> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(OfflinePageStorageManager);
-};
-
-} // namespace offline_pages
-
-#endif // COMPONENTS_OFFLINE_PAGES_CORE_OFFLINE_PAGE_STORAGE_MANAGER_H_
diff --git a/chromium/components/offline_pages/core/offline_page_storage_manager_unittest.cc b/chromium/components/offline_pages/core/offline_page_storage_manager_unittest.cc
deleted file mode 100644
index 4faa2ad98a9..00000000000
--- a/chromium/components/offline_pages/core/offline_page_storage_manager_unittest.cc
+++ /dev/null
@@ -1,556 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/offline_pages/core/offline_page_storage_manager.h"
-
-#include <stdint.h>
-#include <map>
-#include <memory>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/test/histogram_tester.h"
-#include "base/test/simple_test_clock.h"
-#include "base/time/time.h"
-#include "components/offline_pages/core/archive_manager.h"
-#include "components/offline_pages/core/client_policy_controller.h"
-#include "components/offline_pages/core/offline_page_item.h"
-#include "components/offline_pages/core/offline_page_model_impl.h"
-#include "components/offline_pages/core/offline_page_types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using LifetimePolicy = offline_pages::LifetimePolicy;
-using ClearStorageResult =
- offline_pages::OfflinePageStorageManager::ClearStorageResult;
-using StorageStats = offline_pages::ArchiveManager::StorageStats;
-
-namespace offline_pages {
-
-namespace {
-const char kOneDayNamespace[] = "temporary_namespace_1day";
-const char kOneWeekNamespace[] = "temporary_namespace_7day";
-const char kPersistentNamespace[] = "persistent_namespace";
-const GURL kTestUrl("http://example.com");
-const base::FilePath::CharType kFilePath[] = FILE_PATH_LITERAL("/data");
-const int64_t kTestFileSize = 1 << 19; // Make a page 512KB.
-const int64_t kFreeSpaceNormal = 100 * (1 << 20);
-
-enum TestOptions {
- DEFAULT = 1 << 0,
- DELETE_FAILURE = 1 << 1,
-};
-
-struct PageSettings {
- std::string name_space;
- int fresh_pages_count;
- int expired_pages_count;
-};
-
-class TestArchiveManager : public ArchiveManager {
- public:
- explicit TestArchiveManager(StorageStats stats) : stats_(stats) {}
-
- void GetStorageStats(const base::Callback<
- void(const ArchiveManager::StorageStats& storage_stats)>&
- callback) const override {
- callback.Run(stats_);
- }
-
- void SetValues(ArchiveManager::StorageStats stats) { stats_ = stats; }
-
- private:
- StorageStats stats_;
-};
-
-} // namespace
-
-class OfflinePageTestModel : public OfflinePageModelImpl {
- public:
- OfflinePageTestModel(std::vector<PageSettings> page_settings,
- base::SimpleTestClock* clock,
- ClientPolicyController* policy_controller,
- TestOptions options = TestOptions::DEFAULT)
- : policy_controller_(policy_controller),
- clock_(clock),
- options_(options),
- next_offline_id_(0) {
- policy_controller_->AddPolicyForTest(
- kOneDayNamespace,
- OfflinePageClientPolicyBuilder(kOneDayNamespace,
- LifetimePolicy::LifetimeType::TEMPORARY,
- kUnlimitedPages, kUnlimitedPages)
- .SetExpirePeriod(base::TimeDelta::FromDays(1)));
- policy_controller_->AddPolicyForTest(
- kOneWeekNamespace,
- OfflinePageClientPolicyBuilder(kOneWeekNamespace,
- LifetimePolicy::LifetimeType::TEMPORARY,
- kUnlimitedPages, 1)
- .SetExpirePeriod(base::TimeDelta::FromDays(7)));
- policy_controller_->AddPolicyForTest(
- kPersistentNamespace,
- OfflinePageClientPolicyBuilder(kPersistentNamespace,
- LifetimePolicy::LifetimeType::PERSISTENT,
- kUnlimitedPages, kUnlimitedPages)
- .SetIsRemovedOnCacheReset(false));
- for (const auto& setting : page_settings)
- AddPages(setting);
- }
-
- ~OfflinePageTestModel() override;
-
- void GetAllPages(const MultipleOfflinePageItemCallback& callback) override {
- MultipleOfflinePageItemResult pages;
- for (const auto& id_page_pair : pages_)
- pages.push_back(id_page_pair.second);
- callback.Run(pages);
- }
-
- void DeletePagesByOfflineId(const std::vector<int64_t>& offline_ids,
- const DeletePageCallback& callback) override;
-
- void AddPages(const PageSettings& setting);
-
- // The |removed_pages_| would not be cleared in during a test, so the number
- // of removed pages will be accumulative in a single test case.
- const std::vector<OfflinePageItem>& GetRemovedPages() {
- return removed_pages_;
- }
-
- int64_t GetTemporaryPagesSize() const;
-
- base::SimpleTestClock* clock() { return clock_; }
-
- ClientPolicyController* GetPolicyController() override {
- return policy_controller_;
- }
-
- private:
- std::map<int64_t, OfflinePageItem> pages_;
-
- std::vector<OfflinePageItem> removed_pages_;
-
- // Owned by the test.
- ClientPolicyController* policy_controller_;
-
- base::SimpleTestClock* clock_;
-
- TestOptions options_;
-
- int64_t next_offline_id_;
-};
-
-void OfflinePageTestModel::DeletePagesByOfflineId(
- const std::vector<int64_t>& offline_ids,
- const DeletePageCallback& callback) {
- if (options_ & TestOptions::DELETE_FAILURE) {
- callback.Run(DeletePageResult::STORE_FAILURE);
- return;
- }
- for (const auto id : offline_ids) {
- removed_pages_.push_back(pages_.at(id));
- pages_.erase(id);
- }
- callback.Run(DeletePageResult::SUCCESS);
-}
-
-int64_t OfflinePageTestModel::GetTemporaryPagesSize() const {
- int64_t res = 0;
- for (const auto& id_page_pair : pages_)
- if (policy_controller_->GetPolicy(id_page_pair.second.client_id.name_space)
- .lifetime_policy.lifetime_type ==
- LifetimePolicy::LifetimeType::TEMPORARY)
- res += id_page_pair.second.file_size;
- return res;
-}
-
-OfflinePageTestModel::~OfflinePageTestModel() {}
-
-void OfflinePageTestModel::AddPages(const PageSettings& setting) {
- std::string name_space = setting.name_space;
- int fresh_pages_count = setting.fresh_pages_count;
- int expired_pages_count = setting.expired_pages_count;
- base::Time now = clock()->Now();
- // Fresh pages.
- for (int i = 0; i < fresh_pages_count; i++) {
- OfflinePageItem page =
- OfflinePageItem(kTestUrl, next_offline_id_,
- ClientId(name_space, std::to_string(next_offline_id_)),
- base::FilePath(kFilePath), kTestFileSize);
- page.last_access_time = now;
- pages_[next_offline_id_] = page;
- next_offline_id_++;
- }
- // Expired pages.
- for (int i = 0; i < expired_pages_count; i++) {
- OfflinePageItem page =
- OfflinePageItem(kTestUrl, next_offline_id_,
- ClientId(name_space, std::to_string(next_offline_id_)),
- base::FilePath(kFilePath), kTestFileSize);
- page.last_access_time = now -
- policy_controller_->GetPolicy(name_space)
- .lifetime_policy.expiration_period;
- pages_[next_offline_id_] = page;
- next_offline_id_++;
- }
-}
-
-class OfflinePageStorageManagerTest : public testing::Test {
- public:
- OfflinePageStorageManagerTest();
- OfflinePageStorageManager* manager() { return manager_.get(); }
- OfflinePageTestModel* model() { return model_.get(); }
- ClientPolicyController* policy_controller() {
- return policy_controller_.get();
- }
- TestArchiveManager* test_archive_manager() { return archive_manager_.get(); }
- void OnPagesCleared(size_t pages_cleared_count, ClearStorageResult result);
- void Initialize(const std::vector<PageSettings>& settings,
- StorageStats stats = {kFreeSpaceNormal, 0, 0},
- TestOptions options = TestOptions::DEFAULT);
- void TryClearPages();
- std::string GetStorageUsageHistogramName(const std::string& name_space);
-
- // Checks that the total sample count for the storage usage histograms are all
- // equal to |count|.
- void CheckTotalCountForAllStorageUsageHistograms(
- base::HistogramBase::Count count);
-
- // testing::Test
- void TearDown() override;
-
- base::SimpleTestClock* clock() { return clock_; }
- int last_cleared_page_count() const {
- return static_cast<int>(last_cleared_page_count_);
- }
- int total_cleared_times() const { return total_cleared_times_; }
- ClearStorageResult last_clear_storage_result() const {
- return last_clear_storage_result_;
- }
- base::HistogramTester* histogram_tester() { return histogram_tester_.get(); }
-
- private:
- std::unique_ptr<OfflinePageStorageManager> manager_;
- std::unique_ptr<OfflinePageTestModel> model_;
- std::unique_ptr<ClientPolicyController> policy_controller_;
- std::unique_ptr<TestArchiveManager> archive_manager_;
-
- base::SimpleTestClock* clock_;
- std::unique_ptr<base::HistogramTester> histogram_tester_;
-
- size_t last_cleared_page_count_;
- int total_cleared_times_;
- ClearStorageResult last_clear_storage_result_;
-};
-
-OfflinePageStorageManagerTest::OfflinePageStorageManagerTest()
- : policy_controller_(new ClientPolicyController()),
- last_cleared_page_count_(0),
- total_cleared_times_(0),
- last_clear_storage_result_(ClearStorageResult::SUCCESS) {}
-
-void OfflinePageStorageManagerTest::Initialize(
- const std::vector<PageSettings>& page_settings,
- StorageStats stats,
- TestOptions options) {
- std::unique_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock());
- clock_ = clock.get();
- clock_->SetNow(base::Time::Now());
- model_.reset(new OfflinePageTestModel(page_settings, clock_,
- policy_controller_.get(), options));
-
- if (stats.free_disk_space == 0)
- stats.free_disk_space = kFreeSpaceNormal;
- if (stats.total_archives_size() == 0) {
- stats.temporary_archives_size = model_->GetTemporaryPagesSize();
- }
- archive_manager_.reset(new TestArchiveManager(stats));
- manager_.reset(new OfflinePageStorageManager(
- model_.get(), policy_controller(), archive_manager_.get()));
- manager_->SetClockForTesting(std::move(clock));
-
- histogram_tester_ = std::make_unique<base::HistogramTester>();
-}
-
-void OfflinePageStorageManagerTest::TryClearPages() {
- manager()->ClearPagesIfNeeded(base::Bind(
- &OfflinePageStorageManagerTest::OnPagesCleared, base::Unretained(this)));
-}
-
-std::string OfflinePageStorageManagerTest::GetStorageUsageHistogramName(
- const std::string& name_space) {
- return "OfflinePages.ClearStoragePreRunUsage2." + name_space;
-}
-
-void OfflinePageStorageManagerTest::CheckTotalCountForAllStorageUsageHistograms(
- base::HistogramBase::Count count) {
- for (const std::string name_space : policy_controller_->GetAllNamespaces()) {
- std::string histogram_name = GetStorageUsageHistogramName(name_space);
- std::unique_ptr<base::HistogramSamples> samples =
- histogram_tester_->GetHistogramSamplesSinceCreation(histogram_name);
- EXPECT_EQ(count, samples->TotalCount())
- << "Unexpected " << histogram_name << " total sample count";
- }
-}
-
-void OfflinePageStorageManagerTest::TearDown() {
- manager_.reset();
- model_.reset();
-}
-
-void OfflinePageStorageManagerTest::OnPagesCleared(size_t pages_cleared_count,
- ClearStorageResult result) {
- last_cleared_page_count_ = pages_cleared_count;
- total_cleared_times_++;
- last_clear_storage_result_ = result;
-}
-
-TEST_F(OfflinePageStorageManagerTest, TestClearPagesLessThanLimit) {
- Initialize(std::vector<PageSettings>(
- {{kOneWeekNamespace, 1, 1}, {kOneDayNamespace, 1, 1}}));
- clock()->Advance(base::TimeDelta::FromMinutes(30));
- TryClearPages();
- EXPECT_EQ(2, last_cleared_page_count());
- EXPECT_EQ(1, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
- EXPECT_EQ(2, static_cast<int>(model()->GetRemovedPages().size()));
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneWeekNamespace), 2 * 512, 1);
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneDayNamespace), 2 * 512, 1);
- CheckTotalCountForAllStorageUsageHistograms(1);
-}
-
-TEST_F(OfflinePageStorageManagerTest, TestClearPagesMoreThanLimit) {
- Initialize(std::vector<PageSettings>(
- {{kOneWeekNamespace, 10, 15}, {kOneDayNamespace, 5, 30}}));
- clock()->Advance(base::TimeDelta::FromMinutes(30));
- TryClearPages();
- EXPECT_EQ(45, last_cleared_page_count());
- EXPECT_EQ(1, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
- EXPECT_EQ(45, static_cast<int>(model()->GetRemovedPages().size()));
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneWeekNamespace), 25 * 512, 1);
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneDayNamespace), 35 * 512, 1);
- CheckTotalCountForAllStorageUsageHistograms(1);
-}
-
-TEST_F(OfflinePageStorageManagerTest, TestClearPagesMoreFreshPages) {
- Initialize(std::vector<PageSettings>(
- {{kOneWeekNamespace, 30, 0}, {kOneDayNamespace, 100, 1}}),
- {1000 * (1 << 20), 0});
- clock()->Advance(base::TimeDelta::FromMinutes(30));
- TryClearPages();
- EXPECT_EQ(1, last_cleared_page_count());
- EXPECT_EQ(1, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
- EXPECT_EQ(1, static_cast<int>(model()->GetRemovedPages().size()));
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneWeekNamespace), 30 * 512, 1);
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneDayNamespace), 100 * 512, 1);
- CheckTotalCountForAllStorageUsageHistograms(1);
-}
-
-TEST_F(OfflinePageStorageManagerTest, TestDeletePersistentPages) {
- Initialize(std::vector<PageSettings>({{kPersistentNamespace, 20, 0}}));
- clock()->Advance(base::TimeDelta::FromDays(367));
- TryClearPages();
- EXPECT_EQ(0, last_cleared_page_count());
- EXPECT_EQ(1, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::UNNECESSARY, last_clear_storage_result());
- EXPECT_EQ(0, static_cast<int>(model()->GetRemovedPages().size()));
- // As there's no temporary pages, no reporting happens.
- CheckTotalCountForAllStorageUsageHistograms(0);
-}
-
-TEST_F(OfflinePageStorageManagerTest, TestDeletionFailed) {
- Initialize(std::vector<PageSettings>(
- {{kOneWeekNamespace, 10, 10}, {kOneDayNamespace, 10, 10}}),
- {kFreeSpaceNormal, 0}, TestOptions::DELETE_FAILURE);
- TryClearPages();
- EXPECT_EQ(20, last_cleared_page_count());
- EXPECT_EQ(1, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::DELETE_FAILURE, last_clear_storage_result());
- EXPECT_EQ(0, static_cast<int>(model()->GetRemovedPages().size()));
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneWeekNamespace), 20 * 512, 1);
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneDayNamespace), 20 * 512, 1);
- CheckTotalCountForAllStorageUsageHistograms(1);
-}
-
-TEST_F(OfflinePageStorageManagerTest, TestStorageTimeInterval) {
- Initialize(std::vector<PageSettings>(
- {{kOneWeekNamespace, 10, 10}, {kOneDayNamespace, 10, 10}}));
- clock()->Advance(base::TimeDelta::FromMinutes(30));
- SCOPED_TRACE("Invocation #1 of TryClearPages()");
- TryClearPages();
- EXPECT_EQ(20, last_cleared_page_count());
- EXPECT_EQ(1, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
- EXPECT_EQ(20, static_cast<int>(model()->GetRemovedPages().size()));
- // This histogram should only report once per launch. Checking here for the
- // first report.
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneWeekNamespace), 20 * 512, 1);
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneDayNamespace), 20 * 512, 1);
- CheckTotalCountForAllStorageUsageHistograms(1);
-
- // Advance clock so we go over the gap, but no expired pages.
- clock()->Advance(constants::kClearStorageInterval +
- base::TimeDelta::FromMinutes(1));
- SCOPED_TRACE("Invocation #2 of TryClearPages()");
- TryClearPages();
- EXPECT_EQ(0, last_cleared_page_count());
- EXPECT_EQ(2, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
- EXPECT_EQ(20, static_cast<int>(model()->GetRemovedPages().size()));
-
- // Advance clock so we are still in the gap, should be unnecessary.
- clock()->Advance(constants::kClearStorageInterval -
- base::TimeDelta::FromMinutes(1));
- SCOPED_TRACE("Invocation #3 of TryClearPages()");
- TryClearPages();
- EXPECT_EQ(0, last_cleared_page_count());
- EXPECT_EQ(3, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::UNNECESSARY, last_clear_storage_result());
- EXPECT_EQ(20, static_cast<int>(model()->GetRemovedPages().size()));
- // Testing the histogram after the last run to confirm nothing changed.
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneWeekNamespace), 20 * 512, 1);
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneDayNamespace), 20 * 512, 1);
- CheckTotalCountForAllStorageUsageHistograms(1);
-}
-
-TEST_F(OfflinePageStorageManagerTest, TestClearMultipleTimes) {
- Initialize(std::vector<PageSettings>({{kOneWeekNamespace, 30, 0},
- {kOneDayNamespace, 100, 1},
- {kPersistentNamespace, 40, 0}}),
- {1000 * (1 << 20), 0});
- clock()->Advance(base::TimeDelta::FromMinutes(30));
- LifetimePolicy policy =
- policy_controller()->GetPolicy(kOneDayNamespace).lifetime_policy;
-
- // Scopes are being used to limit the reach of each SCOPED_TRACE message.
- {
- SCOPED_TRACE("Invocation #1 of TryClearPages()");
- TryClearPages();
- EXPECT_EQ(1, last_cleared_page_count());
- EXPECT_EQ(1, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
- EXPECT_EQ(1, static_cast<int>(model()->GetRemovedPages().size()));
- // For this test the once-per-launch flag for the reporting of this
- // histogram will be reset before each clearing run. Note: this histogram
- // always reports the start state of cleaning procedure. It will look as it
- // is always one step behind.
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneWeekNamespace), 30 * 512, 1);
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneDayNamespace), 101 * 512, 1);
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kPersistentNamespace), 40 * 512, 1);
- CheckTotalCountForAllStorageUsageHistograms(1);
- }
-
- {
- // Advance the clock by expiration period of last_n namespace, should be
- // expiring all pages left in the namespace.
- clock()->Advance(policy.expiration_period);
- manager()->ResetUsageReportingFlagForTesting();
- SCOPED_TRACE("Invocation #2 of TryClearPages()");
- TryClearPages();
- EXPECT_EQ(100, last_cleared_page_count());
- EXPECT_EQ(2, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
- EXPECT_EQ(101, static_cast<int>(model()->GetRemovedPages().size()));
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneWeekNamespace), 30 * 512, 2);
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kOneDayNamespace), 101 * 512, 2);
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kPersistentNamespace), 40 * 512, 2);
- CheckTotalCountForAllStorageUsageHistograms(2);
- }
-
- {
- // Only 1 ms passes and no changes in pages, so no need to clear page.
- clock()->Advance(base::TimeDelta::FromMilliseconds(1));
- manager()->ResetUsageReportingFlagForTesting();
- SCOPED_TRACE("Invocation #3 of TryClearPages()");
- TryClearPages();
- EXPECT_EQ(0, last_cleared_page_count());
- EXPECT_EQ(3, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::UNNECESSARY, last_clear_storage_result());
- EXPECT_EQ(101, static_cast<int>(model()->GetRemovedPages().size()));
- CheckTotalCountForAllStorageUsageHistograms(2);
- }
-
- {
- // Adding more fresh pages to make it go over limit.
- clock()->Advance(base::TimeDelta::FromMinutes(5));
- model()->AddPages({kOneWeekNamespace, 400, 0});
- int64_t total_size_before = model()->GetTemporaryPagesSize();
- int64_t available_space = 300 * (1 << 20); // 300 MB
- test_archive_manager()->SetValues(
- {available_space, total_size_before, 40 * kTestFileSize});
- EXPECT_GE(total_size_before, constants::kOfflinePageStorageLimit *
- (available_space + total_size_before));
- // Note: No need to reset usage here as for the last run clearing pages was
- // unnecessary.
- SCOPED_TRACE("Invocation #4 of TryClearPages()");
- TryClearPages();
- EXPECT_LE(total_size_before * constants::kOfflinePageStorageClearThreshold,
- model()->GetTemporaryPagesSize());
- EXPECT_EQ(4, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
- // Number of removed pages should be what was already deleted until the last
- // step plus the what's needed to get to the 10% of total free space.
- EXPECT_EQ(101 + 327, static_cast<int>(model()->GetRemovedPages().size()));
- histogram_tester()->ExpectBucketCount(
- GetStorageUsageHistogramName(kOneWeekNamespace), 30 * 512, 2);
- histogram_tester()->ExpectBucketCount(
- GetStorageUsageHistogramName(kOneWeekNamespace), 430 * 512, 1);
- histogram_tester()->ExpectBucketCount(
- GetStorageUsageHistogramName(kOneDayNamespace), 101 * 512, 2);
- histogram_tester()->ExpectBucketCount(
- GetStorageUsageHistogramName(kOneDayNamespace), 0, 1);
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kPersistentNamespace), 40 * 512, 3);
- CheckTotalCountForAllStorageUsageHistograms(3);
- }
-
- {
- // After more days, all pages should be deleted.
- clock()->Advance(base::TimeDelta::FromDays(30));
- manager()->ResetUsageReportingFlagForTesting();
- SCOPED_TRACE("Invocation #5 of TryClearPages()");
- TryClearPages();
- EXPECT_EQ(0, model()->GetTemporaryPagesSize());
- EXPECT_EQ(5, total_cleared_times());
- EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result());
- // Number of removed pages should be all the temporary pages initially
- // created plus 400 more pages added above for bookmark namespace.
- EXPECT_EQ(131 + 400, static_cast<int>(model()->GetRemovedPages().size()));
- histogram_tester()->ExpectBucketCount(
- GetStorageUsageHistogramName(kOneWeekNamespace), 30 * 512, 2);
- histogram_tester()->ExpectBucketCount(
- GetStorageUsageHistogramName(kOneWeekNamespace), 430 * 512, 1);
- histogram_tester()->ExpectBucketCount(
- GetStorageUsageHistogramName(kOneWeekNamespace), 102 * 512, 1);
- histogram_tester()->ExpectBucketCount(
- GetStorageUsageHistogramName(kOneDayNamespace), 101 * 512, 2);
- histogram_tester()->ExpectBucketCount(
- GetStorageUsageHistogramName(kOneDayNamespace), 0, 2);
- histogram_tester()->ExpectUniqueSample(
- GetStorageUsageHistogramName(kPersistentNamespace), 40 * 512, 4);
- CheckTotalCountForAllStorageUsageHistograms(4);
- }
-}
-
-} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/offline_page_test_archiver.cc b/chromium/components/offline_pages/core/offline_page_test_archiver.cc
index 874767433e1..1b77f7ac59f 100644
--- a/chromium/components/offline_pages/core/offline_page_test_archiver.cc
+++ b/chromium/components/offline_pages/core/offline_page_test_archiver.cc
@@ -46,6 +46,18 @@ void OfflinePageTestArchiver::CreateArchive(
CompleteCreateArchive();
}
+void OfflinePageTestArchiver::PublishArchive(
+ const OfflinePageItem& offline_page,
+ const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+ const base::FilePath& new_file_path,
+ SystemDownloadManager* download_manager,
+ PublishArchiveDoneCallback publish_done_callback) {
+ publish_archive_result_.move_result = SavePageResult::SUCCESS;
+ publish_archive_result_.new_file_path = offline_page.file_path;
+ publish_archive_result_.download_id = 0;
+ std::move(publish_done_callback).Run(offline_page, &publish_archive_result_);
+}
+
void OfflinePageTestArchiver::CompleteCreateArchive() {
DCHECK(!callback_.is_null());
base::FilePath archive_path;
diff --git a/chromium/components/offline_pages/core/offline_page_test_archiver.h b/chromium/components/offline_pages/core/offline_page_test_archiver.h
index 6eb462479b1..bf3ed7253fe 100644
--- a/chromium/components/offline_pages/core/offline_page_test_archiver.h
+++ b/chromium/components/offline_pages/core/offline_page_test_archiver.h
@@ -48,6 +48,13 @@ class OfflinePageTestArchiver : public OfflinePageArchiver {
const CreateArchiveParams& create_archive_params,
const CreateArchiveCallback& callback) override;
+ void PublishArchive(
+ const OfflinePageItem& offline_page,
+ const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+ const base::FilePath& publish_directory,
+ SystemDownloadManager* download_manager,
+ PublishArchiveDoneCallback publish_done_callback) override;
+
// Completes the creation of archive. Should be used with |set_delayed| set to
// true.
void CompleteCreateArchive();
@@ -80,6 +87,7 @@ class OfflinePageTestArchiver : public OfflinePageArchiver {
bool delayed_;
base::string16 result_title_;
std::string digest_to_report_;
+ PublishArchiveResult publish_archive_result_;
CreateArchiveCallback callback_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/chromium/components/offline_pages/core/offline_page_test_store.cc b/chromium/components/offline_pages/core/offline_page_test_store.cc
index 1f63830cff4..8a697339b3c 100644
--- a/chromium/components/offline_pages/core/offline_page_test_store.cc
+++ b/chromium/components/offline_pages/core/offline_page_test_store.cc
@@ -5,6 +5,7 @@
#include "components/offline_pages/core/offline_page_test_store.h"
#include <map>
+#include <utility>
#include "base/bind.h"
#include "base/location.h"
@@ -90,7 +91,7 @@ void OfflinePageTestStore::UpdateOfflinePages(
}
if (!callback.is_null())
task_runner_->PostTask(FROM_HERE,
- base::Bind(callback, base::Passed(&result)));
+ base::BindOnce(callback, std::move(result)));
}
void OfflinePageTestStore::RemoveOfflinePages(
@@ -123,7 +124,7 @@ void OfflinePageTestStore::RemoveOfflinePages(
}
task_runner_->PostTask(FROM_HERE,
- base::Bind(callback, base::Passed(&result)));
+ base::BindOnce(callback, std::move(result)));
}
void OfflinePageTestStore::Reset(const ResetCallback& callback) {
diff --git a/chromium/components/offline_pages/core/offline_page_types.h b/chromium/components/offline_pages/core/offline_page_types.h
index 609490eaaeb..da1235e36a4 100644
--- a/chromium/components/offline_pages/core/offline_page_types.h
+++ b/chromium/components/offline_pages/core/offline_page_types.h
@@ -40,6 +40,10 @@ enum class SavePageResult {
INTERSTITIAL_PAGE,
// Failed to compute digest for the archive file.
DIGEST_CALCULATION_FAILED,
+ // Unable to move the file into a public directory.
+ FILE_MOVE_FAILED,
+ // Unable to add the file to the system download manager.
+ ADD_TO_DOWNLOAD_MANAGER_FAILED,
// NOTE: always keep this entry at the end. Add new result types only
// immediately above this line. Make sure to update the corresponding
// histogram enum accordingly.
@@ -86,6 +90,7 @@ enum class URLSearchMode {
typedef std::vector<int64_t> MultipleOfflineIdResult;
typedef std::vector<OfflinePageItem> MultipleOfflinePageItemResult;
+// TODO(carlosk): All or most of these should use base::OnceCallback.
typedef base::Callback<void(SavePageResult, int64_t)> SavePageCallback;
typedef base::Callback<void(AddPageResult, int64_t)> AddPageCallback;
typedef base::Callback<void(DeletePageResult)> DeletePageCallback;
diff --git a/chromium/components/offline_pages/core/prefetch/BUILD.gn b/chromium/components/offline_pages/core/prefetch/BUILD.gn
index 3fbf1291cd8..8b5b4011dc6 100644
--- a/chromium/components/offline_pages/core/prefetch/BUILD.gn
+++ b/chromium/components/offline_pages/core/prefetch/BUILD.gn
@@ -1,5 +1,5 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
+# 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.
if (is_android) {
@@ -17,6 +17,8 @@ static_library("prefetch") {
"download_cleanup_task.h",
"download_completed_task.cc",
"download_completed_task.h",
+ "finalize_dismissed_url_suggestion_task.cc",
+ "finalize_dismissed_url_suggestion_task.h",
"generate_page_bundle_reconcile_task.cc",
"generate_page_bundle_reconcile_task.h",
"generate_page_bundle_request.cc",
@@ -92,7 +94,7 @@ static_library("prefetch") {
deps = [
"//base",
- "//components/download/public",
+ "//components/download/public/background_service:public",
"//components/gcm_driver",
"//components/gcm_driver/common",
"//components/keyed_service/core",
@@ -139,7 +141,7 @@ static_library("test_support") {
deps = [
":prefetch",
"//base",
- "//components/download/public",
+ "//components/download/public/background_service:public",
"//components/gcm_driver/instance_id",
"//components/keyed_service/core",
"//components/offline_pages/core",
@@ -169,6 +171,7 @@ source_set("unit_tests") {
"download_archives_task_unittest.cc",
"download_cleanup_task_unittest.cc",
"download_completed_task_unittest.cc",
+ "finalize_dismissed_url_suggestion_task_unittest.cc",
"generate_page_bundle_reconcile_task_unittest.cc",
"generate_page_bundle_request_unittest.cc",
"generate_page_bundle_task_unittest.cc",
@@ -203,8 +206,8 @@ source_set("unit_tests") {
":prefetch",
":test_support",
"//base",
- "//components/download/public",
- "//components/download/public/test:test_support",
+ "//components/download/public/background_service:public",
+ "//components/download/public/background_service/test:test_support",
"//components/gcm_driver/instance_id",
"//components/offline_pages/core",
"//components/offline_pages/core:switches",
diff --git a/chromium/components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task.cc b/chromium/components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task.cc
new file mode 100644
index 00000000000..37709a8651b
--- /dev/null
+++ b/chromium/components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task.cc
@@ -0,0 +1,66 @@
+// 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/prefetch/finalize_dismissed_url_suggestion_task.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "components/offline_pages/core/client_id.h"
+#include "components/offline_pages/core/prefetch/store/prefetch_store.h"
+#include "sql/connection.h"
+#include "sql/statement.h"
+
+namespace offline_pages {
+namespace {
+
+bool DeletePageByClientIdIfNotDownloadedSync(const ClientId& client_id,
+ sql::Connection* db) {
+ if (!db)
+ return false;
+ static const char kSql[] =
+ "UPDATE prefetch_items SET state = ?, error_code = ?"
+ " WHERE client_id = ? AND client_namespace = ? "
+ // TODO(carlosk): make this check robust to future changes to the
+ // |PrefetchItemState| enum.
+ " AND state NOT IN (?, ?, ?, ?, ?)";
+
+ sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt(0, static_cast<int>(PrefetchItemState::FINISHED));
+ statement.BindInt(
+ 1, static_cast<int>(PrefetchItemErrorCode::SUGGESTION_INVALIDATED));
+ statement.BindString(2, client_id.id);
+ statement.BindString(3, client_id.name_space);
+ statement.BindInt(4, static_cast<int>(PrefetchItemState::DOWNLOADING));
+ statement.BindInt(5, static_cast<int>(PrefetchItemState::DOWNLOADED));
+ statement.BindInt(6, static_cast<int>(PrefetchItemState::IMPORTING));
+ statement.BindInt(7, static_cast<int>(PrefetchItemState::FINISHED));
+ statement.BindInt(8, static_cast<int>(PrefetchItemState::ZOMBIE));
+ return statement.Run();
+}
+} // namespace
+
+FinalizeDismissedUrlSuggestionTask::FinalizeDismissedUrlSuggestionTask(
+ PrefetchStore* prefetch_store,
+ const ClientId& client_id)
+ : prefetch_store_(prefetch_store),
+ client_id_(client_id),
+ weak_ptr_factory_(this) {
+ DCHECK(prefetch_store_);
+}
+
+FinalizeDismissedUrlSuggestionTask::~FinalizeDismissedUrlSuggestionTask() {}
+
+void FinalizeDismissedUrlSuggestionTask::Run() {
+ prefetch_store_->Execute<bool>(
+ base::BindOnce(&DeletePageByClientIdIfNotDownloadedSync, client_id_),
+ base::BindOnce(&FinalizeDismissedUrlSuggestionTask::OnComplete,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void FinalizeDismissedUrlSuggestionTask::OnComplete(bool result) {
+ TaskComplete();
+}
+
+} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task.h b/chromium/components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task.h
new file mode 100644
index 00000000000..1e86bc7d348
--- /dev/null
+++ b/chromium/components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task.h
@@ -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.
+
+#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_FINALIZE_DISMISSED_URL_SUGGESTION_TASK_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_FINALIZE_DISMISSED_URL_SUGGESTION_TASK_H_
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/offline_pages/core/prefetch/prefetch_types.h"
+#include "components/offline_pages/core/task.h"
+
+namespace offline_pages {
+struct ClientId;
+class PrefetchStore;
+
+// A Task that marks a PrefetchItem as finished with a SUGGESTION_INVALIDATED
+// error code if it matches a ClientId, but only when the page has not been (at
+// least partially) downloaded.
+class FinalizeDismissedUrlSuggestionTask : public Task {
+ public:
+ FinalizeDismissedUrlSuggestionTask(PrefetchStore* prefetch_store,
+ const ClientId& client_id);
+ ~FinalizeDismissedUrlSuggestionTask() override;
+
+ void Run() override;
+
+ private:
+ void OnComplete(bool removed);
+
+ PrefetchStore* prefetch_store_;
+ ClientId client_id_;
+ base::WeakPtrFactory<FinalizeDismissedUrlSuggestionTask> weak_ptr_factory_;
+ DISALLOW_COPY_AND_ASSIGN(FinalizeDismissedUrlSuggestionTask);
+};
+
+} // namespace offline_pages
+
+#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_FINALIZE_DISMISSED_URL_SUGGESTION_TASK_H_
diff --git a/chromium/components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task_unittest.cc b/chromium/components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task_unittest.cc
new file mode 100644
index 00000000000..45b21342aa3
--- /dev/null
+++ b/chromium/components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task_unittest.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/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task.h"
+
+#include "components/offline_pages/core/prefetch/prefetch_item.h"
+#include "components/offline_pages/core/prefetch/prefetch_task_test_base.h"
+#include "components/offline_pages/core/prefetch/prefetch_types.h"
+#include "components/offline_pages/core/prefetch/store/prefetch_store.h"
+#include "components/offline_pages/core/prefetch/store/prefetch_store_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace offline_pages {
+
+class FinalizeDismissedUrlSuggestionTaskTest : public PrefetchTaskTestBase {
+ public:
+ ~FinalizeDismissedUrlSuggestionTaskTest() override = default;
+
+ PrefetchItem AddItem(PrefetchItemState state) {
+ PrefetchItem item = item_generator()->CreateItem(state);
+ EXPECT_TRUE(store_util()->InsertPrefetchItem(item));
+ return item;
+ }
+};
+
+TEST_F(FinalizeDismissedUrlSuggestionTaskTest, StoreFailure) {
+ PrefetchItem item = AddItem(PrefetchItemState::RECEIVED_BUNDLE);
+ store_util()->SimulateInitializationError();
+
+ FinalizeDismissedUrlSuggestionTask task(store(), item.client_id);
+ ExpectTaskCompletes(&task);
+ task.Run();
+ RunUntilIdle();
+}
+
+TEST_F(FinalizeDismissedUrlSuggestionTaskTest, NotFound) {
+ PrefetchItem item = AddItem(PrefetchItemState::RECEIVED_BUNDLE);
+ FinalizeDismissedUrlSuggestionTask task(store(), ClientId("abc", "123"));
+ ExpectTaskCompletes(&task);
+ task.Run();
+ RunUntilIdle();
+ EXPECT_EQ(1, store_util()->CountPrefetchItems());
+}
+
+TEST_F(FinalizeDismissedUrlSuggestionTaskTest, Change) {
+ // All states where we expect a transition to SUGGESTION_INVALIDATED.
+ // TODO(carlosk): Make this test robust to future changes to the
+ // |PrefetchItemState| enum.
+ const std::vector<PrefetchItemState> change_states = {
+ PrefetchItemState::NEW_REQUEST,
+ PrefetchItemState::SENT_GENERATE_PAGE_BUNDLE,
+ PrefetchItemState::AWAITING_GCM,
+ PrefetchItemState::RECEIVED_GCM,
+ PrefetchItemState::SENT_GET_OPERATION,
+ PrefetchItemState::RECEIVED_BUNDLE,
+ };
+ // Add an item for each state, and add the FINISHED item to the expectation.
+ std::vector<PrefetchItem> items;
+ std::set<PrefetchItem> want_items;
+ for (const PrefetchItemState state : change_states) {
+ PrefetchItem item = AddItem(state);
+ items.push_back(item);
+ item.state = PrefetchItemState::FINISHED;
+ item.error_code = PrefetchItemErrorCode::SUGGESTION_INVALIDATED;
+ want_items.insert(item);
+ }
+ for (const PrefetchItem& item : items) {
+ FinalizeDismissedUrlSuggestionTask task(store(), item.client_id);
+ ExpectTaskCompletes(&task);
+ task.Run();
+ RunUntilIdle();
+ }
+
+ std::set<PrefetchItem> final_items;
+ store_util()->GetAllItems(&final_items);
+ EXPECT_EQ(want_items, final_items);
+}
+
+TEST_F(FinalizeDismissedUrlSuggestionTaskTest, NoChange) {
+ // All states where no change is made.
+ // TODO(carlosk): Make this test robust to future changes to the
+ // |PrefetchItemState| enum.
+ const std::vector<PrefetchItemState> no_change_states = {
+ PrefetchItemState::DOWNLOADING, PrefetchItemState::DOWNLOADED,
+ PrefetchItemState::IMPORTING, PrefetchItemState::FINISHED,
+ PrefetchItemState::ZOMBIE,
+ };
+ std::set<PrefetchItem> items;
+ for (const PrefetchItemState state : no_change_states) {
+ items.insert(AddItem(state));
+ }
+ for (const PrefetchItem& item : items) {
+ FinalizeDismissedUrlSuggestionTask task(store(), item.client_id);
+ ExpectTaskCompletes(&task);
+ task.Run();
+ RunUntilIdle();
+ }
+
+ std::set<PrefetchItem> final_items;
+ store_util()->GetAllItems(&final_items);
+ EXPECT_EQ(items, final_items);
+}
+
+} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/prefetch/metrics_finalization_task.cc b/chromium/components/offline_pages/core/prefetch/metrics_finalization_task.cc
index 75e56b65f57..f3ecd526a97 100644
--- a/chromium/components/offline_pages/core/prefetch/metrics_finalization_task.cc
+++ b/chromium/components/offline_pages/core/prefetch/metrics_finalization_task.cc
@@ -224,13 +224,13 @@ bool ReportMetricsAndFinalizeSync(sql::Connection* db) {
if (transaction.Commit()) {
for (const auto& url : urls) {
- DVLOG(1) << "Finalized prefetch item: (" << url.offline_id << ", "
- << url.generate_bundle_attempts << ", "
+ DVLOG(1) << "Finalized prefetch item with error code "
+ << static_cast<int>(url.error_code) << ": (" << url.offline_id
+ << ", " << url.generate_bundle_attempts << ", "
<< url.get_operation_attempts << ", "
<< url.download_initiation_attempts << ", "
<< url.archive_body_length << ", " << url.creation_time << ", "
- << static_cast<int>(url.error_code) << ", " << url.file_size
- << ")";
+ << url.file_size << ")";
ReportMetricsFor(url, now);
}
return true;
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc b/chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
index 7b0f609bfb8..e97a36b9897 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
@@ -18,6 +18,7 @@
#include "components/offline_pages/core/prefetch/download_archives_task.h"
#include "components/offline_pages/core/prefetch/download_cleanup_task.h"
#include "components/offline_pages/core/prefetch/download_completed_task.h"
+#include "components/offline_pages/core/prefetch/finalize_dismissed_url_suggestion_task.h"
#include "components/offline_pages/core/prefetch/generate_page_bundle_reconcile_task.h"
#include "components/offline_pages/core/prefetch/generate_page_bundle_task.h"
#include "components/offline_pages/core/prefetch/get_operation_task.h"
@@ -120,8 +121,9 @@ void PrefetchDispatcherImpl::RemovePrefetchURLsByClientId(
const ClientId& client_id) {
if (!service_->GetPrefetchConfiguration()->IsPrefetchingEnabled())
return;
-
- NOTIMPLEMENTED();
+ PrefetchStore* prefetch_store = service_->GetPrefetchStore();
+ task_queue_.AddTask(std::make_unique<FinalizeDismissedUrlSuggestionTask>(
+ prefetch_store, client_id));
}
void PrefetchDispatcherImpl::BeginBackgroundTask(
@@ -195,9 +197,8 @@ void PrefetchDispatcherImpl::QueueActionTasks() {
task_queue_.AddTask(std::move(download_archives_task));
// The following tasks should not be run unless we are in the background task,
- // as we need to ensure WiFi access at that time. Schedule them anyway if
- // limitless prefetching is enabled.
- if (!background_task_ && !offline_pages::IsLimitlessPrefetchingEnabled())
+ // as we need to ensure WiFi access at that time.
+ if (!background_task_)
return;
std::unique_ptr<Task> get_operation_task = std::make_unique<GetOperationTask>(
@@ -216,7 +217,6 @@ void PrefetchDispatcherImpl::QueueActionTasks() {
&PrefetchDispatcherImpl::DidGenerateBundleOrGetOperationRequest,
weak_factory_.GetWeakPtr(), "GeneratePageBundleRequest"));
task_queue_.AddTask(std::move(generate_page_bundle_task));
-
}
void PrefetchDispatcherImpl::StopBackgroundTask() {
@@ -247,8 +247,8 @@ void PrefetchDispatcherImpl::DisposeTask() {
// Delay the deletion till the caller finishes.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&DeleteBackgroundTaskHelper,
- base::Passed(std::move(background_task_))));
+ FROM_HERE,
+ base::BindOnce(&DeleteBackgroundTaskHelper, std::move(background_task_)));
}
void PrefetchDispatcherImpl::GCMOperationCompletedMessageReceived(
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 b681a33742b..83edcb1411e 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
@@ -189,6 +189,17 @@ TEST_F(PrefetchDispatcherTest, AddCandidatePrefetchURLsTask) {
EXPECT_FALSE(dispatcher_task_queue()->HasRunningTask());
}
+TEST_F(PrefetchDispatcherTest, RemovePrefetchURLsByClientId) {
+ prefetch_dispatcher()->AddCandidatePrefetchURLs(kTestNamespace, test_urls_);
+ RunUntilIdle();
+ prefetch_dispatcher()->RemovePrefetchURLsByClientId(
+ ClientId(kTestNamespace, test_urls_.front().id));
+ EXPECT_TRUE(dispatcher_task_queue()->HasPendingTasks());
+ RunUntilIdle();
+ EXPECT_FALSE(dispatcher_task_queue()->HasPendingTasks());
+ EXPECT_FALSE(dispatcher_task_queue()->HasRunningTask());
+}
+
TEST_F(PrefetchDispatcherTest, DispatcherDoesNothingIfFeatureNotEnabled) {
base::test::ScopedFeatureList disabled_feature_list;
disabled_feature_list.InitAndDisableFeature(kPrefetchingOfflinePagesFeature);
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_download_flow_unittest.cc b/chromium/components/offline_pages/core/prefetch/prefetch_download_flow_unittest.cc
index fe281d70e90..f86a9c8535e 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_download_flow_unittest.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_download_flow_unittest.cc
@@ -8,7 +8,7 @@
#include <vector>
#include "base/test/scoped_feature_list.h"
-#include "components/download/public/test/test_download_service.h"
+#include "components/download/public/background_service/test/test_download_service.h"
#include "components/offline_pages/core/offline_page_feature.h"
#include "components/offline_pages/core/prefetch/prefetch_background_task.h"
#include "components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h"
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 06bf3563866..2006d54f1de 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.cc
@@ -9,8 +9,9 @@
#include "base/strings/string_util.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
-#include "components/download/public/download_params.h"
-#include "components/download/public/download_service.h"
+#include "base/trace_event/trace_event.h"
+#include "components/download/public/background_service/download_params.h"
+#include "components/download/public/background_service/download_service.h"
#include "components/offline_pages/core/offline_event_logger.h"
#include "components/offline_pages/core/offline_page_feature.h"
#include "components/offline_pages/core/prefetch/prefetch_dispatcher.h"
@@ -146,6 +147,15 @@ void PrefetchDownloaderImpl::OnDownloadServiceReady(
success_downloads) {
DCHECK_EQ(DownloadServiceStatus::INITIALIZING, download_service_status_);
download_service_status_ = DownloadServiceStatus::STARTED;
+ // Given the imposed simultaneous downloads limits, outstanding_download_ids
+ // will only ever contain a handful of elements and so only a negligible
+ // performance impact is expected from the trace-only loop below.
+ for (const std::string& outstanding_download_id : outstanding_download_ids) {
+ TRACE_EVENT_ASYNC_BEGIN2(
+ "offline_pages", "PrefetchDownloaderImpl: downloading article",
+ std::hash<std::string>{}(outstanding_download_id), "download_id",
+ outstanding_download_id, "resumed after restart", "true");
+ }
prefetch_service_->GetLogger()->RecordActivity("Downloader: Service ready.");
@@ -177,6 +187,9 @@ void PrefetchDownloaderImpl::OnDownloadSucceeded(
const std::string& download_id,
const base::FilePath& file_path,
int64_t file_size) {
+ TRACE_EVENT_ASYNC_END1(
+ "offline_pages", "PrefetchDownloaderImpl: downloading article",
+ std::hash<std::string>{}(download_id), "succeeded", "true");
prefetch_service_->GetLogger()->RecordActivity(
"Downloader: Download succeeded, download_id=" + download_id);
NotifyDispatcher(prefetch_service_,
@@ -184,6 +197,9 @@ void PrefetchDownloaderImpl::OnDownloadSucceeded(
}
void PrefetchDownloaderImpl::OnDownloadFailed(const std::string& download_id) {
+ TRACE_EVENT_ASYNC_END1(
+ "offline_pages", "PrefetchDownloaderImpl: downloading article",
+ std::hash<std::string>{}(download_id), "succeeded", "false");
PrefetchDownloadResult result;
result.download_id = download_id;
prefetch_service_->GetLogger()->RecordActivity(
@@ -206,8 +222,13 @@ void PrefetchDownloaderImpl::OnStartDownload(
// to simplify the control flow since this situation should rarely happen. The
// Download.Service.Request.StartResult.OfflinePage histogram tracks these
// cases and would signal the need to revisit this decision.
- if (result != download::DownloadParams::StartResult::ACCEPTED)
+ if (result != download::DownloadParams::StartResult::ACCEPTED) {
OnDownloadFailed(download_id);
+ } else {
+ TRACE_EVENT_ASYNC_BEGIN1(
+ "offline_pages", "PrefetchDownloaderImpl: downloading article",
+ std::hash<std::string>{}(download_id), "download_id", download_id);
+ }
}
void PrefetchDownloaderImpl::CleanupDownloads(
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.h b/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.h
index 4f920cc78bc..0932c4745b2 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.h
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.h
@@ -14,7 +14,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/clock.h"
-#include "components/download/public/download_params.h"
+#include "components/download/public/background_service/download_params.h"
#include "components/offline_pages/core/prefetch/prefetch_downloader.h"
#include "components/offline_pages/core/prefetch/prefetch_types.h"
#include "components/version_info/channel.h"
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 963464c334c..f42ec4059b2 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
@@ -10,7 +10,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
-#include "components/download/public/test/test_download_service.h"
+#include "components/download/public/background_service/test/test_download_service.h"
#include "components/offline_pages/core/client_namespace_constants.h"
#include "components/offline_pages/core/prefetch/prefetch_request_test_base.h"
#include "components/offline_pages/core/prefetch/prefetch_server_urls.h"
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_network_request_factory_impl.cc b/chromium/components/offline_pages/core/prefetch/prefetch_network_request_factory_impl.cc
index 6de2d9d524e..7d245a74bd9 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_network_request_factory_impl.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_network_request_factory_impl.cc
@@ -6,16 +6,25 @@
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
+#include "components/offline_pages/core/offline_page_feature.h"
#include "components/offline_pages/core/prefetch/generate_page_bundle_request.h"
#include "components/offline_pages/core/prefetch/get_operation_request.h"
namespace {
+// Max size of all articles archives to be generated from a single request. This
+// 20 MiB value matches the current daily download limit.
constexpr int kMaxBundleSizeBytes = 20 * 1024 * 1024; // 20 MB
+// Max size of all articles archives to be generated from a single request when
+// limitless prefetching is enabled. The 200 MiB value allows for 100 URLs (the
+// maximum allowed in a single request) with 2 MiB articles (approximately
+// double the average article size).
+constexpr int kMaxBundleSizeForLimitlessBytes = 200 * 1024 * 1024; // 200 MB
+
// Max concurrent outstanding requests. If more requests asked to be created,
// the requests are silently not created (considered failed). This is used
// as emergency limit that should rarely be encountered in normal operations.
-const int kMaxConcurrentRequests = 10;
+constexpr int kMaxConcurrentRequests = 10;
} // namespace
namespace offline_pages {
@@ -55,10 +64,13 @@ void PrefetchNetworkRequestFactoryImpl::MakeGeneratePageBundleRequest(
const PrefetchRequestFinishedCallback& callback) {
if (!AddConcurrentRequest())
return;
+ int max_bundle_size = IsLimitlessPrefetchingEnabled()
+ ? kMaxBundleSizeForLimitlessBytes
+ : kMaxBundleSizeBytes;
uint64_t request_id = GetNextRequestId();
generate_page_bundle_requests_[request_id] =
std::make_unique<GeneratePageBundleRequest>(
- user_agent_, gcm_registration_id, kMaxBundleSizeBytes, url_strings,
+ user_agent_, gcm_registration_id, max_bundle_size, url_strings,
channel_, request_context_.get(),
base::Bind(
&PrefetchNetworkRequestFactoryImpl::GeneratePageBundleRequestDone,
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_types.h b/chromium/components/offline_pages/core/prefetch/prefetch_types.h
index 0d8c92eb19a..dda8c96d0db 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_types.h
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_types.h
@@ -183,8 +183,11 @@ enum class PrefetchItemErrorCode {
// The archive importing was not completed probably due to that Chrome was
// killed before everything finishes.
IMPORT_LOST = 1600,
+ // The page suggestion is no longer valid, so the item no longer needs to be
+ // downloaded.
+ SUGGESTION_INVALIDATED = 1700,
// Note: Must always have the same value as the last actual entry.
- MAX = IMPORT_LOST
+ MAX = SUGGESTION_INVALIDATED
};
// Callback invoked upon completion of a prefetch request.
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 d316c64839a..355b1e3e6c2 100644
--- a/chromium/components/offline_pages/core/prefetch/store/prefetch_store.h
+++ b/chromium/components/offline_pages/core/prefetch/store/prefetch_store.h
@@ -86,7 +86,7 @@ class PrefetchStore {
}
TRACE_EVENT_ASYNC_BEGIN1(
- "offline_pages", "Prefetch Store: Command execution", this,
+ "offline_pages", "Prefetch Store: task execution", this,
"is store loaded",
initialization_status_ == InitializationStatus::SUCCESS);
// Ensure that any scheduled close operations are canceled.
@@ -128,10 +128,16 @@ class PrefetchStore {
base::BindOnce(&PrefetchStore::CloseInternal,
closing_weak_ptr_factory_.GetWeakPtr()),
kClosingDelay);
- TRACE_EVENT_ASYNC_END0("offline_pages", "Prefetch Store: Command execution",
- this);
+ // Note: the time recorded for this trace step will include thread hop wait
+ // times to the background thread and back.
+ TRACE_EVENT_ASYNC_STEP_PAST0(
+ "offline_pages", "Prefetch Store: task execution", this, "Task");
std::move(result_callback).Run(std::move(result));
+ TRACE_EVENT_ASYNC_STEP_PAST0(
+ "offline_pages", "Prefetch Store: task execution", this, "Callback");
+ TRACE_EVENT_ASYNC_END0("offline_pages", "Prefetch Store: task execution",
+ this);
}
// Internal function initiating the closing.
diff --git a/chromium/components/offline_pages/core/prefetch/suggested_articles_observer.h b/chromium/components/offline_pages/core/prefetch/suggested_articles_observer.h
index 919bfd2b851..4e369b39e5b 100644
--- a/chromium/components/offline_pages/core/prefetch/suggested_articles_observer.h
+++ b/chromium/components/offline_pages/core/prefetch/suggested_articles_observer.h
@@ -33,9 +33,6 @@ class SuggestedArticlesObserver
void SetContentSuggestionsServiceAndObserve(
ntp_snippets::ContentSuggestionsService* service);
- // TODO(dewittj): Make this private when the SQL store is up and running.
- bool GetCurrentSuggestions(std::vector<PrefetchURL>* result);
-
// ContentSuggestionsService::Observer overrides.
void OnNewSuggestions(ntp_snippets::Category category) override;
void OnCategoryStatusChanged(
@@ -51,6 +48,8 @@ class SuggestedArticlesObserver
std::vector<ntp_snippets::ContentSuggestion>* GetTestingArticles();
private:
+ bool GetCurrentSuggestions(std::vector<PrefetchURL>* result);
+
// Unowned, only used when we are called by observer methods (so the
// pointer will be valid).
ntp_snippets::ContentSuggestionsService* content_suggestions_service_ =
diff --git a/chromium/components/offline_pages/core/prefetch/test_download_client.h b/chromium/components/offline_pages/core/prefetch/test_download_client.h
index b91c0d7d526..749651a068c 100644
--- a/chromium/components/offline_pages/core/prefetch/test_download_client.h
+++ b/chromium/components/offline_pages/core/prefetch/test_download_client.h
@@ -6,7 +6,7 @@
#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_TEST_DOWNLOAD_CLIENT_H_
#include "base/macros.h"
-#include "components/download/public/test/empty_client.h"
+#include "components/download/public/background_service/test/empty_client.h"
namespace offline_pages {
diff --git a/chromium/components/offline_pages/core/request_header/BUILD.gn b/chromium/components/offline_pages/core/request_header/BUILD.gn
index 67587c74058..2f906892745 100644
--- a/chromium/components/offline_pages/core/request_header/BUILD.gn
+++ b/chromium/components/offline_pages/core/request_header/BUILD.gn
@@ -16,6 +16,7 @@ static_library("request_header") {
deps = [
"//base",
+ "//url:url",
]
}
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 9c58e7d82ed..7cb311f13c2 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
@@ -14,15 +14,20 @@ const char kOfflinePageHeaderReasonKey[] = "reason";
const char kOfflinePageHeaderReasonValueDueToNetError[] = "error";
const char kOfflinePageHeaderReasonValueFromDownload[] = "download";
const char kOfflinePageHeaderReasonValueReload[] = "reload";
+const char kOfflinePageHeaderReasonValueFromNotification[] = "notification";
+const char kOfflinePageHeaderReasonFileUrlIntent[] = "file_url_intent";
+const char kOfflinePageHeaderReasonContentUrlIntent[] = "content_url_intent";
const char kOfflinePageHeaderPersistKey[] = "persist";
const char kOfflinePageHeaderIDKey[] = "id";
+const char kOfflinePageHeaderIntentUrlKey[] = "intent_url";
namespace {
bool ParseOfflineHeaderValue(const std::string& header_value,
bool* need_to_persist,
OfflinePageHeader::Reason* reason,
- std::string* id) {
+ std::string* id,
+ GURL* intent_url) {
// If the offline header is not present, treat it as not parsed successfully.
if (header_value.empty())
return false;
@@ -51,10 +56,21 @@ bool ParseOfflineHeaderValue(const std::string& header_value,
*reason = OfflinePageHeader::Reason::DOWNLOAD;
else if (value == kOfflinePageHeaderReasonValueReload)
*reason = OfflinePageHeader::Reason::RELOAD;
+ else if (value == kOfflinePageHeaderReasonValueFromNotification)
+ *reason = OfflinePageHeader::Reason::NOTIFICATION;
+ else if (value == kOfflinePageHeaderReasonFileUrlIntent)
+ *reason = OfflinePageHeader::Reason::FILE_URL_INTENT;
+ else if (value == kOfflinePageHeaderReasonContentUrlIntent)
+ *reason = OfflinePageHeader::Reason::CONTENT_URL_INTENT;
else
return false;
} else if (key == kOfflinePageHeaderIDKey) {
*id = value;
+ } else if (key == kOfflinePageHeaderIntentUrlKey) {
+ GURL url = GURL(value);
+ if (!url.is_valid())
+ return false;
+ *intent_url = url;
} else {
return false;
}
@@ -71,6 +87,12 @@ std::string ReasonToString(OfflinePageHeader::Reason reason) {
return kOfflinePageHeaderReasonValueFromDownload;
case OfflinePageHeader::Reason::RELOAD:
return kOfflinePageHeaderReasonValueReload;
+ case OfflinePageHeader::Reason::NOTIFICATION:
+ return kOfflinePageHeaderReasonValueFromNotification;
+ case OfflinePageHeader::Reason::FILE_URL_INTENT:
+ return kOfflinePageHeaderReasonFileUrlIntent;
+ case OfflinePageHeader::Reason::CONTENT_URL_INTENT:
+ return kOfflinePageHeaderReasonContentUrlIntent;
default:
NOTREACHED();
return "";
@@ -88,7 +110,8 @@ OfflinePageHeader::OfflinePageHeader(const std::string& header_value)
: did_fail_parsing_for_test(false),
need_to_persist(false),
reason(Reason::NONE) {
- if (!ParseOfflineHeaderValue(header_value, &need_to_persist, &reason, &id)) {
+ if (!ParseOfflineHeaderValue(header_value, &need_to_persist, &reason, &id,
+ &intent_url)) {
did_fail_parsing_for_test = true;
Clear();
}
@@ -119,6 +142,13 @@ std::string OfflinePageHeader::GetCompleteHeaderString() const {
value += id;
}
+ if (!intent_url.is_empty()) {
+ value += " ";
+ value += kOfflinePageHeaderIntentUrlKey;
+ value += "=";
+ value += intent_url.spec();
+ }
+
return value;
}
diff --git a/chromium/components/offline_pages/core/request_header/offline_page_header.h b/chromium/components/offline_pages/core/request_header/offline_page_header.h
index 07175c6f0b1..c69a545e8b7 100644
--- a/chromium/components/offline_pages/core/request_header/offline_page_header.h
+++ b/chromium/components/offline_pages/core/request_header/offline_page_header.h
@@ -7,6 +7,8 @@
#include <string>
+#include "url/gurl.h"
+
namespace offline_pages {
// Header that defines the custom behavior to load offline pages. Its value is a
@@ -25,23 +27,44 @@ extern const char kOfflinePageHeaderReasonKey[];
// The offline page should be loaded even when the network is connected. This is
// because the live version failed to load due to certain net error.
extern const char kOfflinePageHeaderReasonValueDueToNetError[];
-// The offline page should be loaded because the user clicks to open the
-// downloaded page explicitly.
+// The offline page should be loaded because the user clicks the downloaded page
+// in Downloads home.
extern const char kOfflinePageHeaderReasonValueFromDownload[];
// This only happens after the offline page is loaded due to above reason and
// then the user reload current page. The network condition should be checked
// this time to decide if a live version should be tried again.
extern const char kOfflinePageHeaderReasonValueReload[];
+// The offline page should be loaded because the user clicks the notification
+// about a downloaded page.
+extern const char kOfflinePageHeaderReasonValueFromNotification[];
+// The offline page may be loaded when a file URL intent to view MHTML file is
+// received by Chrome (Android only).
+extern const char kOfflinePageHeaderReasonValueFromFileUrlIntent[];
+// The offline page may be loaded when a content URL intent to view MHTML
+// content is received by Chrome (Android only).
+extern const char kOfflinePageHeaderReasonValueFromContentUrlIntent[];
// The name used in name-value pair of kOfflinePageHeader to denote the offline
// ID of the offline page to load.
extern const char kOfflinePageHeaderIDKey[];
+// The name used in name-value pair of kOfflinePageHeader to provide the source
+// that may trigger loading the offline page.
+extern const char kOfflinePageHeaderIntentUrlKey[];
+
// Used to parse the extra request header string that defines offline page
// loading behaviors.
struct OfflinePageHeader {
public:
- enum class Reason { NONE, NET_ERROR, DOWNLOAD, RELOAD };
+ enum class Reason {
+ NONE,
+ NET_ERROR,
+ DOWNLOAD,
+ RELOAD,
+ NOTIFICATION,
+ FILE_URL_INTENT,
+ CONTENT_URL_INTENT
+ };
OfflinePageHeader();
@@ -68,6 +91,10 @@ struct OfflinePageHeader {
// The offline ID of the page to load.
std::string id;
+
+ // The URL of the intent that may trigger loading the offline page (Android
+ // only).
+ GURL intent_url;
};
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/request_header/offline_page_header_unittest.cc b/chromium/components/offline_pages/core/request_header/offline_page_header_unittest.cc
index 636c3bdbe96..99ac6974b46 100644
--- a/chromium/components/offline_pages/core/request_header/offline_page_header_unittest.cc
+++ b/chromium/components/offline_pages/core/request_header/offline_page_header_unittest.cc
@@ -16,11 +16,13 @@ class OfflinePageHeaderTest : public testing::Test {
bool ParseFromHeaderValue(const std::string& header_value,
bool* need_to_persist,
OfflinePageHeader::Reason* reason,
- std::string* id) {
+ std::string* id,
+ GURL* intent_url) {
OfflinePageHeader header(header_value);
*need_to_persist = header.need_to_persist;
*reason = header.reason;
*id = header.id;
+ *intent_url = header.intent_url;
return !header.did_fail_parsing_for_test;
}
};
@@ -29,45 +31,115 @@ TEST_F(OfflinePageHeaderTest, Parse) {
bool need_to_persist;
OfflinePageHeader::Reason reason;
std::string id;
+ GURL intent_url;
- EXPECT_FALSE(ParseFromHeaderValue("", &need_to_persist, &reason, &id));
- EXPECT_FALSE(ParseFromHeaderValue(" ", &need_to_persist, &reason, &id));
- EXPECT_FALSE(ParseFromHeaderValue(" , ", &need_to_persist, &reason, &id));
- EXPECT_FALSE(ParseFromHeaderValue("reason", &need_to_persist, &reason, &id));
- EXPECT_FALSE(ParseFromHeaderValue("a b c", &need_to_persist, &reason, &id));
-
+ // Unstructured data.
+ EXPECT_FALSE(
+ ParseFromHeaderValue("", &need_to_persist, &reason, &id, &intent_url));
+ EXPECT_FALSE(
+ ParseFromHeaderValue(" ", &need_to_persist, &reason, &id, &intent_url));
+ EXPECT_FALSE(
+ ParseFromHeaderValue(" , ", &need_to_persist, &reason, &id, &intent_url));
+ EXPECT_FALSE(ParseFromHeaderValue("reason", &need_to_persist, &reason, &id,
+ &intent_url));
+ EXPECT_FALSE(ParseFromHeaderValue("a b c", &need_to_persist, &reason, &id,
+ &intent_url));
EXPECT_FALSE(
- ParseFromHeaderValue("persist=aa", &need_to_persist, &reason, &id));
+ ParseFromHeaderValue("a=b", &need_to_persist, &reason, &id, &intent_url));
- EXPECT_TRUE(
- ParseFromHeaderValue("persist=1", &need_to_persist, &reason, &id));
+ // Parse persist field.
+ EXPECT_FALSE(ParseFromHeaderValue("persist=aa", &need_to_persist, &reason,
+ &id, &intent_url));
+
+ EXPECT_TRUE(ParseFromHeaderValue("persist=1", &need_to_persist, &reason, &id,
+ &intent_url));
EXPECT_TRUE(need_to_persist);
+ EXPECT_EQ(OfflinePageHeader::Reason::NONE, reason);
+ EXPECT_EQ("", id);
+ EXPECT_TRUE(intent_url.is_empty());
- EXPECT_TRUE(
- ParseFromHeaderValue("persist=0", &need_to_persist, &reason, &id));
+ EXPECT_TRUE(ParseFromHeaderValue("persist=0", &need_to_persist, &reason, &id,
+ &intent_url));
EXPECT_FALSE(need_to_persist);
EXPECT_EQ(OfflinePageHeader::Reason::NONE, reason);
EXPECT_EQ("", id);
+ EXPECT_TRUE(intent_url.is_empty());
- EXPECT_FALSE(
- ParseFromHeaderValue("reason=foo", &need_to_persist, &reason, &id));
+ // Parse reason field.
+ EXPECT_FALSE(ParseFromHeaderValue("reason=foo", &need_to_persist, &reason,
+ &id, &intent_url));
- EXPECT_TRUE(
- ParseFromHeaderValue("reason=error", &need_to_persist, &reason, &id));
+ EXPECT_TRUE(ParseFromHeaderValue("reason=error", &need_to_persist, &reason,
+ &id, &intent_url));
EXPECT_FALSE(need_to_persist);
EXPECT_EQ(OfflinePageHeader::Reason::NET_ERROR, reason);
EXPECT_EQ("", id);
+ EXPECT_TRUE(intent_url.is_empty());
+
+ EXPECT_TRUE(ParseFromHeaderValue("reason=download", &need_to_persist, &reason,
+ &id, &intent_url));
+ EXPECT_FALSE(need_to_persist);
+ EXPECT_EQ(OfflinePageHeader::Reason::DOWNLOAD, reason);
+ EXPECT_EQ("", id);
+ EXPECT_TRUE(intent_url.is_empty());
+
+ EXPECT_TRUE(ParseFromHeaderValue("reason=reload", &need_to_persist, &reason,
+ &id, &intent_url));
+ EXPECT_FALSE(need_to_persist);
+ EXPECT_EQ(OfflinePageHeader::Reason::RELOAD, reason);
+ EXPECT_EQ("", id);
+ EXPECT_TRUE(intent_url.is_empty());
- EXPECT_TRUE(ParseFromHeaderValue("id=a1b2", &need_to_persist, &reason, &id));
+ EXPECT_TRUE(ParseFromHeaderValue("reason=notification", &need_to_persist,
+ &reason, &id, &intent_url));
+ EXPECT_FALSE(need_to_persist);
+ EXPECT_EQ(OfflinePageHeader::Reason::NOTIFICATION, reason);
+ EXPECT_EQ("", id);
+ EXPECT_TRUE(intent_url.is_empty());
+
+ EXPECT_TRUE(ParseFromHeaderValue("reason=file_url_intent", &need_to_persist,
+ &reason, &id, &intent_url));
+ EXPECT_FALSE(need_to_persist);
+ EXPECT_EQ(OfflinePageHeader::Reason::FILE_URL_INTENT, reason);
+ EXPECT_EQ("", id);
+ EXPECT_TRUE(intent_url.is_empty());
+
+ EXPECT_TRUE(ParseFromHeaderValue("reason=content_url_intent",
+ &need_to_persist, &reason, &id,
+ &intent_url));
+ EXPECT_FALSE(need_to_persist);
+ EXPECT_EQ(OfflinePageHeader::Reason::CONTENT_URL_INTENT, reason);
+ EXPECT_EQ("", id);
+ EXPECT_TRUE(intent_url.is_empty());
+
+ // Parse id field.
+ EXPECT_TRUE(ParseFromHeaderValue("id=a1b2", &need_to_persist, &reason, &id,
+ &intent_url));
EXPECT_FALSE(need_to_persist);
EXPECT_EQ(OfflinePageHeader::Reason::NONE, reason);
EXPECT_EQ("a1b2", id);
+ EXPECT_TRUE(intent_url.is_empty());
+
+ // Parse intent_url field.
+ EXPECT_FALSE(ParseFromHeaderValue("intent_url=://foo/bar", &need_to_persist,
+ &reason, &id, &intent_url));
+
+ EXPECT_TRUE(ParseFromHeaderValue("intent_url=file://foo/bar",
+ &need_to_persist, &reason, &id,
+ &intent_url));
+ EXPECT_FALSE(need_to_persist);
+ EXPECT_EQ(OfflinePageHeader::Reason::NONE, reason);
+ EXPECT_EQ("", id);
+ EXPECT_EQ(GURL("file://foo/bar"), intent_url);
- EXPECT_TRUE(ParseFromHeaderValue("persist=1 reason=download id=a1b2",
- &need_to_persist, &reason, &id));
+ // Parse multiple fields.
+ EXPECT_TRUE(ParseFromHeaderValue(
+ "persist=1 reason=download id=a1b2 intent_url=file://foo/bar",
+ &need_to_persist, &reason, &id, &intent_url));
EXPECT_TRUE(need_to_persist);
EXPECT_EQ(OfflinePageHeader::Reason::DOWNLOAD, reason);
EXPECT_EQ("a1b2", id);
+ EXPECT_EQ(GURL("file://foo/bar"), intent_url);
}
TEST_F(OfflinePageHeaderTest, ToString) {
@@ -75,8 +147,11 @@ TEST_F(OfflinePageHeaderTest, ToString) {
header.need_to_persist = true;
header.reason = OfflinePageHeader::Reason::DOWNLOAD;
header.id = "a1b2";
- EXPECT_EQ("X-Chrome-offline: persist=1 reason=download id=a1b2",
- header.GetCompleteHeaderString());
+ header.intent_url = GURL("file://foo/bar");
+ EXPECT_EQ(
+ "X-Chrome-offline: persist=1 reason=download id=a1b2 "
+ "intent_url=file://foo/bar",
+ header.GetCompleteHeaderString());
}
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/stub_offline_page_model.cc b/chromium/components/offline_pages/core/stub_offline_page_model.cc
index 66eb341c1a7..8979d82018f 100644
--- a/chromium/components/offline_pages/core/stub_offline_page_model.cc
+++ b/chromium/components/offline_pages/core/stub_offline_page_model.cc
@@ -27,6 +27,10 @@ void StubOfflinePageModel::DeletePagesByOfflineId(
void StubOfflinePageModel::DeletePagesByClientIds(
const std::vector<ClientId>& client_ids,
const DeletePageCallback& callback) {}
+void StubOfflinePageModel::DeletePagesByClientIdsAndOrigin(
+ const std::vector<ClientId>& client_ids,
+ const std::string& origin,
+ const DeletePageCallback& callback) {}
void StubOfflinePageModel::GetPagesByClientIds(
const std::vector<ClientId>& client_ids,
const MultipleOfflinePageItemCallback& callback) {}
@@ -48,6 +52,10 @@ void StubOfflinePageModel::GetPagesByURL(
void StubOfflinePageModel::GetPagesByRequestOrigin(
const std::string& origin,
const MultipleOfflinePageItemCallback& callback) {}
+void StubOfflinePageModel::GetPageBySizeAndDigest(
+ int64_t file_size,
+ const std::string& digest,
+ const SingleOfflinePageItemCallback& callback) {}
void StubOfflinePageModel::GetPagesRemovedOnCacheReset(
const MultipleOfflinePageItemCallback& callback) {}
void StubOfflinePageModel::GetPagesByNamespace(
diff --git a/chromium/components/offline_pages/core/stub_offline_page_model.h b/chromium/components/offline_pages/core/stub_offline_page_model.h
index bd08b938115..17cd83cd680 100644
--- a/chromium/components/offline_pages/core/stub_offline_page_model.h
+++ b/chromium/components/offline_pages/core/stub_offline_page_model.h
@@ -10,14 +10,14 @@
#include <vector>
#include "components/offline_pages/core/client_policy_controller.h"
-#include "components/offline_pages/core/offline_page_model_impl.h"
+#include "components/offline_pages/core/offline_page_model.h"
namespace offline_pages {
// Stub implementation of OfflinePageModel interface for testing. Besides using
// as a stub for tests, it may also be subclassed to mock specific methods
// needed for a set of tests.
-class StubOfflinePageModel : public OfflinePageModelImpl {
+class StubOfflinePageModel : public OfflinePageModel {
public:
StubOfflinePageModel();
~StubOfflinePageModel() override;
@@ -34,6 +34,10 @@ class StubOfflinePageModel : public OfflinePageModelImpl {
const DeletePageCallback& callback) override;
void DeletePagesByClientIds(const std::vector<ClientId>& client_ids,
const DeletePageCallback& callback) override;
+ void DeletePagesByClientIdsAndOrigin(
+ const std::vector<ClientId>& client_ids,
+ const std::string& origin,
+ const DeletePageCallback& callback) override;
void GetPagesByClientIds(
const std::vector<ClientId>& client_ids,
const MultipleOfflinePageItemCallback& callback) override;
@@ -54,6 +58,10 @@ class StubOfflinePageModel : public OfflinePageModelImpl {
void GetPagesByRequestOrigin(
const std::string& origin,
const MultipleOfflinePageItemCallback& callback) override;
+ void GetPageBySizeAndDigest(
+ int64_t file_size,
+ const std::string& digest,
+ const SingleOfflinePageItemCallback& callback) override;
void GetPagesRemovedOnCacheReset(
const MultipleOfflinePageItemCallback& callback) override;
void GetPagesByNamespace(
diff --git a/chromium/components/offline_pages/core/system_download_manager_stub.cc b/chromium/components/offline_pages/core/system_download_manager_stub.cc
index 96a1eed596b..95477855b43 100644
--- a/chromium/components/offline_pages/core/system_download_manager_stub.cc
+++ b/chromium/components/offline_pages/core/system_download_manager_stub.cc
@@ -8,7 +8,7 @@ namespace offline_pages {
SystemDownloadManagerStub::SystemDownloadManagerStub(int64_t id_to_use,
bool installed)
- : download_id_(id_to_use), installed_(installed) {}
+ : download_id_(id_to_use), last_removed_id_(0), installed_(installed) {}
SystemDownloadManagerStub::~SystemDownloadManagerStub() {}
@@ -35,7 +35,10 @@ int64_t SystemDownloadManagerStub::AddCompletedDownload(
int SystemDownloadManagerStub::Remove(
const std::vector<int64_t>& android_download_manager_ids) {
- return android_download_manager_ids.size();
+ int count = static_cast<int>(android_download_manager_ids.size());
+ if (count > 0)
+ last_removed_id_ = android_download_manager_ids[count - 1];
+ return count;
}
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/system_download_manager_stub.h b/chromium/components/offline_pages/core/system_download_manager_stub.h
index 6791cc1fad1..7f2b3d797c3 100644
--- a/chromium/components/offline_pages/core/system_download_manager_stub.h
+++ b/chromium/components/offline_pages/core/system_download_manager_stub.h
@@ -35,9 +35,11 @@ class SystemDownloadManagerStub : public SystemDownloadManager {
long length() { return length_; }
void set_installed(bool installed) { installed_ = installed; }
void set_download_id(int64_t download_id) { download_id_ = download_id; }
+ int64_t last_removed_id() { return last_removed_id_; }
private:
int64_t download_id_;
+ int64_t last_removed_id_;
std::string title_;
std::string description_;
std::string path_;
diff --git a/chromium/components/omnibox/browser/BUILD.gn b/chromium/components/omnibox/browser/BUILD.gn
index e642223a738..4629abbe333 100644
--- a/chromium/components/omnibox/browser/BUILD.gn
+++ b/chromium/components/omnibox/browser/BUILD.gn
@@ -31,6 +31,10 @@ aggregate_vector_icons("omnibox_vector_icons") {
"star.1x.icon",
"star.icon",
"tab.icon",
+ "touchable_bookmark.icon",
+ "touchable_clear.icon",
+ "touchable_page.icon",
+ "touchable_search.icon",
]
}
@@ -64,7 +68,6 @@ static_library("browser") {
"clipboard_url_provider.h",
"contextual_suggestions_service.cc",
"contextual_suggestions_service.h",
- "features.h",
"history_match.cc",
"history_match.h",
"history_provider.cc",
@@ -169,7 +172,6 @@ static_library("browser") {
"//components/search",
"//components/search_engines",
"//components/sessions",
- "//components/signin/core/browser",
"//components/strings",
"//components/sync",
"//components/toolbar",
@@ -329,6 +331,7 @@ source_set("unit_tests") {
"//components/search_engines",
"//components/sessions",
"//components/strings",
+ "//components/toolbar:test_support",
"//components/url_formatter",
"//components/variations",
"//net:test_support",
diff --git a/chromium/components/onc/docs/onc_spec.md b/chromium/components/onc/docs/onc_spec.md
index 46a3d77cd40..bb3877a3856 100644
--- a/chromium/components/onc/docs/onc_spec.md
+++ b/chromium/components/onc/docs/onc_spec.md
@@ -1760,6 +1760,18 @@ expansions. These allow one ONC to have basic user-specific variations.
* "X${LOGIN_ID}" -> "Xbobquail"
+
+## String Substitutions
+The value of **WiFi.EAP.Password** is subject to string substitution. These
+differ from the **String Expansions** section above in that an exact match of
+the substitution variable is required in order to substitute the real value.
+
+### Example expansions, assuming the user password was *helloworld*:
+
+* "${PASSWORD}" -> "helloworld"
+
+* "${PASSWORD}foo" -> "${PASSWORD}foo"
+
## Detection
This format should be sent in files ending in the .onc extension. When
diff --git a/chromium/components/onc/onc_constants.cc b/chromium/components/onc/onc_constants.cc
index 41d3142ac66..43be161973c 100644
--- a/chromium/components/onc/onc_constants.cc
+++ b/chromium/components/onc/onc_constants.cc
@@ -440,6 +440,7 @@ const char kWPAD[] = "WPAD";
namespace substitutes {
const char kLoginIDField[] = "${LOGIN_ID}";
+const char kPasswordField[] = "${PASSWORD}";
const char kEmailField[] = "${LOGIN_EMAIL}";
const char kCertSANEmail[] = "${CERT_SAN_EMAIL}";
const char kCertSANUPN[] = "${CERT_SAN_UPN}";
diff --git a/chromium/components/onc/onc_constants.h b/chromium/components/onc/onc_constants.h
index 9b16a5524f5..6091e2b13eb 100644
--- a/chromium/components/onc/onc_constants.h
+++ b/chromium/components/onc/onc_constants.h
@@ -438,6 +438,7 @@ ONC_EXPORT extern const char kSubject[];
namespace substitutes {
ONC_EXPORT extern const char kEmailField[];
+ONC_EXPORT extern const char kPasswordField[];
ONC_EXPORT extern const char kLoginIDField[];
ONC_EXPORT extern const char kCertSANEmail[];
ONC_EXPORT extern const char kCertSANUPN[];
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 6a68d6e8687..95a3d1ecb0a 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
@@ -9,7 +9,6 @@
#include <memory>
-#include "base/memory/ptr_util.h"
#include "base/strings/sys_string_conversions.h"
#import "components/open_from_clipboard/clipboard_recent_content_impl_ios.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -119,7 +118,7 @@ class ClipboardRecentContentIOSTest : public ::testing::Test {
uptime:time_delta.InSecondsF()];
clipboard_content_ =
- base::MakeUnique<ClipboardRecentContentIOSWithFakeUptime>(
+ std::make_unique<ClipboardRecentContentIOSWithFakeUptime>(
clipboard_content_implementation_);
}
diff --git a/chromium/components/optimization_guide/proto/hints.proto b/chromium/components/optimization_guide/proto/hints.proto
index 939918dcf7b..da2efb7f895 100644
--- a/chromium/components/optimization_guide/proto/hints.proto
+++ b/chromium/components/optimization_guide/proto/hints.proto
@@ -25,6 +25,15 @@ enum KeyRepresentation {
message Optimization {
// The type of optimization the hint applies to.
optional OptimizationType optimization_type = 1;
+ // A percent value to inflate the number of received bytes by for the purposes
+ // of data savings calculations in the client.
+ //
+ // If this value is set to 0, the client should use its configured default.
+ //
+ // Ex: If the received bytes is 100 and the inflation_percent is 30, the
+ // inflated bytes calculated by the client will be 30 in order to have a total
+ // consumed bytes value of 130.
+ optional int64 inflation_percent = 2;
}
message Hint {
diff --git a/chromium/components/os_crypt/os_crypt_linux.cc b/chromium/components/os_crypt/os_crypt_linux.cc
index b39bb091746..6510c682e6b 100644
--- a/chromium/components/os_crypt/os_crypt_linux.cc
+++ b/chromium/components/os_crypt/os_crypt_linux.cc
@@ -209,8 +209,10 @@ bool OSCrypt::DecryptString(const std::string& ciphertext,
std::unique_ptr<crypto::SymmetricKey> encryption_key(
GetEncryptionKey(version));
- if (!encryption_key)
+ if (!encryption_key) {
+ VLOG(1) << "Decryption failed: could not get the key";
return false;
+ }
std::string iv(kIVBlockSizeAES128, ' ');
crypto::Encryptor encryptor;
@@ -221,8 +223,10 @@ bool OSCrypt::DecryptString(const std::string& ciphertext,
std::string raw_ciphertext =
ciphertext.substr(strlen(kObfuscationPrefix[version]));
- if (!encryptor.Decrypt(raw_ciphertext, plaintext))
+ if (!encryptor.Decrypt(raw_ciphertext, plaintext)) {
+ VLOG(1) << "Decryption failed";
return false;
+ }
return true;
}
diff --git a/chromium/components/os_crypt/os_crypt_mac.mm b/chromium/components/os_crypt/os_crypt_mac.mm
index f999d25654e..592d1b00798 100644
--- a/chromium/components/os_crypt/os_crypt_mac.mm
+++ b/chromium/components/os_crypt/os_crypt_mac.mm
@@ -152,16 +152,20 @@ bool OSCrypt::DecryptString(const std::string& ciphertext,
ciphertext.substr(strlen(kEncryptionVersionPrefix));
crypto::SymmetricKey* encryption_key = GetEncryptionKey();
- if (!encryption_key)
+ if (!encryption_key) {
+ VLOG(1) << "Decryption failed: could not get the key";
return false;
+ }
std::string iv(kCCBlockSizeAES128, ' ');
crypto::Encryptor encryptor;
if (!encryptor.Init(encryption_key, crypto::Encryptor::CBC, iv))
return false;
- if (!encryptor.Decrypt(raw_ciphertext, plaintext))
+ if (!encryptor.Decrypt(raw_ciphertext, plaintext)) {
+ VLOG(1) << "Decryption failed";
return false;
+ }
return true;
}
diff --git a/chromium/components/os_crypt/os_crypt_mocker_linux.cc b/chromium/components/os_crypt/os_crypt_mocker_linux.cc
index 7a8fd0ec469..37d5cf7c877 100644
--- a/chromium/components/os_crypt/os_crypt_mocker_linux.cc
+++ b/chromium/components/os_crypt/os_crypt_mocker_linux.cc
@@ -8,7 +8,6 @@
#include "base/base64.h"
#include "base/lazy_instance.h"
-#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
#include "components/os_crypt/key_storage_config_linux.h"
#include "components/os_crypt/os_crypt.h"
@@ -16,7 +15,7 @@
namespace {
std::unique_ptr<KeyStorageLinux> CreateNewMock() {
- return base::MakeUnique<OSCryptMockerLinux>();
+ return std::make_unique<OSCryptMockerLinux>();
}
}
@@ -33,7 +32,7 @@ std::string* OSCryptMockerLinux::GetKeyPtr() {
void OSCryptMockerLinux::SetUp() {
UseMockKeyStorageForTesting(
&CreateNewMock, nullptr /* get the key from the provider above */);
- OSCrypt::SetConfig(base::MakeUnique<os_crypt::Config>());
+ OSCrypt::SetConfig(std::make_unique<os_crypt::Config>());
}
// static
diff --git a/chromium/components/page_info_strings.grdp b/chromium/components/page_info_strings.grdp
index c8298effb38..e7f28d631dc 100644
--- a/chromium/components/page_info_strings.grdp
+++ b/chromium/components/page_info_strings.grdp
@@ -2,7 +2,7 @@
<grit-part>
<!-- Security summary strings -->
<message name="IDS_PAGE_INFO_SECURE_SUMMARY" desc="A short summary phrase at the top of the Page Info bubble (which shows when you click the lock icon) that indicates that the connection to the current website is secure.">
- Secure connection
+ Connection is secure
</message>
<message name="IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY" desc="A one-line summary at the top of the Page Info bubble (which shows when you click the security indicator) if the connection to the current website is using mainly using a secure connection but has some insecure parts (like insecurely loaded images).">
Your connection to this site is not fully secure
@@ -239,6 +239,9 @@
<message name="IDS_PAGE_INFO_TYPE_CLIPBOARD" desc="The label used for the clipboard permission controls in the Page Info popup.">
Clipboard
</message>
+ <message name="IDS_PAGE_INFO_TYPE_SENSORS" desc="The label used for the sensor permission controls in the Page Info popup. Title case format.">
+ Motion or Light Sensors
+ </message>
<!-- TODO(crbug.com/716303): A few permissions are missing here. -->
<!-- Permission values -->
@@ -302,6 +305,9 @@
<message name="IDS_PAGE_INFO_USB_DEVICE_LABEL" desc="The label used to describe a USB device that the user has granted the site permission to access.">
<ph name="DEVICE_NAME">$1<ex>Android Phone</ex></ph>
</message>
+ <message name="IDS_PAGE_INFO_USB_DEVICE_SECONDARY_LABEL" desc="The label displayed underneath IDS_PAGE_INFO_USB_DEVICE_LABEL to inform the user that the device name listed is a USB device.">
+ USB device
+ </message>
<message name="IDS_PAGE_INFO_DELETE_USB_DEVICE" desc="The tooltip displayed when hovering over the button that will remove permission to access a USB device that the user previously granted to the site.">
Revoke access
</message>
@@ -370,10 +376,10 @@
</if>
<if expr="use_titlecase">
- <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON" desc="The string used in the page info change password button. Title case format.">
+ <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON" desc="In Title Case: The string used in the page info change password button.">
Help Me Fix This
</message>
- <message name="IDS_PAGE_INFO_IGNORE_PASSWORD_WARNING_BUTTON" desc="The string used in the page info ignore password warning button. Title case format.">
+ <message name="IDS_PAGE_INFO_IGNORE_PASSWORD_WARNING_BUTTON" desc="In Title Case: The string used in the page info ignore password warning button.">
Ignore
</message>
</if>
diff --git a/chromium/components/pairing/BUILD.gn b/chromium/components/pairing/BUILD.gn
index 589d3b8a91d..603fed48fd3 100644
--- a/chromium/components/pairing/BUILD.gn
+++ b/chromium/components/pairing/BUILD.gn
@@ -34,8 +34,8 @@ source_set("pairing") {
"//chromeos",
"//device/bluetooth",
"//net",
- "//services/device/public/interfaces",
- "//services/device/public/interfaces:constants",
+ "//services/device/public/mojom",
+ "//services/device/public/mojom:constants",
"//services/service_manager/public/cpp",
]
}
diff --git a/chromium/components/pairing/DEPS b/chromium/components/pairing/DEPS
index 6bc13ae3f24..efc4e68f982 100644
--- a/chromium/components/pairing/DEPS
+++ b/chromium/components/pairing/DEPS
@@ -3,6 +3,6 @@ include_rules = [
"+device/bluetooth",
"+mojo/public/cpp",
"+net", # For IOBuffer
- "+services/device/public/interfaces",
+ "+services/device/public/mojom",
"+services/service_manager/public/cpp",
]
diff --git a/chromium/components/pairing/bluetooth_host_pairing_controller.cc b/chromium/components/pairing/bluetooth_host_pairing_controller.cc
index f3a35a91ec2..1744bd9bf9f 100644
--- a/chromium/components/pairing/bluetooth_host_pairing_controller.cc
+++ b/chromium/components/pairing/bluetooth_host_pairing_controller.cc
@@ -19,7 +19,7 @@
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/base/io_buffer.h"
-#include "services/device/public/interfaces/constants.mojom.h"
+#include "services/device/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace pairing_chromeos {
@@ -362,8 +362,7 @@ void BluetoothHostPairingController::OnForget() {
if (adapter_.get()) {
if (adapter_->IsDiscoverable()) {
- adapter_->SetDiscoverable(false, base::Bind(&base::DoNothing),
- base::Bind(&base::DoNothing));
+ adapter_->SetDiscoverable(false, base::DoNothing(), base::DoNothing());
}
input_device_manager_->GetDevices(base::BindOnce(
diff --git a/chromium/components/pairing/bluetooth_host_pairing_controller.h b/chromium/components/pairing/bluetooth_host_pairing_controller.h
index b129e091355..a3180a036e3 100644
--- a/chromium/components/pairing/bluetooth_host_pairing_controller.h
+++ b/chromium/components/pairing/bluetooth_host_pairing_controller.h
@@ -19,7 +19,7 @@
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_socket.h"
-#include "services/device/public/interfaces/input_service.mojom.h"
+#include "services/device/public/mojom/input_service.mojom.h"
namespace service_manager {
class Connector;
diff --git a/chromium/components/password_manager/OWNERS b/chromium/components/password_manager/OWNERS
index fe38e2ac8e0..b43b8caaeb7 100644
--- a/chromium/components/password_manager/OWNERS
+++ b/chromium/components/password_manager/OWNERS
@@ -1,8 +1,5 @@
dvadym@chromium.org
-engedy@chromium.org
kolos@chromium.org
-melandory@chromium.org
-mkwst@chromium.org
vabr@chromium.org
vasilii@chromium.org
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 9a9095896c1..79425948d17 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
@@ -248,13 +248,13 @@ void ContentPasswordManagerDriver::DidNavigateFrame(
}
}
-void ContentPasswordManagerDriver::InPageNavigation(
+void ContentPasswordManagerDriver::SameDocumentNavigation(
const autofill::PasswordForm& password_form) {
if (!CheckChildProcessSecurityPolicy(
password_form.origin,
BadMessageReason::CPMD_BAD_ORIGIN_IN_PAGE_NAVIGATION))
return;
- GetPasswordManager()->OnInPageNavigation(this, password_form);
+ GetPasswordManager()->OnSameDocumentNavigation(this, password_form);
}
void ContentPasswordManagerDriver::PresaveGeneratedPassword(
diff --git a/chromium/components/password_manager/content/browser/content_password_manager_driver.h b/chromium/components/password_manager/content/browser/content_password_manager_driver.h
index 3625171af8d..94e775911ce 100644
--- a/chromium/components/password_manager/content/browser/content_password_manager_driver.h
+++ b/chromium/components/password_manager/content/browser/content_password_manager_driver.h
@@ -95,7 +95,8 @@ class ContentPasswordManagerDriver
bool did_stop_loading) override;
void PasswordFormSubmitted(
const autofill::PasswordForm& password_form) override;
- void InPageNavigation(const autofill::PasswordForm& password_form) override;
+ void SameDocumentNavigation(
+ const autofill::PasswordForm& password_form) override;
void PresaveGeneratedPassword(
const autofill::PasswordForm& password_form) override;
void PasswordNoLongerGenerated(
diff --git a/chromium/components/password_manager/content/common/OWNERS b/chromium/components/password_manager/content/common/OWNERS
index 4df0c71cc7d..7aebc8abbf8 100644
--- a/chromium/components/password_manager/content/common/OWNERS
+++ b/chromium/components/password_manager/content/common/OWNERS
@@ -1,4 +1,4 @@
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
per-file *.typemap=set noparent
per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/password_manager/content/common/credential_manager.typemap b/chromium/components/password_manager/content/common/credential_manager.typemap
index e77f29f14d7..6fbe37d367d 100644
--- a/chromium/components/password_manager/content/common/credential_manager.typemap
+++ b/chromium/components/password_manager/content/common/credential_manager.typemap
@@ -5,9 +5,9 @@
mojom = "//third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom"
public_headers =
[ "//components/password_manager/core/common/credential_manager_types.h" ]
-traits_headers = [ "//components/password_manager/content/common/credential_manager_struct_traits.h" ]
+traits_headers = [ "//components/password_manager/content/common/credential_manager_mojom_traits.h" ]
sources = [
- "//components/password_manager/content/common/credential_manager_struct_traits.cc",
+ "//components/password_manager/content/common/credential_manager_mojom_traits.cc",
]
deps = [
"//base",
diff --git a/chromium/components/password_manager/content/common/credential_manager_struct_traits.cc b/chromium/components/password_manager/content/common/credential_manager_mojom_traits.cc
index dceec2a399f..e0e3a3f0355 100644
--- a/chromium/components/password_manager/content/common/credential_manager_struct_traits.cc
+++ b/chromium/components/password_manager/content/common/credential_manager_mojom_traits.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/password_manager/content/common/credential_manager_struct_traits.h"
+#include "components/password_manager/content/common/credential_manager_mojom_traits.h"
-#include "url/mojo/origin_struct_traits.h"
-#include "url/mojo/url_gurl_struct_traits.h"
+#include "url/mojom/origin_mojom_traits.h"
+#include "url/mojom/url_gurl_mojom_traits.h"
namespace mojo {
@@ -87,7 +87,6 @@ bool EnumTraits<password_manager::mojom::CredentialManagerError,
password_manager::CredentialManagerError::PASSWORDSTOREUNAVAILABLE;
return true;
case password_manager::mojom::CredentialManagerError::NOT_ALLOWED:
- case password_manager::mojom::CredentialManagerError::TIMED_OUT:
case password_manager::mojom::CredentialManagerError::NOT_SUPPORTED:
case password_manager::mojom::CredentialManagerError::INVALID_DOMAIN:
case password_manager::mojom::CredentialManagerError::NOT_IMPLEMENTED:
diff --git a/chromium/components/password_manager/content/common/credential_manager_struct_traits.h b/chromium/components/password_manager/content/common/credential_manager_mojom_traits.h
index 9f4fec56226..23b982e388c 100644
--- a/chromium/components/password_manager/content/common/credential_manager_struct_traits.h
+++ b/chromium/components/password_manager/content/common/credential_manager_mojom_traits.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_PASSWORD_MANAGER_CONTENT_COMMON_CREDENTIAL_MANAGER_STRUCT_TRAITS_H_
-#define COMPONENTS_PASSWORD_MANAGER_CONTENT_COMMON_CREDENTIAL_MANAGER_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_PASSWORD_MANAGER_CONTENT_COMMON_CREDENTIAL_MANAGER_MOJOM_TRAITS_H_
+#define COMPONENTS_PASSWORD_MANAGER_CONTENT_COMMON_CREDENTIAL_MANAGER_MOJOM_TRAITS_H_
#include "base/strings/string16.h"
#include "components/password_manager/core/common/credential_manager_types.h"
@@ -76,4 +76,4 @@ struct StructTraits<password_manager::mojom::CredentialInfoDataView,
} // namespace mojo
-#endif // COMPONENTS_PASSWORD_MANAGER_CONTENT_COMMON_CREDENTIAL_MANAGER_STRUCT_TRAITS_H_
+#endif // COMPONENTS_PASSWORD_MANAGER_CONTENT_COMMON_CREDENTIAL_MANAGER_MOJOM_TRAITS_H_
diff --git a/chromium/components/password_manager/core/browser/BUILD.gn b/chromium/components/password_manager/core/browser/BUILD.gn
index d4f2b3c4bf6..2f260de5df0 100644
--- a/chromium/components/password_manager/core/browser/BUILD.gn
+++ b/chromium/components/password_manager/core/browser/BUILD.gn
@@ -142,6 +142,7 @@ static_library("browser") {
"suppressed_form_fetcher.h",
"ui/credential_provider_interface.h",
"ui/export_flow.h",
+ "ui/export_progress_status.h",
"ui/import_flow.h",
"webdata/logins_table.cc",
"webdata/logins_table.h",
@@ -174,7 +175,6 @@ static_library("browser") {
deps = [
":hash_password_manager",
":proto",
- "//base",
"//base:i18n",
"//components/autofill/core/browser",
"//components/autofill/core/browser/proto",
@@ -425,6 +425,7 @@ fuzzer_test("csv_reader_fuzzer") {
]
deps = [
":browser",
+ "//base:i18n",
"//components/autofill/core/common:common",
]
seed_corpus = "import/password_csv_reader_corpus"
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/OWNERS b/chromium/components/password_manager/core/browser/android_affiliation/OWNERS
new file mode 100644
index 00000000000..992fe263f95
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/android_affiliation/OWNERS
@@ -0,0 +1,3 @@
+engedy@chromium.org
+
+# COMPONENT: UI>Browser>Passwords
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.cc b/chromium/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.cc
index 42a236bc61e..77377488e34 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliated_match_helper.cc
@@ -94,10 +94,10 @@ void AffiliatedMatchHelper::InjectAffiliationAndBrandingInformation(
if (IsValidAndroidCredential(PasswordStore::FormDigest(*form)))
android_credentials.push_back(form.get());
}
- base::Closure on_get_all_realms(
- base::Bind(result_callback, base::Passed(&forms)));
- base::Closure barrier_closure =
- base::BarrierClosure(android_credentials.size(), on_get_all_realms);
+ base::OnceClosure on_get_all_realms(
+ base::BindOnce(result_callback, std::move(forms)));
+ base::RepeatingClosure barrier_closure = base::BarrierClosure(
+ android_credentials.size(), std::move(on_get_all_realms));
for (auto* form : android_credentials) {
affiliation_service_->GetAffiliationsAndBranding(
FacetURI::FromPotentiallyInvalidSpec(form->signon_realm),
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc
index 0aca7ae4164..9e74c347449 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc
@@ -27,12 +27,12 @@ namespace password_manager {
AffiliationBackend::AffiliationBackend(
const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
const scoped_refptr<base::SequencedTaskRunner>& task_runner,
- std::unique_ptr<base::Clock> time_source,
- std::unique_ptr<base::TickClock> time_tick_source)
+ base::Clock* time_source,
+ base::TickClock* time_tick_source)
: request_context_getter_(request_context_getter),
task_runner_(task_runner),
- clock_(std::move(time_source)),
- tick_clock_(std::move(time_tick_source)),
+ clock_(time_source),
+ tick_clock_(time_tick_source),
construction_time_(clock_->Now()),
weak_ptr_factory_(this) {
DCHECK_LT(base::Time(), clock_->Now());
@@ -46,7 +46,7 @@ void AffiliationBackend::Initialize(const base::FilePath& db_path) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!throttler_);
throttler_.reset(
- new AffiliationFetchThrottler(this, task_runner_, tick_clock_.get()));
+ new AffiliationFetchThrottler(this, task_runner_, tick_clock_));
// TODO(engedy): Currently, when Init() returns false, it always poisons the
// DB, so subsequent operations will silently fail. Consider either fully
@@ -114,8 +114,7 @@ FacetManager* AffiliationBackend::GetOrCreateFacetManager(
const FacetURI& facet_uri) {
std::unique_ptr<FacetManager>& facet_manager = facet_managers_[facet_uri];
if (!facet_manager) {
- facet_manager =
- std::make_unique<FacetManager>(facet_uri, this, clock_.get());
+ facet_manager = std::make_unique<FacetManager>(facet_uri, this, clock_);
}
return facet_manager.get();
}
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend.h b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend.h
index dadeb111e3d..bce8b24db6e 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend.h
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend.h
@@ -64,8 +64,8 @@ class AffiliationBackend : public FacetManagerHost,
AffiliationBackend(
const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
const scoped_refptr<base::SequencedTaskRunner>& task_runner,
- std::unique_ptr<base::Clock> time_source,
- std::unique_ptr<base::TickClock> time_tick_source);
+ base::Clock* time_source,
+ base::TickClock* time_tick_source);
~AffiliationBackend() override;
// Performs the I/O-heavy part of initialization. The database used to cache
@@ -142,8 +142,8 @@ class AffiliationBackend : public FacetManagerHost,
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
- std::unique_ptr<base::Clock> clock_;
- std::unique_ptr<base::TickClock> tick_clock_;
+ base::Clock* clock_;
+ base::TickClock* tick_clock_;
std::unique_ptr<AffiliationDatabase> cache_;
std::unique_ptr<AffiliationFetcher> fetcher_;
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend_unittest.cc b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend_unittest.cc
index 43f97c6c75b..12ef7c4b952 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend_unittest.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend_unittest.cc
@@ -154,6 +154,8 @@ class AffiliationBackendTest : public testing::Test {
AffiliationBackendTest()
: backend_task_runner_(new base::TestMockTimeTaskRunner),
consumer_task_runner_(new base::TestSimpleTaskRunner),
+ clock_(backend_task_runner_->GetMockClock()),
+ tick_clock_(backend_task_runner_->GetMockTickClock()),
mock_fetch_throttler_(nullptr) {}
~AffiliationBackendTest() override {}
@@ -295,13 +297,11 @@ class AffiliationBackendTest : public testing::Test {
}
bool IsCachedDataFreshForFacetURI(const FacetURI& facet_uri) {
- std::unique_ptr<base::Clock> clock(backend_task_runner_->GetMockClock());
- return FacetManager(facet_uri, backend(), clock.get()).IsCachedDataFresh();
+ return FacetManager(facet_uri, backend(), clock_.get()).IsCachedDataFresh();
}
bool IsCachedDataNearStaleForFacetURI(const FacetURI& facet_uri) {
- std::unique_ptr<base::Clock> clock(backend_task_runner_->GetMockClock());
- return FacetManager(facet_uri, backend(), clock.get())
+ return FacetManager(facet_uri, backend(), clock_.get())
.IsCachedDataNearStale();
}
@@ -331,9 +331,8 @@ class AffiliationBackendTest : public testing::Test {
// testing::Test:
void SetUp() override {
ASSERT_TRUE(CreateTemporaryFile(&db_path_));
- backend_.reset(new AffiliationBackend(
- nullptr, backend_task_runner_, backend_task_runner_->GetMockClock(),
- backend_task_runner_->GetMockTickClock()));
+ backend_.reset(new AffiliationBackend(nullptr, backend_task_runner_,
+ clock_.get(), tick_clock_.get()));
backend_->Initialize(db_path());
auto mock_fetch_throttler =
std::make_unique<MockAffiliationFetchThrottler>(backend_.get());
@@ -351,6 +350,11 @@ class AffiliationBackendTest : public testing::Test {
scoped_refptr<base::TestMockTimeTaskRunner> backend_task_runner_;
scoped_refptr<base::TestSimpleTaskRunner> consumer_task_runner_;
+ // TODO(tzik): Remove |clock_| and |tick_clock_| after updating
+ // TestMockTimeTaskRunner to own the clock instances.
+ std::unique_ptr<base::Clock> clock_;
+ std::unique_ptr<base::TickClock> tick_clock_;
+
base::FilePath db_path_;
ScopedFakeAffiliationAPI fake_affiliation_api_;
MockAffiliationConsumer mock_consumer_;
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc
index ea6612df680..9354d0b1a1a 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc
@@ -126,6 +126,8 @@ class AffiliationFetchThrottlerTest : public testing::Test {
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
+ // TODO(tzik): Remove |mock_tick_clock_| after updating TestMockTimeTaskRunner
+ // to own the clock instances.
std::unique_ptr<base::TickClock> mock_tick_clock_;
MockAffiliationFetchThrottlerDelegate mock_delegate_;
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_service.cc b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_service.cc
index 7783fff7327..e20d57c0b32 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_service.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_service.cc
@@ -38,12 +38,10 @@ void AffiliationService::Initialize(
const base::FilePath& db_path) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!backend_);
- backend_ =
- new AffiliationBackend(request_context_getter, backend_task_runner_,
- std::make_unique<base::DefaultClock>(),
- std::make_unique<base::DefaultTickClock>());
+ backend_ = new AffiliationBackend(
+ request_context_getter, backend_task_runner_,
+ base::DefaultClock::GetInstance(), base::DefaultTickClock::GetInstance());
- std::unique_ptr<base::TickClock> tick_clock(new base::DefaultTickClock);
backend_task_runner_->PostTask(
FROM_HERE, base::Bind(&AffiliationBackend::Initialize,
base::Unretained(backend_), db_path));
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/facet_manager_unittest.cc b/chromium/components/password_manager/core/browser/android_affiliation/facet_manager_unittest.cc
index 547fd74bdcb..29e6fa29dd8 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/facet_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/facet_manager_unittest.cc
@@ -413,6 +413,8 @@ class FacetManagerTest : public testing::Test {
MockAffiliationConsumer mock_consumer_;
scoped_refptr<base::TestSimpleTaskRunner> consumer_task_runner_;
scoped_refptr<base::TestMockTimeTaskRunner> main_task_runner_;
+ // TODO(tzik): Remove |main_clock_| after updating TestMockTimeTaskRunner to
+ // own the clock instances.
std::unique_ptr<base::Clock> main_clock_;
TestFacetManagerNotifier facet_manager_notifier_;
MockFacetManagerHost facet_manager_host_;
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 46fca823813..1c205987a89 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
@@ -1504,6 +1504,24 @@ TEST_F(CredentialManagerImplTest, GetSynthesizedFormForOrigin) {
EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, synthesized.scheme);
}
+TEST_F(CredentialManagerImplTest, GetBlacklistedPasswordCredential) {
+ autofill::PasswordForm blacklisted;
+ blacklisted.blacklisted_by_user = true;
+ blacklisted.origin = form_.origin;
+ blacklisted.signon_realm = blacklisted.origin.spec();
+ // Deliberately use a wrong format with a non-empty username to simulate a
+ // leak. See https://crbug.com/817754.
+ blacklisted.username_value = base::ASCIIToUTF16("Username");
+ store_->AddLogin(blacklisted);
+
+ EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _)).Times(0);
+ EXPECT_CALL(*client_, NotifyUserAutoSigninPtr()).Times(0);
+
+ std::vector<GURL> federations;
+ ExpectCredentialType(CredentialMediationRequirement::kOptional, true,
+ federations, CredentialType::CREDENTIAL_TYPE_EMPTY);
+}
+
TEST_F(CredentialManagerImplTest, BlacklistPasswordCredential) {
EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(_));
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 b3e71fabb46..72030d400cb 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
@@ -157,6 +157,11 @@ void CredentialManagerPendingRequestTask::ProcessForms(
delegate_->SendCredential(send_callback_, CredentialInfo());
return;
}
+ // Get rid of the blacklisted credentials.
+ base::EraseIf(results,
+ [](const std::unique_ptr<autofill::PasswordForm>& form) {
+ return form->blacklisted_by_user;
+ });
std::vector<std::unique_ptr<autofill::PasswordForm>> local_results;
std::vector<std::unique_ptr<autofill::PasswordForm>> psl_results;
diff --git a/chromium/components/password_manager/core/browser/credentials_filter.h b/chromium/components/password_manager/core/browser/credentials_filter.h
index 03bce524158..aec30291a22 100644
--- a/chromium/components/password_manager/core/browser/credentials_filter.h
+++ b/chromium/components/password_manager/core/browser/credentials_filter.h
@@ -25,8 +25,7 @@ class CredentialsFilter {
std::vector<std::unique_ptr<autofill::PasswordForm>> results) const = 0;
// Should |form| be offered to be saved?
- virtual bool ShouldSave(const autofill::PasswordForm& form,
- const GURL& main_frame_url) const = 0;
+ virtual bool ShouldSave(const autofill::PasswordForm& form) const = 0;
// Call this if the form associated with |form_manager| was filled, and the
// subsequent sign-in looked like a success.
diff --git a/chromium/components/password_manager/core/browser/export/password_manager_exporter.cc b/chromium/components/password_manager/core/browser/export/password_manager_exporter.cc
index d606ad497aa..2a330d3edc8 100644
--- a/chromium/components/password_manager/core/browser/export/password_manager_exporter.cc
+++ b/chromium/components/password_manager/core/browser/export/password_manager_exporter.cc
@@ -10,91 +10,192 @@
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "base/task_runner_util.h"
+#include "base/task_scheduler/lazy_task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/export/password_csv_writer.h"
+#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/ui/credential_provider_interface.h"
namespace {
-std::vector<std::unique_ptr<autofill::PasswordForm>> CopyOf(
- const std::vector<std::unique_ptr<autofill::PasswordForm>>& password_list) {
- std::vector<std::unique_ptr<autofill::PasswordForm>> ret_val;
- for (const auto& form : password_list) {
- ret_val.push_back(std::make_unique<autofill::PasswordForm>(*form));
- }
- return ret_val;
+// Multiple exports should be queued in sequence. This helps avoid race
+// conditions where there are multiple simultaneous exports to the same
+// destination and one of them was cancelled and will delete the file. We use
+// TaskPriority::USER_VISIBLE, because a busy UI is displayed while the
+// passwords are being exported.
+base::LazySingleThreadTaskRunner g_task_runner =
+ LAZY_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(
+ base::TaskTraits(base::MayBlock(), base::TaskPriority::USER_VISIBLE),
+ base::SingleThreadTaskRunnerThreadMode::SHARED);
+
+// A wrapper for |write_function|, which can be bound and keep a copy of its
+// data on the closure.
+bool Write(
+ password_manager::PasswordManagerExporter::WriteCallback write_function,
+ const base::FilePath& destination,
+ const std::string& serialised) {
+ int written =
+ write_function.Run(destination, serialised.c_str(), serialised.size());
+ return written == static_cast<int>(serialised.size());
}
} // namespace
namespace password_manager {
+using metrics_util::ExportPasswordsResult;
+
PasswordManagerExporter::PasswordManagerExporter(
password_manager::CredentialProviderInterface*
- credential_provider_interface)
+ credential_provider_interface,
+ ProgressCallback on_progress)
: credential_provider_interface_(credential_provider_interface),
- write_function_(&base::WriteFile),
- task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::TaskPriority::USER_VISIBLE, base::MayBlock()})),
+ on_progress_(std::move(on_progress)),
+ last_progress_status_(ExportProgressStatus::NOT_STARTED),
+ write_function_(base::BindRepeating(&base::WriteFile)),
+ delete_function_(base::BindRepeating(&base::DeleteFile)),
+ task_runner_(g_task_runner.Get()),
weak_factory_(this) {}
PasswordManagerExporter::~PasswordManagerExporter() {}
void PasswordManagerExporter::PreparePasswordsForExport() {
- password_list_ = credential_provider_interface_->GetAllPasswords();
+ DCHECK_EQ(GetProgressStatus(), ExportProgressStatus::NOT_STARTED);
+ export_preparation_started_ = base::Time::Now();
- if (IsReadyForExport())
- Export();
+ std::vector<std::unique_ptr<autofill::PasswordForm>> password_list =
+ credential_provider_interface_->GetAllPasswords();
+ size_t password_list_size = password_list.size();
+
+ base::PostTaskAndReplyWithResult(
+ task_runner_.get(), FROM_HERE,
+ base::BindOnce(&password_manager::PasswordCSVWriter::SerializePasswords,
+ std::move(password_list)),
+ base::BindOnce(&PasswordManagerExporter::SetSerialisedPasswordList,
+ weak_factory_.GetWeakPtr(), password_list_size));
}
void PasswordManagerExporter::SetDestination(
const base::FilePath& destination) {
+ DCHECK_EQ(GetProgressStatus(), ExportProgressStatus::NOT_STARTED);
+
destination_ = destination;
if (IsReadyForExport())
Export();
+
+ OnProgress(ExportProgressStatus::IN_PROGRESS, std::string());
+}
+
+void PasswordManagerExporter::SetSerialisedPasswordList(
+ size_t count,
+ const std::string& serialised) {
+ serialised_password_list_ = serialised;
+ password_count_ = count;
+
+ UMA_HISTOGRAM_MEDIUM_TIMES("PasswordManager.TimeReadingExportedPasswords",
+ base::Time::Now() - export_preparation_started_);
+
+ if (IsReadyForExport())
+ Export();
}
void PasswordManagerExporter::Cancel() {
// Tasks which had their pointers invalidated won't run.
weak_factory_.InvalidateWeakPtrs();
- destination_.clear();
- password_list_.clear();
+ // If we are currently still serialising, Export() will see the cancellation
+ // status and won't schedule writing.
+ OnProgress(ExportProgressStatus::FAILED_CANCELLED, std::string());
+
+ // If we are currently writing to the disk, we will have to cleanup the file
+ // once writing stops.
+ Cleanup();
+
+ // TODO(crbug.com/789561) If the passwords have already been written to the
+ // disk, then we've already recorded ExportPasswordsResult::SUCCESS. Ideally,
+ // we should make different results mutually exclusive.
+ UMA_HISTOGRAM_ENUMERATION("PasswordManager.ExportPasswordsToCSVResult",
+ ExportPasswordsResult::USER_ABORTED,
+ ExportPasswordsResult::COUNT);
+}
+
+password_manager::ExportProgressStatus
+PasswordManagerExporter::GetProgressStatus() {
+ return last_progress_status_;
+}
+
+void PasswordManagerExporter::SetWriteForTesting(WriteCallback write_function) {
+ write_function_ = std::move(write_function);
}
-void PasswordManagerExporter::SetWriteForTesting(
- int (*write_function)(const base::FilePath& filename,
- const char* data,
- int size)) {
- write_function_ = write_function;
+void PasswordManagerExporter::SetDeleteForTesting(
+ DeleteCallback delete_callback) {
+ delete_function_ = std::move(delete_callback);
}
bool PasswordManagerExporter::IsReadyForExport() {
- return !destination_.empty() && !password_list_.empty();
+ return !destination_.empty() && !serialised_password_list_.empty();
}
void PasswordManagerExporter::Export() {
- UMA_HISTOGRAM_COUNTS("PasswordManager.ExportedPasswordsPerUserInCSV",
- password_list_.size());
+ // If cancelling was requested while we were serialising the passwords, don't
+ // write anything to the disk.
+ if (GetProgressStatus() == ExportProgressStatus::FAILED_CANCELLED) {
+ serialised_password_list_.clear();
+ return;
+ }
base::PostTaskAndReplyWithResult(
task_runner_.get(), FROM_HERE,
- base::BindOnce(&password_manager::PasswordCSVWriter::SerializePasswords,
- base::Passed(CopyOf(password_list_))),
- base::BindOnce(&PasswordManagerExporter::OnPasswordsSerialised,
- weak_factory_.GetWeakPtr(),
- base::Passed(std::move(destination_))));
+ base::BindOnce(::Write, write_function_, destination_,
+ std::move(serialised_password_list_)),
+ base::BindOnce(&PasswordManagerExporter::OnPasswordsExported,
+ weak_factory_.GetWeakPtr()));
+}
+
+void PasswordManagerExporter::OnPasswordsExported(
+ bool success) {
+ if (success) {
+ OnProgress(ExportProgressStatus::SUCCEEDED, std::string());
+
+ UMA_HISTOGRAM_ENUMERATION("PasswordManager.ExportPasswordsToCSVResult",
+ ExportPasswordsResult::SUCCESS,
+ ExportPasswordsResult::COUNT);
+ UMA_HISTOGRAM_COUNTS("PasswordManager.ExportedPasswordsPerUserInCSV",
+ password_count_);
+ } else {
+ OnProgress(ExportProgressStatus::FAILED_WRITE_FAILED,
+ destination_.DirName().BaseName().AsUTF8Unsafe());
+ // Don't leave partial password files, if we tell the user we couldn't write
+ Cleanup();
+
+ UMA_HISTOGRAM_ENUMERATION("PasswordManager.ExportPasswordsToCSVResult",
+ ExportPasswordsResult::WRITE_FAILED,
+ ExportPasswordsResult::COUNT);
+ }
+}
- password_list_.clear();
- destination_.clear();
+void PasswordManagerExporter::OnProgress(
+ password_manager::ExportProgressStatus status,
+ const std::string& folder) {
+ last_progress_status_ = status;
+ on_progress_.Run(status, folder);
}
-void PasswordManagerExporter::OnPasswordsSerialised(
- base::FilePath destination,
- const std::string& serialised) {
- write_function_(destination, serialised.c_str(), serialised.size());
+void PasswordManagerExporter::Cleanup() {
+ // The PasswordManagerExporter instance may be destroyed before the cleanup is
+ // executed, e.g. because a new export was initiated. The cleanup should be
+ // carried out regardless, so we only schedule tasks which own their
+ // arguments.
+ // TODO(crbug.com/811779) When Chrome is overwriting an existing file, cancel
+ // should restore the file rather than delete it.
+ if (!destination_.empty()) {
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(base::IgnoreResult(delete_function_),
+ destination_, false));
+ }
}
} // namespace password_manager
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 154832097c4..e4b685a4232 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
@@ -13,71 +13,112 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
-
-namespace autofill {
-struct PasswordForm;
-}
+#include "base/time/time.h"
+#include "components/password_manager/core/browser/ui/export_progress_status.h"
namespace password_manager {
class CredentialProviderInterface;
-// Controls the exporting of passwords. PasswordManagerExporter will perform
-// the export asynchrnously as soon as all the required info is available
-// (password list and destination), unless canceled.
+// Controls the exporting of passwords. One instance per export flow.
+// PasswordManagerExporter will perform the export asynchronously as soon as all
+// the required info is available (password list and destination), unless
+// canceled.
class PasswordManagerExporter {
public:
+ using ProgressCallback =
+ base::RepeatingCallback<void(password_manager::ExportProgressStatus,
+ const std::string&)>;
+ using WriteCallback =
+ base::RepeatingCallback<int(const base::FilePath&, const char*, int)>;
+ using DeleteCallback =
+ base::RepeatingCallback<bool(const base::FilePath&, bool)>;
+
explicit PasswordManagerExporter(
password_manager::CredentialProviderInterface*
- credential_provider_interface);
+ credential_provider_interface,
+ ProgressCallback on_progress);
virtual ~PasswordManagerExporter();
// Pre-load the passwords from the password store.
- // TODO(crbug.com/785237) Notify the UI about the result.
virtual void PreparePasswordsForExport();
// Set the destination, where the passwords will be written when they are
- // ready.
+ // ready. This is expected to be called after PreparePasswordsForExport().
virtual void SetDestination(const base::FilePath& destination);
- // Best-effort canceling of any on-going task related to exporting.
+ // Cancel any pending exporting tasks and clear the file, if it was written
+ // to the disk.
virtual void Cancel();
+ // Returns the most recent ExportProgressStatus value, as would have been
+ // seen on the callback provided to the constructor.
+ virtual ExportProgressStatus GetProgressStatus();
+
// Replace the function which writes to the filesystem with a custom action.
// The return value is -1 on error, otherwise the number of bytes written.
- void SetWriteForTesting(int (*write_function)(const base::FilePath& filename,
- const char* data,
- int size));
+ void SetWriteForTesting(WriteCallback write_callback);
+
+ // Replace the function which writes to the filesystem with a custom action.
+ // The return value is true when deleting successfully.
+ void SetDeleteForTesting(DeleteCallback delete_callback);
private:
+ // Caches the serialised password list. It proceeds to export, if all the
+ // parts are ready. |count| is the number of passwords which were serialised.
+ // |serialised| is the serialised list of passwords.
+ void SetSerialisedPasswordList(size_t count, const std::string& serialised);
+
// Returns true if all the necessary data is available.
bool IsReadyForExport();
// Performs the export. It should not be called before the data is available.
// At the end, it clears cached fields.
- // TODO(crbug.com/785237) Notify the UI about the result.
void Export();
- // Callback after the passwords have been serialised.
- void OnPasswordsSerialised(base::FilePath destination,
- const std::string& serialised);
+ // Callback after the passwords have been serialised. It reports the result to
+ // the UI and to metrics. |destination| is the folder we wrote to. |count| is
+ // the number of passwords exported. |success| is whether they were actually
+ // written.
+ void OnPasswordsExported(bool success);
+
+ // Wrapper for the |on_progress_| callback, which caches |status|, so that
+ // it can be provided by GetProgressStatus.
+ void OnProgress(ExportProgressStatus status, const std::string& folder);
+
+ // Export failed or was cancelled. Restore the state of the file system by
+ // removing any partial or unwanted files from the filesystem.
+ void Cleanup();
// The source of the password list which will be exported.
- password_manager::CredentialProviderInterface* credential_provider_interface_;
+ CredentialProviderInterface* const credential_provider_interface_;
+
+ // Callback to the UI.
+ ProgressCallback on_progress_;
- // The password list that was read from the store. It will be cleared once
- // exporting is complete.
- std::vector<std::unique_ptr<autofill::PasswordForm>> password_list_;
+ // The most recent progress status update, as was seen on |on_progress_|.
+ ExportProgressStatus last_progress_status_;
+
+ // The password list that was read from the store and serialised.
+ std::string serialised_password_list_;
+ // The number of passwords that were serialised. Useful for metrics.
+ size_t password_count_;
// The destination which was provided and where the password list will be
// sent. It will be cleared once exporting is complete.
base::FilePath destination_;
- // The function which does the actual writing. It should point to
+ // The moment in time that we started reading and serialising the password
+ // list. Useful for metrics.
+ base::Time export_preparation_started_;
+
+ // The function which does the actual writing. It should wrap
// base::WriteFile, unless it's changed for testing purposes.
- int (*write_function_)(const base::FilePath& filename,
- const char* data,
- int size);
+ WriteCallback write_function_;
+
+ // The function which does the actual deleting of a file. It should wrap
+ // base::DeleteFile, unless it's changed for testing purposes.
+ DeleteCallback delete_function_;
// |task_runner_| is used for time-consuming tasks during exporting. The tasks
// will dereference a WeakPtr to |*this|, which means they all need to run on
diff --git a/chromium/components/password_manager/core/browser/export/password_manager_exporter_unittest.cc b/chromium/components/password_manager/core/browser/export/password_manager_exporter_unittest.cc
index 17312a3f159..9800fbd3164 100644
--- a/chromium/components/password_manager/core/browser/export/password_manager_exporter_unittest.cc
+++ b/chromium/components/password_manager/core/browser/export/password_manager_exporter_unittest.cc
@@ -10,25 +10,36 @@
#include <vector>
#include "base/strings/utf_string_conversions.h"
+#include "base/test/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/export/password_csv_writer.h"
+#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/ui/credential_provider_interface.h"
+#include "components/password_manager/core/browser/ui/export_progress_status.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
using ::testing::_;
+using ::testing::IsEmpty;
+using ::testing::Not;
+using ::testing::Return;
using ::testing::ReturnArg;
+using ::testing::SaveArg;
using ::testing::StrEq;
using ::testing::StrictMock;
+using password_manager::metrics_util::ExportPasswordsResult;
+
// A callback that matches the signature of base::WriteFile
using WriteCallback =
base::RepeatingCallback<int(const base::FilePath&, const char*, int)>;
+using DeleteCallback =
+ password_manager::PasswordManagerExporter::DeleteCallback;
#if defined(OS_WIN)
const base::FilePath::CharType kNullFileName[] = FILE_PATH_LITERAL("/nul");
@@ -67,17 +78,6 @@ class FakeCredentialProvider
DISALLOW_COPY_AND_ASSIGN(FakeCredentialProvider);
};
-// WriteFunction will delegate to this callback, if set. Use for setting
-// expectations for base::WriteFile in PasswordManagerExporter.
-base::MockCallback<WriteCallback>* g_write_callback = nullptr;
-
-// Mock for base::WriteFile. Expectations should be set on |g_write_callback|.
-int WriteFunction(const base::FilePath& filename, const char* data, int size) {
- if (g_write_callback)
- return g_write_callback->Get().Run(filename, data, size);
- return size;
-}
-
// Creates a hardcoded set of credentials for tests.
std::vector<std::unique_ptr<autofill::PasswordForm>> CreatePasswordList() {
auto password_form = std::make_unique<autofill::PasswordForm>();
@@ -95,142 +95,212 @@ class PasswordManagerExporterTest : public testing::Test {
PasswordManagerExporterTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::UI),
- exporter_(&fake_credential_provider_),
+ exporter_(&fake_credential_provider_, mock_on_progress_.Get()),
destination_path_(kNullFileName) {
- g_write_callback = &mock_write_file_;
- exporter_.SetWriteForTesting(&WriteFunction);
+ exporter_.SetWriteForTesting(mock_write_file_.Get());
+ exporter_.SetDeleteForTesting(mock_delete_file_.Get());
+ password_list_ = CreatePasswordList();
+ fake_credential_provider_.SetPasswordList(password_list_);
}
- ~PasswordManagerExporterTest() override { g_write_callback = nullptr; }
+ ~PasswordManagerExporterTest() override = default;
protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
+ std::vector<std::unique_ptr<autofill::PasswordForm>> password_list_;
FakeCredentialProvider fake_credential_provider_;
+ base::MockCallback<base::RepeatingCallback<
+ void(password_manager::ExportProgressStatus, const std::string&)>>
+ mock_on_progress_;
password_manager::PasswordManagerExporter exporter_;
StrictMock<base::MockCallback<WriteCallback>> mock_write_file_;
+ StrictMock<base::MockCallback<DeleteCallback>> mock_delete_file_;
base::FilePath destination_path_;
+ base::HistogramTester histogram_tester_;
private:
DISALLOW_COPY_AND_ASSIGN(PasswordManagerExporterTest);
};
TEST_F(PasswordManagerExporterTest, PasswordExportSetPasswordListFirst) {
- std::vector<std::unique_ptr<autofill::PasswordForm>> password_list =
- CreatePasswordList();
- fake_credential_provider_.SetPasswordList(password_list);
const std::string serialised(
- password_manager::PasswordCSVWriter::SerializePasswords(password_list));
+ password_manager::PasswordCSVWriter::SerializePasswords(password_list_));
EXPECT_CALL(mock_write_file_,
Run(destination_path_, StrEq(serialised), serialised.size()))
.WillOnce(ReturnArg<2>());
+ EXPECT_CALL(
+ mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::IN_PROGRESS, IsEmpty()));
+ EXPECT_CALL(
+ mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::SUCCEEDED, IsEmpty()));
exporter_.PreparePasswordsForExport();
exporter_.SetDestination(destination_path_);
scoped_task_environment_.RunUntilIdle();
+ histogram_tester_.ExpectUniqueSample(
+ "PasswordManager.ExportedPasswordsPerUserInCSV", password_list_.size(),
+ 1);
+ histogram_tester_.ExpectTotalCount(
+ "PasswordManager.TimeReadingExportedPasswords", 1);
+ histogram_tester_.ExpectUniqueSample(
+ "PasswordManager.ExportPasswordsToCSVResult",
+ ExportPasswordsResult::SUCCESS, 1);
}
-TEST_F(PasswordManagerExporterTest, PasswordExportSetDestinationFirst) {
- std::vector<std::unique_ptr<autofill::PasswordForm>> password_list =
- CreatePasswordList();
- fake_credential_provider_.SetPasswordList(password_list);
- const std::string serialised(
- password_manager::PasswordCSVWriter::SerializePasswords(password_list));
+// When writing fails, we should notify the UI of the failure and try to cleanup
+// a possibly partial passwords file.
+TEST_F(PasswordManagerExporterTest, WriteFileFailed) {
+ const std::string destination_folder_name(
+ destination_path_.DirName().BaseName().AsUTF8Unsafe());
+
+ EXPECT_CALL(mock_write_file_, Run(_, _, _)).WillOnce(Return(-1));
+ EXPECT_CALL(mock_delete_file_, Run(destination_path_, false));
+ EXPECT_CALL(
+ mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::IN_PROGRESS, IsEmpty()));
+ EXPECT_CALL(mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::FAILED_WRITE_FAILED,
+ StrEq(destination_folder_name)));
- EXPECT_CALL(mock_write_file_,
- Run(destination_path_, StrEq(serialised), serialised.size()))
- .WillOnce(ReturnArg<2>());
-
- exporter_.SetDestination(destination_path_);
exporter_.PreparePasswordsForExport();
+ exporter_.SetDestination(destination_path_);
scoped_task_environment_.RunUntilIdle();
+ histogram_tester_.ExpectTotalCount(
+ "PasswordManager.ExportedPasswordsPerUserInCSV", 0);
+ histogram_tester_.ExpectUniqueSample(
+ "PasswordManager.ExportPasswordsToCSVResult",
+ ExportPasswordsResult::WRITE_FAILED, 1);
}
-TEST_F(PasswordManagerExporterTest, DontExportWithOnlyDestination) {
- std::vector<std::unique_ptr<autofill::PasswordForm>> password_list =
- CreatePasswordList();
- fake_credential_provider_.SetPasswordList(password_list);
-
- EXPECT_CALL(mock_write_file_, Run(_, _, _)).Times(0);
+// A partial write should be considered a failure and be cleaned up.
+TEST_F(PasswordManagerExporterTest, WriteFileFailedHalfway) {
+ const std::string serialised(
+ password_manager::PasswordCSVWriter::SerializePasswords(password_list_));
+ const std::string destination_folder_name(
+ destination_path_.DirName().BaseName().AsUTF8Unsafe());
+
+ EXPECT_CALL(mock_write_file_, Run(_, _, _))
+ .WillOnce(Return(serialised.size() / 2));
+ EXPECT_CALL(mock_delete_file_, Run(destination_path_, false));
+ EXPECT_CALL(
+ mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::IN_PROGRESS, IsEmpty()));
+ EXPECT_CALL(mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::FAILED_WRITE_FAILED,
+ StrEq(destination_folder_name)));
+ exporter_.PreparePasswordsForExport();
exporter_.SetDestination(destination_path_);
scoped_task_environment_.RunUntilIdle();
}
-TEST_F(PasswordManagerExporterTest, CancelAfterPasswords) {
- std::vector<std::unique_ptr<autofill::PasswordForm>> password_list =
- CreatePasswordList();
- fake_credential_provider_.SetPasswordList(password_list);
+// Test that GetProgressStatus() returns the last ExportProgressStatus sent
+// to the callback.
+TEST_F(PasswordManagerExporterTest, GetProgressReturnsLastCallbackStatus) {
+ const std::string serialised(
+ password_manager::PasswordCSVWriter::SerializePasswords(password_list_));
+ const std::string destination_folder_name(
+ destination_path_.DirName().BaseName().AsUTF8Unsafe());
- EXPECT_CALL(mock_write_file_, Run(_, _, _)).Times(0);
+ // The last status seen in the callback.
+ password_manager::ExportProgressStatus status =
+ password_manager::ExportProgressStatus::NOT_STARTED;
+
+ EXPECT_CALL(mock_write_file_, Run(_, _, _)).WillOnce(ReturnArg<2>());
+ EXPECT_CALL(mock_on_progress_, Run(_, _)).WillRepeatedly(SaveArg<0>(&status));
+ ASSERT_EQ(exporter_.GetProgressStatus(), status);
exporter_.PreparePasswordsForExport();
- exporter_.Cancel();
exporter_.SetDestination(destination_path_);
+ ASSERT_EQ(exporter_.GetProgressStatus(), status);
scoped_task_environment_.RunUntilIdle();
+ ASSERT_EQ(exporter_.GetProgressStatus(), status);
}
-TEST_F(PasswordManagerExporterTest, CancelAfterDestination) {
- std::vector<std::unique_ptr<autofill::PasswordForm>> password_list =
- CreatePasswordList();
- fake_credential_provider_.SetPasswordList(password_list);
-
+TEST_F(PasswordManagerExporterTest, DontExportWithOnlyDestination) {
EXPECT_CALL(mock_write_file_, Run(_, _, _)).Times(0);
+ EXPECT_CALL(
+ mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::IN_PROGRESS, IsEmpty()));
exporter_.SetDestination(destination_path_);
- exporter_.Cancel();
- exporter_.PreparePasswordsForExport();
scoped_task_environment_.RunUntilIdle();
+ histogram_tester_.ExpectTotalCount(
+ "PasswordManager.ExportedPasswordsPerUserInCSV", 0);
+ histogram_tester_.ExpectTotalCount(
+ "PasswordManager.TimeReadingExportedPasswords", 0);
+ histogram_tester_.ExpectTotalCount(
+ "PasswordManager.ExportPasswordsToCSVResult", 0);
}
-// Test that PasswordManagerExporter is reusable, after an export has been
-// cancelled.
-TEST_F(PasswordManagerExporterTest, CancelAfterPasswordsThenExport) {
- std::vector<std::unique_ptr<autofill::PasswordForm>> password_list =
- CreatePasswordList();
- const std::string serialised(
- password_manager::PasswordCSVWriter::SerializePasswords(password_list));
- fake_credential_provider_.SetPasswordList(password_list);
-
- EXPECT_CALL(mock_write_file_,
- Run(destination_path_, StrEq(serialised), serialised.size()))
- .WillOnce(ReturnArg<2>());
+TEST_F(PasswordManagerExporterTest, CancelAfterPasswords) {
+ EXPECT_CALL(mock_write_file_, Run(_, _, _)).Times(0);
+ EXPECT_CALL(
+ mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::FAILED_CANCELLED, IsEmpty()));
exporter_.PreparePasswordsForExport();
exporter_.Cancel();
- exporter_.SetDestination(destination_path_);
- exporter_.PreparePasswordsForExport();
scoped_task_environment_.RunUntilIdle();
+ histogram_tester_.ExpectTotalCount(
+ "PasswordManager.ExportedPasswordsPerUserInCSV", 0);
+ histogram_tester_.ExpectUniqueSample(
+ "PasswordManager.ExportPasswordsToCSVResult",
+ ExportPasswordsResult::USER_ABORTED, 1);
}
-// Test that PasswordManagerExporter is reusable, after an export has been
-// cancelled.
-TEST_F(PasswordManagerExporterTest, CancelAfterDestinationThenExport) {
- std::vector<std::unique_ptr<autofill::PasswordForm>> password_list =
- CreatePasswordList();
- const std::string serialised(
- password_manager::PasswordCSVWriter::SerializePasswords(password_list));
- fake_credential_provider_.SetPasswordList(password_list);
+TEST_F(PasswordManagerExporterTest, CancelWhileExporting) {
+ EXPECT_CALL(mock_write_file_, Run(_, _, _)).Times(0);
+ EXPECT_CALL(mock_delete_file_, Run(destination_path_, false));
+ EXPECT_CALL(
+ mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::IN_PROGRESS, IsEmpty()));
+ EXPECT_CALL(
+ mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::FAILED_CANCELLED, IsEmpty()));
- base::FilePath cancelled_path(FILE_PATH_LITERAL("clean_me_up"));
+ exporter_.PreparePasswordsForExport();
+ exporter_.SetDestination(destination_path_);
+ exporter_.Cancel();
- EXPECT_CALL(mock_write_file_, Run(cancelled_path, _, _)).Times(0);
- EXPECT_CALL(mock_write_file_,
- Run(destination_path_, StrEq(serialised), serialised.size()))
- .WillOnce(ReturnArg<2>());
+ scoped_task_environment_.RunUntilIdle();
+ histogram_tester_.ExpectTotalCount(
+ "PasswordManager.ExportedPasswordsPerUserInCSV", 0);
+ histogram_tester_.ExpectUniqueSample(
+ "PasswordManager.ExportPasswordsToCSVResult",
+ ExportPasswordsResult::USER_ABORTED, 1);
+}
+
+// The "Cancel" button may still be visible on the UI after we've completed
+// exporting. If they choose to cancel, we should clear the file.
+TEST_F(PasswordManagerExporterTest, CancelAfterExporting) {
+ EXPECT_CALL(mock_write_file_, Run(_, _, _)).WillOnce(ReturnArg<2>());
+ EXPECT_CALL(mock_delete_file_, Run(destination_path_, false));
+ EXPECT_CALL(
+ mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::IN_PROGRESS, IsEmpty()));
+ EXPECT_CALL(
+ mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::SUCCEEDED, IsEmpty()));
+ EXPECT_CALL(
+ mock_on_progress_,
+ Run(password_manager::ExportProgressStatus::FAILED_CANCELLED, IsEmpty()));
- exporter_.SetDestination(std::move(cancelled_path));
- exporter_.Cancel();
exporter_.PreparePasswordsForExport();
exporter_.SetDestination(destination_path_);
scoped_task_environment_.RunUntilIdle();
+ exporter_.Cancel();
+
+ scoped_task_environment_.RunUntilIdle();
}
} // namespace
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 d07e911f86d..d0975d27457 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
@@ -78,13 +78,12 @@ class NameFilter : public StubCredentialsFilter {
std::vector<std::unique_ptr<PasswordForm>> FilterResults(
std::vector<std::unique_ptr<PasswordForm>> results) const override {
base::EraseIf(results, [this](const std::unique_ptr<PasswordForm>& form) {
- return !ShouldSave(*form, form->origin);
+ return !ShouldSave(*form);
});
return results;
}
- bool ShouldSave(const PasswordForm& form,
- const GURL& main_frame_url) const override {
+ bool ShouldSave(const PasswordForm& form) const override {
return form.username_value != name_;
}
diff --git a/chromium/components/password_manager/core/browser/form_saver_impl.cc b/chromium/components/password_manager/core/browser/form_saver_impl.cc
index 802cd1c5fe6..fac82be89ac 100644
--- a/chromium/components/password_manager/core/browser/form_saver_impl.cc
+++ b/chromium/components/password_manager/core/browser/form_saver_impl.cc
@@ -29,6 +29,8 @@ FormSaverImpl::~FormSaverImpl() = default;
void FormSaverImpl::PermanentlyBlacklist(PasswordForm* observed) {
observed->preferred = false;
observed->blacklisted_by_user = true;
+ observed->username_value.clear();
+ observed->password_value.clear();
observed->other_possible_usernames.clear();
observed->date_created = base::Time::Now();
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 49766a74282..56a306f413c 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
@@ -91,11 +91,18 @@ TEST_F(FormSaverImplTest, PermanentlyBlacklist) {
observed.blacklisted_by_user = false;
observed.preferred = true;
+ observed.username_value = ASCIIToUTF16("user1");
+ observed.password_value = ASCIIToUTF16("12345");
+ observed.other_possible_usernames = {
+ {ASCIIToUTF16("user2"), ASCIIToUTF16("field")}};
EXPECT_CALL(*mock_store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved));
form_saver_.PermanentlyBlacklist(&observed);
EXPECT_TRUE(saved.blacklisted_by_user);
EXPECT_FALSE(saved.preferred);
+ EXPECT_EQ(base::string16(), saved.username_value);
+ EXPECT_EQ(base::string16(), saved.password_value);
+ EXPECT_TRUE(saved.other_possible_usernames.empty());
}
// Check that saving the pending form as new adds the credential to the store
diff --git a/chromium/components/password_manager/core/browser/http_data_cleaner.cc b/chromium/components/password_manager/core/browser/http_data_cleaner.cc
index 1a3c71967f8..f57f8413918 100644
--- a/chromium/components/password_manager/core/browser/http_data_cleaner.cc
+++ b/chromium/components/password_manager/core/browser/http_data_cleaner.cc
@@ -8,6 +8,7 @@
#include <iterator>
#include <memory>
#include <tuple>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -208,9 +209,9 @@ void WaitUntilCleaningIsDone(std::unique_ptr<ObsoleteHttpCleaner> cleaner,
const auto post_to_thread =
[](std::unique_ptr<ObsoleteHttpCleaner> cleaner, PrefService* prefs,
scoped_refptr<base::SequencedTaskRunner> thread_runner) {
- thread_runner->PostTask(
- FROM_HERE, base::Bind(&WaitUntilCleaningIsDone,
- base::Passed(std::move(cleaner)), prefs));
+ thread_runner->PostTask(FROM_HERE,
+ base::BindOnce(&WaitUntilCleaningIsDone,
+ std::move(cleaner), prefs));
};
// Calling |ScheduleTask| through the raw pointer is necessary, because
diff --git a/chromium/components/password_manager/core/browser/import/password_csv_reader_fuzzer.cc b/chromium/components/password_manager/core/browser/import/password_csv_reader_fuzzer.cc
index 6a6e2286fbc..3906e418113 100644
--- a/chromium/components/password_manager/core/browser/import/password_csv_reader_fuzzer.cc
+++ b/chromium/components/password_manager/core/browser/import/password_csv_reader_fuzzer.cc
@@ -8,11 +8,21 @@
#include <string>
#include <vector>
+#include "base/at_exit.h"
+#include "base/i18n/icu_util.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/import/password_csv_reader.h"
namespace password_manager {
+struct IcuEnvironment {
+ IcuEnvironment() { CHECK(base::i18n::InitializeICU()); }
+ // used by ICU integration.
+ base::AtExitManager at_exit_manager;
+};
+
+IcuEnvironment* env = new IcuEnvironment();
+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
std::vector<autofill::PasswordForm> passwords;
PasswordCSVReader reader;
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 1e40614605a..93d08fe2f41 100644
--- a/chromium/components/password_manager/core/browser/login_database_unittest.cc
+++ b/chromium/components/password_manager/core/browser/login_database_unittest.cc
@@ -975,6 +975,8 @@ TEST_F(LoginDatabaseTest, ClearPrivateData_SavedPasswords) {
base::Time now = base::Time::Now();
base::TimeDelta one_day = base::TimeDelta::FromDays(1);
+ base::Time back_30_days = now - base::TimeDelta::FromDays(30);
+ base::Time back_31_days = now - base::TimeDelta::FromDays(31);
// Create one with a 0 time.
EXPECT_TRUE(
@@ -985,10 +987,13 @@ TEST_F(LoginDatabaseTest, ClearPrivateData_SavedPasswords) {
EXPECT_TRUE(AddTimestampedLogin(&db(), "http://3.com", "foo3", now, true));
EXPECT_TRUE(
AddTimestampedLogin(&db(), "http://4.com", "foo4", now + one_day, true));
+ // Create one with 31 days old.
+ EXPECT_TRUE(
+ AddTimestampedLogin(&db(), "http://5.com", "foo5", back_31_days, true));
// Verify inserts worked.
EXPECT_TRUE(db().GetAutofillableLogins(&result));
- EXPECT_EQ(4U, result.size());
+ EXPECT_EQ(5U, result.size());
result.clear();
// Get everything from today's date and on.
@@ -996,12 +1001,26 @@ TEST_F(LoginDatabaseTest, ClearPrivateData_SavedPasswords) {
EXPECT_EQ(2U, result.size());
result.clear();
+ // Get all logins created more than 30 days back.
+ EXPECT_TRUE(
+ db().GetLoginsCreatedBetween(base::Time(), back_30_days, &result));
+ EXPECT_EQ(2U, result.size());
+ result.clear();
+
// Delete everything from today's date and on.
db().RemoveLoginsCreatedBetween(now, base::Time());
- // Should have deleted half of what we inserted.
+ // Should have deleted two logins.
EXPECT_TRUE(db().GetAutofillableLogins(&result));
- EXPECT_EQ(2U, result.size());
+ EXPECT_EQ(3U, result.size());
+ result.clear();
+
+ // Delete all logins created more than 30 days back.
+ db().RemoveLoginsCreatedBetween(base::Time(), back_30_days);
+
+ // Should have deleted two logins.
+ EXPECT_TRUE(db().GetAutofillableLogins(&result));
+ EXPECT_EQ(1U, result.size());
result.clear();
// Delete with 0 date (should delete all).
diff --git a/chromium/components/password_manager/core/browser/mock_password_store.h b/chromium/components/password_manager/core/browser/mock_password_store.h
index 11603b98e2b..f8ed24e52c8 100644
--- a/chromium/components/password_manager/core/browser/mock_password_store.h
+++ b/chromium/components/password_manager/core/browser/mock_password_store.h
@@ -71,12 +71,14 @@ class MockPasswordStore : public PasswordStore {
MOCK_METHOD1(AddSiteStatsImpl, void(const InteractionsStats&));
MOCK_METHOD1(RemoveSiteStatsImpl, void(const GURL&));
// TODO(crbug.com/706392): Fix password reuse detection for Android.
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
MOCK_METHOD3(CheckReuse,
void(const base::string16&,
const std::string&,
PasswordReuseDetectorConsumer*));
- MOCK_METHOD1(SaveSyncPasswordHash, void(const base::string16&));
+ MOCK_METHOD2(SaveSyncPasswordHash,
+ void(const base::string16&,
+ metrics_util::SyncPasswordHashChange));
MOCK_METHOD0(ClearSyncPasswordHash, void());
#endif
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 a485756f24f..7e43d9e0d95 100644
--- a/chromium/components/password_manager/core/browser/password_autofill_manager.cc
+++ b/chromium/components/password_manager/core/browser/password_autofill_manager.cc
@@ -301,7 +301,7 @@ void PasswordAutofillManager::OnShowPasswordSuggestions(
if (ShouldShowManualFallbackForPreLollipop(
autofill_client_->GetSyncService())) {
if (base::FeatureList::IsEnabled(
- password_manager::features::kEnableManualFallbacksFilling) &&
+ password_manager::features::kManualFallbacksFilling) &&
(options & autofill::IS_PASSWORD_FIELD) && password_client_ &&
password_client_->IsFillingFallbackEnabledForCurrentPage()) {
AddSimpleSuggestionWithSeparatorOnTop(
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 187b77b4630..7a5f2364c07 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
@@ -173,10 +173,10 @@ class PasswordAutofillManagerTest : public testing::Test {
void SetManualFallbacksForFilling(bool enabled) {
if (enabled) {
scoped_feature_list_.InitAndEnableFeature(
- password_manager::features::kEnableManualFallbacksFilling);
+ password_manager::features::kManualFallbacksFilling);
} else {
scoped_feature_list_.InitAndDisableFeature(
- password_manager::features::kEnableManualFallbacksFilling);
+ password_manager::features::kManualFallbacksFilling);
}
}
@@ -192,13 +192,13 @@ class PasswordAutofillManagerTest : public testing::Test {
static bool IsManualFallbackForFillingEnabled() {
return base::FeatureList::IsEnabled(
- password_manager::features::kEnableManualFallbacksFilling) &&
+ password_manager::features::kManualFallbacksFilling) &&
!IsPreLollipopAndroid();
}
void SetManualFallbacks(bool enabled) {
std::vector<std::string> features = {
- password_manager::features::kEnableManualFallbacksFilling.name,
+ password_manager::features::kManualFallbacksFilling.name,
password_manager::features::kEnableManualFallbacksFillingStandalone
.name,
password_manager::features::kEnableManualFallbacksGeneration.name};
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 18b678fcf10..f5f2b167d15 100644
--- a/chromium/components/password_manager/core/browser/password_form_manager.cc
+++ b/chromium/components/password_manager/core/browser/password_form_manager.cc
@@ -679,6 +679,7 @@ void PasswordFormManager::ProcessFrameInternal(
driver->AllowPasswordGenerationForForm(observed_form_);
if (best_matches_.empty()) {
+ driver->InformNoSavedCredentials();
metrics_recorder_->RecordFillEvent(
PasswordFormMetricsRecorder::kManagerFillEventNoCredential);
return;
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 9f66ed38774..eb29199e79d 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
@@ -332,6 +332,7 @@ class MockPasswordManagerDriver : public StubPasswordManagerDriver {
~MockPasswordManagerDriver() {}
MOCK_METHOD1(FillPasswordForm, void(const autofill::PasswordFormFillData&));
+ MOCK_METHOD0(InformNoSavedCredentials, void());
MOCK_METHOD1(ShowInitialPasswordAccountSuggestions,
void(const autofill::PasswordFormFillData&));
MOCK_METHOD1(AllowPasswordGenerationForForm,
@@ -2736,6 +2737,12 @@ TEST_F(PasswordFormManagerTest, ProcessFrame) {
fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);
}
+// Test that driver is informed when there are not saved credentials.
+TEST_F(PasswordFormManagerTest, InformNoSavedCredentials) {
+ EXPECT_CALL(*client()->mock_driver(), InformNoSavedCredentials());
+ fake_form_fetcher()->SetNonFederated({}, 0u);
+}
+
// Test that ProcessFrame can also be called directly, resulting in an
// additional FillPasswordForm call.
TEST_F(PasswordFormManagerTest, ProcessFrame_MoreProcessFrameMoreFill) {
diff --git a/chromium/components/password_manager/core/browser/password_generation_manager_unittest.cc b/chromium/components/password_manager/core/browser/password_generation_manager_unittest.cc
index ea862c3fd01..75741e94787 100644
--- a/chromium/components/password_manager/core/browser/password_generation_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_generation_manager_unittest.cc
@@ -296,7 +296,7 @@ TEST_F(PasswordGenerationManagerTest, CheckIfFormClassifierShouldRun) {
scoped_refptr<base::FieldTrial> field_trial;
if (is_autofill_field_metadata_enabled) {
field_trial_list.reset(new base::FieldTrialList(
- std::make_unique<metrics::SHA1EntropyProvider>("foo")));
+ std::make_unique<variations::SHA1EntropyProvider>("foo")));
field_trial = base::FieldTrialList::CreateFieldTrial(
"AutofillFieldMetadata", "Enabled");
EXPECT_CALL(*GetTestDriver(), AllowToRunFormClassifier())
diff --git a/chromium/components/password_manager/core/browser/password_manager.cc b/chromium/components/password_manager/core/browser/password_manager.cc
index cd1133eac35..2093f518291 100644
--- a/chromium/components/password_manager/core/browser/password_manager.cc
+++ b/chromium/components/password_manager/core/browser/password_manager.cc
@@ -71,11 +71,19 @@ bool URLsEqualUpToHttpHttpsSubstitution(const GURL& a, const GURL& b) {
return false;
}
+// Since empty or unspecified form's action is automatically set to the page
+// origin, this function checks if a form's action is empty by comparing it to
+// its origin.
+bool HasNonEmptyAction(const autofill::PasswordForm& form) {
+ return form.action != form.origin;
+}
+
// Checks if the observed form looks like the submitted one to handle "Invalid
// password entered" case so we don't offer a password save when we shouldn't.
bool IsPasswordFormReappeared(const autofill::PasswordForm& observed_form,
const autofill::PasswordForm& submitted_form) {
- if (observed_form.action.is_valid() &&
+ if (observed_form.action.is_valid() && HasNonEmptyAction(observed_form) &&
+ HasNonEmptyAction(submitted_form) &&
URLsEqualUpToHttpHttpsSubstitution(submitted_form.action,
observed_form.action)) {
return true;
@@ -492,7 +500,7 @@ void PasswordManager::OnPasswordFormSubmittedNoChecks(
const autofill::PasswordForm& password_form) {
if (password_manager_util::IsLoggingActive(client_)) {
BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
- logger.LogMessage(Logger::STRING_ON_IN_PAGE_NAVIGATION);
+ logger.LogMessage(Logger::STRING_ON_SAME_DOCUMENT_NAVIGATION);
}
ProvisionallySavePassword(password_form, driver);
@@ -540,7 +548,6 @@ void PasswordManager::ShowManualFallbackForSaving(
client_->ShowManualFallbackForSaving(std::move(provisional_save_manager_),
has_generated_password, is_update);
} else {
- provisional_save_manager_.reset();
HideManualFallbackForSaving();
}
}
@@ -821,7 +828,7 @@ void PasswordManager::OnPasswordFormsRendered(
}
}
-void PasswordManager::OnInPageNavigation(
+void PasswordManager::OnSameDocumentNavigation(
password_manager::PasswordManagerDriver* driver,
const PasswordForm& password_form) {
OnPasswordFormSubmittedNoChecks(driver, password_form);
@@ -848,8 +855,7 @@ void PasswordManager::OnLoginSuccessful() {
DCHECK(provisional_save_manager_->submitted_form());
if (!client_->GetStoreResultFilter()->ShouldSave(
- *provisional_save_manager_->submitted_form(),
- client_->GetMainFrameURL())) {
+ *provisional_save_manager_->submitted_form())) {
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
// When |username_value| is empty, it's not clear whether the submitted
// credentials are really sync credentials. Don't save sync password hash
@@ -861,15 +867,15 @@ void PasswordManager::OnLoginSuccessful() {
bool is_sync_password_change =
!provisional_save_manager_->submitted_form()
->new_password_element.empty();
- metrics_util::LogSyncPasswordHashChange(
- is_sync_password_change
- ? metrics_util::SyncPasswordHashChange::CHANGED_IN_CONTENT_AREA
- : metrics_util::SyncPasswordHashChange::SAVED_IN_CONTENT_AREA);
- store->SaveSyncPasswordHash(
- is_sync_password_change
- ? provisional_save_manager_->submitted_form()
- ->new_password_value
- : provisional_save_manager_->submitted_form()->password_value);
+ if (is_sync_password_change) {
+ store->SaveSyncPasswordHash(
+ provisional_save_manager_->submitted_form()->new_password_value,
+ metrics_util::SyncPasswordHashChange::CHANGED_IN_CONTENT_AREA);
+ } else {
+ store->SaveSyncPasswordHash(
+ provisional_save_manager_->submitted_form()->password_value,
+ metrics_util::SyncPasswordHashChange::SAVED_IN_CONTENT_AREA);
+ }
}
}
#endif
diff --git a/chromium/components/password_manager/core/browser/password_manager.h b/chromium/components/password_manager/core/browser/password_manager.h
index bfafe7fcd7a..e463ad56dbe 100644
--- a/chromium/components/password_manager/core/browser/password_manager.h
+++ b/chromium/components/password_manager/core/browser/password_manager.h
@@ -177,8 +177,8 @@ class PasswordManager : public LoginModel {
// means history.pushState being called from JavaScript. If this causes false
// positive in password saving, update http://crbug.com/357696.
// TODO(https://crbug.com/795462): find better name for this function.
- void OnInPageNavigation(password_manager::PasswordManagerDriver* driver,
- const autofill::PasswordForm& password_form);
+ void OnSameDocumentNavigation(password_manager::PasswordManagerDriver* driver,
+ const autofill::PasswordForm& password_form);
void ProcessAutofillPredictions(
password_manager::PasswordManagerDriver* driver,
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 6f415df8841..0469659be97 100644
--- a/chromium/components/password_manager/core/browser/password_manager_driver.h
+++ b/chromium/components/password_manager/core/browser/password_manager_driver.h
@@ -39,6 +39,11 @@ class PasswordManagerDriver
virtual void FillPasswordForm(
const autofill::PasswordFormFillData& form_data) = 0;
+ // Informs the driver that there are no saved credentials in the password
+ // store for the current page.
+ // TODO(https://crbug.com/621355): Remove and observe FormFetcher instead.
+ virtual void InformNoSavedCredentials() {}
+
// Informs the driver that |form| can be used for password generation.
virtual void AllowPasswordGenerationForForm(
const autofill::PasswordForm& form) = 0;
diff --git a/chromium/components/password_manager/core/browser/password_manager_metrics_recorder.cc b/chromium/components/password_manager/core/browser/password_manager_metrics_recorder.cc
index 4ba9a27e892..db3ba690dc6 100644
--- a/chromium/components/password_manager/core/browser/password_manager_metrics_recorder.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_metrics_recorder.cc
@@ -4,6 +4,8 @@
#include "components/password_manager/core/browser/password_manager_metrics_recorder.h"
+#include <memory>
+
#include "base/metrics/histogram_macros.h"
#include "components/autofill/core/common/save_password_progress_logger.h"
#include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
@@ -21,7 +23,7 @@ PasswordManagerMetricsRecorder::PasswordManagerMetricsRecorder(
const GURL& main_frame_url)
: main_frame_url_(main_frame_url),
ukm_entry_builder_(
- base::MakeUnique<ukm::builders::PageWithPassword>(source_id)) {}
+ std::make_unique<ukm::builders::PageWithPassword>(source_id)) {}
PasswordManagerMetricsRecorder::PasswordManagerMetricsRecorder(
PasswordManagerMetricsRecorder&& that) noexcept = default;
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 73d7876608a..26c26a7024a 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
@@ -274,6 +274,15 @@ enum class CertificateError {
COUNT
};
+// Metric: PasswordManager.ExportPasswordsToCSVResult
+enum class ExportPasswordsResult {
+ SUCCESS = 0,
+ USER_ABORTED = 1,
+ WRITE_FAILED = 2,
+ NO_CONSUMER = 3, // Only used on Android.
+ COUNT,
+};
+
// A version of the UMA_HISTOGRAM_BOOLEAN macro that allows the |name|
// to vary over the program's runtime.
void LogUMAHistogramBoolean(const std::string& name, bool sample);
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 5c09f502787..c153ff1a386 100644
--- a/chromium/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_unittest.cc
@@ -16,6 +16,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
+#include "base/test/user_action_tester.h"
#include "build/build_config.h"
#include "components/password_manager/core/browser/form_fetcher_impl.h"
#include "components/password_manager/core/browser/mock_password_store.h"
@@ -48,9 +49,7 @@ namespace {
class MockStoreResultFilter : public StubCredentialsFilter {
public:
- MOCK_CONST_METHOD2(ShouldSave,
- bool(const autofill::PasswordForm& form,
- const GURL& main_frame_url));
+ MOCK_CONST_METHOD1(ShouldSave, bool(const autofill::PasswordForm& form));
MOCK_CONST_METHOD1(ReportFormLoginSuccess,
void(const PasswordFormManager& form_manager));
};
@@ -61,7 +60,7 @@ class MockPasswordManagerClient : public StubPasswordManagerClient {
EXPECT_CALL(*this, GetStoreResultFilter())
.Times(AnyNumber())
.WillRepeatedly(Return(&filter_));
- ON_CALL(filter_, ShouldSave(_, _)).WillByDefault(Return(true));
+ ON_CALL(filter_, ShouldSave(_)).WillByDefault(Return(true));
}
MOCK_CONST_METHOD0(IsSavingAndFillingEnabledForCurrentPage, bool());
@@ -100,7 +99,7 @@ class MockPasswordManagerClient : public StubPasswordManagerClient {
}
void FilterAllResultsForSaving() {
- EXPECT_CALL(filter_, ShouldSave(_, _)).WillRepeatedly(Return(false));
+ EXPECT_CALL(filter_, ShouldSave(_)).WillRepeatedly(Return(false));
}
private:
@@ -535,6 +534,8 @@ TEST_F(PasswordManagerTest, DontSaveAlreadySavedCredential) {
EXPECT_THAT(form_manager_to_save->pending_credentials(),
FormMatches(incomplete_match));
+ base::UserActionTester user_action_tester;
+
// The user completes typing the credential. No fallback should be available,
// because the credential is already in the store.
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true)).Times(0);
@@ -549,6 +550,8 @@ TEST_F(PasswordManagerTest, DontSaveAlreadySavedCredential) {
observed.clear();
manager()->OnPasswordFormsParsed(&driver_, observed);
manager()->OnPasswordFormsRendered(&driver_, observed, true);
+ EXPECT_EQ(1,
+ user_action_tester.GetActionCount("PasswordManager_LoginPassed"));
}
TEST_F(PasswordManagerTest, FormSeenThenLeftPage) {
@@ -761,7 +764,7 @@ TEST_F(PasswordManagerTest, SyncCredentialsNotSaved) {
EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
EXPECT_CALL(*store_, AddLogin(_)).Times(0);
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
- EXPECT_CALL(*store_, SaveSyncPasswordHash(form.password_value));
+ EXPECT_CALL(*store_, SaveSyncPasswordHash(form.password_value, _));
#endif
// Prefs are needed for failure logging about sync credentials.
EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
@@ -809,7 +812,7 @@ TEST_F(PasswordManagerTest, ReportFormLoginSuccessAndShouldSaveCalled) {
PasswordForm submitted_form = observed_form;
submitted_form.preferred = true;
- EXPECT_CALL(*client_.GetStoreResultFilter(), ShouldSave(submitted_form, _));
+ EXPECT_CALL(*client_.GetStoreResultFilter(), ShouldSave(submitted_form));
EXPECT_CALL(*store_, UpdateLogin(_));
observed.clear();
manager()->OnPasswordFormsParsed(&driver_, observed);
@@ -839,7 +842,7 @@ TEST_F(PasswordManagerTest, SyncCredentialsNotDroppedIfUpToDate) {
.WillRepeatedly(Return(true));
EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
- EXPECT_CALL(*store_, SaveSyncPasswordHash(form.password_value));
+ EXPECT_CALL(*store_, SaveSyncPasswordHash(form.password_value, _));
#endif
manager()->ProvisionallySavePassword(form, nullptr);
@@ -875,7 +878,7 @@ TEST_F(PasswordManagerTest, SyncCredentialsDroppedWhenObsolete) {
.WillRepeatedly(Return(true));
EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
- EXPECT_CALL(*store_, SaveSyncPasswordHash(ASCIIToUTF16("n3w passw0rd")));
+ EXPECT_CALL(*store_, SaveSyncPasswordHash(ASCIIToUTF16("n3w passw0rd"), _));
#endif
manager()->ProvisionallySavePassword(updated_form, nullptr);
@@ -1135,7 +1138,7 @@ TEST_F(PasswordManagerTest, FillPasswordOnManyFrames) {
manager()->OnPasswordFormsParsed(&driver_b, observed);
}
-TEST_F(PasswordManagerTest, InPageNavigation) {
+TEST_F(PasswordManagerTest, SameDocumentNavigation) {
// Test that observing a newly submitted form shows the save password bar on
// call in page navigation.
std::vector<PasswordForm> observed;
@@ -1153,7 +1156,7 @@ TEST_F(PasswordManagerTest, InPageNavigation) {
EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
- manager()->OnInPageNavigation(&driver_, form);
+ manager()->OnSameDocumentNavigation(&driver_, form);
ASSERT_TRUE(form_manager_to_save);
// Simulate saving the form, as if the info bar was accepted.
@@ -1164,7 +1167,7 @@ TEST_F(PasswordManagerTest, InPageNavigation) {
form_manager_to_save->Save();
}
-TEST_F(PasswordManagerTest, InPageNavigationBlacklistedSite) {
+TEST_F(PasswordManagerTest, SameDocumentBlacklistedSite) {
// Test that observing a newly submitted form on blacklisted site does notify
// the embedder on call in page navigation.
std::vector<PasswordForm> observed;
@@ -1188,7 +1191,7 @@ TEST_F(PasswordManagerTest, InPageNavigationBlacklistedSite) {
EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
- manager()->OnInPageNavigation(&driver_, form);
+ manager()->OnSameDocumentNavigation(&driver_, form);
EXPECT_TRUE(form_manager_to_save->IsBlacklisted());
}
@@ -1951,7 +1954,7 @@ TEST_F(PasswordManagerTest, NotSavingSyncPasswordHash_NoUsername) {
client_.FilterAllResultsForSaving();
// Check that no sync credential password hash is saved.
- EXPECT_CALL(*store_, SaveSyncPasswordHash(_)).Times(0);
+ EXPECT_CALL(*store_, SaveSyncPasswordHash(_, _)).Times(0);
OnPasswordFormSubmitted(form);
observed.clear();
manager()->OnPasswordFormsRendered(&driver_, observed, true);
@@ -1973,7 +1976,7 @@ TEST_F(PasswordManagerTest, NotSavingSyncPasswordHash_NotSyncCredentials) {
// Check that no sync credential password hash is saved since these
// credentials are eligible for saving.
- EXPECT_CALL(*store_, SaveSyncPasswordHash(_)).Times(0);
+ EXPECT_CALL(*store_, SaveSyncPasswordHash(_, _)).Times(0);
std::unique_ptr<PasswordFormManager> form_manager_to_save;
EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
@@ -2202,7 +2205,11 @@ TEST_F(PasswordManagerTest, SaveSyncPasswordHashOnChangePasswordPage) {
.WillRepeatedly(Return(true));
EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
- EXPECT_CALL(*store_, SaveSyncPasswordHash(form.new_password_value));
+ EXPECT_CALL(
+ *store_,
+ SaveSyncPasswordHash(
+ form.new_password_value,
+ metrics_util::SyncPasswordHashChange::CHANGED_IN_CONTENT_AREA));
#endif
client_.FilterAllResultsForSaving();
OnPasswordFormSubmitted(form);
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 3cccd72398c..3630c932b83 100644
--- a/chromium/components/password_manager/core/browser/password_manager_util.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_util.cc
@@ -114,6 +114,8 @@ bool ShowAllSavedPasswordsContextMenuEnabled() {
void UserTriggeredShowAllSavedPasswordsFromContextMenu(
autofill::AutofillClient* autofill_client) {
+ if (!autofill_client)
+ return;
autofill_client->ExecuteCommand(
autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY);
password_manager::metrics_util::LogContextOfShowAllSavedPasswordsAccepted(
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 36ef36382a7..0fff42d45d4 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
@@ -24,7 +24,7 @@ constexpr TimeDelta kMaxInactivityTime = TimeDelta::FromSeconds(10);
PasswordReuseDetectionManager::PasswordReuseDetectionManager(
PasswordManagerClient* client)
- : client_(client), clock_(new base::DefaultClock) {
+ : client_(client), clock_(base::DefaultClock::GetInstance()) {
DCHECK(client_);
}
@@ -113,9 +113,8 @@ void PasswordReuseDetectionManager::OnReuseFound(
#endif
}
-void PasswordReuseDetectionManager::SetClockForTesting(
- std::unique_ptr<base::Clock> clock) {
- clock_ = std::move(clock);
+void PasswordReuseDetectionManager::SetClockForTesting(base::Clock* clock) {
+ clock_ = clock;
}
} // namespace password_manager
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 71711ecbad7..02eb8546e92 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
@@ -35,7 +35,7 @@ class PasswordReuseDetectionManager : public PasswordReuseDetectorConsumer {
const std::vector<std::string>& matching_domains,
int saved_passwords) override;
- void SetClockForTesting(std::unique_ptr<base::Clock> clock);
+ void SetClockForTesting(base::Clock* clock);
private:
PasswordManagerClient* client_;
@@ -43,7 +43,7 @@ class PasswordReuseDetectionManager : public PasswordReuseDetectorConsumer {
GURL main_frame_url_;
base::Time last_keystroke_time_;
// Used to retrieve the current time, in base::Time units.
- std::unique_ptr<base::Clock> clock_;
+ base::Clock* clock_;
bool reuse_on_this_page_was_found_ = false;
DISALLOW_COPY_AND_ASSIGN(PasswordReuseDetectionManager);
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 a31ab884fab..094c0583080 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
@@ -96,17 +96,16 @@ TEST_F(PasswordReuseDetectionManagerTest,
.WillRepeatedly(testing::Return(store_.get()));
PasswordReuseDetectionManager manager(&client_);
- std::unique_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock);
+ base::SimpleTestClock clock;
base::Time now = base::Time::Now();
- clock->SetNow(now);
- base::SimpleTestClock* clock_weak = clock.get();
- manager.SetClockForTesting(std::move(clock));
+ clock.SetNow(now);
+ manager.SetClockForTesting(&clock);
EXPECT_CALL(*store_, CheckReuse(base::ASCIIToUTF16("1"), _, _));
manager.OnKeyPressed(base::ASCIIToUTF16("1"));
// Simulate 10 seconds of inactivity.
- clock_weak->SetNow(now + base::TimeDelta::FromSeconds(10));
+ clock.SetNow(now + base::TimeDelta::FromSeconds(10));
// Expect that a keystroke typed before inactivity is cleared.
EXPECT_CALL(*store_, CheckReuse(base::ASCIIToUTF16("2"), _, _));
manager.OnKeyPressed(base::ASCIIToUTF16("2"));
diff --git a/chromium/components/password_manager/core/browser/password_store.cc b/chromium/components/password_manager/core/browser/password_store.cc
index a04fb42a544..66d0eb2dd97 100644
--- a/chromium/components/password_manager/core/browser/password_store.cc
+++ b/chromium/components/password_manager/core/browser/password_store.cc
@@ -53,15 +53,16 @@ void PasswordStore::GetLoginsRequest::NotifyConsumerWithResults(
}
origin_task_runner_->PostTask(
- FROM_HERE, base::Bind(&PasswordStoreConsumer::OnGetPasswordStoreResults,
- consumer_weak_, base::Passed(&results)));
+ FROM_HERE,
+ base::BindOnce(&PasswordStoreConsumer::OnGetPasswordStoreResults,
+ consumer_weak_, std::move(results)));
}
void PasswordStore::GetLoginsRequest::NotifyWithSiteStatistics(
std::vector<InteractionsStats> stats) {
origin_task_runner_->PostTask(
- FROM_HERE, base::Bind(&PasswordStoreConsumer::OnGetSiteStatistics,
- consumer_weak_, base::Passed(&stats)));
+ FROM_HERE, base::BindOnce(&PasswordStoreConsumer::OnGetSiteStatistics,
+ consumer_weak_, std::move(stats)));
}
// TODO(crbug.com/706392): Fix password reuse detection for Android.
@@ -352,20 +353,26 @@ void PasswordStore::CheckReuse(const base::string16& input,
#endif
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
-void PasswordStore::SaveSyncPasswordHash(const base::string16& password) {
- // TODO(crbug.com/657041): Log success of saving password hash to UMA.
- hash_password_manager_.SavePasswordHash(password);
- base::Optional<SyncPasswordData> sync_password_data =
- hash_password_manager_.RetrievePasswordHash();
- ScheduleTask(base::Bind(&PasswordStore::SaveSyncPasswordHashImpl, this,
- std::move(sync_password_data)));
+void PasswordStore::SaveSyncPasswordHash(
+ const base::string16& password,
+ metrics_util::SyncPasswordHashChange event) {
+ if (hash_password_manager_.SavePasswordHash(password)) {
+ base::Optional<SyncPasswordData> sync_password_data =
+ hash_password_manager_.RetrievePasswordHash();
+ metrics_util::LogSyncPasswordHashChange(event);
+ ScheduleTask(base::BindRepeating(&PasswordStore::SaveSyncPasswordHashImpl,
+ this, std::move(sync_password_data)));
+ }
}
void PasswordStore::SaveSyncPasswordHash(
- const SyncPasswordData& sync_password_data) {
- hash_password_manager_.SavePasswordHash(sync_password_data);
- ScheduleTask(base::BindRepeating(&PasswordStore::SaveSyncPasswordHashImpl,
- this, sync_password_data));
+ const SyncPasswordData& sync_password_data,
+ metrics_util::SyncPasswordHashChange event) {
+ if (hash_password_manager_.SavePasswordHash(sync_password_data)) {
+ metrics_util::LogSyncPasswordHashChange(event);
+ ScheduleTask(base::BindRepeating(&PasswordStore::SaveSyncPasswordHashImpl,
+ this, sync_password_data));
+ }
}
void PasswordStore::ClearSyncPasswordHash() {
@@ -496,7 +503,7 @@ void PasswordStore::Schedule(
std::unique_ptr<GetLoginsRequest> request(new GetLoginsRequest(consumer));
consumer->cancelable_task_tracker()->PostTask(
background_task_runner_.get(), FROM_HERE,
- base::BindOnce(func, this, base::Passed(&request)));
+ base::BindOnce(func, this, std::move(request)));
}
void PasswordStore::WrapModificationTask(ModificationTask task) {
@@ -601,8 +608,8 @@ void PasswordStore::
// post a request to UI thread.
main_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&PasswordStore::InjectAffiliationAndBrandingInformation, this,
- base::Passed(&obtained_forms), base::Passed(&request)));
+ base::BindOnce(&PasswordStore::InjectAffiliationAndBrandingInformation,
+ this, std::move(obtained_forms), std::move(request)));
}
void PasswordStore::GetBlacklistLoginsImpl(
@@ -622,8 +629,8 @@ void PasswordStore::GetBlacklistLoginsWithAffiliationAndBrandingInformationImpl(
// post a request to UI thread.
main_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&PasswordStore::InjectAffiliationAndBrandingInformation, this,
- base::Passed(&obtained_forms), base::Passed(&request)));
+ base::BindOnce(&PasswordStore::InjectAffiliationAndBrandingInformation,
+ this, std::move(obtained_forms), std::move(request)));
}
void PasswordStore::NotifyAllSiteStats(
diff --git a/chromium/components/password_manager/core/browser/password_store.h b/chromium/components/password_manager/core/browser/password_store.h
index 859c03ca859..4c0b4bce1f6 100644
--- a/chromium/components/password_manager/core/browser/password_store.h
+++ b/chromium/components/password_manager/core/browser/password_store.h
@@ -26,6 +26,7 @@
// TODO(crbug.com/706392): Fix password reuse detection for Android.
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
#include "components/password_manager/core/browser/hash_password_manager.h"
+#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_reuse_detector.h"
#include "components/password_manager/core/browser/password_reuse_detector_consumer.h"
#endif
@@ -259,10 +260,14 @@ class PasswordStore : protected PasswordStoreSync,
PasswordReuseDetectorConsumer* consumer);
// Saves a hash of |password| for password reuse checking.
- virtual void SaveSyncPasswordHash(const base::string16& password);
+ // |event| is used for metric logging.
+ virtual void SaveSyncPasswordHash(const base::string16& password,
+ metrics_util::SyncPasswordHashChange event);
// Saves |sync_password_data| for password reuse checking.
- virtual void SaveSyncPasswordHash(const SyncPasswordData& sync_password_data);
+ // |event| is used for metric logging.
+ virtual void SaveSyncPasswordHash(const SyncPasswordData& sync_password_data,
+ metrics_util::SyncPasswordHashChange event);
// Clears the saved sync password hash.
virtual void ClearSyncPasswordHash();
diff --git a/chromium/components/password_manager/core/browser/password_store_signin_notifier.cc b/chromium/components/password_manager/core/browser/password_store_signin_notifier.cc
index e874af1d8e1..de487acd78a 100644
--- a/chromium/components/password_manager/core/browser/password_store_signin_notifier.cc
+++ b/chromium/components/password_manager/core/browser/password_store_signin_notifier.cc
@@ -14,10 +14,11 @@ PasswordStoreSigninNotifier::PasswordStoreSigninNotifier() {}
PasswordStoreSigninNotifier::~PasswordStoreSigninNotifier() {}
void PasswordStoreSigninNotifier::NotifySignin(const std::string& password) {
- metrics_util::LogSyncPasswordHashChange(
- metrics_util::SyncPasswordHashChange::SAVED_ON_CHROME_SIGNIN);
- if (store_)
- store_->SaveSyncPasswordHash(base::UTF8ToUTF16(password));
+ if (store_) {
+ store_->SaveSyncPasswordHash(
+ base::UTF8ToUTF16(password),
+ metrics_util::SyncPasswordHashChange::SAVED_ON_CHROME_SIGNIN);
+ }
}
void PasswordStoreSigninNotifier::NotifySignedOut() {
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 cba6931b3fa..20ffc81702a 100644
--- a/chromium/components/password_manager/core/browser/password_store_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_store_unittest.cc
@@ -927,7 +927,9 @@ TEST_F(PasswordStoreTest, SavingClearingSyncPassword) {
const base::string16 sync_password = base::ASCIIToUTF16("password");
const base::string16 input = base::ASCIIToUTF16("123password");
- store->SaveSyncPasswordHash(sync_password);
+ store->SaveSyncPasswordHash(
+ sync_password,
+ metrics_util::SyncPasswordHashChange::SAVED_ON_CHROME_SIGNIN);
WaitForPasswordStore();
EXPECT_TRUE(prefs.HasPrefPath(prefs::kSyncPasswordHash));
diff --git a/chromium/components/password_manager/core/browser/site_affiliation/asset_link_retriever.cc b/chromium/components/password_manager/core/browser/site_affiliation/asset_link_retriever.cc
index 9095f63cda6..87edae58d7e 100644
--- a/chromium/components/password_manager/core/browser/site_affiliation/asset_link_retriever.cc
+++ b/chromium/components/password_manager/core/browser/site_affiliation/asset_link_retriever.cc
@@ -83,7 +83,7 @@ void AssetLinkRetriever::OnURLFetchComplete(const net::URLFetcher* source) {
base::BindOnce(&AssetLinkData::Parse, base::Unretained(data_raw),
std::move(response_string)),
base::BindOnce(&AssetLinkRetriever::OnResponseParsed, this,
- base::Passed(&data)));
+ std::move(data)));
}
fetcher_.reset();
}
diff --git a/chromium/components/password_manager/core/browser/stub_credentials_filter.cc b/chromium/components/password_manager/core/browser/stub_credentials_filter.cc
index 233e4d92f70..8782cc324f9 100644
--- a/chromium/components/password_manager/core/browser/stub_credentials_filter.cc
+++ b/chromium/components/password_manager/core/browser/stub_credentials_filter.cc
@@ -17,8 +17,8 @@ StubCredentialsFilter::FilterResults(
return results;
}
-bool StubCredentialsFilter::ShouldSave(const autofill::PasswordForm& form,
- const GURL& main_frame_url) const {
+bool StubCredentialsFilter::ShouldSave(
+ const autofill::PasswordForm& form) const {
return true;
}
diff --git a/chromium/components/password_manager/core/browser/stub_credentials_filter.h b/chromium/components/password_manager/core/browser/stub_credentials_filter.h
index 09fc10f40f2..03fcd34c671 100644
--- a/chromium/components/password_manager/core/browser/stub_credentials_filter.h
+++ b/chromium/components/password_manager/core/browser/stub_credentials_filter.h
@@ -22,8 +22,7 @@ class StubCredentialsFilter : public CredentialsFilter {
std::vector<std::unique_ptr<autofill::PasswordForm>> FilterResults(
std::vector<std::unique_ptr<autofill::PasswordForm>> results)
const override;
- bool ShouldSave(const autofill::PasswordForm& form,
- const GURL& main_frame_url) const override;
+ bool ShouldSave(const autofill::PasswordForm& form) const override;
void ReportFormLoginSuccess(
const PasswordFormManager& form_manager) const override;
diff --git a/chromium/components/password_manager/core/browser/test_password_store.cc b/chromium/components/password_manager/core/browser/test_password_store.cc
index 8770c7a9a0e..2166d73d67a 100644
--- a/chromium/components/password_manager/core/browser/test_password_store.cc
+++ b/chromium/components/password_manager/core/browser/test_password_store.cc
@@ -13,6 +13,7 @@
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/psl_matching_helper.h"
#include "components/password_manager/core/browser/statistics_table.h"
+#include "url/gurl.h"
namespace password_manager {
@@ -140,8 +141,16 @@ bool TestPasswordStore::FillBlacklistLogins(
std::vector<std::unique_ptr<autofill::PasswordForm>>
TestPasswordStore::FillLoginsForSameOrganizationName(
const std::string& signon_realm) {
- NOTIMPLEMENTED();
- return {};
+ // Note: To keep TestPasswordStore simple, and because no tests currently
+ // require anything more complex, this is a simplistic implementation which
+ // assumes that that the signon_realm is a serialised URL.
+ return FillMatchingLogins(FormDigest(autofill::PasswordForm::SCHEME_HTML,
+ signon_realm, GURL(signon_realm)));
+}
+
+std::vector<InteractionsStats> TestPasswordStore::GetSiteStatsImpl(
+ const GURL& origin_domain) {
+ return std::vector<InteractionsStats>();
}
void TestPasswordStore::ReportMetricsImpl(const std::string& sync_username,
@@ -198,10 +207,4 @@ std::vector<InteractionsStats> TestPasswordStore::GetAllSiteStatsImpl() {
return std::vector<InteractionsStats>();
}
-std::vector<InteractionsStats> TestPasswordStore::GetSiteStatsImpl(
- const GURL& origin_domain) {
- NOTIMPLEMENTED();
- return std::vector<InteractionsStats>();
-}
-
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/test_password_store.h b/chromium/components/password_manager/core/browser/test_password_store.h
index db4838b2136..1c89ade8d8c 100644
--- a/chromium/components/password_manager/core/browser/test_password_store.h
+++ b/chromium/components/password_manager/core/browser/test_password_store.h
@@ -53,10 +53,12 @@ class TestPasswordStore : public PasswordStore {
std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) override;
bool FillBlacklistLogins(
std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) override;
-
- // Unused portions of PasswordStore interface
std::vector<std::unique_ptr<autofill::PasswordForm>>
FillLoginsForSameOrganizationName(const std::string& signon_realm) override;
+ std::vector<InteractionsStats> GetSiteStatsImpl(
+ const GURL& origin_domain) override;
+
+ // Unused portions of PasswordStore interface
void ReportMetricsImpl(const std::string& sync_username,
bool custom_passphrase_sync_enabled) override;
PasswordStoreChangeList RemoveLoginsByURLAndTimeImpl(
@@ -78,8 +80,6 @@ class TestPasswordStore : public PasswordStore {
void AddSiteStatsImpl(const InteractionsStats& stats) override;
void RemoveSiteStatsImpl(const GURL& origin_domain) override;
std::vector<InteractionsStats> GetAllSiteStatsImpl() override;
- std::vector<InteractionsStats> GetSiteStatsImpl(
- const GURL& origin_domain) override;
private:
PasswordMap stored_passwords_;
diff --git a/chromium/components/password_manager/core/browser/ui/export_flow.h b/chromium/components/password_manager/core/browser/ui/export_flow.h
index 62b827dfa13..b445cfc4719 100644
--- a/chromium/components/password_manager/core/browser/ui/export_flow.h
+++ b/chromium/components/password_manager/core/browser/ui/export_flow.h
@@ -5,13 +5,24 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_EXPORT_FLOW_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_EXPORT_FLOW_H_
+#include "components/password_manager/core/browser/ui/export_progress_status.h"
+
namespace password_manager {
// This represents the controller for the UI flow of exporting passwords.
class ExportFlow {
public:
- // Store exported passwords to the export destination.
- virtual void Store() = 0;
+ // Store exported passwords to the export destination. If an export is already
+ // in progress this will do nothing and return false.
+ virtual bool Store() = 0;
+
+ // Cancel any previous Store() request and restore the state of the
+ // filesystem. The cancellation request may come a few seconds after Store()
+ // is completely finished.
+ virtual void CancelStore() = 0;
+
+ // Get the status of the export, which was initiated by Store().
+ virtual password_manager::ExportProgressStatus GetExportProgressStatus() = 0;
protected:
virtual ~ExportFlow() {}
diff --git a/chromium/components/password_manager/core/browser/ui/export_progress_status.h b/chromium/components/password_manager/core/browser/ui/export_progress_status.h
new file mode 100644
index 00000000000..df6cb23666e
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/ui/export_progress_status.h
@@ -0,0 +1,20 @@
+// 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_PASSWORD_MANAGER_CORE_BROWSER_UI_EXPORT_PROGRESS_STATUS_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_EXPORT_PROGRESS_STATUS_H_
+
+namespace password_manager {
+
+enum class ExportProgressStatus {
+ NOT_STARTED,
+ IN_PROGRESS,
+ SUCCEEDED,
+ FAILED_CANCELLED,
+ FAILED_WRITE_FAILED
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_EXPORT_PROGRESS_STATUS_H_
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 b7d2818cbf3..8c5e0c50126 100644
--- a/chromium/components/password_manager/core/common/password_manager_features.cc
+++ b/chromium/components/password_manager/core/common/password_manager_features.cc
@@ -4,8 +4,6 @@
#include "components/password_manager/core/common/password_manager_features.h"
-#include "build/build_config.h"
-
namespace password_manager {
namespace features {
@@ -17,8 +15,8 @@ const base::Feature kAffiliationBasedMatching = {
"AffiliationBasedMatching", base::FEATURE_ENABLED_BY_DEFAULT};
// Use HTML based username detector.
-const base::Feature kEnableHtmlBasedUsernameDetector = {
- "EnableHtmlBaseUsernameDetector", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kHtmlBasedUsernameDetector = {
+ "HtmlBaseUsernameDetector", base::FEATURE_ENABLED_BY_DEFAULT};
// Enable additional elements in the form popup UI, which will allow the user to
// view all saved passwords.
@@ -27,8 +25,8 @@ const base::Feature kEnableManualFallbacksGeneration = {
// Enable additional elements in the form popup UI, which will allow the user to
// trigger generation or view all saved passwords.
-const base::Feature kEnableManualFallbacksFilling = {
- "EnableManualFallbacksFilling", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kManualFallbacksFilling = {
+ "ManualFallbacksFilling", base::FEATURE_DISABLED_BY_DEFAULT};
// Enable a standalone popup UI, which will allow the user to view all saved
// passwords.
@@ -39,7 +37,7 @@ const base::Feature kEnableManualFallbacksFillingStandalone = {
// Enable that an omnibox icon is shown when the user types into a password
// field. When the user clicks on the icon, a password save/update bubble is
// shown.
-const base::Feature kEnableManualSaving = {"EnableManualSaving",
+const base::Feature kManualSaving = {"ManualSaving",
base::FEATURE_ENABLED_BY_DEFAULT};
// Enable a context menu item in the password field that allows the user
@@ -67,17 +65,15 @@ const base::Feature kProtectSyncCredentialOnReauth = {
// Controls the ability to export passwords from Chrome's settings page.
const base::Feature kPasswordExport = {"PasswordExport",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Controls the ability to import passwords from Chrome's settings page.
const base::Feature kPasswordImport = {"PasswordImport",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Control whether users can view and copy passwords. This is only used for
-// mobile, the desktop version of Chrome always allows users to view
-// passwords.
-const base::Feature kViewPasswords = {"ViewPasswords",
- base::FEATURE_ENABLED_BY_DEFAULT};
+// Allows searching for saved passwords in the settings page on mobile devices.
+const base::Feature kPasswordSearchMobile = {"PasswordSearchMobile",
+ base::FEATURE_DISABLED_BY_DEFAULT};
// Enables the experiment for the password manager to only fill on account
// selection, rather than autofilling on page load, with highlighting of fields.
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 cd495b9fd9e..d7d4029c03d 100644
--- a/chromium/components/password_manager/core/common/password_manager_features.h
+++ b/chromium/components/password_manager/core/common/password_manager_features.h
@@ -18,20 +18,20 @@ namespace features {
// alongside the definition of their values in the .cc file.
extern const base::Feature kAffiliationBasedMatching;
-extern const base::Feature kEnableHtmlBasedUsernameDetector;
-extern const base::Feature kEnableManualFallbacksFilling;
+extern const base::Feature kHtmlBasedUsernameDetector;
+extern const base::Feature kManualFallbacksFilling;
extern const base::Feature kEnableManualFallbacksFillingStandalone;
extern const base::Feature kEnableManualFallbacksGeneration;
extern const base::Feature kEnableManualPasswordGeneration;
-extern const base::Feature kEnableManualSaving;
+extern const base::Feature kManualSaving;
extern const base::Feature kPasswordForceSaving;
extern const base::Feature kEnableShowAllSavedPasswordsContextMenu;
extern const base::Feature kFillOnAccountSelect;
extern const base::Feature kPasswordExport;
extern const base::Feature kPasswordImport;
+extern const base::Feature kPasswordSearchMobile;
extern const base::Feature kProtectSyncCredential;
extern const base::Feature kProtectSyncCredentialOnReauth;
-extern const base::Feature kViewPasswords;
} // namespace features
diff --git a/chromium/components/password_manager/sync/browser/sync_credentials_filter.cc b/chromium/components/password_manager/sync/browser/sync_credentials_filter.cc
index 73300eeaabe..ce09894033d 100644
--- a/chromium/components/password_manager/sync/browser/sync_credentials_filter.cc
+++ b/chromium/components/password_manager/sync/browser/sync_credentials_filter.cc
@@ -14,7 +14,6 @@
#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/password_manager/sync/browser/password_sync_util.h"
-#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/base/url_util.h"
@@ -65,7 +64,7 @@ std::vector<std::unique_ptr<PasswordForm>> SyncCredentialsFilter::FilterResults(
auto begin_of_removed =
std::partition(results.begin(), results.end(),
[this](const std::unique_ptr<PasswordForm>& form) {
- return ShouldSave(*form, form->origin);
+ return ShouldSave(*form);
});
UMA_HISTOGRAM_BOOLEAN("PasswordManager.SyncCredentialFiltered",
@@ -76,12 +75,11 @@ std::vector<std::unique_ptr<PasswordForm>> SyncCredentialsFilter::FilterResults(
return results;
}
-bool SyncCredentialsFilter::ShouldSave(const autofill::PasswordForm& form,
- const GURL& main_frame_url) const {
- return !gaia::ShouldSkipSavePasswordForGaiaURL(main_frame_url) &&
- !sync_util::IsSyncAccountCredential(
- form, sync_service_factory_function_.Run(),
- signin_manager_factory_function_.Run());
+bool SyncCredentialsFilter::ShouldSave(
+ const autofill::PasswordForm& form) const {
+ return !sync_util::IsSyncAccountCredential(
+ form, sync_service_factory_function_.Run(),
+ signin_manager_factory_function_.Run());
}
void SyncCredentialsFilter::ReportFormLoginSuccess(
diff --git a/chromium/components/password_manager/sync/browser/sync_credentials_filter.h b/chromium/components/password_manager/sync/browser/sync_credentials_filter.h
index 9a40d511e62..ecabd5e0ae4 100644
--- a/chromium/components/password_manager/sync/browser/sync_credentials_filter.h
+++ b/chromium/components/password_manager/sync/browser/sync_credentials_filter.h
@@ -43,8 +43,7 @@ class SyncCredentialsFilter : public CredentialsFilter {
std::vector<std::unique_ptr<autofill::PasswordForm>> FilterResults(
std::vector<std::unique_ptr<autofill::PasswordForm>> results)
const override;
- bool ShouldSave(const autofill::PasswordForm& form,
- const GURL& main_frame_url) const override;
+ bool ShouldSave(const autofill::PasswordForm& form) const override;
void ReportFormLoginSuccess(
const PasswordFormManager& form_manager) const override;
diff --git a/chromium/components/password_manager/sync/browser/sync_credentials_filter_unittest.cc b/chromium/components/password_manager/sync/browser/sync_credentials_filter_unittest.cc
index 0e4b743e4ba..a6a3759f930 100644
--- a/chromium/components/password_manager/sync/browser/sync_credentials_filter_unittest.cc
+++ b/chromium/components/password_manager/sync/browser/sync_credentials_filter_unittest.cc
@@ -28,7 +28,6 @@
#include "components/password_manager/core/browser/stub_password_manager_driver.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/password_manager/sync/browser/sync_username_test_base.h"
-#include "google_apis/gaia/gaia_urls.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -340,7 +339,7 @@ TEST_F(CredentialsFilterTest, ShouldSave_NotSyncCredential) {
ASSERT_NE("user@example.org",
signin_manager()->GetAuthenticatedAccountInfo().email);
SetSyncingPasswords(true);
- EXPECT_TRUE(filter_.ShouldSave(form, GURL("https://example.org")));
+ EXPECT_TRUE(filter_.ShouldSave(form));
}
TEST_F(CredentialsFilterTest, ShouldSave_SyncCredential) {
@@ -348,7 +347,7 @@ TEST_F(CredentialsFilterTest, ShouldSave_SyncCredential) {
FakeSigninAs("user@example.org");
SetSyncingPasswords(true);
- EXPECT_FALSE(filter_.ShouldSave(form, GURL("https://example.org")));
+ EXPECT_FALSE(filter_.ShouldSave(form));
}
TEST_F(CredentialsFilterTest, ShouldSave_SyncCredential_NotSyncingPasswords) {
@@ -356,13 +355,7 @@ TEST_F(CredentialsFilterTest, ShouldSave_SyncCredential_NotSyncingPasswords) {
FakeSigninAs("user@example.org");
SetSyncingPasswords(false);
- EXPECT_TRUE(filter_.ShouldSave(form, GURL("https://example.org")));
-}
-
-TEST_F(CredentialsFilterTest, ShouldSave_ChomeSigninURLForDice) {
- PasswordForm form = SimpleGaiaForm("user@gmail.com");
- EXPECT_FALSE(filter_.ShouldSave(
- form, GaiaUrls::GetInstance()->signin_chrome_sync_dice()));
+ EXPECT_TRUE(filter_.ShouldSave(form));
}
TEST_F(CredentialsFilterTest, ShouldFilterOneForm) {
diff --git a/chromium/components/patch_service/patch_service.cc b/chromium/components/patch_service/patch_service.cc
index b92536e167e..906ac79904e 100644
--- a/chromium/components/patch_service/patch_service.cc
+++ b/chromium/components/patch_service/patch_service.cc
@@ -32,8 +32,7 @@ std::unique_ptr<service_manager::Service> PatchService::CreateService() {
void PatchService::OnStart() {
ref_factory_.reset(new service_manager::ServiceContextRefFactory(
- base::Bind(&service_manager::ServiceContext::RequestQuit,
- base::Unretained(context()))));
+ context()->CreateQuitClosure()));
registry_.AddInterface(base::Bind(&OnFilePatcherRequest, ref_factory_.get()));
}
diff --git a/chromium/components/payments/content/BUILD.gn b/chromium/components/payments/content/BUILD.gn
index f836ea40e7a..325d6599b7f 100644
--- a/chromium/components/payments/content/BUILD.gn
+++ b/chromium/components/payments/content/BUILD.gn
@@ -46,13 +46,15 @@ static_library("content") {
# Files used by content and utility.
static_library("content_common") {
sources = [
- "web_app_manifest_section.cc",
- "web_app_manifest_section.h",
+ "web_app_manifest.cc",
+ "web_app_manifest.h",
]
}
static_library("utils") {
sources = [
+ "installable_payment_app_crawler.cc",
+ "installable_payment_app_crawler.h",
"manifest_verifier.cc",
"manifest_verifier.h",
"origin_security_checker.cc",
diff --git a/chromium/components/payments/content/android/payment_manifest_parser_android.cc b/chromium/components/payments/content/android/payment_manifest_parser_android.cc
index b951daea528..3463b7554da 100644
--- a/chromium/components/payments/content/android/payment_manifest_parser_android.cc
+++ b/chromium/components/payments/content/android/payment_manifest_parser_android.cc
@@ -11,6 +11,7 @@
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/bind.h"
+#include "base/callback.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
diff --git a/chromium/components/payments/content/installable_payment_app_crawler.cc b/chromium/components/payments/content/installable_payment_app_crawler.cc
new file mode 100644
index 00000000000..7114de62c79
--- /dev/null
+++ b/chromium/components/payments/content/installable_payment_app_crawler.cc
@@ -0,0 +1,187 @@
+// Copyright 2018 The Chromium Authors. All 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/installable_payment_app_crawler.h"
+
+#include <utility>
+
+#include "content/public/browser/browser_thread.h"
+#include "url/gurl.h"
+
+namespace payments {
+
+// TODO(crbug.com/782270): Use cache to accelerate crawling procedure.
+// TODO(crbug.com/782270): Add integration tests for this class.
+InstallablePaymentAppCrawler::InstallablePaymentAppCrawler(
+ PaymentManifestDownloader* downloader,
+ PaymentManifestParser* parser,
+ PaymentManifestWebDataService* cache)
+ : downloader_(downloader),
+ parser_(parser),
+ number_of_payment_method_manifest_to_download_(0),
+ number_of_payment_method_manifest_to_parse_(0),
+ number_of_web_app_manifest_to_download_(0),
+ number_of_web_app_manifest_to_parse_(0),
+ weak_ptr_factory_(this) {}
+
+InstallablePaymentAppCrawler::~InstallablePaymentAppCrawler() {}
+
+void InstallablePaymentAppCrawler::Start(
+ const std::vector<mojom::PaymentMethodDataPtr>& requested_method_data,
+ FinishedCrawlingCallback callback,
+ base::OnceClosure finished_using_resources) {
+ callback_ = std::move(callback);
+ finished_using_resources_ = std::move(finished_using_resources);
+
+ std::set<GURL> manifests_to_download;
+ for (const auto& method_data : requested_method_data) {
+ for (const auto& method_name : method_data->supported_methods) {
+ if (!base::IsStringUTF8(method_name))
+ continue;
+ GURL url = GURL(method_name);
+ if (url.is_valid()) {
+ manifests_to_download.insert(url);
+ }
+ }
+ }
+
+ if (manifests_to_download.empty()) {
+ // Post the result back asynchronously.
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &InstallablePaymentAppCrawler::FinishCrawlingPaymentAppsIfReady,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
+ }
+
+ number_of_payment_method_manifest_to_download_ = manifests_to_download.size();
+ for (const auto& url : manifests_to_download) {
+ downloader_->DownloadPaymentMethodManifest(
+ url,
+ base::BindOnce(
+ &InstallablePaymentAppCrawler::OnPaymentMethodManifestDownloaded,
+ weak_ptr_factory_.GetWeakPtr(), url));
+ }
+}
+
+void InstallablePaymentAppCrawler::OnPaymentMethodManifestDownloaded(
+ const GURL& method_manifest_url,
+ const std::string& content) {
+ number_of_payment_method_manifest_to_download_--;
+ if (content.empty()) {
+ FinishCrawlingPaymentAppsIfReady();
+ return;
+ }
+
+ number_of_payment_method_manifest_to_parse_++;
+ parser_->ParsePaymentMethodManifest(
+ content, base::BindOnce(
+ &InstallablePaymentAppCrawler::OnPaymentMethodManifestParsed,
+ weak_ptr_factory_.GetWeakPtr(), method_manifest_url));
+}
+
+void InstallablePaymentAppCrawler::OnPaymentMethodManifestParsed(
+ const GURL& method_manifest_url,
+ const std::vector<GURL>& default_applications,
+ const std::vector<url::Origin>& supported_origins,
+ bool all_origins_supported) {
+ number_of_payment_method_manifest_to_parse_--;
+
+ for (const auto& url : default_applications) {
+ if (downloaded_web_app_manifests_.find(url) !=
+ downloaded_web_app_manifests_.end()) {
+ // Do not download the same web app manifest again since a web app could
+ // be the default application of multiple payment methods.
+ continue;
+ }
+
+ number_of_web_app_manifest_to_download_++;
+ downloaded_web_app_manifests_.insert(url);
+ downloader_->DownloadWebAppManifest(
+ url,
+ base::BindOnce(
+ &InstallablePaymentAppCrawler::OnPaymentWebAppManifestDownloaded,
+ weak_ptr_factory_.GetWeakPtr(), method_manifest_url, url));
+ }
+
+ FinishCrawlingPaymentAppsIfReady();
+}
+
+void InstallablePaymentAppCrawler::OnPaymentWebAppManifestDownloaded(
+ const GURL& method_manifest_url,
+ const GURL& web_app_manifest_url,
+ const std::string& content) {
+ number_of_web_app_manifest_to_download_--;
+ if (content.empty()) {
+ FinishCrawlingPaymentAppsIfReady();
+ return;
+ }
+
+ number_of_web_app_manifest_to_parse_++;
+ parser_->ParseWebAppInstallationInfo(
+ content,
+ base::BindOnce(
+ &InstallablePaymentAppCrawler::OnPaymentWebAppInstallationInfo,
+ weak_ptr_factory_.GetWeakPtr(), method_manifest_url,
+ web_app_manifest_url));
+}
+
+void InstallablePaymentAppCrawler::OnPaymentWebAppInstallationInfo(
+ const GURL& method_manifest_url,
+ const GURL& web_app_manifest_url,
+ std::unique_ptr<WebAppInstallationInfo> app_info) {
+ number_of_web_app_manifest_to_parse_--;
+
+ if (app_info != nullptr) {
+ if (app_info->sw_js_url.empty() ||
+ !base::IsStringUTF8(app_info->sw_js_url)) {
+ FinishCrawlingPaymentAppsIfReady();
+ LOG(ERROR) << "The installable payment app's js url is not a non-empty "
+ "UTF8 string.";
+ return;
+ }
+
+ // Check and complete relative url.
+ if (!GURL(app_info->sw_js_url).is_valid()) {
+ GURL absolute_url = web_app_manifest_url.Resolve(app_info->sw_js_url);
+ if (!absolute_url.is_valid()) {
+ LOG(ERROR) << "Failed to resolve the installable payment app's js url.";
+ FinishCrawlingPaymentAppsIfReady();
+ return;
+ }
+ app_info->sw_js_url = absolute_url.spec();
+ }
+
+ if (!GURL(app_info->sw_scope).is_valid()) {
+ GURL absolute_scope =
+ web_app_manifest_url.GetWithoutFilename().Resolve(app_info->sw_scope);
+ if (!absolute_scope.is_valid()) {
+ LOG(ERROR) << "Failed to resolve the installable payment app's "
+ "registration scope.";
+ FinishCrawlingPaymentAppsIfReady();
+ return;
+ }
+ app_info->sw_scope = absolute_scope.spec();
+ }
+
+ installable_apps_[method_manifest_url] = std::move(app_info);
+ }
+
+ FinishCrawlingPaymentAppsIfReady();
+}
+
+void InstallablePaymentAppCrawler::FinishCrawlingPaymentAppsIfReady() {
+ if (number_of_payment_method_manifest_to_download_ != 0 ||
+ number_of_payment_method_manifest_to_parse_ != 0 ||
+ number_of_web_app_manifest_to_download_ != 0 ||
+ number_of_web_app_manifest_to_parse_ != 0) {
+ return;
+ }
+
+ std::move(callback_).Run(std::move(installable_apps_));
+ std::move(finished_using_resources_).Run();
+}
+
+} // namespace payments.
diff --git a/chromium/components/payments/content/installable_payment_app_crawler.h b/chromium/components/payments/content/installable_payment_app_crawler.h
new file mode 100644
index 00000000000..1fcfecb9ede
--- /dev/null
+++ b/chromium/components/payments/content/installable_payment_app_crawler.h
@@ -0,0 +1,89 @@
+// Copyright 2018 The Chromium Authors. All 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_INSTALLABLE_PAYMENT_APP_CRAWLER_H_
+#define COMPONENTS_PAYMENTS_CONTENT_INSTALLABLE_PAYMENT_APP_CRAWLER_H_
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "components/payments/content/manifest_verifier.h"
+#include "components/payments/content/payment_manifest_web_data_service.h"
+#include "components/payments/content/utility/payment_manifest_parser.h"
+#include "components/payments/content/web_app_manifest.h"
+#include "components/payments/core/payment_manifest_downloader.h"
+#include "third_party/WebKit/public/platform/modules/payments/payment_request.mojom.h"
+
+class GURL;
+
+namespace payments {
+
+// Crawls installable web payment apps. First, fetches and parses the payment
+// method manifests to get 'default_applications' manifest urls. Then, fetches
+// and parses the web app manifests to get the installable payment apps' info.
+class InstallablePaymentAppCrawler {
+ public:
+ using FinishedCrawlingCallback = base::OnceCallback<void(
+ std::map<GURL, std::unique_ptr<WebAppInstallationInfo>>)>;
+
+ // The owner of InstallablePaymentAppCrawler owns |downloader|, |parser| and
+ // |cache|. They should live until |finished_using_resources| parameter to
+ // Start() method is called.
+ InstallablePaymentAppCrawler(PaymentManifestDownloader* downloader,
+ PaymentManifestParser* parser,
+ PaymentManifestWebDataService* cache);
+ ~InstallablePaymentAppCrawler();
+
+ // Starts the crawling process. All the url based payment methods in
+ // |request_method_data| will be crawled. A list of installable payment apps'
+ // info will be send back through |callback|. |finished_using_resources| is
+ // called after finished using the resources (downloader, parser and cache),
+ // then this object is safe to be deleted.
+ void Start(
+ const std::vector<mojom::PaymentMethodDataPtr>& requested_method_data,
+ FinishedCrawlingCallback callback,
+ base::OnceClosure finished_using_resources);
+
+ private:
+ void OnPaymentMethodManifestDownloaded(const GURL& method_manifest_url,
+ const std::string& content);
+ void OnPaymentMethodManifestParsed(
+ const GURL& method_manifest_url,
+ const std::vector<GURL>& default_applications,
+ const std::vector<url::Origin>& supported_origins,
+ bool all_origins_supported);
+ void OnPaymentWebAppManifestDownloaded(const GURL& method_manifest_url,
+ const GURL& web_app_manifest_url,
+ const std::string& content);
+ void OnPaymentWebAppInstallationInfo(
+ const GURL& method_manifest_url,
+ const GURL& web_app_manifest_url,
+ std::unique_ptr<WebAppInstallationInfo> app_info);
+ void FinishCrawlingPaymentAppsIfReady();
+
+ PaymentManifestDownloader* downloader_;
+ PaymentManifestParser* parser_;
+ FinishedCrawlingCallback callback_;
+ base::OnceClosure finished_using_resources_;
+
+ size_t number_of_payment_method_manifest_to_download_;
+ size_t number_of_payment_method_manifest_to_parse_;
+ size_t number_of_web_app_manifest_to_download_;
+ size_t number_of_web_app_manifest_to_parse_;
+ std::set<GURL> downloaded_web_app_manifests_;
+ std::map<GURL, std::unique_ptr<WebAppInstallationInfo>> installable_apps_;
+
+ base::WeakPtrFactory<InstallablePaymentAppCrawler> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(InstallablePaymentAppCrawler);
+};
+
+} // namespace payments.
+
+#endif // COMPONENTS_PAYMENTS_CONTENT_INSTALLABLE_PAYMENT_APP_CRAWLER_H_
diff --git a/chromium/components/payments/content/manifest_verifier.cc b/chromium/components/payments/content/manifest_verifier.cc
index 97485f0e308..b83fadf42d3 100644
--- a/chromium/components/payments/content/manifest_verifier.cc
+++ b/chromium/components/payments/content/manifest_verifier.cc
@@ -55,14 +55,13 @@ void EnableMethodManifestUrlForSupportedApps(
} // namespace
-ManifestVerifier::ManifestVerifier(
- content::WebContents* web_contents,
- std::unique_ptr<PaymentMethodManifestDownloaderInterface> downloader,
- std::unique_ptr<PaymentManifestParser> parser,
- scoped_refptr<PaymentManifestWebDataService> cache)
+ManifestVerifier::ManifestVerifier(content::WebContents* web_contents,
+ PaymentManifestDownloader* downloader,
+ PaymentManifestParser* parser,
+ PaymentManifestWebDataService* cache)
: dev_tools_(web_contents),
- downloader_(std::move(downloader)),
- parser_(std::move(parser)),
+ downloader_(downloader),
+ parser_(parser),
cache_(cache),
number_of_manifests_to_verify_(0),
number_of_manifests_to_download_(0),
@@ -178,13 +177,29 @@ void ManifestVerifier::OnWebDataServiceRequestDone(
GURL method_manifest_url = it->second;
cache_request_handles_.erase(it);
- const std::vector<std::string>& supported_origin_strings =
+ const std::vector<std::string>& cached_strings =
(static_cast<const WDResult<std::vector<std::string>>*>(result.get()))
->GetValue();
- bool all_origins_supported = std::find(supported_origin_strings.begin(),
- supported_origin_strings.end(),
- kAllOriginsSupportedIndicator) !=
- supported_origin_strings.end();
+
+ bool all_origins_supported = false;
+ std::vector<std::string> native_app_ids;
+ std::vector<std::string> supported_origin_strings;
+ for (const auto& origin_or_id : cached_strings) {
+ // The string could be "*", origin or native payment app package Id on
+ // Android.
+ if (origin_or_id == kAllOriginsSupportedIndicator) {
+ all_origins_supported = true;
+ continue;
+ }
+
+ if (base::IsStringUTF8(origin_or_id) && GURL(origin_or_id).is_valid()) {
+ supported_origin_strings.emplace_back(origin_or_id);
+ } else {
+ native_app_ids.emplace_back(origin_or_id);
+ }
+ }
+ cached_supported_native_app_ids_[method_manifest_url] = native_app_ids;
+
EnableMethodManifestUrlForSupportedApps(
method_manifest_url, supported_origin_strings, all_origins_supported,
manifest_url_to_app_origins_map_[method_manifest_url], &apps_,
@@ -256,6 +271,15 @@ void ManifestVerifier::OnPaymentMethodManifestParsed(
if (all_origins_supported)
supported_origin_strings.emplace_back(kAllOriginsSupportedIndicator);
+
+ // Keep Android native payment app Ids in cache.
+ std::map<GURL, std::vector<std::string>>::const_iterator it =
+ cached_supported_native_app_ids_.find(method_manifest_url);
+ if (it != cached_supported_native_app_ids_.end()) {
+ supported_origin_strings.insert(supported_origin_strings.end(),
+ it->second.begin(), it->second.end());
+ }
+
cache_->AddPaymentMethodManifest(method_manifest_url.spec(),
supported_origin_strings);
diff --git a/chromium/components/payments/content/manifest_verifier.h b/chromium/components/payments/content/manifest_verifier.h
index a8bdaac98ab..c3d57719e85 100644
--- a/chromium/components/payments/content/manifest_verifier.h
+++ b/chromium/components/payments/content/manifest_verifier.h
@@ -32,9 +32,9 @@ class Origin;
namespace payments {
+class PaymentManifestDownloader;
class PaymentManifestParser;
class PaymentManifestWebDataService;
-class PaymentMethodManifestDownloaderInterface;
// Verifies that payment handlers (i.e., service worker payment apps) can use
// the payment method names that they claim. Each object can be used to verify
@@ -55,11 +55,13 @@ class ManifestVerifier final : public WebDataServiceConsumer {
base::OnceCallback<void(content::PaymentAppProvider::PaymentApps)>;
// Creates the verifier and starts up the parser utility process.
- ManifestVerifier(
- content::WebContents* web_contents,
- std::unique_ptr<PaymentMethodManifestDownloaderInterface> downloader,
- std::unique_ptr<PaymentManifestParser> parser,
- scoped_refptr<PaymentManifestWebDataService> cache);
+ // The owner of ManifestVerifier owns |downloader|, |parser| and
+ // |cache|. They should live until |finished_using_resources| parameter to
+ // Verify() method is called.
+ ManifestVerifier(content::WebContents* web_contents,
+ PaymentManifestDownloader* downloader,
+ PaymentManifestParser* parser,
+ PaymentManifestWebDataService* cache);
~ManifestVerifier() override;
@@ -100,13 +102,13 @@ class ManifestVerifier final : public WebDataServiceConsumer {
DevToolsHelper dev_tools_;
// Downloads the manifests.
- std::unique_ptr<PaymentMethodManifestDownloaderInterface> downloader_;
+ PaymentManifestDownloader* downloader_;
// Parses the manifests.
- std::unique_ptr<PaymentManifestParser> parser_;
+ PaymentManifestParser* parser_;
// Caches the manifests.
- scoped_refptr<PaymentManifestWebDataService> cache_;
+ PaymentManifestWebDataService* cache_;
// The list of payment apps being verified.
content::PaymentAppProvider::PaymentApps apps_;
@@ -134,6 +136,12 @@ class ManifestVerifier final : public WebDataServiceConsumer {
// used.
std::set<GURL> cached_manifest_urls_;
+ // The mapping of payment method names to cached native payment app Ids.
+ // Note that the supported native payment app Ids have been cached for a
+ // payment method in the same cache in PaymentManifestVerifier.java. Do not
+ // override them since we do not refresh them in this class.
+ std::map<GURL, std::vector<std::string>> cached_supported_native_app_ids_;
+
// The number of manifests that have not been verified yet. A manifest can be
// either be retrieved from cache or downloaded for verification. Once this
// number reaches 0, the verification callback is invoked.
diff --git a/chromium/components/payments/content/origin_security_checker.h b/chromium/components/payments/content/origin_security_checker.h
index 818188d321c..12c227bd255 100644
--- a/chromium/components/payments/content/origin_security_checker.h
+++ b/chromium/components/payments/content/origin_security_checker.h
@@ -17,7 +17,7 @@ class OriginSecurityChecker {
static bool IsOriginSecure(const GURL& url);
// Returns true for a valid |url| with a cryptographic scheme, e.g., HTTPS,
- // HTTPS-SO, WSS.
+ // WSS.
static bool IsSchemeCryptographic(const GURL& url);
// Returns true for a valid |url| with localhost or file:// scheme origin.
diff --git a/chromium/components/payments/content/payment_manifest_web_data_service.h b/chromium/components/payments/content/payment_manifest_web_data_service.h
index aa1cb838c29..a57a7645b1e 100644
--- a/chromium/components/payments/content/payment_manifest_web_data_service.h
+++ b/chromium/components/payments/content/payment_manifest_web_data_service.h
@@ -9,7 +9,7 @@
#include <vector>
#include "base/memory/ref_counted.h"
-#include "components/payments/content/web_app_manifest_section.h"
+#include "components/payments/content/web_app_manifest.h"
#include "components/webdata/common/web_data_service_base.h"
#include "components/webdata/common/web_database.h"
diff --git a/chromium/components/payments/content/payment_request.cc b/chromium/components/payments/content/payment_request.cc
index 0e952d71a93..d253cc5d641 100644
--- a/chromium/components/payments/content/payment_request.cc
+++ b/chromium/components/payments/content/payment_request.cc
@@ -348,6 +348,10 @@ void PaymentRequest::HideIfNecessary() {
display_handle_.reset();
}
+bool PaymentRequest::IsIncognito() const {
+ return delegate_->IsIncognito();
+}
+
void PaymentRequest::RecordFirstAbortReason(
JourneyLogger::AbortReason abort_reason) {
if (!has_recorded_completion_) {
diff --git a/chromium/components/payments/content/payment_request.h b/chromium/components/payments/content/payment_request.h
index 2fea03885e4..30a7c5564dd 100644
--- a/chromium/components/payments/content/payment_request.h
+++ b/chromium/components/payments/content/payment_request.h
@@ -101,6 +101,8 @@ class PaymentRequest : public mojom::PaymentRequest,
// Hide this Payment Request if it's already showing.
void HideIfNecessary();
+ bool IsIncognito() const;
+
content::WebContents* web_contents() { return web_contents_; }
PaymentRequestSpec* spec() { return spec_.get(); }
diff --git a/chromium/components/payments/content/payment_request_spec.cc b/chromium/components/payments/content/payment_request_spec.cc
index 5e4a1412c04..8b48157fd4a 100644
--- a/chromium/components/payments/content/payment_request_spec.cc
+++ b/chromium/components/payments/content/payment_request_spec.cc
@@ -189,7 +189,7 @@ const mojom::PaymentItemPtr& PaymentRequestSpec::GetTotal(
PaymentInstrument* selected_instrument) const {
const mojom::PaymentDetailsModifierPtr* modifier =
GetApplicableModifier(selected_instrument);
- return modifier ? (*modifier)->total : details_->total;
+ return modifier && (*modifier)->total ? (*modifier)->total : details_->total;
}
std::vector<const mojom::PaymentItemPtr*> PaymentRequestSpec::GetDisplayItems(
diff --git a/chromium/components/payments/content/payment_request_state.cc b/chromium/components/payments/content/payment_request_state.cc
index 3dd4c37a94d..a3923fb1758 100644
--- a/chromium/components/payments/content/payment_request_state.cc
+++ b/chromium/components/payments/content/payment_request_state.cc
@@ -18,7 +18,6 @@
#include "components/payments/content/content_payment_request_delegate.h"
#include "components/payments/content/payment_manifest_web_data_service.h"
#include "components/payments/content/payment_response_helper.h"
-#include "components/payments/content/service_worker_payment_app_factory.h"
#include "components/payments/content/service_worker_payment_instrument.h"
#include "components/payments/core/autofill_payment_instrument.h"
#include "components/payments/core/journey_logger.h"
@@ -61,9 +60,8 @@ PaymentRequestState::PaymentRequestState(
payment_request_delegate_->GetPaymentManifestWebDataService(),
spec_->method_data(),
base::BindOnce(&PaymentRequestState::GetAllPaymentAppsCallback,
- weak_ptr_factory_.GetWeakPtr(),
- web_contents->GetBrowserContext(), top_level_origin,
- frame_origin),
+ weak_ptr_factory_.GetWeakPtr(), web_contents,
+ top_level_origin, frame_origin),
base::BindOnce([]() {
/* Nothing needs to be done after writing cache. This callback is used
* only in tests. */
@@ -78,11 +76,13 @@ PaymentRequestState::PaymentRequestState(
PaymentRequestState::~PaymentRequestState() {}
void PaymentRequestState::GetAllPaymentAppsCallback(
- content::BrowserContext* context,
+ content::WebContents* web_contents,
const GURL& top_level_origin,
const GURL& frame_origin,
- content::PaymentAppProvider::PaymentApps apps) {
- number_of_pending_sw_payment_instruments_ = apps.size();
+ content::PaymentAppProvider::PaymentApps apps,
+ ServiceWorkerPaymentAppFactory::InstallablePaymentApps installable_apps) {
+ number_of_pending_sw_payment_instruments_ =
+ apps.size() + installable_apps.size();
if (number_of_pending_sw_payment_instruments_ == 0U) {
FinishedGetAllSWPaymentInstruments();
return;
@@ -91,8 +91,20 @@ void PaymentRequestState::GetAllPaymentAppsCallback(
for (auto& app : apps) {
std::unique_ptr<ServiceWorkerPaymentInstrument> instrument =
std::make_unique<ServiceWorkerPaymentInstrument>(
- context, top_level_origin, frame_origin, spec_,
- std::move(app.second), payment_request_delegate_);
+ web_contents->GetBrowserContext(), top_level_origin, frame_origin,
+ spec_, std::move(app.second), payment_request_delegate_);
+ instrument->ValidateCanMakePayment(
+ base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated,
+ weak_ptr_factory_.GetWeakPtr()));
+ available_instruments_.push_back(std::move(instrument));
+ }
+
+ for (auto& installable_app : installable_apps) {
+ std::unique_ptr<ServiceWorkerPaymentInstrument> instrument =
+ std::make_unique<ServiceWorkerPaymentInstrument>(
+ web_contents, top_level_origin, frame_origin, spec_,
+ std::move(installable_app.second), installable_app.first.spec(),
+ payment_request_delegate_);
instrument->ValidateCanMakePayment(
base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated,
weak_ptr_factory_.GetWeakPtr()));
diff --git a/chromium/components/payments/content/payment_request_state.h b/chromium/components/payments/content/payment_request_state.h
index a8791265793..3e7a29e5b63 100644
--- a/chromium/components/payments/content/payment_request_state.h
+++ b/chromium/components/payments/content/payment_request_state.h
@@ -14,6 +14,7 @@
#include "components/autofill/core/browser/address_normalizer.h"
#include "components/payments/content/payment_request_spec.h"
#include "components/payments/content/payment_response_helper.h"
+#include "components/payments/content/service_worker_payment_app_factory.h"
#include "components/payments/core/payments_profile_comparator.h"
#include "content/public/browser/payment_app_provider.h"
#include "content/public/browser/web_contents.h"
@@ -227,10 +228,12 @@ class PaymentRequestState : public PaymentResponseHelper::Delegate,
bool ArePaymentOptionsSatisfied();
// The PaymentAppProvider::GetAllPaymentAppsCallback.
- void GetAllPaymentAppsCallback(content::BrowserContext* context,
- const GURL& top_level_origin,
- const GURL& frame_origin,
- content::PaymentAppProvider::PaymentApps apps);
+ void GetAllPaymentAppsCallback(
+ content::WebContents* web_contents,
+ const GURL& top_level_origin,
+ const GURL& frame_origin,
+ content::PaymentAppProvider::PaymentApps apps,
+ ServiceWorkerPaymentAppFactory::InstallablePaymentApps installable_apps);
// The ServiceWorkerPaymentInstrument::ValidateCanMakePaymentCallback.
void OnSWPaymentInstrumentValidated(
diff --git a/chromium/components/payments/content/service_worker_payment_app_factory.cc b/chromium/components/payments/content/service_worker_payment_app_factory.cc
index 9a1e3d89c81..e959d324eb8 100644
--- a/chromium/components/payments/content/service_worker_payment_app_factory.cc
+++ b/chromium/components/payments/content/service_worker_payment_app_factory.cc
@@ -11,6 +11,8 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/payments/content/installable_payment_app_crawler.h"
#include "components/payments/content/manifest_verifier.h"
#include "components/payments/content/payment_manifest_web_data_service.h"
#include "components/payments/content/utility/payment_manifest_parser.h"
@@ -97,35 +99,33 @@ class SelfDeletingServiceWorkerPaymentAppFactory {
// until |finished_using_resources_callback| has run.
void GetAllPaymentApps(
content::WebContents* web_contents,
- std::unique_ptr<PaymentMethodManifestDownloaderInterface> downloader,
+ std::unique_ptr<PaymentManifestDownloader> downloader,
scoped_refptr<PaymentManifestWebDataService> cache,
const std::vector<mojom::PaymentMethodDataPtr>& requested_method_data,
- content::PaymentAppProvider::GetAllPaymentAppsCallback callback,
+ ServiceWorkerPaymentAppFactory::GetAllPaymentAppsCallback callback,
base::OnceClosure finished_using_resources_callback) {
DCHECK(!verifier_);
+ downloader_ = std::move(downloader);
+ parser_ = std::make_unique<PaymentManifestParser>();
+ cache_ = cache;
verifier_ = std::make_unique<ManifestVerifier>(
- web_contents, std::move(downloader),
- std::make_unique<PaymentManifestParser>(), cache);
+ web_contents, downloader_.get(), parser_.get(), cache_.get());
// Method data cannot be copied and is passed in as a const-ref, which
- // cannot be moved, so make a manual copy for moving into the callback
- // below.
- std::vector<mojom::PaymentMethodDataPtr> requested_method_data_copy;
- for (const auto& request : requested_method_data) {
- requested_method_data_copy.emplace_back(request.Clone());
+ // cannot be moved, so make a manual copy for using below.
+ for (const auto& method_data : requested_method_data) {
+ requested_method_data_.emplace_back(method_data.Clone());
}
+ callback_ = std::move(callback);
+ finished_using_resources_callback_ =
+ std::move(finished_using_resources_callback);
content::PaymentAppProvider::GetInstance()->GetAllPaymentApps(
web_contents->GetBrowserContext(),
base::BindOnce(
&SelfDeletingServiceWorkerPaymentAppFactory::OnGotAllPaymentApps,
- base::Unretained(this), std::move(requested_method_data_copy),
- std::move(callback),
- base::BindOnce(&SelfDeletingServiceWorkerPaymentAppFactory::
- OnPaymentAppsVerifierFinishedUsingResources,
- base::Owned(this),
- std::move(finished_using_resources_callback))));
+ base::Unretained(this)));
}
void IgnorePortInAppScopeForTesting() {
@@ -134,35 +134,100 @@ class SelfDeletingServiceWorkerPaymentAppFactory {
private:
void OnGotAllPaymentApps(
- const std::vector<mojom::PaymentMethodDataPtr>& requested_method_data,
- content::PaymentAppProvider::GetAllPaymentAppsCallback callback,
- base::OnceClosure finished_using_resources_callback,
content::PaymentAppProvider::PaymentApps apps) {
if (ignore_port_in_app_scope_for_testing_)
RemovePortNumbersFromScopesForTest(&apps);
ServiceWorkerPaymentAppFactory::RemoveAppsWithoutMatchingMethodData(
- requested_method_data, &apps);
+ requested_method_data_, &apps);
if (apps.empty()) {
- std::move(callback).Run(std::move(apps));
- std::move(finished_using_resources_callback).Run();
+ OnPaymentAppsVerified(std::move(apps));
+ OnPaymentAppsVerifierFinishedUsingResources();
return;
}
- // The |verifier_| will invoke |callback| with the list of all valid payment
- // apps. This list may be empty, if none of the apps were found to be valid.
- verifier_->Verify(std::move(apps), std::move(callback),
- std::move(finished_using_resources_callback));
+ // The |verifier_| will invoke |OnPaymentAppsVerified| with the list of all
+ // valid payment apps. This list may be empty, if none of the apps were
+ // found to be valid.
+ is_payment_verifier_finished_using_resources_ = false;
+ verifier_->Verify(
+ std::move(apps),
+ base::BindOnce(
+ &SelfDeletingServiceWorkerPaymentAppFactory::OnPaymentAppsVerified,
+ base::Unretained(this)),
+ base::BindOnce(&SelfDeletingServiceWorkerPaymentAppFactory::
+ OnPaymentAppsVerifierFinishedUsingResources,
+ base::Unretained(this)));
}
- void OnPaymentAppsVerifierFinishedUsingResources(
- base::OnceClosure finished_using_resources_callback) {
+ void OnPaymentAppsVerified(content::PaymentAppProvider::PaymentApps apps) {
+ if (apps.empty()) {
+ // Crawls installable web payment apps if no web payment apps have been
+ // installed.
+ crawler_ = std::make_unique<InstallablePaymentAppCrawler>(
+ downloader_.get(), parser_.get(), cache_.get());
+ is_payment_app_crawler_finished_using_resources_ = false;
+ crawler_->Start(
+ requested_method_data_,
+ base::BindOnce(
+ &SelfDeletingServiceWorkerPaymentAppFactory::OnPaymentAppsCrawled,
+ base::Unretained(this)),
+ base::BindOnce(&SelfDeletingServiceWorkerPaymentAppFactory::
+ OnPaymentAppsCrawlerFinishedUsingResources,
+ base::Unretained(this)));
+ return;
+ }
+
+ std::move(callback_).Run(
+ std::move(apps),
+ ServiceWorkerPaymentAppFactory::InstallablePaymentApps());
+ }
+
+ void OnPaymentAppsCrawled(
+ std::map<GURL, std::unique_ptr<WebAppInstallationInfo>> apps_info) {
+ std::move(callback_).Run(content::PaymentAppProvider::PaymentApps(),
+ std::move(apps_info));
+ }
+
+ void OnPaymentAppsCrawlerFinishedUsingResources() {
+ crawler_.reset();
+
+ is_payment_app_crawler_finished_using_resources_ = true;
+ FinishUsingResourcesIfReady();
+ }
+
+ void OnPaymentAppsVerifierFinishedUsingResources() {
verifier_.reset();
- std::move(finished_using_resources_callback).Run();
- // No need to self-delete here, because of using base::Owned(this).
+
+ is_payment_verifier_finished_using_resources_ = true;
+ FinishUsingResourcesIfReady();
}
+ void FinishUsingResourcesIfReady() {
+ if (is_payment_verifier_finished_using_resources_ &&
+ is_payment_app_crawler_finished_using_resources_ &&
+ !finished_using_resources_callback_.is_null()) {
+ downloader_.reset();
+ parser_.reset();
+ std::move(finished_using_resources_callback_).Run();
+
+ base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
+ }
+ }
+
+ std::unique_ptr<PaymentManifestDownloader> downloader_;
+ std::unique_ptr<PaymentManifestParser> parser_;
+ scoped_refptr<PaymentManifestWebDataService> cache_;
+ std::vector<mojom::PaymentMethodDataPtr> requested_method_data_;
+ ServiceWorkerPaymentAppFactory::GetAllPaymentAppsCallback callback_;
+ base::OnceClosure finished_using_resources_callback_;
+
std::unique_ptr<ManifestVerifier> verifier_;
+ bool is_payment_verifier_finished_using_resources_ = true;
+
+ std::unique_ptr<InstallablePaymentAppCrawler> crawler_;
+ bool is_payment_app_crawler_finished_using_resources_ = true;
+
bool ignore_port_in_app_scope_for_testing_ = false;
DISALLOW_COPY_AND_ASSIGN(SelfDeletingServiceWorkerPaymentAppFactory);
@@ -179,7 +244,7 @@ void ServiceWorkerPaymentAppFactory::GetAllPaymentApps(
content::WebContents* web_contents,
scoped_refptr<PaymentManifestWebDataService> cache,
const std::vector<mojom::PaymentMethodDataPtr>& requested_method_data,
- content::PaymentAppProvider::GetAllPaymentAppsCallback callback,
+ GetAllPaymentAppsCallback callback,
base::OnceClosure finished_writing_cache_callback_for_testing) {
SelfDeletingServiceWorkerPaymentAppFactory* self_delete_factory =
new SelfDeletingServiceWorkerPaymentAppFactory();
@@ -219,7 +284,7 @@ void ServiceWorkerPaymentAppFactory::RemoveAppsWithoutMatchingMethodData(
void ServiceWorkerPaymentAppFactory::
SetDownloaderAndIgnorePortInAppScopeForTesting(
- std::unique_ptr<PaymentMethodManifestDownloaderInterface> downloader) {
+ std::unique_ptr<PaymentManifestDownloader> downloader) {
test_downloader_ = std::move(downloader);
}
diff --git a/chromium/components/payments/content/service_worker_payment_app_factory.h b/chromium/components/payments/content/service_worker_payment_app_factory.h
index 48f2cc3da8d..e7bc1863f1f 100644
--- a/chromium/components/payments/content/service_worker_payment_app_factory.h
+++ b/chromium/components/payments/content/service_worker_payment_app_factory.h
@@ -5,29 +5,45 @@
#ifndef COMPONENTS_PAYMENTS_CONTENT_SERVICE_WORKER_PAYMENT_APP_FACTORY_H_
#define COMPONENTS_PAYMENTS_CONTENT_SERVICE_WORKER_PAYMENT_APP_FACTORY_H_
+#include <map>
#include <memory>
#include <set>
#include <string>
+#include "base/callback.h"
#include "base/macros.h"
+#include "components/payments/content/web_app_manifest.h"
#include "content/public/browser/payment_app_provider.h"
#include "third_party/WebKit/public/platform/modules/payments/payment_request.mojom.h"
+class GURL;
+
template <class T>
class scoped_refptr;
+namespace base {
+template <typename Type>
+struct DefaultSingletonTraits;
+} // namespace base
+
namespace content {
class WebContents;
} // namespace content
namespace payments {
+class PaymentManifestDownloader;
class PaymentManifestWebDataService;
-class PaymentMethodManifestDownloaderInterface;
// Retrieves service worker payment apps.
class ServiceWorkerPaymentAppFactory {
public:
+ using InstallablePaymentApps =
+ std::map<GURL, std::unique_ptr<WebAppInstallationInfo>>;
+ using GetAllPaymentAppsCallback =
+ base::OnceCallback<void(content::PaymentAppProvider::PaymentApps,
+ InstallablePaymentApps)>;
+
static ServiceWorkerPaymentAppFactory* GetInstance();
// Retrieves all service worker payment apps that can handle payments for
@@ -47,7 +63,7 @@ class ServiceWorkerPaymentAppFactory {
content::WebContents* web_contents,
scoped_refptr<PaymentManifestWebDataService> cache,
const std::vector<mojom::PaymentMethodDataPtr>& requested_method_data,
- content::PaymentAppProvider::GetAllPaymentAppsCallback callback,
+ GetAllPaymentAppsCallback callback,
base::OnceClosure finished_writing_cache_callback_for_testing);
// Removes |apps| that don't match any of the |requested_method_data| based on
@@ -68,9 +84,9 @@ class ServiceWorkerPaymentAppFactory {
// Should be called before every call to GetAllPaymentApps() (because the test
// downloader is moved into the SelfDeletingServiceWorkerPaymentAppFactory).
void SetDownloaderAndIgnorePortInAppScopeForTesting(
- std::unique_ptr<PaymentMethodManifestDownloaderInterface> downloader);
+ std::unique_ptr<PaymentManifestDownloader> downloader);
- std::unique_ptr<PaymentMethodManifestDownloaderInterface> test_downloader_;
+ std::unique_ptr<PaymentManifestDownloader> test_downloader_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPaymentAppFactory);
};
diff --git a/chromium/components/payments/content/service_worker_payment_instrument.cc b/chromium/components/payments/content/service_worker_payment_instrument.cc
index 9ef9fe2e6f9..01cc3317ea4 100644
--- a/chromium/components/payments/content/service_worker_payment_instrument.cc
+++ b/chromium/components/payments/content/service_worker_payment_instrument.cc
@@ -4,12 +4,14 @@
#include "components/payments/content/service_worker_payment_instrument.h"
+#include "base/bind_helpers.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/payments/content/payment_request_converter.h"
#include "components/payments/core/payment_request_delegate.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/payment_app_provider.h"
+#include "content/public/browser/web_contents.h"
#include "ui/gfx/image/image_skia.h"
namespace payments {
@@ -17,14 +19,14 @@ namespace payments {
// Service worker payment app provides icon through bitmap, so set 0 as invalid
// resource Id.
ServiceWorkerPaymentInstrument::ServiceWorkerPaymentInstrument(
- content::BrowserContext* context,
+ content::BrowserContext* browser_context,
const GURL& top_level_origin,
const GURL& frame_origin,
const PaymentRequestSpec* spec,
std::unique_ptr<content::StoredPaymentApp> stored_payment_app_info,
PaymentRequestDelegate* payment_request_delegate)
: PaymentInstrument(0, PaymentInstrument::Type::SERVICE_WORKER_APP),
- browser_context_(context),
+ browser_context_(browser_context),
top_level_origin_(top_level_origin),
frame_origin_(frame_origin),
spec_(spec),
@@ -32,6 +34,7 @@ ServiceWorkerPaymentInstrument::ServiceWorkerPaymentInstrument(
delegate_(nullptr),
payment_request_delegate_(payment_request_delegate),
can_make_payment_result_(false),
+ needs_installation_(false),
weak_ptr_factory_(this) {
DCHECK(browser_context_);
DCHECK(top_level_origin_.is_valid());
@@ -48,25 +51,65 @@ ServiceWorkerPaymentInstrument::ServiceWorkerPaymentInstrument(
}
}
+// Service worker payment app provides icon through bitmap, so set 0 as invalid
+// resource Id.
+ServiceWorkerPaymentInstrument::ServiceWorkerPaymentInstrument(
+ content::WebContents* web_contents,
+ const GURL& top_level_origin,
+ const GURL& frame_origin,
+ const PaymentRequestSpec* spec,
+ std::unique_ptr<WebAppInstallationInfo> installable_payment_app_info,
+ const std::string& enabled_method,
+ PaymentRequestDelegate* payment_request_delegate)
+ : PaymentInstrument(0, PaymentInstrument::Type::SERVICE_WORKER_APP),
+ top_level_origin_(top_level_origin),
+ frame_origin_(frame_origin),
+ spec_(spec),
+ delegate_(nullptr),
+ payment_request_delegate_(payment_request_delegate),
+ can_make_payment_result_(false),
+ needs_installation_(true),
+ web_contents_(web_contents),
+ installable_web_app_info_(std::move(installable_payment_app_info)),
+ installable_enabled_method_(enabled_method),
+ weak_ptr_factory_(this) {
+ DCHECK(web_contents_);
+ DCHECK(top_level_origin_.is_valid());
+ DCHECK(frame_origin_.is_valid());
+ DCHECK(spec_);
+
+ // Icon is not available in WebAppInstallationInfo for now, so create an empty
+ // icon image to avoid using invalid icon resource id.
+ icon_image_ = gfx::ImageSkia::CreateFrom1xBitmap(SkBitmap()).DeepCopy();
+}
+
ServiceWorkerPaymentInstrument::~ServiceWorkerPaymentInstrument() {
- if (delegate_) {
- // If there's a payment handler in progress, abort it before destroying this
+ // TODO(crbug.com/782270): Implement abort InstallAndInvokePaymentApp for
+ // payment app that needs installation.
+ if (delegate_ && !needs_installation_) {
+ // If there's a payment in progress, abort it before destroying this
// so that it can close its window. Since the PaymentRequest will be
- // destroyed, pass an empty callback to the payment handler.
+ // destroyed, pass an empty callback to the payment app.
content::PaymentAppProvider::GetInstance()->AbortPayment(
browser_context_, stored_payment_app_info_->registration_id,
- base::Bind([](bool) {}));
+ base::DoNothing());
}
}
void ServiceWorkerPaymentInstrument::ValidateCanMakePayment(
ValidateCanMakePaymentCallback callback) {
+ // Returns true for payment app that needs installation.
+ if (needs_installation_) {
+ OnCanMakePayment(std::move(callback), true);
+ return;
+ }
+
mojom::CanMakePaymentEventDataPtr event_data =
CreateCanMakePaymentEventData();
if (event_data.is_null()) {
// This could only happen if this instrument only supports non-url based
// payment methods of the payment request, then return true
- // and do not send CanMakePaymentEvent to the payment handler.
+ // and do not send CanMakePaymentEvent to the payment app.
OnCanMakePayment(std::move(callback), true);
return;
}
@@ -145,11 +188,22 @@ void ServiceWorkerPaymentInstrument::OnCanMakePayment(
void ServiceWorkerPaymentInstrument::InvokePaymentApp(Delegate* delegate) {
delegate_ = delegate;
- content::PaymentAppProvider::GetInstance()->InvokePaymentApp(
- browser_context_, stored_payment_app_info_->registration_id,
- CreatePaymentRequestEventData(),
- base::BindOnce(&ServiceWorkerPaymentInstrument::OnPaymentAppInvoked,
- weak_ptr_factory_.GetWeakPtr()));
+ if (needs_installation_) {
+ content::PaymentAppProvider::GetInstance()->InstallAndInvokePaymentApp(
+ web_contents_, CreatePaymentRequestEventData(),
+ installable_web_app_info_->name, installable_web_app_info_->sw_js_url,
+ installable_web_app_info_->sw_scope,
+ installable_web_app_info_->sw_use_cache,
+ std::vector<std::string>(1, installable_enabled_method_),
+ base::BindOnce(&ServiceWorkerPaymentInstrument::OnPaymentAppInvoked,
+ weak_ptr_factory_.GetWeakPtr()));
+ } else {
+ content::PaymentAppProvider::GetInstance()->InvokePaymentApp(
+ browser_context_, stored_payment_app_info_->registration_id,
+ CreatePaymentRequestEventData(),
+ base::BindOnce(&ServiceWorkerPaymentInstrument::OnPaymentAppInvoked,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
payment_request_delegate_->ShowProcessingSpinner();
}
@@ -168,8 +222,12 @@ ServiceWorkerPaymentInstrument::CreatePaymentRequestEventData() {
event_data->total = spec_->details().total->amount.Clone();
std::unordered_set<std::string> supported_methods;
- supported_methods.insert(stored_payment_app_info_->enabled_methods.begin(),
- stored_payment_app_info_->enabled_methods.end());
+ if (needs_installation_) {
+ supported_methods.insert(installable_enabled_method_);
+ } else {
+ supported_methods.insert(stored_payment_app_info_->enabled_methods.begin(),
+ stored_payment_app_info_->enabled_methods.end());
+ }
for (const auto& modifier : spec_->details().modifiers) {
std::vector<std::string>::const_iterator it =
modifier->method_data->supported_methods.begin();
@@ -228,6 +286,11 @@ bool ServiceWorkerPaymentInstrument::IsValidForCanMakePayment() const {
// , so this interface should not be invoked.
DCHECK(can_make_payment_result_);
+ // Returns false for PaymentRequest.CanMakePayment query if the app needs
+ // installation.
+ if (needs_installation_)
+ return false;
+
return true;
}
@@ -236,10 +299,17 @@ void ServiceWorkerPaymentInstrument::RecordUse() {
}
base::string16 ServiceWorkerPaymentInstrument::GetLabel() const {
- return base::UTF8ToUTF16(stored_payment_app_info_->name);
+ return base::UTF8ToUTF16(needs_installation_
+ ? installable_web_app_info_->name
+ : stored_payment_app_info_->name);
}
base::string16 ServiceWorkerPaymentInstrument::GetSublabel() const {
+ if (needs_installation_) {
+ DCHECK(GURL(installable_web_app_info_->sw_scope).is_valid());
+ return base::UTF8ToUTF16(
+ GURL(installable_web_app_info_->sw_scope).GetOrigin().spec());
+ }
return base::UTF8ToUTF16(stored_payment_app_info_->scope.GetOrigin().spec());
}
@@ -249,6 +319,13 @@ bool ServiceWorkerPaymentInstrument::IsValidForModifier(
const std::set<std::string>& supported_networks,
bool supported_types_specified,
const std::set<autofill::CreditCard::CardType>& supported_types) const {
+ // Payment app that needs installation only supports url based payment
+ // methods.
+ if (needs_installation_) {
+ return std::find(methods.begin(), methods.end(),
+ installable_enabled_method_) != methods.end();
+ }
+
std::vector<std::string> matched_methods;
for (const auto& modifier_supported_method : methods) {
if (base::ContainsValue(stored_payment_app_info_->enabled_methods,
@@ -260,6 +337,8 @@ bool ServiceWorkerPaymentInstrument::IsValidForModifier(
if (matched_methods.empty())
return false;
+ // Return true if 'basic-card' is not the only matched payment method. This
+ // assumes that there is no duplicated payment methods.
if (matched_methods.size() > 1U || matched_methods[0] != "basic-card")
return true;
diff --git a/chromium/components/payments/content/service_worker_payment_instrument.h b/chromium/components/payments/content/service_worker_payment_instrument.h
index f599ee4ee5a..37e8063d2d8 100644
--- a/chromium/components/payments/content/service_worker_payment_instrument.h
+++ b/chromium/components/payments/content/service_worker_payment_instrument.h
@@ -6,12 +6,17 @@
#define COMPONENTS_PAYMENTS_CONTENT_SERVICE_WORKER_PAYMENT_INSTRUMENT_H_
#include "components/payments/content/payment_request_spec.h"
+#include "components/payments/content/web_app_manifest.h"
#include "components/payments/core/payment_instrument.h"
-#include "content/public/browser/browser_context.h"
#include "content/public/browser/stored_payment_app.h"
#include "third_party/WebKit/public/platform/modules/payments/payment_app.mojom.h"
#include "third_party/WebKit/public/platform/modules/payments/payment_request.mojom.h"
+namespace content {
+class BrowserContext;
+class WebContents;
+} // namespace content
+
namespace payments {
class PaymentRequestDelegate;
@@ -19,13 +24,26 @@ class PaymentRequestDelegate;
// Represents a service worker based payment app.
class ServiceWorkerPaymentInstrument : public PaymentInstrument {
public:
+ // This constructor is used for a payment app that has been installed in
+ // Chrome.
ServiceWorkerPaymentInstrument(
- content::BrowserContext* context,
+ content::BrowserContext* browser_context,
const GURL& top_level_origin,
const GURL& frame_origin,
const PaymentRequestSpec* spec,
std::unique_ptr<content::StoredPaymentApp> stored_payment_app_info,
PaymentRequestDelegate* payment_request_delegate);
+
+ // This contructor is used for a payment app that has not been installed in
+ // Chrome but can be installed when paying with it.
+ ServiceWorkerPaymentInstrument(
+ content::WebContents* web_contents,
+ const GURL& top_level_origin,
+ const GURL& frame_origin,
+ const PaymentRequestSpec* spec,
+ std::unique_ptr<WebAppInstallationInfo> installable_payment_app_info,
+ const std::string& enabled_methods,
+ PaymentRequestDelegate* payment_request_delegate);
~ServiceWorkerPaymentInstrument() override;
// The callback for ValidateCanMakePayment.
@@ -36,10 +54,10 @@ class ServiceWorkerPaymentInstrument : public PaymentInstrument {
base::OnceCallback<void(ServiceWorkerPaymentInstrument*, bool)>;
// Validates whether this payment instrument can be used for this payment
- // request. It fires CanMakePaymentEvent to the payment handler to do
- // validation. The result is returned through callback.If the returned result
- // is false, then this instrument should not be used for this payment request.
- // This interface must be called before any other interfaces in this class.
+ // request. It fires CanMakePaymentEvent to the payment app to do validation.
+ // The result is returned through callback.If the returned result is false,
+ // then this instrument should not be used for this payment request. This
+ // interface must be called before any other interfaces in this class.
void ValidateCanMakePayment(ValidateCanMakePaymentCallback callback);
// PaymentInstrument:
@@ -85,6 +103,13 @@ class ServiceWorkerPaymentInstrument : public PaymentInstrument {
// PaymentAppProvider::CanMakePayment result of this payment instrument.
bool can_make_payment_result_;
+ // Below variables are used for installable ServiceWorkerPaymentInstrument
+ // specifically.
+ bool needs_installation_;
+ content::WebContents* web_contents_;
+ std::unique_ptr<WebAppInstallationInfo> installable_web_app_info_;
+ std::string installable_enabled_method_;
+
base::WeakPtrFactory<ServiceWorkerPaymentInstrument> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerPaymentInstrument);
diff --git a/chromium/components/payments/content/utility/BUILD.gn b/chromium/components/payments/content/utility/BUILD.gn
index 84d14aa936c..81ba337c4d7 100644
--- a/chromium/components/payments/content/utility/BUILD.gn
+++ b/chromium/components/payments/content/utility/BUILD.gn
@@ -42,6 +42,7 @@ fuzzer_test("payment_method_manifest_fuzzer") {
deps = [
":utility",
"//base",
+ "//base:i18n",
"//url",
]
dict = "payment_manifest_json.dict"
diff --git a/chromium/components/payments/content/utility/payment_manifest_parser.cc b/chromium/components/payments/content/utility/payment_manifest_parser.cc
index 1bad8ab538a..8b9225b7583 100644
--- a/chromium/components/payments/content/utility/payment_manifest_parser.cc
+++ b/chromium/components/payments/content/utility/payment_manifest_parser.cc
@@ -29,6 +29,11 @@ const char* const kDefaultApplications = "default_applications";
const char* const kHttpPrefix = "http://";
const char* const kHttpsPrefix = "https://";
const char* const kSupportedOrigins = "supported_origins";
+const char* const kServiceWorker = "serviceworker";
+const char* const kServiceWorkerSrc = "src";
+const char* const kServiceWorkerScope = "scope";
+const char* const kServiceWorkerUseCache = "use_cache";
+const char* const kWebAppName = "name";
// Parses the "default_applications": ["https://some/url"] from |dict| into
// |web_app_manifest_urls|. Returns 'false' for invalid data.
@@ -233,6 +238,25 @@ void PaymentManifestParser::ParseWebAppManifest(const std::string& content,
parser_callback));
}
+void PaymentManifestParser::ParseWebAppInstallationInfo(
+ const std::string& content,
+ WebAppInstallationInfoCallback callback) {
+ scoped_refptr<JsonParserCallback<WebAppInstallationInfoCallback>>
+ sw_parser_callback =
+ new JsonParserCallback<WebAppInstallationInfoCallback>(
+ base::Bind(&PaymentManifestParser::OnWebAppParseInstallationInfo,
+ weak_factory_.GetWeakPtr()),
+ std::move(callback));
+
+ data_decoder::SafeJsonParser::Parse(
+ content::ServiceManagerConnection::GetForProcess()->GetConnector(),
+ content,
+ base::Bind(&JsonParserCallback<WebAppInstallationInfoCallback>::OnSuccess,
+ sw_parser_callback),
+ base::Bind(&JsonParserCallback<WebAppInstallationInfoCallback>::OnError,
+ sw_parser_callback));
+}
+
// static
void PaymentManifestParser::ParsePaymentMethodManifestIntoVectors(
std::unique_ptr<base::Value> value,
@@ -413,4 +437,40 @@ void PaymentManifestParser::OnWebAppParse(WebAppCallback callback,
std::move(callback).Run(manifest);
}
+void PaymentManifestParser::OnWebAppParseInstallationInfo(
+ WebAppInstallationInfoCallback callback,
+ std::unique_ptr<base::Value> value) {
+ // TODO(crbug.com/782270): Move this function into a static function for unit
+ // test.
+ if (value->FindKey({kServiceWorker}) == nullptr) {
+ return std::move(callback).Run(nullptr);
+ }
+
+ std::unique_ptr<WebAppInstallationInfo> sw =
+ std::make_unique<WebAppInstallationInfo>();
+ auto* v = value->FindPath({kServiceWorker, kServiceWorkerSrc});
+ if (v == nullptr) {
+ LOG(ERROR) << "Service Worker js src cannot be empty.";
+ return std::move(callback).Run(nullptr);
+ }
+ sw->sw_js_url = v->GetString();
+
+ v = value->FindPath({kServiceWorker, kServiceWorkerScope});
+ if (v != nullptr) {
+ sw->sw_scope = v->GetString();
+ }
+
+ v = value->FindPath({kServiceWorker, kServiceWorkerUseCache});
+ if (v != nullptr) {
+ sw->sw_use_cache = v->GetBool();
+ }
+
+ v = value->FindKey({kWebAppName});
+ if (v != nullptr) {
+ sw->name = v->GetString();
+ }
+
+ return std::move(callback).Run(std::move(sw));
+}
+
} // namespace payments
diff --git a/chromium/components/payments/content/utility/payment_manifest_parser.h b/chromium/components/payments/content/utility/payment_manifest_parser.h
index 86d9fc8deeb..a224bce35f6 100644
--- a/chromium/components/payments/content/utility/payment_manifest_parser.h
+++ b/chromium/components/payments/content/utility/payment_manifest_parser.h
@@ -15,7 +15,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
-#include "components/payments/content/web_app_manifest_section.h"
+#include "components/payments/content/web_app_manifest.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -40,6 +40,20 @@ namespace payments {
// Example valid web app manifest structure:
//
// {
+// "name": "bobpay",
+// "serviceworker": {
+// "src": "bobpay.js",
+// "scope": "/pay",
+// "use_cache": false
+// },
+// "icons": [{
+// "src": "icon/bobpay.png",
+// "sizes": "48x48",
+// "type": "image/png"
+// },{
+// "src": "icon/lowres",
+// "sizes": "48x48"
+// }],
// "related_applications": [{
// "platform": "play",
// "id": "com.bobpay.app",
@@ -51,8 +65,9 @@ namespace payments {
// }]
// }
//
-// Spec:
+// Specs:
// https://docs.google.com/document/d/1izV4uC-tiRJG3JLooqY3YRLU22tYOsLTNq0P_InPJeE
+// https://w3c.github.io/manifest/
//
// Note the JSON parsing is done using the SafeJsonParser (either OOP or in a
// safe environment).
@@ -66,6 +81,11 @@ class PaymentManifestParser {
// in an empty vector.
using WebAppCallback =
base::OnceCallback<void(const std::vector<WebAppManifestSection>&)>;
+ // Called on successful parsing of the installation info (name, icons,
+ // and serviceworker) in the web app manifest. Parse failure results in a
+ // nullptr.
+ using WebAppInstallationInfoCallback =
+ base::OnceCallback<void(std::unique_ptr<WebAppInstallationInfo>)>;
PaymentManifestParser();
~PaymentManifestParser();
@@ -74,6 +94,13 @@ class PaymentManifestParser {
PaymentMethodCallback callback);
void ParseWebAppManifest(const std::string& content, WebAppCallback callback);
+ // Parses the installation info in the web app manifest |content|. Sends the
+ // result back through callback.
+ // Refer to:
+ // https://www.w3.org/TR/appmanifest/#webappmanifest-dictionary
+ void ParseWebAppInstallationInfo(const std::string& content,
+ WebAppInstallationInfoCallback callback);
+
// Visible for tests.
static void ParsePaymentMethodManifestIntoVectors(
std::unique_ptr<base::Value> value,
@@ -90,6 +117,8 @@ class PaymentManifestParser {
std::unique_ptr<base::Value> value);
void OnWebAppParse(WebAppCallback callback,
std::unique_ptr<base::Value> value);
+ void OnWebAppParseInstallationInfo(WebAppInstallationInfoCallback callback,
+ std::unique_ptr<base::Value> value);
int64_t parse_payment_callback_counter_ = 0;
int64_t parse_webapp_callback_counter_ = 0;
diff --git a/chromium/components/payments/content/utility/payment_method_manifest_parser_fuzzer.cc b/chromium/components/payments/content/utility/payment_method_manifest_parser_fuzzer.cc
index 12d0884ed17..c3b6d35bac2 100644
--- a/chromium/components/payments/content/utility/payment_method_manifest_parser_fuzzer.cc
+++ b/chromium/components/payments/content/utility/payment_method_manifest_parser_fuzzer.cc
@@ -7,17 +7,24 @@
#include <string>
#include <vector>
+#include "base/at_exit.h"
+#include "base/i18n/icu_util.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "components/payments/content/utility/payment_manifest_parser.h"
#include "url/gurl.h"
#include "url/origin.h"
-struct Environment {
- Environment() { logging::SetMinLogLevel(logging::LOG_FATAL); }
+struct IcuEnvironment {
+ IcuEnvironment() {
+ logging::SetMinLogLevel(logging::LOG_FATAL);
+ CHECK(base::i18n::InitializeICU());
+ }
+ // used by ICU integration.
+ base::AtExitManager at_exit_manager;
};
-Environment* env = new Environment();
+IcuEnvironment* env = new IcuEnvironment();
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
std::vector<GURL> web_app_manifest_urls;
diff --git a/chromium/components/payments/content/utility/payment_web_app_manifest_parser_fuzzer.cc b/chromium/components/payments/content/utility/payment_web_app_manifest_parser_fuzzer.cc
index 5a4ed0c612d..d324ef82575 100644
--- a/chromium/components/payments/content/utility/payment_web_app_manifest_parser_fuzzer.cc
+++ b/chromium/components/payments/content/utility/payment_web_app_manifest_parser_fuzzer.cc
@@ -12,7 +12,7 @@
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "components/payments/content/utility/payment_manifest_parser.h"
-#include "components/payments/content/web_app_manifest_section.h"
+#include "components/payments/content/web_app_manifest.h"
struct Environment {
Environment() { logging::SetMinLogLevel(logging::LOG_FATAL); }
diff --git a/chromium/components/payments/content/web_app_manifest_section.cc b/chromium/components/payments/content/web_app_manifest.cc
index 8f5da8555ba..b556153347a 100644
--- a/chromium/components/payments/content/web_app_manifest_section.cc
+++ b/chromium/components/payments/content/web_app_manifest.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/payments/content/web_app_manifest_section.h"
+#include "components/payments/content/web_app_manifest.h"
namespace payments {
@@ -13,4 +13,7 @@ WebAppManifestSection::WebAppManifestSection(
WebAppManifestSection::~WebAppManifestSection() = default;
+WebAppInstallationInfo::WebAppInstallationInfo() = default;
+WebAppInstallationInfo::~WebAppInstallationInfo() = default;
+
} // namespace payments
diff --git a/chromium/components/payments/content/web_app_manifest_section.h b/chromium/components/payments/content/web_app_manifest.h
index 4f0ae18a125..facfe2486a6 100644
--- a/chromium/components/payments/content/web_app_manifest_section.h
+++ b/chromium/components/payments/content/web_app_manifest.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_CONTENT_WEB_APP_MANIFEST_SECTION_H_
-#define COMPONENTS_PAYMENTS_CONTENT_WEB_APP_MANIFEST_SECTION_H_
+#ifndef COMPONENTS_PAYMENTS_CONTENT_WEB_APP_MANIFEST_H_
+#define COMPONENTS_PAYMENTS_CONTENT_WEB_APP_MANIFEST_H_
#include <stdint.h>
@@ -28,6 +28,17 @@ struct WebAppManifestSection {
std::vector<std::vector<uint8_t>> fingerprints;
};
+struct WebAppInstallationInfo {
+ WebAppInstallationInfo();
+ ~WebAppInstallationInfo();
+
+ // TODO(crbug.com/782270): Add icons.
+ std::string name;
+ std::string sw_js_url;
+ std::string sw_scope;
+ bool sw_use_cache;
+};
+
} // namespace payments
-#endif // COMPONENTS_PAYMENTS_CONTENT_WEB_APP_MANIFEST_SECTION_H_ \ No newline at end of file
+#endif // COMPONENTS_PAYMENTS_CONTENT_WEB_APP_MANIFEST_H_ \ No newline at end of file
diff --git a/chromium/components/payments/content/web_app_manifest_section_table.h b/chromium/components/payments/content/web_app_manifest_section_table.h
index c440885b4de..8a30646676e 100644
--- a/chromium/components/payments/content/web_app_manifest_section_table.h
+++ b/chromium/components/payments/content/web_app_manifest_section_table.h
@@ -9,7 +9,7 @@
#include <vector>
#include "base/macros.h"
-#include "components/payments/content/web_app_manifest_section.h"
+#include "components/payments/content/web_app_manifest.h"
#include "components/webdata/common/web_database_table.h"
class WebDatabase;
diff --git a/chromium/components/payments/core/payment_details.cc b/chromium/components/payments/core/payment_details.cc
index fc000ff4c74..8716ce0bd3c 100644
--- a/chromium/components/payments/core/payment_details.cc
+++ b/chromium/components/payments/core/payment_details.cc
@@ -136,7 +136,7 @@ bool PaymentDetails::FromDictionaryValue(const base::DictionaryValue& value,
const base::DictionaryValue* additional_display_item_dict = nullptr;
PaymentItem additional_display_item;
if (!additional_display_items_list->GetDictionary(
- i, &additional_display_item_dict) ||
+ j, &additional_display_item_dict) ||
!additional_display_item.FromDictionaryValue(
*additional_display_item_dict)) {
return false;
diff --git a/chromium/components/payments/core/payment_details_validation_unittest.cc b/chromium/components/payments/core/payment_details_validation_unittest.cc
index c8f69e06d68..dddfe16d756 100644
--- a/chromium/components/payments/core/payment_details_validation_unittest.cc
+++ b/chromium/components/payments/core/payment_details_validation_unittest.cc
@@ -277,6 +277,19 @@ INSTANTIATE_TEST_CASE_P(TestCases,
"label": "Debit card discount",
"amount": {"currency": "USD", "value": "-0.20"}
}]
+ }, {
+ "supportedMethods": ["basic-card"],
+ "data": {
+ "supportedTypes": ["mastercard"]
+ },
+ "total": {
+ "label": "MasterCard discounted total",
+ "amount": {"currency": "USD", "value": "0.80"}
+ },
+ "additionalDisplayItems": [{
+ "label": "MasterCard discount",
+ "amount": {"currency": "USD", "value": "-0.20"}
+ }]
}]
})",
DO_NOT_REQUIRE_TOTAL,
diff --git a/chromium/components/payments/core/payment_manifest_downloader.h b/chromium/components/payments/core/payment_manifest_downloader.h
index a6a4d2438b1..0e2f38d5b8d 100644
--- a/chromium/components/payments/core/payment_manifest_downloader.h
+++ b/chromium/components/payments/core/payment_manifest_downloader.h
@@ -37,13 +37,19 @@ namespace payments {
using PaymentManifestDownloadCallback =
base::OnceCallback<void(const std::string&)>;
-// The interface for the downloader of the payment method manifest.
+// Downloader of the payment method manifest and web-app manifest based on the
+// payment method name that is a URL with HTTPS scheme, e.g.,
+// https://bobpay.com.
//
// The downloader does not follow redirects. A download succeeds only if all
// HTTP response codes are 200 or 204.
-class PaymentMethodManifestDownloaderInterface {
+class PaymentManifestDownloader : public net::URLFetcherDelegate {
public:
- virtual ~PaymentMethodManifestDownloaderInterface() {}
+ // |delegate| should not be null and must outlive this object.
+ explicit PaymentManifestDownloader(
+ const scoped_refptr<net::URLRequestContextGetter>& context);
+
+ ~PaymentManifestDownloader() override;
// Download a payment method manifest via two consecutive HTTP requests:
//
@@ -66,43 +72,15 @@ class PaymentMethodManifestDownloaderInterface {
// |url| should be a valid URL with HTTPS scheme.
virtual void DownloadPaymentMethodManifest(
const GURL& url,
- PaymentManifestDownloadCallback callback) = 0;
-
- protected:
- PaymentMethodManifestDownloaderInterface() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PaymentMethodManifestDownloaderInterface);
-};
-
-// Downloader of the payment method manifest and web-app manifest based on the
-// payment method name that is a URL with HTTPS scheme, e.g.,
-// https://bobpay.com.
-//
-// The downloader does not follow redirects. A download succeeds only if all
-// HTTP response codes are 200 or 204.
-class PaymentManifestDownloader
- : public net::URLFetcherDelegate,
- public PaymentMethodManifestDownloaderInterface {
- public:
- // |delegate| should not be null and must outlive this object.
- explicit PaymentManifestDownloader(
- const scoped_refptr<net::URLRequestContextGetter>& context);
-
- ~PaymentManifestDownloader() override;
-
- // PaymentMethodManifestDownloaderInterface implementation.
- void DownloadPaymentMethodManifest(
- const GURL& url,
- PaymentManifestDownloadCallback callback) override;
+ PaymentManifestDownloadCallback callback);
// Download a web app manifest via a single HTTP request:
//
// 1) GET request for the payment method name.
//
// |url| should be a valid URL with HTTPS scheme.
- void DownloadWebAppManifest(const GURL& url,
- PaymentManifestDownloadCallback callback);
+ virtual void DownloadWebAppManifest(const GURL& url,
+ PaymentManifestDownloadCallback callback);
private:
// Information about an ongoing download request.
diff --git a/chromium/components/payments/core/payment_request_data_util.cc b/chromium/components/payments/core/payment_request_data_util.cc
index 7b502f444a7..19092912716 100644
--- a/chromium/components/payments/core/payment_request_data_util.cc
+++ b/chromium/components/payments/core/payment_request_data_util.cc
@@ -4,6 +4,8 @@
#include "components/payments/core/payment_request_data_util.h"
+#include <memory>
+
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -74,7 +76,7 @@ std::unique_ptr<BasicCardResponse> GetBasicCardResponseFromAutofillCreditCard(
const autofill::AutofillProfile& billing_profile,
const std::string& app_locale) {
std::unique_ptr<BasicCardResponse> response =
- base::MakeUnique<BasicCardResponse>();
+ std::make_unique<BasicCardResponse>();
response->cardholder_name = card.GetRawInfo(autofill::CREDIT_CARD_NAME_FULL);
response->card_number = card.GetRawInfo(autofill::CREDIT_CARD_NUMBER);
response->expiry_month = card.GetRawInfo(autofill::CREDIT_CARD_EXP_MONTH);
diff --git a/chromium/components/payments/core/test_payment_manifest_downloader.cc b/chromium/components/payments/core/test_payment_manifest_downloader.cc
index 892ccc0174b..422ba40939a 100644
--- a/chromium/components/payments/core/test_payment_manifest_downloader.cc
+++ b/chromium/components/payments/core/test_payment_manifest_downloader.cc
@@ -14,7 +14,7 @@ namespace payments {
TestDownloader::TestDownloader(
const scoped_refptr<net::URLRequestContextGetter>& context)
- : impl_(context) {}
+ : PaymentManifestDownloader(context) {}
TestDownloader::~TestDownloader() {}
@@ -41,7 +41,8 @@ void TestDownloader::DownloadPaymentMethodManifest(
}
}
- impl_.DownloadPaymentMethodManifest(actual_url, std::move(callback));
+ PaymentManifestDownloader::DownloadPaymentMethodManifest(actual_url,
+ std::move(callback));
}
} // namespace payments
diff --git a/chromium/components/payments/core/test_payment_manifest_downloader.h b/chromium/components/payments/core/test_payment_manifest_downloader.h
index 1f5536eeef0..d4bae37ff81 100644
--- a/chromium/components/payments/core/test_payment_manifest_downloader.h
+++ b/chromium/components/payments/core/test_payment_manifest_downloader.h
@@ -6,6 +6,7 @@
#define COMPONENTS_PAYMENTS_CORE_TEST_PAYMENT_MANIFEST_DOWNLOADER_H_
#include <map>
+#include <memory>
#include <string>
#include "base/macros.h"
@@ -45,13 +46,13 @@ namespace payments {
// // Actual URL downloaded is https://127.0.0.1:9090/webpay.
// downloader.DownloadPaymentMethodManifest(
// "https://bobpay.com/webpay", callback);
-class TestDownloader : public PaymentMethodManifestDownloaderInterface {
+class TestDownloader : public PaymentManifestDownloader {
public:
explicit TestDownloader(
const scoped_refptr<net::URLRequestContextGetter>& context);
~TestDownloader() override;
- // PaymentMethodManifestDownloaderInterface implementation.
+ // PaymentManifestDownloader implementation.
void DownloadPaymentMethodManifest(
const GURL& url,
PaymentManifestDownloadCallback callback) override;
@@ -91,9 +92,6 @@ class TestDownloader : public PaymentMethodManifestDownloaderInterface {
void AddTestServerURL(const std::string& prefix, const GURL& test_server_url);
private:
- // The actual downloader.
- PaymentManifestDownloader impl_;
-
// The mapping from the URL prefix to the URL of the test server to be used.
// Example 1:
//
diff --git a/chromium/components/payments_strings.grdp b/chromium/components/payments_strings.grdp
index 4e0c802d430..60c8306824e 100644
--- a/chromium/components/payments_strings.grdp
+++ b/chromium/components/payments_strings.grdp
@@ -1,14 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
- <!-- Titles and buttons which are title-cased on certain platforms. Make sure to keep the title-cased and sentence-cased variants in sync. -->
+ <!-- Dialog titles, sentence-cased -->
+ <message name="IDS_PAYMENTS_TITLE" desc="Title of the dialog that presents a request for payment for some good or service. Sentence-cased.">
+ Review your payment
+ </message>
+ <message name="IDS_PAYMENTS_ERROR_MESSAGE_DIALOG_TITLE" desc="The title of the dialog that informs the user that there is error in verifying and charging the payment.">
+ Payment not completed
+ </message>
+ <!-- Section labels and buttons which are title-cased on certain platforms. Make sure to keep the title-cased and sentence-cased variants in sync. -->
<!-- General titles, sentence-cased -->
<if expr="not use_titlecase">
- <message name="IDS_PAYMENTS_TITLE" desc="Title of the dialog that presents a request for payment for some good or service. Sentence-cased.">
- Your payment
- </message>
<message name="IDS_PAYMENTS_METHOD_OF_PAYMENT_LABEL" desc="The title for the section that lets the user select the method of payment. Sentence-cased." formatter_data="android_java">
Payment method
</message>
@@ -75,9 +79,6 @@
</if> <!-- not use_titlecase -->
<!-- General Titles, Title-Cased -->
<if expr="use_titlecase">
- <message name="IDS_PAYMENTS_TITLE" desc="Title of the dialog that presents a request for payment for some good or service. Title-Cased.">
- Your Payment
- </message>
<message name="IDS_PAYMENTS_METHOD_OF_PAYMENT_LABEL" desc="The title for the section that lets the user select the method of payment. Title-Cased.">
Payment Method
</message>
@@ -286,9 +287,6 @@
<message name="IDS_PAYMENTS_PROCESSING_MESSAGE" desc="The text that informs the user that payment is being processed. Sentence-cased.">
Processing
</message>
- <message name="IDS_PAYMENTS_ERROR_MESSAGE_DIALOG_TITLE" desc="The title of the dialog that informs the user that there is error in verifying and charging the payment. Sentence-cased.">
- Payment not completed
- </message>
<message name="IDS_PAYMENTS_CHECKING_OPTION" desc="Text explaining that the option the user selected is being checked and verified. Sentence-cased." formatter_data="android_java">
Checking
</message>
@@ -340,9 +338,6 @@
<message name="IDS_PAYMENTS_PROCESSING_MESSAGE" desc="The text that informs the user that payment is being processed. Title-Cased.">
Processing
</message>
- <message name="IDS_PAYMENTS_ERROR_MESSAGE_DIALOG_TITLE" desc="The title of the dialog that informs the user that there is error in verifying and charging the payment. Title-Cased.">
- Payment Not Completed
- </message>
<message name="IDS_PAYMENTS_CHECKING_OPTION" desc="Text explaining that the option the user selected is being checked and verified. Title-Cased." formatter_data="android_java">
Checking
</message>
diff --git a/chromium/components/pdf/browser/pdf_web_contents_helper.cc b/chromium/components/pdf/browser/pdf_web_contents_helper.cc
index e54ae672542..efa166b9716 100644
--- a/chromium/components/pdf/browser/pdf_web_contents_helper.cc
+++ b/chromium/components/pdf/browser/pdf_web_contents_helper.cc
@@ -146,6 +146,8 @@ void PDFWebContentsHelper::SelectBetweenCoordinates(const gfx::PointF& base,
void PDFWebContentsHelper::OnSelectionEvent(ui::SelectionEventType event) {}
+void PDFWebContentsHelper::OnDragUpdate(const gfx::PointF& position) {}
+
std::unique_ptr<ui::TouchHandleDrawable>
PDFWebContentsHelper::CreateDrawable() {
// We can return null here, as the manager will look after this.
diff --git a/chromium/components/pdf/browser/pdf_web_contents_helper.h b/chromium/components/pdf/browser/pdf_web_contents_helper.h
index fb6afa22738..98cef8feda7 100644
--- a/chromium/components/pdf/browser/pdf_web_contents_helper.h
+++ b/chromium/components/pdf/browser/pdf_web_contents_helper.h
@@ -50,6 +50,7 @@ class PDFWebContentsHelper
void SelectBetweenCoordinates(const gfx::PointF& base,
const gfx::PointF& extent) override;
void OnSelectionEvent(ui::SelectionEventType event) override;
+ void OnDragUpdate(const gfx::PointF& position) override;
std::unique_ptr<ui::TouchHandleDrawable> CreateDrawable() override;
void DidScroll() override;
diff --git a/chromium/components/pdf/common/BUILD.gn b/chromium/components/pdf/common/BUILD.gn
index 370b7a98a2b..4d11977830b 100644
--- a/chromium/components/pdf/common/BUILD.gn
+++ b/chromium/components/pdf/common/BUILD.gn
@@ -12,7 +12,7 @@ mojom("interfaces") {
public_deps = [
"//third_party/WebKit/public:mojo_bindings",
- "//url/mojo:url_mojom_gurl",
+ "//url/mojom:url_mojom_gurl",
]
overridden_deps = [ "//third_party/WebKit/public:mojo_bindings" ]
diff --git a/chromium/components/pdf/common/pdf.mojom b/chromium/components/pdf/common/pdf.mojom
index 5483a7eb255..6a91a7dbb44 100644
--- a/chromium/components/pdf/common/pdf.mojom
+++ b/chromium/components/pdf/common/pdf.mojom
@@ -6,7 +6,7 @@ module pdf.mojom;
import "third_party/WebKit/public/platform/referrer.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
-import "url/mojo/url.mojom";
+import "url/mojom/url.mojom";
interface PdfListener {
// Sets the current caret position.
diff --git a/chromium/components/pdf/renderer/DEPS b/chromium/components/pdf/renderer/DEPS
index 2ab25aac9f4..94012530304 100644
--- a/chromium/components/pdf/renderer/DEPS
+++ b/chromium/components/pdf/renderer/DEPS
@@ -3,7 +3,6 @@ include_rules = [
"+gin",
"+mojo/public/cpp/bindings",
"+skia/ext",
- "+third_party/WebKit/common",
"+ui/accessibility",
"+ui/gfx",
]
diff --git a/chromium/components/pdf/renderer/pdf_accessibility_tree.cc b/chromium/components/pdf/renderer/pdf_accessibility_tree.cc
index 73d354b1a5b..1722498cbff 100644
--- a/chromium/components/pdf/renderer/pdf_accessibility_tree.cc
+++ b/chromium/components/pdf/renderer/pdf_accessibility_tree.cc
@@ -5,6 +5,7 @@
#include <algorithm>
#include "base/debug/crash_logging.h"
+#include "base/i18n/break_iterator.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversion_utils.h"
@@ -80,7 +81,7 @@ void PdfAccessibilityTree::SetAccessibilityDocInfo(
return;
doc_info_ = doc_info;
- doc_node_ = CreateNode(ui::AX_ROLE_GROUP);
+ doc_node_ = CreateNode(ax::mojom::Role::kGroup);
// Because all of the coordinates are expressed relative to the
// doc's coordinates, the origin of the doc must be (0, 0). Its
@@ -101,11 +102,10 @@ void PdfAccessibilityTree::SetAccessibilityPageInfo(
CHECK_GE(page_index, 0U);
CHECK_LT(page_index, doc_info_.page_count);
- ui::AXNodeData* page_node = CreateNode(ui::AX_ROLE_REGION);
+ ui::AXNodeData* page_node = CreateNode(ax::mojom::Role::kRegion);
page_node->AddStringAttribute(
- ui::AX_ATTR_NAME,
- l10n_util::GetPluralStringFUTF8(
- IDS_PDF_PAGE_INDEX, page_index + 1));
+ ax::mojom::StringAttribute::kName,
+ l10n_util::GetPluralStringFUTF8(IDS_PDF_PAGE_INDEX, page_index + 1));
gfx::RectF page_bounds = ToRectF(page_info.bounds);
page_node->location = page_bounds;
@@ -133,39 +133,44 @@ void PdfAccessibilityTree::SetAccessibilityPageInfo(
// If we don't have a paragraph, create one.
if (!para_node) {
- para_node = CreateNode(ui::AX_ROLE_PARAGRAPH);
+ para_node = CreateNode(ax::mojom::Role::kParagraph);
page_node->child_ids.push_back(para_node->id);
if (heading_font_size_threshold > 0 &&
text_run.font_size > heading_font_size_threshold) {
- para_node->role = ui::AX_ROLE_HEADING;
- para_node->AddIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL, 2);
- para_node->AddStringAttribute(ui::AX_ATTR_HTML_TAG, "h2");
+ para_node->role = ax::mojom::Role::kHeading;
+ para_node->AddIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel,
+ 2);
+ para_node->AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
+ "h2");
}
// This node is for the text inside the paragraph, it includes
// the text of all of the text runs.
- static_text_node = CreateNode(ui::AX_ROLE_STATIC_TEXT);
+ static_text_node = CreateNode(ax::mojom::Role::kStaticText);
para_node->child_ids.push_back(static_text_node->id);
}
// Add this text run to the current static text node.
- ui::AXNodeData* inline_text_box_node = CreateNode(
- ui::AX_ROLE_INLINE_TEXT_BOX);
+ ui::AXNodeData* inline_text_box_node =
+ CreateNode(ax::mojom::Role::kInlineTextBox);
static_text_node->child_ids.push_back(inline_text_box_node->id);
- inline_text_box_node->AddStringAttribute(ui::AX_ATTR_NAME, chars_utf8);
+ inline_text_box_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
+ chars_utf8);
gfx::RectF text_run_bounds = ToGfxRectF(text_run.bounds);
text_run_bounds += page_bounds.OffsetFromOrigin();
inline_text_box_node->location = text_run_bounds;
- inline_text_box_node->AddIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS,
- char_offsets);
+ inline_text_box_node->AddIntListAttribute(
+ ax::mojom::IntListAttribute::kCharacterOffsets, char_offsets);
+ AddWordStartsAndEnds(inline_text_box_node);
para_node->location.Union(inline_text_box_node->location);
static_text_node->location.Union(inline_text_box_node->location);
if (i == text_runs.size() - 1) {
- static_text_node->AddStringAttribute(ui::AX_ATTR_NAME, static_text);
+ static_text_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
+ static_text);
break;
}
@@ -174,7 +179,8 @@ void PdfAccessibilityTree::SetAccessibilityPageInfo(
if (text_run.font_size != text_runs[i + 1].font_size ||
(line_spacing_threshold > 0 &&
line_spacing > line_spacing_threshold)) {
- static_text_node->AddStringAttribute(ui::AX_ATTR_NAME, static_text);
+ static_text_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
+ static_text);
para_node = nullptr;
static_text_node = nullptr;
static_text.clear();
@@ -280,14 +286,14 @@ gfx::RectF PdfAccessibilityTree::ToRectF(const PP_Rect& r) {
return gfx::RectF(r.point.x, r.point.y, r.size.width, r.size.height);
}
-ui::AXNodeData* PdfAccessibilityTree::CreateNode(ui::AXRole role) {
+ui::AXNodeData* PdfAccessibilityTree::CreateNode(ax::mojom::Role role) {
content::RenderAccessibility* render_accessibility = GetRenderAccessibility();
DCHECK(render_accessibility);
ui::AXNodeData* node = new ui::AXNodeData();
node->id = render_accessibility->GenerateAXID();
node->role = role;
- node->AddIntAttribute(ui::AX_ATTR_RESTRICTION, ui::AX_RESTRICTION_READ_ONLY);
+ node->SetRestriction(ax::mojom::Restriction::kReadOnly);
// All nodes other than the first one have coordinates relative to
// the first node.
@@ -334,6 +340,28 @@ gfx::Transform* PdfAccessibilityTree::MakeTransformFromViewInfo() {
return transform;
}
+void PdfAccessibilityTree::AddWordStartsAndEnds(
+ ui::AXNodeData* inline_text_box) {
+ base::string16 text =
+ inline_text_box->GetString16Attribute(ax::mojom::StringAttribute::kName);
+ base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD);
+ if (!iter.Init())
+ return;
+
+ std::vector<int32_t> word_starts;
+ std::vector<int32_t> word_ends;
+ while (iter.Advance()) {
+ if (iter.IsWord()) {
+ word_starts.push_back(iter.prev());
+ word_ends.push_back(iter.pos());
+ }
+ }
+ inline_text_box->AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
+ word_starts);
+ inline_text_box->AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
+ word_ends);
+}
+
//
// AXTreeSource implementation.
//
diff --git a/chromium/components/pdf/renderer/pdf_accessibility_tree.h b/chromium/components/pdf/renderer/pdf_accessibility_tree.h
index d4b65013548..440cb4c8df6 100644
--- a/chromium/components/pdf/renderer/pdf_accessibility_tree.h
+++ b/chromium/components/pdf/renderer/pdf_accessibility_tree.h
@@ -76,10 +76,11 @@ class PdfAccessibilityTree
int char_index);
gfx::Vector2dF ToVector2dF(const PP_Point& p);
gfx::RectF ToRectF(const PP_Rect& r);
- ui::AXNodeData* CreateNode(ui::AXRole role);
+ ui::AXNodeData* CreateNode(ax::mojom::Role role);
float GetDeviceScaleFactor() const;
content::RenderAccessibility* GetRenderAccessibility();
gfx::Transform* MakeTransformFromViewInfo();
+ void AddWordStartsAndEnds(ui::AXNodeData* inline_text_box);
ui::AXTree tree_;
content::RendererPpapiHost* host_;
diff --git a/chromium/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc b/chromium/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc
index 385e6d2400d..0936c5f8d7c 100644
--- a/chromium/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc
+++ b/chromium/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc
@@ -121,7 +121,8 @@ TEST_F(PdfAccessibilityTreeTest, TestEmptyPDFPage) {
pdf_accessibility_tree.SetAccessibilityPageInfo(page_info_, text_runs_,
chars_);
- EXPECT_EQ(ui::AX_ROLE_GROUP, pdf_accessibility_tree.GetRoot()->data().role);
+ EXPECT_EQ(ax::mojom::Role::kGroup,
+ pdf_accessibility_tree.GetRoot()->data().role);
}
TEST_F(PdfAccessibilityTreeTest, TestAccessibilityDisabledDuringPDFLoad) {
diff --git a/chromium/components/pdf/renderer/pepper_pdf_host.cc b/chromium/components/pdf/renderer/pepper_pdf_host.cc
index 4610a20a0a3..b2099de0b9a 100644
--- a/chromium/components/pdf/renderer/pepper_pdf_host.cc
+++ b/chromium/components/pdf/renderer/pepper_pdf_host.cc
@@ -4,8 +4,9 @@
#include "components/pdf/renderer/pepper_pdf_host.h"
+#include <memory>
+
#include "base/lazy_instance.h"
-#include "base/memory/ptr_util.h"
#include "components/pdf/renderer/pdf_accessibility_tree.h"
#include "content/public/common/referrer.h"
#include "content/public/renderer/pepper_plugin_instance.h"
@@ -22,7 +23,7 @@
#include "ppapi/shared_impl/scoped_pp_resource.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_image_data_api.h"
-#include "third_party/WebKit/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/WebKit/public/common/associated_interfaces/associated_interface_provider.h"
namespace pdf {
@@ -264,7 +265,7 @@ int32_t PepperPDFHost::OnHostMsgDidScroll(
void PepperPDFHost::CreatePdfAccessibilityTreeIfNeeded() {
if (!pdf_accessibility_tree_) {
pdf_accessibility_tree_ =
- base::MakeUnique<PdfAccessibilityTree>(host_, pp_instance());
+ std::make_unique<PdfAccessibilityTree>(host_, pp_instance());
}
}
diff --git a/chromium/components/physical_web/data_source/fake_physical_web_data_source.cc b/chromium/components/physical_web/data_source/fake_physical_web_data_source.cc
index 727339a65fa..2447a4bcadf 100644
--- a/chromium/components/physical_web/data_source/fake_physical_web_data_source.cc
+++ b/chromium/components/physical_web/data_source/fake_physical_web_data_source.cc
@@ -4,6 +4,8 @@
#include "components/physical_web/data_source/fake_physical_web_data_source.h"
+#include <memory>
+
#include "base/strings/string_number_conversions.h"
#include "components/physical_web/data_source/physical_web_listener.h"
#include "url/gurl.h"
@@ -18,7 +20,7 @@ std::unique_ptr<Metadata> CreatePhysicalWebPage(
const std::string& title,
const std::string& description,
const std::string& scanned_url) {
- auto page = base::MakeUnique<Metadata>();
+ auto page = std::make_unique<Metadata>();
page->resolved_url = GURL(resolved_url);
page->distance_estimate = distance_estimate;
page->group_id = group_id;
@@ -43,7 +45,7 @@ std::unique_ptr<MetadataList> CreateDummyPhysicalWebPages(
const std::vector<int>& ids) {
int distance = 1;
int timestamp = static_cast<int>(ids.size());
- auto list = base::MakeUnique<MetadataList>();
+ auto list = std::make_unique<MetadataList>();
for (int id : ids) {
std::unique_ptr<Metadata> page =
CreateDummyPhysicalWebPage(id, distance, timestamp);
@@ -67,7 +69,7 @@ void FakePhysicalWebDataSource::StopDiscovery() {
}
std::unique_ptr<MetadataList> FakePhysicalWebDataSource::GetMetadataList() {
- return base::MakeUnique<MetadataList>(*metadata_list_.get());
+ return std::make_unique<MetadataList>(*metadata_list_.get());
}
bool FakePhysicalWebDataSource::HasUnresolvedDiscoveries() {
diff --git a/chromium/components/physical_web/webui/physical_web_base_message_handler.cc b/chromium/components/physical_web/webui/physical_web_base_message_handler.cc
index f68cfb08c74..17b089b4ff2 100644
--- a/chromium/components/physical_web/webui/physical_web_base_message_handler.cc
+++ b/chromium/components/physical_web/webui/physical_web_base_message_handler.cc
@@ -4,10 +4,10 @@
#include "components/physical_web/webui/physical_web_base_message_handler.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "components/physical_web/data_source/physical_web_data_source.h"
@@ -70,11 +70,11 @@ void PhysicalWebBaseMessageHandler::PushNearbyURLs() {
}
}
- auto metadata = base::MakeUnique<base::ListValue>();
+ auto metadata = std::make_unique<base::ListValue>();
int index = 0;
for (const auto& group_id : ordered_group_ids_) {
auto metadata_list_item = metadata_map_[group_id];
- auto metadata_item = base::MakeUnique<base::DictionaryValue>();
+ auto metadata_item = std::make_unique<base::DictionaryValue>();
metadata_item->SetString(physical_web_ui::kResolvedUrl,
metadata_list_item.resolved_url.spec());
metadata_item->SetString(physical_web_ui::kPageInfoIcon,
diff --git a/chromium/components/plugins/renderer/DEPS b/chromium/components/plugins/renderer/DEPS
index c9f1d1f47f8..0e11b3fb191 100644
--- a/chromium/components/plugins/renderer/DEPS
+++ b/chromium/components/plugins/renderer/DEPS
@@ -7,7 +7,7 @@ include_rules = [
"+content/public/common",
"+content/public/test",
"+services/service_manager/public/cpp",
- "+third_party/WebKit/common/page/page_visibility_state.mojom.h",
+ "+third_party/WebKit/public/mojom/page/page_visibility_state.mojom.h",
"+third_party/WebKit/public",
"+third_party/re2",
"+skia",
diff --git a/chromium/components/plugins/renderer/webview_plugin.cc b/chromium/components/plugins/renderer/webview_plugin.cc
index 209bdff665d..2d9e8745c48 100644
--- a/chromium/components/plugins/renderer/webview_plugin.cc
+++ b/chromium/components/plugins/renderer/webview_plugin.cc
@@ -17,7 +17,7 @@
#include "content/public/renderer/render_view.h"
#include "gin/converter.h"
#include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/common/page/page_visibility_state.mojom.h"
+#include "third_party/WebKit/public/mojom/page/page_visibility_state.mojom.h"
#include "third_party/WebKit/public/platform/WebCoalescedInputEvent.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
diff --git a/chromium/components/policy/android/BUILD.gn b/chromium/components/policy/android/BUILD.gn
index 9b45f32d6ed..6042c4210b8 100644
--- a/chromium/components/policy/android/BUILD.gn
+++ b/chromium/components/policy/android/BUILD.gn
@@ -52,6 +52,7 @@ junit_binary("components_policy_junit_tests") {
":policy_java",
":policy_java_test_support",
"//base:base_java",
+ "//base:base_junit_test_support",
"//third_party/hamcrest:hamcrest_java",
]
}
diff --git a/chromium/components/policy/resources/policy_templates.gni b/chromium/components/policy/resources/policy_templates.gni
index 7159dfc6b97..37b97378db3 100644
--- a/chromium/components/policy/resources/policy_templates.gni
+++ b/chromium/components/policy/resources/policy_templates.gni
@@ -11,62 +11,123 @@
policy_templates_base_dir = "$root_gen_dir/chrome/app/policy"
-# Languages we're going to process.
+# Languages we're going to process. Should match the XX-YY of the translated
+# policy_templates_XX-YY.json files, see policy_templates.grd.
policy_templates_languages = [
"am",
- "ar",
- "bg",
- "bn",
- "ca",
- "cs",
- "da",
- "de",
- "el",
+ "ar-EG",
+ "bg-BG",
+ "ms-BN",
+ "ca-ES",
+ "cs-CZ",
+ "da-DK",
+ "de-DE",
+ "el-GR",
"en-GB",
"en-US",
- "es",
+ "es-ES",
"es-419",
- "et",
- "fa",
- "fi",
+ "et-EE",
+ "fa-IR",
+ "fi-FI",
"fil",
- "fr",
- "gu",
- "he",
- "hi",
- "hr",
- "hu",
- "id",
- "it",
- "ja",
- "kn",
- "ko",
- "lt",
- "lv",
+ "fr-FR",
+ "gu-IN",
+ "he-IL",
+ "hi-IN",
+ "hr-HR",
+ "hu-HU",
+ "id-ID",
+ "it-IT",
+ "ja-JP",
+ "kn-IN",
+ "ko-KR",
+ "lt-LT",
+ "lv-LV",
"ml",
- "mr",
- "ms",
- "nl",
- "nb",
- "pl",
+ "mr-IN",
+ "ms-MY",
+ "nl-NL",
+ "nb-NO",
+ "pl-PL",
"pt-BR",
"pt-PT",
- "ro",
- "ru",
- "sk",
- "sl",
- "sr",
- "sv",
- "sw",
- "ta",
- "te",
- "th",
- "tr",
- "uk",
- "vi",
+ "ro-RO",
+ "ru-RU",
+ "sk-SK",
+ "sl-SI",
+ "Cy-sr-SP",
+ "sv-SE",
+ "sw-KE",
+ "ta-IN",
+ "te-IN",
+ "th-TH",
+ "tr-TR",
+ "uk-UA",
+ "vi-VN",
"zh-CN",
"zh-TW",
]
+
+# Macs use a slightly different naming convention:
+# - '_' instead of '-'
+# - 'en' instead of 'en-US'
+mac_policy_templates_languages = [
+ "am",
+ "ar_EG",
+ "bg_BG",
+ "ms_BN",
+ "ca_ES",
+ "cs_CZ",
+ "da_DK",
+ "de_DE",
+ "el_GR",
+ "en_GB",
+ "en",
+ "es_ES",
+ "es_419",
+ "et_EE",
+ "fa_IR",
+ "fi_FI",
+ "fil",
+ "fr_FR",
+ "gu_IN",
+ "he_IL",
+ "hi_IN",
+ "hr_HR",
+ "hu_HU",
+ "id_ID",
+ "it_IT",
+ "ja_JP",
+ "kn_IN",
+ "ko_KR",
+ "lt_LT",
+ "lv_LV",
+ "ml",
+ "mr_IN",
+ "ms_MY",
+ "nl_NL",
+ "nb_NO",
+ "pl_PL",
+ "pt_BR",
+ "pt_PT",
+ "ro_RO",
+ "ru_RU",
+ "sk_SK",
+ "sl_SI",
+ "Cy_sr_SP",
+ "sv_SE",
+ "sw_KE",
+ "ta_IN",
+ "te_IN",
+ "th_TH",
+ "tr_TR",
+ "uk_UA",
+ "vi_VN",
+ "zh_CN",
+ "zh_TW",
+]
+
policy_templates_languages_str = ""
foreach(lang, policy_templates_languages) {
# Note: The final , is filtered out by scripts. There's no string.join here...
@@ -78,7 +139,9 @@ policy_templates_translation_json_path =
"$policy_templates_base_dir/translations/policy_templates_\${lang}.json"
policy_templates_translation_outputs = []
foreach(lang, policy_templates_languages) {
- policy_templates_translation_outputs += [ "$policy_templates_base_dir/translations/policy_templates_${lang}.json" ]
+ policy_templates_translation_outputs += [
+ "$policy_templates_base_dir/translations/policy_templates_${lang}.json",
+ ]
}
# Android outputs.
@@ -91,7 +154,9 @@ policy_templates_doc_path =
"$policy_templates_base_dir/common/html/\${lang}/chrome_policy_list.html"
policy_templates_common_outputs = []
foreach(lang, policy_templates_languages) {
- policy_templates_common_outputs += [ "$policy_templates_base_dir/common/html/${lang}/chrome_policy_list.html" ]
+ policy_templates_common_outputs += [
+ "$policy_templates_base_dir/common/html/${lang}/chrome_policy_list.html",
+ ]
}
# Linux outputs.
@@ -105,24 +170,10 @@ policy_templates_plist_path =
policy_templates_plist_strings_path =
"$policy_templates_base_dir/mac/strings/\${lang}.lproj/Localizable.strings"
policy_templates_mac_outputs = [ policy_templates_plist_path ]
-foreach(lang, policy_templates_languages) {
- # Mac uses a slightly different naming convention for languages.
- if (lang == "en-US") {
- lang = "en"
- } else if (lang == "en-GB") {
- lang = "en_GB"
- } else if (lang == "es-419") {
- lang = "es_419"
- } else if (lang == "pt-BR") {
- lang = "pt_BR"
- } else if (lang == "pt-PT") {
- lang = "pt_PT"
- } else if (lang == "zh-CN") {
- lang = "zh_CN"
- } else if (lang == "zh-TW") {
- lang = "zh_TW"
- }
- policy_templates_mac_outputs += [ "$policy_templates_base_dir/mac/strings/${lang}.lproj/Localizable.strings" ]
+foreach(lang, mac_policy_templates_languages) {
+ policy_templates_mac_outputs += [
+ "$policy_templates_base_dir/mac/strings/${lang}.lproj/Localizable.strings",
+ ]
}
# Windows outputs.
diff --git a/chromium/components/policy_strings.grdp b/chromium/components/policy_strings.grdp
index aca914809bb..9fb732cec80 100644
--- a/chromium/components/policy_strings.grdp
+++ b/chromium/components/policy_strings.grdp
@@ -268,9 +268,6 @@
<message name="IDS_EXPORT_POLICIES_JSON" desc="Label for the button that exports policies in JSON format.">
Export to JSON
</message>
- <message name="IDS_POLICY_CHROME_FOR_WORK" desc="Title of the link to the chrome for work website.">
- Using Chrome at work? Businesses can manage Chrome settings for their employees. Learn more
- </message>
<message name="IDS_POLICY_STATUS" desc="Title of the status section.">
Status
</message>
diff --git a/chromium/components/prefs/json_pref_store.cc b/chromium/components/prefs/json_pref_store.cc
index 38b6daead06..5c6cad1bd5b 100644
--- a/chromium/components/prefs/json_pref_store.cc
+++ b/chromium/components/prefs/json_pref_store.cc
@@ -287,8 +287,8 @@ void JsonPrefStore::CommitPendingWrite(base::OnceClosure done_callback) {
// posted to |file_task_runner_| will run after currently pending disk
// operations. Also, by definition of PostTaskAndReply(), the reply will run
// on the current sequence.
- file_task_runner_->PostTaskAndReply(
- FROM_HERE, base::BindOnce(&base::DoNothing), std::move(done_callback));
+ file_task_runner_->PostTaskAndReply(FROM_HERE, base::DoNothing(),
+ std::move(done_callback));
}
}
diff --git a/chromium/components/prefs/json_pref_store_unittest.cc b/chromium/components/prefs/json_pref_store_unittest.cc
index b0e2229fcb0..2d63df8bec7 100644
--- a/chromium/components/prefs/json_pref_store_unittest.cc
+++ b/chromium/components/prefs/json_pref_store_unittest.cc
@@ -26,7 +26,6 @@
#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread.h"
#include "base/values.h"
#include "components/prefs/persistent_pref_store_unittest.h"
diff --git a/chromium/components/prefs/pref_change_registrar_unittest.cc b/chromium/components/prefs/pref_change_registrar_unittest.cc
index 4027618a460..5cfaa2b3b43 100644
--- a/chromium/components/prefs/pref_change_registrar_unittest.cc
+++ b/chromium/components/prefs/pref_change_registrar_unittest.cc
@@ -44,9 +44,7 @@ class PrefChangeRegistrarTest : public testing::Test {
protected:
void SetUp() override;
- base::Closure observer() const {
- return base::Bind(&base::DoNothing);
- }
+ base::Closure observer() const { return base::DoNothing(); }
MockPrefService* service() const { return service_.get(); }
@@ -138,7 +136,7 @@ class ObserveSetOfPreferencesTest : public testing::Test {
PrefChangeRegistrar* CreatePrefChangeRegistrar() {
PrefChangeRegistrar* pref_set = new PrefChangeRegistrar();
- base::Closure callback = base::Bind(&base::DoNothing);
+ base::Closure callback = base::DoNothing();
pref_set->Init(pref_service_.get());
pref_set->Add(kHomePage, callback);
pref_set->Add(kHomePageIsNewTabPage, callback);
diff --git a/chromium/components/prefs/pref_registry_simple.cc b/chromium/components/prefs/pref_registry_simple.cc
index f7d1ef379b0..670a4b44df7 100644
--- a/chromium/components/prefs/pref_registry_simple.cc
+++ b/chromium/components/prefs/pref_registry_simple.cc
@@ -10,84 +10,8 @@
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
-PrefRegistrySimple::PrefRegistrySimple() {
-}
-
-PrefRegistrySimple::~PrefRegistrySimple() {
-}
-
-void PrefRegistrySimple::RegisterBooleanPref(const std::string& path,
- bool default_value) {
- RegisterPreference(path, std::make_unique<base::Value>(default_value),
- NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterIntegerPref(const std::string& path,
- int default_value) {
- RegisterPreference(path, std::make_unique<base::Value>(default_value),
- NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterDoublePref(const std::string& path,
- double default_value) {
- RegisterPreference(path, std::make_unique<base::Value>(default_value),
- NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterStringPref(const std::string& path,
- const std::string& default_value) {
- RegisterPreference(path, std::make_unique<base::Value>(default_value),
- NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterFilePathPref(
- const std::string& path,
- const base::FilePath& default_value) {
- RegisterPreference(path, std::make_unique<base::Value>(default_value.value()),
- NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterListPref(const std::string& path) {
- RegisterPreference(path, std::make_unique<base::ListValue>(),
- NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterListPref(
- const std::string& path,
- std::unique_ptr<base::ListValue> default_value) {
- RegisterPreference(path, std::move(default_value), NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterDictionaryPref(const std::string& path) {
- RegisterPreference(path, std::make_unique<base::DictionaryValue>(),
- NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterDictionaryPref(
- const std::string& path,
- std::unique_ptr<base::DictionaryValue> default_value) {
- RegisterPreference(path, std::move(default_value), NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterInt64Pref(const std::string& path,
- int64_t default_value) {
- RegisterPreference(
- path, std::make_unique<base::Value>(base::Int64ToString(default_value)),
- NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterUint64Pref(const std::string& path,
- uint64_t default_value) {
- RegisterPreference(
- path, std::make_unique<base::Value>(base::NumberToString(default_value)),
- NO_REGISTRATION_FLAGS);
-}
-
-void PrefRegistrySimple::RegisterTimePref(const std::string& path,
- base::Time default_value) {
- RegisterInt64Pref(path,
- default_value.ToDeltaSinceWindowsEpoch().InMicroseconds());
-}
+PrefRegistrySimple::PrefRegistrySimple() = default;
+PrefRegistrySimple::~PrefRegistrySimple() = default;
void PrefRegistrySimple::RegisterBooleanPref(const std::string& path,
bool default_value,
diff --git a/chromium/components/prefs/pref_registry_simple.h b/chromium/components/prefs/pref_registry_simple.h
index e68301c4a78..5e01cc4ecc1 100644
--- a/chromium/components/prefs/pref_registry_simple.h
+++ b/chromium/components/prefs/pref_registry_simple.h
@@ -26,59 +26,54 @@ class COMPONENTS_PREFS_EXPORT PrefRegistrySimple : public PrefRegistry {
public:
PrefRegistrySimple();
- void RegisterBooleanPref(const std::string& path, bool default_value);
- void RegisterIntegerPref(const std::string& path, int default_value);
- void RegisterDoublePref(const std::string& path, double default_value);
- void RegisterStringPref(const std::string& path,
- const std::string& default_value);
- void RegisterFilePathPref(const std::string& path,
- const base::FilePath& default_value);
- void RegisterListPref(const std::string& path);
- void RegisterDictionaryPref(const std::string& path);
- void RegisterListPref(const std::string& path,
- std::unique_ptr<base::ListValue> default_value);
- void RegisterDictionaryPref(
- const std::string& path,
- std::unique_ptr<base::DictionaryValue> default_value);
- void RegisterInt64Pref(const std::string& path, int64_t default_value);
- void RegisterUint64Pref(const std::string&, uint64_t default_value);
- void RegisterTimePref(const std::string& path, base::Time default_value);
-
- // Versions of registration functions that accept PrefRegistrationFlags.
- // |flags| is a bitmask of PrefRegistrationFlags.
- void RegisterBooleanPref(const std::string&,
+ // For each of these registration methods, |flags| is an optional bitmask of
+ // PrefRegistrationFlags.
+ void RegisterBooleanPref(const std::string& path,
bool default_value,
- uint32_t flags);
- void RegisterIntegerPref(const std::string&,
+ uint32_t flags = NO_REGISTRATION_FLAGS);
+
+ void RegisterIntegerPref(const std::string& path,
int default_value,
- uint32_t flags);
- void RegisterDoublePref(const std::string&,
+ uint32_t flags = NO_REGISTRATION_FLAGS);
+
+ void RegisterDoublePref(const std::string& path,
double default_value,
- uint32_t flags);
- void RegisterStringPref(const std::string&,
+ uint32_t flags = NO_REGISTRATION_FLAGS);
+
+ void RegisterStringPref(const std::string& path,
const std::string& default_value,
- uint32_t flags);
- void RegisterFilePathPref(const std::string&,
+ uint32_t flags = NO_REGISTRATION_FLAGS);
+
+ void RegisterFilePathPref(const std::string& path,
const base::FilePath& default_value,
- uint32_t flags);
- void RegisterListPref(const std::string&, uint32_t flags);
- void RegisterDictionaryPref(const std::string&, uint32_t flags);
- void RegisterListPref(const std::string&,
+ uint32_t flags = NO_REGISTRATION_FLAGS);
+
+ void RegisterListPref(const std::string& path,
+ uint32_t flags = NO_REGISTRATION_FLAGS);
+
+ void RegisterListPref(const std::string& path,
std::unique_ptr<base::ListValue> default_value,
- uint32_t flags);
+ uint32_t flags = NO_REGISTRATION_FLAGS);
+
+ void RegisterDictionaryPref(const std::string& path,
+ uint32_t flags = NO_REGISTRATION_FLAGS);
+
void RegisterDictionaryPref(
- const std::string&,
+ const std::string& path,
std::unique_ptr<base::DictionaryValue> default_value,
- uint32_t flags);
- void RegisterInt64Pref(const std::string&,
+ uint32_t flags = NO_REGISTRATION_FLAGS);
+
+ void RegisterInt64Pref(const std::string& path,
int64_t default_value,
- uint32_t flags);
- void RegisterUint64Pref(const std::string&,
+ uint32_t flags = NO_REGISTRATION_FLAGS);
+
+ void RegisterUint64Pref(const std::string& path,
uint64_t default_value,
- uint32_t flags);
- void RegisterTimePref(const std::string&,
+ uint32_t flags = NO_REGISTRATION_FLAGS);
+
+ void RegisterTimePref(const std::string& path,
base::Time default_value,
- uint32_t flags);
+ uint32_t flags = NO_REGISTRATION_FLAGS);
protected:
~PrefRegistrySimple() override;
diff --git a/chromium/components/prefs/pref_service.cc b/chromium/components/prefs/pref_service.cc
index 592d429c0ef..ab9b9e5d36f 100644
--- a/chromium/components/prefs/pref_service.cc
+++ b/chromium/components/prefs/pref_service.cc
@@ -30,7 +30,7 @@ namespace {
class ReadErrorHandler : public PersistentPrefStore::ReadErrorDelegate {
public:
using ErrorCallback =
- base::Callback<void(PersistentPrefStore::PrefReadError)>;
+ base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>;
explicit ReadErrorHandler(ErrorCallback cb) : callback_(cb) {}
void OnError(PersistentPrefStore::PrefReadError error) override {
@@ -61,35 +61,26 @@ uint32_t GetWriteFlags(const PrefService::Preference* pref) {
PrefService::PrefService(
std::unique_ptr<PrefNotifierImpl> pref_notifier,
std::unique_ptr<PrefValueStore> pref_value_store,
- PersistentPrefStore* user_prefs,
- PrefRegistry* pref_registry,
- base::Callback<void(PersistentPrefStore::PrefReadError)>
+ scoped_refptr<PersistentPrefStore> user_prefs,
+ scoped_refptr<PrefRegistry> pref_registry,
+ base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>
read_error_callback,
bool async)
: pref_notifier_(std::move(pref_notifier)),
pref_value_store_(std::move(pref_value_store)),
- pref_registry_(pref_registry),
- user_pref_store_(user_prefs),
- read_error_callback_(read_error_callback) {
+ pref_registry_(std::move(pref_registry)),
+ user_pref_store_(std::move(user_prefs)),
+ read_error_callback_(std::move(read_error_callback)) {
pref_notifier_->SetPrefService(this);
- // TODO(battre): This is a check for crbug.com/435208 to make sure that
- // access violations are caused by a use-after-free bug and not by an
- // initialization bug.
- CHECK(pref_registry_);
- CHECK(pref_value_store_);
+ DCHECK(pref_registry_);
+ DCHECK(pref_value_store_);
InitFromStorage(async);
}
PrefService::~PrefService() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- // Reset pointers so accesses after destruction reliably crash.
- pref_value_store_.reset();
- pref_registry_ = nullptr;
- user_pref_store_ = nullptr;
- pref_notifier_.reset();
}
void PrefService::InitFromStorage(bool async) {
diff --git a/chromium/components/prefs/pref_service.h b/chromium/components/prefs/pref_service.h
index 68b5439ed9a..7b4b8ff783a 100644
--- a/chromium/components/prefs/pref_service.h
+++ b/chromium/components/prefs/pref_service.h
@@ -166,9 +166,9 @@ class COMPONENTS_PREFS_EXPORT PrefService {
// for simplified construction.
PrefService(std::unique_ptr<PrefNotifierImpl> pref_notifier,
std::unique_ptr<PrefValueStore> pref_value_store,
- PersistentPrefStore* user_prefs,
- PrefRegistry* pref_registry,
- base::Callback<void(PersistentPrefStore::PrefReadError)>
+ scoped_refptr<PersistentPrefStore> user_prefs,
+ scoped_refptr<PrefRegistry> pref_registry,
+ base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>
read_error_callback,
bool async);
virtual ~PrefService();
@@ -347,19 +347,20 @@ class COMPONENTS_PREFS_EXPORT PrefService {
// The PrefNotifier handles registering and notifying preference observers.
// It is created and owned by this PrefService. Subclasses may access it for
// unit testing.
- std::unique_ptr<PrefNotifierImpl> pref_notifier_;
+ const std::unique_ptr<PrefNotifierImpl> pref_notifier_;
// The PrefValueStore provides prioritized preference values. It is owned by
// this PrefService. Subclasses may access it for unit testing.
- std::unique_ptr<PrefValueStore> pref_value_store_;
+ const std::unique_ptr<PrefValueStore> pref_value_store_;
- scoped_refptr<PrefRegistry> pref_registry_;
+ const scoped_refptr<PrefRegistry> pref_registry_;
// Pref Stores and profile that we passed to the PrefValueStore.
- scoped_refptr<PersistentPrefStore> user_pref_store_;
+ const scoped_refptr<PersistentPrefStore> user_pref_store_;
// Callback to call when a read error occurs.
- base::Callback<void(PersistentPrefStore::PrefReadError)> read_error_callback_;
+ const base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>
+ read_error_callback_;
private:
// Hash map expected to be fastest here since it minimises expensive
diff --git a/chromium/components/prefs/pref_service_factory.cc b/chromium/components/prefs/pref_service_factory.cc
index b7b0edd8ec3..5d52eecd401 100644
--- a/chromium/components/prefs/pref_service_factory.cc
+++ b/chromium/components/prefs/pref_service_factory.cc
@@ -15,17 +15,8 @@
#include "components/prefs/pref_service.h"
#include "components/prefs/pref_value_store.h"
-namespace {
-
-// Do-nothing default implementation.
-void DoNothingHandleReadError(PersistentPrefStore::PrefReadError error) {
-}
-
-} // namespace
-
PrefServiceFactory::PrefServiceFactory()
- : read_error_callback_(base::Bind(&DoNothingHandleReadError)),
- async_(false) {}
+ : read_error_callback_(base::DoNothing()), async_(false) {}
PrefServiceFactory::~PrefServiceFactory() {}
@@ -37,7 +28,7 @@ void PrefServiceFactory::SetUserPrefsFile(
}
std::unique_ptr<PrefService> PrefServiceFactory::Create(
- PrefRegistry* pref_registry,
+ scoped_refptr<PrefRegistry> pref_registry,
std::unique_ptr<PrefValueStore::Delegate> delegate) {
auto pref_notifier = std::make_unique<PrefNotifierImpl>();
auto pref_value_store = std::make_unique<PrefValueStore>(
@@ -47,5 +38,5 @@ std::unique_ptr<PrefService> PrefServiceFactory::Create(
pref_notifier.get(), std::move(delegate));
return std::make_unique<PrefService>(
std::move(pref_notifier), std::move(pref_value_store), user_prefs_.get(),
- pref_registry, read_error_callback_, async_);
+ std::move(pref_registry), read_error_callback_, async_);
}
diff --git a/chromium/components/prefs/pref_service_factory.h b/chromium/components/prefs/pref_service_factory.h
index 11b983a2cf9..1f59c6a51bc 100644
--- a/chromium/components/prefs/pref_service_factory.h
+++ b/chromium/components/prefs/pref_service_factory.h
@@ -55,9 +55,9 @@ class COMPONENTS_PREFS_EXPORT PrefServiceFactory {
// Sets up error callback for the PrefService. A do-nothing default
// is provided if this is not called.
void set_read_error_callback(
- const base::Callback<void(PersistentPrefStore::PrefReadError)>&
+ base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>
read_error_callback) {
- read_error_callback_ = read_error_callback;
+ read_error_callback_ = std::move(read_error_callback);
}
// Specifies to use an actual file-backed user pref store.
@@ -71,7 +71,7 @@ class COMPONENTS_PREFS_EXPORT PrefServiceFactory {
// Creates a PrefService object initialized with the parameters from
// this factory.
std::unique_ptr<PrefService> Create(
- PrefRegistry* registry,
+ scoped_refptr<PrefRegistry> pref_registry,
std::unique_ptr<PrefValueStore::Delegate> delegate = nullptr);
protected:
@@ -82,7 +82,8 @@ class COMPONENTS_PREFS_EXPORT PrefServiceFactory {
scoped_refptr<PersistentPrefStore> user_prefs_;
scoped_refptr<PrefStore> recommended_prefs_;
- base::Callback<void(PersistentPrefStore::PrefReadError)> read_error_callback_;
+ base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>
+ read_error_callback_;
// Defaults to false.
bool async_;
diff --git a/chromium/components/previews/content/previews_content_util.cc b/chromium/components/previews/content/previews_content_util.cc
index 69ebc3776e0..2d312006d51 100644
--- a/chromium/components/previews/content/previews_content_util.cc
+++ b/chromium/components/previews/content/previews_content_util.cc
@@ -18,9 +18,13 @@ bool HasEnabledPreviews(content::PreviewsState previews_state) {
content::PreviewsState DetermineEnabledClientPreviewsState(
const net::URLRequest& url_request,
- previews::PreviewsDecider* previews_decider) {
+ const previews::PreviewsDecider* previews_decider) {
content::PreviewsState previews_state = content::PREVIEWS_UNSPECIFIED;
+ if (!previews::params::ArePreviewsAllowed()) {
+ return previews_state;
+ }
+
if (!url_request.url().SchemeIsHTTPOrHTTPS()) {
return previews_state;
}
@@ -28,11 +32,8 @@ content::PreviewsState DetermineEnabledClientPreviewsState(
// Check for client-side previews in precendence order.
// Note: this for for the beginning of navigation so we should not
// check for https here (since an http request may redirect to https).
- if (previews_decider->ShouldAllowPreviewAtECT(
- url_request, previews::PreviewsType::NOSCRIPT,
- previews::params::GetECTThresholdForPreview(
- previews::PreviewsType::NOSCRIPT),
- std::vector<std::string>())) {
+ if (previews_decider->ShouldAllowPreview(url_request,
+ previews::PreviewsType::NOSCRIPT)) {
previews_state |= content::NOSCRIPT_ON;
return previews_state;
}
@@ -51,7 +52,8 @@ content::PreviewsState DetermineEnabledClientPreviewsState(
content::PreviewsState DetermineCommittedClientPreviewsState(
const net::URLRequest& url_request,
- content::PreviewsState previews_state) {
+ content::PreviewsState previews_state,
+ const previews::PreviewsDecider* previews_decider) {
bool is_https = url_request.url().SchemeIs(url::kHttpsScheme);
// If a server preview is set, retain only the bits determined for the server.
@@ -78,14 +80,17 @@ content::PreviewsState DetermineCommittedClientPreviewsState(
return content::PREVIEWS_OFF;
}
- // Make priority decision among allow client preview types that can be decided
- // at Commit time.
+ // Make priority decision among allowed client preview types that can be
+ // decided at Commit time.
if (previews_state & content::NOSCRIPT_ON) {
- if (is_https) {
+ // NoScript was chosen for the original URL but only continue with it
+ // if the committed URL has HTTPS scheme and is allowed by decider.
+ if (is_https && previews_decider &&
+ previews_decider->IsURLAllowedForPreview(
+ url_request, previews::PreviewsType::NOSCRIPT)) {
return content::NOSCRIPT_ON;
- } else {
- previews_state &= ~(content::NOSCRIPT_ON);
}
+ return content::PREVIEWS_OFF;
}
if (previews_state & content::CLIENT_LOFI_ON) {
return content::CLIENT_LOFI_ON;
diff --git a/chromium/components/previews/content/previews_content_util.h b/chromium/components/previews/content/previews_content_util.h
index 6063ef8e388..df779c3e686 100644
--- a/chromium/components/previews/content/previews_content_util.h
+++ b/chromium/components/previews/content/previews_content_util.h
@@ -19,7 +19,7 @@ bool HasEnabledPreviews(content::PreviewsState previews_state);
// definitions for content::PreviewsState.
content::PreviewsState DetermineEnabledClientPreviewsState(
const net::URLRequest& url_request,
- previews::PreviewsDecider* previews_decider);
+ const previews::PreviewsDecider* previews_decider);
// Returns an updated PreviewsState given |previews_state| that has already
// been updated wrt server previews. This should be called at Navigation Commit
@@ -27,7 +27,8 @@ content::PreviewsState DetermineEnabledClientPreviewsState(
// client preview bits to retain for processing the main frame response.
content::PreviewsState DetermineCommittedClientPreviewsState(
const net::URLRequest& url_request,
- content::PreviewsState previews_state);
+ content::PreviewsState previews_state,
+ const previews::PreviewsDecider* previews_decider);
// Returns the effective PreviewsType known on a main frame basis given the
// |previews_state| bitmask for the committed main frame. This uses the same
diff --git a/chromium/components/previews/content/previews_content_util_unittest.cc b/chromium/components/previews/content/previews_content_util_unittest.cc
index 6989f32cecc..5d0c259a3e2 100644
--- a/chromium/components/previews/content/previews_content_util_unittest.cc
+++ b/chromium/components/previews/content/previews_content_util_unittest.cc
@@ -20,10 +20,12 @@ namespace previews {
namespace {
-class TestPreviewsDecider : public PreviewsDecider {
+// A test implementation of PreviewsDecider that simply returns whether the
+// preview type feature is enabled (ignores ECT and blacklist considerations).
+class PreviewEnabledPreviewsDecider : public PreviewsDecider {
public:
- TestPreviewsDecider() {}
- ~TestPreviewsDecider() override {}
+ PreviewEnabledPreviewsDecider() {}
+ ~PreviewEnabledPreviewsDecider() override {}
bool ShouldAllowPreviewAtECT(
const net::URLRequest& request,
@@ -31,8 +33,23 @@ class TestPreviewsDecider : public PreviewsDecider {
net::EffectiveConnectionType effective_connection_type_threshold,
const std::vector<std::string>& host_blacklist_from_server)
const override {
- // For these tests, simply return whether client preview feature is enabled
- // or not (ignores ECT and blacklist considerations).
+ return IsEnabled(type);
+ }
+
+ bool ShouldAllowPreview(const net::URLRequest& request,
+ PreviewsType type) const override {
+ return ShouldAllowPreviewAtECT(request, type,
+ params::GetECTThresholdForPreview(type),
+ std::vector<std::string>());
+ }
+
+ bool IsURLAllowedForPreview(const net::URLRequest& request,
+ PreviewsType type) const override {
+ return IsEnabled(type);
+ }
+
+ private:
+ bool IsEnabled(PreviewsType type) const {
switch (type) {
case previews::PreviewsType::OFFLINE:
return previews::params::IsOfflinePreviewsEnabled();
@@ -44,27 +61,23 @@ class TestPreviewsDecider : public PreviewsDecider {
return previews::params::IsNoScriptPreviewsEnabled();
case previews::PreviewsType::LITE_PAGE:
case previews::PreviewsType::NONE:
+ case previews::PreviewsType::UNSPECIFIED:
case previews::PreviewsType::LAST:
break;
}
NOTREACHED();
return false;
}
-
- bool ShouldAllowPreview(const net::URLRequest& request,
- PreviewsType type) const override {
- // Not used for these tests.
- NOTREACHED();
- return false;
- }
};
class PreviewsContentUtilTest : public testing::Test {
public:
- PreviewsContentUtilTest() : previews_decider_(), context_() {}
+ PreviewsContentUtilTest() : enabled_previews_decider_(), context_() {}
~PreviewsContentUtilTest() override {}
- TestPreviewsDecider* previews_decider() { return &previews_decider_; }
+ PreviewsDecider* enabled_previews_decider() {
+ return &enabled_previews_decider_;
+ }
std::unique_ptr<net::URLRequest> CreateRequest() const {
return CreateRequestWithURL(GURL("http://example.com"));
@@ -84,69 +97,101 @@ class PreviewsContentUtilTest : public testing::Test {
base::MessageLoopForIO loop_;
private:
- TestPreviewsDecider previews_decider_;
+ PreviewEnabledPreviewsDecider enabled_previews_decider_;
net::TestURLRequestContext context_;
};
+TEST_F(PreviewsContentUtilTest,
+ DetermineEnabledClientPreviewsStatePreviewsDisabled) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine("ClientLoFi" /* enable_features */,
+ "Previews" /* disable_features */);
+ EXPECT_EQ(content::PREVIEWS_UNSPECIFIED,
+ previews::DetermineEnabledClientPreviewsState(
+ *CreateHttpsRequest(), enabled_previews_decider()));
+ EXPECT_EQ(content::PREVIEWS_UNSPECIFIED,
+ previews::DetermineEnabledClientPreviewsState(
+ *CreateRequest(), enabled_previews_decider()));
+}
+
TEST_F(PreviewsContentUtilTest, DetermineEnabledClientPreviewsStateClientLoFi) {
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitFromCommandLine("ClientLoFi", std::string());
+ scoped_feature_list.InitFromCommandLine("Previews,ClientLoFi", std::string());
EXPECT_EQ(content::CLIENT_LOFI_ON,
- previews::DetermineEnabledClientPreviewsState(*CreateHttpsRequest(),
- previews_decider()));
+ previews::DetermineEnabledClientPreviewsState(
+ *CreateHttpsRequest(), enabled_previews_decider()));
EXPECT_EQ(content::CLIENT_LOFI_ON,
- previews::DetermineEnabledClientPreviewsState(*CreateRequest(),
- previews_decider()));
+ previews::DetermineEnabledClientPreviewsState(
+ *CreateRequest(), enabled_previews_decider()));
}
TEST_F(PreviewsContentUtilTest,
DetermineEnabledClientPreviewsStateNoScriptAndClientLoFi) {
- // First, verify no client previews enabled.
- EXPECT_EQ(content::PREVIEWS_UNSPECIFIED,
- previews::DetermineEnabledClientPreviewsState(*CreateHttpsRequest(),
- previews_decider()));
-
- // Now, enable both Client LoFi and NoScript.
+ // Enable both Client LoFi and NoScript.
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitFromCommandLine("ClientLoFi,NoScriptPreviews",
- std::string());
+ scoped_feature_list.InitFromCommandLine(
+ "Previews,ClientLoFi,NoScriptPreviews", std::string());
// Verify NoScript takes precendence over LoFi (for https).
EXPECT_EQ(content::NOSCRIPT_ON,
- previews::DetermineEnabledClientPreviewsState(*CreateHttpsRequest(),
- previews_decider()));
- EXPECT_EQ(content::NOSCRIPT_ON, previews::DetermineEnabledClientPreviewsState(
- *CreateRequest(), previews_decider()));
+ previews::DetermineEnabledClientPreviewsState(
+ *CreateHttpsRequest(), enabled_previews_decider()));
+ EXPECT_EQ(content::NOSCRIPT_ON,
+ previews::DetermineEnabledClientPreviewsState(
+ *CreateRequest(), enabled_previews_decider()));
// Verify non-HTTP[S] URL has no previews enabled.
std::unique_ptr<net::URLRequest> data_url_request(
CreateRequestWithURL(GURL("data://someblob")));
EXPECT_EQ(content::PREVIEWS_UNSPECIFIED,
- previews::DetermineEnabledClientPreviewsState(*data_url_request,
- previews_decider()));
+ previews::DetermineEnabledClientPreviewsState(
+ *data_url_request, enabled_previews_decider()));
}
-TEST_F(PreviewsContentUtilTest,
- DetermineCommittedClientPreviewsStateClientLoFi) {
+TEST_F(PreviewsContentUtilTest, DetermineCommittedClientPreviewsState) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(
+ "Previews,ClientLoFi,NoScriptPreviews", std::string());
// Server bits take precendence over NoScript:
EXPECT_EQ(content::SERVER_LITE_PAGE_ON | content::SERVER_LOFI_ON |
content::CLIENT_LOFI_ON,
previews::DetermineCommittedClientPreviewsState(
*CreateHttpsRequest(),
content::SERVER_LITE_PAGE_ON | content::SERVER_LOFI_ON |
- content::CLIENT_LOFI_ON | content::NOSCRIPT_ON));
+ content::CLIENT_LOFI_ON | content::NOSCRIPT_ON,
+ enabled_previews_decider()));
- // For HTTPS, NoScript has precendence over Client LoFi:
- EXPECT_EQ(content::NOSCRIPT_ON,
+ // NoScript has precedence over Client LoFi - kept for committed HTTPS:
+ EXPECT_EQ(
+ content::NOSCRIPT_ON,
+ previews::DetermineCommittedClientPreviewsState(
+ *CreateHttpsRequest(), content::CLIENT_LOFI_ON | content::NOSCRIPT_ON,
+ enabled_previews_decider()));
+
+ // NoScript has precedence over Client LoFi - dropped for committed HTTP:
+ EXPECT_EQ(
+ content::PREVIEWS_OFF,
+ previews::DetermineCommittedClientPreviewsState(
+ *CreateRequest(), content::CLIENT_LOFI_ON | content::NOSCRIPT_ON,
+ enabled_previews_decider()));
+
+ // Client LoFi:
+ EXPECT_EQ(content::CLIENT_LOFI_ON,
previews::DetermineCommittedClientPreviewsState(
- *CreateHttpsRequest(),
- content::CLIENT_LOFI_ON | content::NOSCRIPT_ON));
+ *CreateHttpsRequest(), content::CLIENT_LOFI_ON,
+ enabled_previews_decider()));
+}
- // HTTP allows Client LoFi:
+TEST_F(PreviewsContentUtilTest,
+ DetermineCommittedClientPreviewsStateNoScriptCheckIfStillAllowed) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine("Previews,ClientLoFi", std::string());
+ // NoScript not allowed at commit time so Client LoFi chosen:
EXPECT_EQ(
- content::CLIENT_LOFI_ON,
+ content::PREVIEWS_OFF,
previews::DetermineCommittedClientPreviewsState(
- *CreateRequest(), content::CLIENT_LOFI_ON | content::NOSCRIPT_ON));
+ *CreateHttpsRequest(), content::CLIENT_LOFI_ON | content::NOSCRIPT_ON,
+ enabled_previews_decider()));
}
TEST_F(PreviewsContentUtilTest, GetMainFramePreviewsType) {
diff --git a/chromium/components/previews/content/previews_io_data.cc b/chromium/components/previews/content/previews_io_data.cc
index 7f85fac72c0..69bf9ac553a 100644
--- a/chromium/components/previews/content/previews_io_data.cc
+++ b/chromium/components/previews/content/previews_io_data.cc
@@ -5,6 +5,7 @@
#include "components/previews/content/previews_io_data.h"
#include <algorithm>
+#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -54,6 +55,7 @@ bool AllowedOnReload(PreviewsType type) {
case PreviewsType::OFFLINE:
return false;
case PreviewsType::NONE:
+ case PreviewsType::UNSPECIFIED:
case PreviewsType::LAST:
break;
}
@@ -72,6 +74,7 @@ bool IsServerWhitelistedType(PreviewsType type) {
case PreviewsType::AMP_REDIRECTION:
return false;
case PreviewsType::NONE:
+ case PreviewsType::UNSPECIFIED:
case PreviewsType::LAST:
break;
}
@@ -109,9 +112,9 @@ void PreviewsIOData::Initialize(
// Set up the IO thread portion of |this|.
io_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&PreviewsIOData::InitializeOnIOThread, base::Unretained(this),
- base::Passed(&previews_opt_out_store)));
+ FROM_HERE, base::BindOnce(&PreviewsIOData::InitializeOnIOThread,
+ base::Unretained(this),
+ std::move(previews_opt_out_store)));
}
void PreviewsIOData::OnNewBlacklistedHost(const std::string& host,
@@ -172,9 +175,9 @@ void PreviewsIOData::LogPreviewDecisionMade(
uint64_t page_id) const {
LogPreviewsEligibilityReason(reason, type);
ui_task_runner_->PostTask(
- FROM_HERE, base::Bind(&PreviewsUIService::LogPreviewDecisionMade,
- previews_ui_service_, reason, url, time, type,
- base::Passed(std::move(passed_reasons)), page_id));
+ FROM_HERE, base::BindOnce(&PreviewsUIService::LogPreviewDecisionMade,
+ previews_ui_service_, reason, url, time, type,
+ std::move(passed_reasons), page_id));
}
void PreviewsIOData::AddPreviewNavigation(const GURL& url,
@@ -214,6 +217,10 @@ bool PreviewsIOData::ShouldAllowPreviewAtECT(
PreviewsType type,
net::EffectiveConnectionType effective_connection_type_threshold,
const std::vector<std::string>& host_blacklist_from_server) const {
+ if (!previews::params::ArePreviewsAllowed()) {
+ return false;
+ }
+
if (!request.url().has_host() || !PreviewsUserData::GetData(request)) {
// Don't capture UMA on this case, as it is not important and can happen
// when navigating to files on disk, etc.
@@ -299,18 +306,15 @@ bool PreviewsIOData::ShouldAllowPreviewAtECT(
if (IsServerWhitelistedType(type)) {
if (params::IsOptimizationHintsEnabled()) {
// Optimization hints are configured, so require whitelist match.
- if (!previews_opt_guide_ ||
- !previews_opt_guide_->IsWhitelisted(request, type)) {
- LogPreviewDecisionMade(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER,
- request.url(), base::Time::Now(), type, std::move(passed_reasons),
- page_id);
+ PreviewsEligibilityReason status =
+ IsPreviewAllowedByOptmizationHints(request, type, &passed_reasons);
+ if (status != PreviewsEligibilityReason::ALLOWED) {
+ LogPreviewDecisionMade(status, request.url(), base::Time::Now(), type,
+ std::move(passed_reasons), page_id);
return false;
}
- passed_reasons.push_back(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER);
} else {
- // Since server optimization guidance not configure, allow the preview
+ // Since server optimization guidance not configured, allow the preview
// but with qualified eligibility reason.
LogPreviewDecisionMade(
PreviewsEligibilityReason::ALLOWED_WITHOUT_OPTIMIZATION_HINTS,
@@ -326,6 +330,56 @@ bool PreviewsIOData::ShouldAllowPreviewAtECT(
return true;
}
+bool PreviewsIOData::IsURLAllowedForPreview(const net::URLRequest& request,
+ PreviewsType type) const {
+ if (previews_black_list_ && !blacklist_ignored_) {
+ std::vector<PreviewsEligibilityReason> passed_reasons;
+ // The blacklist will disallow certain hosts for periods of time based on
+ // user's opting out of the preview.
+ PreviewsEligibilityReason status = previews_black_list_->IsLoadedAndAllowed(
+ request.url(), type, &passed_reasons);
+ if (status != PreviewsEligibilityReason::ALLOWED) {
+ LogPreviewDecisionMade(status, request.url(), base::Time::Now(), type,
+ std::move(passed_reasons),
+ PreviewsUserData::GetData(request)->page_id());
+ return false;
+ }
+ }
+
+ // Check whitelist from the server, if provided.
+ if (IsServerWhitelistedType(type)) {
+ if (params::IsOptimizationHintsEnabled()) {
+ std::vector<PreviewsEligibilityReason> passed_reasons;
+ PreviewsEligibilityReason status =
+ IsPreviewAllowedByOptmizationHints(request, type, &passed_reasons);
+ if (status != PreviewsEligibilityReason::ALLOWED) {
+ LogPreviewDecisionMade(status, request.url(), base::Time::Now(), type,
+ std::move(passed_reasons),
+ PreviewsUserData::GetData(request)->page_id());
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+PreviewsEligibilityReason PreviewsIOData::IsPreviewAllowedByOptmizationHints(
+ const net::URLRequest& request,
+ PreviewsType type,
+ std::vector<PreviewsEligibilityReason>* passed_reasons) const {
+ if (!previews_opt_guide_)
+ return PreviewsEligibilityReason::ALLOWED;
+
+ // Check optmization guide whitelist.
+ if (!previews_opt_guide_->IsWhitelisted(request, type)) {
+ return PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER;
+ }
+ passed_reasons->push_back(
+ PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER);
+
+ return PreviewsEligibilityReason::ALLOWED;
+}
+
uint64_t PreviewsIOData::GeneratePageId() {
return ++page_id_;
}
diff --git a/chromium/components/previews/content/previews_io_data.h b/chromium/components/previews/content/previews_io_data.h
index a1ce94df473..9304cb947a7 100644
--- a/chromium/components/previews/content/previews_io_data.h
+++ b/chromium/components/previews/content/previews_io_data.h
@@ -68,11 +68,13 @@ class PreviewsIOData : public PreviewsDecider,
base::Time time,
uint64_t page_id) const;
- // Adds log message of preview decision made asynchronously. |passed_reasons|
- // are PreviewsEligibilityReasons that got passed the decision before
- // |reason|. The method takes ownership of |passed_reasons|. |page_id| is
- // generated by PreviewsIOData, and used to group decisions into groups on the
- // page, messages that don't need to be grouped can pass in 0 as page_id.
+ // Adds a log message for the preview decision made (|reason|) asynchronously.
+ // |passed_reasons| is a collection of reason codes that correspond to
+ // eligibility checks that were satisfied prior to determining |reason| and
+ // so the opposite of these |passed_reasons| codes was true. The method
+ // takes ownership of |passed_reasons|. |page_id| is generated by
+ // PreviewsIOData, and used to group decisions into groups on the page,
+ // messages that don't need to be grouped can pass in 0 as page_id.
void LogPreviewDecisionMade(
PreviewsEligibilityReason reason,
const GURL& url,
@@ -107,6 +109,8 @@ class PreviewsIOData : public PreviewsDecider,
net::EffectiveConnectionType effective_connection_type_threshold,
const std::vector<std::string>& host_blacklist_from_server)
const override;
+ bool IsURLAllowedForPreview(const net::URLRequest& request,
+ PreviewsType type) const override;
// Generates a page ID that is guaranteed to be unique from any other page ID
// generated in this browser session. Also, guaranteed to be non-zero.
@@ -123,6 +127,14 @@ class PreviewsIOData : public PreviewsDecider,
std::unique_ptr<PreviewsBlackList> previews_back_list);
private:
+ // Whether |request| is allowed for |type| according to server provided
+ // optimization hints, if available. Returns ALLOWED if no optimization
+ // hints are available.
+ PreviewsEligibilityReason IsPreviewAllowedByOptmizationHints(
+ const net::URLRequest& request,
+ PreviewsType type,
+ std::vector<PreviewsEligibilityReason>* passed_reasons) const;
+
// The UI thread portion of the inter-thread communication for previews.
base::WeakPtr<PreviewsUIService> previews_ui_service_;
diff --git a/chromium/components/previews/content/previews_io_data_unittest.cc b/chromium/components/previews/content/previews_io_data_unittest.cc
index eae65287c30..63230114aff 100644
--- a/chromium/components/previews/content/previews_io_data_unittest.cc
+++ b/chromium/components/previews/content/previews_io_data_unittest.cc
@@ -8,6 +8,7 @@
#include <map>
#include <memory>
#include <string>
+#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -69,6 +70,7 @@ bool IsPreviewFieldTrialEnabled(PreviewsType type) {
case PreviewsType::NOSCRIPT:
return params::IsNoScriptPreviewsEnabled();
case PreviewsType::NONE:
+ case PreviewsType::UNSPECIFIED:
case PreviewsType::LAST:
break;
}
@@ -317,9 +319,9 @@ class TestPreviewsOptOutStore : public PreviewsOptOutStore {
std::unique_ptr<PreviewsBlackListItem> host_indifferent_black_list_item =
PreviewsBlackList::CreateHostIndifferentBlackListItem();
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&RunLoadCallback, callback,
- base::Passed(&black_list_item_map),
- base::Passed(&host_indifferent_black_list_item)));
+ FROM_HERE, base::BindOnce(&RunLoadCallback, callback,
+ std::move(black_list_item_map),
+ std::move(host_indifferent_black_list_item)));
}
void ClearBlackList(base::Time begin_time, base::Time end_time) override {}
@@ -407,15 +409,6 @@ class PreviewsIODataTest : public testing::Test {
net::TestURLRequestContext context_;
};
-void CreateFieldTrialWithParams(
- const std::string& trial_name,
- const std::string& group_name,
- std::initializer_list<
- typename std::map<std::string, std::string>::value_type> params) {
- EXPECT_TRUE(base::AssociateFieldTrialParams(trial_name, group_name, params));
- EXPECT_TRUE(base::FieldTrialList::CreateFieldTrial(trial_name, group_name));
-}
-
TEST_F(PreviewsIODataTest, TestInitialization) {
InitializeUIService();
// After the outstanding posted tasks have run, |io_data_| should be fully
@@ -423,10 +416,34 @@ TEST_F(PreviewsIODataTest, TestInitialization) {
EXPECT_TRUE(io_data()->initialized());
}
+TEST_F(PreviewsIODataTest, AllPreviewsDisabledByFeature) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kClientLoFi, features::kNoScriptPreviews},
+ {features::kPreviews} /* disable_features */);
+ InitializeUIService();
+
+ network_quality_estimator()->set_effective_connection_type(
+ net::EFFECTIVE_CONNECTION_TYPE_2G);
+
+ EXPECT_FALSE(io_data()->ShouldAllowPreviewAtECT(
+ *CreateHttpsRequest(), PreviewsType::LOFI,
+ previews::params::GetECTThresholdForPreview(
+ previews::PreviewsType::NOSCRIPT),
+ std::vector<std::string>()));
+ EXPECT_FALSE(io_data()->ShouldAllowPreviewAtECT(
+ *CreateHttpsRequest(), PreviewsType::NOSCRIPT,
+ previews::params::GetECTThresholdForPreview(
+ previews::PreviewsType::NOSCRIPT),
+ std::vector<std::string>()));
+}
+
// Tests most of the reasons that a preview could be disallowed because of the
// state of the blacklist. Excluded values are USER_RECENTLY_OPTED_OUT,
// USER_BLACKLISTED, HOST_BLACKLISTED. These are internal to the blacklist.
TEST_F(PreviewsIODataTest, TestDisallowPreviewBecauseOfBlackListState) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kPreviews);
std::unique_ptr<net::URLRequest> request = CreateRequest();
base::HistogramTester histogram_tester;
@@ -458,10 +475,14 @@ TEST_F(PreviewsIODataTest, TestDisallowPreviewBecauseOfBlackListState) {
"Previews.EligibilityReason.Offline",
static_cast<int>(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED),
1);
+ histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 0);
+
variations::testing::ClearAllVariationParams();
}
TEST_F(PreviewsIODataTest, TestDisallowOfflineWhenNetworkQualityUnavailable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kPreviews);
InitializeUIService();
network_quality_estimator()->set_effective_connection_type(
@@ -477,9 +498,11 @@ TEST_F(PreviewsIODataTest, TestDisallowOfflineWhenNetworkQualityUnavailable) {
}
TEST_F(PreviewsIODataTest, TestAllowLitePageWhenNetworkQualityFast) {
- // LoFi and LitePage check NQE on their own.
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kPreviews);
InitializeUIService();
+ // LoFi and LitePage check NQE on their own.
network_quality_estimator()->set_effective_connection_type(
net::EFFECTIVE_CONNECTION_TYPE_3G);
@@ -493,6 +516,8 @@ TEST_F(PreviewsIODataTest, TestAllowLitePageWhenNetworkQualityFast) {
}
TEST_F(PreviewsIODataTest, TestDisallowOfflineWhenNetworkQualityFast) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kPreviews);
InitializeUIService();
network_quality_estimator()->set_effective_connection_type(
@@ -506,6 +531,8 @@ TEST_F(PreviewsIODataTest, TestDisallowOfflineWhenNetworkQualityFast) {
}
TEST_F(PreviewsIODataTest, TestDisallowOfflineOnReload) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kPreviews);
InitializeUIService();
network_quality_estimator()->set_effective_connection_type(
@@ -522,6 +549,8 @@ TEST_F(PreviewsIODataTest, TestDisallowOfflineOnReload) {
}
TEST_F(PreviewsIODataTest, TestAllowOffline) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kPreviews);
InitializeUIService();
network_quality_estimator()->set_effective_connection_type(
@@ -535,20 +564,16 @@ TEST_F(PreviewsIODataTest, TestAllowOffline) {
static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1);
}
-TEST_F(PreviewsIODataTest, ClientLoFiDisallowedByDefault) {
+TEST_F(PreviewsIODataTest, ClientLoFiDisallowedWhenFeatureDisabled) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures({features::kPreviews},
+ {features::kClientLoFi});
InitializeUIService();
- base::HistogramTester histogram_tester;
- EXPECT_FALSE(io_data()->ShouldAllowPreviewAtECT(
- *CreateRequest(), PreviewsType::LOFI,
- params::EffectiveConnectionTypeThresholdForClientLoFi(),
- params::GetBlackListedHostsForClientLoFiFieldTrial()));
- histogram_tester.ExpectTotalCount("Previews.EligibilityReason.LoFi", 0);
-}
-
-TEST_F(PreviewsIODataTest, ClientLoFiDisallowedWhenFieldTrialDisabled) {
- InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Disabled", {});
+ EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G,
+ params::EffectiveConnectionTypeThresholdForClientLoFi());
+ network_quality_estimator()->set_effective_connection_type(
+ net::EFFECTIVE_CONNECTION_TYPE_2G);
base::HistogramTester histogram_tester;
EXPECT_FALSE(io_data()->ShouldAllowPreviewAtECT(
@@ -556,12 +581,13 @@ TEST_F(PreviewsIODataTest, ClientLoFiDisallowedWhenFieldTrialDisabled) {
params::EffectiveConnectionTypeThresholdForClientLoFi(),
params::GetBlackListedHostsForClientLoFiFieldTrial()));
histogram_tester.ExpectTotalCount("Previews.EligibilityReason.LoFi", 0);
- variations::testing::ClearAllVariationParams();
}
TEST_F(PreviewsIODataTest, ClientLoFiDisallowedWhenNetworkQualityUnavailable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled", {});
network_quality_estimator()->set_effective_connection_type(
net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
@@ -575,14 +601,16 @@ TEST_F(PreviewsIODataTest, ClientLoFiDisallowedWhenNetworkQualityUnavailable) {
"Previews.EligibilityReason.LoFi",
static_cast<int>(PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE),
1);
- variations::testing::ClearAllVariationParams();
}
TEST_F(PreviewsIODataTest, ClientLoFiDisallowedWhenNetworkFast) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled",
- {{"max_allowed_effective_connection_type", "2G"}});
+ EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G,
+ params::EffectiveConnectionTypeThresholdForClientLoFi());
network_quality_estimator()->set_effective_connection_type(
net::EFFECTIVE_CONNECTION_TYPE_3G);
@@ -594,14 +622,16 @@ TEST_F(PreviewsIODataTest, ClientLoFiDisallowedWhenNetworkFast) {
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.LoFi",
static_cast<int>(PreviewsEligibilityReason::NETWORK_NOT_SLOW), 1);
- variations::testing::ClearAllVariationParams();
}
TEST_F(PreviewsIODataTest, ClientLoFiAllowed) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled",
- {{"max_allowed_effective_connection_type", "2G"}});
+ EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G,
+ params::EffectiveConnectionTypeThresholdForClientLoFi());
network_quality_estimator()->set_effective_connection_type(
net::EFFECTIVE_CONNECTION_TYPE_2G);
@@ -613,14 +643,16 @@ TEST_F(PreviewsIODataTest, ClientLoFiAllowed) {
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.LoFi",
static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1);
- variations::testing::ClearAllVariationParams();
}
TEST_F(PreviewsIODataTest, MissingHostDisallowed) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled",
- {{"max_allowed_effective_connection_type", "2G"}});
+ EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G,
+ params::EffectiveConnectionTypeThresholdForClientLoFi());
network_quality_estimator()->set_effective_connection_type(
net::EFFECTIVE_CONNECTION_TYPE_2G);
@@ -628,14 +660,16 @@ TEST_F(PreviewsIODataTest, MissingHostDisallowed) {
*CreateRequestWithURL(GURL("file:///sdcard")), PreviewsType::LOFI,
params::EffectiveConnectionTypeThresholdForClientLoFi(),
params::GetBlackListedHostsForClientLoFiFieldTrial()));
- variations::testing::ClearAllVariationParams();
}
TEST_F(PreviewsIODataTest, ClientLoFiAllowedOnReload) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled",
- {{"max_allowed_effective_connection_type", "2G"}});
+ EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G,
+ params::EffectiveConnectionTypeThresholdForClientLoFi());
network_quality_estimator()->set_effective_connection_type(
net::EFFECTIVE_CONNECTION_TYPE_2G);
@@ -650,15 +684,20 @@ TEST_F(PreviewsIODataTest, ClientLoFiAllowedOnReload) {
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.LoFi",
static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1);
- variations::testing::ClearAllVariationParams();
}
TEST_F(PreviewsIODataTest, ClientLoFiObeysHostBlackListFromServer) {
- InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled",
- {{"max_allowed_effective_connection_type", "2G"},
+ base::test::ScopedFeatureList scoped_previews_feature_list;
+ scoped_previews_feature_list.InitAndEnableFeature(features::kPreviews);
+
+ // Use a nested ScopedFeatureList so that parameters can be set.
+ base::test::ScopedFeatureList scoped_lofi_feature_list;
+ scoped_lofi_feature_list.InitAndEnableFeatureWithParameters(
+ features::kClientLoFi, {{"max_allowed_effective_connection_type", "2G"},
{"short_host_blacklist", "foo.com, ,bar.net "}});
+ InitializeUIService();
+
network_quality_estimator()->set_effective_connection_type(
net::EFFECTIVE_CONNECTION_TYPE_2G);
@@ -695,10 +734,11 @@ TEST_F(PreviewsIODataTest, ClientLoFiObeysHostBlackListFromServer) {
: PreviewsEligibilityReason::HOST_BLACKLISTED_BY_SERVER),
1);
}
- variations::testing::ClearAllVariationParams();
}
TEST_F(PreviewsIODataTest, NoScriptDisallowedByDefault) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kPreviews);
InitializeUIService();
network_quality_estimator()->set_effective_connection_type(
@@ -714,9 +754,10 @@ TEST_F(PreviewsIODataTest, NoScriptDisallowedByDefault) {
}
TEST_F(PreviewsIODataTest, NoScriptAllowedByFeature) {
- InitializeUIService();
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(features::kNoScriptPreviews);
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kNoScriptPreviews}, {});
+ InitializeUIService();
network_quality_estimator()->set_effective_connection_type(
net::EFFECTIVE_CONNECTION_TYPE_2G);
@@ -735,10 +776,12 @@ TEST_F(PreviewsIODataTest, NoScriptAllowedByFeature) {
}
TEST_F(PreviewsIODataTest, NoScriptAllowedByFeatureWithWhitelist) {
- InitializeUIService();
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitWithFeatures(
- {features::kNoScriptPreviews, features::kOptimizationHints}, {});
+ {features::kPreviews, features::kNoScriptPreviews,
+ features::kOptimizationHints},
+ {});
+ InitializeUIService();
network_quality_estimator()->set_effective_connection_type(
net::EFFECTIVE_CONNECTION_TYPE_2G);
@@ -771,7 +814,45 @@ TEST_F(PreviewsIODataTest, NoScriptAllowedByFeatureWithWhitelist) {
static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1);
}
+TEST_F(PreviewsIODataTest, NoScriptCommitTimeWhitelistCheck) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kNoScriptPreviews,
+ features::kOptimizationHints},
+ {});
+ InitializeUIService();
+
+ network_quality_estimator()->set_effective_connection_type(
+ net::EFFECTIVE_CONNECTION_TYPE_2G);
+
+ // First verify not allowed for non-whitelisted url.
+ {
+ base::HistogramTester histogram_tester;
+ EXPECT_FALSE(io_data()->IsURLAllowedForPreview(*CreateHttpsRequest(),
+ PreviewsType::NOSCRIPT));
+
+ histogram_tester.ExpectUniqueSample(
+ "Previews.EligibilityReason.NoScript",
+ static_cast<int>(
+ PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER),
+ 1);
+ }
+
+ // Now verify preview for whitelisted url.
+ {
+ base::HistogramTester histogram_tester;
+ EXPECT_TRUE(io_data()->IsURLAllowedForPreview(
+ *CreateRequestWithURL(GURL("https://whitelisted.example.com")),
+ PreviewsType::NOSCRIPT));
+
+ // Expect no eligibility logging.
+ histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 0);
+ }
+}
+
TEST_F(PreviewsIODataTest, LogPreviewNavigationPassInCorrectParams) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kPreviews);
InitializeUIService();
const GURL url("http://www.url_a.com/url_a");
const bool opt_out = true;
@@ -792,6 +873,8 @@ TEST_F(PreviewsIODataTest, LogPreviewNavigationPassInCorrectParams) {
}
TEST_F(PreviewsIODataTest, LogPreviewDecisionMadePassInCorrectParams) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kPreviews);
InitializeUIService();
const PreviewsEligibilityReason reason(
PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE);
@@ -826,8 +909,11 @@ TEST_F(PreviewsIODataTest, LogPreviewDecisionMadePassInCorrectParams) {
} // namespace
TEST_F(PreviewsIODataTest, LogDecisionMadeBlacklistNotAvailable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
+
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled", {});
auto expected_reason = PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE;
auto expected_type = PreviewsType::LOFI;
@@ -844,8 +930,10 @@ TEST_F(PreviewsIODataTest, LogDecisionMadeBlacklistNotAvailable) {
}
TEST_F(PreviewsIODataTest, LogDecisionMadeBlacklistStatusesDefault) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled", {});
PreviewsEligibilityReason expected_reasons[] = {
PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
@@ -879,9 +967,52 @@ TEST_F(PreviewsIODataTest, LogDecisionMadeBlacklistStatusesDefault) {
}
}
+TEST_F(PreviewsIODataTest, IsURLAllowedForPreviewBlacklistStatuses) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kNoScriptPreviews}, {});
+ InitializeUIService();
+ auto expected_type = PreviewsType::NOSCRIPT;
+
+ // First verify URL is allowed for no blacklist status.
+ EXPECT_TRUE(
+ io_data()->IsURLAllowedForPreview(*CreateRequest(), expected_type));
+
+ PreviewsEligibilityReason expected_reasons[] = {
+ PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
+ PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
+ PreviewsEligibilityReason::USER_BLACKLISTED,
+ PreviewsEligibilityReason::HOST_BLACKLISTED,
+ };
+
+ const size_t reasons_size = 4;
+
+ for (size_t i = 0; i < reasons_size; i++) {
+ auto expected_reason = expected_reasons[i];
+
+ std::unique_ptr<TestPreviewsBlackList> blacklist =
+ std::make_unique<TestPreviewsBlackList>(expected_reason, io_data());
+ io_data()->InjectTestBlacklist(std::move(blacklist));
+
+ EXPECT_FALSE(
+ io_data()->IsURLAllowedForPreview(*CreateRequest(), expected_type));
+ base::RunLoop().RunUntilIdle();
+ // Testing correct log method is called.
+ // Check for all decision upto current decision is logged.
+ for (size_t j = 0; j <= i; j++) {
+ EXPECT_THAT(ui_service()->decision_reasons(),
+ ::testing::Contains(expected_reasons[j]));
+ }
+ EXPECT_THAT(ui_service()->decision_types(),
+ ::testing::Contains(expected_type));
+ }
+}
+
TEST_F(PreviewsIODataTest, LogDecisionMadeBlacklistStatusesIgnore) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled", {});
network_quality_estimator()->set_effective_connection_type(
net::EFFECTIVE_CONNECTION_TYPE_2G);
auto expected_reason = PreviewsEligibilityReason::ALLOWED;
@@ -916,8 +1047,10 @@ TEST_F(PreviewsIODataTest, LogDecisionMadeBlacklistStatusesIgnore) {
}
TEST_F(PreviewsIODataTest, LogDecisionMadeNetworkQualityNotAvailable) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled", {});
std::unique_ptr<TestPreviewsBlackList> blacklist =
std::make_unique<TestPreviewsBlackList>(
PreviewsEligibilityReason::ALLOWED, io_data());
@@ -959,8 +1092,10 @@ TEST_F(PreviewsIODataTest, LogDecisionMadeNetworkQualityNotAvailable) {
}
TEST_F(PreviewsIODataTest, LogDecisionMadeNetworkNotSlow) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled", {});
std::unique_ptr<TestPreviewsBlackList> blacklist =
std::make_unique<TestPreviewsBlackList>(
PreviewsEligibilityReason::ALLOWED, io_data());
@@ -1001,9 +1136,15 @@ TEST_F(PreviewsIODataTest, LogDecisionMadeNetworkNotSlow) {
}
TEST_F(PreviewsIODataTest, LogDecisionMadeHostBlacklisted) {
+ base::test::ScopedFeatureList scoped_previews_feature_list;
+ scoped_previews_feature_list.InitAndEnableFeature(features::kPreviews);
+
+ // Use a nested ScopedFeatureList in order to set parameters.
+ base::test::ScopedFeatureList scoped_lofi_feature_list;
+ scoped_lofi_feature_list.InitAndEnableFeatureWithParameters(
+ features::kClientLoFi, {{"short_host_blacklist", "example.com"}});
+
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled",
- {{"short_host_blacklist", "example.com"}});
std::unique_ptr<TestPreviewsBlackList> blacklist =
std::make_unique<TestPreviewsBlackList>(
PreviewsEligibilityReason::ALLOWED, io_data());
@@ -1048,6 +1189,8 @@ TEST_F(PreviewsIODataTest, LogDecisionMadeHostBlacklisted) {
}
TEST_F(PreviewsIODataTest, LogDecisionMadeReloadDisallowed) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kPreviews);
InitializeUIService();
std::unique_ptr<TestPreviewsBlackList> blacklist =
std::make_unique<TestPreviewsBlackList>(
@@ -1094,6 +1237,9 @@ TEST_F(PreviewsIODataTest, LogDecisionMadeReloadDisallowed) {
}
TEST_F(PreviewsIODataTest, IgnoreBlacklistEnabledViaFlag) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
base::test::ScopedCommandLine scoped_command_line;
base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
command_line->AppendSwitch(switches::kIgnorePreviewsBlacklist);
@@ -1103,7 +1249,6 @@ TEST_F(PreviewsIODataTest, IgnoreBlacklistEnabledViaFlag) {
InitializeIOData();
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled", {});
std::unique_ptr<TestPreviewsBlackList> blacklist =
std::make_unique<TestPreviewsBlackList>(
PreviewsEligibilityReason::HOST_BLACKLISTED, io_data());
@@ -1123,8 +1268,10 @@ TEST_F(PreviewsIODataTest, IgnoreBlacklistEnabledViaFlag) {
}
TEST_F(PreviewsIODataTest, LogDecisionMadeAllowPreviewsOnECT) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
InitializeUIService();
- CreateFieldTrialWithParams("PreviewsClientLoFi", "Enabled", {});
std::unique_ptr<TestPreviewsBlackList> blacklist =
std::make_unique<TestPreviewsBlackList>(
diff --git a/chromium/components/previews/content/previews_optimization_guide.cc b/chromium/components/previews/content/previews_optimization_guide.cc
index bcb26b273b4..8923216fe9c 100644
--- a/chromium/components/previews/content/previews_optimization_guide.cc
+++ b/chromium/components/previews/content/previews_optimization_guide.cc
@@ -11,6 +11,7 @@
#include "base/task_runner_util.h"
#include "base/task_scheduler/post_task.h"
#include "components/optimization_guide/proto/hints.pb.h"
+#include "components/previews/core/previews_user_data.h"
#include "net/url_request/url_request.h"
#include "url/gurl.h"
@@ -109,8 +110,11 @@ class PreviewsOptimizationGuide::Hints {
const optimization_guide::proto::Configuration& config,
const optimization_guide::ComponentInfo& info);
- // Whether the URL is whitelisted for the given previews type.
- bool IsWhitelisted(const GURL& url, PreviewsType type);
+ // Whether the URL is whitelisted for the given previews type. If so,
+ // |out_inflation_percent| will be populated if meta data available for it.
+ bool IsWhitelisted(const GURL& url,
+ PreviewsType type,
+ int* out_inflation_percent);
private:
Hints();
@@ -119,9 +123,10 @@ class PreviewsOptimizationGuide::Hints {
// it.
url_matcher::URLMatcher url_matcher_;
- // A map from the condition set ID to the preview types it is whitelisted by
- // the server for.
- std::map<url_matcher::URLMatcherConditionSet::ID, std::set<PreviewsType>>
+ // A map from the condition set ID to associated whitelist Optimization
+ // details.
+ std::map<url_matcher::URLMatcherConditionSet::ID,
+ std::set<std::pair<PreviewsType, int>>>
whitelist_;
};
@@ -175,11 +180,12 @@ PreviewsOptimizationGuide::Hints::CreateFromConfig(
// Create whitelist condition set out of the optimizations that are
// whitelisted for the host suffix.
- std::set<PreviewsType> whitelisted_optimizations;
+ std::set<std::pair<PreviewsType, int>> whitelisted_optimizations;
for (const auto optimization : hint.whitelisted_optimizations()) {
if (optimization.optimization_type() ==
optimization_guide::proto::NOSCRIPT) {
- whitelisted_optimizations.insert(PreviewsType::NOSCRIPT);
+ whitelisted_optimizations.insert(std::make_pair(
+ PreviewsType::NOSCRIPT, optimization.inflation_percent()));
}
}
url_matcher::URLMatcherCondition condition =
@@ -199,8 +205,10 @@ PreviewsOptimizationGuide::Hints::CreateFromConfig(
return hints;
}
-bool PreviewsOptimizationGuide::Hints::IsWhitelisted(const GURL& url,
- PreviewsType type) {
+bool PreviewsOptimizationGuide::Hints::IsWhitelisted(
+ const GURL& url,
+ PreviewsType type,
+ int* out_inflation_percent) {
std::set<url_matcher::URLMatcherConditionSet::ID> matches =
url_matcher_.MatchURL(url);
@@ -216,8 +224,16 @@ bool PreviewsOptimizationGuide::Hints::IsWhitelisted(const GURL& url,
return false;
}
- const auto& whitelisted_previews = whitelist_iter->second;
- return whitelisted_previews.find(type) != whitelisted_previews.end();
+ const auto& whitelisted_optimizations = whitelist_iter->second;
+ for (auto optimization_iter = whitelisted_optimizations.begin();
+ optimization_iter != whitelisted_optimizations.end();
+ ++optimization_iter) {
+ if (optimization_iter->first == type) {
+ *out_inflation_percent = optimization_iter->second;
+ return true;
+ }
+ }
+ return false;
}
PreviewsOptimizationGuide::PreviewsOptimizationGuide(
@@ -241,7 +257,16 @@ bool PreviewsOptimizationGuide::IsWhitelisted(const net::URLRequest& request,
if (!hints_)
return false;
- return hints_->IsWhitelisted(request.url(), type);
+ int inflation_percent = 0;
+ if (!hints_->IsWhitelisted(request.url(), type, &inflation_percent))
+ return false;
+
+ previews::PreviewsUserData* previews_user_data =
+ previews::PreviewsUserData::GetData(request);
+ if (inflation_percent != 0 && previews_user_data)
+ previews_user_data->SetDataSavingsInflationPercent(inflation_percent);
+
+ return true;
}
void PreviewsOptimizationGuide::OnHintsProcessed(
diff --git a/chromium/components/previews/content/previews_optimization_guide_unittest.cc b/chromium/components/previews/content/previews_optimization_guide_unittest.cc
index 0056022b71c..35bed74c7a4 100644
--- a/chromium/components/previews/content/previews_optimization_guide_unittest.cc
+++ b/chromium/components/previews/content/previews_optimization_guide_unittest.cc
@@ -17,6 +17,7 @@
#include "components/optimization_guide/optimization_guide_service.h"
#include "components/optimization_guide/optimization_guide_service_observer.h"
#include "components/optimization_guide/proto/hints.pb.h"
+#include "components/previews/core/previews_user_data.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
@@ -311,6 +312,7 @@ TEST_F(PreviewsOptimizationGuideTest, IsWhitelistedWithMultipleHintMatches) {
optimization_guide::proto::Optimization* optimization1 =
hint1->add_whitelisted_optimizations();
optimization1->set_optimization_type(optimization_guide::proto::NOSCRIPT);
+ optimization1->set_inflation_percent(10);
// No optimizations for sports.yahoo.com:
optimization_guide::proto::Hint* hint2 = config.add_hints();
@@ -324,6 +326,7 @@ TEST_F(PreviewsOptimizationGuideTest, IsWhitelistedWithMultipleHintMatches) {
optimization_guide::proto::Optimization* optimization3 =
hint3->add_whitelisted_optimizations();
optimization3->set_optimization_type(optimization_guide::proto::NOSCRIPT);
+ optimization3->set_inflation_percent(30);
// No optimizations for mail.yahoo.com:
optimization_guide::proto::Hint* hint4 = config.add_hints();
@@ -335,7 +338,10 @@ TEST_F(PreviewsOptimizationGuideTest, IsWhitelistedWithMultipleHintMatches) {
std::unique_ptr<net::URLRequest> request1 =
CreateRequestWithURL(GURL("https://yahoo.com"));
+ previews::PreviewsUserData::Create(request1.get(), 1);
EXPECT_TRUE(guide()->IsWhitelisted(*request1, PreviewsType::NOSCRIPT));
+ EXPECT_EQ(30, previews::PreviewsUserData::GetData(*request1)
+ ->data_savings_inflation_percent());
std::unique_ptr<net::URLRequest> request2 =
CreateRequestWithURL(GURL("https://sports.yahoo.com"));
@@ -344,13 +350,19 @@ TEST_F(PreviewsOptimizationGuideTest, IsWhitelistedWithMultipleHintMatches) {
std::unique_ptr<net::URLRequest> request3 =
CreateRequestWithURL(GURL("https://mail.yahoo.com"));
+ previews::PreviewsUserData::Create(request3.get(), 3);
// Uses "yahoo.com" match before "mail.yahoo.com" match.
EXPECT_TRUE(guide()->IsWhitelisted(*request3, PreviewsType::NOSCRIPT));
+ EXPECT_EQ(30, previews::PreviewsUserData::GetData(*request3)
+ ->data_savings_inflation_percent());
std::unique_ptr<net::URLRequest> request4 =
CreateRequestWithURL(GURL("https://indoor.sports.yahoo.com"));
+ previews::PreviewsUserData::Create(request4.get(), 4);
// Uses "indoor.sports.yahoo.com" match before "sports.yahoo.com" match.
EXPECT_TRUE(guide()->IsWhitelisted(*request4, PreviewsType::NOSCRIPT));
+ EXPECT_EQ(10, previews::PreviewsUserData::GetData(*request4)
+ ->data_savings_inflation_percent());
std::unique_ptr<net::URLRequest> request5 =
CreateRequestWithURL(GURL("https://outdoor.sports.yahoo.com"));
diff --git a/chromium/components/previews/content/previews_ui_service.h b/chromium/components/previews/content/previews_ui_service.h
index 44f356c54a9..7b96f2d52f0 100644
--- a/chromium/components/previews/content/previews_ui_service.h
+++ b/chromium/components/previews/content/previews_ui_service.h
@@ -85,10 +85,12 @@ class PreviewsUIService {
base::Time time,
uint64_t page_id);
- // Log the made decision of previews to PreviewsLogger. |passed_reasons| is a
- // collection of PreviewsEligibilityReasons passed the checks before |reason|.
- // The method takes ownership of |passed_reasons|. |page_id| is generated by
- // PreviewsIOData, and used to group decisions into groups on the page,
+ // Log the determined previews eligibility decision |reason| to the
+ // PreviewsLogger. |passed_reasons| is a collection of reason codes that
+ // correspond to eligibility checks that were satisfied prior to determining
+ // |reason| and so the opposite of these |passed_reasons| codes was true.
+ // The method takes ownership of |passed_reasons|. |page_id| is generated
+ // by PreviewsIOData, and used to group decisions into groups on the page,
// messages that don't need to be grouped can pass in 0 as page_id.
// Virtualized in testing.
virtual void LogPreviewDecisionMade(
diff --git a/chromium/components/previews/core/BUILD.gn b/chromium/components/previews/core/BUILD.gn
index fa7217db164..6ab04816343 100644
--- a/chromium/components/previews/core/BUILD.gn
+++ b/chromium/components/previews/core/BUILD.gn
@@ -25,6 +25,8 @@ static_library("core") {
"previews_switches.h",
"previews_user_data.cc",
"previews_user_data.h",
+ "test_previews_decider.cc",
+ "test_previews_decider.h",
]
deps = [
diff --git a/chromium/components/previews/core/previews_black_list.h b/chromium/components/previews/core/previews_black_list.h
index 2860f7793ae..ef56ed75292 100644
--- a/chromium/components/previews/core/previews_black_list.h
+++ b/chromium/components/previews/core/previews_black_list.h
@@ -61,7 +61,11 @@ enum class PreviewsEligibilityReason {
// The preview is allowed but without an expected check of server optimization
// hints because they are not enabled (features::kOptimizationHints).
ALLOWED_WITHOUT_OPTIMIZATION_HINTS = 11,
- LAST = 9,
+ // The preview type chosen as the committed preview.
+ COMMITTED = 12,
+ // Previews blocked by a Cache-Control:no-transform directive.
+ CACHE_CONTROL_NO_TRANSFORM = 13,
+ LAST,
};
// Manages the state of black listed domains for the previews experiment. Loads
diff --git a/chromium/components/previews/core/previews_black_list_unittest.cc b/chromium/components/previews/core/previews_black_list_unittest.cc
index fa8405357d1..fb851da95fe 100644
--- a/chromium/components/previews/core/previews_black_list_unittest.cc
+++ b/chromium/components/previews/core/previews_black_list_unittest.cc
@@ -9,6 +9,7 @@
#include <memory>
#include <string>
#include <unordered_map>
+#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -128,9 +129,9 @@ class TestPreviewsOptOutStore : public PreviewsOptOutStore {
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(&RunLoadCallback, callback,
- base::Passed(&black_list_item_map_),
- base::Passed(&host_indifferent_black_list_item_)));
+ base::BindOnce(&RunLoadCallback, callback,
+ std::move(black_list_item_map_),
+ std::move(host_indifferent_black_list_item_)));
}
void ClearBlackList(base::Time begin_time, base::Time end_time) override {
diff --git a/chromium/components/previews/core/previews_decider.h b/chromium/components/previews/core/previews_decider.h
index ece8e7632f3..96e706a0e44 100644
--- a/chromium/components/previews/core/previews_decider.h
+++ b/chromium/components/previews/core/previews_decider.h
@@ -37,6 +37,13 @@ class PreviewsDecider {
virtual bool ShouldAllowPreview(const net::URLRequest& request,
PreviewsType type) const = 0;
+ // Whether the URL in |request| is allowed to show a preview of |type|.
+ // This only considers whether the URL is constrained/allowed in
+ // blacklists/whitelists. It does not include other constraints such
+ // as the effective connection type.
+ virtual bool IsURLAllowedForPreview(const net::URLRequest& request,
+ PreviewsType type) const = 0;
+
protected:
PreviewsDecider() {}
virtual ~PreviewsDecider() {}
diff --git a/chromium/components/previews/core/previews_experiments.cc b/chromium/components/previews/core/previews_experiments.cc
index e1604120b62..93f092afb52 100644
--- a/chromium/components/previews/core/previews_experiments.cc
+++ b/chromium/components/previews/core/previews_experiments.cc
@@ -22,8 +22,6 @@ namespace {
// client side blacklist.
const char kClientSidePreviewsFieldTrial[] = "ClientSidePreviews";
-const char kEnabled[] = "Enabled";
-
// Name for the version parameter of a field trial. Version changes will
// result in older blacklist entries being removed.
const char kVersion[] = "version";
@@ -34,8 +32,6 @@ const char kVersion[] = "version";
const char kEffectiveConnectionTypeThreshold[] =
"max_allowed_effective_connection_type";
-const char kClientLoFiExperimentName[] = "PreviewsClientLoFi";
-
// Inflation parameters for estimating NoScript data savings.
const char kNoScriptInflationPercent[] = "NoScriptInflationPercent";
const char kNoScriptInflationBytes[] = "NoScriptInflationBytes";
@@ -71,6 +67,15 @@ net::EffectiveConnectionType GetParamValueAsECT(
.value_or(default_value);
}
+net::EffectiveConnectionType GetParamValueAsECTByFeature(
+ const base::Feature& feature,
+ const std::string& param_name,
+ net::EffectiveConnectionType default_value) {
+ return net::GetEffectiveConnectionTypeForName(
+ base::GetFieldTrialParamValueByFeature(feature, param_name))
+ .value_or(default_value);
+}
+
} // namespace
namespace params {
@@ -133,9 +138,9 @@ net::EffectiveConnectionType GetECTThresholdForPreview(
kEffectiveConnectionTypeThreshold,
net::EFFECTIVE_CONNECTION_TYPE_2G);
case PreviewsType::LOFI:
- return GetParamValueAsECT(kClientLoFiExperimentName,
- kEffectiveConnectionTypeThreshold,
- net::EFFECTIVE_CONNECTION_TYPE_2G);
+ return GetParamValueAsECTByFeature(features::kClientLoFi,
+ kEffectiveConnectionTypeThreshold,
+ net::EFFECTIVE_CONNECTION_TYPE_2G);
case PreviewsType::LITE_PAGE:
NOTREACHED();
break;
@@ -143,6 +148,7 @@ net::EffectiveConnectionType GetECTThresholdForPreview(
return net::EFFECTIVE_CONNECTION_TYPE_LAST; // Trigger irrespective of
// ECT.
case PreviewsType::NONE:
+ case PreviewsType::UNSPECIFIED:
case PreviewsType::LAST:
break;
}
@@ -150,15 +156,16 @@ net::EffectiveConnectionType GetECTThresholdForPreview(
return net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
}
+bool ArePreviewsAllowed() {
+ return base::FeatureList::IsEnabled(features::kPreviews);
+}
+
bool IsOfflinePreviewsEnabled() {
return base::FeatureList::IsEnabled(features::kOfflinePreviews);
}
bool IsClientLoFiEnabled() {
- return base::FeatureList::IsEnabled(features::kClientLoFi) ||
- base::StartsWith(
- base::FieldTrialList::FindFullName(kClientLoFiExperimentName),
- kEnabled, base::CompareCase::SENSITIVE);
+ return base::FeatureList::IsEnabled(features::kClientLoFi);
}
bool IsAMPRedirectionPreviewEnabled() {
@@ -174,7 +181,8 @@ int OfflinePreviewsVersion() {
}
int ClientLoFiVersion() {
- return GetParamValueAsInt(kClientLoFiExperimentName, kVersion, 0);
+ return base::GetFieldTrialParamByFeatureAsInt(features::kClientLoFi, kVersion,
+ 0);
}
int AMPRedirectionPreviewsVersion() {
@@ -192,16 +200,16 @@ bool IsOptimizationHintsEnabled() {
}
net::EffectiveConnectionType EffectiveConnectionTypeThresholdForClientLoFi() {
- return GetParamValueAsECT(kClientLoFiExperimentName,
- kEffectiveConnectionTypeThreshold,
- net::EFFECTIVE_CONNECTION_TYPE_2G);
+ return GetParamValueAsECTByFeature(features::kClientLoFi,
+ kEffectiveConnectionTypeThreshold,
+ net::EFFECTIVE_CONNECTION_TYPE_2G);
}
std::vector<std::string> GetBlackListedHostsForClientLoFiFieldTrial() {
- return base::SplitString(
- base::GetFieldTrialParamValue(kClientLoFiExperimentName,
- "short_host_blacklist"),
- ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ return base::SplitString(base::GetFieldTrialParamValueByFeature(
+ features::kClientLoFi, "short_host_blacklist"),
+ ",", base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY);
}
int NoScriptPreviewsInflationPercent() {
@@ -223,6 +231,8 @@ std::string GetStringNameForType(PreviewsType type) {
// The returned string is used to record histograms for the new preview type.
// Also add the string to Previews.Types histogram suffix in histograms.xml.
switch (type) {
+ case PreviewsType::NONE:
+ return "None";
case PreviewsType::OFFLINE:
return "Offline";
case PreviewsType::LOFI:
@@ -233,7 +243,8 @@ std::string GetStringNameForType(PreviewsType type) {
return "AMPRedirection";
case PreviewsType::NOSCRIPT:
return "NoScript";
- case PreviewsType::NONE:
+ case PreviewsType::UNSPECIFIED:
+ return "Unspecified";
case PreviewsType::LAST:
break;
}
diff --git a/chromium/components/previews/core/previews_experiments.h b/chromium/components/previews/core/previews_experiments.h
index 1755106f51b..27726d52209 100644
--- a/chromium/components/previews/core/previews_experiments.h
+++ b/chromium/components/previews/core/previews_experiments.h
@@ -15,6 +15,7 @@
namespace previews {
enum class PreviewsType {
+ // Used to indicate that there is no preview type.
NONE = 0,
// The user is shown an offline page as a preview.
@@ -32,9 +33,13 @@ enum class PreviewsType {
// Preview that disables JavaScript for the navigation.
NOSCRIPT = 5,
+ // Special value that indicates that no specific type is identified. This
+ // might be used for checks or logging that applies to any type.
+ UNSPECIFIED = 6,
+
// Insert new enum values here. Keep values sequential to allow looping from
// NONE+1 to LAST-1. Also add the enum to Previews.Types histogram suffix.
- LAST = 6,
+ LAST = 7,
};
typedef std::vector<std::pair<PreviewsType, int>> PreviewsTypeList;
@@ -81,6 +86,9 @@ base::TimeDelta OfflinePreviewFreshnessDuration();
net::EffectiveConnectionType GetECTThresholdForPreview(
previews::PreviewsType type);
+// Whether any previews are allowed. Acts as a kill-switch or holdback check.
+bool ArePreviewsAllowed();
+
// Whether the preview type is enabled.
bool IsOfflinePreviewsEnabled();
bool IsClientLoFiEnabled();
diff --git a/chromium/components/previews/core/previews_experiments_unittest.cc b/chromium/components/previews/core/previews_experiments_unittest.cc
index d082789a04d..5655deb2013 100644
--- a/chromium/components/previews/core/previews_experiments_unittest.cc
+++ b/chromium/components/previews/core/previews_experiments_unittest.cc
@@ -12,6 +12,9 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
+#include "components/previews/core/previews_features.h"
#include "components/variations/variations_associated_data.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -21,9 +24,7 @@ namespace previews {
namespace {
const char kClientSidePreviewsFieldTrial[] = "ClientSidePreviews";
-const char kClientLoFiFieldTrial[] = "PreviewsClientLoFi";
const char kEnabled[] = "Enabled";
-const char kDisabled[] = "Disabled";
// Verifies that we can enable offline previews via comand line.
TEST(PreviewsExperimentsTest, TestCommandLineOfflinePage) {
@@ -100,29 +101,35 @@ TEST(PreviewsExperimentsTest, TestParamsForBlackListAndOffline) {
variations::testing::ClearAllVariationParams();
}
-TEST(PreviewsExperimentsTest, TestClientLoFiDisabledByDefault) {
- base::FieldTrialList field_trial_list(nullptr);
+#if defined(OS_ANDROID)
+
+TEST(PreviewsExperimentsTest, TestClientLoFiEnabledByDefaultOnAndroid) {
+ EXPECT_TRUE(params::IsClientLoFiEnabled());
+}
+
+#else // !defined(OS_ANDROID)
+
+TEST(PreviewsExperimentsTest, TestClientLoFiDisabledByDefaultOnNonAndroid) {
EXPECT_FALSE(params::IsClientLoFiEnabled());
}
+#endif // defined(OS_ANDROID)
+
TEST(PreviewsExperimentsTest, TestClientLoFiExplicitlyDisabled) {
- base::FieldTrialList field_trial_list(nullptr);
- EXPECT_TRUE(
- base::FieldTrialList::CreateFieldTrial(kClientLoFiFieldTrial, kDisabled));
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndDisableFeature(features::kClientLoFi);
EXPECT_FALSE(params::IsClientLoFiEnabled());
}
-TEST(PreviewsExperimentsTest, TestClientLoFiEnabled) {
- base::FieldTrialList field_trial_list(nullptr);
- EXPECT_TRUE(
- base::FieldTrialList::CreateFieldTrial(kClientLoFiFieldTrial, kEnabled));
+TEST(PreviewsExperimentsTest, TestClientLoFiExplicitlyEnabled) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kClientLoFi);
EXPECT_TRUE(params::IsClientLoFiEnabled());
}
TEST(PreviewsExperimentsTest, TestEnableClientLoFiWithDefaultParams) {
- base::FieldTrialList field_trial_list(nullptr);
- EXPECT_TRUE(
- base::FieldTrialList::CreateFieldTrial(kClientLoFiFieldTrial, kEnabled));
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kClientLoFi);
EXPECT_TRUE(params::IsClientLoFiEnabled());
EXPECT_EQ(0, params::ClientLoFiVersion());
@@ -133,18 +140,12 @@ TEST(PreviewsExperimentsTest, TestEnableClientLoFiWithDefaultParams) {
}
TEST(PreviewsExperimentsTest, TestEnableClientLoFiWithCustomParams) {
- base::FieldTrialList field_trial_list(nullptr);
-
- // Set some custom params for Client LoFi.
- std::map<std::string, std::string> custom_params = {
- {"version", "10"},
- {"max_allowed_effective_connection_type", "3G"},
- {"short_host_blacklist", "some,hosts, to-blacklist ,,"},
- };
- EXPECT_TRUE(base::AssociateFieldTrialParams(kClientLoFiFieldTrial, kEnabled,
- custom_params));
- EXPECT_TRUE(
- base::FieldTrialList::CreateFieldTrial(kClientLoFiFieldTrial, kEnabled));
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeatureWithParameters(
+ features::kClientLoFi,
+ {{"version", "10"},
+ {"max_allowed_effective_connection_type", "3G"},
+ {"short_host_blacklist", "some,hosts, to-blacklist ,,"}});
EXPECT_TRUE(params::IsClientLoFiEnabled());
EXPECT_EQ(10, params::ClientLoFiVersion());
@@ -152,24 +153,6 @@ TEST(PreviewsExperimentsTest, TestEnableClientLoFiWithCustomParams) {
params::EffectiveConnectionTypeThresholdForClientLoFi());
EXPECT_EQ(std::vector<std::string>({"some", "hosts", "to-blacklist"}),
params::GetBlackListedHostsForClientLoFiFieldTrial());
-
- variations::testing::ClearAllVariationParams();
-}
-
-// Verifies that we can enable offline previews via comand line.
-TEST(PreviewsExperimentsTest, TestCommandLineClientLoFi) {
- EXPECT_FALSE(params::IsClientLoFiEnabled());
-
- std::unique_ptr<base::FeatureList> feature_list =
- std::make_unique<base::FeatureList>();
-
- // The feature is explicitly enabled on the command-line.
- feature_list->InitializeFromCommandLine("ClientLoFi", "");
- base::FeatureList::ClearInstanceForTesting();
- base::FeatureList::SetInstance(std::move(feature_list));
-
- EXPECT_TRUE(params::IsClientLoFiEnabled());
- base::FeatureList::ClearInstanceForTesting();
}
} // namespace
diff --git a/chromium/components/previews/core/previews_features.cc b/chromium/components/previews/core/previews_features.cc
index 833f78db2d3..a248816c221 100644
--- a/chromium/components/previews/core/previews_features.cc
+++ b/chromium/components/previews/core/previews_features.cc
@@ -4,16 +4,37 @@
#include "components/previews/core/previews_features.h"
+#include "build/build_config.h"
+
namespace previews {
namespace features {
+// Kill switch (or holdback) for all previews. No previews will be allowed
+// if this feature is disabled. If enabled, which specific previews that
+// are enabled are controlled by other features.
+const base::Feature kPreviews {
+ "Previews",
+#if defined(OS_ANDROID) || defined(OS_LINUX)
+ // Previews allowed for Android (but also allow on Linux for dev/debug).
+ base::FEATURE_ENABLED_BY_DEFAULT
+#else // !defined(OS_ANDROID) || defined(OS_LINUX)
+ base::FEATURE_DISABLED_BY_DEFAULT
+#endif // defined(OS_ANDROID) || defined(OS_LINUX)
+};
+
// Enables the Offline previews on android slow connections.
const base::Feature kOfflinePreviews{"OfflinePreviews",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Enables the Client Lo-Fi previews on Android.
-const base::Feature kClientLoFi{"ClientLoFi",
- base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables the Client Lo-Fi previews.
+const base::Feature kClientLoFi {
+ "ClientLoFi",
+#if defined(OS_ANDROID)
+ base::FEATURE_ENABLED_BY_DEFAULT
+#else // !defined(OS_ANDROID)
+ base::FEATURE_DISABLED_BY_DEFAULT
+#endif // defined(OS_ANDROID)
+};
// Enables the NoScript previews for Android.
const base::Feature kNoScriptPreviews{"NoScriptPreviews",
diff --git a/chromium/components/previews/core/previews_features.h b/chromium/components/previews/core/previews_features.h
index e4f8e26cfb1..61f61f1fb03 100644
--- a/chromium/components/previews/core/previews_features.h
+++ b/chromium/components/previews/core/previews_features.h
@@ -10,6 +10,7 @@
namespace previews {
namespace features {
+extern const base::Feature kPreviews;
extern const base::Feature kOfflinePreviews;
extern const base::Feature kClientLoFi;
extern const base::Feature kNoScriptPreviews;
diff --git a/chromium/components/previews/core/previews_logger.cc b/chromium/components/previews/core/previews_logger.cc
index ad51f6efa37..d6e41a3b442 100644
--- a/chromium/components/previews/core/previews_logger.cc
+++ b/chromium/components/previews/core/previews_logger.cc
@@ -32,55 +32,66 @@ std::string GetDescriptionForPreviewsNavigation(PreviewsType type,
}
std::string GetReasonDescription(PreviewsEligibilityReason reason,
- bool final_reason) {
+ bool want_inverse_description) {
switch (reason) {
case PreviewsEligibilityReason::ALLOWED:
- DCHECK(final_reason);
+ DCHECK(!want_inverse_description);
return "Allowed";
case PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE:
- return final_reason ? "Blacklist failed to be created"
- : "Blacklist not null";
+ return want_inverse_description ? "Blacklist not null"
+ : "Blacklist failed to be created";
case PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED:
- return final_reason ? "Blacklist not loaded from disk yet"
- : "Blacklist loaded from disk";
+ return want_inverse_description ? "Blacklist loaded from disk"
+ : "Blacklist not loaded from disk yet";
case PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT:
- return final_reason ? "User recently opted out"
- : "User did not opt out recently";
+ return want_inverse_description ? "User did not opt out recently"
+ : "User recently opted out";
case PreviewsEligibilityReason::USER_BLACKLISTED:
- return final_reason ? "All previews are blacklisted"
- : "Not all previews are blacklisted";
+ return want_inverse_description ? "Not all previews are blacklisted"
+ : "All previews are blacklisted";
case PreviewsEligibilityReason::HOST_BLACKLISTED:
- return final_reason ? "All previews on this host are blacklisted"
- : "Host is not blacklisted on all previews";
+ return want_inverse_description
+ ? "Host is not blacklisted on all previews"
+ : "All previews on this host are blacklisted";
case PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE:
- return final_reason ? "Network quality unavailable"
- : "Network quality available";
+ return want_inverse_description ? "Network quality available"
+ : "Network quality unavailable";
case PreviewsEligibilityReason::NETWORK_NOT_SLOW:
- return final_reason ? "Network not slow" : "Network is slow";
+ return want_inverse_description ? "Network is slow" : "Network not slow";
case PreviewsEligibilityReason::RELOAD_DISALLOWED:
- return final_reason
- ? "Page reloads do not show previews for this preview type"
- : "Page reloads allowed";
+ return want_inverse_description
+ ? "Page reloads allowed"
+ : "Page reloads do not show previews for this preview type";
case PreviewsEligibilityReason::HOST_BLACKLISTED_BY_SERVER:
- return final_reason ? "Host blacklisted by server rules"
- : "Host not blacklisted by server rules";
+ return want_inverse_description ? "Host not blacklisted by server rules"
+ : "Host blacklisted by server rules";
case PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER:
- return final_reason ? "Host not whitelisted by server rules"
- : "Host whitelisted by server rules";
+ return want_inverse_description ? "Host whitelisted by server rules"
+ : "Host not whitelisted by server rules";
case PreviewsEligibilityReason::ALLOWED_WITHOUT_OPTIMIZATION_HINTS:
- return final_reason ? "Allowed (but without server rule check)"
- : "Not allowed (without server rule check)";
+ return want_inverse_description
+ ? "Not allowed (without server rule check)"
+ : "Allowed (but without server rule check)";
+ case PreviewsEligibilityReason::COMMITTED:
+ return want_inverse_description ? "Not Committed" : "Committed";
+ case PreviewsEligibilityReason::CACHE_CONTROL_NO_TRANSFORM:
+ return want_inverse_description
+ ? "Cache-control no-transform not received"
+ : "Cache-control no-transform received";
+ case PreviewsEligibilityReason::LAST:
+ break;
}
NOTREACHED();
return "";
}
-std::string GetDescriptionForPreviewsDecision(PreviewsEligibilityReason reason,
- PreviewsType type,
- bool final_reason) {
- return base::StringPrintf("%s preview - %s",
- GetStringNameForType(type).c_str(),
- GetReasonDescription(reason, final_reason).c_str());
+std::string GetDescriptionForPreviewsDecision(
+ PreviewsEligibilityReason reason,
+ PreviewsType type,
+ bool want_inverse_description = false) {
+ return base::StringPrintf(
+ "%s preview - %s", GetStringNameForType(type).c_str(),
+ GetReasonDescription(reason, want_inverse_description).c_str());
}
} // namespace
@@ -203,15 +214,14 @@ void PreviewsLogger::LogPreviewDecisionMade(
// Logs all passed decisions messages.
for (auto decision : passed_reasons) {
std::string decision_description = GetDescriptionForPreviewsDecision(
- decision, type, false /* final_reason */);
+ decision, type, true /* want_inverse_description */);
LogMessage(kPreviewDecisionMadeEventType, decision_description, url, time,
page_id);
decisions_logs_.emplace_back(kPreviewDecisionMadeEventType,
decision_description, url, time, page_id);
}
- std::string description =
- GetDescriptionForPreviewsDecision(reason, type, true /* final_reason */);
+ std::string description = GetDescriptionForPreviewsDecision(reason, type);
LogMessage(kPreviewDecisionMadeEventType, description, url, time, page_id);
// Pop out the older messages when the list is full.
diff --git a/chromium/components/previews/core/previews_logger_unittest.cc b/chromium/components/previews/core/previews_logger_unittest.cc
index 387f9f1b0f0..4e768548cd6 100644
--- a/chromium/components/previews/core/previews_logger_unittest.cc
+++ b/chromium/components/previews/core/previews_logger_unittest.cc
@@ -590,6 +590,22 @@ TEST_F(
EXPECT_EQ(expected_description, actual_description);
}
+TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionCommitted) {
+ std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
+ PreviewsEligibilityReason::COMMITTED, true /* final_reason */);
+ std::string expected_description = "Committed";
+ EXPECT_EQ(expected_description, actual_description);
+}
+
+TEST_F(PreviewsLoggerTest,
+ LogPreviewDecisionDescriptionCacheControlNoTransform) {
+ std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
+ PreviewsEligibilityReason::CACHE_CONTROL_NO_TRANSFORM,
+ true /* final_reason */);
+ std::string expected_description = "Cache-control no-transform received";
+ EXPECT_EQ(expected_description, actual_description);
+}
+
TEST_F(PreviewsLoggerTest, NotifyObserversOfNewBlacklistedHost) {
TestPreviewsLoggerObserver observers[3];
diff --git a/chromium/components/previews/core/previews_opt_out_store_sql.cc b/chromium/components/previews/core/previews_opt_out_store_sql.cc
index 503fd31eac1..88bb76b6cca 100644
--- a/chromium/components/previews/core/previews_opt_out_store_sql.cc
+++ b/chromium/components/previews/core/previews_opt_out_store_sql.cc
@@ -361,8 +361,8 @@ void LoadBlackListFromDataBase(
}
runner->PostTask(FROM_HERE,
- base::Bind(callback, base::Passed(&black_list_item_map),
- base::Passed(&host_indifferent_black_list_item)));
+ base::BindOnce(callback, std::move(black_list_item_map),
+ std::move(host_indifferent_black_list_item)));
}
// Synchronous implementations, these are run on the background thread
@@ -453,9 +453,9 @@ void PreviewsOptOutStoreSQL::LoadBlackList(LoadBlackListCallback callback) {
std::unique_ptr<PreviewsTypeList> enabled_previews =
std::make_unique<PreviewsTypeList>(*enabled_previews_);
background_task_runner_->PostTask(
- FROM_HERE, base::Bind(&LoadBlackListSync, db_.get(), db_file_path_,
- base::Passed(std::move(enabled_previews)),
- base::ThreadTaskRunnerHandle::Get(), callback));
+ FROM_HERE, base::BindOnce(&LoadBlackListSync, db_.get(), db_file_path_,
+ std::move(enabled_previews),
+ base::ThreadTaskRunnerHandle::Get(), callback));
}
} // namespace previews
diff --git a/chromium/components/previews/core/previews_user_data.cc b/chromium/components/previews/core/previews_user_data.cc
index 50b2d18f1aa..0e06452cd29 100644
--- a/chromium/components/previews/core/previews_user_data.cc
+++ b/chromium/components/previews/core/previews_user_data.cc
@@ -11,15 +11,13 @@ namespace previews {
const void* const kPreviewsUserDataKey = &kPreviewsUserDataKey;
-PreviewsUserData::PreviewsUserData(uint64_t page_id)
- : page_id_(page_id),
- cache_control_no_transform_directive_(false),
- committed_previews_type_(PreviewsType::NONE) {}
+PreviewsUserData::PreviewsUserData(uint64_t page_id) : page_id_(page_id) {}
PreviewsUserData::~PreviewsUserData() {}
std::unique_ptr<PreviewsUserData> PreviewsUserData::DeepCopy() const {
std::unique_ptr<PreviewsUserData> copy(new PreviewsUserData(page_id_));
+ copy->data_savings_inflation_percent_ = data_savings_inflation_percent_;
copy->cache_control_no_transform_directive_ =
cache_control_no_transform_directive_;
copy->SetCommittedPreviewsType(committed_previews_type_);
diff --git a/chromium/components/previews/core/previews_user_data.h b/chromium/components/previews/core/previews_user_data.h
index 16e070ebba1..881f1b98678 100644
--- a/chromium/components/previews/core/previews_user_data.h
+++ b/chromium/components/previews/core/previews_user_data.h
@@ -36,6 +36,20 @@ class PreviewsUserData : public base::SupportsUserData::Data {
// A session unique ID related to this navigation.
uint64_t page_id() const { return page_id_; }
+ // Sets a data savings inflation percent value to use instead of the default
+ // if there is a committed preview. Note that this is expected to be used for
+ // specific preview types (such as NoScript) that don't have better data use
+ // estimation information.
+ void SetDataSavingsInflationPercent(int inflation_percent) {
+ data_savings_inflation_percent_ = inflation_percent;
+ }
+
+ // Returns the data savings inflation percent to use for this navigation
+ // instead of the default if it is not 0.
+ int data_savings_inflation_percent() {
+ return data_savings_inflation_percent_;
+ }
+
// Sets that the page load received the Cache-Control:no-transform
// directive. Expected to be set upon receiving a committed response.
void SetCacheControlNoTransformDirective() {
@@ -65,10 +79,13 @@ class PreviewsUserData : public base::SupportsUserData::Data {
private:
// A session unique ID related to this navigation.
const uint64_t page_id_;
- bool cache_control_no_transform_directive_;
+ // A previews data savings inflation percent for the navigation if not 0.
+ int data_savings_inflation_percent_ = 0;
+ // Whether the origin provided a no-transform directive.
+ bool cache_control_no_transform_directive_ = false;
// The committed previews type, if any.
- previews::PreviewsType committed_previews_type_;
+ previews::PreviewsType committed_previews_type_ = PreviewsType::NONE;
DISALLOW_COPY_AND_ASSIGN(PreviewsUserData);
};
diff --git a/chromium/components/previews/core/previews_user_data_unittest.cc b/chromium/components/previews/core/previews_user_data_unittest.cc
index 2301929eb61..9c4f995812b 100644
--- a/chromium/components/previews/core/previews_user_data_unittest.cc
+++ b/chromium/components/previews/core/previews_user_data_unittest.cc
@@ -57,7 +57,20 @@ TEST_F(PreviewsUserDataTest, DeepCopy) {
std::unique_ptr<PreviewsUserData> data(new PreviewsUserData(5u));
EXPECT_EQ(id, data->page_id());
- EXPECT_EQ(id, data->DeepCopy()->page_id());
+ EXPECT_EQ(0, data->data_savings_inflation_percent());
+ EXPECT_FALSE(data->cache_control_no_transform_directive());
+ EXPECT_EQ(previews::PreviewsType::NONE, data->committed_previews_type());
+
+ data->SetDataSavingsInflationPercent(123);
+ data->SetCacheControlNoTransformDirective();
+ data->SetCommittedPreviewsType(previews::PreviewsType::NOSCRIPT);
+
+ std::unique_ptr<PreviewsUserData> deep_copy = data->DeepCopy();
+ EXPECT_EQ(id, deep_copy->page_id());
+ EXPECT_EQ(123, deep_copy->data_savings_inflation_percent());
+ EXPECT_TRUE(deep_copy->cache_control_no_transform_directive());
+ EXPECT_EQ(previews::PreviewsType::NOSCRIPT,
+ deep_copy->committed_previews_type());
}
} // namespace
diff --git a/chromium/components/previews/core/test_previews_decider.cc b/chromium/components/previews/core/test_previews_decider.cc
new file mode 100644
index 00000000000..f6a9f3abcde
--- /dev/null
+++ b/chromium/components/previews/core/test_previews_decider.cc
@@ -0,0 +1,33 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/previews/core/test_previews_decider.h"
+
+namespace previews {
+
+TestPreviewsDecider::TestPreviewsDecider(bool allow_previews)
+ : allow_previews_(allow_previews) {}
+
+TestPreviewsDecider::~TestPreviewsDecider() {}
+
+bool TestPreviewsDecider::ShouldAllowPreviewAtECT(
+ const net::URLRequest& request,
+ previews::PreviewsType type,
+ net::EffectiveConnectionType effective_connection_type_threshold,
+ const std::vector<std::string>& host_blacklist_from_server) const {
+ return allow_previews_;
+}
+
+bool TestPreviewsDecider::ShouldAllowPreview(
+ const net::URLRequest& request,
+ previews::PreviewsType type) const {
+ return allow_previews_;
+}
+
+bool TestPreviewsDecider::IsURLAllowedForPreview(const net::URLRequest& request,
+ PreviewsType type) const {
+ return allow_previews_;
+}
+
+} // namespace previews
diff --git a/chromium/components/previews/core/test_previews_decider.h b/chromium/components/previews/core/test_previews_decider.h
new file mode 100644
index 00000000000..015993bd5ee
--- /dev/null
+++ b/chromium/components/previews/core/test_previews_decider.h
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PREVIEWS_CORE_TEST_PREVIEWS_DECIDER_H_
+#define COMPONENTS_PREVIEWS_CORE_TEST_PREVIEWS_DECIDER_H_
+
+#include "components/previews/core/previews_decider.h"
+
+namespace previews {
+
+// Simple test implementation of PreviewsDecider interface.
+class TestPreviewsDecider : public previews::PreviewsDecider {
+ public:
+ TestPreviewsDecider(bool allow_previews);
+ ~TestPreviewsDecider() override;
+
+ // previews::PreviewsDecider:
+ bool ShouldAllowPreviewAtECT(
+ const net::URLRequest& request,
+ previews::PreviewsType type,
+ net::EffectiveConnectionType effective_connection_type_threshold,
+ const std::vector<std::string>& host_blacklist_from_server)
+ const override;
+ bool ShouldAllowPreview(const net::URLRequest& request,
+ previews::PreviewsType type) const override;
+ bool IsURLAllowedForPreview(const net::URLRequest& request,
+ PreviewsType type) const override;
+
+ private:
+ bool allow_previews_;
+};
+
+} // namespace previews
+
+#endif // COMPONENTS_PREVIEWS_CORE_TEST_PREVIEWS_DECIDER_H_
diff --git a/chromium/components/printing/DEPS b/chromium/components/printing/DEPS
index 1332b45375b..bb758ef3c4c 100644
--- a/chromium/components/printing/DEPS
+++ b/chromium/components/printing/DEPS
@@ -1,10 +1,10 @@
include_rules = [
+ "+components/cloud_devices/common",
"-components/printing",
"+components/printing/common",
"+content/public/common",
"+ipc",
"+printing",
- "+third_party/WebKit/common",
"+third_party/WebKit/public",
"+ui/gfx"
]
diff --git a/chromium/components/printing/browser/BUILD.gn b/chromium/components/printing/browser/BUILD.gn
index d910171d52e..d7e30dd9df8 100644
--- a/chromium/components/printing/browser/BUILD.gn
+++ b/chromium/components/printing/browser/BUILD.gn
@@ -4,6 +4,8 @@
static_library("browser") {
sources = [
+ "features.cc",
+ "features.h",
"print_composite_client.cc",
"print_composite_client.h",
"print_manager.cc",
@@ -19,8 +21,9 @@ static_library("browser") {
deps = [
"//base",
"//components/printing/common",
- "//components/printing/service/public/cpp:client",
+ "//components/printing/service/public/interfaces",
"//printing",
+ "//printing/common:common",
"//services/service_manager/public/cpp",
]
}
diff --git a/chromium/components/printing/browser/DEPS b/chromium/components/printing/browser/DEPS
index f67625c944f..8dc6d21d04f 100644
--- a/chromium/components/printing/browser/DEPS
+++ b/chromium/components/printing/browser/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+components/printing/service/public/cpp",
+ "+components/printing/service/public/interfaces",
"+content/public/browser",
"+mojo/public/cpp/system",
"+services/service_manager/public/cpp",
diff --git a/chromium/components/printing/browser/features.cc b/chromium/components/printing/browser/features.cc
new file mode 100644
index 00000000000..cca95f2de52
--- /dev/null
+++ b/chromium/components/printing/browser/features.cc
@@ -0,0 +1,14 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/printing/browser/features.h"
+
+namespace printing {
+namespace features {
+
+const base::Feature kUsePdfCompositorServiceForPrint{
+ "UsePdfCompositorServiceForPrint", base::FEATURE_DISABLED_BY_DEFAULT};
+
+} // namespace features
+} // namespace printing
diff --git a/chromium/components/printing/browser/features.h b/chromium/components/printing/browser/features.h
new file mode 100644
index 00000000000..1d18c2fe3ee
--- /dev/null
+++ b/chromium/components/printing/browser/features.h
@@ -0,0 +1,19 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PRINTING_BROWSER_FEATURES_H_
+#define COMPONENTS_PRINTING_BROWSER_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace printing {
+namespace features {
+
+// Use pdf compositor service to generate PDF files for printing.
+extern const base::Feature kUsePdfCompositorServiceForPrint;
+
+} // namespace features
+} // namespace printing
+
+#endif // COMPONENTS_PRINTING_BROWSER_FEATURES_H_
diff --git a/chromium/components/printing/browser/print_composite_client.cc b/chromium/components/printing/browser/print_composite_client.cc
index 167cdeed469..d5bd4abda0d 100644
--- a/chromium/components/printing/browser/print_composite_client.cc
+++ b/chromium/components/printing/browser/print_composite_client.cc
@@ -4,41 +4,286 @@
#include "components/printing/browser/print_composite_client.h"
-#include <memory>
#include <utility>
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/bind.h"
+#include "base/memory/shared_memory_handle.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
+#include "components/printing/common/print_messages.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/common/service_manager_connection.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "printing/printing_utils.h"
#include "services/service_manager/public/cpp/connector.h"
DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintCompositeClient);
+namespace {
+
+uint64_t GenerateFrameGuid(int process_id, int frame_id) {
+ return static_cast<uint64_t>(process_id) << 32 | frame_id;
+}
+
+} // namespace
+
namespace printing {
PrintCompositeClient::PrintCompositeClient(content::WebContents* web_contents)
- : for_preview_(false) {}
+ : content::WebContentsObserver(web_contents) {}
PrintCompositeClient::~PrintCompositeClient() {}
-void PrintCompositeClient::CreateConnectorRequest() {
- connector_ = service_manager::Connector::Create(&connector_request_);
- content::ServiceManagerConnection::GetForProcess()
- ->GetConnector()
- ->BindConnectorRequest(std::move(connector_request_));
+bool PrintCompositeClient::OnMessageReceived(
+ const IPC::Message& message,
+ content::RenderFrameHost* render_frame_host) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(PrintCompositeClient, message,
+ render_frame_host)
+ IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintFrameContent,
+ OnDidPrintFrameContent)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PrintCompositeClient::RenderFrameDeleted(
+ content::RenderFrameHost* render_frame_host) {
+ auto frame_guid = GenerateFrameGuid(render_frame_host->GetProcess()->GetID(),
+ render_frame_host->GetRoutingID());
+ auto iter = pending_subframe_cookies_.find(frame_guid);
+ if (iter != pending_subframe_cookies_.end()) {
+ // When a subframe we are expecting is deleted, we should notify pdf
+ // compositor service.
+ for (auto doc_cookie : iter->second) {
+ auto& compositor = GetCompositeRequest(doc_cookie);
+ compositor->NotifyUnavailableSubframe(frame_guid);
+ }
+ pending_subframe_cookies_.erase(iter);
+ }
}
-void PrintCompositeClient::DoComposite(
+void PrintCompositeClient::OnDidPrintFrameContent(
+ content::RenderFrameHost* render_frame_host,
+ int document_cookie,
+ const PrintHostMsg_DidPrintContent_Params& params) {
+ auto* outer_contents = web_contents()->GetOuterWebContents();
+ if (outer_contents) {
+ // When the printed content belongs to an extension or app page, the print
+ // composition needs to be handled by its outer content.
+ // TODO(weili): so far, we don't have printable web contents nested in more
+ // than one level. In the future, especially after PDF plugin is moved to
+ // OOPIF-based webview, we should check whether we need to handle web
+ // contents nested in multiple layers.
+ auto* outer_client = PrintCompositeClient::FromWebContents(outer_contents);
+ DCHECK(outer_client);
+ outer_client->OnDidPrintFrameContent(render_frame_host, document_cookie,
+ params);
+ return;
+ }
+
+ // Content in |params| is sent from untrusted source; only minimal processing
+ // is done here. Most of it will be directly forwarded to pdf compositor
+ // service.
+ auto& compositor = GetCompositeRequest(document_cookie);
+
+ mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
+ params.metafile_data_handle, params.data_size,
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly);
+ auto frame_guid = GenerateFrameGuid(render_frame_host->GetProcess()->GetID(),
+ render_frame_host->GetRoutingID());
+ compositor->AddSubframeContent(
+ frame_guid, std::move(buffer_handle),
+ ConvertContentInfoMap(web_contents(), render_frame_host,
+ params.subframe_content_info));
+
+ // Update our internal states about this frame.
+ pending_subframe_cookies_[frame_guid].erase(document_cookie);
+ if (pending_subframe_cookies_[frame_guid].empty())
+ pending_subframe_cookies_.erase(frame_guid);
+ printed_subframes_[document_cookie].insert(frame_guid);
+}
+
+void PrintCompositeClient::PrintCrossProcessSubframe(
+ const gfx::Rect& rect,
+ int document_cookie,
+ content::RenderFrameHost* subframe_host) {
+ PrintMsg_PrintFrame_Params params;
+ params.printable_area = rect;
+ params.document_cookie = document_cookie;
+ uint64_t frame_guid = GenerateFrameGuid(subframe_host->GetProcess()->GetID(),
+ subframe_host->GetRoutingID());
+ if (subframe_host->IsRenderFrameLive()) {
+ auto subframe_iter = printed_subframes_.find(document_cookie);
+ if (subframe_iter != printed_subframes_.end() &&
+ base::ContainsKey(subframe_iter->second, frame_guid)) {
+ // If this frame is already printed, no need to print again.
+ return;
+ }
+
+ auto cookie_iter = pending_subframe_cookies_.find(frame_guid);
+ if (cookie_iter != pending_subframe_cookies_.end() &&
+ base::ContainsKey(cookie_iter->second, document_cookie)) {
+ // If this frame is being printed, no need to print again.
+ return;
+ }
+
+ // Send the request to the destination frame.
+ subframe_host->Send(
+ new PrintMsg_PrintFrameContent(subframe_host->GetRoutingID(), params));
+ pending_subframe_cookies_[frame_guid].insert(document_cookie);
+ } else {
+ // When the subframe is dead, no need to send message,
+ // just notify the service.
+ auto& compositor = GetCompositeRequest(document_cookie);
+ compositor->NotifyUnavailableSubframe(frame_guid);
+ }
+}
+
+void PrintCompositeClient::DoCompositePageToPdf(
+ int document_cookie,
+ content::RenderFrameHost* render_frame_host,
+ int page_num,
base::SharedMemoryHandle handle,
uint32_t data_size,
- mojom::PdfCompositor::CompositePdfCallback callback) {
+ const ContentToProxyIdMap& subframe_content_info,
+ mojom::PdfCompositor::CompositePageToPdfCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ auto& compositor = GetCompositeRequest(document_cookie);
+
DCHECK(data_size);
+ mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
+ handle, data_size,
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly);
+ // Since this class owns compositor, compositor will be gone when this class
+ // is destructed. Mojo won't call its callback in that case so it is safe to
+ // use unretained |this| pointer here.
+ compositor->CompositePageToPdf(
+ GenerateFrameGuid(render_frame_host->GetProcess()->GetID(),
+ render_frame_host->GetRoutingID()),
+ page_num, std::move(buffer_handle),
+ ConvertContentInfoMap(web_contents(), render_frame_host,
+ subframe_content_info),
+ base::BindOnce(&PrintCompositeClient::OnDidCompositePageToPdf,
+ base::Unretained(this), std::move(callback)));
+}
+
+void PrintCompositeClient::DoCompositeDocumentToPdf(
+ int document_cookie,
+ content::RenderFrameHost* render_frame_host,
+ base::SharedMemoryHandle handle,
+ uint32_t data_size,
+ const ContentToProxyIdMap& subframe_content_info,
+ mojom::PdfCompositor::CompositeDocumentToPdfCallback callback) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ auto& compositor = GetCompositeRequest(document_cookie);
+
+ DCHECK(data_size);
+ mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
+ handle, data_size,
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly);
+ // Since this class owns compositor, compositor will be gone when this class
+ // is destructed. Mojo won't call its callback in that case so it is safe to
+ // use unretained |this| pointer here.
+ compositor->CompositeDocumentToPdf(
+ GenerateFrameGuid(render_frame_host->GetProcess()->GetID(),
+ render_frame_host->GetRoutingID()),
+ std::move(buffer_handle),
+ ConvertContentInfoMap(web_contents(), render_frame_host,
+ subframe_content_info),
+ base::BindOnce(&PrintCompositeClient::OnDidCompositeDocumentToPdf,
+ base::Unretained(this), document_cookie,
+ std::move(callback)));
+}
+
+void PrintCompositeClient::OnDidCompositePageToPdf(
+ printing::mojom::PdfCompositor::CompositePageToPdfCallback callback,
+ printing::mojom::PdfCompositor::Status status,
+ mojo::ScopedSharedBufferHandle handle) {
+ // Due to https://crbug.com/742517, we can not add and use COUNT for enums in
+ // mojo.
+ UMA_HISTOGRAM_ENUMERATION(
+ "CompositePageToPdf.Status", status,
+ static_cast<int32_t>(
+ printing::mojom::PdfCompositor::Status::COMPOSTING_FAILURE) +
+ 1);
+ std::move(callback).Run(status, std::move(handle));
+}
+
+void PrintCompositeClient::OnDidCompositeDocumentToPdf(
+ int document_cookie,
+ printing::mojom::PdfCompositor::CompositeDocumentToPdfCallback callback,
+ printing::mojom::PdfCompositor::Status status,
+ mojo::ScopedSharedBufferHandle handle) {
+ RemoveCompositeRequest(document_cookie);
+ // Clear all stored printed subframes.
+ printed_subframes_.erase(document_cookie);
+
+ // Due to https://crbug.com/742517, we can not add and use COUNT for enums in
+ // mojo.
+ UMA_HISTOGRAM_ENUMERATION(
+ "CompositeDocToPdf.Status", status,
+ static_cast<int32_t>(
+ printing::mojom::PdfCompositor::Status::COMPOSTING_FAILURE) +
+ 1);
+ std::move(callback).Run(status, std::move(handle));
+}
+
+ContentToFrameMap PrintCompositeClient::ConvertContentInfoMap(
+ content::WebContents* web_contents,
+ content::RenderFrameHost* render_frame_host,
+ const ContentToProxyIdMap& content_proxy_map) {
+ ContentToFrameMap content_frame_map;
+ int process_id = render_frame_host->GetProcess()->GetID();
+ for (auto& entry : content_proxy_map) {
+ auto content_id = entry.first;
+ auto proxy_id = entry.second;
+ // Find the RenderFrameHost that the proxy id corresponds to.
+ content::RenderFrameHost* rfh =
+ content::RenderFrameHost::FromPlaceholderId(process_id, proxy_id);
+ if (!rfh) {
+ // If we could not find the corresponding RenderFrameHost,
+ // just skip it.
+ continue;
+ }
+
+ // Store this frame's global unique id into the map.
+ content_frame_map[content_id] =
+ GenerateFrameGuid(rfh->GetProcess()->GetID(), rfh->GetRoutingID());
+ }
+ return content_frame_map;
+}
+
+mojom::PdfCompositorPtr& PrintCompositeClient::GetCompositeRequest(int cookie) {
+ auto iter = compositor_map_.find(cookie);
+ if (iter != compositor_map_.end()) {
+ DCHECK(iter->second.is_bound());
+ return iter->second;
+ }
+
+ auto iterator =
+ compositor_map_.emplace(cookie, CreateCompositeRequest()).first;
+ return iterator->second;
+}
+
+void PrintCompositeClient::RemoveCompositeRequest(int cookie) {
+ size_t erased = compositor_map_.erase(cookie);
+ DCHECK_EQ(erased, 1u);
+}
- if (!connector_)
- CreateConnectorRequest();
- Composite(connector_.get(), handle, data_size, std::move(callback),
- base::ThreadTaskRunnerHandle::Get());
+mojom::PdfCompositorPtr PrintCompositeClient::CreateCompositeRequest() {
+ if (!connector_) {
+ service_manager::mojom::ConnectorRequest connector_request;
+ connector_ = service_manager::Connector::Create(&connector_request);
+ content::ServiceManagerConnection::GetForProcess()
+ ->GetConnector()
+ ->BindConnectorRequest(std::move(connector_request));
+ }
+ mojom::PdfCompositorPtr compositor;
+ connector_->BindInterface(mojom::kServiceName, &compositor);
+ return compositor;
}
} // namespace printing
diff --git a/chromium/components/printing/browser/print_composite_client.h b/chromium/components/printing/browser/print_composite_client.h
index 99dfa5a1fbd..2d23b45e64e 100644
--- a/chromium/components/printing/browser/print_composite_client.h
+++ b/chromium/components/printing/browser/print_composite_client.h
@@ -5,34 +5,127 @@
#ifndef COMPONENTS_PRINTING_BROWSER_PRINT_COMPOSITE_CLIENT_H_
#define COMPONENTS_PRINTING_BROWSER_PRINT_COMPOSITE_CLIENT_H_
-#include "components/printing/service/public/cpp/pdf_compositor_client.h"
+#include <map>
+#include <memory>
+
+#include "base/containers/flat_set.h"
+#include "base/optional.h"
+#include "components/printing/service/public/cpp/pdf_service_mojo_types.h"
+#include "components/printing/service/public/interfaces/pdf_compositor.mojom.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
+#include "printing/common/pdf_metafile_utils.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+struct PrintHostMsg_DidPrintContent_Params;
namespace printing {
+// Class to manage print requests and their communication with pdf
+// compositor service.
+// Each composite request have a separate interface pointer to connect
+// with remote service. The request and its subframe printing results are
+// tracked by its document cookie and print page number.
class PrintCompositeClient
- : public PdfCompositorClient,
- public content::WebContentsUserData<PrintCompositeClient> {
+ : public content::WebContentsUserData<PrintCompositeClient>,
+ public content::WebContentsObserver {
public:
explicit PrintCompositeClient(content::WebContents* web_contents);
~PrintCompositeClient() override;
+ // content::WebContentsObserver
+ bool OnMessageReceived(const IPC::Message& message,
+ content::RenderFrameHost* render_frame_host) override;
+ void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
+
+ // IPC message handler.
+ void OnDidPrintFrameContent(
+ content::RenderFrameHost* render_frame_host,
+ int document_cookie,
+ const PrintHostMsg_DidPrintContent_Params& params);
+
+ // Instructs the specified subframe to print.
+ void PrintCrossProcessSubframe(const gfx::Rect& rect,
+ int document_cookie,
+ content::RenderFrameHost* subframe_host);
+
// NOTE: |handle| must be a READ-ONLY base::SharedMemoryHandle, i.e. one
// acquired by base::SharedMemory::GetReadOnlyHandle().
- void DoComposite(base::SharedMemoryHandle handle,
- uint32_t data_size,
- mojom::PdfCompositor::CompositePdfCallback callback);
- void set_for_preview(bool for_preview) { for_preview_ = for_preview; }
- bool for_preview() const { return for_preview_; }
+ // Printing single pages is only used by print preview for early return of
+ // rendered results. In this case, the pages share the content with printed
+ // document. The entire document will always be printed and sent at the end.
+ // This is for compositing such a single preview page.
+ void DoCompositePageToPdf(
+ int cookie,
+ content::RenderFrameHost* render_frame_host,
+ int page_num,
+ base::SharedMemoryHandle handle,
+ uint32_t data_size,
+ const ContentToProxyIdMap& subframe_content_info,
+ mojom::PdfCompositor::CompositePageToPdfCallback callback);
+
+ // Used for compositing the entire document for print preview or actual
+ // printing.
+ void DoCompositeDocumentToPdf(
+ int cookie,
+ content::RenderFrameHost* render_frame_host,
+ base::SharedMemoryHandle handle,
+ uint32_t data_size,
+ const ContentToProxyIdMap& subframe_content_info,
+ mojom::PdfCompositor::CompositeDocumentToPdfCallback callback);
+
+ // Converts a ContentToProxyIdMap to ContentToFrameMap.
+ // ContentToProxyIdMap maps content id to its corresponding render frame proxy
+ // routing id. This is generated when the content holder was created;
+ // ContentToFrameMap maps content id to its render frame's global unique id.
+ // The global unique id has the render process id concatenated with render
+ // frame routing id, which can uniquely identify a render frame.
+ static ContentToFrameMap ConvertContentInfoMap(
+ content::WebContents* web_contents,
+ content::RenderFrameHost* render_frame_host,
+ const ContentToProxyIdMap& content_proxy_map);
private:
- void CreateConnectorRequest();
+ // Since page number is always non-negative, use this value to indicate it is
+ // for the whole document -- no page number specified.
+ static constexpr int kPageNumForWholeDoc = -1;
+
+ // Callback functions for getting the replies.
+ void OnDidCompositePageToPdf(
+ printing::mojom::PdfCompositor::CompositePageToPdfCallback callback,
+ printing::mojom::PdfCompositor::Status status,
+ mojo::ScopedSharedBufferHandle handle);
+
+ void OnDidCompositeDocumentToPdf(
+ int document_cookie,
+ printing::mojom::PdfCompositor::CompositeDocumentToPdfCallback callback,
+ printing::mojom::PdfCompositor::Status status,
+ mojo::ScopedSharedBufferHandle handle);
+
+ // Get the request or create a new one if none exists.
+ // Since printed pages always share content with it document, they share the
+ // same composite request.
+ mojom::PdfCompositorPtr& GetCompositeRequest(int cookie);
+
+ // Remove an existing request from |compositor_map_|.
+ void RemoveCompositeRequest(int cookie);
+
+ mojom::PdfCompositorPtr CreateCompositeRequest();
- service_manager::mojom::ConnectorRequest connector_request_;
std::unique_ptr<service_manager::Connector> connector_;
- bool for_preview_;
+
+ // Stores the mapping between document cookies and their corresponding
+ // requests.
+ std::map<int, mojom::PdfCompositorPtr> compositor_map_;
+
+ // Stores the mapping between render frame's global unique id and document
+ // cookies that requested such frame.
+ std::map<uint64_t, base::flat_set<int>> pending_subframe_cookies_;
+
+ // Stores the mapping between document cookie and all the printed subframes
+ // for that document.
+ std::map<int, base::flat_set<uint64_t>> printed_subframes_;
DISALLOW_COPY_AND_ASSIGN(PrintCompositeClient);
};
diff --git a/chromium/components/printing/browser/print_manager_utils.cc b/chromium/components/printing/browser/print_manager_utils.cc
index 844fcf5bd23..b7ccb27ce8c 100644
--- a/chromium/components/printing/browser/print_manager_utils.cc
+++ b/chromium/components/printing/browser/print_manager_utils.cc
@@ -5,6 +5,7 @@
#include "components/printing/browser/print_manager_utils.h"
#include "base/command_line.h"
+#include "components/printing/browser/features.h"
#include "components/printing/browser/print_composite_client.h"
#include "components/printing/common/print_messages.h"
#include "content/public/common/content_features.h"
@@ -25,17 +26,37 @@ bool IsOopifEnabled() {
return g_oopif_enabled;
}
-void CreateCompositeClientIfNeeded(content::WebContents* web_contents,
- bool for_preview) {
+void CreateCompositeClientIfNeeded(content::WebContents* web_contents) {
+ // TODO(weili): We only create pdf compositor client and use pdf compositor
+ // service when site-per-process or isolate-origins flag/feature is enabled,
+ // or top-document-isolation feature is enabled. This may not cover all cases
+ // where OOPIF is used such as isolate-extensions, but should be good for
+ // feature testing purpose. Eventually, we will remove this check and use pdf
+ // compositor service by default for printing.
+
+ bool is_site_isolation_enabled;
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSitePerProcess) ||
- base::FeatureList::IsEnabled(features::kTopDocumentIsolation)) {
- // For cases need to support OOPIFs.
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kIsolateOrigins)) {
+ is_site_isolation_enabled = true;
+ } else if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableSiteIsolationTrials)) {
+ is_site_isolation_enabled = false;
+ } else {
+ // The features need to be checked last, because checking a feature
+ // activates the field trial and assigns the client either to a control or
+ // an experiment group.
+ is_site_isolation_enabled =
+ base::FeatureList::IsEnabled(::features::kSitePerProcess) ||
+ base::FeatureList::IsEnabled(::features::kIsolateOrigins) ||
+ base::FeatureList::IsEnabled(::features::kTopDocumentIsolation);
+ }
+
+ if (is_site_isolation_enabled ||
+ base::FeatureList::IsEnabled(
+ printing::features::kUsePdfCompositorServiceForPrint)) {
PrintCompositeClient::CreateForWebContents(web_contents);
- if (for_preview) {
- PrintCompositeClient::FromWebContents(web_contents)
- ->set_for_preview(true);
- }
SetOopifEnabled();
}
}
@@ -53,7 +74,7 @@ void RenderParamsFromPrintSettings(const PrintSettings& settings,
settings.page_setup_device_units().printable_area().height());
params->margin_top = settings.page_setup_device_units().content_area().y();
params->margin_left = settings.page_setup_device_units().content_area().x();
- params->dpi = settings.dpi();
+ params->dpi = settings.dpi_size();
params->scale_factor = settings.scale_factor();
params->rasterize_pdf = settings.rasterize_pdf();
// Always use an invalid cookie.
diff --git a/chromium/components/printing/browser/print_manager_utils.h b/chromium/components/printing/browser/print_manager_utils.h
index 5b2b62a7dbf..ecd4ac612e6 100644
--- a/chromium/components/printing/browser/print_manager_utils.h
+++ b/chromium/components/printing/browser/print_manager_utils.h
@@ -20,8 +20,7 @@ bool IsOopifEnabled();
// Check on the current feature settings to decide whether we need to
// create a PDF compositor client for this |web_contents|.
-void CreateCompositeClientIfNeeded(content::WebContents* web_contents,
- bool for_preview);
+void CreateCompositeClientIfNeeded(content::WebContents* web_contents);
// Converts given settings to Print_Params and stores them in the output
// parameter |params|.
diff --git a/chromium/components/printing/common/BUILD.gn b/chromium/components/printing/common/BUILD.gn
index 11fca1b1722..681852441e0 100644
--- a/chromium/components/printing/common/BUILD.gn
+++ b/chromium/components/printing/common/BUILD.gn
@@ -4,6 +4,8 @@
static_library("common") {
sources = [
+ "cloud_print_cdd_conversion.cc",
+ "cloud_print_cdd_conversion.h",
"print_messages.cc",
"print_messages.h",
"printing_param_traits_macros.h",
@@ -11,6 +13,7 @@ static_library("common") {
deps = [
"//base",
+ "//components/cloud_devices/common:common",
"//ipc",
"//printing",
"//printing/common:common",
diff --git a/chromium/components/printing/common/cloud_print_cdd_conversion.cc b/chromium/components/printing/common/cloud_print_cdd_conversion.cc
new file mode 100644
index 00000000000..4ceed34dd77
--- /dev/null
+++ b/chromium/components/printing/common/cloud_print_cdd_conversion.cc
@@ -0,0 +1,129 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/printing/common/cloud_print_cdd_conversion.h"
+
+#include <stddef.h>
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "components/cloud_devices/common/printer_description.h"
+#include "printing/backend/print_backend.h"
+
+namespace cloud_print {
+
+std::unique_ptr<base::DictionaryValue> PrinterSemanticCapsAndDefaultsToCdd(
+ const printing::PrinterSemanticCapsAndDefaults& semantic_info) {
+ using namespace cloud_devices::printer;
+ cloud_devices::CloudDeviceDescription description;
+
+ ContentTypesCapability content_types;
+ content_types.AddOption("application/pdf");
+ content_types.SaveTo(&description);
+
+ if (semantic_info.collate_capable) {
+ CollateCapability collate;
+ collate.set_default_value(semantic_info.collate_default);
+ collate.SaveTo(&description);
+ }
+
+ if (semantic_info.copies_capable) {
+ CopiesCapability copies;
+ copies.SaveTo(&description);
+ }
+
+ if (semantic_info.duplex_capable) {
+ DuplexCapability duplex;
+ duplex.AddDefaultOption(NO_DUPLEX,
+ semantic_info.duplex_default == printing::SIMPLEX);
+ duplex.AddDefaultOption(
+ LONG_EDGE, semantic_info.duplex_default == printing::LONG_EDGE);
+ duplex.AddDefaultOption(
+ SHORT_EDGE, semantic_info.duplex_default == printing::SHORT_EDGE);
+ duplex.SaveTo(&description);
+ }
+
+ ColorCapability color;
+ if (semantic_info.color_default || semantic_info.color_changeable) {
+ Color standard_color(STANDARD_COLOR);
+ standard_color.vendor_id = base::IntToString(semantic_info.color_model);
+ color.AddDefaultOption(standard_color, semantic_info.color_default);
+ }
+ if (!semantic_info.color_default || semantic_info.color_changeable) {
+ Color standard_monochrome(STANDARD_MONOCHROME);
+ standard_monochrome.vendor_id = base::IntToString(semantic_info.bw_model);
+ color.AddDefaultOption(standard_monochrome, !semantic_info.color_default);
+ }
+ color.SaveTo(&description);
+
+ if (!semantic_info.papers.empty()) {
+ Media default_media(semantic_info.default_paper.display_name,
+ semantic_info.default_paper.vendor_id,
+ semantic_info.default_paper.size_um.width(),
+ semantic_info.default_paper.size_um.height());
+ default_media.MatchBySize();
+
+ MediaCapability media;
+ bool is_default_set = false;
+ for (size_t i = 0; i < semantic_info.papers.size(); ++i) {
+ gfx::Size paper_size = semantic_info.papers[i].size_um;
+ if (paper_size.width() > paper_size.height())
+ paper_size.SetSize(paper_size.height(), paper_size.width());
+ Media new_media(semantic_info.papers[i].display_name,
+ semantic_info.papers[i].vendor_id, paper_size.width(),
+ paper_size.height());
+ new_media.MatchBySize();
+ if (new_media.IsValid() && !media.Contains(new_media)) {
+ if (!default_media.IsValid())
+ default_media = new_media;
+ media.AddDefaultOption(new_media, new_media == default_media);
+ is_default_set = is_default_set || (new_media == default_media);
+ }
+ }
+ if (!is_default_set && default_media.IsValid())
+ media.AddDefaultOption(default_media, true);
+
+ if (media.IsValid()) {
+ media.SaveTo(&description);
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ if (!semantic_info.dpis.empty()) {
+ DpiCapability dpi;
+ Dpi default_dpi(semantic_info.default_dpi.width(),
+ semantic_info.default_dpi.height());
+ bool is_default_set = false;
+ for (size_t i = 0; i < semantic_info.dpis.size(); ++i) {
+ Dpi new_dpi(semantic_info.dpis[i].width(),
+ semantic_info.dpis[i].height());
+ if (new_dpi.IsValid() && !dpi.Contains(new_dpi)) {
+ if (!default_dpi.IsValid())
+ default_dpi = new_dpi;
+ dpi.AddDefaultOption(new_dpi, new_dpi == default_dpi);
+ is_default_set = is_default_set || (new_dpi == default_dpi);
+ }
+ }
+ if (!is_default_set && default_dpi.IsValid())
+ dpi.AddDefaultOption(default_dpi, true);
+ if (dpi.IsValid()) {
+ dpi.SaveTo(&description);
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ OrientationCapability orientation;
+ orientation.AddDefaultOption(PORTRAIT, true);
+ orientation.AddOption(LANDSCAPE);
+ orientation.AddOption(AUTO_ORIENTATION);
+ orientation.SaveTo(&description);
+
+ return base::WrapUnique(description.root().DeepCopy());
+}
+
+} // namespace cloud_print
diff --git a/chromium/components/printing/common/cloud_print_cdd_conversion.h b/chromium/components/printing/common/cloud_print_cdd_conversion.h
new file mode 100644
index 00000000000..69eba7e2813
--- /dev/null
+++ b/chromium/components/printing/common/cloud_print_cdd_conversion.h
@@ -0,0 +1,24 @@
+// 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_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 {
+struct PrinterSemanticCapsAndDefaults;
+}
+
+namespace cloud_print {
+
+std::unique_ptr<base::DictionaryValue> PrinterSemanticCapsAndDefaultsToCdd(
+ const printing::PrinterSemanticCapsAndDefaults& semantic_info);
+
+} // namespace cloud_print
+
+#endif // COMPONENTS_PRINTING_COMMON_CLOUD_PRINT_CDD_CONVERSION_H_
diff --git a/chromium/components/printing/common/print_messages.cc b/chromium/components/printing/common/print_messages.cc
index ef1e25b11af..6df98550d22 100644
--- a/chromium/components/printing/common/print_messages.cc
+++ b/chromium/components/printing/common/print_messages.cc
@@ -6,8 +6,14 @@
#include "printing/features/features.h"
#include "ui/gfx/geometry/size.h"
+// Generating implementations for all aspects of the IPC message
+// handling by setting appropriate IPC macros and including the
+// message file, over and over again until all versions have been
+// generated.
+
#define IPC_MESSAGE_IMPL
#undef COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
+#undef COMPONENTS_PRINTING_COMMON_PRINTING_PARAM_TRAITS_MACROS_H_
#include "components/printing/common/print_messages.h"
#ifndef COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
#error "Failed to include header components/printing/common/print_messages.h"
@@ -16,6 +22,7 @@
// Generate constructors.
#include "ipc/struct_constructor_macros.h"
#undef COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
+#undef COMPONENTS_PRINTING_COMMON_PRINTING_PARAM_TRAITS_MACROS_H_
#include "components/printing/common/print_messages.h"
#ifndef COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
#error "Failed to include header components/printing/common/print_messages.h"
@@ -24,6 +31,7 @@
// Generate destructors.
#include "ipc/struct_destructor_macros.h"
#undef COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
+#undef COMPONENTS_PRINTING_COMMON_PRINTING_PARAM_TRAITS_MACROS_H_
#include "components/printing/common/print_messages.h"
#ifndef COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
#error "Failed to include header components/printing/common/print_messages.h"
@@ -33,6 +41,7 @@
#include "ipc/param_traits_write_macros.h"
namespace IPC {
#undef COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
+#undef COMPONENTS_PRINTING_COMMON_PRINTING_PARAM_TRAITS_MACROS_H_
#include "components/printing/common/print_messages.h"
#ifndef COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
#error "Failed to include header components/printing/common/print_messages.h"
@@ -43,6 +52,7 @@ namespace IPC {
#include "ipc/param_traits_read_macros.h"
namespace IPC {
#undef COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
+#undef COMPONENTS_PRINTING_COMMON_PRINTING_PARAM_TRAITS_MACROS_H_
#include "components/printing/common/print_messages.h"
#ifndef COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
#error "Failed to include header components/printing/common/print_messages.h"
@@ -53,6 +63,9 @@ namespace IPC {
#include "ipc/param_traits_log_macros.h"
namespace IPC {
#undef COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
+// Force multiple inclusion of the param traits file to generate all methods.
+#undef COMPONENTS_PRINTING_COMMON_PRINTING_PARAM_TRAITS_MACROS_H_
+
#include "components/printing/common/print_messages.h"
#ifndef COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
#error "Failed to include header components/printing/common/print_messages.h"
@@ -65,7 +78,7 @@ PrintMsg_Print_Params::PrintMsg_Print_Params()
printable_area(),
margin_top(0),
margin_left(0),
- dpi(0),
+ dpi(),
scale_factor(1.0f),
rasterize_pdf(false),
document_cookie(0),
@@ -82,7 +95,8 @@ PrintMsg_Print_Params::PrintMsg_Print_Params()
header_template(),
footer_template(),
should_print_backgrounds(false),
- printed_doc_type(printing::SkiaDocumentType::PDF) {}
+ printed_doc_type(printing::SkiaDocumentType::PDF),
+ prefer_css_page_size(false) {}
PrintMsg_Print_Params::PrintMsg_Print_Params(
const PrintMsg_Print_Params& other) = default;
@@ -95,7 +109,7 @@ void PrintMsg_Print_Params::Reset() {
printable_area = gfx::Rect();
margin_top = 0;
margin_left = 0;
- dpi = 0;
+ dpi = gfx::Size();
scale_factor = 1.0f;
rasterize_pdf = false;
document_cookie = 0;
@@ -113,6 +127,7 @@ void PrintMsg_Print_Params::Reset() {
footer_template = base::string16();
should_print_backgrounds = false;
printed_doc_type = printing::SkiaDocumentType::PDF;
+ prefer_css_page_size = false;
}
PrintMsg_PrintPages_Params::PrintMsg_PrintPages_Params()
@@ -129,6 +144,10 @@ void PrintMsg_PrintPages_Params::Reset() {
pages = std::vector<int>();
}
+PrintMsg_PrintFrame_Params::PrintMsg_PrintFrame_Params() {}
+
+PrintMsg_PrintFrame_Params::~PrintMsg_PrintFrame_Params() {}
+
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
PrintHostMsg_RequestPrintPreview_Params::
PrintHostMsg_RequestPrintPreview_Params()
diff --git a/chromium/components/printing/common/print_messages.h b/chromium/components/printing/common/print_messages.h
index 6d02771d018..22469f97d1f 100644
--- a/chromium/components/printing/common/print_messages.h
+++ b/chromium/components/printing/common/print_messages.h
@@ -28,9 +28,6 @@
#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
#include "ui/gfx/native_widget_types.h"
-// Force multiple inclusion of the param traits file to generate all methods.
-#undef COMPONENTS_PRINTING_COMMON_PRINTING_PARAM_TRAITS_MACROS_H_
-
#ifndef INTERNAL_COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
#define INTERNAL_COMPONENTS_PRINTING_COMMON_PRINT_MESSAGES_H_
@@ -47,7 +44,7 @@ struct PrintMsg_Print_Params {
gfx::Rect printable_area;
int margin_top;
int margin_left;
- double dpi;
+ gfx::Size dpi;
double scale_factor;
bool rasterize_pdf;
int document_cookie;
@@ -65,6 +62,7 @@ struct PrintMsg_Print_Params {
base::string16 footer_template;
bool should_print_backgrounds;
printing::SkiaDocumentType printed_doc_type;
+ bool prefer_css_page_size;
};
struct PrintMsg_PrintPages_Params {
@@ -79,6 +77,14 @@ struct PrintMsg_PrintPages_Params {
std::vector<int> pages;
};
+struct PrintMsg_PrintFrame_Params {
+ PrintMsg_PrintFrame_Params();
+ ~PrintMsg_PrintFrame_Params();
+
+ gfx::Rect printable_area;
+ int document_cookie;
+};
+
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
struct PrintHostMsg_RequestPrintPreview_Params {
PrintHostMsg_RequestPrintPreview_Params();
@@ -115,7 +121,7 @@ IPC_STRUCT_TRAITS_BEGIN(PrintMsg_Print_Params)
// in pixels according to dpi.
IPC_STRUCT_TRAITS_MEMBER(page_size)
- // In pixels according to dpi_x and dpi_y.
+ // In pixels according to dpi.
IPC_STRUCT_TRAITS_MEMBER(content_size)
// Physical printable area of the page in pixels according to dpi.
@@ -127,7 +133,7 @@ IPC_STRUCT_TRAITS_BEGIN(PrintMsg_Print_Params)
// The x-offset of the printable area, in pixels according to dpi.
IPC_STRUCT_TRAITS_MEMBER(margin_left)
- // Specifies dots per inch.
+ // Specifies dots per inch in the x and y direction.
IPC_STRUCT_TRAITS_MEMBER(dpi)
// Specifies the scale factor in percent
@@ -182,6 +188,9 @@ IPC_STRUCT_TRAITS_BEGIN(PrintMsg_Print_Params)
// The document type of printed page(s) from render.
IPC_STRUCT_TRAITS_MEMBER(printed_doc_type)
+
+ // True if page size defined by css should be preferred.
+ IPC_STRUCT_TRAITS_MEMBER(prefer_css_page_size)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(printing::PageRange)
@@ -230,15 +239,37 @@ IPC_STRUCT_TRAITS_BEGIN(PrintMsg_PrintPages_Params)
IPC_STRUCT_TRAITS_MEMBER(pages)
IPC_STRUCT_TRAITS_END()
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
-// Parameters to describe a rendered document.
-IPC_STRUCT_BEGIN(PrintHostMsg_DidPreviewDocument_Params)
+IPC_STRUCT_TRAITS_BEGIN(PrintMsg_PrintFrame_Params)
+ // Physical printable area of the page in pixels according to dpi.
+ IPC_STRUCT_TRAITS_MEMBER(printable_area)
+
+ // Cookie that is unique for each print request.
+ // It is used to associate the printed frame with its original print request.
+ IPC_STRUCT_TRAITS_MEMBER(document_cookie)
+IPC_STRUCT_TRAITS_END()
+
+// Holds the printed content information.
+// The printed content is in shared memory, and passed by its handle
+// and data size.
+// A map on out-of-process subframe contents is also included so the printed
+// content can be composited as needed.
+IPC_STRUCT_BEGIN(PrintHostMsg_DidPrintContent_Params)
// A shared memory handle to metafile data.
IPC_STRUCT_MEMBER(base::SharedMemoryHandle, metafile_data_handle)
// Size of metafile data.
IPC_STRUCT_MEMBER(uint32_t, data_size)
+ // Content id to render frame proxy id mapping for out-of-process subframes.
+ IPC_STRUCT_MEMBER(printing::ContentToProxyIdMap, subframe_content_info)
+IPC_STRUCT_END()
+
+#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
+// Parameters to describe a rendered document.
+IPC_STRUCT_BEGIN(PrintHostMsg_DidPreviewDocument_Params)
+ // Document's content including metafile data and subframe info.
+ IPC_STRUCT_MEMBER(PrintHostMsg_DidPrintContent_Params, content)
+
// Cookie for the document to ensure correctness.
IPC_STRUCT_MEMBER(int, document_cookie)
@@ -254,17 +285,17 @@ IPC_STRUCT_END()
// Parameters to describe a rendered preview page.
IPC_STRUCT_BEGIN(PrintHostMsg_DidPreviewPage_Params)
- // A shared memory handle to metafile data for a draft document of the page.
- IPC_STRUCT_MEMBER(base::SharedMemoryHandle, metafile_data_handle)
-
- // Size of metafile data.
- IPC_STRUCT_MEMBER(uint32_t, data_size)
+ // Page's content including metafile data and subframe info.
+ IPC_STRUCT_MEMBER(PrintHostMsg_DidPrintContent_Params, content)
// |page_number| is zero-based and should not be negative.
IPC_STRUCT_MEMBER(int, page_number)
// The id of the preview request.
IPC_STRUCT_MEMBER(int, preview_request_id)
+
+ // Cookie for the document to ensure correctness.
+ IPC_STRUCT_MEMBER(int, document_cookie)
IPC_STRUCT_END()
// Parameters sent along with the page count.
@@ -277,20 +308,13 @@ IPC_STRUCT_BEGIN(PrintHostMsg_DidGetPreviewPageCount_Params)
// The id of the preview request.
IPC_STRUCT_MEMBER(int, preview_request_id)
-
- // Indicates whether the existing preview data needs to be cleared or not.
- IPC_STRUCT_MEMBER(bool, clear_preview_data)
IPC_STRUCT_END()
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
// Parameters to describe a rendered page.
IPC_STRUCT_BEGIN(PrintHostMsg_DidPrintDocument_Params)
- // A shared memory handle to the PDF data. This data can be quite large so a
- // memory map needs to be used.
- IPC_STRUCT_MEMBER(base::SharedMemoryHandle, metafile_data_handle)
-
- // Size of the metafile data.
- IPC_STRUCT_MEMBER(uint32_t, data_size)
+ // Document's content including metafile data and subframe info.
+ IPC_STRUCT_MEMBER(PrintHostMsg_DidPrintContent_Params, content)
// Cookie for the document to ensure correctness.
IPC_STRUCT_MEMBER(int, document_cookie)
@@ -339,6 +363,9 @@ IPC_MESSAGE_ROUTED0(PrintMsg_PrintPages)
IPC_MESSAGE_ROUTED0(PrintMsg_PrintForSystemDialog)
#endif
+// Print content of an out-of-process subframe.
+IPC_MESSAGE_ROUTED1(PrintMsg_PrintFrameContent, PrintMsg_PrintFrame_Params)
+
// Tells the RenderFrame that printing is done so it can clean up.
IPC_MESSAGE_ROUTED1(PrintMsg_PrintingDone,
bool /* success */)
@@ -378,6 +405,12 @@ IPC_MESSAGE_ROUTED0(PrintHostMsg_DidShowPrintDialog)
IPC_MESSAGE_ROUTED1(PrintHostMsg_DidPrintDocument,
PrintHostMsg_DidPrintDocument_Params /* page content */)
+// Sends back to the browser the rendered subframe content that was
+// requested by a PrintMsg_PrintFrameContent message.
+IPC_MESSAGE_ROUTED2(PrintHostMsg_DidPrintFrameContent,
+ int /* rendered document cookie */,
+ PrintHostMsg_DidPrintContent_Params)
+
// The renderer wants to know the default print settings.
IPC_SYNC_MESSAGE_ROUTED0_1(PrintHostMsg_GetDefaultPrintSettings,
PrintMsg_Print_Params /* default_settings */)
diff --git a/chromium/components/printing/renderer/BUILD.gn b/chromium/components/printing/renderer/BUILD.gn
index 9d92b864320..5153b59bade 100644
--- a/chromium/components/printing/renderer/BUILD.gn
+++ b/chromium/components/printing/renderer/BUILD.gn
@@ -19,8 +19,8 @@ static_library("renderer") {
"//content/public/renderer",
"//net",
"//printing",
- "//third_party/WebKit/common:blink_common",
"//third_party/WebKit/public:blink",
+ "//third_party/WebKit/public/common",
"//ui/base",
]
}
diff --git a/chromium/components/printing/renderer/print_render_frame_helper.cc b/chromium/components/printing/renderer/print_render_frame_helper.cc
index 86c3b7a291e..2d81ba90d69 100644
--- a/chromium/components/printing/renderer/print_render_frame_helper.cc
+++ b/chromium/components/printing/renderer/print_render_frame_helper.cc
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <algorithm>
+#include <memory>
#include <string>
#include <utility>
@@ -16,7 +17,6 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/process_handle.h"
#include "base/single_thread_task_runner.h"
@@ -38,8 +38,8 @@
#include "printing/metafile_skia_wrapper.h"
#include "printing/pdf_metafile_skia.h"
#include "printing/units.h"
-#include "third_party/WebKit/common/page/page_visibility_state.mojom.h"
-#include "third_party/WebKit/common/sandbox_flags.h"
+#include "third_party/WebKit/public/common/frame/sandbox_flags.h"
+#include "third_party/WebKit/public/mojom/page/page_visibility_state.mojom.h"
#include "third_party/WebKit/public/platform/Platform.h"
#include "third_party/WebKit/public/platform/WebDoubleSize.h"
#include "third_party/WebKit/public/platform/WebSize.h"
@@ -117,15 +117,19 @@ int GetDPI(const PrintMsg_Print_Params* print_params) {
// on dpi.
return kPointsPerInch;
#else
- return static_cast<int>(print_params->dpi);
+ // Render using the higher of the two resolutions in both dimensions to
+ // prevent bad quality print jobs on rectantular DPI printers.
+ return static_cast<int>(
+ std::max(print_params->dpi.width(), print_params->dpi.height()));
#endif // defined(OS_MACOSX)
}
bool PrintMsg_Print_Params_IsValid(const PrintMsg_Print_Params& params) {
return !params.content_size.IsEmpty() && !params.page_size.IsEmpty() &&
!params.printable_area.IsEmpty() && params.document_cookie &&
- params.dpi && params.margin_top >= 0 && params.margin_left >= 0 &&
- params.dpi > kMinDpi && params.document_cookie != 0;
+ !params.dpi.IsEmpty() && params.dpi.width() > kMinDpi &&
+ params.dpi.height() > kMinDpi && params.margin_top >= 0 &&
+ params.margin_left >= 0 && params.document_cookie != 0;
}
// Helper function to check for fit to page
@@ -524,7 +528,6 @@ PrintMsg_Print_Params CalculatePrintParamsForCss(
return result_params;
}
-
} // namespace
FrameReference::FrameReference(blink::WebLocalFrame* frame) {
@@ -615,7 +618,7 @@ void PrintRenderFrameHelper::PrintHeaderAndFooter(
// Load page with script to avoid async operations.
ExecuteScript(frame, kPageLoadScriptFormat, html);
- auto options = base::MakeUnique<base::DictionaryValue>();
+ auto options = std::make_unique<base::DictionaryValue>();
options->SetDouble(kSettingHeaderFooterDate, base::Time::Now().ToJsTime());
options->SetDouble("width", page_size.width);
options->SetDouble("height", page_size.height);
@@ -932,10 +935,6 @@ void PrepareFrameAndViewForPrint::FinishPrinting() {
on_ready_.Reset();
}
-bool PrintRenderFrameHelper::Delegate::IsAskPrintSettingsEnabled() {
- return true;
-}
-
bool PrintRenderFrameHelper::Delegate::IsScriptedPrintEnabled() {
return true;
}
@@ -1055,6 +1054,7 @@ bool PrintRenderFrameHelper::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(PrintMsg_ClosePrintPreviewDialog,
OnClosePrintPreviewDialog)
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
+ IPC_MESSAGE_HANDLER(PrintMsg_PrintFrameContent, OnPrintFrameContent)
IPC_MESSAGE_HANDLER(PrintMsg_SetPrintingEnabled, OnSetPrintingEnabled)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -1174,12 +1174,6 @@ void PrintRenderFrameHelper::OnPrintPreview(
// PDF printer device supports alpha blending.
print_pages_params_->params.supports_alpha_blend = true;
- bool generate_draft_pages = false;
- if (!settings.GetBoolean(kSettingGenerateDraftData, &generate_draft_pages)) {
- NOTREACHED();
- }
- print_preview_context_.set_generate_draft_pages(generate_draft_pages);
-
PrepareFrameForPreviewDocument();
}
@@ -1199,7 +1193,7 @@ void PrintRenderFrameHelper::PrepareFrameForPreviewDocument() {
}
const PrintMsg_Print_Params& print_params = print_pages_params_->params;
- prep_frame_view_ = base::MakeUnique<PrepareFrameAndViewForPrint>(
+ prep_frame_view_ = std::make_unique<PrepareFrameAndViewForPrint>(
print_params, print_preview_context_.source_frame(),
print_preview_context_.source_node(), ignore_css_margins_);
prep_frame_view_->CopySelectionIfNeeded(
@@ -1227,7 +1221,8 @@ bool PrintRenderFrameHelper::CreatePreviewDocument() {
const std::vector<int>& pages = print_pages_params_->pages;
if (!print_preview_context_.CreatePreviewDocument(
- std::move(prep_frame_view_), pages, print_params.printed_doc_type)) {
+ std::move(prep_frame_view_), pages, print_params.printed_doc_type,
+ print_params.document_cookie)) {
return false;
}
@@ -1290,8 +1285,6 @@ bool PrintRenderFrameHelper::CreatePreviewDocument() {
params.page_count = print_preview_context_.total_page_count();
params.fit_to_page_scaling = fit_to_page_scaling;
params.preview_request_id = print_params.preview_request_id;
- params.clear_preview_data = print_preview_context_.generate_draft_pages() ||
- !print_preview_context_.IsModifiable();
Send(new PrintHostMsg_DidGetPreviewPageCount(routing_id(), params));
if (CheckForCancel())
return false;
@@ -1326,18 +1319,11 @@ bool PrintRenderFrameHelper::CreatePreviewDocument() {
return true;
}
-#if !defined(OS_MACOSX) && BUILDFLAG(ENABLE_PRINT_PREVIEW)
+#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
bool PrintRenderFrameHelper::RenderPreviewPage(
int page_number,
const PrintMsg_Print_Params& print_params) {
- std::unique_ptr<PdfMetafileSkia> draft_metafile;
PdfMetafileSkia* initial_render_metafile = print_preview_context_.metafile();
- if (print_preview_context_.IsModifiable() && is_print_ready_metafile_sent_) {
- draft_metafile =
- base::MakeUnique<PdfMetafileSkia>(print_params.printed_doc_type);
- initial_render_metafile = draft_metafile.get();
- }
-
base::TimeTicks begin_time = base::TimeTicks::Now();
PrintPageInternal(print_params, page_number,
print_preview_context_.total_page_count(),
@@ -1345,18 +1331,23 @@ bool PrintRenderFrameHelper::RenderPreviewPage(
initial_render_metafile, nullptr, nullptr);
print_preview_context_.RenderedPreviewPage(base::TimeTicks::Now() -
begin_time);
- if (draft_metafile.get()) {
- draft_metafile->FinishDocument();
- } else if (print_preview_context_.IsModifiable() &&
- print_preview_context_.generate_draft_pages()) {
- DCHECK(!draft_metafile.get());
- draft_metafile =
- print_preview_context_.metafile()->GetMetafileForCurrentPage(
- print_params.printed_doc_type);
- }
- return PreviewPageRendered(page_number, draft_metafile.get());
+
+ // For non-modifiable content, there is no need to call PreviewPageRendered()
+ // since it generally renders very fast. Just render and send the finished
+ // document to the browser.
+ if (!print_preview_context_.IsModifiable())
+ return true;
+
+ // Let the browser know this page has been rendered. Send |metafile|, which
+ // contains the rendering for just this one page. Then the browser can update
+ // the user visible print preview one page at a time, instead of waiting for
+ // the entire document to be rendered.
+ std::unique_ptr<PdfMetafileSkia> metafile =
+ initial_render_metafile->GetMetafileForCurrentPage(
+ print_params.printed_doc_type);
+ return PreviewPageRendered(page_number, std::move(metafile));
}
-#endif // !defined(OS_MACOSX) && BUILDFLAG(ENABLE_PRINT_PREVIEW)
+#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
bool PrintRenderFrameHelper::FinalizePrintReadyDocument() {
DCHECK(!is_print_ready_metafile_sent_);
@@ -1365,14 +1356,13 @@ bool PrintRenderFrameHelper::FinalizePrintReadyDocument() {
PdfMetafileSkia* metafile = print_preview_context_.metafile();
PrintHostMsg_DidPreviewDocument_Params preview_params;
- if (!CopyMetafileDataToReadOnlySharedMem(
- *metafile, &preview_params.metafile_data_handle)) {
+ if (!CopyMetafileDataToReadOnlySharedMem(*metafile,
+ &preview_params.content)) {
LOG(ERROR) << "CopyMetafileDataToReadOnlySharedMem failed";
print_preview_context_.set_error(PREVIEW_ERROR_METAFILE_COPY_FAILED);
return false;
}
- preview_params.data_size = metafile->GetDataSize();
preview_params.document_cookie = print_pages_params_->params.document_cookie;
preview_params.expected_pages_count =
print_preview_context_.total_page_count();
@@ -1425,6 +1415,68 @@ void PrintRenderFrameHelper::OnClosePrintPreviewDialog() {
}
#endif
+void PrintRenderFrameHelper::OnPrintFrameContent(
+ const PrintMsg_PrintFrame_Params& params) {
+ if (ipc_nesting_level_ > 1)
+ return;
+
+ // If the last request is not finished yet, do not proceed.
+ if (prep_frame_view_) {
+ DLOG(ERROR) << "Previous request is still ongoing";
+ return;
+ }
+
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
+ blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
+ frame->DispatchBeforePrintEvent();
+ if (!weak_this)
+ return;
+
+ PdfMetafileSkia metafile(SkiaDocumentType::MSKP, params.document_cookie);
+ gfx::Size area_size = params.printable_area.size();
+ // Since GetVectorCanvasForNewPage() starts a new recording, it will return
+ // a valid canvas.
+ cc::PaintCanvas* canvas =
+ metafile.GetVectorCanvasForNewPage(area_size, gfx::Rect(area_size), 1.0f);
+ DCHECK(canvas);
+
+ MetafileSkiaWrapper::SetMetafileOnCanvas(canvas, &metafile);
+
+ // This subframe doesn't need to fit to the page size, thus we are not using
+ // printing layout for it. It just prints with the specified size.
+ blink::WebPrintParams web_print_params(area_size,
+ /*use_printing_layout=*/false);
+
+ // Printing embedded pdf plugin has been broken since pdf plugin viewer was
+ // moved out-of-process
+ // (https://bugs.chromium.org/p/chromium/issues/detail?id=464269). So don't
+ // try to handle pdf plugin element until that bug is fixed.
+ if (frame->PrintBegin(web_print_params,
+ /*constrain_to_node=*/blink::WebElement())) {
+ frame->PrintPage(0, canvas);
+ }
+ frame->PrintEnd();
+
+ // Done printing. Close the canvas to retrieve the compiled metafile.
+ bool ret = metafile.FinishPage();
+ DCHECK(ret);
+
+ metafile.FinishFrameContent();
+
+ // Send the printed result back.
+ PrintHostMsg_DidPrintContent_Params printed_frame_params;
+ if (!CopyMetafileDataToReadOnlySharedMem(metafile, &printed_frame_params)) {
+ DLOG(ERROR) << "CopyMetafileDataToSharedMem failed";
+ return;
+ }
+
+ Send(new PrintHostMsg_DidPrintFrameContent(
+ routing_id(), params.document_cookie, printed_frame_params));
+
+ if (!render_frame_gone_)
+ frame->DispatchAfterPrintEvent();
+}
+
bool PrintRenderFrameHelper::IsPrintingEnabled() const {
return is_printing_enabled_;
}
@@ -1491,7 +1543,7 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
}
// Ask the browser to show UI to retrieve the final print settings.
- if (delegate_->IsAskPrintSettingsEnabled()) {
+ {
// PrintHostMsg_ScriptedPrint in GetPrintSettingsFromUser() will reset
// |print_scaling_option|, so save the value here and restore it afterwards.
blink::WebPrintScalingOption scaling_option =
@@ -1505,9 +1557,13 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
if (!self)
return;
- print_settings.params.print_scaling_option = scaling_option;
+ print_settings.params.print_scaling_option =
+ print_settings.params.prefer_css_page_size
+ ? blink::kWebPrintScalingOptionSourceSize
+ : scaling_option;
SetPrintPagesParams(print_settings);
- if (!print_settings.params.dpi || !print_settings.params.document_cookie) {
+ if (print_settings.params.dpi.IsEmpty() ||
+ !print_settings.params.document_cookie) {
DidFinishPrinting(OK); // Release resources and fail silently on failure.
return;
}
@@ -1613,7 +1669,8 @@ bool PrintRenderFrameHelper::PrintPagesNative(blink::WebLocalFrame* frame,
if (printed_pages.empty())
return false;
- PdfMetafileSkia metafile(print_params.printed_doc_type);
+ PdfMetafileSkia metafile(print_params.printed_doc_type,
+ print_params.document_cookie);
CHECK(metafile.Init());
PrintHostMsg_DidPrintDocument_Params page_params;
@@ -1630,12 +1687,10 @@ bool PrintRenderFrameHelper::PrintPagesNative(blink::WebLocalFrame* frame,
metafile.FinishDocument();
- if (!CopyMetafileDataToReadOnlySharedMem(metafile,
- &page_params.metafile_data_handle)) {
+ if (!CopyMetafileDataToReadOnlySharedMem(metafile, &page_params.content)) {
return false;
}
- page_params.data_size = metafile.GetDataSize();
page_params.document_cookie = print_params.document_cookie;
#if defined(OS_WIN)
page_params.physical_offsets = printer_printable_area_.origin();
@@ -1845,7 +1900,7 @@ void PrintRenderFrameHelper::GetPrintSettingsFromUser(
print_pages_params_.reset();
- auto msg = base::MakeUnique<PrintHostMsg_ScriptedPrint>(routing_id(), params,
+ auto msg = std::make_unique<PrintHostMsg_ScriptedPrint>(routing_id(), params,
print_settings);
msg->EnableMessagePumping();
Send(msg.release());
@@ -1860,7 +1915,7 @@ bool PrintRenderFrameHelper::RenderPagesForPrint(blink::WebLocalFrame* frame,
const PrintMsg_PrintPages_Params& params = *print_pages_params_;
const PrintMsg_Print_Params& print_params = params.params;
- prep_frame_view_ = base::MakeUnique<PrepareFrameAndViewForPrint>(
+ prep_frame_view_ = std::make_unique<PrepareFrameAndViewForPrint>(
print_params, frame, node, ignore_css_margins_);
DCHECK(!print_pages_params_->params.selection_only ||
print_pages_params_->pages.empty());
@@ -1953,7 +2008,7 @@ void PrintRenderFrameHelper::PrintPageInternal(
bool PrintRenderFrameHelper::CopyMetafileDataToReadOnlySharedMem(
const PdfMetafileSkia& metafile,
- base::SharedMemoryHandle* shared_mem_handle) {
+ PrintHostMsg_DidPrintContent_Params* params) {
uint32_t buf_size = metafile.GetDataSize();
if (buf_size == 0)
return false;
@@ -1972,8 +2027,10 @@ bool PrintRenderFrameHelper::CopyMetafileDataToReadOnlySharedMem(
MojoResult result = mojo::UnwrapSharedMemoryHandle(
buffer->Clone(mojo::SharedBufferHandle::AccessMode::READ_ONLY),
- shared_mem_handle, nullptr, nullptr);
+ &params->metafile_data_handle, nullptr, nullptr);
DCHECK_EQ(MOJO_RESULT_OK, result);
+ params->data_size = metafile.GetDataSize();
+ params->subframe_content_info = metafile.GetSubframeContentInfo();
return true;
}
@@ -2017,7 +2074,7 @@ void PrintRenderFrameHelper::RequestPrintPreview(PrintPreviewRequestType type) {
base::Bind(&PrintRenderFrameHelper::ShowScriptedPrintPreview,
weak_ptr_factory_.GetWeakPtr()));
}
- auto msg = base::MakeUnique<PrintHostMsg_SetupScriptedPrintPreview>(
+ auto msg = std::make_unique<PrintHostMsg_SetupScriptedPrintPreview>(
routing_id());
msg->EnableMessagePumping();
auto self = weak_ptr_factory_.GetWeakPtr();
@@ -2076,38 +2133,26 @@ bool PrintRenderFrameHelper::CheckForCancel() {
return cancel;
}
-bool PrintRenderFrameHelper::PreviewPageRendered(int page_number,
- PdfMetafileSkia* metafile) {
+bool PrintRenderFrameHelper::PreviewPageRendered(
+ int page_number,
+ std::unique_ptr<PdfMetafileSkia> metafile) {
DCHECK_GE(page_number, FIRST_PAGE_INDEX);
-
- // For non-modifiable files, |metafile| should be NULL, so do not bother
- // sending a message. If we don't generate draft metafiles, |metafile| is
- // NULL.
- if (!print_preview_context_.IsModifiable() ||
- !print_preview_context_.generate_draft_pages()) {
- DCHECK(!metafile);
- return true;
- }
-
- if (!metafile) {
- NOTREACHED();
- print_preview_context_.set_error(
- PREVIEW_ERROR_PAGE_RENDERED_WITHOUT_METAFILE);
- return false;
- }
+ DCHECK(metafile);
+ DCHECK(print_preview_context_.IsModifiable());
PrintHostMsg_DidPreviewPage_Params preview_page_params;
- if (!CopyMetafileDataToReadOnlySharedMem(
- *metafile, &preview_page_params.metafile_data_handle)) {
+ if (!CopyMetafileDataToReadOnlySharedMem(*metafile,
+ &preview_page_params.content)) {
LOG(ERROR) << "CopyMetafileDataToReadOnlySharedMem failed";
print_preview_context_.set_error(PREVIEW_ERROR_METAFILE_COPY_FAILED);
return false;
}
- preview_page_params.data_size = metafile->GetDataSize();
preview_page_params.page_number = page_number;
preview_page_params.preview_request_id =
print_pages_params_->params.preview_request_id;
+ preview_page_params.document_cookie =
+ print_pages_params_->params.document_cookie;
Send(new PrintHostMsg_DidPreviewPage(routing_id(), preview_page_params));
return true;
@@ -2117,7 +2162,6 @@ bool PrintRenderFrameHelper::PreviewPageRendered(int page_number,
PrintRenderFrameHelper::PrintPreviewContext::PrintPreviewContext()
: total_page_count_(0),
current_page_index_(0),
- generate_draft_pages_(true),
is_modifiable_(true),
print_ready_metafile_page_count_(0),
error_(PREVIEW_ERROR_NONE),
@@ -2154,7 +2198,8 @@ void PrintRenderFrameHelper::PrintPreviewContext::OnPrintPreview() {
bool PrintRenderFrameHelper::PrintPreviewContext::CreatePreviewDocument(
std::unique_ptr<PrepareFrameAndViewForPrint> prepared_frame,
const std::vector<int>& pages,
- SkiaDocumentType doc_type) {
+ SkiaDocumentType doc_type,
+ int document_cookie) {
DCHECK_EQ(INITIALIZED, state_);
state_ = RENDERING;
@@ -2169,7 +2214,7 @@ bool PrintRenderFrameHelper::PrintPreviewContext::CreatePreviewDocument(
return false;
}
- metafile_ = base::MakeUnique<PdfMetafileSkia>(doc_type);
+ metafile_ = std::make_unique<PdfMetafileSkia>(doc_type, document_cookie);
CHECK(metafile_->Init());
current_page_index_ = 0;
@@ -2184,23 +2229,14 @@ bool PrintRenderFrameHelper::PrintPreviewContext::CreatePreviewDocument(
pages_to_render_.end(),
total_page_count_) -
pages_to_render_.begin());
- print_ready_metafile_page_count_ = pages_to_render_.size();
+
if (pages_to_render_.empty()) {
- print_ready_metafile_page_count_ = total_page_count_;
// Render all pages.
+ pages_to_render_.reserve(total_page_count_);
for (int i = 0; i < total_page_count_; ++i)
pages_to_render_.push_back(i);
- } else if (generate_draft_pages_) {
- int pages_index = 0;
- for (int i = 0; i < total_page_count_; ++i) {
- if (pages_index < print_ready_metafile_page_count_ &&
- i == pages_to_render_[pages_index]) {
- pages_index++;
- continue;
- }
- pages_to_render_.push_back(i);
- }
}
+ print_ready_metafile_page_count_ = pages_to_render_.size();
document_render_time_ = base::TimeDelta();
begin_time_ = base::TimeTicks::Now();
@@ -2290,12 +2326,6 @@ bool PrintRenderFrameHelper::PrintPreviewContext::IsFinalPageRendered() const {
return static_cast<size_t>(current_page_index_) == pages_to_render_.size();
}
-void PrintRenderFrameHelper::PrintPreviewContext::set_generate_draft_pages(
- bool generate_draft_pages) {
- DCHECK_EQ(INITIALIZED, state_);
- generate_draft_pages_ = generate_draft_pages;
-}
-
void PrintRenderFrameHelper::PrintPreviewContext::set_error(
enum PrintPreviewErrorBuckets error) {
error_ = error;
@@ -2330,10 +2360,6 @@ int PrintRenderFrameHelper::PrintPreviewContext::total_page_count() const {
return total_page_count_;
}
-bool PrintRenderFrameHelper::PrintPreviewContext::generate_draft_pages() const {
- return generate_draft_pages_;
-}
-
PdfMetafileSkia* PrintRenderFrameHelper::PrintPreviewContext::metafile() {
DCHECK(IsRendering());
return metafile_.get();
@@ -2357,7 +2383,7 @@ void PrintRenderFrameHelper::PrintPreviewContext::CalculateIsModifiable() {
void PrintRenderFrameHelper::SetPrintPagesParams(
const PrintMsg_PrintPages_Params& settings) {
- print_pages_params_ = base::MakeUnique<PrintMsg_PrintPages_Params>(settings);
+ print_pages_params_ = std::make_unique<PrintMsg_PrintPages_Params>(settings);
Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(),
settings.params.document_cookie));
}
diff --git a/chromium/components/printing/renderer/print_render_frame_helper.h b/chromium/components/printing/renderer/print_render_frame_helper.h
index b087b9efe6c..64a6dd6a191 100644
--- a/chromium/components/printing/renderer/print_render_frame_helper.h
+++ b/chromium/components/printing/renderer/print_render_frame_helper.h
@@ -26,6 +26,8 @@
struct PrintMsg_Print_Params;
struct PrintMsg_PrintPages_Params;
+struct PrintMsg_PrintFrame_Params;
+struct PrintHostMsg_DidPrintContent_Params;
struct PrintHostMsg_SetOptionsFromDocument_Params;
// RenderViewTest-based tests crash on Android
@@ -99,10 +101,6 @@ class PrintRenderFrameHelper
virtual bool IsPrintPreviewEnabled() = 0;
- // If true, the user can be asked to provide print settings.
- // The default implementation returns |true|.
- virtual bool IsAskPrintSettingsEnabled();
-
// If false, window.print() won't do anything.
// The default implementation returns |true|.
virtual bool IsScriptedPrintEnabled();
@@ -153,15 +151,17 @@ class PrintRenderFrameHelper
#endif
};
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
enum PrintPreviewErrorBuckets {
- PREVIEW_ERROR_NONE, // Always first.
- PREVIEW_ERROR_BAD_SETTING,
- PREVIEW_ERROR_METAFILE_COPY_FAILED,
- PREVIEW_ERROR_METAFILE_INIT_FAILED_DEPRECATED,
- PREVIEW_ERROR_ZERO_PAGES,
- PREVIEW_ERROR_MAC_DRAFT_METAFILE_INIT_FAILED_DEPRECATED,
- PREVIEW_ERROR_PAGE_RENDERED_WITHOUT_METAFILE,
- PREVIEW_ERROR_INVALID_PRINTER_SETTINGS,
+ PREVIEW_ERROR_NONE = 0, // Always first.
+ PREVIEW_ERROR_BAD_SETTING = 1,
+ PREVIEW_ERROR_METAFILE_COPY_FAILED = 2,
+ PREVIEW_ERROR_METAFILE_INIT_FAILED_DEPRECATED = 3,
+ PREVIEW_ERROR_ZERO_PAGES = 4,
+ PREVIEW_ERROR_MAC_DRAFT_METAFILE_INIT_FAILED_DEPRECATED = 5,
+ PREVIEW_ERROR_PAGE_RENDERED_WITHOUT_METAFILE_DEPRECATED = 6,
+ PREVIEW_ERROR_INVALID_PRINTER_SETTINGS = 7,
PREVIEW_ERROR_LAST_ENUM // Always last.
};
@@ -191,6 +191,7 @@ class PrintRenderFrameHelper
void OnPrintPreview(const base::DictionaryValue& settings);
void OnClosePrintPreviewDialog();
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
+ void OnPrintFrameContent(const PrintMsg_PrintFrame_Params& params);
void OnPrintingDone(bool success);
// Get |page_size| and |content_area| information from
@@ -309,7 +310,7 @@ class PrintRenderFrameHelper
bool CopyMetafileDataToReadOnlySharedMem(
const PdfMetafileSkia& metafile,
- base::SharedMemoryHandle* read_only_shared_mem_handle);
+ PrintHostMsg_DidPrintContent_Params* params);
// Helper method to get page layout in points and fit to page if needed.
static void ComputePageLayoutInPointsForCss(
@@ -359,12 +360,13 @@ class PrintRenderFrameHelper
// Returns true if canceling, false if continuing.
bool CheckForCancel();
- // Notifies the browser a print preview page has been rendered.
+ // Notifies the browser a print preview page has been rendered for modifiable
+ // content.
// |page_number| is 0-based.
- // For a valid |page_number| with modifiable content,
- // |metafile| is the rendered page. Otherwise |metafile| is NULL.
+ // |metafile| is the rendered page and should be valid.
// Returns true if print preview should continue, false on failure.
- bool PreviewPageRendered(int page_number, PdfMetafileSkia* metafile);
+ bool PreviewPageRendered(int page_number,
+ std::unique_ptr<PdfMetafileSkia> metafile);
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
void SetPrintPagesParams(const PrintMsg_PrintPages_Params& settings);
@@ -407,7 +409,8 @@ class PrintRenderFrameHelper
bool CreatePreviewDocument(
std::unique_ptr<PrepareFrameAndViewForPrint> prepared_frame,
const std::vector<int>& pages,
- SkiaDocumentType doc_type);
+ SkiaDocumentType doc_type,
+ int document_cookie);
// Called after a page gets rendered. |page_time| is how long the
// rendering took.
@@ -434,7 +437,6 @@ class PrintRenderFrameHelper
bool IsFinalPageRendered() const;
// Setters
- void set_generate_draft_pages(bool generate_draft_pages);
void set_error(enum PrintPreviewErrorBuckets error);
// Getters
@@ -451,7 +453,6 @@ class PrintRenderFrameHelper
const blink::WebNode& prepared_node() const;
int total_page_count() const;
- bool generate_draft_pages() const;
PdfMetafileSkia* metafile();
int last_error() const;
@@ -484,9 +485,6 @@ class PrintRenderFrameHelper
// List of page indices that need to be rendered.
std::vector<int> pages_to_render_;
- // True, when draft pages needs to be generated.
- bool generate_draft_pages_;
-
// True, if the document source is modifiable. e.g. HTML and not PDF.
bool is_modifiable_;
diff --git a/chromium/components/printing/renderer/print_render_frame_helper_linux.cc b/chromium/components/printing/renderer/print_render_frame_helper_linux.cc
index 4d135484e7d..3b29a21be3e 100644
--- a/chromium/components/printing/renderer/print_render_frame_helper_linux.cc
+++ b/chromium/components/printing/renderer/print_render_frame_helper_linux.cc
@@ -53,7 +53,8 @@ bool PrintRenderFrameHelper::PrintPagesNative(blink::WebLocalFrame* frame,
if (printed_pages.empty())
return false;
- PdfMetafileSkia metafile(print_params.printed_doc_type);
+ PdfMetafileSkia metafile(print_params.printed_doc_type,
+ print_params.document_cookie);
CHECK(metafile.Init());
for (int page_number : printed_pages) {
@@ -82,12 +83,10 @@ bool PrintRenderFrameHelper::PrintPagesNative(blink::WebLocalFrame* frame,
return true;
#else
PrintHostMsg_DidPrintDocument_Params page_params;
- if (!CopyMetafileDataToReadOnlySharedMem(metafile,
- &page_params.metafile_data_handle)) {
+ if (!CopyMetafileDataToReadOnlySharedMem(metafile, &page_params.content)) {
return false;
}
- page_params.data_size = metafile.GetDataSize();
page_params.document_cookie = print_params.document_cookie;
Send(new PrintHostMsg_DidPrintDocument(routing_id(), page_params));
return true;
diff --git a/chromium/components/printing/renderer/print_render_frame_helper_mac.mm b/chromium/components/printing/renderer/print_render_frame_helper_mac.mm
index 8cc4806de50..cf77c682805 100644
--- a/chromium/components/printing/renderer/print_render_frame_helper_mac.mm
+++ b/chromium/components/printing/renderer/print_render_frame_helper_mac.mm
@@ -6,6 +6,8 @@
#import <AppKit/AppKit.h>
+#include <memory>
+
#include "base/logging.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/metrics/histogram.h"
@@ -18,46 +20,6 @@
namespace printing {
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
-bool PrintRenderFrameHelper::RenderPreviewPage(
- int page_number,
- const PrintMsg_Print_Params& print_params) {
- std::unique_ptr<PdfMetafileSkia> draft_metafile;
- PdfMetafileSkia* initial_render_metafile = print_preview_context_.metafile();
-
- bool render_to_draft =
- print_preview_context_.IsModifiable() && is_print_ready_metafile_sent_;
-
- if (render_to_draft) {
- draft_metafile =
- base::MakeUnique<PdfMetafileSkia>(print_params.printed_doc_type);
- CHECK(draft_metafile->Init());
- initial_render_metafile = draft_metafile.get();
- }
-
- base::TimeTicks begin_time = base::TimeTicks::Now();
- PrintPageInternal(print_params, page_number,
- print_preview_context_.total_page_count(),
- print_preview_context_.prepared_frame(),
- initial_render_metafile, nullptr, nullptr);
- print_preview_context_.RenderedPreviewPage(base::TimeTicks::Now() -
- begin_time);
-
- if (draft_metafile.get()) {
- draft_metafile->FinishDocument();
- } else {
- if (print_preview_context_.IsModifiable() &&
- print_preview_context_.generate_draft_pages()) {
- DCHECK(!draft_metafile.get());
- draft_metafile =
- print_preview_context_.metafile()->GetMetafileForCurrentPage(
- print_params.printed_doc_type);
- }
- }
- return PreviewPageRendered(page_number, draft_metafile.get());
-}
-#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
-
void PrintRenderFrameHelper::PrintPageInternal(
const PrintMsg_Print_Params& params,
int page_number,
diff --git a/chromium/components/printing/service/BUILD.gn b/chromium/components/printing/service/BUILD.gn
index e18edb15e0f..cca6033a49c 100644
--- a/chromium/components/printing/service/BUILD.gn
+++ b/chromium/components/printing/service/BUILD.gn
@@ -42,6 +42,7 @@ if (enable_basic_printing || enable_print_preview) {
source_set("unit_tests") {
testonly = true
sources = [
+ "pdf_compositor_impl_unittest.cc",
"pdf_compositor_service_unittest.cc",
]
@@ -57,6 +58,7 @@ if (enable_basic_printing || enable_print_preview) {
"//components/printing/service/public/interfaces",
"//mojo/common",
"//services/service_manager/public/cpp:service_test_support",
+ "//skia",
"//testing/gmock",
"//testing/gtest",
]
diff --git a/chromium/components/printing/service/DEPS b/chromium/components/printing/service/DEPS
index b5766208f27..e3fedafc0c3 100644
--- a/chromium/components/printing/service/DEPS
+++ b/chromium/components/printing/service/DEPS
@@ -6,7 +6,7 @@ include_rules = [
"+mojo/public/cpp",
"+printing/common",
"+services/service_manager/public/cpp",
- "+services/service_manager/public/interfaces",
+ "+services/service_manager/public/mojom",
"+skia",
"+third_party/skia",
]
diff --git a/chromium/components/printing/service/pdf_compositor_impl.cc b/chromium/components/printing/service/pdf_compositor_impl.cc
index 212514a8ee4..eb3799b5201 100644
--- a/chromium/components/printing/service/pdf_compositor_impl.cc
+++ b/chromium/components/printing/service/pdf_compositor_impl.cc
@@ -4,17 +4,18 @@
#include "components/printing/service/pdf_compositor_impl.h"
-#include <utility>
-#include <vector>
+#include <tuple>
#include "base/logging.h"
-#include "base/memory/shared_memory.h"
#include "base/memory/shared_memory_handle.h"
+#include "base/stl_util.h"
+#include "components/printing/service/public/cpp/pdf_service_mojo_types.h"
#include "components/printing/service/public/cpp/pdf_service_mojo_utils.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "printing/common/pdf_metafile_utils.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkDocument.h"
+#include "third_party/skia/include/core/SkSerialProcs.h"
#include "third_party/skia/src/utils/SkMultiPictureDocument.h"
namespace printing {
@@ -26,29 +27,185 @@ PdfCompositorImpl::PdfCompositorImpl(
PdfCompositorImpl::~PdfCompositorImpl() = default;
-void PdfCompositorImpl::CompositePdf(
- mojo::ScopedSharedBufferHandle sk_handle,
- mojom::PdfCompositor::CompositePdfCallback callback) {
- DCHECK(sk_handle.is_valid());
+void PdfCompositorImpl::NotifyUnavailableSubframe(uint64_t frame_guid) {
+ // Add this frame into the map.
+ DCHECK(!base::ContainsKey(frame_info_map_, frame_guid));
+ auto& frame_info =
+ frame_info_map_.emplace(frame_guid, std::make_unique<FrameInfo>())
+ .first->second;
+ frame_info->composited = true;
+ // Set content to be nullptr so it will be replaced by an empty picture during
+ // deserialization of its parent.
+ frame_info->content = nullptr;
- std::unique_ptr<base::SharedMemory> shm =
- GetShmFromMojoHandle(std::move(sk_handle));
+ // Update the requests in case any of them might be waiting for this frame.
+ UpdateRequestsWithSubframeInfo(frame_guid, std::vector<uint64_t>());
+}
+
+void PdfCompositorImpl::AddSubframeContent(
+ uint64_t frame_guid,
+ mojo::ScopedSharedBufferHandle serialized_content,
+ const ContentToFrameMap& subframe_content_map) {
+ // Add this frame and its serialized content.
+ DCHECK(!base::ContainsKey(frame_info_map_, frame_guid));
+ auto& frame_info =
+ frame_info_map_.emplace(frame_guid, std::make_unique<FrameInfo>())
+ .first->second;
+ frame_info->serialized_content =
+ GetShmFromMojoHandle(std::move(serialized_content));
+
+ // Copy the subframe content information.
+ frame_info->subframe_content_map = subframe_content_map;
+
+ // If there is no request, we do nothing more.
+ // Otherwise, we need to check whether any request actually waits on this
+ // frame content.
+ if (requests_.empty())
+ return;
+
+ // Get the pending list which is a list of subframes this frame needs
+ // but are still unavailable.
+ std::vector<uint64_t> pending_subframes;
+ for (auto& subframe_content : subframe_content_map) {
+ auto subframe_guid = subframe_content.second;
+ if (!base::ContainsKey(frame_info_map_, subframe_guid))
+ pending_subframes.push_back(subframe_guid);
+ }
+
+ // Update the requests in case any of them is waiting for this frame.
+ UpdateRequestsWithSubframeInfo(frame_guid, pending_subframes);
+}
+
+void PdfCompositorImpl::CompositePageToPdf(
+ uint64_t frame_guid,
+ uint32_t page_num,
+ mojo::ScopedSharedBufferHandle serialized_content,
+ const ContentToFrameMap& subframe_content_map,
+ mojom::PdfCompositor::CompositePageToPdfCallback callback) {
+ HandleCompositionRequest(frame_guid, page_num, std::move(serialized_content),
+ subframe_content_map, std::move(callback));
+}
+
+void PdfCompositorImpl::CompositeDocumentToPdf(
+ uint64_t frame_guid,
+ mojo::ScopedSharedBufferHandle serialized_content,
+ const ContentToFrameMap& subframe_content_map,
+ mojom::PdfCompositor::CompositeDocumentToPdfCallback callback) {
+ HandleCompositionRequest(frame_guid, base::nullopt,
+ std::move(serialized_content), subframe_content_map,
+ std::move(callback));
+}
+
+void PdfCompositorImpl::UpdateRequestsWithSubframeInfo(
+ uint64_t frame_guid,
+ const std::vector<uint64_t>& pending_subframes) {
+ // Check for each request's pending list.
+ for (auto it = requests_.begin(); it != requests_.end();) {
+ auto& request = *it;
+ // If the request needs this frame, we can remove the dependency, but
+ // update with this frame's pending list.
+ auto& pending_list = request->pending_subframes;
+ if (pending_list.erase(frame_guid)) {
+ std::copy(pending_subframes.begin(), pending_subframes.end(),
+ std::inserter(pending_list, pending_list.end()));
+ if (pending_list.empty()) {
+ // If the request isn't waiting on any subframes then it is ready.
+ // Fulfill the request now.
+ FulfillRequest(request->frame_guid, request->page_number,
+ std::move(request->serialized_content),
+ request->subframe_content_map,
+ std::move(request->callback));
+ it = requests_.erase(it);
+ continue;
+ }
+ }
+ // If the request still has pending frames, keep waiting.
+ ++it;
+ }
+}
+
+bool PdfCompositorImpl::IsReadyToComposite(
+ uint64_t frame_guid,
+ const ContentToFrameMap& subframe_content_map,
+ base::flat_set<uint64_t>* pending_subframes) {
+ pending_subframes->clear();
+ base::flat_set<uint64_t> visited_frames;
+ visited_frames.insert(frame_guid);
+ CheckFramesForReadiness(frame_guid, subframe_content_map, pending_subframes,
+ &visited_frames);
+ return pending_subframes->empty();
+}
+
+void PdfCompositorImpl::CheckFramesForReadiness(
+ uint64_t frame_guid,
+ const ContentToFrameMap& subframe_content_map,
+ base::flat_set<uint64_t>* pending_subframes,
+ base::flat_set<uint64_t>* visited) {
+ for (auto& subframe_content : subframe_content_map) {
+ auto subframe_guid = subframe_content.second;
+ // If this frame has been checked, skip it.
+ auto result = visited->insert(subframe_guid);
+ if (!result.second)
+ continue;
+
+ auto iter = frame_info_map_.find(subframe_guid);
+ if (iter == frame_info_map_.end()) {
+ pending_subframes->insert(subframe_guid);
+ } else {
+ CheckFramesForReadiness(subframe_guid, iter->second->subframe_content_map,
+ pending_subframes, visited);
+ }
+ }
+}
+
+void PdfCompositorImpl::HandleCompositionRequest(
+ uint64_t frame_guid,
+ base::Optional<uint32_t> page_num,
+ mojo::ScopedSharedBufferHandle serialized_content,
+ const ContentToFrameMap& subframe_content_map,
+ CompositeToPdfCallback callback) {
+ base::flat_set<uint64_t> pending_subframes;
+ if (IsReadyToComposite(frame_guid, subframe_content_map,
+ &pending_subframes)) {
+ FulfillRequest(frame_guid, page_num,
+ GetShmFromMojoHandle(std::move(serialized_content)),
+ subframe_content_map, std::move(callback));
+ return;
+ }
- SkMemoryStream stream(shm->memory(), shm->mapped_size());
+ // When it is not ready yet, keep its information and
+ // wait until all dependent subframes are ready.
+ auto iter = frame_info_map_.find(frame_guid);
+ if (iter == frame_info_map_.end())
+ frame_info_map_[frame_guid] = std::make_unique<FrameInfo>();
+
+ requests_.push_back(std::make_unique<RequestInfo>(
+ frame_guid, page_num, GetShmFromMojoHandle(std::move(serialized_content)),
+ subframe_content_map, std::move(pending_subframes), std::move(callback)));
+}
+
+mojom::PdfCompositor::Status PdfCompositorImpl::CompositeToPdf(
+ uint64_t frame_guid,
+ base::Optional<uint32_t> page_num,
+ std::unique_ptr<base::SharedMemory> shared_mem,
+ const ContentToFrameMap& subframe_content_map,
+ mojo::ScopedSharedBufferHandle* handle) {
+ DeserializationContext subframes =
+ GetDeserializationContext(subframe_content_map);
+
+ // Read in content and convert it into pdf.
+ SkMemoryStream stream(shared_mem->memory(), shared_mem->mapped_size());
int page_count = SkMultiPictureDocumentReadPageCount(&stream);
if (!page_count) {
- DLOG(ERROR) << "CompositePdf: No page is read.";
- std::move(callback).Run(mojom::PdfCompositor::Status::CONTENT_FORMAT_ERROR,
- mojo::ScopedSharedBufferHandle());
- return;
+ DLOG(ERROR) << "CompositeToPdf: No page is read.";
+ return mojom::PdfCompositor::Status::CONTENT_FORMAT_ERROR;
}
std::vector<SkDocumentPage> pages(page_count);
- if (!SkMultiPictureDocumentRead(&stream, pages.data(), page_count)) {
- DLOG(ERROR) << "CompositePdf: Page reading failed.";
- std::move(callback).Run(mojom::PdfCompositor::Status::CONTENT_FORMAT_ERROR,
- mojo::ScopedSharedBufferHandle());
- return;
+ SkDeserialProcs procs = DeserializationProcs(&subframes);
+ if (!SkMultiPictureDocumentRead(&stream, pages.data(), page_count, &procs)) {
+ DLOG(ERROR) << "CompositeToPdf: Page reading failed.";
+ return mojom::PdfCompositor::Status::CONTENT_FORMAT_ERROR;
}
SkDynamicMemoryWStream wstream;
@@ -61,16 +218,95 @@ void PdfCompositorImpl::CompositePdf(
}
doc->close();
- mojo::ScopedSharedBufferHandle buffer =
- mojo::SharedBufferHandle::Create(wstream.bytesWritten());
- DCHECK(buffer.is_valid());
+ *handle = mojo::SharedBufferHandle::Create(wstream.bytesWritten());
+ DCHECK((*handle).is_valid());
- mojo::ScopedSharedBufferMapping mapping = buffer->Map(wstream.bytesWritten());
+ mojo::ScopedSharedBufferMapping mapping =
+ (*handle)->Map(wstream.bytesWritten());
DCHECK(mapping);
wstream.copyToAndReset(mapping.get());
- std::move(callback).Run(mojom::PdfCompositor::Status::SUCCESS,
- std::move(buffer));
+ return mojom::PdfCompositor::Status::SUCCESS;
+}
+
+sk_sp<SkPicture> PdfCompositorImpl::CompositeSubframe(uint64_t frame_guid) {
+ // The content of this frame should be available.
+ auto iter = frame_info_map_.find(frame_guid);
+ DCHECK(iter != frame_info_map_.end());
+
+ std::unique_ptr<FrameInfo>& frame_info = iter->second;
+ frame_info->composited = true;
+
+ // Composite subframes first.
+ DeserializationContext subframes =
+ GetDeserializationContext(frame_info->subframe_content_map);
+
+ // Composite the entire frame.
+ SkMemoryStream stream(iter->second->serialized_content->memory(),
+ iter->second->serialized_content->mapped_size());
+ SkDeserialProcs procs = DeserializationProcs(&subframes);
+ iter->second->content = SkPicture::MakeFromStream(&stream, &procs);
+ return iter->second->content;
+}
+
+PdfCompositorImpl::DeserializationContext
+PdfCompositorImpl::GetDeserializationContext(
+ const ContentToFrameMap& subframe_content_map) {
+ DeserializationContext subframes;
+ for (auto& content_info : subframe_content_map) {
+ uint32_t content_id = content_info.first;
+ uint64_t frame_guid = content_info.second;
+ auto frame_iter = frame_info_map_.find(frame_guid);
+ if (frame_iter == frame_info_map_.end())
+ continue;
+
+ if (frame_iter->second->composited)
+ subframes[content_id] = frame_iter->second->content;
+ else
+ subframes[content_id] = CompositeSubframe(frame_iter->first);
+ }
+ return subframes;
+}
+
+void PdfCompositorImpl::FulfillRequest(
+ uint64_t frame_guid,
+ base::Optional<uint32_t> page_num,
+ std::unique_ptr<base::SharedMemory> serialized_content,
+ const ContentToFrameMap& subframe_content_map,
+ CompositeToPdfCallback callback) {
+ mojo::ScopedSharedBufferHandle handle;
+ auto status =
+ CompositeToPdf(frame_guid, page_num, std::move(serialized_content),
+ subframe_content_map, &handle);
+ std::move(callback).Run(status, std::move(handle));
}
+PdfCompositorImpl::FrameContentInfo::FrameContentInfo(
+ std::unique_ptr<base::SharedMemory> content,
+ const ContentToFrameMap& map)
+ : serialized_content(std::move(content)), subframe_content_map(map) {}
+
+PdfCompositorImpl::FrameContentInfo::FrameContentInfo() {}
+
+PdfCompositorImpl::FrameContentInfo::~FrameContentInfo() {}
+
+PdfCompositorImpl::FrameInfo::FrameInfo() {}
+
+PdfCompositorImpl::FrameInfo::~FrameInfo() {}
+
+PdfCompositorImpl::RequestInfo::RequestInfo(
+ uint64_t frame_guid,
+ base::Optional<uint32_t> page_num,
+ std::unique_ptr<base::SharedMemory> content,
+ const ContentToFrameMap& content_info,
+ const base::flat_set<uint64_t>& pending_subframes,
+ mojom::PdfCompositor::CompositePageToPdfCallback callback)
+ : FrameContentInfo(std::move(content), content_info),
+ frame_guid(frame_guid),
+ page_number(page_num),
+ pending_subframes(pending_subframes),
+ callback(std::move(callback)) {}
+
+PdfCompositorImpl::RequestInfo::~RequestInfo() {}
+
} // namespace printing
diff --git a/chromium/components/printing/service/pdf_compositor_impl.h b/chromium/components/printing/service/pdf_compositor_impl.h
index b7890fa10ee..809055e42ea 100644
--- a/chromium/components/printing/service/pdf_compositor_impl.h
+++ b/chromium/components/printing/service/pdf_compositor_impl.h
@@ -5,13 +5,23 @@
#ifndef COMPONENTS_PRINTING_SERVICE_PDF_COMPOSITOR_IMPL_H_
#define COMPONENTS_PRINTING_SERVICE_PDF_COMPOSITOR_IMPL_H_
+#include <map>
#include <memory>
#include <string>
+#include <vector>
+#include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
#include "base/macros.h"
+#include "base/memory/ref_counted_memory.h"
+#include "base/memory/shared_memory.h"
+#include "base/optional.h"
+#include "components/printing/service/public/cpp/pdf_service_mojo_types.h"
#include "components/printing/service/public/interfaces/pdf_compositor.mojom.h"
#include "mojo/public/cpp/system/buffer.h"
#include "services/service_manager/public/cpp/service_context_ref.h"
+#include "third_party/skia/include/core/SkPicture.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
namespace printing {
@@ -22,14 +32,156 @@ class PdfCompositorImpl : public mojom::PdfCompositor {
std::unique_ptr<service_manager::ServiceContextRef> service_ref);
~PdfCompositorImpl() override;
- void CompositePdf(
- mojo::ScopedSharedBufferHandle sk_handle,
- mojom::PdfCompositor::CompositePdfCallback callback) override;
+ // mojom::PdfCompositor
+ void NotifyUnavailableSubframe(uint64_t frame_guid) override;
+ void AddSubframeContent(
+ uint64_t frame_guid,
+ mojo::ScopedSharedBufferHandle serialized_content,
+ const ContentToFrameMap& subframe_content_map) override;
+ void CompositePageToPdf(
+ uint64_t frame_guid,
+ uint32_t page_num,
+ mojo::ScopedSharedBufferHandle serialized_content,
+ const ContentToFrameMap& subframe_content_map,
+ mojom::PdfCompositor::CompositePageToPdfCallback callback) override;
+ void CompositeDocumentToPdf(
+ uint64_t frame_guid,
+ mojo::ScopedSharedBufferHandle serialized_content,
+ const ContentToFrameMap& subframe_content_map,
+ mojom::PdfCompositor::CompositeDocumentToPdfCallback callback) override;
+
+ protected:
+ // This is the uniform underlying type for both
+ // mojom::PdfCompositor::CompositePageToPdfCallback and
+ // mojom::PdfCompositor::CompositeDocumentToPdfCallback.
+ using CompositeToPdfCallback =
+ base::OnceCallback<void(PdfCompositor::Status,
+ mojo::ScopedSharedBufferHandle)>;
+
+ // Make this function virtual so tests can override it.
+ virtual void FulfillRequest(
+ uint64_t frame_guid,
+ base::Optional<uint32_t> page_num,
+ std::unique_ptr<base::SharedMemory> serialized_content,
+ const ContentToFrameMap& subframe_content_map,
+ CompositeToPdfCallback callback);
private:
+ FRIEND_TEST_ALL_PREFIXES(PdfCompositorImplTest, IsReadyToComposite);
+ FRIEND_TEST_ALL_PREFIXES(PdfCompositorImplTest, MultiLayerDependency);
+ FRIEND_TEST_ALL_PREFIXES(PdfCompositorImplTest, DependencyLoop);
+
+ // The map needed during content deserialization. It stores the mapping
+ // between content id and its actual content.
+ using DeserializationContext = base::flat_map<uint32_t, sk_sp<SkPicture>>;
+
+ // Base structure to store a frame's content and its subframe
+ // content information.
+ struct FrameContentInfo {
+ FrameContentInfo(std::unique_ptr<base::SharedMemory> content,
+ const ContentToFrameMap& map);
+ FrameContentInfo();
+ ~FrameContentInfo();
+
+ // Serialized SkPicture content of this frame.
+ std::unique_ptr<base::SharedMemory> serialized_content;
+
+ // Frame content after composition with subframe content.
+ sk_sp<SkPicture> content;
+
+ // Subframe content id and its corresponding frame guid.
+ ContentToFrameMap subframe_content_map;
+ };
+
+ // Other than content, it also stores the status during frame composition.
+ struct FrameInfo : public FrameContentInfo {
+ FrameInfo();
+ ~FrameInfo();
+
+ // The following fields are used for storing composition status.
+ // Set to true when this frame's |serialized_content| is composed with
+ // subframe content and the final result is stored in |content|.
+ bool composited = false;
+ };
+
+ // Stores the mapping between frame's global unique ids and their
+ // corresponding frame information.
+ using FrameMap = base::flat_map<uint64_t, std::unique_ptr<FrameInfo>>;
+
+ // Stores the page or document's request information.
+ struct RequestInfo : public FrameContentInfo {
+ RequestInfo(uint64_t frame_guid,
+ base::Optional<uint32_t> page_num,
+ std::unique_ptr<base::SharedMemory> content,
+ const ContentToFrameMap& content_info,
+ const base::flat_set<uint64_t>& pending_subframes,
+ CompositeToPdfCallback callback);
+ ~RequestInfo();
+
+ uint64_t frame_guid;
+ base::Optional<uint32_t> page_number;
+
+ // All pending frame ids whose content is not available but needed
+ // for composition.
+ base::flat_set<uint64_t> pending_subframes;
+
+ CompositeToPdfCallback callback;
+ };
+
+ // Check whether any request is waiting for the specific subframe, if so,
+ // update its dependecy with the subframe's pending child frames.
+ void UpdateRequestsWithSubframeInfo(
+ uint64_t frame_guid,
+ const std::vector<uint64_t>& pending_subframes);
+
+ // Check whether the frame with a list of subframe content is ready to
+ // composite. If not, return all unavailable frames' ids in
+ // |pending_subframes|.
+ bool IsReadyToComposite(uint64_t frame_guid,
+ const ContentToFrameMap& subframe_content_map,
+ base::flat_set<uint64_t>* pending_subframes);
+
+ // Recursive check all the frames |frame_guid| depends on and put those
+ // not ready in |pending_subframes|.
+ void CheckFramesForReadiness(uint64_t frame_guid,
+ const ContentToFrameMap& subframe_content_map,
+ base::flat_set<uint64_t>* pending_subframes,
+ base::flat_set<uint64_t>* visited);
+
+ // The internal implementation for handling page and documentation composition
+ // requests.
+ void HandleCompositionRequest(
+ uint64_t frame_guid,
+ base::Optional<uint32_t> page_num,
+ mojo::ScopedSharedBufferHandle serialized_content,
+ const ContentToFrameMap& subframe_content_ids,
+ CompositeToPdfCallback callback);
+
+ // The core function for content composition and conversion to a pdf file.
+ mojom::PdfCompositor::Status CompositeToPdf(
+ uint64_t frame_guid,
+ base::Optional<uint32_t> page_num,
+ std::unique_ptr<base::SharedMemory> shared_mem,
+ const ContentToFrameMap& subframe_content_map,
+ mojo::ScopedSharedBufferHandle* handle);
+
+ // Composite the content of a subframe.
+ sk_sp<SkPicture> CompositeSubframe(uint64_t frame_guid);
+
+ bool CheckForPendingFrame(uint64_t frame_guid,
+ base::flat_set<uint64_t> visited_frames);
+
+ DeserializationContext GetDeserializationContext(
+ const ContentToFrameMap& subframe_content_map);
+
const std::unique_ptr<service_manager::ServiceContextRef> service_ref_;
const std::string creator_;
+ // Keep track of all frames' information indexed by frame id.
+ FrameMap frame_info_map_;
+
+ std::vector<std::unique_ptr<RequestInfo>> requests_;
+
DISALLOW_COPY_AND_ASSIGN(PdfCompositorImpl);
};
diff --git a/chromium/components/printing/service/pdf_compositor_impl_unittest.cc b/chromium/components/printing/service/pdf_compositor_impl_unittest.cc
new file mode 100644
index 00000000000..cae20e77fe0
--- /dev/null
+++ b/chromium/components/printing/service/pdf_compositor_impl_unittest.cc
@@ -0,0 +1,348 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/printing/service/pdf_compositor_impl.h"
+#include "components/printing/service/public/cpp/pdf_service_mojo_types.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace printing {
+
+class MockPdfCompositorImpl : public PdfCompositorImpl {
+ public:
+ MockPdfCompositorImpl() : PdfCompositorImpl("unittest", nullptr) {}
+ ~MockPdfCompositorImpl() override {}
+
+ MOCK_METHOD2(OnFulfillRequest, void(uint64_t, int));
+
+ protected:
+ void FulfillRequest(uint64_t frame_guid,
+ base::Optional<uint32_t> page_num,
+ std::unique_ptr<base::SharedMemory> serialized_content,
+ const ContentToFrameMap& subframe_content_map,
+ CompositeToPdfCallback callback) override {
+ OnFulfillRequest(frame_guid, page_num.has_value() ? page_num.value() : -1);
+ }
+};
+
+class PdfCompositorImplTest : public testing::Test {
+ public:
+ PdfCompositorImplTest()
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::IO),
+ run_loop_(std::make_unique<base::RunLoop>()),
+ is_ready_(false) {}
+
+ void OnIsReadyToCompositeCallback(bool is_ready) {
+ is_ready_ = is_ready;
+ run_loop_->Quit();
+ }
+
+ bool ResultFromCallback() {
+ run_loop_->Run();
+ run_loop_ = std::make_unique<base::RunLoop>();
+ return is_ready_;
+ }
+
+ void OnCompositeToPdfCallback(mojom::PdfCompositor::Status status,
+ mojo::ScopedSharedBufferHandle handle) {
+ // A stub for testing, no implementation.
+ }
+
+ protected:
+ base::test::ScopedTaskEnvironment task_environment_;
+ std::unique_ptr<base::RunLoop> run_loop_;
+ bool is_ready_;
+};
+
+TEST_F(PdfCompositorImplTest, IsReadyToComposite) {
+ PdfCompositorImpl impl("unittest", nullptr);
+ // Frame 2 and 3 are painted.
+ impl.AddSubframeContent(2u, mojo::SharedBufferHandle::Create(10),
+ ContentToFrameMap());
+ impl.AddSubframeContent(3u, mojo::SharedBufferHandle::Create(10),
+ ContentToFrameMap());
+
+ // Frame 1 contains content 3 which corresponds to frame 2.
+ // Frame 1 should be ready as frame 2 is ready.
+ ContentToFrameMap subframe_content_map;
+ subframe_content_map[3u] = 2u;
+ base::flat_set<uint64_t> pending_subframes;
+ bool is_ready = impl.IsReadyToComposite(1u, std::move(subframe_content_map),
+ &pending_subframes);
+ EXPECT_TRUE(is_ready);
+ EXPECT_TRUE(pending_subframes.empty());
+
+ // If another page of frame 1 needs content 2 which corresponds to frame 3.
+ // This page is ready since frame 3 was painted also.
+ subframe_content_map.clear();
+ subframe_content_map[2u] = 3u;
+ is_ready = impl.IsReadyToComposite(1u, std::move(subframe_content_map),
+ &pending_subframes);
+ EXPECT_TRUE(is_ready);
+ EXPECT_TRUE(pending_subframes.empty());
+
+ // Frame 1 with content 1, 2 and 3 should not be ready since content 1's
+ // content in frame 4 is not painted yet.
+ subframe_content_map.clear();
+ subframe_content_map[1u] = 4u;
+ subframe_content_map[2u] = 3u;
+ subframe_content_map[3u] = 2u;
+ is_ready = impl.IsReadyToComposite(1u, std::move(subframe_content_map),
+ &pending_subframes);
+ EXPECT_FALSE(is_ready);
+ ASSERT_EQ(pending_subframes.size(), 1u);
+ EXPECT_EQ(*pending_subframes.begin(), 4u);
+
+ // Add content of frame 4. Now it is ready for composition.
+ subframe_content_map.clear();
+ subframe_content_map[1u] = 4u;
+ subframe_content_map[2u] = 3u;
+ subframe_content_map[3u] = 2u;
+ impl.AddSubframeContent(4u, mojo::SharedBufferHandle::Create(10),
+ ContentToFrameMap());
+ is_ready = impl.IsReadyToComposite(1u, std::move(subframe_content_map),
+ &pending_subframes);
+ EXPECT_TRUE(is_ready);
+ EXPECT_TRUE(pending_subframes.empty());
+}
+
+TEST_F(PdfCompositorImplTest, MultiLayerDependency) {
+ PdfCompositorImpl impl("unittest", nullptr);
+ // Frame 3 has content 1 which refers to subframe 1.
+ ContentToFrameMap subframe_content_map;
+ subframe_content_map[1u] = 1u;
+ impl.AddSubframeContent(3u, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map));
+
+ // Frame 5 has content 3 which refers to subframe 3.
+ // Although frame 3's content is added, its subframe 1's content is not added.
+ // So frame 5 is not ready.
+ subframe_content_map.clear();
+ subframe_content_map[3u] = 3u;
+ base::flat_set<uint64_t> pending_subframes;
+ bool is_ready = impl.IsReadyToComposite(5u, std::move(subframe_content_map),
+ &pending_subframes);
+ EXPECT_FALSE(is_ready);
+ ASSERT_EQ(pending_subframes.size(), 1u);
+ EXPECT_EQ(*pending_subframes.begin(), 1u);
+
+ // Frame 6 is not ready either since it needs frame 5 to be ready.
+ subframe_content_map.clear();
+ subframe_content_map[1u] = 5u;
+ is_ready = impl.IsReadyToComposite(6u, std::move(subframe_content_map),
+ &pending_subframes);
+ EXPECT_FALSE(is_ready);
+ ASSERT_EQ(pending_subframes.size(), 1u);
+ EXPECT_EQ(*pending_subframes.begin(), 5u);
+
+ // When frame 1's content is added, frame 5 is ready.
+ impl.AddSubframeContent(1u, mojo::SharedBufferHandle::Create(10),
+ ContentToFrameMap());
+ subframe_content_map.clear();
+ subframe_content_map[3u] = 3u;
+ is_ready = impl.IsReadyToComposite(5u, std::move(subframe_content_map),
+ &pending_subframes);
+ EXPECT_TRUE(is_ready);
+ EXPECT_TRUE(pending_subframes.empty());
+
+ // Add frame 5's content.
+ subframe_content_map.clear();
+ subframe_content_map[3u] = 3u;
+ impl.AddSubframeContent(5u, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map));
+
+ // Frame 6 is ready too.
+ subframe_content_map.clear();
+ subframe_content_map[1u] = 5u;
+ is_ready = impl.IsReadyToComposite(6u, std::move(subframe_content_map),
+ &pending_subframes);
+ EXPECT_TRUE(is_ready);
+ EXPECT_TRUE(pending_subframes.empty());
+}
+
+TEST_F(PdfCompositorImplTest, DependencyLoop) {
+ PdfCompositorImpl impl("unittest", nullptr);
+ // Frame 3 has content 1, which refers to frame 1.
+ // Frame 1 has content 3, which refers to frame 3.
+ ContentToFrameMap subframe_content_map;
+ subframe_content_map[3u] = 3u;
+ impl.AddSubframeContent(1u, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map));
+
+ subframe_content_map.clear();
+ subframe_content_map[1u] = 1u;
+ impl.AddSubframeContent(3u, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map));
+
+ // Both frame 1 and 3 are painted, frame 5 should be ready.
+ base::flat_set<uint64_t> pending_subframes;
+ subframe_content_map.clear();
+ subframe_content_map[1u] = 3u;
+ bool is_ready = impl.IsReadyToComposite(5u, std::move(subframe_content_map),
+ &pending_subframes);
+ EXPECT_TRUE(is_ready);
+ EXPECT_TRUE(pending_subframes.empty());
+
+ // Frame 6 has content 7, which refers to frame 7.
+ subframe_content_map.clear();
+ subframe_content_map[7u] = 7u;
+ impl.AddSubframeContent(6, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map));
+ // Frame 7 should be ready since frame 6's own content is added and it only
+ // depends on frame 7.
+ subframe_content_map.clear();
+ subframe_content_map[6u] = 6u;
+ is_ready = impl.IsReadyToComposite(7u, std::move(subframe_content_map),
+ &pending_subframes);
+ EXPECT_TRUE(is_ready);
+ EXPECT_TRUE(pending_subframes.empty());
+}
+
+TEST_F(PdfCompositorImplTest, MultiRequestsBasic) {
+ MockPdfCompositorImpl impl;
+ // Page 0 with frame 3 has content 1, which refers to frame 8.
+ // When the content is not available, the request is not fulfilled.
+ ContentToFrameMap subframe_content_map;
+ subframe_content_map[1u] = 8u;
+ EXPECT_CALL(impl, OnFulfillRequest(testing::_, testing::_)).Times(0);
+ impl.CompositePageToPdf(
+ 3u, 0, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map),
+ base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback,
+ base::Unretained(this)));
+ testing::Mock::VerifyAndClearExpectations(&impl);
+
+ // When frame 8's content is ready, the previous request should be fulfilled.
+ EXPECT_CALL(impl, OnFulfillRequest(3u, 0)).Times(1);
+ impl.AddSubframeContent(8u, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map));
+ testing::Mock::VerifyAndClearExpectations(&impl);
+
+ // The following requests which only depends on frame 8 should be
+ // immediately fulfilled.
+ EXPECT_CALL(impl, OnFulfillRequest(3u, 1)).Times(1);
+ EXPECT_CALL(impl, OnFulfillRequest(3u, -1)).Times(1);
+ subframe_content_map.clear();
+ subframe_content_map[1u] = 8u;
+ impl.CompositePageToPdf(
+ 3u, 1, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map),
+ base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback,
+ base::Unretained(this)));
+
+ subframe_content_map.clear();
+ subframe_content_map[1u] = 8u;
+ impl.CompositeDocumentToPdf(
+ 3u, mojo::SharedBufferHandle::Create(10), std::move(subframe_content_map),
+ base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback,
+ base::Unretained(this)));
+}
+
+TEST_F(PdfCompositorImplTest, MultiRequestsOrder) {
+ MockPdfCompositorImpl impl;
+ // Page 0 with frame 3 has content 1, which refers to frame 8.
+ // When the content is not available, the request is not fulfilled.
+ ContentToFrameMap subframe_content_map;
+ subframe_content_map[1u] = 8u;
+ EXPECT_CALL(impl, OnFulfillRequest(testing::_, testing::_)).Times(0);
+ impl.CompositePageToPdf(
+ 3u, 0, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map),
+ base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback,
+ base::Unretained(this)));
+
+ // The following requests which only depends on frame 8 should be
+ // immediately fulfilled.
+ subframe_content_map.clear();
+ subframe_content_map[1u] = 8u;
+ impl.CompositePageToPdf(
+ 3u, 1, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map),
+ base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback,
+ base::Unretained(this)));
+
+ subframe_content_map.clear();
+ subframe_content_map[1u] = 8u;
+ impl.CompositeDocumentToPdf(
+ 3u, mojo::SharedBufferHandle::Create(10), std::move(subframe_content_map),
+ base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback,
+ base::Unretained(this)));
+ testing::Mock::VerifyAndClearExpectations(&impl);
+
+ // When frame 8's content is ready, the previous request should be
+ // fulfilled.
+ EXPECT_CALL(impl, OnFulfillRequest(3u, 0)).Times(1);
+ EXPECT_CALL(impl, OnFulfillRequest(3u, 1)).Times(1);
+ EXPECT_CALL(impl, OnFulfillRequest(3u, -1)).Times(1);
+ subframe_content_map.clear();
+ impl.AddSubframeContent(8u, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map));
+}
+
+TEST_F(PdfCompositorImplTest, MultiRequestsDepOrder) {
+ MockPdfCompositorImpl impl;
+ // Page 0 with frame 1 has content 1, which refers to frame
+ // 2. When the content is not available, the request is not
+ // fulfilled.
+ EXPECT_CALL(impl, OnFulfillRequest(testing::_, testing::_)).Times(0);
+ ContentToFrameMap subframe_content_map;
+ subframe_content_map[1u] = 2u;
+ impl.CompositePageToPdf(
+ 1u, 0, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map),
+ base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback,
+ base::Unretained(this)));
+
+ // Page 1 with frame 1 has content 1, which refers to frame
+ // 3. When the content is not available, the request is not
+ // fulfilled either.
+ subframe_content_map.clear();
+ subframe_content_map[1u] = 3u;
+ impl.CompositePageToPdf(
+ 1u, 1, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map),
+ base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback,
+ base::Unretained(this)));
+ testing::Mock::VerifyAndClearExpectations(&impl);
+
+ // When frame 3 and 2 become available, the pending requests should be
+ // satisfied, thus be fulfilled in order.
+ testing::Sequence order;
+ EXPECT_CALL(impl, OnFulfillRequest(1, 1)).Times(1).InSequence(order);
+ EXPECT_CALL(impl, OnFulfillRequest(1, 0)).Times(1).InSequence(order);
+ subframe_content_map.clear();
+ impl.AddSubframeContent(3u, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map));
+ impl.AddSubframeContent(2u, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map));
+}
+
+TEST_F(PdfCompositorImplTest, NotifyUnavailableSubframe) {
+ MockPdfCompositorImpl impl;
+ // Page 0 with frame 3 has content 1, which refers to frame 8.
+ // When the content is not available, the request is not fulfilled.
+ ContentToFrameMap subframe_content_map;
+ subframe_content_map[1u] = 8u;
+ EXPECT_CALL(impl, OnFulfillRequest(testing::_, testing::_)).Times(0);
+ impl.CompositePageToPdf(
+ 3u, 0, mojo::SharedBufferHandle::Create(10),
+ std::move(subframe_content_map),
+ base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback,
+ base::Unretained(this)));
+ testing::Mock::VerifyAndClearExpectations(&impl);
+
+ // Notifies that frame 8's unavailable, the previous request should be
+ // fulfilled.
+ EXPECT_CALL(impl, OnFulfillRequest(3u, 0)).Times(1);
+ impl.NotifyUnavailableSubframe(8u);
+ testing::Mock::VerifyAndClearExpectations(&impl);
+}
+
+} // namespace printing
diff --git a/chromium/components/printing/service/pdf_compositor_service.cc b/chromium/components/printing/service/pdf_compositor_service.cc
index b9098ce618e..59bf06278cd 100644
--- a/chromium/components/printing/service/pdf_compositor_service.cc
+++ b/chromium/components/printing/service/pdf_compositor_service.cc
@@ -6,9 +6,10 @@
#include <utility>
+#include <memory>
+
#include "base/lazy_instance.h"
#include "base/memory/discardable_memory.h"
-#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "components/printing/service/pdf_compositor_impl.h"
#include "components/printing/service/public/interfaces/pdf_compositor.mojom.h"
@@ -28,7 +29,7 @@ void OnPdfCompositorRequest(
const std::string& creator,
service_manager::ServiceContextRefFactory* ref_factory,
printing::mojom::PdfCompositorRequest request) {
- mojo::MakeStrongBinding(base::MakeUnique<printing::PdfCompositorImpl>(
+ mojo::MakeStrongBinding(std::make_unique<printing::PdfCompositorImpl>(
creator, ref_factory->CreateRef()),
std::move(request));
}
@@ -52,7 +53,7 @@ std::unique_ptr<service_manager::Service> PdfCompositorService::Create(
// Initialize direct write font proxy so skia can use it.
content::InitializeDWriteFontProxy();
#endif
- return base::MakeUnique<printing::PdfCompositorService>(creator);
+ return std::make_unique<printing::PdfCompositorService>(creator);
}
void PdfCompositorService::PrepareToStart() {
@@ -60,7 +61,7 @@ void PdfCompositorService::PrepareToStart() {
discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr;
context()->connector()->BindInterface(content::mojom::kBrowserServiceName,
&manager_ptr);
- discardable_shared_memory_manager_ = base::MakeUnique<
+ discardable_shared_memory_manager_ = std::make_unique<
discardable_memory::ClientDiscardableSharedMemoryManager>(
std::move(manager_ptr), content::UtilityThread::Get()->GetIOTaskRunner());
DCHECK(discardable_shared_memory_manager_);
@@ -71,9 +72,8 @@ void PdfCompositorService::PrepareToStart() {
void PdfCompositorService::OnStart() {
PrepareToStart();
- ref_factory_ = base::MakeUnique<service_manager::ServiceContextRefFactory>(
- base::Bind(&service_manager::ServiceContext::RequestQuit,
- base::Unretained(context())));
+ ref_factory_ = std::make_unique<service_manager::ServiceContextRefFactory>(
+ context()->CreateQuitClosure());
registry_.AddInterface(
base::Bind(&OnPdfCompositorRequest, creator_, ref_factory_.get()));
}
diff --git a/chromium/components/printing/service/pdf_compositor_service_unittest.cc b/chromium/components/printing/service/pdf_compositor_service_unittest.cc
index 7b2193c9036..9f031f9e771 100644
--- a/chromium/components/printing/service/pdf_compositor_service_unittest.cc
+++ b/chromium/components/printing/service/pdf_compositor_service_unittest.cc
@@ -14,13 +14,14 @@
#include "cc/paint/paint_flags.h"
#include "cc/paint/skia_paint_canvas.h"
#include "components/printing/service/pdf_compositor_service.h"
+#include "components/printing/service/public/cpp/pdf_service_mojo_types.h"
#include "components/printing/service/public/interfaces/pdf_compositor.mojom.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/service_context.h"
#include "services/service_manager/public/cpp/service_test.h"
-#include "services/service_manager/public/interfaces/service_factory.mojom.h"
+#include "services/service_manager/public/mojom/service_factory.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkStream.h"
@@ -86,14 +87,14 @@ class PdfCompositorServiceTest : public service_manager::test::ServiceTest {
PdfCompositorServiceTest() : ServiceTest("pdf_compositor_service_unittest") {}
~PdfCompositorServiceTest() override {}
- MOCK_METHOD1(CallbackOnSuccess, void(mojo::SharedBufferHandle));
- MOCK_METHOD1(CallbackOnError, void(mojom::PdfCompositor::Status));
- void OnCallback(mojom::PdfCompositor::Status status,
- mojo::ScopedSharedBufferHandle handle) {
+ MOCK_METHOD1(CallbackOnCompositeSuccess, void(mojo::SharedBufferHandle));
+ MOCK_METHOD1(CallbackOnCompositeStatus, void(mojom::PdfCompositor::Status));
+ void OnCompositeToPdfCallback(mojom::PdfCompositor::Status status,
+ mojo::ScopedSharedBufferHandle handle) {
if (status == mojom::PdfCompositor::Status::SUCCESS)
- CallbackOnSuccess(handle.get());
+ CallbackOnCompositeSuccess(handle.get());
else
- CallbackOnError(status);
+ CallbackOnCompositeStatus(status);
run_loop_->Quit();
}
@@ -123,7 +124,7 @@ class PdfCompositorServiceTest : public service_manager::test::ServiceTest {
return std::make_unique<PdfServiceTestClient>(this);
}
- base::SharedMemoryHandle CreateMSKPInSharedMemory() {
+ mojo::ScopedSharedBufferHandle CreateMSKP() {
SkDynamicMemoryWStream stream;
sk_sp<SkDocument> doc = SkMakeMultiPictureDocument(&stream);
cc::SkiaPaintCanvas canvas(doc->beginPage(800, 600));
@@ -144,22 +145,23 @@ class PdfCompositorServiceTest : public service_manager::test::ServiceTest {
base::SharedMemory shared_memory;
if (shared_memory.Create(options) && shared_memory.Map(len)) {
stream.copyTo(shared_memory.memory());
- return shared_memory.GetReadOnlyHandle();
+ auto handle = shared_memory.GetReadOnlyHandle();
+ return mojo::WrapSharedMemoryHandle(
+ handle, handle.GetSize(),
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly);
}
- return base::SharedMemoryHandle();
+ return mojo::ScopedSharedBufferHandle();
}
void CallCompositorWithSuccess(mojom::PdfCompositorPtr ptr) {
- auto handle = CreateMSKPInSharedMemory();
- ASSERT_TRUE(handle.IsValid());
- mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
- handle, handle.GetSize(),
- mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly);
- ASSERT_TRUE(buffer_handle->is_valid());
- EXPECT_CALL(*this, CallbackOnSuccess(testing::_)).Times(1);
- ptr->CompositePdf(std::move(buffer_handle),
- base::BindOnce(&PdfCompositorServiceTest::OnCallback,
- base::Unretained(this)));
+ static constexpr uint64_t kFrameGuid = 1234;
+ auto handle = CreateMSKP();
+ ASSERT_TRUE(handle->is_valid());
+ EXPECT_CALL(*this, CallbackOnCompositeSuccess(testing::_)).Times(1);
+ ptr->CompositeDocumentToPdf(
+ kFrameGuid, std::move(handle), ContentToFrameMap(),
+ base::BindOnce(&PdfCompositorServiceTest::OnCompositeToPdfCallback,
+ base::Unretained(this)));
run_loop_->Run();
}
@@ -171,23 +173,25 @@ class PdfCompositorServiceTest : public service_manager::test::ServiceTest {
DISALLOW_COPY_AND_ASSIGN(PdfCompositorServiceTest);
};
-// Test callback is called on error conditions in service.
+// Test callback function is called on error conditions in service.
TEST_F(PdfCompositorServiceTest, InvokeCallbackOnContentError) {
- EXPECT_CALL(*this, CallbackOnError(
+ EXPECT_CALL(*this, CallbackOnCompositeStatus(
mojom::PdfCompositor::Status::CONTENT_FORMAT_ERROR))
.Times(1);
- compositor_->CompositePdf(
- mojo::SharedBufferHandle::Create(10),
- base::BindOnce(&PdfCompositorServiceTest::OnCallback,
+ compositor_->CompositeDocumentToPdf(
+ 5u, mojo::SharedBufferHandle::Create(10), ContentToFrameMap(),
+ base::BindOnce(&PdfCompositorServiceTest::OnCompositeToPdfCallback,
base::Unretained(this)));
run_loop_->Run();
}
+// Test callback function is called upon success.
TEST_F(PdfCompositorServiceTest, InvokeCallbackOnSuccess) {
CallCompositorWithSuccess(std::move(compositor_));
}
-TEST_F(PdfCompositorServiceTest, ServiceInstances) {
+// Test coexistence of multiple service instances.
+TEST_F(PdfCompositorServiceTest, MultipleServiceInstances) {
// One service can bind multiple interfaces.
mojom::PdfCompositorPtr another_compositor;
ASSERT_FALSE(another_compositor);
@@ -200,4 +204,48 @@ TEST_F(PdfCompositorServiceTest, ServiceInstances) {
CallCompositorWithSuccess(std::move(another_compositor));
}
+// Test data structures and content of multiple service instances
+// are independent from each other.
+TEST_F(PdfCompositorServiceTest, IndependentServiceInstances) {
+ // Create a new connection 2.
+ mojom::PdfCompositorPtr compositor2;
+ ASSERT_FALSE(compositor2);
+ connector()->BindInterface(mojom::kServiceName, &compositor2);
+ ASSERT_TRUE(compositor2);
+
+ // In original connection, add frame 4 with content 2 referring
+ // to subframe 1.
+ compositor_->AddSubframeContent(1u, CreateMSKP(), ContentToFrameMap());
+
+ // Original connection can use this subframe 1.
+ EXPECT_CALL(*this, CallbackOnCompositeSuccess(testing::_)).Times(1);
+ ContentToFrameMap subframe_content_map;
+ subframe_content_map[2u] = 1u;
+
+ compositor_->CompositeDocumentToPdf(
+ 4u, CreateMSKP(), std::move(subframe_content_map),
+ base::BindOnce(&PdfCompositorServiceTest::OnCompositeToPdfCallback,
+ base::Unretained(this)));
+ run_loop_->Run();
+ testing::Mock::VerifyAndClearExpectations(this);
+
+ // Connection 2 doesn't know about subframe 1.
+ subframe_content_map.clear();
+ subframe_content_map[2u] = 1u;
+ EXPECT_CALL(*this, CallbackOnCompositeSuccess(testing::_)).Times(0);
+ compositor2->CompositeDocumentToPdf(
+ 4u, CreateMSKP(), std::move(subframe_content_map),
+ base::BindOnce(&PdfCompositorServiceTest::OnCompositeToPdfCallback,
+ base::Unretained(this)));
+ testing::Mock::VerifyAndClearExpectations(this);
+
+ // Add info about subframe 1 to connection 2 so it can use it.
+ EXPECT_CALL(*this, CallbackOnCompositeSuccess(testing::_)).Times(1);
+ // Add subframe 1's content.
+ // Now all content needed for previous request is ready.
+ compositor2->AddSubframeContent(1u, CreateMSKP(), ContentToFrameMap());
+ run_loop_ = std::make_unique<base::RunLoop>();
+ run_loop_->Run();
+}
+
} // namespace printing
diff --git a/chromium/components/printing/service/public/cpp/BUILD.gn b/chromium/components/printing/service/public/cpp/BUILD.gn
index 83110a4b6bd..dc0e09d66ca 100644
--- a/chromium/components/printing/service/public/cpp/BUILD.gn
+++ b/chromium/components/printing/service/public/cpp/BUILD.gn
@@ -4,18 +4,6 @@
import("//mojo/public/tools/bindings/mojom.gni")
-source_set("client") {
- sources = [
- "pdf_compositor_client.cc",
- "pdf_compositor_client.h",
- ]
-
- public_deps = [
- "//components/printing/service/public/interfaces",
- "//services/service_manager/public/cpp",
- ]
-}
-
source_set("factory") {
sources = [
"pdf_compositor_service_factory.cc",
diff --git a/chromium/components/printing/service/public/cpp/pdf_compositor_client.cc b/chromium/components/printing/service/public/cpp/pdf_compositor_client.cc
deleted file mode 100644
index 921b068e2e1..00000000000
--- a/chromium/components/printing/service/public/cpp/pdf_compositor_client.cc
+++ /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.
-
-#include "components/printing/service/public/cpp/pdf_compositor_client.h"
-
-#include <utility>
-
-#include "mojo/public/cpp/system/platform_handle.h"
-
-namespace printing {
-
-namespace {
-
-// Helper callback which owns an PdfCompositorPtr until invoked. This keeps the
-// PdfCompositor pipe open just long enough to dispatch a reply, at which point
-// the reply is forwarded to the wrapped |callback|.
-void OnCompositePdf(
- printing::mojom::PdfCompositorPtr compositor,
- printing::mojom::PdfCompositor::CompositePdfCallback callback,
- scoped_refptr<base::SequencedTaskRunner> task_runner,
- mojom::PdfCompositor::Status status,
- mojo::ScopedSharedBufferHandle pdf_handle) {
- task_runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback), status,
- base::Passed(&pdf_handle)));
-}
-
-} // namespace
-
-PdfCompositorClient::PdfCompositorClient() : compositor_(nullptr) {}
-
-PdfCompositorClient::~PdfCompositorClient() {}
-
-void PdfCompositorClient::Connect(service_manager::Connector* connector) {
- DCHECK(!compositor_.is_bound());
- connector->BindInterface(mojom::kServiceName, &compositor_);
-}
-
-void PdfCompositorClient::Composite(
- service_manager::Connector* connector,
- base::SharedMemoryHandle handle,
- size_t data_size,
- mojom::PdfCompositor::CompositePdfCallback callback,
- scoped_refptr<base::SequencedTaskRunner> callback_task_runner) {
- DCHECK(data_size);
-
- if (!compositor_)
- Connect(connector);
-
- mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
- handle, data_size,
- mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly);
-
- compositor_->CompositePdf(
- std::move(buffer_handle),
- base::BindOnce(&OnCompositePdf, base::Passed(&compositor_),
- std::move(callback), callback_task_runner));
-}
-
-} // namespace printing
diff --git a/chromium/components/printing/service/public/cpp/pdf_compositor_client.h b/chromium/components/printing/service/public/cpp/pdf_compositor_client.h
deleted file mode 100644
index 98168485977..00000000000
--- a/chromium/components/printing/service/public/cpp/pdf_compositor_client.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_PRINTING_SERVICE_PUBLIC_CPP_PDF_COMPOSITOR_CLIENT_H_
-#define COMPONENTS_PRINTING_SERVICE_PUBLIC_CPP_PDF_COMPOSITOR_CLIENT_H_
-
-#include "base/memory/shared_memory_handle.h"
-#include "components/printing/service/public/interfaces/pdf_compositor.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
-
-namespace printing {
-
-// Helper class to composite a pdf via the pdf_compositor service.
-class PdfCompositorClient {
- public:
- PdfCompositorClient();
- ~PdfCompositorClient();
-
- // Composite the final picture and convert into a PDF file.
- //
- // NOTE: |handle| must be a READ-ONLY base::SharedMemoryHandle, i.e. one
- // acquired by base::SharedMemory::GetReadOnlyHandle().
- void Composite(service_manager::Connector* connector,
- base::SharedMemoryHandle handle,
- size_t data_size,
- mojom::PdfCompositor::CompositePdfCallback callback,
- scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
-
- private:
- // Connect to the service.
- void Connect(service_manager::Connector* connector);
-
- mojom::PdfCompositorPtr compositor_;
-
- DISALLOW_COPY_AND_ASSIGN(PdfCompositorClient);
-};
-
-} // namespace printing
-
-#endif // COMPONENTS_PRINTING_SERVICE_PUBLIC_CPP_PDF_COMPOSITOR_CLIENT_H_
diff --git a/chromium/components/printing/service/public/cpp/pdf_service_mojo_types.h b/chromium/components/printing/service/public/cpp/pdf_service_mojo_types.h
new file mode 100644
index 00000000000..05828cd09c2
--- /dev/null
+++ b/chromium/components/printing/service/public/cpp/pdf_service_mojo_types.h
@@ -0,0 +1,17 @@
+// Copyright 2018 The Chromium Authors. All 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_SERVICE_PUBLIC_CPP_PDF_SERVICE_MOJO_TYPES_H_
+#define COMPONENTS_PRINTING_SERVICE_PUBLIC_CPP_PDF_SERVICE_MOJO_TYPES_H_
+
+#include <unordered_map>
+
+namespace printing {
+
+// Create an alias for map<uint32, uint64> type.
+using ContentToFrameMap = std::unordered_map<uint32_t, uint64_t>;
+
+} // namespace printing
+
+#endif // COMPONENTS_PRINTING_SERVICE_PUBLIC_CPP_PDF_SERVICE_MOJO_TYPES_H_
diff --git a/chromium/components/printing/service/public/interfaces/pdf_compositor.mojom b/chromium/components/printing/service/public/interfaces/pdf_compositor.mojom
index ad8b5549902..ca9ba7aeaf4 100644
--- a/chromium/components/printing/service/public/interfaces/pdf_compositor.mojom
+++ b/chromium/components/printing/service/public/interfaces/pdf_compositor.mojom
@@ -6,20 +6,48 @@ module printing.mojom;
const string kServiceName = "pdf_compositor";
-// TODO(weili): Add support for printing frames from different processes.
interface PdfCompositor {
- // The status of CompositePdf execution.
+ // The status of composition and conversion execution.
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
enum Status {
- SUCCESS,
- HANDLE_MAP_ERROR,
- CONTENT_FORMAT_ERROR,
- COMPOSTING_FAILURE,
+ SUCCESS = 0,
+ HANDLE_MAP_ERROR = 1,
+ CONTENT_FORMAT_ERROR = 2,
+ COMPOSTING_FAILURE = 3,
};
- // Currently directly convert passed in page data to a PDF file.
- // |sk_handle| points to a buffer of a Skia MultiPictureDocument.
- // |status| records the function execution status.
- // |pdf_handle| points to the generated PDF file buffer upon success.
- CompositePdf(handle<shared_buffer> sk_handle)
+ // Notifies that a subframe is unavailable, such as the render frame process
+ // hosting it crashed or terminated. The subframe will be composited with no
+ // content in the composited result.
+ // |frame_guid| is this subframe's global unique id.
+ NotifyUnavailableSubframe(uint64 frame_guid);
+
+ // Add the content of a subframe for composition.
+ // |frame_guid| is this subframe's global unique id.
+ // |serialized_content| points to a buffer of a serialized Skia picture which
+ // has the painted content of this frame.
+ // |subframe_content_map| records content id and its corresponding frame's
+ // global unique id.
+ AddSubframeContent(uint64 frame_guid, handle<shared_buffer> serialized_content,
+ map<uint32, uint64> subframe_content_info);
+
+ // Request to composite a page and convert it into a PDF file.
+ // |frame_guid| is the global unique id of the frame to be composited.
+ // |page_num| is zero-based sequence number of page.
+ // |sk_handle| points to a buffer of a Skia MultiPictureDocument which has
+ // the drawing content of this frame or a page of this frame.
+ // |subframe_content_map| records content id and its corresponding frame's
+ // global unique id.
+ CompositePageToPdf(uint64 frame_guid, uint32 page_num,
+ handle<shared_buffer> sk_handle,
+ map<uint32, uint64> subframe_content_info)
+ => (Status status, handle<shared_buffer>? pdf_handle);
+
+ // Request to composite the entire document and convert it into a PDF file.
+ // All the arguments carry the same meaning as CompositePageToPdf() above,
+ // except this call doesn't have |page_num|.
+ CompositeDocumentToPdf(uint64 frame_guid, handle<shared_buffer> sk_handle,
+ map<uint32, uint64> subframe_content_info)
=> (Status status, handle<shared_buffer>? pdf_handle);
};
diff --git a/chromium/components/printing_strings.grdp b/chromium/components/printing_strings.grdp
new file mode 100644
index 00000000000..f157cbaec42
--- /dev/null
+++ b/chromium/components/printing_strings.grdp
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <if expr="enable_print_preview">
+ <if expr="is_win">
+ <message name="IDS_PRINT_PREVIEW_FRIENDLY_WIN_NETWORK_PRINTER_NAME" desc="Friendly name for a printer with a given name on a given server. This uses the same format as the Windows print dialog.">
+ <ph name="PRINTER_NAME">$1<ex>HP LaserJet</ex></ph> on <ph name="SERVER_NAME">$2<ex>printserver</ex></ph>
+ </message>
+ </if>
+ </if>
+</grit-part>
diff --git a/chromium/components/proxy_config/ios/DEPS b/chromium/components/proxy_config/ios/DEPS
index c11101cf81b..d39f540402a 100644
--- a/chromium/components/proxy_config/ios/DEPS
+++ b/chromium/components/proxy_config/ios/DEPS
@@ -1,5 +1,5 @@
include_rules = [
"+ios/public/provider/web",
"+ios/web/public",
- "+net/proxy"
+ "+net/proxy_resolution"
]
diff --git a/chromium/components/proxy_config/ios/proxy_service_factory.cc b/chromium/components/proxy_config/ios/proxy_service_factory.cc
index e0e0775a558..ad272d9ec88 100644
--- a/chromium/components/proxy_config/ios/proxy_service_factory.cc
+++ b/chromium/components/proxy_config/ios/proxy_service_factory.cc
@@ -6,17 +6,18 @@
#include <utility>
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
#include "ios/web/public/web_thread.h"
-#include "net/proxy/proxy_config_service.h"
-#include "net/proxy/proxy_service.h"
+#include "net/proxy_resolution/proxy_config_service.h"
+#include "net/proxy_resolution/proxy_service.h"
// static
std::unique_ptr<net::ProxyConfigService>
ProxyServiceFactory::CreateProxyConfigService(PrefProxyConfigTracker* tracker) {
std::unique_ptr<net::ProxyConfigService> base_service(
- net::ProxyService::CreateSystemProxyConfigService(
+ net::ProxyResolutionService::CreateSystemProxyConfigService(
web::WebThread::GetTaskRunnerForThread(web::WebThread::IO)));
return tracker->CreateTrackingProxyConfigService(std::move(base_service));
}
@@ -26,7 +27,7 @@ std::unique_ptr<PrefProxyConfigTracker>
ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile(
PrefService* browser_state_prefs,
PrefService* local_state_prefs) {
- return base::MakeUnique<PrefProxyConfigTrackerImpl>(
+ return std::make_unique<PrefProxyConfigTrackerImpl>(
browser_state_prefs,
web::WebThread::GetTaskRunnerForThread(web::WebThread::IO));
}
@@ -35,22 +36,23 @@ ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile(
std::unique_ptr<PrefProxyConfigTracker>
ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
PrefService* local_state_prefs) {
- return base::MakeUnique<PrefProxyConfigTrackerImpl>(
+ return std::make_unique<PrefProxyConfigTrackerImpl>(
local_state_prefs,
web::WebThread::GetTaskRunnerForThread(web::WebThread::IO));
}
// static
-std::unique_ptr<net::ProxyService> ProxyServiceFactory::CreateProxyService(
+std::unique_ptr<net::ProxyResolutionService>
+ProxyServiceFactory::CreateProxyService(
net::NetLog* net_log,
net::URLRequestContext* context,
net::NetworkDelegate* network_delegate,
std::unique_ptr<net::ProxyConfigService> proxy_config_service,
bool quick_check_enabled) {
DCHECK_CURRENTLY_ON(web::WebThread::IO);
- std::unique_ptr<net::ProxyService> proxy_service(
- net::ProxyService::CreateUsingSystemProxyResolver(
+ std::unique_ptr<net::ProxyResolutionService> proxy_resolution_service(
+ net::ProxyResolutionService::CreateUsingSystemProxyResolver(
std::move(proxy_config_service), net_log));
- proxy_service->set_quick_check_enabled(quick_check_enabled);
- return proxy_service;
+ proxy_resolution_service->set_quick_check_enabled(quick_check_enabled);
+ return proxy_resolution_service;
}
diff --git a/chromium/components/proxy_config/ios/proxy_service_factory.h b/chromium/components/proxy_config/ios/proxy_service_factory.h
index dfa00ca542e..77e112e2b3a 100644
--- a/chromium/components/proxy_config/ios/proxy_service_factory.h
+++ b/chromium/components/proxy_config/ios/proxy_service_factory.h
@@ -17,7 +17,7 @@ namespace net {
class NetLog;
class NetworkDelegate;
class ProxyConfigService;
-class ProxyService;
+class ProxyResolutionService;
class URLRequestContext;
}
@@ -38,7 +38,7 @@ class PROXY_CONFIG_EXPORT ProxyServiceFactory {
CreatePrefProxyConfigTrackerOfLocalState(PrefService* local_state_prefs);
// Create a proxy service.
- static std::unique_ptr<net::ProxyService> CreateProxyService(
+ static std::unique_ptr<net::ProxyResolutionService> CreateProxyService(
net::NetLog* net_log,
net::URLRequestContext* context,
net::NetworkDelegate* network_delegate,
diff --git a/chromium/components/proxy_config/pref_proxy_config_tracker_impl.cc b/chromium/components/proxy_config/pref_proxy_config_tracker_impl.cc
index c39d5e4c22e..07e151dfe44 100644
--- a/chromium/components/proxy_config/pref_proxy_config_tracker_impl.cc
+++ b/chromium/components/proxy_config/pref_proxy_config_tracker_impl.cc
@@ -17,7 +17,7 @@
#include "components/prefs/pref_service.h"
#include "components/proxy_config/proxy_config_dictionary.h"
#include "components/proxy_config/proxy_config_pref_names.h"
-#include "net/proxy/proxy_server.h"
+#include "net/base/proxy_server.h"
#include "url/gurl.h"
//============================= ProxyConfigServiceImpl =======================
diff --git a/chromium/components/proxy_config/pref_proxy_config_tracker_impl.h b/chromium/components/proxy_config/pref_proxy_config_tracker_impl.h
index 4a5b7f5e463..65f467a5cad 100644
--- a/chromium/components/proxy_config/pref_proxy_config_tracker_impl.h
+++ b/chromium/components/proxy_config/pref_proxy_config_tracker_impl.h
@@ -14,8 +14,8 @@
#include "components/prefs/pref_change_registrar.h"
#include "components/proxy_config/pref_proxy_config_tracker.h"
#include "components/proxy_config/proxy_config_dictionary.h"
-#include "net/proxy/proxy_config.h"
-#include "net/proxy/proxy_config_service.h"
+#include "net/proxy_resolution/proxy_config.h"
+#include "net/proxy_resolution/proxy_config_service.h"
class PrefService;
class PrefRegistrySimple;
diff --git a/chromium/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc b/chromium/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc
index b0fd3b51326..5e46c82134a 100644
--- a/chromium/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc
+++ b/chromium/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc
@@ -15,8 +15,8 @@
#include "components/prefs/testing_pref_service.h"
#include "components/proxy_config/proxy_config_dictionary.h"
#include "components/proxy_config/proxy_config_pref_names.h"
-#include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_list.h"
+#include "net/proxy_resolution/proxy_info.h"
+#include "net/proxy_resolution/proxy_list.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -126,7 +126,7 @@ TEST_F(PrefProxyConfigTrackerImplTest, DynamicPrefOverrides) {
EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID,
proxy_config_service_->GetLatestProxyConfig(&actual_config));
EXPECT_FALSE(actual_config.auto_detect());
- EXPECT_EQ(net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY,
+ EXPECT_EQ(net::ProxyConfig::ProxyRules::Type::PROXY_LIST,
actual_config.proxy_rules().type);
EXPECT_EQ(actual_config.proxy_rules().single_proxies.Get(),
net::ProxyServer::FromURI("http://example.com:3128",
@@ -141,10 +141,9 @@ TEST_F(PrefProxyConfigTrackerImplTest, DynamicPrefOverrides) {
EXPECT_TRUE(actual_config.auto_detect());
}
-// Compares proxy configurations, but allows different identifiers.
+// Compares proxy configurations, but allows different sources.
MATCHER_P(ProxyConfigMatches, config, "") {
net::ProxyConfig reference(config);
- reference.set_id(arg.id());
return reference.Equals(arg);
}
diff --git a/chromium/components/proxy_config/proxy_config_dictionary.cc b/chromium/components/proxy_config/proxy_config_dictionary.cc
index a55133c71be..1451425c28b 100644
--- a/chromium/components/proxy_config/proxy_config_dictionary.cc
+++ b/chromium/components/proxy_config/proxy_config_dictionary.cc
@@ -4,12 +4,12 @@
#include "components/proxy_config/proxy_config_dictionary.h"
+#include <memory>
#include <utility>
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/values.h"
-#include "net/proxy/proxy_config.h"
+#include "net/proxy_resolution/proxy_config.h"
namespace {
@@ -133,7 +133,7 @@ std::unique_ptr<base::DictionaryValue> ProxyConfigDictionary::CreateDictionary(
bool pac_mandatory,
const std::string& proxy_server,
const std::string& bypass_list) {
- auto dict = base::MakeUnique<base::DictionaryValue>();
+ auto dict = std::make_unique<base::DictionaryValue>();
dict->SetString(kProxyMode, ProxyModeToString(mode));
if (!pac_url.empty()) {
dict->SetString(kProxyPacUrl, pac_url);
diff --git a/chromium/components/pwg_encoder/BUILD.gn b/chromium/components/pwg_encoder/BUILD.gn
new file mode 100644
index 00000000000..452c53bff69
--- /dev/null
+++ b/chromium/components/pwg_encoder/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//printing/features/features.gni")
+
+assert(enable_print_preview)
+
+static_library("pwg_encoder") {
+ sources = [
+ "bitmap_image.cc",
+ "bitmap_image.h",
+ "pwg_encoder.cc",
+ "pwg_encoder.h",
+ ]
+
+ deps = [
+ "//base",
+ "//ui/gfx/geometry",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+
+ sources = [
+ "pwg_encoder_unittest.cc",
+ ]
+
+ deps = [
+ ":pwg_encoder",
+ "//base/test:test_support",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/pwg_encoder/DEPS b/chromium/components/pwg_encoder/DEPS
new file mode 100644
index 00000000000..194be1c46b7
--- /dev/null
+++ b/chromium/components/pwg_encoder/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+ui/gfx/geometry",
+]
diff --git a/chromium/components/pwg_encoder/OWNERS b/chromium/components/pwg_encoder/OWNERS
new file mode 100644
index 00000000000..5a90025bab3
--- /dev/null
+++ b/chromium/components/pwg_encoder/OWNERS
@@ -0,0 +1,3 @@
+file://printing/OWNERS
+
+# COMPONENT: Services>CloudPrint
diff --git a/chromium/components/pwg_encoder/bitmap_image.cc b/chromium/components/pwg_encoder/bitmap_image.cc
new file mode 100644
index 00000000000..2e302bb8891
--- /dev/null
+++ b/chromium/components/pwg_encoder/bitmap_image.cc
@@ -0,0 +1,32 @@
+// 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/pwg_encoder/bitmap_image.h"
+
+#include "base/logging.h"
+
+namespace pwg_encoder {
+
+namespace {
+const uint8_t kCurrentlySupportedNumberOfChannels = 4;
+}
+
+BitmapImage::BitmapImage(const gfx::Size& size, Colorspace colorspace)
+ : size_(size),
+ colorspace_(colorspace),
+ data_(new uint8_t[size.GetArea() * channels()]) {}
+
+BitmapImage::~BitmapImage() {}
+
+uint8_t BitmapImage::channels() const {
+ return kCurrentlySupportedNumberOfChannels;
+}
+
+const uint8_t* BitmapImage::GetPixel(const gfx::Point& point) const {
+ DCHECK_LT(point.x(), size_.width());
+ DCHECK_LT(point.y(), size_.height());
+ return data_.get() + (point.y() * size_.width() + point.x()) * channels();
+}
+
+} // namespace pwg_encoder
diff --git a/chromium/components/pwg_encoder/bitmap_image.h b/chromium/components/pwg_encoder/bitmap_image.h
new file mode 100644
index 00000000000..d13033bf527
--- /dev/null
+++ b/chromium/components/pwg_encoder/bitmap_image.h
@@ -0,0 +1,48 @@
+// 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_PWG_ENCODER_BITMAP_IMAGE_H_
+#define COMPONENTS_PWG_ENCODER_BITMAP_IMAGE_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/macros.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace pwg_encoder {
+
+class BitmapImage {
+ public:
+ enum Colorspace {
+ // These are the only types PWGEncoder currently supports.
+ RGBA,
+ BGRA
+ };
+
+ BitmapImage(const gfx::Size& size, Colorspace colorspace);
+ ~BitmapImage();
+
+ uint8_t channels() const;
+ const gfx::Size& size() const { return size_; }
+ Colorspace colorspace() const { return colorspace_; }
+
+ const uint8_t* pixel_data() const { return data_.get(); }
+ uint8_t* pixel_data() { return data_.get(); }
+
+ const uint8_t* GetPixel(const gfx::Point& point) const;
+
+ private:
+ gfx::Size size_;
+ Colorspace colorspace_;
+ std::unique_ptr<uint8_t[]> data_;
+
+ DISALLOW_COPY_AND_ASSIGN(BitmapImage);
+};
+
+} // namespace pwg_encoder
+
+#endif // COMPONENTS_PWG_ENCODER_BITMAP_IMAGE_H_
diff --git a/chromium/components/pwg_encoder/pwg_encoder.cc b/chromium/components/pwg_encoder/pwg_encoder.cc
new file mode 100644
index 00000000000..f66cfc4d419
--- /dev/null
+++ b/chromium/components/pwg_encoder/pwg_encoder.cc
@@ -0,0 +1,264 @@
+// 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/pwg_encoder/pwg_encoder.h"
+
+#include <limits.h>
+#include <string.h>
+
+#include <algorithm>
+#include <memory>
+
+#include "base/big_endian.h"
+#include "base/logging.h"
+#include "components/pwg_encoder/bitmap_image.h"
+
+namespace pwg_encoder {
+
+namespace {
+
+const uint32_t kBitsPerColor = 8;
+const uint32_t kColorOrder = 0; // chunky.
+
+// Coefficients used to convert from RGB to monochrome.
+const uint32_t kRedCoefficient = 2125;
+const uint32_t kGreenCoefficient = 7154;
+const uint32_t kBlueCoefficient = 721;
+const uint32_t kColorCoefficientDenominator = 10000;
+
+const char kPwgKeyword[] = "RaS2";
+
+const uint32_t kHeaderSize = 1796;
+const uint32_t kHeaderCupsDuplex = 272;
+const uint32_t kHeaderCupsHwResolutionHorizontal = 276;
+const uint32_t kHeaderCupsHwResolutionVertical = 280;
+const uint32_t kHeaderCupsTumble = 368;
+const uint32_t kHeaderCupsWidth = 372;
+const uint32_t kHeaderCupsHeight = 376;
+const uint32_t kHeaderCupsBitsPerColor = 384;
+const uint32_t kHeaderCupsBitsPerPixel = 388;
+const uint32_t kHeaderCupsBytesPerLine = 392;
+const uint32_t kHeaderCupsColorOrder = 396;
+const uint32_t kHeaderCupsColorSpace = 400;
+const uint32_t kHeaderCupsNumColors = 420;
+const uint32_t kHeaderPwgTotalPageCount = 452;
+const uint32_t kHeaderPwgCrossFeedTransform = 456;
+const uint32_t kHeaderPwgFeedTransform = 460;
+
+const int kPwgMaxPackedRows = 256;
+
+const int kPwgMaxPackedPixels = 128;
+
+struct RGBA8 {
+ uint8_t red;
+ uint8_t green;
+ uint8_t blue;
+ uint8_t alpha;
+};
+
+struct BGRA8 {
+ uint8_t blue;
+ uint8_t green;
+ uint8_t red;
+ uint8_t alpha;
+};
+
+template <class InputStruct>
+void EncodePixelToRGB(const void* pixel, std::string* output) {
+ const InputStruct* i = reinterpret_cast<const InputStruct*>(pixel);
+ output->push_back(static_cast<char>(i->red));
+ output->push_back(static_cast<char>(i->green));
+ output->push_back(static_cast<char>(i->blue));
+}
+
+template <class InputStruct>
+void EncodePixelToMonochrome(const void* pixel, std::string* output) {
+ const InputStruct* i = reinterpret_cast<const InputStruct*>(pixel);
+ output->push_back(static_cast<char>((i->red * kRedCoefficient +
+ i->green * kGreenCoefficient +
+ i->blue * kBlueCoefficient) /
+ kColorCoefficientDenominator));
+}
+
+std::string EncodePageHeader(const BitmapImage& image,
+ const PwgHeaderInfo& pwg_header_info) {
+ char header[kHeaderSize];
+ memset(header, 0, kHeaderSize);
+
+ uint32_t num_colors =
+ pwg_header_info.color_space == PwgHeaderInfo::SGRAY ? 1 : 3;
+ uint32_t bits_per_pixel = num_colors * kBitsPerColor;
+
+ base::WriteBigEndian<uint32_t>(header + kHeaderCupsDuplex,
+ pwg_header_info.duplex ? 1 : 0);
+ base::WriteBigEndian<uint32_t>(header + kHeaderCupsHwResolutionHorizontal,
+ pwg_header_info.dpi.width());
+ base::WriteBigEndian<uint32_t>(header + kHeaderCupsHwResolutionVertical,
+ pwg_header_info.dpi.height());
+ base::WriteBigEndian<uint32_t>(header + kHeaderCupsTumble,
+ pwg_header_info.tumble ? 1 : 0);
+ base::WriteBigEndian<uint32_t>(header + kHeaderCupsWidth,
+ image.size().width());
+ base::WriteBigEndian<uint32_t>(header + kHeaderCupsHeight,
+ image.size().height());
+ base::WriteBigEndian<uint32_t>(header + kHeaderCupsBitsPerColor,
+ kBitsPerColor);
+ base::WriteBigEndian<uint32_t>(header + kHeaderCupsBitsPerPixel,
+ bits_per_pixel);
+ base::WriteBigEndian<uint32_t>(
+ header + kHeaderCupsBytesPerLine,
+ (bits_per_pixel * image.size().width() + 7) / 8);
+ base::WriteBigEndian<uint32_t>(header + kHeaderCupsColorOrder, kColorOrder);
+ base::WriteBigEndian<uint32_t>(header + kHeaderCupsColorSpace,
+ pwg_header_info.color_space);
+ base::WriteBigEndian<uint32_t>(header + kHeaderCupsNumColors, num_colors);
+ base::WriteBigEndian<uint32_t>(header + kHeaderPwgCrossFeedTransform,
+ pwg_header_info.flipx ? -1 : 1);
+ base::WriteBigEndian<uint32_t>(header + kHeaderPwgFeedTransform,
+ pwg_header_info.flipy ? -1 : 1);
+ base::WriteBigEndian<uint32_t>(header + kHeaderPwgTotalPageCount,
+ pwg_header_info.total_pages);
+ return std::string(header, kHeaderSize);
+}
+
+template <typename InputStruct, class RandomAccessIterator>
+void EncodeRow(RandomAccessIterator pos,
+ RandomAccessIterator row_end,
+ bool monochrome,
+ std::string* output) {
+ // According to PWG-raster, a sequence of N identical pixels (up to 128)
+ // can be encoded by a byte N-1, followed by the information on
+ // that pixel. Any generic sequence of N pixels (up to 129) can be encoded
+ // with (signed) byte 1-N, followed by the information on the N pixels.
+ // Notice that for sequences of 1 pixel there is no difference between
+ // the two encodings.
+
+ // We encode every largest sequence of identical pixels together because it
+ // usually saves the most space. Every other pixel should be encoded in the
+ // smallest number of generic sequences.
+ // NOTE: the algorithm is not optimal especially in case of monochrome.
+ while (pos != row_end) {
+ RandomAccessIterator it = pos + 1;
+ RandomAccessIterator end = std::min(pos + kPwgMaxPackedPixels, row_end);
+
+ // Counts how many identical pixels (up to 128).
+ while (it != end && *pos == *it) {
+ ++it;
+ }
+ if (it != pos + 1) { // More than one pixel
+ output->push_back(static_cast<char>((it - pos) - 1));
+ if (monochrome)
+ EncodePixelToMonochrome<InputStruct>(&*pos, output);
+ else
+ EncodePixelToRGB<InputStruct>(&*pos, output);
+ pos = it;
+ } else {
+ // Finds how many pixels there are each different from the previous one.
+ // IMPORTANT: even if sequences of different pixels can contain as many
+ // as 129 pixels, we restrict to 128 because some decoders don't manage
+ // it correctly. So iterating until it != end is correct.
+ while (it != end && *it != *(it - 1)) {
+ ++it;
+ }
+ // Optimization: ignores the last pixel of the sequence if it is followed
+ // by an identical pixel, as it is more convenient for it to be the start
+ // of a new sequence of identical pixels. Notice that we don't compare
+ // to end, but row_end.
+ if (it != row_end && *it == *(it - 1)) {
+ --it;
+ }
+ output->push_back(static_cast<char>(1 - (it - pos)));
+ while (pos != it) {
+ if (monochrome)
+ EncodePixelToMonochrome<InputStruct>(&*pos, output);
+ else
+ EncodePixelToRGB<InputStruct>(&*pos, output);
+ ++pos;
+ }
+ }
+ }
+}
+
+const uint8_t* GetRow(const BitmapImage& image, int row, bool flipy) {
+ return image.GetPixel(
+ gfx::Point(0, flipy ? image.size().height() - 1 - row : row));
+}
+
+template <typename InputStruct>
+std::string EncodePageWithColorspace(const BitmapImage& image,
+ const PwgHeaderInfo& pwg_header_info) {
+ bool monochrome = pwg_header_info.color_space == PwgHeaderInfo::SGRAY;
+ std::string output = EncodePageHeader(image, pwg_header_info);
+
+ // Ensure no integer overflow.
+ CHECK(image.size().width() < INT_MAX / image.channels());
+ int row_size = image.size().width() * image.channels();
+
+ int row_number = 0;
+ while (row_number < image.size().height()) {
+ const uint8_t* current_row =
+ GetRow(image, row_number++, pwg_header_info.flipy);
+ int num_identical_rows = 1;
+ // We count how many times the current row is repeated.
+ while (num_identical_rows < kPwgMaxPackedRows &&
+ row_number < image.size().height() &&
+ !memcmp(current_row,
+ GetRow(image, row_number, pwg_header_info.flipy),
+ row_size)) {
+ num_identical_rows++;
+ row_number++;
+ }
+ output.push_back(static_cast<char>(num_identical_rows - 1));
+
+ // Both supported colorspaces have a 32-bit pixels information.
+ // Converts the list of uint8_t to uint32_t as every pixels contains 4 bytes
+ // of information and comparison of elements is easier. The actual
+ // Management of the bytes of the pixel is done by pixel_encoder function
+ // on the original array to avoid endian problems.
+ const uint32_t* pos = reinterpret_cast<const uint32_t*>(current_row);
+ const uint32_t* row_end = pos + image.size().width();
+ if (!pwg_header_info.flipx) {
+ EncodeRow<InputStruct>(pos, row_end, monochrome, &output);
+ } else {
+ // We reverse the iterators.
+ EncodeRow<InputStruct>(std::reverse_iterator<const uint32_t*>(row_end),
+ std::reverse_iterator<const uint32_t*>(pos),
+ monochrome, &output);
+ }
+ }
+ return output;
+}
+
+} // namespace
+
+// static
+std::string PwgEncoder::GetDocumentHeader() {
+ std::string output;
+ output.append(kPwgKeyword, 4);
+ return output;
+}
+
+// static
+std::string PwgEncoder::EncodePage(const BitmapImage& image,
+ const PwgHeaderInfo& pwg_header_info) {
+ // pwg_header_info.color_space can only contain color spaces that are
+ // supported, so no sanity check is needed.
+ std::string data;
+ switch (image.colorspace()) {
+ case BitmapImage::RGBA:
+ data = EncodePageWithColorspace<RGBA8>(image, pwg_header_info);
+ break;
+
+ case BitmapImage::BGRA:
+ data = EncodePageWithColorspace<BGRA8>(image, pwg_header_info);
+ break;
+
+ default:
+ LOG(ERROR) << "Unsupported colorspace.";
+ break;
+ }
+ return data;
+}
+
+} // namespace pwg_encoder
diff --git a/chromium/components/pwg_encoder/pwg_encoder.h b/chromium/components/pwg_encoder/pwg_encoder.h
new file mode 100644
index 00000000000..c621b72ffb6
--- /dev/null
+++ b/chromium/components/pwg_encoder/pwg_encoder.h
@@ -0,0 +1,53 @@
+// 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_PWG_ENCODER_PWG_ENCODER_H_
+#define COMPONENTS_PWG_ENCODER_PWG_ENCODER_H_
+
+#include <stdint.h>
+
+#include <string>
+
+#include "base/macros.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace pwg_encoder {
+
+class BitmapImage;
+
+struct PwgHeaderInfo {
+ PwgHeaderInfo()
+ : dpi(300, 300),
+ total_pages(1),
+ flipx(false),
+ flipy(false),
+ color_space(SRGB),
+ duplex(false),
+ tumble(false) {}
+ enum ColorSpace { SGRAY = 18, SRGB = 19 };
+ gfx::Size dpi;
+ uint32_t total_pages;
+ bool flipx;
+ bool flipy;
+ ColorSpace color_space;
+ bool duplex;
+ bool tumble;
+};
+
+class PwgEncoder {
+ public:
+ static std::string GetDocumentHeader();
+
+ // Given an image, create a PWG of the image and put the compressed image data
+ // in the returned string, or return an empty string on failure.
+ static std::string EncodePage(const BitmapImage& image,
+ const PwgHeaderInfo& pwg_header_info);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(PwgEncoder);
+};
+
+} // namespace pwg_encoder
+
+#endif // COMPONENTS_PWG_ENCODER_PWG_ENCODER_H_
diff --git a/chromium/components/pwg_encoder/pwg_encoder_unittest.cc b/chromium/components/pwg_encoder/pwg_encoder_unittest.cc
new file mode 100644
index 00000000000..96e822b7b88
--- /dev/null
+++ b/chromium/components/pwg_encoder/pwg_encoder_unittest.cc
@@ -0,0 +1,83 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/pwg_encoder/pwg_encoder.h"
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/sha1.h"
+#include "base/strings/string_number_conversions.h"
+#include "components/pwg_encoder/bitmap_image.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace pwg_encoder {
+
+namespace {
+
+const int kRasterWidth = 612;
+const int kRasterHeight = 792;
+const int kRasterDPI = 72;
+
+std::unique_ptr<BitmapImage> MakeSampleBitmap() {
+ auto bitmap_image = std::make_unique<BitmapImage>(
+ gfx::Size(kRasterWidth, kRasterHeight), BitmapImage::RGBA);
+ uint32_t* bitmap_data =
+ reinterpret_cast<uint32_t*>(bitmap_image->pixel_data());
+ for (int i = 0; i < kRasterWidth * kRasterHeight; i++)
+ bitmap_data[i] = 0xFFFFFF;
+
+ for (int i = 0; i < kRasterWidth; i++) {
+ for (int j = 200; j < 300; j++) {
+ int row_start = j * kRasterWidth;
+ uint32_t red = (i * 255) / kRasterWidth;
+ bitmap_data[row_start + i] = red;
+ }
+ }
+
+ // To test run length encoding
+ for (int i = 0; i < kRasterWidth; i++) {
+ for (int j = 400; j < 500; j++) {
+ int row_start = j * kRasterWidth;
+ if ((i / 40) % 2 == 0) {
+ bitmap_data[row_start + i] = 255 << 8;
+ } else {
+ bitmap_data[row_start + i] = 255 << 16;
+ }
+ }
+ }
+
+ return bitmap_image;
+}
+
+} // namespace
+
+TEST(PwgRasterTest, Encode) {
+ // Encode in color by default.
+ std::unique_ptr<BitmapImage> image = MakeSampleBitmap();
+ PwgHeaderInfo header_info;
+ header_info.dpi = gfx::Size(kRasterDPI, kRasterDPI);
+
+ std::string output = PwgEncoder::GetDocumentHeader();
+ output += PwgEncoder::EncodePage(*image, header_info);
+ EXPECT_EQ(2970U, output.size());
+
+ std::string sha1 = base::SHA1HashString(output);
+ EXPECT_EQ("4AD7442998C8FEAE94BC9C8B177A7C94766CC9FB",
+ base::HexEncode(sha1.data(), sha1.size()));
+
+ // Encode again in monochrome.
+ header_info.color_space = PwgHeaderInfo::SGRAY;
+
+ output = PwgEncoder::GetDocumentHeader();
+ output += PwgEncoder::EncodePage(*image, header_info);
+ EXPECT_EQ(2388U, output.size());
+
+ sha1 = base::SHA1HashString(output);
+ EXPECT_EQ("4E718B0A69AC26A366A2E23AE1ECA6055079A1FF",
+ base::HexEncode(sha1.data(), sha1.size()));
+}
+
+} // namespace pwg_encoder
diff --git a/chromium/components/query_parser/OWNERS b/chromium/components/query_parser/OWNERS
index b221410c272..90b3e809ffe 100644
--- a/chromium/components/query_parser/OWNERS
+++ b/chromium/components/query_parser/OWNERS
@@ -1,2 +1 @@
-brettw@chromium.org
sky@chromium.org
diff --git a/chromium/components/query_parser/query_parser.cc b/chromium/components/query_parser/query_parser.cc
index c65b06ee252..b7426eaffca 100644
--- a/chromium/components/query_parser/query_parser.cc
+++ b/chromium/components/query_parser/query_parser.cc
@@ -5,13 +5,13 @@
#include "components/query_parser/query_parser.h"
#include <algorithm>
+#include <memory>
#include "base/compiler_specific.h"
#include "base/i18n/break_iterator.h"
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
namespace query_parser {
@@ -424,7 +424,7 @@ bool QueryParser::ParseQueryImpl(const base::string16& query,
// or whitespace.
if (iter.IsWord()) {
std::unique_ptr<QueryNodeWord> word_node =
- base::MakeUnique<QueryNodeWord>(iter.GetString(), matching_algorithm);
+ std::make_unique<QueryNodeWord>(iter.GetString(), matching_algorithm);
if (in_quotes)
word_node->set_literal(true);
query_stack.back()->AddChild(std::move(word_node));
@@ -432,7 +432,7 @@ bool QueryParser::ParseQueryImpl(const base::string16& query,
if (IsQueryQuote(query[iter.prev()])) {
if (!in_quotes) {
std::unique_ptr<QueryNodeList> quotes_node =
- base::MakeUnique<QueryNodePhrase>();
+ std::make_unique<QueryNodePhrase>();
QueryNodeList* quotes_node_ptr = quotes_node.get();
query_stack.back()->AddChild(std::move(quotes_node));
query_stack.push_back(quotes_node_ptr);
diff --git a/chromium/components/quirks/quirks_manager.cc b/chromium/components/quirks/quirks_manager.cc
index f883745fc02..7b927d5f67d 100644
--- a/chromium/components/quirks/quirks_manager.cc
+++ b/chromium/components/quirks/quirks_manager.cc
@@ -13,6 +13,8 @@
#include "base/strings/stringprintf.h"
#include "base/task_runner.h"
#include "base/task_runner_util.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/quirks/pref_names.h"
@@ -57,12 +59,11 @@ std::string IdToFileName(int64_t product_id) {
QuirksManager::QuirksManager(
std::unique_ptr<Delegate> delegate,
- scoped_refptr<base::TaskRunner> task_runner,
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> url_context_getter)
: waiting_for_login_(true),
delegate_(std::move(delegate)),
- task_runner_(task_runner),
+ task_runner_(base::CreateTaskRunnerWithTraits({base::MayBlock()})),
local_state_(local_state),
url_context_getter_(url_context_getter),
weak_ptr_factory_(this) {}
@@ -75,11 +76,10 @@ QuirksManager::~QuirksManager() {
// static
void QuirksManager::Initialize(
std::unique_ptr<Delegate> delegate,
- scoped_refptr<base::TaskRunner> task_runner,
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> url_context_getter) {
- manager_ = new QuirksManager(std::move(delegate), task_runner, local_state,
- url_context_getter);
+ manager_ =
+ new QuirksManager(std::move(delegate), local_state, url_context_getter);
}
// static
diff --git a/chromium/components/quirks/quirks_manager.h b/chromium/components/quirks/quirks_manager.h
index d5a90a7fd98..f1ea85de4fc 100644
--- a/chromium/components/quirks/quirks_manager.h
+++ b/chromium/components/quirks/quirks_manager.h
@@ -78,7 +78,6 @@ class QUIRKS_EXPORT QuirksManager {
static void Initialize(
std::unique_ptr<Delegate> delegate,
- scoped_refptr<base::TaskRunner> task_runner,
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> url_context_getter);
static void Shutdown();
@@ -118,7 +117,6 @@ class QUIRKS_EXPORT QuirksManager {
private:
QuirksManager(std::unique_ptr<Delegate> delegate,
- scoped_refptr<base::TaskRunner> task_runner,
PrefService* local_state,
scoped_refptr<net::URLRequestContextGetter> url_context_getter);
~QuirksManager();
diff --git a/chromium/components/rappor/public/interfaces/BUILD.gn b/chromium/components/rappor/public/interfaces/BUILD.gn
index 1c9a554265a..2a1614295a6 100644
--- a/chromium/components/rappor/public/interfaces/BUILD.gn
+++ b/chromium/components/rappor/public/interfaces/BUILD.gn
@@ -10,6 +10,6 @@ mojom("interfaces") {
]
public_deps = [
- "//url/mojo:url_mojom_gurl",
+ "//url/mojom:url_mojom_gurl",
]
}
diff --git a/chromium/components/rappor/public/interfaces/rappor_recorder.mojom b/chromium/components/rappor/public/interfaces/rappor_recorder.mojom
index 38647b45154..60a270d1111 100644
--- a/chromium/components/rappor/public/interfaces/rappor_recorder.mojom
+++ b/chromium/components/rappor/public/interfaces/rappor_recorder.mojom
@@ -4,7 +4,7 @@
module rappor.mojom;
-import "url/mojo/url.mojom";
+import "url/mojom/url.mojom";
// Records aggregate, privacy-preserving samples from the renderers.
// See: https://www.chromium.org/developers/design-documents/rappor
diff --git a/chromium/components/rappor/rappor_recorder_impl.cc b/chromium/components/rappor/rappor_recorder_impl.cc
index 52a281138fd..1b4634c9dda 100644
--- a/chromium/components/rappor/rappor_recorder_impl.cc
+++ b/chromium/components/rappor/rappor_recorder_impl.cc
@@ -4,7 +4,8 @@
#include "components/rappor/rappor_recorder_impl.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "components/rappor/public/rappor_utils.h"
#include "components/rappor/rappor_service_impl.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -20,7 +21,7 @@ RapporRecorderImpl::~RapporRecorderImpl() = default;
void RapporRecorderImpl::Create(
RapporServiceImpl* rappor_service,
mojom::RapporRecorderRequest request) {
- mojo::MakeStrongBinding(base::MakeUnique<RapporRecorderImpl>(rappor_service),
+ mojo::MakeStrongBinding(std::make_unique<RapporRecorderImpl>(rappor_service),
std::move(request));
}
diff --git a/chromium/components/rappor/rappor_service_impl.cc b/chromium/components/rappor/rappor_service_impl.cc
index 9e8891aac62..36322838617 100644
--- a/chromium/components/rappor/rappor_service_impl.cc
+++ b/chromium/components/rappor/rappor_service_impl.cc
@@ -4,9 +4,9 @@
#include "components/rappor/rappor_service_impl.h"
+#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "base/metrics/metrics_hashes.h"
#include "base/time/time.h"
#include "components/rappor/log_uploader.h"
@@ -64,7 +64,7 @@ void RapporServiceImpl::Initialize(
}
DVLOG(1) << "RapporServiceImpl reporting to " << server_url.spec();
InitializeInternal(
- base::MakeUnique<LogUploader>(server_url, kMimeType, request_context),
+ std::make_unique<LogUploader>(server_url, kMimeType, request_context),
internal::LoadCohort(pref_service_), internal::LoadSecret(pref_service_));
}
diff --git a/chromium/components/reading_list/core/reading_list_model_storage.h b/chromium/components/reading_list/core/reading_list_model_storage.h
index 5edc30d08d9..9e29547372d 100644
--- a/chromium/components/reading_list/core/reading_list_model_storage.h
+++ b/chromium/components/reading_list/core/reading_list_model_storage.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_READING_LIST_CORE_READING_LIST_MODEL_STORAGE_H_
#define COMPONENTS_READING_LIST_CORE_READING_LIST_MODEL_STORAGE_H_
+#include <memory>
#include <vector>
#include "base/macros.h"
@@ -37,7 +38,7 @@ class ReadingListModelStorage : public syncer::ModelTypeSyncBridge {
// Sets the model the Storage is backing.
// This will trigger store initalization and load persistent entries.
// Pass the |clock| from the |model| to ensure synchroization when loading
- // entries.
+ // entries. Must be called no more than once.
virtual void SetReadingListModel(ReadingListModel* model,
ReadingListStoreDelegate* delegate,
base::Clock* clock) = 0;
diff --git a/chromium/components/reading_list/core/reading_list_store.cc b/chromium/components/reading_list/core/reading_list_store.cc
index 6a4412af9ee..62fbb31c955 100644
--- a/chromium/components/reading_list/core/reading_list_store.cc
+++ b/chromium/components/reading_list/core/reading_list_store.cc
@@ -22,10 +22,10 @@
#include "components/sync/protocol/model_type_state.pb.h"
ReadingListStore::ReadingListStore(
- StoreFactoryFunction create_store_callback,
+ syncer::OnceModelTypeStoreFactory create_store_callback,
const ChangeProcessorFactory& change_processor_factory)
: ReadingListModelStorage(change_processor_factory, syncer::READING_LIST),
- create_store_callback_(create_store_callback),
+ create_store_callback_(std::move(create_store_callback)),
pending_transaction_count_(0) {}
ReadingListStore::~ReadingListStore() {
@@ -40,9 +40,10 @@ void ReadingListStore::SetReadingListModel(ReadingListModel* model,
model_ = model;
delegate_ = delegate;
clock_ = clock;
- create_store_callback_.Run(
- syncer::READING_LIST,
- base::Bind(&ReadingListStore::OnStoreCreated, base::AsWeakPtr(this)));
+ std::move(create_store_callback_)
+ .Run(syncer::READING_LIST,
+ base::BindOnce(&ReadingListStore::OnStoreCreated,
+ base::AsWeakPtr(this)));
}
std::unique_ptr<ReadingListModelStorage::ScopedBatchUpdate>
@@ -122,12 +123,11 @@ void ReadingListStore::RemoveEntry(const ReadingListEntry& entry) {
}
void ReadingListStore::OnDatabaseLoad(
- syncer::ModelTypeStore::Result result,
+ const base::Optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore::RecordList> entries) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (result != syncer::ModelTypeStore::Result::SUCCESS) {
- change_processor()->ReportError(FROM_HERE,
- "Cannot load Reading List Database.");
+ if (error) {
+ change_processor()->ReportError(*error);
return;
}
auto loaded_entries =
@@ -158,25 +158,26 @@ void ReadingListStore::OnDatabaseLoad(
}
void ReadingListStore::OnReadAllMetadata(
- base::Optional<syncer::ModelError> error,
+ const base::Optional<syncer::ModelError>& error,
std::unique_ptr<syncer::MetadataBatch> metadata_batch) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (error) {
- change_processor()->ReportError(FROM_HERE, "Failed to read metadata.");
+ change_processor()->ReportError({FROM_HERE, "Failed to read metadata."});
} else {
change_processor()->ModelReadyToSync(std::move(metadata_batch));
}
}
-void ReadingListStore::OnDatabaseSave(syncer::ModelTypeStore::Result result) {
+void ReadingListStore::OnDatabaseSave(
+ const base::Optional<syncer::ModelError>& error) {
return;
}
void ReadingListStore::OnStoreCreated(
- syncer::ModelTypeStore::Result result,
+ const base::Optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore> store) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (result != syncer::ModelTypeStore::Result::SUCCESS) {
+ if (error) {
// TODO(crbug.com/664926): handle store creation error.
return;
}
diff --git a/chromium/components/reading_list/core/reading_list_store.h b/chromium/components/reading_list/core/reading_list_store.h
index e321e1e7ba0..71813505a11 100644
--- a/chromium/components/reading_list/core/reading_list_store.h
+++ b/chromium/components/reading_list/core/reading_list_store.h
@@ -22,12 +22,8 @@ class ReadingListModel;
// A ReadingListModelStorage storing and syncing data in protobufs.
class ReadingListStore : public ReadingListModelStorage {
- using StoreFactoryFunction = base::Callback<void(
- syncer::ModelType type,
- const syncer::ModelTypeStore::InitCallback& callback)>;
-
public:
- ReadingListStore(StoreFactoryFunction create_store_callback,
+ ReadingListStore(syncer::OnceModelTypeStoreFactory create_store_callback,
const ChangeProcessorFactory& change_processor_factory);
~ReadingListStore() override;
@@ -129,7 +125,7 @@ class ReadingListStore : public ReadingListModelStorage {
std::string GetStorageKey(const syncer::EntityData& entity_data) override;
// Methods used as callbacks given to DataTypeStore.
- void OnStoreCreated(syncer::ModelTypeStore::Result result,
+ void OnStoreCreated(const base::Optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore> store);
class ScopedBatchUpdate : public ReadingListModelStorage::ScopedBatchUpdate {
@@ -149,10 +145,10 @@ class ReadingListStore : public ReadingListModelStorage {
void CommitTransaction();
// Callbacks needed for the database handling.
void OnDatabaseLoad(
- syncer::ModelTypeStore::Result result,
+ const base::Optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore::RecordList> entries);
- void OnDatabaseSave(syncer::ModelTypeStore::Result result);
- void OnReadAllMetadata(base::Optional<syncer::ModelError> error,
+ void OnDatabaseSave(const base::Optional<syncer::ModelError>& error);
+ void OnReadAllMetadata(const base::Optional<syncer::ModelError>& error,
std::unique_ptr<syncer::MetadataBatch> metadata_batch);
void AddEntryToBatch(syncer::MutableDataBatch* batch,
@@ -161,7 +157,7 @@ class ReadingListStore : public ReadingListModelStorage {
std::unique_ptr<syncer::ModelTypeStore> store_;
ReadingListModel* model_;
ReadingListStoreDelegate* delegate_;
- StoreFactoryFunction create_store_callback_;
+ syncer::OnceModelTypeStoreFactory create_store_callback_;
int pending_transaction_count_;
std::unique_ptr<syncer::ModelTypeStore::WriteBatch> batch_;
diff --git a/chromium/components/reading_list/core/reading_list_store_unittest.cc b/chromium/components/reading_list/core/reading_list_store_unittest.cc
index 84f2fad9212..7282617333d 100644
--- a/chromium/components/reading_list/core/reading_list_store_unittest.cc
+++ b/chromium/components/reading_list/core/reading_list_store_unittest.cc
@@ -6,6 +6,7 @@
#include <map>
#include <set>
+#include <utility>
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
@@ -91,8 +92,8 @@ class ReadingListStoreTest : public testing::Test,
: store_(syncer::ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()) {
ClearState();
reading_list_store_ = std::make_unique<ReadingListStore>(
- base::Bind(&syncer::ModelTypeStoreTestUtil::MoveStoreToCallback,
- base::Passed(&store_)),
+ base::BindOnce(&syncer::ModelTypeStoreTestUtil::MoveStoreToCallback,
+ std::move(store_)),
base::Bind(&ReadingListStoreTest::CreateModelTypeChangeProcessor,
base::Unretained(this)));
auto clock = std::make_unique<base::SimpleTestClock>();
diff --git a/chromium/components/reading_list/features/BUILD.gn b/chromium/components/reading_list/features/BUILD.gn
index 948c8be01fd..d31dd8e4dcf 100644
--- a/chromium/components/reading_list/features/BUILD.gn
+++ b/chromium/components/reading_list/features/BUILD.gn
@@ -1,8 +1,8 @@
import("//build/buildflag_header.gni")
import("//components/reading_list/features/reading_list.gni")
-buildflag_header("reading_list_enable_flags") {
- header = "reading_list_enable_flags.h"
+buildflag_header("reading_list_buildflags") {
+ header = "reading_list_buildflags.h"
_enabled = is_ios && enable_reading_list
flags = [ "ENABLE_READING_LIST=$_enabled" ]
}
@@ -16,6 +16,6 @@ source_set("flags") {
"//base",
]
public_deps = [
- "//components/reading_list/features:reading_list_enable_flags",
+ "//components/reading_list/features:reading_list_buildflags",
]
}
diff --git a/chromium/components/reading_list/features/reading_list_switches.cc b/chromium/components/reading_list/features/reading_list_switches.cc
index 93007e1c045..a7b7d890646 100644
--- a/chromium/components/reading_list/features/reading_list_switches.cc
+++ b/chromium/components/reading_list/features/reading_list_switches.cc
@@ -6,7 +6,7 @@
#include "base/command_line.h"
#include "build/build_config.h"
-#include "components/reading_list/features/reading_list_enable_flags.h"
+#include "components/reading_list/features/reading_list_buildflags.h"
namespace reading_list {
namespace switches {
diff --git a/chromium/components/renderer_context_menu/context_menu_delegate.cc b/chromium/components/renderer_context_menu/context_menu_delegate.cc
index c9957792dac..fd6e69789e5 100644
--- a/chromium/components/renderer_context_menu/context_menu_delegate.cc
+++ b/chromium/components/renderer_context_menu/context_menu_delegate.cc
@@ -4,7 +4,8 @@
#include "components/renderer_context_menu/context_menu_delegate.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "content/public/browser/web_contents.h"
namespace {
@@ -27,7 +28,7 @@ class ContextMenuDelegateUserData : public base::SupportsUserData::Data {
ContextMenuDelegate::ContextMenuDelegate(content::WebContents* web_contents) {
web_contents->SetUserData(
&kMenuDelegateUserDataKey,
- base::MakeUnique<ContextMenuDelegateUserData>(this));
+ std::make_unique<ContextMenuDelegateUserData>(this));
}
ContextMenuDelegate::~ContextMenuDelegate() {
diff --git a/chromium/components/resources/BUILD.gn b/chromium/components/resources/BUILD.gn
index af21090adf5..ad5cec8d455 100644
--- a/chromium/components/resources/BUILD.gn
+++ b/chromium/components/resources/BUILD.gn
@@ -19,8 +19,6 @@ group("resources") {
grit("components_resources") {
source = "components_resources.grd"
- # TODO(hashimoto): Remove this line.
- output_name = "components_resources_new"
outputs = [
"grit/components_resources.h",
"components_resources.pak",
@@ -44,8 +42,6 @@ grit("components_resources") {
grit("components_scaled_resources") {
source = "components_scaled_resources.grd"
- # TODO(hashimoto): Remove this line.
- output_name = "components_scaled_resources_new"
outputs = [
"grit/components_scaled_resources.h",
"grit/components_scaled_resources_map.cc",
diff --git a/chromium/components/resources/dom_distiller_resources.grdp b/chromium/components/resources/dom_distiller_resources.grdp
index d340722c1cd..3c3cc1a1eeb 100644
--- a/chromium/components/resources/dom_distiller_resources.grdp
+++ b/chromium/components/resources/dom_distiller_resources.grdp
@@ -9,9 +9,7 @@
<include name="IDR_DISTILLER_CSS" file="../dom_distiller/core/css/distilledpage.css" type="BINDATA" />
<include name="IDR_DISTILLER_IOS_CSS" file="../dom_distiller/core/css/distilledpage_ios.css" type="BINDATA" />
<include name="IDR_DISTILLER_LOADING_IMAGE" file="../dom_distiller/core/images/dom_distiller_material_spinner.svg" type="BINDATA" />
- <include name="IDR_IS_DISTILLABLE_JS" file="../dom_distiller/core/javascript/is_distillable_trigger.js" type="BINDATA" />
<include name="IDR_EXTRACT_PAGE_FEATURES_JS" file="../dom_distiller/core/javascript/extract_features.js" type="BINDATA" />
- <include name="IDR_DISTILLABLE_PAGE_SERIALIZED_MODEL" file="../dom_distiller/core/data/distillable_page_model.bin" type="BINDATA" />
<include name="IDR_DISTILLABLE_PAGE_SERIALIZED_MODEL_NEW" file="../dom_distiller/core/data/distillable_page_model_new.bin" type="BINDATA" />
<include name="IDR_LONG_PAGE_SERIALIZED_MODEL" file="../dom_distiller/core/data/long_page_model.bin" type="BINDATA" />
</grit-part>
diff --git a/chromium/components/resources/security_interstitials_resources.grdp b/chromium/components/resources/security_interstitials_resources.grdp
index 4d72526b941..1ca9152b042 100644
--- a/chromium/components/resources/security_interstitials_resources.grdp
+++ b/chromium/components/resources/security_interstitials_resources.grdp
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
+ <include name="IDR_SECURITY_INTERSTITIAL_COMMON_CSS" file="../security_interstitials/core/common/resources/interstitial_common.css" type="BINDATA" />
+ <include name="IDR_SECURITY_INTERSTITIAL_CORE_CSS" file="../security_interstitials/core/common/resources/interstitial_core.css" type="BINDATA" />
<include name="IDR_SECURITY_INTERSTITIAL_UI_HTML" file="../security_interstitials/core/browser/resources/list_of_interstitials.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_SECURITY_INTERSTITIAL_HTML" file="../security_interstitials/core/browser/resources/interstitial_large.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_SECURITY_INTERSTITIAL_QUIET_HTML" file="../security_interstitials/core/browser/resources/interstitial_webview_quiet.html" flattenhtml="true" type="BINDATA" />
diff --git a/chromium/components/safe_browsing/OWNERS b/chromium/components/safe_browsing/OWNERS
index 51a1ca118dc..3f03255af9e 100644
--- a/chromium/components/safe_browsing/OWNERS
+++ b/chromium/components/safe_browsing/OWNERS
@@ -5,7 +5,4 @@ vakh@chromium.org
# For componentization
timvolodine@chromium.org
-per-file *resource_throttle*=yzshen@chromium.org
-per-file *url_loader_throttle*=yzshen@chromium.org
-
# COMPONENT: Services>Safebrowsing
diff --git a/chromium/components/safe_browsing/android/remote_database_manager.cc b/chromium/components/safe_browsing/android/remote_database_manager.cc
index f936a492ced..78d39f83422 100644
--- a/chromium/components/safe_browsing/android/remote_database_manager.cc
+++ b/chromium/components/safe_browsing/android/remote_database_manager.cc
@@ -5,6 +5,7 @@
#include "components/safe_browsing/android/remote_database_manager.h"
#include <memory>
+#include <utility>
#include <vector>
#include "base/metrics/histogram_macros.h"
@@ -203,9 +204,11 @@ bool RemoteSafeBrowsingDatabaseManager::CheckBrowseUrl(
// SubresourceFilterSafeBrowsingActivationThrottle check IsSupported()
// earlier.
DCHECK(api_handler) << "SafeBrowsingApiHandler was never constructed";
- api_handler->StartURLCheck(
- base::Bind(&ClientRequest::OnRequestDoneWeak, req->GetWeakPtr()), url,
- threat_types);
+
+ auto callback =
+ std::make_unique<SafeBrowsingApiHandler::URLCheckCallbackMeta>(
+ base::BindOnce(&ClientRequest::OnRequestDoneWeak, req->GetWeakPtr()));
+ api_handler->StartURLCheck(std::move(callback), url, threat_types);
current_requests_.push_back(req.release());
@@ -250,8 +253,11 @@ bool RemoteSafeBrowsingDatabaseManager::CheckUrlForSubresourceFilter(
// SubresourceFilterSafeBrowsingActivationThrottle check IsSupported()
// earlier.
DCHECK(api_handler) << "SafeBrowsingApiHandler was never constructed";
+ auto callback =
+ std::make_unique<SafeBrowsingApiHandler::URLCheckCallbackMeta>(
+ base::BindOnce(&ClientRequest::OnRequestDoneWeak, req->GetWeakPtr()));
api_handler->StartURLCheck(
- base::Bind(&ClientRequest::OnRequestDoneWeak, req->GetWeakPtr()), url,
+ std::move(callback), url,
CreateSBThreatTypeSet(
{SB_THREAT_TYPE_SUBRESOURCE_FILTER, SB_THREAT_TYPE_URL_PHISHING}));
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 b8c58354df4..c73ae08ed37 100644
--- a/chromium/components/safe_browsing/android/remote_database_manager_unittest.cc
+++ b/chromium/components/safe_browsing/android/remote_database_manager_unittest.cc
@@ -4,6 +4,7 @@
#include "components/safe_browsing/android/remote_database_manager.h"
+#include <map>
#include <memory>
#include "base/logging.h"
@@ -22,7 +23,7 @@ namespace {
class TestSafeBrowsingApiHandler : public SafeBrowsingApiHandler {
public:
- void StartURLCheck(const URLCheckCallbackMeta& callback,
+ void StartURLCheck(std::unique_ptr<URLCheckCallbackMeta> callback,
const GURL& url,
const SBThreatTypeSet& threat_types) override {}
};
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 c2aa238da4d..b608627431f 100644
--- a/chromium/components/safe_browsing/android/safe_browsing_api_handler.h
+++ b/chromium/components/safe_browsing/android/safe_browsing_api_handler.h
@@ -8,6 +8,7 @@
#ifndef COMPONENTS_SAFE_BROWSING_ANDROID_SAFE_BROWSING_API_HANDLER_H_
#define COMPONENTS_SAFE_BROWSING_ANDROID_SAFE_BROWSING_API_HANDLER_H_
+#include <memory>
#include <string>
#include <vector>
@@ -24,12 +25,12 @@ class SafeBrowsingApiHandler {
static void SetInstance(SafeBrowsingApiHandler* instance);
static SafeBrowsingApiHandler* GetInstance();
- typedef base::Callback<void(SBThreatType sb_threat_type,
- const ThreatMetadata& metadata)>
+ typedef base::OnceCallback<void(SBThreatType sb_threat_type,
+ const ThreatMetadata& metadata)>
URLCheckCallbackMeta;
// Makes Native->Java call and invokes callback when check is done.
- virtual void StartURLCheck(const URLCheckCallbackMeta& callback,
+ virtual void StartURLCheck(std::unique_ptr<URLCheckCallbackMeta> callback,
const GURL& url,
const SBThreatTypeSet& threat_types) = 0;
diff --git a/chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc b/chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc
index 39efccbb971..2d798650d2c 100644
--- a/chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc
+++ b/chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc
@@ -6,6 +6,7 @@
#include <memory>
#include <string>
+#include <utility>
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
@@ -16,6 +17,9 @@
#include "base/metrics/histogram_macros.h"
#include "base/task_scheduler/post_task.h"
#include "base/task_scheduler/task_traits.h"
+#include "base/threading/scoped_blocking_call.h"
+#include "base/time/time.h"
+#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "components/safe_browsing/android/safe_browsing_api_handler_util.h"
#include "components/safe_browsing/db/v4_protocol_manager_util.h"
@@ -35,11 +39,12 @@ namespace safe_browsing {
namespace {
void RunCallbackOnIOThread(
- const SafeBrowsingApiHandler::URLCheckCallbackMeta& callback,
+ std::unique_ptr<SafeBrowsingApiHandler::URLCheckCallbackMeta> callback,
SBThreatType threat_type,
const ThreatMetadata& metadata) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(callback, threat_type, metadata));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(std::move(*callback), threat_type, metadata));
}
void ReportUmaResult(safe_browsing::UmaRemoteCallResult result) {
@@ -68,7 +73,7 @@ int SBThreatTypeToJavaThreatType(const SBThreatType& sb_threat_type) {
ScopedJavaLocalRef<jintArray> SBThreatTypeSetToJavaArray(
JNIEnv* env,
const SBThreatTypeSet& threat_types) {
- DCHECK(threat_types.size() > 0);
+ DCHECK_LT(0u, threat_types.size());
int int_threat_types[threat_types.size()];
int* itr = &int_threat_types[0];
for (auto threat_type : threat_types) {
@@ -120,14 +125,16 @@ void JNI_SafeBrowsingApiBridge_OnUrlCheckDone(
DCHECK_EQ(result_status, RESULT_STATUS_INTERNAL_ERROR);
ReportUmaResult(UMA_STATUS_INTERNAL_ERROR);
}
- RunCallbackOnIOThread(*callback, SB_THREAT_TYPE_SAFE, ThreatMetadata());
+ RunCallbackOnIOThread(std::move(callback), SB_THREAT_TYPE_SAFE,
+ ThreatMetadata());
return;
}
// Shortcut for safe, so we don't have to parse JSON.
if (metadata_str == "{}") {
ReportUmaResult(UMA_STATUS_SAFE);
- RunCallbackOnIOThread(*callback, SB_THREAT_TYPE_SAFE, ThreatMetadata());
+ RunCallbackOnIOThread(std::move(callback), SB_THREAT_TYPE_SAFE,
+ ThreatMetadata());
} else {
// Unsafe, assuming we can parse the JSON.
SBThreatType worst_threat;
@@ -138,7 +145,7 @@ void JNI_SafeBrowsingApiBridge_OnUrlCheckDone(
DVLOG(1) << "Check " << callback_id << " was a MATCH";
}
- RunCallbackOnIOThread(*callback, worst_threat, threat_metadata);
+ RunCallbackOnIOThread(std::move(callback), worst_threat, threat_metadata);
}
}
@@ -162,7 +169,7 @@ void SafeBrowsingApiHandlerBridge::Initialize() {
}
void SafeBrowsingApiHandlerBridge::StartURLCheck(
- const SafeBrowsingApiHandler::URLCheckCallbackMeta& callback,
+ std::unique_ptr<SafeBrowsingApiHandler::URLCheckCallbackMeta> callback,
const GURL& url,
const SBThreatTypeSet& threat_types) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -179,7 +186,7 @@ void SafeBrowsingApiHandlerBridge::StartURLCheck(
// >100ms, so use base::MayBlock even though we aren't technically doing
// blocking IO.
if (!api_task_runner_) {
- core_->StartURLCheck(callback, url, threat_types);
+ core_->StartURLCheck(std::move(callback), url, threat_types);
return;
}
// Unretained is safe because the task to delete |core_| will be sequenced
@@ -187,7 +194,7 @@ void SafeBrowsingApiHandlerBridge::StartURLCheck(
api_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&SafeBrowsingApiHandlerBridge::Core::StartURLCheck,
- base::Unretained(core_.get()), callback, url,
+ base::Unretained(core_.get()), std::move(callback), url,
threat_types));
}
@@ -211,7 +218,7 @@ bool SafeBrowsingApiHandlerBridge::Core::CheckApiIsSupported() {
}
void SafeBrowsingApiHandlerBridge::Core::StartURLCheck(
- const URLCheckCallbackMeta& callback,
+ std::unique_ptr<URLCheckCallbackMeta> callback,
const GURL& url,
const SBThreatTypeSet& threat_types) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -220,14 +227,16 @@ void SafeBrowsingApiHandlerBridge::Core::StartURLCheck(
if (!CheckApiIsSupported()) {
// Mark all requests as safe. Only users who have an old, broken GMSCore or
// have sideloaded Chrome w/o PlayStore should land here.
- RunCallbackOnIOThread(callback, SB_THREAT_TYPE_SAFE, ThreatMetadata());
+ RunCallbackOnIOThread(std::move(callback), SB_THREAT_TYPE_SAFE,
+ ThreatMetadata());
ReportUmaResult(UMA_STATUS_UNSUPPORTED);
return;
}
- // Make copy on the heap so we can pass the pointer through JNI.
- intptr_t callback_id =
- reinterpret_cast<intptr_t>(new URLCheckCallbackMeta(callback));
+ // Save the address on the heap so we can pass it through JNI. The unique ptr
+ // releases ownership, we will re-own this callback when the response is
+ // received in JNI_SafeBrowsingApiBridge_OnUrlCheckDone.
+ intptr_t callback_id = reinterpret_cast<intptr_t>(callback.release());
DVLOG(1) << "Starting check " << callback_id << " for URL " << url;
@@ -238,8 +247,15 @@ void SafeBrowsingApiHandlerBridge::Core::StartURLCheck(
ScopedJavaLocalRef<jintArray> j_threat_types =
SBThreatTypeSetToJavaArray(env, threat_types);
+ // Increase parallelism by indicating that the lookup may block. Only the long
+ // tail of these calls block for more than 10ms, which is the current
+ // threshold for increasing worker capacity.
+ base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
+ base::ElapsedTimer check_timer;
Java_SafeBrowsingApiBridge_startUriLookup(env, j_api_handler_, callback_id,
j_url, j_threat_types);
+ UMA_HISTOGRAM_COUNTS_10M("SB2.RemoteCall.CheckDispatchTime",
+ check_timer.Elapsed().InMicroseconds());
}
} // namespace safe_browsing
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 b545128a109..8794fea9811 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
@@ -29,7 +29,7 @@ class SafeBrowsingApiHandlerBridge : public SafeBrowsingApiHandler {
~SafeBrowsingApiHandlerBridge() override;
// Makes Native->Java call to check the URL against Safe Browsing lists.
- void StartURLCheck(const URLCheckCallbackMeta& callback,
+ void StartURLCheck(std::unique_ptr<URLCheckCallbackMeta> callback,
const GURL& url,
const SBThreatTypeSet& threat_types) override;
@@ -43,7 +43,7 @@ class SafeBrowsingApiHandlerBridge : public SafeBrowsingApiHandler {
Core();
~Core();
- void StartURLCheck(const URLCheckCallbackMeta& callback,
+ void StartURLCheck(std::unique_ptr<URLCheckCallbackMeta> callback,
const GURL& url,
const SBThreatTypeSet& threat_types);
diff --git a/chromium/components/safe_browsing/base_blocking_page.cc b/chromium/components/safe_browsing/base_blocking_page.cc
index 3cd89c1d336..1e84e464266 100644
--- a/chromium/components/safe_browsing/base_blocking_page.cc
+++ b/chromium/components/safe_browsing/base_blocking_page.cc
@@ -79,6 +79,7 @@ BaseBlockingPage::CreateDefaultDisplayOptions(
false, // is_off_the_record
false, // is_extended_reporting
false, // is_scout
+ false, // is_sber_policy_managed
false, // kSafeBrowsingProceedAnywayDisabled
false, // should_open_links_in_new_tab
true, // always_show_back_to_safety
diff --git a/chromium/components/safe_browsing/browser/DEPS b/chromium/components/safe_browsing/browser/DEPS
index 65d370926ce..a60e25d1fa3 100644
--- a/chromium/components/safe_browsing/browser/DEPS
+++ b/chromium/components/safe_browsing/browser/DEPS
@@ -9,10 +9,11 @@ include_rules = [
"+net/ssl",
"+net/traffic_annotation",
"+services/network/public/cpp",
+ "+services/service_manager/public/cpp",
]
specific_include_rules = {
".*test\.cc": [
"+content/public/test/test_browser_thread_bundle.h",
],
-} \ No newline at end of file
+}
diff --git a/chromium/components/safe_browsing/browser/base_parallel_resource_throttle.cc b/chromium/components/safe_browsing/browser/base_parallel_resource_throttle.cc
index 36178a924a2..cb064204274 100644
--- a/chromium/components/safe_browsing/browser/base_parallel_resource_throttle.cc
+++ b/chromium/components/safe_browsing/browser/base_parallel_resource_throttle.cc
@@ -32,7 +32,8 @@ class BaseParallelResourceThrottle::URLLoaderThrottleHolder
uint32_t inside_delegate_calls() const { return inside_delegate_calls_; }
// content::URLLoaderThrottle::Delegate implementation:
- void CancelWithError(int error_code) override {
+ void CancelWithError(int error_code,
+ base::StringPiece custom_reason) override {
if (!owner_)
return;
diff --git a/chromium/components/safe_browsing/browser/base_parallel_resource_throttle_unittest.cc b/chromium/components/safe_browsing/browser/base_parallel_resource_throttle_unittest.cc
index 9be044fe424..d0a28411b60 100644
--- a/chromium/components/safe_browsing/browser/base_parallel_resource_throttle_unittest.cc
+++ b/chromium/components/safe_browsing/browser/base_parallel_resource_throttle_unittest.cc
@@ -117,6 +117,15 @@ class TestUrlCheckerDelegate : public UrlCheckerDelegate {
bool IsUrlWhitelisted(const GURL& url) override { return false; }
+ bool ShouldSkipRequestCheck(content::ResourceContext* resource_context,
+ const GURL& original_url,
+ int frame_tree_node_id,
+ int render_process_id,
+ int render_frame_id,
+ bool originated_from_service_worker) override {
+ return false;
+ }
+
const SBThreatTypeSet& GetThreatTypes() override { return threat_types_; }
SafeBrowsingDatabaseManager* GetDatabaseManager() override {
return database_manager_.get();
diff --git a/chromium/components/safe_browsing/browser/browser_url_loader_throttle.cc b/chromium/components/safe_browsing/browser/browser_url_loader_throttle.cc
index 2cce3052677..1447b38c849 100644
--- a/chromium/components/safe_browsing/browser/browser_url_loader_throttle.cc
+++ b/chromium/components/safe_browsing/browser/browser_url_loader_throttle.cc
@@ -8,6 +8,7 @@
#include "base/trace_event/trace_event.h"
#include "components/safe_browsing/browser/safe_browsing_url_checker_impl.h"
#include "components/safe_browsing/browser/url_checker_delegate.h"
+#include "components/safe_browsing/common/safebrowsing_constants.h"
#include "components/safe_browsing/common/utils.h"
#include "net/log/net_log_event_type.h"
#include "net/url_request/redirect_info.h"
@@ -141,7 +142,8 @@ void BrowserURLLoaderThrottle::OnCompleteCheck(bool slow_check,
url_checker_.reset();
pending_checks_ = 0;
pending_slow_checks_ = 0;
- delegate_->CancelWithError(net::ERR_ABORTED);
+ delegate_->CancelWithError(net::ERR_ABORTED,
+ kCustomCancelReasonForURLLoader);
}
}
diff --git a/chromium/components/safe_browsing/browser/mojo_safe_browsing_impl.cc b/chromium/components/safe_browsing/browser/mojo_safe_browsing_impl.cc
index 58cac7bcf96..d8e0b323411 100644
--- a/chromium/components/safe_browsing/browser/mojo_safe_browsing_impl.cc
+++ b/chromium/components/safe_browsing/browser/mojo_safe_browsing_impl.cc
@@ -10,6 +10,7 @@
#include "components/safe_browsing/browser/safe_browsing_url_checker_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/resource_context.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/resource_type.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -58,8 +59,13 @@ class CheckUrlCallbackWrapper {
MojoSafeBrowsingImpl::MojoSafeBrowsingImpl(
scoped_refptr<UrlCheckerDelegate> delegate,
- int render_process_id)
- : delegate_(std::move(delegate)), render_process_id_(render_process_id) {
+ int render_process_id,
+ content::ResourceContext* resource_context)
+ : delegate_(std::move(delegate)),
+ render_process_id_(render_process_id),
+ resource_context_(resource_context) {
+ DCHECK(resource_context_);
+
// It is safe to bind |this| as Unretained because |bindings_| is owned by
// |this| and will not call this callback after it is destroyed.
bindings_.set_connection_error_handler(base::Bind(
@@ -73,18 +79,26 @@ MojoSafeBrowsingImpl::~MojoSafeBrowsingImpl() {
// static
void MojoSafeBrowsingImpl::MaybeCreate(
int render_process_id,
+ content::ResourceContext* resource_context,
const base::Callback<UrlCheckerDelegate*()>& delegate_getter,
mojom::SafeBrowsingRequest request) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
scoped_refptr<UrlCheckerDelegate> delegate = delegate_getter.Run();
- if (!delegate || !delegate->GetDatabaseManager()->IsSupported())
+ if (!resource_context || !delegate ||
+ !delegate->GetDatabaseManager()->IsSupported())
return;
- auto* impl = new MojoSafeBrowsingImpl(std::move(delegate), render_process_id);
+ std::unique_ptr<MojoSafeBrowsingImpl> impl(new MojoSafeBrowsingImpl(
+ std::move(delegate), render_process_id, resource_context));
impl->Clone(std::move(request));
- // |impl| will be freed when there are no more pipes bound to it.
+
+ // Need to store the value of |impl.get()| in a temp variable instead of
+ // getting the value on the same line as |std::move(impl)|, because the
+ // evalution order is unspecified.
+ const void* key = impl.get();
+ resource_context->SetUserData(key, std::move(impl));
}
void MojoSafeBrowsingImpl::CreateCheckerAndCheck(
@@ -96,8 +110,19 @@ void MojoSafeBrowsingImpl::CreateCheckerAndCheck(
int32_t load_flags,
content::ResourceType resource_type,
bool has_user_gesture,
+ bool originated_from_service_worker,
CreateCheckerAndCheckCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ if (delegate_->ShouldSkipRequestCheck(resource_context_, url,
+ -1 /* frame_tree_node_id */,
+ render_process_id_, render_frame_id,
+ originated_from_service_worker)) {
+ // This will drop |request|. The result is that the renderer side will
+ // consider all URLs in the redirect chain of this request as safe.
+ return;
+ }
+
auto checker_impl = std::make_unique<SafeBrowsingUrlCheckerImpl>(
headers, static_cast<int>(load_flags), resource_type, has_user_gesture,
delegate_,
@@ -117,8 +142,10 @@ void MojoSafeBrowsingImpl::Clone(mojom::SafeBrowsingRequest request) {
}
void MojoSafeBrowsingImpl::OnConnectionError() {
- if (bindings_.empty())
- delete this;
+ if (bindings_.empty()) {
+ resource_context_->RemoveUserData(this);
+ // This object is destroyed.
+ }
}
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/browser/mojo_safe_browsing_impl.h b/chromium/components/safe_browsing/browser/mojo_safe_browsing_impl.h
index e246f62fc82..e627f1ded72 100644
--- a/chromium/components/safe_browsing/browser/mojo_safe_browsing_impl.h
+++ b/chromium/components/safe_browsing/browser/mojo_safe_browsing_impl.h
@@ -7,27 +7,37 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/supports_user_data.h"
#include "components/safe_browsing/browser/url_checker_delegate.h"
#include "components/safe_browsing/common/safe_browsing.mojom.h"
#include "ipc/ipc_message.h"
#include "mojo/public/cpp/bindings/binding_set.h"
+namespace content {
+class ResourceContext;
+}
+
namespace safe_browsing {
// This class implements the Mojo interface for renderers to perform
// SafeBrowsing URL checks.
-class MojoSafeBrowsingImpl : public mojom::SafeBrowsing {
+// A MojoSafeBrowsingImpl instance is destructed when the Mojo message pipe is
+// disconnected or |resource_context_| is destructed.
+class MojoSafeBrowsingImpl : public mojom::SafeBrowsing,
+ public base::SupportsUserData::Data {
public:
~MojoSafeBrowsingImpl() override;
static void MaybeCreate(
int render_process_id,
+ content::ResourceContext* resource_context,
const base::Callback<UrlCheckerDelegate*()>& delegate_getter,
mojom::SafeBrowsingRequest request);
private:
MojoSafeBrowsingImpl(scoped_refptr<UrlCheckerDelegate> delegate,
- int render_process_id);
+ int render_process_id,
+ content::ResourceContext* resource_context);
// mojom::SafeBrowsing implementation.
void CreateCheckerAndCheck(int32_t render_frame_id,
@@ -38,6 +48,7 @@ class MojoSafeBrowsingImpl : public mojom::SafeBrowsing {
int32_t load_flags,
content::ResourceType resource_type,
bool has_user_gesture,
+ bool originated_from_service_worker,
CreateCheckerAndCheckCallback callback) override;
void Clone(mojom::SafeBrowsingRequest request) override;
@@ -47,6 +58,10 @@ class MojoSafeBrowsingImpl : public mojom::SafeBrowsing {
scoped_refptr<UrlCheckerDelegate> delegate_;
int render_process_id_ = MSG_ROUTING_NONE;
+ // Not owned by this object. It is always valid during the lifetime of this
+ // object.
+ content::ResourceContext* resource_context_;
+
DISALLOW_COPY_AND_ASSIGN(MojoSafeBrowsingImpl);
};
diff --git a/chromium/components/safe_browsing/browser/threat_details.cc b/chromium/components/safe_browsing/browser/threat_details.cc
index 901b2b1600f..d33cbfb7f2d 100644
--- a/chromium/components/safe_browsing/browser/threat_details.cc
+++ b/chromium/components/safe_browsing/browser/threat_details.cc
@@ -9,6 +9,7 @@
#include <stddef.h>
#include <stdint.h>
#include <unordered_set>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -19,7 +20,6 @@
#include "components/safe_browsing/base_ui_manager.h"
#include "components/safe_browsing/browser/threat_details_cache.h"
#include "components/safe_browsing/browser/threat_details_history.h"
-#include "components/safe_browsing/common/safebrowsing_messages.h"
#include "components/safe_browsing/db/hit_report.h"
#include "components/safe_browsing/features.h"
#include "components/safe_browsing/web_ui/safe_browsing_ui.h"
@@ -30,6 +30,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
using content::BrowserThread;
using content::NavigationEntry;
@@ -197,11 +198,11 @@ void TrimElements(const std::set<int> target_ids,
}
// Take a second pass and determine which element IDs to keep. We want to keep
- // both siblings and children of the target ids. We start by identifying the
- // siblings by finding the common parent of each target element, and keeping
- // all of its children (ie: the siblings of the target elements).
+ // the immediate parent, the siblings, and the children of the target ids.
+ // By keeping the parent of the target and all of its children, this covers
+ // the target's siblings as well.
std::vector<int> ids_to_keep;
- // Keep track of ids that were kept to avoid duplicated. We still need the
+ // Keep track of ids that were kept to avoid duplication. We still need the
// vector above for handling the children where it is used like a queue.
std::unordered_set<int> kept_ids;
for (int target_id : target_ids) {
@@ -213,12 +214,12 @@ void TrimElements(const std::set<int> target_ids,
return;
}
- const HTMLElement* parent_element = elements_by_id[parent_id];
- for (int sibling_id : parent_element->child_ids()) {
- if (kept_ids.count(sibling_id) == 0) {
- ids_to_keep.push_back(sibling_id);
- kept_ids.insert(sibling_id);
- }
+ // Otherwise, insert the parent ID into the list of ids to keep. This will
+ // capture the parent and siblings of the target element, as well as each of
+ // their children.
+ if (kept_ids.count(parent_id) == 0) {
+ ids_to_keep.push_back(parent_id);
+ kept_ids.insert(parent_id);
}
}
@@ -350,17 +351,6 @@ ThreatDetails::~ThreatDetails() {
DCHECK(all_done_expected_ == is_all_done_);
}
-bool ThreatDetails::OnMessageReceived(const IPC::Message& message,
- RenderFrameHost* render_frame_host) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ThreatDetails, message, render_frame_host)
- IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_ThreatDOMDetails,
- OnReceivedThreatDOMDetails)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
bool ThreatDetails::IsReportableUrl(const GURL& url) const {
// TODO(panayiotis): also skip internal urls.
return url.SchemeIs("http") || url.SchemeIs("https");
@@ -445,7 +435,7 @@ void ThreatDetails::AddDomElement(
const int element_node_id,
const std::string& tagname,
const int parent_element_node_id,
- const std::vector<AttributeNameValue>& attributes,
+ const std::vector<mojom::AttributeNameValuePtr> attributes,
const ClientSafeBrowsingReportRequest::Resource* resource) {
// Create the element. It should not exist already since this function should
// only be called once for each element.
@@ -458,10 +448,10 @@ void ThreatDetails::AddDomElement(
if (!tag_name_upper.empty()) {
cur_element->set_tag(tag_name_upper);
}
- for (const AttributeNameValue& attribute : attributes) {
+ for (const mojom::AttributeNameValuePtr& attribute : attributes) {
HTMLElement::Attribute* attribute_pb = cur_element->add_attribute();
- attribute_pb->set_name(attribute.first);
- attribute_pb->set_value(attribute.second);
+ attribute_pb->set_name(std::move(attribute->name));
+ attribute_pb->set_value(std::move(attribute->value));
// Remember which the IDs of elements that represent ads so we can trim the
// report down to just those parts later.
@@ -568,28 +558,39 @@ void ThreatDetails::StartCollection() {
// OnReceivedThreatDOMDetails will be called when the renderer replies.
// TODO(mattm): In theory, if the user proceeds through the warning DOM
// detail collection could be started once the page loads.
- web_contents()->SendToAllFrames(
- new SafeBrowsingMsg_GetThreatDOMDetails(MSG_ROUTING_NONE));
+ web_contents()->ForEachFrame(
+ base::BindRepeating(&ThreatDetails::RequestThreatDOMDetails, this));
}
}
+void ThreatDetails::RequestThreatDOMDetails(content::RenderFrameHost* frame) {
+ safe_browsing::mojom::ThreatReporterPtr threat_reporter;
+ frame->GetRemoteInterfaces()->GetInterface(&threat_reporter);
+ safe_browsing::mojom::ThreatReporter* raw_threat_report =
+ threat_reporter.get();
+ raw_threat_report->GetThreatDOMDetails(
+ base::BindOnce(&ThreatDetails::OnReceivedThreatDOMDetails, this,
+ base::Passed(&threat_reporter), frame));
+}
+
// When the renderer is done, this is called.
void ThreatDetails::OnReceivedThreatDOMDetails(
+ mojom::ThreatReporterPtr threat_reporter,
content::RenderFrameHost* sender,
- const std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node>& params) {
+ std::vector<mojom::ThreatDOMDetailsNodePtr> params) {
// Lookup the FrameTreeNode ID of any child frames in the list of DOM nodes.
const int sender_process_id = sender->GetProcess()->GetID();
const int sender_frame_tree_node_id = sender->GetFrameTreeNodeId();
KeyToFrameTreeIdMap child_frame_tree_map;
- for (const SafeBrowsingHostMsg_ThreatDOMDetails_Node& node : params) {
- if (node.child_frame_routing_id == 0)
+ for (const mojom::ThreatDOMDetailsNodePtr& node : params) {
+ if (node->child_frame_routing_id == 0)
continue;
const std::string cur_element_key =
- GetElementKey(sender_frame_tree_node_id, node.node_id);
+ GetElementKey(sender_frame_tree_node_id, node->node_id);
int child_frame_tree_node_id =
content::RenderFrameHost::GetFrameTreeNodeIdForRoutingId(
- sender_process_id, node.child_frame_routing_id);
+ sender_process_id, node->child_frame_routing_id);
if (child_frame_tree_node_id ==
content::RenderFrameHost::kNoFrameTreeNodeId) {
ambiguous_dom_ = true;
@@ -602,13 +603,14 @@ void ThreatDetails::OnReceivedThreatDOMDetails(
// of our data structures (eg GetSerializedReport).
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ThreatDetails::AddDOMDetails, this, sender_frame_tree_node_id,
- params, child_frame_tree_map));
+ base::BindOnce(&ThreatDetails::AddDOMDetails, this,
+ sender_frame_tree_node_id, std::move(params),
+ child_frame_tree_map));
}
void ThreatDetails::AddDOMDetails(
const int frame_tree_node_id,
- const std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node>& params,
+ std::vector<mojom::ThreatDOMDetailsNodePtr> params,
const KeyToFrameTreeIdMap& child_frame_tree_map) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "Nodes from the DOM: " << params.size();
@@ -635,7 +637,7 @@ void ThreatDetails::AddDOMDetails(
// bogus messages, so limit the number of nodes we accept.
// Also update |elements_| with the DOM structure.
for (size_t i = 0; i < params.size() && i < kMaxDomNodes; ++i) {
- SafeBrowsingHostMsg_ThreatDOMDetails_Node node = params[i];
+ mojom::ThreatDOMDetailsNode& node = *params[i];
DVLOG(1) << node.url << ", " << node.tag_name << ", " << node.parent;
ClientSafeBrowsingReportRequest::Resource* resource = nullptr;
if (!node.url.is_empty()) {
@@ -644,7 +646,7 @@ void ThreatDetails::AddDOMDetails(
// Check for a tag_name to avoid adding the summary node to the DOM.
if (!node.tag_name.empty()) {
AddDomElement(frame_tree_node_id, node.node_id, node.tag_name,
- node.parent_node_id, node.attributes, resource);
+ node.parent_node_id, std::move(node.attributes), resource);
}
}
}
@@ -766,9 +768,9 @@ void ThreatDetails::OnCacheCollectionReady() {
BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
- base::Bind(&WebUIInfoSingleton::AddToReportsSent,
- base::Unretained(WebUIInfoSingleton::GetInstance()),
- base::Passed(&report_)));
+ base::BindOnce(&WebUIInfoSingleton::AddToReportsSent,
+ base::Unretained(WebUIInfoSingleton::GetInstance()),
+ std::move(report_)));
ui_manager_->SendSerializedThreatDetails(serialized);
AllDone();
diff --git a/chromium/components/safe_browsing/browser/threat_details.h b/chromium/components/safe_browsing/browser/threat_details.h
index ac38fa92b7e..257984fbb24 100644
--- a/chromium/components/safe_browsing/browser/threat_details.h
+++ b/chromium/components/safe_browsing/browser/threat_details.h
@@ -20,7 +20,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "components/safe_browsing/common/safebrowsing_types.h"
+#include "components/safe_browsing/common/safe_browsing.mojom.h"
#include "components/safe_browsing/proto/csd.pb.h"
#include "components/security_interstitials/content/unsafe_resource.h"
#include "content/public/browser/browser_thread.h"
@@ -35,8 +35,6 @@ namespace net {
class URLRequestContextGetter;
} // namespace net
-struct SafeBrowsingHostMsg_ThreatDOMDetails_Node;
-
namespace safe_browsing {
class BaseUIManager;
@@ -103,10 +101,6 @@ class ThreatDetails : public base::RefCountedThreadSafe<
void OnRedirectionCollectionReady();
- // content::WebContentsObserver implementation.
- bool OnMessageReceived(const IPC::Message& message,
- content::RenderFrameHost* render_frame_host) override;
-
protected:
friend class ThreatDetailsFactoryImpl;
friend class TestThreatDetailsFactory;
@@ -125,10 +119,9 @@ class ThreatDetails : public base::RefCountedThreadSafe<
~ThreatDetails() override;
// Called on the IO thread with the DOM details.
- virtual void AddDOMDetails(
- const int frame_tree_node_id,
- const std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node>& params,
- const KeyToFrameTreeIdMap& child_frame_tree_map);
+ virtual void AddDOMDetails(const int frame_tree_node_id,
+ std::vector<mojom::ThreatDOMDetailsNodePtr> params,
+ const KeyToFrameTreeIdMap& child_frame_tree_map);
// The report protocol buffer.
std::unique_ptr<ClientSafeBrowsingReportRequest> report_;
@@ -166,10 +159,12 @@ class ThreatDetails : public base::RefCountedThreadSafe<
const std::string& tagname,
const std::vector<GURL>* children);
- // Message handler.
+ void RequestThreatDOMDetails(content::RenderFrameHost* frame);
+
void OnReceivedThreatDOMDetails(
+ mojom::ThreatReporterPtr threat_reporter,
content::RenderFrameHost* sender,
- const std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node>& params);
+ std::vector<mojom::ThreatDOMDetailsNodePtr> params);
void AddRedirectUrlList(const std::vector<GURL>& urls);
@@ -183,7 +178,7 @@ class ThreatDetails : public base::RefCountedThreadSafe<
const int element_node_id,
const std::string& tag_name,
const int parent_element_node_id,
- const std::vector<AttributeNameValue>& attributes,
+ const std::vector<mojom::AttributeNameValuePtr> attributes,
const ClientSafeBrowsingReportRequest::Resource* resource);
// Called when the report is complete. Runs |done_callback_|.
diff --git a/chromium/components/safe_browsing/browser/url_checker_delegate.h b/chromium/components/safe_browsing/browser/url_checker_delegate.h
index d55373b902c..5c3dcc05d88 100644
--- a/chromium/components/safe_browsing/browser/url_checker_delegate.h
+++ b/chromium/components/safe_browsing/browser/url_checker_delegate.h
@@ -12,6 +12,7 @@
#include "components/safe_browsing/db/v4_protocol_manager_util.h"
namespace content {
+class ResourceContext;
class WebContents;
}
@@ -53,6 +54,20 @@ class UrlCheckerDelegate
// the SafeBrowsing database.
virtual bool IsUrlWhitelisted(const GURL& url) = 0;
+ // If the method returns true, the entire request won't be checked, including
+ // the original URL and redirects.
+ // If neither of |render_process_id| and |render_frame_id| is -1, they will be
+ // used to identify the frame making the request; otherwise
+ // |frame_tree_node_id| will be used. Please note that |frame_tree_node_id|
+ // could also be -1, if a request is not associated with a frame.
+ virtual bool ShouldSkipRequestCheck(
+ content::ResourceContext* resource_context,
+ const GURL& original_url,
+ int frame_tree_node_id,
+ int render_process_id,
+ int render_frame_id,
+ bool originated_from_service_worker) = 0;
+
virtual const SBThreatTypeSet& GetThreatTypes() = 0;
virtual SafeBrowsingDatabaseManager* GetDatabaseManager() = 0;
virtual BaseUIManager* GetUIManager() = 0;
diff --git a/chromium/components/safe_browsing/common/BUILD.gn b/chromium/components/safe_browsing/common/BUILD.gn
index 7fc71ce008e..0d963a83820 100644
--- a/chromium/components/safe_browsing/common/BUILD.gn
+++ b/chromium/components/safe_browsing/common/BUILD.gn
@@ -2,18 +2,15 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//chrome/common/features.gni")
import("//mojo/public/tools/bindings/mojom.gni")
source_set("common") {
sources = [
"safebrowsing_constants.cc",
"safebrowsing_constants.h",
- "safebrowsing_message_generator.cc",
- "safebrowsing_message_generator.h",
- "safebrowsing_messages.h",
"safebrowsing_switches.cc",
"safebrowsing_switches.h",
- "safebrowsing_types.h",
"utils.cc",
"utils.h",
]
@@ -35,10 +32,14 @@ static_library("safe_browsing_prefs") {
"safe_browsing_prefs.cc",
"safe_browsing_prefs.h",
]
+
deps = [
"//base:base",
"//components/pref_registry:pref_registry",
"//components/prefs",
+ "//components/safe_browsing:features",
+ "//content/public/browser:browser",
+ "//net:net",
]
}
@@ -52,7 +53,10 @@ source_set("unit_tests") {
"//base:base",
"//base/test:test_support",
"//components/prefs:test_support",
+ "//components/safe_browsing:features",
+ "//content/test:test_support",
"//testing/gtest",
+ "//url:url",
]
}
@@ -63,7 +67,12 @@ mojom("interfaces") {
public_deps = [
"//content/public/common:resource_type_bindings",
- "//services/network/public/interfaces",
- "//url/mojo:url_mojom_gurl",
+ "//services/network/public/mojom",
+ "//url/mojom:url_mojom_gurl",
]
+
+ enabled_features = []
+ if (safe_browsing_mode == 1) {
+ enabled_features += [ "full_safe_browsing" ]
+ }
}
diff --git a/chromium/components/safe_browsing/common/DEPS b/chromium/components/safe_browsing/common/DEPS
index 60d09aaed9f..0e7f7e169f5 100644
--- a/chromium/components/safe_browsing/common/DEPS
+++ b/chromium/components/safe_browsing/common/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+components/pref_registry",
"+components/prefs",
+ "+content/public/test",
"+crypto/sha2.h",
"+ipc",
"+url"
diff --git a/chromium/components/safe_browsing/common/safe_browsing.mojom b/chromium/components/safe_browsing/common/safe_browsing.mojom
index 5b79c1a809e..02c4ca82275 100644
--- a/chromium/components/safe_browsing/common/safe_browsing.mojom
+++ b/chromium/components/safe_browsing/common/safe_browsing.mojom
@@ -5,8 +5,8 @@
module safe_browsing.mojom;
import "content/public/common/resource_type.mojom";
-import "services/network/public/interfaces/http_request_headers.mojom";
-import "url/mojo/url.mojom";
+import "services/network/public/mojom/http_request_headers.mojom";
+import "url/mojom/url.mojom";
// Provided by the browser and used by renderers to perform SafeBrowsing URL
// checks.
@@ -45,9 +45,11 @@ interface SafeBrowsing {
network.mojom.HttpRequestHeaders headers,
int32 load_flags,
content.mojom.ResourceType resource_type,
- bool has_user_gesture) => (UrlCheckNotifier&? slow_check_notifier,
- bool proceed,
- bool showed_interstitial);
+ bool has_user_gesture,
+ bool originated_from_service_worker)
+ => (UrlCheckNotifier&? slow_check_notifier,
+ bool proceed,
+ bool showed_interstitial);
// Bind an additional pipe to this instance of the SafeBrowsing interface.
Clone(SafeBrowsing& request);
@@ -62,4 +64,66 @@ interface SafeBrowsingUrlChecker {
interface UrlCheckNotifier {
OnCompleteCheck(bool proceed, bool showed_interstitial);
-}; \ No newline at end of file
+};
+
+// Used to store the name and value of an HTML Element's attribute.
+struct AttributeNameValue {
+ string name;
+ string value;
+};
+
+// A node is essentially a frame.
+struct ThreatDOMDetailsNode {
+ // A unique ID for this node, unique to the current Render Frame.
+ int32 node_id;
+ // URL of this resource. Can be empty.
+ url.mojom.Url url;
+ // If this resource was in the "src" attribute of a tag, this is the tagname
+ // (eg "IFRAME"). Can be empty.
+ string tag_name;
+ // URL of the parent node. Can be empty.
+ url.mojom.Url parent;
+ // The unique ID of the parent node. Can be 0 if this is the top node.
+ int32 parent_node_id;
+ // Children of this node. Can be empty.
+ array<url.mojom.Url> children;
+ // The unique IDs of the child nodes. Can be empty if there are no children.
+ array<int32> child_node_ids;
+ // The node's attributes as a collection of name-value pairs.
+ array<AttributeNameValue> attributes;
+ // If this node represents a frame or iframe, then this field is set to the
+ // routing ID of the local or remote frame in this renderer process that is
+ // responsible for rendering the contents of this frame (to handle OOPIFs).
+ int32 child_frame_routing_id;
+};
+
+interface ThreatReporter {
+ // Client-side detection message sent from the browser to the renderer.
+ // Request a DOM tree when a safe browsing interstitial is shown.
+ // Renderer returns part of the DOM to be used in a threat report.
+ GetThreatDOMDetails() => (array<ThreatDOMDetailsNode> nodes);
+};
+
+[EnableIf=full_safe_browsing]
+interface PhishingDetector {
+ // Tells the renderer to begin phishing detection for the given toplevel URL
+ // which it has started loading
+ StartPhishingDetection(url.mojom.Url url);
+};
+
+[EnableIf=full_safe_browsing]
+interface PhishingDetectorClient {
+ // Inform the browser that the client-side phishing detector running in the
+ // renderer is done classifying the current URL. If the URL is phishing
+ // the request proto will have |is_phishing()| set to true.
+ // TODO(noelutz): we may want to create custom ParamTraits for MessageLite to
+ // have a generic way to send protocol messages over IPC.
+ PhishingDetectionDone(string request_proto);
+};
+
+interface PhishingModelSetter {
+ // 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);
+};
diff --git a/chromium/components/safe_browsing/common/safe_browsing_prefs.cc b/chromium/components/safe_browsing/common/safe_browsing_prefs.cc
index 525dde34256..153ff9a65f1 100644
--- a/chromium/components/safe_browsing/common/safe_browsing_prefs.cc
+++ b/chromium/components/safe_browsing/common/safe_browsing_prefs.cc
@@ -10,6 +10,11 @@
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
+#include "components/safe_browsing/features.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/url_util.h"
+#include "url/gurl.h"
+#include "url/url_canon.h"
namespace {
@@ -133,6 +138,23 @@ void RecordExtendedReportingPrefChanged(
}
}
}
+
+// A helper function to return a GURL containing just the scheme, host, port,
+// and path from a URL. Equivalent to clearing any username, password, query,
+// and ref. Return empty URL if |url| is not valid.
+GURL GetSimplifiedURL(const GURL& url) {
+ if (!url.is_valid() || !url.IsStandard())
+ return GURL();
+
+ url::Replacements<char> replacements;
+ replacements.ClearUsername();
+ replacements.ClearPassword();
+ replacements.ClearQuery();
+ replacements.ClearRef();
+
+ return url.ReplaceComponents(replacements);
+}
+
} // namespace
namespace prefs {
@@ -154,6 +176,16 @@ const char kSafeBrowsingScoutReportingEnabled[] =
"safebrowsing.scout_reporting_enabled";
const char kSafeBrowsingUnhandledSyncPasswordReuses[] =
"safebrowsing.unhandled_sync_password_reuses";
+const char kSafeBrowsingWhitelistDomains[] =
+ "safebrowsing.safe_browsing_whitelist_domains";
+const char kPasswordProtectionChangePasswordURL[] =
+ "safebrowsing.password_protection_change_password_url";
+const char kPasswordProtectionLoginURLs[] =
+ "safebrowsing.password_protection_login_urls";
+const char kPasswordProtectionWarningTrigger[] =
+ "safebrowsing.password_protection_warning_trigger";
+const char kPasswordProtectionRiskTrigger[] =
+ "safebrowsing.password_protection_risk_trigger";
} // namespace prefs
namespace safe_browsing {
@@ -276,6 +308,10 @@ bool IsExtendedReportingEnabled(const PrefService& prefs) {
return prefs.GetBoolean(GetExtendedReportingPrefName(prefs));
}
+bool IsExtendedReportingPolicyManaged(const PrefService& prefs) {
+ return prefs.IsManagedPreference(GetExtendedReportingPrefName(prefs));
+}
+
bool IsScout(const PrefService& prefs) {
return GetExtendedReportingPrefName(prefs) ==
prefs::kSafeBrowsingScoutReportingEnabled;
@@ -343,6 +379,13 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(prefs::kSafeBrowsingIncidentsSent);
registry->RegisterDictionaryPref(
prefs::kSafeBrowsingUnhandledSyncPasswordReuses);
+ registry->RegisterListPref(prefs::kSafeBrowsingWhitelistDomains);
+ registry->RegisterStringPref(prefs::kPasswordProtectionChangePasswordURL, "");
+ registry->RegisterListPref(prefs::kPasswordProtectionLoginURLs);
+ registry->RegisterIntegerPref(prefs::kPasswordProtectionWarningTrigger,
+ PASSWORD_PROTECTION_OFF);
+ registry->RegisterIntegerPref(prefs::kPasswordProtectionRiskTrigger,
+ PASSWORD_PROTECTION_OFF);
}
void SetExtendedReportingPrefAndMetric(
@@ -458,4 +501,121 @@ base::ListValue GetSafeBrowsingPreferencesList(PrefService* prefs) {
return preferences_list;
}
+void GetSafeBrowsingWhitelistDomainsPref(
+ const PrefService& prefs,
+ std::vector<std::string>* out_canonicalized_domain_list) {
+ if (base::FeatureList::IsEnabled(kEnterprisePasswordProtectionV1)) {
+ const base::ListValue* pref_value =
+ prefs.GetList(prefs::kSafeBrowsingWhitelistDomains);
+ CanonicalizeDomainList(*pref_value, out_canonicalized_domain_list);
+ }
+}
+
+void CanonicalizeDomainList(
+ const base::ListValue& raw_domain_list,
+ std::vector<std::string>* out_canonicalized_domain_list) {
+ out_canonicalized_domain_list->clear();
+ for (auto it = raw_domain_list.GetList().begin();
+ it != raw_domain_list.GetList().end(); it++) {
+ // Verify if it is valid domain string.
+ url::CanonHostInfo host_info;
+ std::string canonical_host =
+ net::CanonicalizeHost(it->GetString(), &host_info);
+ if (!canonical_host.empty())
+ out_canonicalized_domain_list->push_back(canonical_host);
+ }
+}
+
+bool IsURLWhitelistedByPolicy(const GURL& url,
+ StringListPrefMember* pref_member) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ if (!pref_member ||
+ !base::FeatureList::IsEnabled(kEnterprisePasswordProtectionV1)) {
+ return false;
+ }
+ std::vector<std::string> sb_whitelist_domains = pref_member->GetValue();
+ return std::find_if(sb_whitelist_domains.begin(), sb_whitelist_domains.end(),
+ [&url](const std::string& domain) {
+ return url.DomainIs(domain);
+ }) != sb_whitelist_domains.end();
+}
+
+bool IsURLWhitelistedByPolicy(const GURL& url, const PrefService& pref) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (!base::FeatureList::IsEnabled(kEnterprisePasswordProtectionV1))
+ return false;
+
+ if (!pref.HasPrefPath(prefs::kSafeBrowsingWhitelistDomains))
+ return false;
+ const base::ListValue* whitelist =
+ pref.GetList(prefs::kSafeBrowsingWhitelistDomains);
+ for (const base::Value& value : whitelist->GetList()) {
+ if (url.DomainIs(value.GetString()))
+ return true;
+ }
+ return false;
+}
+
+void GetPasswordProtectionLoginURLsPref(const PrefService& prefs,
+ std::vector<GURL>* out_login_url_list) {
+ const base::ListValue* pref_value =
+ prefs.GetList(prefs::kPasswordProtectionLoginURLs);
+ out_login_url_list->clear();
+ for (const base::Value& value : pref_value->GetList()) {
+ GURL login_url(value.GetString());
+ // Skip invalid or none-http/https login URLs.
+ if (login_url.is_valid() && login_url.SchemeIsHTTPOrHTTPS())
+ out_login_url_list->push_back(login_url);
+ }
+}
+
+bool MatchesPasswordProtectionLoginURL(const GURL& url,
+ const PrefService& prefs) {
+ if (!base::FeatureList::IsEnabled(kEnterprisePasswordProtectionV1) ||
+ !url.is_valid()) {
+ return false;
+ }
+
+ std::vector<GURL> login_urls;
+ GetPasswordProtectionLoginURLsPref(prefs, &login_urls);
+ if (login_urls.empty())
+ return false;
+
+ GURL simple_url = GetSimplifiedURL(url);
+ for (const GURL& login_url : login_urls) {
+ if (GetSimplifiedURL(login_url) == simple_url) {
+ return true;
+ }
+ }
+ return false;
+}
+
+GURL GetPasswordProtectionChangePasswordURLPref(const PrefService& prefs) {
+ if (!prefs.HasPrefPath(prefs::kPasswordProtectionChangePasswordURL))
+ return GURL();
+ GURL change_password_url_from_pref(
+ prefs.GetString(prefs::kPasswordProtectionChangePasswordURL));
+ // Skip invalid or non-http/https URL.
+ if (change_password_url_from_pref.is_valid() &&
+ change_password_url_from_pref.SchemeIsHTTPOrHTTPS()) {
+ return change_password_url_from_pref;
+ }
+
+ return GURL();
+}
+
+bool MatchesPasswordProtectionChangePasswordURL(const GURL& url,
+ const PrefService& prefs) {
+ if (!base::FeatureList::IsEnabled(kEnterprisePasswordProtectionV1) ||
+ !url.is_valid()) {
+ return false;
+ }
+
+ GURL change_password_url = GetPasswordProtectionChangePasswordURLPref(prefs);
+ if (change_password_url.is_empty())
+ return false;
+
+ return GetSimplifiedURL(change_password_url) == GetSimplifiedURL(url);
+}
+
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/common/safe_browsing_prefs.h b/chromium/components/safe_browsing/common/safe_browsing_prefs.h
index 6b55a5eba8c..50a2946e90d 100644
--- a/chromium/components/safe_browsing/common/safe_browsing_prefs.h
+++ b/chromium/components/safe_browsing/common/safe_browsing_prefs.h
@@ -9,9 +9,11 @@
#include "base/feature_list.h"
#include "base/values.h"
+#include "components/prefs/pref_member.h"
class PrefRegistrySimple;
class PrefService;
+class GURL;
namespace prefs {
// Boolean that is true when SafeBrowsing is enabled.
@@ -52,6 +54,32 @@ extern const char kSafeBrowsingScoutReportingEnabled[];
// Dictionary that records the origin and navigation ID pairs of unhandled sync
// password reuses.
extern const char kSafeBrowsingUnhandledSyncPasswordReuses[];
+
+// List of domains where Safe Browsing should trust. That means Safe Browsing
+// won't check for malware/phishing/Uws on resources on these domains, or
+// trigger warnings.
+extern const char kSafeBrowsingWhitelistDomains[];
+
+// String indicating the URL where password protection service should send user
+// to change their password if they've been phished. Password protection service
+// also captures new password on this page in a change password event.
+extern const char kPasswordProtectionChangePasswordURL[];
+
+// List of string indicating the URL(s) users use to log in. Password protection
+// service will capture passwords on these URLs.
+// This is managed by enterprise policy and has no effect on users who are not
+// managed by enterprise policy.
+extern const char kPasswordProtectionLoginURLs[];
+
+// Integer indicating the password protection warning trigger. This is managed
+// by enterprise policy and has no effect on users who are not managed by
+// enterprise policy.
+extern const char kPasswordProtectionWarningTrigger[];
+
+// Integer indicating the password protection at-risk account flagging trigger.
+// This is managed by enterprise policy and has no effect on users who are not
+// managed by enterprise policy.
+extern const char kPasswordProtectionRiskTrigger[];
}
namespace safe_browsing {
@@ -91,6 +119,19 @@ enum ExtendedReportingOptInLocation {
SBER_OPTIN_SITE_MAX
};
+// Enumerates all the triggers of password protection.
+enum PasswordProtectionTrigger {
+ // Password protection is off.
+ PASSWORD_PROTECTION_OFF = 0,
+ // Password protection triggered by password reuse event.
+ // Not used for now.
+ PASSWORD_REUSE = 1,
+ // Password protection triggered by password reuse event on phishing page.
+ PHISHING_REUSE = 2,
+ // New triggers must be added before PASSWORD_PROTECTION_TRIGGER_MAX.
+ PASSWORD_PROTECTION_TRIGGER_MAX,
+};
+
// Determines which opt-in text should be used based on the currently active
// preference. Will return either |extended_reporting_pref| if the legacy
// Extended Reporting pref is active, or |scout_pref| if the Scout pref is
@@ -133,6 +174,10 @@ bool IsExtendedReportingOptInAllowed(const PrefService& prefs);
// regardless of which specific one is set.
bool IsExtendedReportingEnabled(const PrefService& prefs);
+// Returns whether the active Extended Reporting pref is currently managed by
+// enterprise policy, meaning the user can't change it.
+bool IsExtendedReportingPolicyManaged(const PrefService& prefs);
+
// Returns whether the currently-active Extended Reporting pref is Scout.
bool IsScout(const PrefService& prefs);
@@ -169,6 +214,45 @@ void UpdatePrefsBeforeSecurityInterstitial(PrefService* prefs);
// values represented as strings.
base::ListValue GetSafeBrowsingPreferencesList(PrefService* prefs);
+// Returns a list of valid domains that Safe Browsing service trusts.
+void GetSafeBrowsingWhitelistDomainsPref(
+ const PrefService& prefs,
+ std::vector<std::string>* out_canonicalized_domain_list);
+
+// Helper function to validate and canonicalize a list of domain strings.
+void CanonicalizeDomainList(
+ const base::ListValue& raw_domain_list,
+ std::vector<std::string>* out_canonicalized_domain_list);
+
+// Helper function to determine if |url| matches Safe Browsing whitelist domains
+// (a.k. a prefs::kSafeBrowsingWhitelistDomains).
+// Called on IO thread.
+bool IsURLWhitelistedByPolicy(const GURL& url,
+ StringListPrefMember* pref_member);
+
+// Helper function to determine if |url| matches Safe Browsing whitelist domains
+// (a.k. a prefs::kSafeBrowsingWhitelistDomains).
+// Called on UI thread.
+bool IsURLWhitelistedByPolicy(const GURL& url, const PrefService& pref);
+
+// Helper function to get the pref value of password protection login URLs.
+void GetPasswordProtectionLoginURLsPref(const PrefService& prefs,
+ std::vector<GURL>* out_login_url_list);
+
+// Helper function that returns true if |url| matches any password protection
+// login URLs. Returns false otherwise.
+bool MatchesPasswordProtectionLoginURL(const GURL& url,
+ const PrefService& prefs);
+
+// Helper function to get the pref value of password protection change password
+// URL.
+GURL GetPasswordProtectionChangePasswordURLPref(const PrefService& prefs);
+
+// Helper function that returns true if |url| matches password protection
+// change password URL. Returns false otherwise.
+bool MatchesPasswordProtectionChangePasswordURL(const GURL& url,
+ const PrefService& prefs);
+
} // namespace safe_browsing
#endif // COMPONENTS_SAFE_BROWSING_COMMON_SAFE_BROWSING_PREFS_H_
diff --git a/chromium/components/safe_browsing/common/safe_browsing_prefs_unittest.cc b/chromium/components/safe_browsing/common/safe_browsing_prefs_unittest.cc
index 8e236d8e742..afe3ba8231d 100644
--- a/chromium/components/safe_browsing/common/safe_browsing_prefs_unittest.cc
+++ b/chromium/components/safe_browsing/common/safe_browsing_prefs_unittest.cc
@@ -12,7 +12,10 @@
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/features.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
namespace safe_browsing {
@@ -29,6 +32,12 @@ class SafeBrowsingPrefsTest : public ::testing::Test {
prefs::kSafeBrowsingSawInterstitialExtendedReporting, false);
prefs_.registry()->RegisterBooleanPref(
prefs::kSafeBrowsingSawInterstitialScoutReporting, false);
+ prefs_.registry()->RegisterStringPref(
+ prefs::kPasswordProtectionChangePasswordURL, "");
+ prefs_.registry()->RegisterListPref(prefs::kPasswordProtectionLoginURLs);
+ prefs_.registry()->RegisterBooleanPref(
+ prefs::kSafeBrowsingExtendedReportingOptInAllowed, true);
+ prefs_.registry()->RegisterListPref(prefs::kSafeBrowsingWhitelistDomains);
ResetExperiments(/*can_show_scout=*/false);
}
@@ -55,6 +64,11 @@ class SafeBrowsingPrefsTest : public ::testing::Test {
base::JoinString(disabled_features, ","));
}
+ void EnableEnterprisePasswordProtectionFeature() {
+ feature_list_.reset(new base::test::ScopedFeatureList);
+ feature_list_->InitAndEnableFeature(kEnterprisePasswordProtectionV1);
+ }
+
std::string GetActivePref() { return GetExtendedReportingPrefName(prefs_); }
// Convenience method for explicitly setting up all combinations of prefs and
@@ -107,6 +121,7 @@ class SafeBrowsingPrefsTest : public ::testing::Test {
private:
std::unique_ptr<base::test::ScopedFeatureList> feature_list_;
+ content::TestBrowserThreadBundle thread_bundle_;
};
// This test ensures that we correctly select between SBER and Scout as the
@@ -350,4 +365,97 @@ TEST_F(SafeBrowsingPrefsTest, GetSafeBrowsingExtendedReportingLevel) {
EXPECT_EQ(SBER_LEVEL_SCOUT, GetExtendedReportingLevel(prefs_));
}
+TEST_F(SafeBrowsingPrefsTest, VerifyMatchesPasswordProtectionLoginURL) {
+ EnableEnterprisePasswordProtectionFeature();
+
+ GURL url("https://mydomain.com/login.html#ref?username=alice");
+ EXPECT_FALSE(prefs_.HasPrefPath(prefs::kPasswordProtectionLoginURLs));
+ EXPECT_FALSE(MatchesPasswordProtectionLoginURL(url, prefs_));
+
+ base::ListValue login_urls;
+ login_urls.AppendString("https://otherdomain.com/login.html");
+ prefs_.Set(prefs::kPasswordProtectionLoginURLs, login_urls);
+ EXPECT_TRUE(prefs_.HasPrefPath(prefs::kPasswordProtectionLoginURLs));
+ EXPECT_FALSE(MatchesPasswordProtectionLoginURL(url, prefs_));
+
+ login_urls.AppendString("https://mydomain.com/login.html");
+ prefs_.Set(prefs::kPasswordProtectionLoginURLs, login_urls);
+ EXPECT_TRUE(prefs_.HasPrefPath(prefs::kPasswordProtectionLoginURLs));
+ EXPECT_TRUE(MatchesPasswordProtectionLoginURL(url, prefs_));
+}
+
+TEST_F(SafeBrowsingPrefsTest,
+ VerifyMatchesPasswordProtectionChangePasswordURL) {
+ EnableEnterprisePasswordProtectionFeature();
+
+ GURL url("https://mydomain.com/change_password.html#ref?username=alice");
+ EXPECT_FALSE(prefs_.HasPrefPath(prefs::kPasswordProtectionChangePasswordURL));
+ EXPECT_FALSE(MatchesPasswordProtectionChangePasswordURL(url, prefs_));
+
+ prefs_.SetString(prefs::kPasswordProtectionChangePasswordURL,
+ "https://otherdomain.com/change_password.html");
+ EXPECT_TRUE(prefs_.HasPrefPath(prefs::kPasswordProtectionChangePasswordURL));
+ EXPECT_FALSE(MatchesPasswordProtectionChangePasswordURL(url, prefs_));
+
+ prefs_.SetString(prefs::kPasswordProtectionChangePasswordURL,
+ "https://mydomain.com/change_password.html");
+ EXPECT_TRUE(prefs_.HasPrefPath(prefs::kPasswordProtectionChangePasswordURL));
+ EXPECT_TRUE(MatchesPasswordProtectionChangePasswordURL(url, prefs_));
+}
+
+TEST_F(SafeBrowsingPrefsTest, IsExtendedReportingPolicyManaged) {
+ // This test checks that manipulating SBEROptInAllowed and the management
+ // state of SBER behaves as expected. Below, we describe what should happen
+ // to the results of IsExtendedReportingPolicyManaged and
+ // IsExtendedReportingOptInAllowed.
+
+ // Confirm default state, SBER should be disabled, OptInAllowed should
+ // be enabled, and SBER is not managed.
+ EXPECT_FALSE(IsExtendedReportingEnabled(prefs_));
+ EXPECT_TRUE(IsExtendedReportingOptInAllowed(prefs_));
+ EXPECT_FALSE(IsExtendedReportingPolicyManaged(prefs_));
+
+ // Setting SBEROptInAllowed to false disallows opt-in but doesn't change
+ // whether SBER is managed.
+ prefs_.SetBoolean(prefs::kSafeBrowsingExtendedReportingOptInAllowed, false);
+ EXPECT_FALSE(IsExtendedReportingOptInAllowed(prefs_));
+ EXPECT_FALSE(IsExtendedReportingPolicyManaged(prefs_));
+ // Setting the value back to true reverts back to the default.
+ prefs_.SetBoolean(prefs::kSafeBrowsingExtendedReportingOptInAllowed, true);
+ EXPECT_TRUE(IsExtendedReportingOptInAllowed(prefs_));
+ EXPECT_FALSE(IsExtendedReportingPolicyManaged(prefs_));
+
+ // Make the SBER pref managed and enable it and ensure that the pref gets
+ // the expected value. Making SBER managed doesn't change the
+ // SBEROptInAllowed setting.
+ prefs_.SetManagedPref(GetExtendedReportingPrefName(prefs_),
+ std::make_unique<base::Value>(true));
+ EXPECT_TRUE(prefs_.IsManagedPreference(GetExtendedReportingPrefName(prefs_)));
+ // The value of the pref comes from the policy.
+ EXPECT_TRUE(IsExtendedReportingEnabled(prefs_));
+ // SBER being managed doesn't change the SBEROptInAllowed pref.
+ EXPECT_TRUE(IsExtendedReportingOptInAllowed(prefs_));
+}
+
+TEST_F(SafeBrowsingPrefsTest, VerifyIsURLWhitelistedByPolicy) {
+ EnableEnterprisePasswordProtectionFeature();
+
+ GURL target_url("https://www.foo.com");
+ // When PrefMember is null, URL is not whitelisted.
+ EXPECT_FALSE(IsURLWhitelistedByPolicy(target_url, nullptr));
+
+ EXPECT_FALSE(prefs_.HasPrefPath(prefs::kSafeBrowsingWhitelistDomains));
+ base::ListValue whitelisted_domains;
+ whitelisted_domains.AppendString("foo.com");
+ prefs_.Set(prefs::kSafeBrowsingWhitelistDomains, whitelisted_domains);
+ StringListPrefMember string_list_pref;
+ string_list_pref.Init(prefs::kSafeBrowsingWhitelistDomains, &prefs_);
+ EXPECT_TRUE(IsURLWhitelistedByPolicy(target_url, prefs_));
+ EXPECT_TRUE(IsURLWhitelistedByPolicy(target_url, &string_list_pref));
+
+ GURL not_whitelisted_url("https://www.bar.com");
+ EXPECT_FALSE(IsURLWhitelistedByPolicy(not_whitelisted_url, prefs_));
+ EXPECT_FALSE(
+ IsURLWhitelistedByPolicy(not_whitelisted_url, &string_list_pref));
+}
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/common/safebrowsing_constants.cc b/chromium/components/safe_browsing/common/safebrowsing_constants.cc
index 65c2b54bb0e..0281893f133 100644
--- a/chromium/components/safe_browsing/common/safebrowsing_constants.cc
+++ b/chromium/components/safe_browsing/common/safebrowsing_constants.cc
@@ -32,4 +32,6 @@ const char kSbBackupHttpErrorURLPrefix[] =
const char kSbBackupNetworkErrorURLPrefix[] =
"https://alt3-safebrowsing.google.com/safebrowsing";
+const char kCustomCancelReasonForURLLoader[] = "SafeBrowsing";
+
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/common/safebrowsing_constants.h b/chromium/components/safe_browsing/common/safebrowsing_constants.h
index 598352e3997..a339a81d466 100644
--- a/chromium/components/safe_browsing/common/safebrowsing_constants.h
+++ b/chromium/components/safe_browsing/common/safebrowsing_constants.h
@@ -29,6 +29,12 @@ extern const char kSbBackupHttpErrorURLPrefix[];
// The backup URL prefix used when there are local network specific issues.
extern const char kSbBackupNetworkErrorURLPrefix[];
+
+// When a network::mojom::URLLoader is cancelled because of SafeBrowsing, this
+// custom cancellation reason could be used to notify the implementation side.
+// Please see network::mojom::URLLoader::kClientDisconnectReason for more
+// details.
+extern const char kCustomCancelReasonForURLLoader[];
}
#endif // COMPONENTS_SAFE_BROWSING_COMMON_SAFEBROWSING_CONSTANTS_H_
diff --git a/chromium/components/safe_browsing/common/safebrowsing_message_generator.cc b/chromium/components/safe_browsing/common/safebrowsing_message_generator.cc
deleted file mode 100644
index 0ed1b08e74a..00000000000
--- a/chromium/components/safe_browsing/common/safebrowsing_message_generator.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Get basic type definitions.
-#define IPC_MESSAGE_IMPL
-#include "components/safe_browsing/common/safebrowsing_message_generator.h"
-
-// Generate constructors.
-#include "ipc/struct_constructor_macros.h"
-#include "components/safe_browsing/common/safebrowsing_message_generator.h"
-
-// Generate destructors.
-#include "ipc/struct_destructor_macros.h"
-#include "components/safe_browsing/common/safebrowsing_message_generator.h"
-
-// Generate param traits write methods.
-#include "ipc/param_traits_write_macros.h"
-namespace IPC {
-#include "components/safe_browsing/common/safebrowsing_message_generator.h"
-} // namespace IPC
-
-// Generate param traits read methods.
-#include "ipc/param_traits_read_macros.h"
-namespace IPC {
-#include "components/safe_browsing/common/safebrowsing_message_generator.h"
-} // namespace IPC
-
-// Generate param traits log methods.
-#include "ipc/param_traits_log_macros.h"
-namespace IPC {
-#include "components/safe_browsing/common/safebrowsing_message_generator.h"
-} // namespace IPC
diff --git a/chromium/components/safe_browsing/common/safebrowsing_message_generator.h b/chromium/components/safe_browsing/common/safebrowsing_message_generator.h
deleted file mode 100644
index 8141e6d9cff..00000000000
--- a/chromium/components/safe_browsing/common/safebrowsing_message_generator.h
+++ /dev/null
@@ -1,7 +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.
-
-// Multiply-included file, hence no include guard.
-
-#include "components/safe_browsing/common/safebrowsing_messages.h"
diff --git a/chromium/components/safe_browsing/common/safebrowsing_messages.h b/chromium/components/safe_browsing/common/safebrowsing_messages.h
deleted file mode 100644
index 400201d0d2d..00000000000
--- a/chromium/components/safe_browsing/common/safebrowsing_messages.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Multiply-included message file, so no include guard.
-
-#include <stdint.h>
-#include <string>
-#include <vector>
-
-#include "components/safe_browsing/common/safebrowsing_types.h"
-#include "ipc/ipc_message_macros.h"
-#include "url/gurl.h"
-#include "url/ipc/url_param_traits.h"
-
-#define IPC_MESSAGE_START SafeBrowsingMsgStart
-
-// A node is essentially a frame.
-IPC_STRUCT_BEGIN(SafeBrowsingHostMsg_ThreatDOMDetails_Node)
- // A unique ID for this node, unique to the current Render Frame.
- IPC_STRUCT_MEMBER(int32_t, node_id)
-
- // URL of this resource. Can be empty.
- IPC_STRUCT_MEMBER(GURL, url)
-
- // If this resource was in the "src" attribute of a tag, this is the tagname
- // (eg "IFRAME"). Can be empty.
- IPC_STRUCT_MEMBER(std::string, tag_name)
-
- // URL of the parent node. Can be empty.
- IPC_STRUCT_MEMBER(GURL, parent)
-
- // The unique ID of the parent node. Can be 0 if this is the top node.
- IPC_STRUCT_MEMBER(int32_t, parent_node_id)
-
- // children of this node. Can be emtpy.
- IPC_STRUCT_MEMBER(std::vector<GURL>, children)
-
- // The unique IDs of the child nodes. Can be empty if there are no children.
- IPC_STRUCT_MEMBER(std::vector<int32_t>, child_node_ids)
-
- // The node's attributes, as a collection of name-value pairs.
- IPC_STRUCT_MEMBER(std::vector<safe_browsing::AttributeNameValue>, attributes)
-
- // If this node represents a frame or iframe, then this field is set to the
- // routing ID of the local or remote frame in this renderer process that is
- // responsible for rendering the contents of this frame (to handle OOPIFs).
- IPC_STRUCT_MEMBER(int32_t, child_frame_routing_id)
-IPC_STRUCT_END()
-
-// SafeBrowsing client-side detection messages sent from the renderer to the
-// browser.
-
-// Send part of the DOM to the browser, to be used in a threat report.
-IPC_MESSAGE_ROUTED1(SafeBrowsingHostMsg_ThreatDOMDetails,
- std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node>)
-
-#if defined(FULL_SAFE_BROWSING)
-// Inform the browser that the client-side phishing detector running in the
-// renderer is done classifying the current URL. If the URL is phishing
-// the request proto will have |is_phishing()| set to true.
-// TODO(noelutz): we may want to create custom ParamTraits for MessageLite to
-// have a generic way to send protocol messages over IPC.
-IPC_MESSAGE_ROUTED1(SafeBrowsingHostMsg_PhishingDetectionDone,
- std::string /* encoded ClientPhishingRequest proto */)
-#endif
-
-// SafeBrowsing client-side detection messages sent from the browser to the
-// renderer.
-
-// Request a DOM tree when a safe browsing interstitial is shown.
-IPC_MESSAGE_ROUTED0(SafeBrowsingMsg_GetThreatDOMDetails)
-
-#if defined(FULL_SAFE_BROWSING)
-// 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.
-IPC_MESSAGE_CONTROL1(SafeBrowsingMsg_SetPhishingModel,
- std::string /* encoded ClientSideModel proto */)
-
-// Tells the renderer to begin phishing detection for the given toplevel URL
-// which it has started loading.
-IPC_MESSAGE_ROUTED1(SafeBrowsingMsg_StartPhishingDetection,
- GURL)
-#endif
diff --git a/chromium/components/safe_browsing/common/safebrowsing_types.h b/chromium/components/safe_browsing/common/safebrowsing_types.h
deleted file mode 100644
index 9b6428f21b9..00000000000
--- a/chromium/components/safe_browsing/common/safebrowsing_types.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SAFE_BROWSING_COMMON_SAFEBROWSING_TYPES_H_
-#define COMPONENTS_SAFE_BROWSING_COMMON_SAFEBROWSING_TYPES_H_
-
-#include <string>
-
-namespace safe_browsing {
-
-// Used to store the name and value of an HTML Element's attribute.
-using AttributeNameValue = std::pair<std::string, std::string>;
-}
-
-#endif // COMPONENTS_SAFE_BROWSING_COMMON_SAFEBROWSING_TYPES_H_
diff --git a/chromium/components/safe_browsing/db/v4_database.cc b/chromium/components/safe_browsing/db/v4_database.cc
index b03300f43f4..3e77977ff59 100644
--- a/chromium/components/safe_browsing/db/v4_database.cc
+++ b/chromium/components/safe_browsing/db/v4_database.cc
@@ -2,7 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "components/safe_browsing/db/v4_database.h"
+
#include <memory>
+#include <utility>
#include "base/callback.h"
#include "base/files/file_util.h"
@@ -10,7 +13,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "components/safe_browsing/db/v4_database.h"
#include "components/safe_browsing/proto/webui.pb.h"
#include "content/public/browser/browser_thread.h"
@@ -108,7 +110,7 @@ void V4Database::CreateOnTaskRunner(
// Database is done loading, pass it to the new_db_callback on the caller's
// thread. This would unblock resource loads.
callback_task_runner->PostTask(
- FROM_HERE, base::Bind(new_db_callback, base::Passed(&v4_database)));
+ FROM_HERE, base::BindOnce(new_db_callback, std::move(v4_database)));
UMA_HISTOGRAM_TIMES("SafeBrowsing.V4DatabaseOpen.Time",
TimeTicks::Now() - create_start_time);
@@ -176,10 +178,10 @@ void V4Database::ApplyUpdate(
base::Bind(&V4Database::UpdatedStoreReady,
weak_factory_on_io_.GetWeakPtr(), identifier);
db_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&V4Store::ApplyUpdate, base::Unretained(old_store.get()),
- base::Passed(std::move(response)), current_task_runner,
- store_ready_callback));
+ FROM_HERE, base::BindOnce(&V4Store::ApplyUpdate,
+ base::Unretained(old_store.get()),
+ std::move(response), current_task_runner,
+ store_ready_callback));
}
} else {
NOTREACHED() << "Got update for unexpected identifier: " << identifier;
diff --git a/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager.cc b/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager.cc
index be6647769d1..94cf71deea6 100644
--- a/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager.cc
+++ b/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager.cc
@@ -242,7 +242,7 @@ V4GetHashProtocolManager::V4GetHashProtocolManager(
config_(config),
request_context_getter_(request_context_getter),
url_fetcher_id_(0),
- clock_(new base::DefaultClock()) {
+ clock_(base::DefaultClock::GetInstance()) {
DCHECK(!stores_to_check.empty());
std::set<PlatformType> platform_types;
std::set<ThreatEntryType> threat_entry_types;
@@ -708,9 +708,8 @@ void V4GetHashProtocolManager::ResetGetHashErrors() {
gethash_back_off_mult_ = 1;
}
-void V4GetHashProtocolManager::SetClockForTests(
- std::unique_ptr<base::Clock> clock) {
- clock_ = std::move(clock);
+void V4GetHashProtocolManager::SetClockForTests(base::Clock* clock) {
+ clock_ = clock;
}
void V4GetHashProtocolManager::UpdateCache(
diff --git a/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager.h b/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager.h
index 4167bc6c59d..5f07eff885d 100644
--- a/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager.h
+++ b/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager.h
@@ -291,7 +291,7 @@ class V4GetHashProtocolManager : public net::URLFetcherDelegate {
void ResetGetHashErrors();
// Overrides the clock used to check the time.
- void SetClockForTests(std::unique_ptr<base::Clock> clock);
+ void SetClockForTests(base::Clock* clock);
// Updates the state of the full hash cache upon receiving a valid response
// from the server.
@@ -345,7 +345,7 @@ class V4GetHashProtocolManager : public net::URLFetcherDelegate {
int url_fetcher_id_;
// The clock used to vend times.
- std::unique_ptr<base::Clock> clock_;
+ base::Clock* clock_;
// The following sets represent the combination of lists that we would always
// request from the server, irrespective of which list we found the hash
diff --git a/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager_unittest.cc b/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager_unittest.cc
index f4ae5d63978..80e53f02e46 100644
--- a/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager_unittest.cc
+++ b/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager_unittest.cc
@@ -103,9 +103,8 @@ class V4GetHashProtocolManagerTest : public PlatformTest {
}
void SetTestClock(base::Time now, V4GetHashProtocolManager* pm) {
- base::SimpleTestClock* clock = new base::SimpleTestClock();
- clock->SetNow(now);
- pm->SetClockForTests(base::WrapUnique(clock));
+ clock_.SetNow(now);
+ pm->SetClockForTests(&clock_);
}
void ValidateGetV4ApiResults(const ThreatMetadata& expected_md,
@@ -155,6 +154,7 @@ class V4GetHashProtocolManagerTest : public PlatformTest {
}
bool callback_called_;
+ base::SimpleTestClock clock_;
content::TestBrowserThreadBundle thread_bundle_;
};
diff --git a/chromium/components/safe_browsing/db/v4_local_database_manager.cc b/chromium/components/safe_browsing/db/v4_local_database_manager.cc
index 74e1ad88676..26d83c5c8a4 100644
--- a/chromium/components/safe_browsing/db/v4_local_database_manager.cc
+++ b/chromium/components/safe_browsing/db/v4_local_database_manager.cc
@@ -7,6 +7,7 @@
#include "components/safe_browsing/db/v4_local_database_manager.h"
+#include <utility>
#include <vector>
#include "base/bind_helpers.h"
@@ -764,9 +765,9 @@ void V4LocalDatabaseManager::ScheduleFullHashCheck(
// Post on the IO thread to enforce async behavior.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&V4LocalDatabaseManager::PerformFullHashCheck,
- weak_factory_.GetWeakPtr(), base::Passed(std::move(check)),
- full_hash_to_store_and_hash_prefixes));
+ base::BindOnce(&V4LocalDatabaseManager::PerformFullHashCheck,
+ weak_factory_.GetWeakPtr(), std::move(check),
+ full_hash_to_store_and_hash_prefixes));
}
bool V4LocalDatabaseManager::HandleHashSynchronously(
diff --git a/chromium/components/safe_browsing/db/v4_local_database_manager_unittest.cc b/chromium/components/safe_browsing/db/v4_local_database_manager_unittest.cc
index 77d82e45c91..7231c925aa3 100644
--- a/chromium/components/safe_browsing/db/v4_local_database_manager_unittest.cc
+++ b/chromium/components/safe_browsing/db/v4_local_database_manager_unittest.cc
@@ -3,6 +3,9 @@
// found in the LICENSE file.
#include "components/safe_browsing/db/v4_local_database_manager.h"
+
+#include <utility>
+
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
@@ -105,10 +108,10 @@ class FakeV4Database : public V4Database {
const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner =
base::MessageLoop::current()->task_runner();
db_task_runner->PostTask(
- FROM_HERE,
- base::Bind(&FakeV4Database::CreateOnTaskRunner, db_task_runner,
- base::Passed(&store_map), store_and_hash_prefixes,
- callback_task_runner, new_db_callback, stores_available));
+ FROM_HERE, base::BindOnce(&FakeV4Database::CreateOnTaskRunner,
+ db_task_runner, std::move(store_map),
+ store_and_hash_prefixes, callback_task_runner,
+ new_db_callback, stores_available));
}
// V4Database implementation
@@ -151,7 +154,7 @@ class FakeV4Database : public V4Database {
store_and_hash_prefixes, stores_available));
callback_task_runner->PostTask(
FROM_HERE,
- base::Bind(new_db_callback, base::Passed(&fake_v4_database)));
+ base::BindOnce(new_db_callback, std::move(fake_v4_database)));
}
FakeV4Database(const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
diff --git a/chromium/components/safe_browsing/db/v4_store.cc b/chromium/components/safe_browsing/db/v4_store.cc
index ec4d08cb904..3ebcfcdb721 100644
--- a/chromium/components/safe_browsing/db/v4_store.cc
+++ b/chromium/components/safe_browsing/db/v4_store.cc
@@ -4,6 +4,8 @@
#include "components/safe_browsing/db/v4_store.h"
+#include <utility>
+
#include "base/base64.h"
#include "base/bind.h"
#include "base/files/file_util.h"
@@ -393,7 +395,7 @@ void V4Store::ApplyUpdate(
// happens, the old store will get destoyed and can lead to use-after-free in
// this function.
callback_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, base::Passed(&new_store)));
+ FROM_HERE, base::BindOnce(callback, std::move(new_store)));
}
ApplyUpdateResult V4Store::UpdateHashPrefixMapFromAdditions(
diff --git a/chromium/components/safe_browsing/features.cc b/chromium/components/safe_browsing/features.cc
index b6655dcf062..323eb971bc5 100644
--- a/chromium/components/safe_browsing/features.cc
+++ b/chromium/components/safe_browsing/features.cc
@@ -28,6 +28,20 @@ const base::Feature kAdSamplerCollectButDontSendFeature{
const base::Feature kAdSamplerTriggerFeature{"SafeBrowsingAdSamplerTrigger",
base::FEATURE_DISABLED_BY_DEFAULT};
+// If enabled in pre-network-service world, SafeBrowsing URL checks are done by
+// applying SafeBrowsing's URLLoaderThrottle subclasses to ThrottlingURLLoader.
+// It affects:
+// - subresource loading from renderers;
+// - frame resource loading from the browser, if
+// content::IsNavigationMojoResponseEnabled() is true.
+//
+// This flag has no effect if network service is enabled. With network service,
+// SafeBrowsing URL checks are always done by SafeBrowsing's URLLoaderThrottle
+// subclasses.
+const base::Feature kCheckByURLLoaderThrottle{
+ "S13nSafeBrowsingCheckByURLLoaderThrottle",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kGaiaPasswordReuseReporting{
"SyncPasswordReuseEvent", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -43,11 +57,17 @@ const base::Feature kTriggerThrottlerDailyQuotaFeature{
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kDispatchSafetyNetCheckOffThread{
- "DispatchSafetyNetCheckOffThread", base::FEATURE_DISABLED_BY_DEFAULT};
+ "DispatchSafetyNetCheckOffThread", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kAppendRecentNavigationEvents{
"AppendRecentNavigationEvents", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kInspectDownloadedRarFiles{
+ "InspectDownloadedRarFiles", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kEnterprisePasswordProtectionV1{
+ "EnterprisePasswordProtectionV1", base::FEATURE_DISABLED_BY_DEFAULT};
+
namespace {
// List of experimental features. Boolean value for each list member should be
// set to true if the experiment is currently running at a probability other
@@ -60,11 +80,14 @@ constexpr struct {
{&kAdSamplerCollectButDontSendFeature, false},
{&kAdSamplerTriggerFeature, false},
{&kAppendRecentNavigationEvents, true},
+ {&kCheckByURLLoaderThrottle, true},
+ {&kDispatchSafetyNetCheckOffThread, false},
+ {&kEnterprisePasswordProtectionV1, true},
{&kGaiaPasswordReuseReporting, true},
{&kGoogleBrandedPhishingWarning, true},
+ {&kInspectDownloadedRarFiles, true},
{&kThreatDomDetailsTagAndAttributeFeature, false},
{&kTriggerThrottlerDailyQuotaFeature, false},
- {&kDispatchSafetyNetCheckOffThread, false},
};
// Adds the name and the enabled/disabled status of a given feature.
diff --git a/chromium/components/safe_browsing/features.h b/chromium/components/safe_browsing/features.h
index 9a1e4eff159..3a8ba49d58f 100644
--- a/chromium/components/safe_browsing/features.h
+++ b/chromium/components/safe_browsing/features.h
@@ -21,6 +21,7 @@ namespace safe_browsing {
// Features list
extern const base::Feature kAdSamplerCollectButDontSendFeature;
extern const base::Feature kAdSamplerTriggerFeature;
+extern const base::Feature kCheckByURLLoaderThrottle;
// Gates logging of GaiaPasswordReuse user events.
extern const base::Feature kGaiaPasswordReuseReporting;
extern const base::Feature kGoogleBrandedPhishingWarning;
@@ -47,6 +48,13 @@ extern const base::Feature kDispatchSafetyNetCheckOffThread;
// users if referrer chain is incomplete.
extern const base::Feature kAppendRecentNavigationEvents;
+// Controls whether .rar files downloaded by the user are inspected for being
+// unsafe.
+extern const base::Feature kInspectDownloadedRarFiles;
+
+// Control the Password Protection for Enterprise V1 feature;
+extern const base::Feature kEnterprisePasswordProtectionV1;
+
base::ListValue GetFeatureStatusList();
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/password_protection/BUILD.gn b/chromium/components/safe_browsing/password_protection/BUILD.gn
index dbd0aea7da7..52e8d85fe6f 100644
--- a/chromium/components/safe_browsing/password_protection/BUILD.gn
+++ b/chromium/components/safe_browsing/password_protection/BUILD.gn
@@ -25,6 +25,7 @@ source_set("password_protection") {
"//components/password_manager/core/browser:browser",
"//components/safe_browsing:csd_proto",
"//components/safe_browsing:features",
+ "//components/safe_browsing/common:safe_browsing_prefs",
"//components/safe_browsing/db:database_manager",
"//components/safe_browsing/db:v4_protocol_manager_util",
"//components/safe_browsing/db:whitelist_checker_client",
diff --git a/chromium/components/safe_browsing/password_protection/password_protection_service.cc b/chromium/components/safe_browsing/password_protection/password_protection_service.cc
index ea7b003a01f..9b479992be1 100644
--- a/chromium/components/safe_browsing/password_protection/password_protection_service.cc
+++ b/chromium/components/safe_browsing/password_protection/password_protection_service.cc
@@ -151,23 +151,23 @@ void PasswordProtectionService::RecordWarningAction(WarningUIType ui_type,
}
}
-// static
bool PasswordProtectionService::ShouldShowModalWarning(
LoginReputationClientRequest::TriggerType trigger_type,
bool matches_sync_password,
- LoginReputationClientRequest::PasswordReuseEvent::SyncAccountType
- account_type,
LoginReputationClientResponse::VerdictType verdict_type) {
- return base::FeatureList::IsEnabled(kGoogleBrandedPhishingWarning) &&
- trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT &&
- matches_sync_password &&
- account_type ==
- LoginReputationClientRequest::PasswordReuseEvent::GMAIL &&
- (verdict_type == LoginReputationClientResponse::PHISHING ||
+ if (trigger_type != LoginReputationClientRequest::PASSWORD_REUSE_EVENT ||
+ !matches_sync_password ||
+ GetSyncAccountType() ==
+ LoginReputationClientRequest::PasswordReuseEvent::NOT_SIGNED_IN) {
+ return false;
+ }
+
+ return (verdict_type == LoginReputationClientResponse::PHISHING ||
(verdict_type == LoginReputationClientResponse::LOW_REPUTATION &&
base::GetFieldTrialParamByFeatureAsBool(
kGoogleBrandedPhishingWarning, "warn_on_low_reputation",
- false)));
+ false))) &&
+ IsWarningEnabled();
}
bool PasswordProtectionService::ShouldShowSofterWarning() {
@@ -420,6 +420,7 @@ bool PasswordProtectionService::CanSendPing(
bool matches_sync_password) {
RequestOutcome request_outcome = URL_NOT_VALID_FOR_REPUTATION_COMPUTING;
if (IsPingingEnabled(trigger_type, &request_outcome) &&
+ !IsURLWhitelistedForPasswordEntry(main_frame_url, &request_outcome) &&
CanGetReputationOfURL(main_frame_url)) {
return true;
}
@@ -439,9 +440,9 @@ void PasswordProtectionService::RequestFinished(
CacheVerdict(request->main_frame_url(), request->trigger_type(),
response.get(), base::Time::Now());
}
- if (ShouldShowModalWarning(
- request->trigger_type(), request->matches_sync_password(),
- GetSyncAccountType(), response->verdict_type())) {
+ if (ShouldShowModalWarning(request->trigger_type(),
+ request->matches_sync_password(),
+ response->verdict_type())) {
ShowModalWarning(request->web_contents(), response->verdict_token());
request->set_is_modal_warning_showing(true);
}
@@ -838,4 +839,20 @@ bool PasswordProtectionService::IsModalWarningShowingInWebContents(
return false;
}
+bool PasswordProtectionService::IsWarningEnabled() {
+ return base::FeatureList::IsEnabled(kGoogleBrandedPhishingWarning) &&
+ GetSyncAccountType() !=
+ LoginReputationClientRequest::PasswordReuseEvent::NOT_SIGNED_IN &&
+ GetPasswordProtectionTriggerPref(
+ prefs::kPasswordProtectionWarningTrigger) == PHISHING_REUSE;
+}
+
+bool PasswordProtectionService::IsEventLoggingEnabled() {
+ return base::FeatureList::IsEnabled(kGaiaPasswordReuseReporting) &&
+ GetSyncAccountType() !=
+ LoginReputationClientRequest::PasswordReuseEvent::NOT_SIGNED_IN &&
+ GetPasswordProtectionTriggerPref(
+ prefs::kPasswordProtectionRiskTrigger) == PHISHING_REUSE;
+}
+
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/password_protection/password_protection_service.h b/chromium/components/safe_browsing/password_protection/password_protection_service.h
index 4e10aeb0f98..f515185427c 100644
--- a/chromium/components/safe_browsing/password_protection/password_protection_service.h
+++ b/chromium/components/safe_browsing/password_protection/password_protection_service.h
@@ -18,6 +18,7 @@
#include "base/task/cancelable_task_tracker.h"
#include "base/values.h"
#include "components/history/core/browser/history_service_observer.h"
+#include "components/safe_browsing/common/safe_browsing_prefs.h"
#include "components/safe_browsing/db/v4_protocol_manager_util.h"
#include "components/safe_browsing/proto/csd.pb.h"
#include "net/url_request/url_request_context_getter.h"
@@ -74,6 +75,9 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
DISABLED_DUE_TO_FEATURE_DISABLED = 12,
DISABLED_DUE_TO_USER_POPULATION = 13,
URL_NOT_VALID_FOR_REPUTATION_COMPUTING = 14,
+ MATCHED_ENTERPRISE_WHITELIST = 15,
+ MATCHED_ENTERPRISE_CHANGE_PASSWORD_URL = 16,
+ MATCHED_ENTERPRISE_LOGIN_URL = 17,
MAX_OUTCOME
};
@@ -183,11 +187,9 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
void RecordWarningAction(WarningUIType ui_type, WarningAction action);
// If we want to show password reuse modal warning.
- static bool ShouldShowModalWarning(
+ bool ShouldShowModalWarning(
LoginReputationClientRequest::TriggerType trigger_type,
bool matches_sync_password,
- LoginReputationClientRequest::PasswordReuseEvent::SyncAccountType
- account_type,
LoginReputationClientResponse::VerdictType verdict_type);
// Shows modal warning dialog on the current |web_contents| and pass the
@@ -222,6 +224,23 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
std::unique_ptr<PasswordProtectionNavigationThrottle>
MaybeCreateNavigationThrottle(content::NavigationHandle* navigation_handle);
+ // Returns if the warning UI is enabled.
+ bool IsWarningEnabled();
+
+ // Returns if the event logging is enabled.
+ bool IsEventLoggingEnabled();
+
+ // Returns the pref value of password protection trigger.
+ virtual PasswordProtectionTrigger GetPasswordProtectionTriggerPref(
+ const std::string& pref_name) const = 0;
+
+ // If |url| matches Safe Browsing whitelist domains, password protection
+ // change password URL, or password protection login URLs in the enterprise
+ // policy.
+ virtual bool IsURLWhitelistedForPasswordEntry(
+ const GURL& url,
+ RequestOutcome* reason) const = 0;
+
protected:
friend class PasswordProtectionRequest;
@@ -283,7 +302,7 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
// Gets the type of sync account associated with current profile or
// |NOT_SIGNED_IN|.
virtual LoginReputationClientRequest::PasswordReuseEvent::SyncAccountType
- GetSyncAccountType() = 0;
+ GetSyncAccountType() const = 0;
// Records a Chrome Sync event for the result of the URL reputation lookup
// if the user enters their sync password on a website.
@@ -370,6 +389,7 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
LoginReputationClientRequest::TriggerType trigger_type,
RequestOutcome reason,
bool matches_sync_password);
+
// Number of verdict stored for this profile for password on focus pings.
int stored_verdict_count_password_on_focus_;
diff --git a/chromium/components/safe_browsing/password_protection/password_protection_service_unittest.cc b/chromium/components/safe_browsing/password_protection/password_protection_service_unittest.cc
index 105e27d9c2a..478c37d1e32 100644
--- a/chromium/components/safe_browsing/password_protection/password_protection_service_unittest.cc
+++ b/chromium/components/safe_browsing/password_protection/password_protection_service_unittest.cc
@@ -85,7 +85,10 @@ class TestPasswordProtectionService : public PasswordProtectionService {
content_setting_map.get()),
is_extended_reporting_(true),
is_incognito_(false),
- latest_request_(nullptr) {}
+ latest_request_(nullptr),
+ password_protection_trigger_(PASSWORD_PROTECTION_OFF),
+ sync_account_type_(
+ LoginReputationClientRequest::PasswordReuseEvent::NOT_SIGNED_IN) {}
void RequestFinished(
PasswordProtectionRequest* request,
@@ -118,8 +121,13 @@ class TestPasswordProtectionService : public PasswordProtectionService {
bool IsHistorySyncEnabled() override { return false; }
LoginReputationClientRequest::PasswordReuseEvent::SyncAccountType
- GetSyncAccountType() override {
- return LoginReputationClientRequest::PasswordReuseEvent::NOT_SIGNED_IN;
+ GetSyncAccountType() const override {
+ return sync_account_type_;
+ }
+
+ void set_sync_account_type(
+ LoginReputationClientRequest::PasswordReuseEvent::SyncAccountType type) {
+ sync_account_type_ = type;
}
LoginReputationClientResponse* latest_response() {
@@ -134,6 +142,20 @@ class TestPasswordProtectionService : public PasswordProtectionService {
return latest_request_ ? latest_request_->request_proto() : nullptr;
}
+ void set_password_protection_trigger(PasswordProtectionTrigger trigger) {
+ password_protection_trigger_ = trigger;
+ }
+
+ PasswordProtectionTrigger GetPasswordProtectionTriggerPref(
+ const std::string& pref_name_unused) const override {
+ return password_protection_trigger_;
+ }
+
+ bool IsURLWhitelistedForPasswordEntry(const GURL& url,
+ RequestOutcome* reason) const override {
+ return false;
+ }
+
MOCK_METHOD3(FillReferrerChain,
void(const GURL&, int, LoginReputationClientRequest::Frame*));
MOCK_METHOD1(MaybeLogPasswordReuseDetectedEvent, void(content::WebContents*));
@@ -152,6 +174,9 @@ class TestPasswordProtectionService : public PasswordProtectionService {
bool is_incognito_;
PasswordProtectionRequest* latest_request_;
std::unique_ptr<LoginReputationClientResponse> latest_response_;
+ PasswordProtectionTrigger password_protection_trigger_;
+ LoginReputationClientRequest::PasswordReuseEvent::SyncAccountType
+ sync_account_type_;
DISALLOW_COPY_AND_ASSIGN(TestPasswordProtectionService);
};
@@ -1036,11 +1061,10 @@ TEST_P(PasswordProtectionServiceTest, VerifyShouldShowModalWarning) {
base::test::ScopedFeatureList scoped_feature_list1;
scoped_feature_list1.InitAndDisableFeature(
safe_browsing::kGoogleBrandedPhishingWarning);
- // Don't show modal warning is feature is disabled.
- EXPECT_FALSE(PasswordProtectionService::ShouldShowModalWarning(
+ // Don't show modal warning if feature is disabled.
+ EXPECT_FALSE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
/*matches_sync_password=*/true,
- LoginReputationClientRequest::PasswordReuseEvent::GMAIL,
LoginReputationClientResponse::PHISHING));
}
@@ -1049,39 +1073,65 @@ TEST_P(PasswordProtectionServiceTest, VerifyShouldShowModalWarning) {
scoped_feature_list2.InitAndEnableFeatureWithParameters(
safe_browsing::kGoogleBrandedPhishingWarning,
{{"softer_warning", "true"}, {"warn_on_low_reputation", "false"}});
+ password_protection_service_->set_sync_account_type(
+ LoginReputationClientRequest::PasswordReuseEvent::GMAIL);
+ password_protection_service_->set_password_protection_trigger(
+ PHISHING_REUSE);
// Don't show modal warning if it is not a password reuse ping.
- EXPECT_FALSE(PasswordProtectionService::ShouldShowModalWarning(
+ EXPECT_FALSE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
/*matches_sync_password=*/true,
- LoginReputationClientRequest::PasswordReuseEvent::GMAIL,
LoginReputationClientResponse::PHISHING));
- // Don't show modal warning if it is not a signin password reuse.
- EXPECT_FALSE(PasswordProtectionService::ShouldShowModalWarning(
+ // Don't show modal warning if it is not a sync password reuse.
+ EXPECT_FALSE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
/*matches_sync_password=*/false,
- LoginReputationClientRequest::PasswordReuseEvent::GMAIL,
LoginReputationClientResponse::PHISHING));
- // Don't show modal warning if user is using a GSUITE account.
- EXPECT_FALSE(PasswordProtectionService::ShouldShowModalWarning(
+ // Show modal warning otherwise
+ EXPECT_TRUE(password_protection_service_->ShouldShowModalWarning(
+ LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
+ /*matches_sync_password=*/true,
+ LoginReputationClientResponse::PHISHING));
+
+ // For a GSUITE account, don't show warning if password protection is off.
+ password_protection_service_->set_sync_account_type(
+ LoginReputationClientRequest::PasswordReuseEvent::GSUITE);
+ password_protection_service_->set_password_protection_trigger(
+ PASSWORD_PROTECTION_OFF);
+ EXPECT_EQ(PASSWORD_PROTECTION_OFF,
+ password_protection_service_->GetPasswordProtectionTriggerPref(
+ prefs::kPasswordProtectionWarningTrigger));
+ EXPECT_FALSE(password_protection_service_->ShouldShowModalWarning(
+ LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
+ /*matches_sync_password=*/true,
+ LoginReputationClientResponse::PHISHING));
+
+ // For a GSUITE account, show warning if password protection is set to
+ // PHISHING_REUSE.
+ password_protection_service_->set_password_protection_trigger(
+ PHISHING_REUSE);
+ EXPECT_EQ(PHISHING_REUSE,
+ password_protection_service_->GetPasswordProtectionTriggerPref(
+ prefs::kPasswordProtectionWarningTrigger));
+ EXPECT_TRUE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
/*matches_sync_password=*/true,
- LoginReputationClientRequest::PasswordReuseEvent::GSUITE,
LoginReputationClientResponse::PHISHING));
// When "warn_on_low_reputation" is set to false, don't show modal warning
// on LOW_REPUTATION verdict, only show on PHISHING verdict.
- EXPECT_FALSE(PasswordProtectionService::ShouldShowModalWarning(
+ password_protection_service_->set_sync_account_type(
+ LoginReputationClientRequest::PasswordReuseEvent::GMAIL);
+ EXPECT_FALSE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
/*matches_sync_password=*/true,
- LoginReputationClientRequest::PasswordReuseEvent::GMAIL,
LoginReputationClientResponse::LOW_REPUTATION));
- EXPECT_TRUE(PasswordProtectionService::ShouldShowModalWarning(
+ EXPECT_TRUE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
/*matches_sync_password=*/true,
- LoginReputationClientRequest::PasswordReuseEvent::GMAIL,
LoginReputationClientResponse::PHISHING));
}
{
@@ -1091,19 +1141,68 @@ TEST_P(PasswordProtectionServiceTest, VerifyShouldShowModalWarning) {
scoped_feature_list3.InitAndEnableFeatureWithParameters(
safe_browsing::kGoogleBrandedPhishingWarning,
{{"softer_warning", "true"}, {"warn_on_low_reputation", "true"}});
- EXPECT_TRUE(PasswordProtectionService::ShouldShowModalWarning(
+ EXPECT_TRUE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
/*matches_sync_password=*/true,
- LoginReputationClientRequest::PasswordReuseEvent::GMAIL,
LoginReputationClientResponse::LOW_REPUTATION));
- EXPECT_TRUE(PasswordProtectionService::ShouldShowModalWarning(
+ EXPECT_TRUE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
/*matches_sync_password=*/true,
- LoginReputationClientRequest::PasswordReuseEvent::GMAIL,
LoginReputationClientResponse::PHISHING));
}
}
+TEST_P(PasswordProtectionServiceTest, VerifyIsEventLoggingEnabled) {
+ {
+ // Event logging should be disabled if feature is disabled.
+ base::test::ScopedFeatureList scoped_feature_list1;
+ scoped_feature_list1.InitAndDisableFeature(kGaiaPasswordReuseReporting);
+ EXPECT_FALSE(password_protection_service_->IsEventLoggingEnabled());
+ }
+
+ {
+ base::test::ScopedFeatureList scoped_feature_list2;
+ scoped_feature_list2.InitAndEnableFeature(
+ safe_browsing::kGaiaPasswordReuseReporting);
+
+ // For user who is not signed-in, event logging should be disabled.
+ EXPECT_EQ(LoginReputationClientRequest::PasswordReuseEvent::NOT_SIGNED_IN,
+ password_protection_service_->GetSyncAccountType());
+ EXPECT_FALSE(password_protection_service_->IsEventLoggingEnabled());
+
+ // Event logging should be enable for all signed-in users, if
+ // password protection trigger is set to PHISHING_REUSE.
+ password_protection_service_->set_sync_account_type(
+ LoginReputationClientRequest::PasswordReuseEvent::GMAIL);
+ password_protection_service_->set_password_protection_trigger(
+ PHISHING_REUSE);
+ EXPECT_EQ(LoginReputationClientRequest::PasswordReuseEvent::GMAIL,
+ password_protection_service_->GetSyncAccountType());
+ EXPECT_TRUE(password_protection_service_->IsEventLoggingEnabled());
+
+ password_protection_service_->set_sync_account_type(
+ LoginReputationClientRequest::PasswordReuseEvent::GSUITE);
+ EXPECT_EQ(LoginReputationClientRequest::PasswordReuseEvent::GSUITE,
+ password_protection_service_->GetSyncAccountType());
+ EXPECT_TRUE(password_protection_service_->IsEventLoggingEnabled());
+
+ // If password protection trigger is sent to off, then event logging
+ // should be disabled.
+ password_protection_service_->set_password_protection_trigger(
+ PASSWORD_PROTECTION_OFF);
+ EXPECT_EQ(PASSWORD_PROTECTION_OFF,
+ password_protection_service_->GetPasswordProtectionTriggerPref(
+ prefs::kPasswordProtectionRiskTrigger));
+ EXPECT_FALSE(password_protection_service_->IsEventLoggingEnabled());
+ password_protection_service_->set_sync_account_type(
+ LoginReputationClientRequest::PasswordReuseEvent::GMAIL);
+ EXPECT_FALSE(password_protection_service_->IsEventLoggingEnabled());
+
+ // TODO(jialiul): update test when we start to introduce PASSWORD_REUSE
+ // trigger.
+ }
+}
+
INSTANTIATE_TEST_CASE_P(
InstSBERIncog,
PasswordProtectionServiceTest,
diff --git a/chromium/components/safe_browsing/renderer/DEPS b/chromium/components/safe_browsing/renderer/DEPS
index c2bc19a8c92..f8b2f6bddd2 100644
--- a/chromium/components/safe_browsing/renderer/DEPS
+++ b/chromium/components/safe_browsing/renderer/DEPS
@@ -7,4 +7,5 @@ include_rules = [
"+mojo/public/cpp",
"+net/http/redirect_info.h",
"+services/network/public/cpp",
+ "+services/service_manager/public/cpp",
]
diff --git a/chromium/components/safe_browsing/renderer/renderer_url_loader_throttle.cc b/chromium/components/safe_browsing/renderer/renderer_url_loader_throttle.cc
index c586f25e1cc..83d932bbb0c 100644
--- a/chromium/components/safe_browsing/renderer/renderer_url_loader_throttle.cc
+++ b/chromium/components/safe_browsing/renderer/renderer_url_loader_throttle.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
+#include "components/safe_browsing/common/safebrowsing_constants.h"
#include "components/safe_browsing/common/utils.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/url_request/redirect_info.h"
@@ -59,7 +60,7 @@ void RendererURLLoaderThrottle::WillStartRequest(
render_frame_id_, mojo::MakeRequest(&url_checker_), request->url,
request->method, headers, request->load_flags,
static_cast<content::ResourceType>(request->resource_type),
- request->has_user_gesture,
+ request->has_user_gesture, request->originated_from_service_worker,
base::BindOnce(&RendererURLLoaderThrottle::OnCheckUrlResult,
weak_factory_.GetWeakPtr()));
safe_browsing_ = nullptr;
@@ -181,7 +182,8 @@ void RendererURLLoaderThrottle::OnCompleteCheckInternal(
notifier_bindings_.reset();
pending_checks_ = 0;
pending_slow_checks_ = 0;
- delegate_->CancelWithError(net::ERR_ABORTED);
+ delegate_->CancelWithError(net::ERR_ABORTED,
+ kCustomCancelReasonForURLLoader);
}
}
diff --git a/chromium/components/safe_browsing/renderer/threat_dom_details.cc b/chromium/components/safe_browsing/renderer/threat_dom_details.cc
index eee6d491039..e8ebd8b5d55 100644
--- a/chromium/components/safe_browsing/renderer/threat_dom_details.cc
+++ b/chromium/components/safe_browsing/renderer/threat_dom_details.cc
@@ -15,8 +15,6 @@
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
-#include "components/safe_browsing/common/safebrowsing_messages.h"
-#include "components/safe_browsing/common/safebrowsing_types.h"
#include "components/safe_browsing/features.h"
#include "content/public/renderer/render_frame.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -112,13 +110,13 @@ void ParseTagAndAttributeParams(
});
}
-SafeBrowsingHostMsg_ThreatDOMDetails_Node* GetNodeForElement(
+mojom::ThreatDOMDetailsNode* GetNodeForElement(
const blink::WebNode& element,
const safe_browsing::ElementToNodeMap& element_to_node_map,
- std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node>* resources) {
+ std::vector<mojom::ThreatDOMDetailsNodePtr>* resources) {
DCHECK_GT(element_to_node_map.count(element), 0u);
size_t resource_index = element_to_node_map.at(element);
- return &(resources->at(resource_index));
+ return (*resources)[resource_index].get();
}
std::string TruncateAttributeString(const std::string& input) {
@@ -137,8 +135,8 @@ std::string TruncateAttributeString(const std::string& input) {
void HandleElement(
const blink::WebElement& element,
const std::vector<TagAndAttributesItem>& tag_and_attributes_list,
- SafeBrowsingHostMsg_ThreatDOMDetails_Node* summary_node,
- std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node>* resources,
+ mojom::ThreatDOMDetailsNode* summary_node,
+ std::vector<mojom::ThreatDOMDetailsNodePtr>* resources,
safe_browsing::ElementToNodeMap* element_to_node_map) {
// Retrieve the link and resolve the link in case it's relative.
blink::WebURL full_url =
@@ -149,17 +147,18 @@ void HandleElement(
summary_node->children.push_back(child_url);
}
- SafeBrowsingHostMsg_ThreatDOMDetails_Node child_node;
- child_node.url = child_url;
- child_node.tag_name = element.TagName().Utf8();
- child_node.parent = summary_node->url;
+ mojom::ThreatDOMDetailsNodePtr child_node =
+ mojom::ThreatDOMDetailsNode::New();
+ child_node->url = child_url;
+ child_node->tag_name = element.TagName().Utf8();
+ child_node->parent = summary_node->url;
// The body of an iframe may be in a different renderer. Look up the routing
// ID of the local or remote frame and store it with the iframe node. If this
// element is not a frame then the result of the lookup will be null.
blink::WebFrame* subframe = blink::WebFrame::FromFrameOwnerElement(element);
if (subframe) {
- child_node.child_frame_routing_id =
+ child_node->child_frame_routing_id =
content::RenderFrame::GetRoutingIdForWebFrame(subframe);
}
@@ -167,7 +166,7 @@ void HandleElement(
// configured in the finch study.
const auto& tag_attribute_iter = std::find_if(
tag_and_attributes_list.begin(), tag_and_attributes_list.end(),
- TagNameIs(base::ToLowerASCII(child_node.tag_name)));
+ TagNameIs(base::ToLowerASCII(child_node->tag_name)));
if (tag_attribute_iter != tag_and_attributes_list.end()) {
const std::vector<std::string> attributes_to_collect =
tag_attribute_iter->attributes;
@@ -176,10 +175,12 @@ void HandleElement(
if (!element.HasAttribute(attr_webstring)) {
continue;
}
- child_node.attributes.push_back(std::make_pair(
- attribute, TruncateAttributeString(
- element.GetAttribute(attr_webstring).Ascii())));
- if (child_node.attributes.size() == ThreatDOMDetails::kMaxAttributes) {
+ mojom::AttributeNameValuePtr attribute_name_value =
+ mojom::AttributeNameValue::New(
+ attribute, TruncateAttributeString(
+ element.GetAttribute(attr_webstring).Ascii()));
+ child_node->attributes.push_back(std::move(attribute_name_value));
+ if (child_node->attributes.size() == ThreatDOMDetails::kMaxAttributes) {
break;
}
}
@@ -189,14 +190,13 @@ void HandleElement(
// Then, if its parent is available, set the current node's parent ID, and
// also update the parent's children with the current node's ID.
const int child_id = static_cast<int>(element_to_node_map->size()) + 1;
- child_node.node_id = child_id;
+ child_node->node_id = child_id;
blink::WebNode cur_parent_element = element.ParentNode();
while (!cur_parent_element.IsNull()) {
if (element_to_node_map->count(cur_parent_element) > 0) {
- SafeBrowsingHostMsg_ThreatDOMDetails_Node* parent_node =
- GetNodeForElement(cur_parent_element, *element_to_node_map,
- resources);
- child_node.parent_node_id = parent_node->node_id;
+ mojom::ThreatDOMDetailsNode* parent_node = GetNodeForElement(
+ cur_parent_element, *element_to_node_map, resources);
+ child_node->parent_node_id = parent_node->node_id;
parent_node->child_node_ids.push_back(child_id);
// TODO(lpz): Consider also updating the URL-level parent/child mapping
@@ -211,7 +211,7 @@ void HandleElement(
}
}
// Add the child node to the list of resources.
- resources->push_back(child_node);
+ resources->push_back(std::move(child_node));
// .. and remember which index it was inserted at so we can look it up later.
(*element_to_node_map)[element] = resources->size() - 1;
}
@@ -263,47 +263,51 @@ uint32_t ThreatDOMDetails::kMaxAttributes = 100;
uint32_t ThreatDOMDetails::kMaxAttributeStringLength = 100;
// static
-ThreatDOMDetails* ThreatDOMDetails::Create(content::RenderFrame* render_frame) {
+ThreatDOMDetails* ThreatDOMDetails::Create(
+ content::RenderFrame* render_frame,
+ service_manager::BinderRegistry* registry) {
// Private constructor and public static Create() method to facilitate
// stubbing out this class for binary-size reduction purposes.
- return new ThreatDOMDetails(render_frame);
+ return new ThreatDOMDetails(render_frame, registry);
}
-ThreatDOMDetails::ThreatDOMDetails(content::RenderFrame* render_frame)
+void ThreatDOMDetails::OnThreatReporterRequest(
+ mojom::ThreatReporterRequest request) {
+ threat_reporter_bindings_.AddBinding(this, std::move(request));
+}
+
+ThreatDOMDetails::ThreatDOMDetails(content::RenderFrame* render_frame,
+ service_manager::BinderRegistry* registry)
: content::RenderFrameObserver(render_frame) {
ParseTagAndAttributeParams(&tag_and_attributes_list_);
+ // Base::Unretained() is safe here because both the registry and the
+ // ThreatDOMDetails are scoped to the same render frame.
+ registry->AddInterface(base::BindRepeating(
+ &ThreatDOMDetails::OnThreatReporterRequest, base::Unretained(this)));
}
ThreatDOMDetails::~ThreatDOMDetails() {}
-bool ThreatDOMDetails::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(ThreatDOMDetails, message)
- IPC_MESSAGE_HANDLER(SafeBrowsingMsg_GetThreatDOMDetails,
- OnGetThreatDOMDetails)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void ThreatDOMDetails::OnGetThreatDOMDetails() {
- std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node> resources;
+void ThreatDOMDetails::GetThreatDOMDetails(
+ GetThreatDOMDetailsCallback callback) {
+ std::vector<mojom::ThreatDOMDetailsNodePtr> resources;
ExtractResources(&resources);
// Notify the browser.
- Send(new SafeBrowsingHostMsg_ThreatDOMDetails(routing_id(), resources));
+ std::move(callback).Run(std::move(resources));
}
void ThreatDOMDetails::ExtractResources(
- std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node>* resources) {
+ std::vector<mojom::ThreatDOMDetailsNodePtr>* resources) {
blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
if (!frame)
return;
- SafeBrowsingHostMsg_ThreatDOMDetails_Node details_node;
+ mojom::ThreatDOMDetailsNodePtr details_node =
+ mojom::ThreatDOMDetailsNode::New();
blink::WebDocument document = frame->GetDocument();
- details_node.url = GURL(document.Url());
+ details_node->url = GURL(document.Url());
if (document.IsNull()) {
// Nothing in this frame. Just report its URL.
- resources->push_back(details_node);
+ resources->push_back(std::move(details_node));
return;
}
@@ -313,8 +317,8 @@ void ThreatDOMDetails::ExtractResources(
bool max_nodes_exceeded = false;
for (; !element.IsNull(); element = elements.NextItem()) {
if (ShouldHandleElement(element, tag_and_attributes_list_)) {
- HandleElement(element, tag_and_attributes_list_, &details_node, resources,
- &element_to_node_map);
+ HandleElement(element, tag_and_attributes_list_, details_node.get(),
+ resources, &element_to_node_map);
if (resources->size() >= kMaxNodes) {
// We have reached kMaxNodes, exit early.
max_nodes_exceeded = true;
@@ -324,7 +328,7 @@ void ThreatDOMDetails::ExtractResources(
}
UMA_HISTOGRAM_BOOLEAN("SafeBrowsing.ThreatReport.MaxNodesExceededInFrame",
max_nodes_exceeded);
- resources->push_back(details_node);
+ resources->push_back(std::move(details_node));
}
void ThreatDOMDetails::OnDestruct() {
diff --git a/chromium/components/safe_browsing/renderer/threat_dom_details.h b/chromium/components/safe_browsing/renderer/threat_dom_details.h
index 1b1e3933cac..9aae208b346 100644
--- a/chromium/components/safe_browsing/renderer/threat_dom_details.h
+++ b/chromium/components/safe_browsing/renderer/threat_dom_details.h
@@ -13,9 +13,10 @@
#include "base/compiler_specific.h"
#include "base/feature_list.h"
+#include "components/safe_browsing/common/safe_browsing.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
-
-struct SafeBrowsingHostMsg_ThreatDOMDetails_Node;
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
namespace safe_browsing {
@@ -37,7 +38,8 @@ class TagAndAttributesItem {
};
// There is one ThreatDOMDetails per RenderFrame.
-class ThreatDOMDetails : public content::RenderFrameObserver {
+class ThreatDOMDetails : public content::RenderFrameObserver,
+ public mojom::ThreatReporter {
public:
// An upper limit on the number of nodes we collect. Not const for the test.
static uint32_t kMaxNodes;
@@ -49,26 +51,30 @@ class ThreatDOMDetails : public content::RenderFrameObserver {
// An upper limit on the length of an attribute string.
static uint32_t kMaxAttributeStringLength;
- static ThreatDOMDetails* Create(content::RenderFrame* render_frame);
+ static ThreatDOMDetails* Create(content::RenderFrame* render_frame,
+ service_manager::BinderRegistry* registry);
~ThreatDOMDetails() override;
// Begins extracting resource urls for the page currently loaded in
// this object's RenderFrame.
// Exposed for testing.
- void ExtractResources(
- std::vector<SafeBrowsingHostMsg_ThreatDOMDetails_Node>* resources);
+ void ExtractResources(std::vector<mojom::ThreatDOMDetailsNodePtr>* resources);
private:
// Creates a ThreatDOMDetails for the specified RenderFrame.
// The ThreatDOMDetails should be destroyed prior to destroying
// the RenderFrame.
- explicit ThreatDOMDetails(content::RenderFrame* render_frame);
+ ThreatDOMDetails(content::RenderFrame* render_frame,
+ service_manager::BinderRegistry* registry);
- // RenderFrameObserver implementation.
- bool OnMessageReceived(const IPC::Message& message) override;
void OnDestruct() override;
- void OnGetThreatDOMDetails();
+ // safe_browsing::mojom::ThreatReporter:
+ void GetThreatDOMDetails(GetThreatDOMDetailsCallback callback) override;
+
+ void OnThreatReporterRequest(mojom::ThreatReporterRequest request);
+
+ mojo::BindingSet<mojom::ThreatReporter> threat_reporter_bindings_;
// A list of tag names and associates attributes, used to determine which
// elements need to be collected.
diff --git a/chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle.cc b/chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle.cc
index 42c39a332f1..bcc49cbaea4 100644
--- a/chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle.cc
+++ b/chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle.cc
@@ -62,7 +62,8 @@ void WebSocketSBHandshakeThrottle::ThrottleHandshake(
safe_browsing_->CreateCheckerAndCheck(
render_frame_id, mojo::MakeRequest(&url_checker_), url, "GET",
net::HttpRequestHeaders(), load_flags,
- content::RESOURCE_TYPE_SUB_RESOURCE, false,
+ content::RESOURCE_TYPE_SUB_RESOURCE, false /* has_user_gesture */,
+ false /* originated_from_service_worker */,
base::BindOnce(&WebSocketSBHandshakeThrottle::OnCheckResult,
weak_factory_.GetWeakPtr()));
diff --git a/chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle_unittest.cc b/chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle_unittest.cc
index 991c1508838..7d6dc46c66e 100644
--- a/chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle_unittest.cc
+++ b/chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle_unittest.cc
@@ -31,7 +31,8 @@ class FakeSafeBrowsing : public mojom::SafeBrowsing {
: render_frame_id_(),
load_flags_(-1),
resource_type_(),
- has_user_gesture_(false) {}
+ has_user_gesture_(false),
+ originated_from_service_worker_(false) {}
void CreateCheckerAndCheck(int32_t render_frame_id,
mojom::SafeBrowsingUrlCheckerRequest request,
@@ -41,6 +42,7 @@ class FakeSafeBrowsing : public mojom::SafeBrowsing {
int32_t load_flags,
content::ResourceType resource_type,
bool has_user_gesture,
+ bool originated_from_service_worker,
CreateCheckerAndCheckCallback callback) override {
render_frame_id_ = render_frame_id;
request_ = std::move(request);
@@ -50,6 +52,7 @@ class FakeSafeBrowsing : public mojom::SafeBrowsing {
load_flags_ = load_flags;
resource_type_ = resource_type;
has_user_gesture_ = has_user_gesture;
+ originated_from_service_worker_ = originated_from_service_worker;
callback_ = std::move(callback);
run_loop_.Quit();
}
@@ -66,6 +69,7 @@ class FakeSafeBrowsing : public mojom::SafeBrowsing {
int32_t load_flags_;
content::ResourceType resource_type_;
bool has_user_gesture_;
+ bool originated_from_service_worker_;
CreateCheckerAndCheckCallback callback_;
base::RunLoop run_loop_;
};
@@ -127,6 +131,7 @@ TEST_F(WebSocketSBHandshakeThrottleTest, CheckArguments) {
EXPECT_EQ(0, safe_browsing_.load_flags_);
EXPECT_EQ(content::RESOURCE_TYPE_SUB_RESOURCE, safe_browsing_.resource_type_);
EXPECT_FALSE(safe_browsing_.has_user_gesture_);
+ EXPECT_FALSE(safe_browsing_.originated_from_service_worker_);
EXPECT_TRUE(safe_browsing_.callback_);
}
diff --git a/chromium/components/safe_browsing/triggers/ad_sampler_trigger.cc b/chromium/components/safe_browsing/triggers/ad_sampler_trigger.cc
index ba8237b4fc8..30294e8c7da 100644
--- a/chromium/components/safe_browsing/triggers/ad_sampler_trigger.cc
+++ b/chromium/components/safe_browsing/triggers/ad_sampler_trigger.cc
@@ -32,6 +32,10 @@ const char kAdSamplerFrequencyDenominatorParam[] =
// A frequency denominator with this value indicates sampling is disabled.
const size_t kSamplerFrequencyDisabled = 0;
+// Number of milliseconds to wait after a page finished loading before starting
+// a report. Allows ads which load in the background to finish loading.
+const int64_t kAdSampleCollectionStartDelayMilliseconds = 1000;
+
// Number of milliseconds to allow data collection to run before sending a
// report (since this trigger runs in the background).
const int64_t kAdSampleCollectionPeriodMilliseconds = 5000;
@@ -99,11 +103,15 @@ AdSamplerTrigger::AdSamplerTrigger(
history::HistoryService* history_service)
: content::WebContentsObserver(web_contents),
sampler_frequency_denominator_(GetSamplerFrequencyDenominator()),
+ start_report_delay_ms_(kAdSampleCollectionStartDelayMilliseconds),
finish_report_delay_ms_(kAdSampleCollectionPeriodMilliseconds),
trigger_manager_(trigger_manager),
prefs_(prefs),
request_context_(request_context),
- history_service_(history_service) {}
+ history_service_(history_service),
+ task_runner_(content::BrowserThread::GetTaskRunnerForThread(
+ content::BrowserThread::UI)),
+ weak_ptr_factory_(this) {}
AdSamplerTrigger::~AdSamplerTrigger() {}
@@ -141,6 +149,16 @@ void AdSamplerTrigger::DidFinishLoad(
return;
}
+ // Create a report after a short delay. The delay gives more time for ads to
+ // finish loading in the background. This is best-effort.
+ task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&AdSamplerTrigger::CreateAdSampleReport,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(start_report_delay_ms_));
+}
+
+void AdSamplerTrigger::CreateAdSampleReport() {
SBErrorOptions error_options =
TriggerManager::GetSBErrorDisplayOptions(*prefs_, *web_contents());
@@ -163,8 +181,8 @@ void AdSamplerTrigger::DidFinishLoad(
// ads that are detected during this delay will be rejected by TriggerManager
// because a report is already being collected, so we won't send multiple
// reports for the same page.
- content::BrowserThread::PostDelayedTask(
- content::BrowserThread::UI, FROM_HERE,
+ task_runner_->PostDelayedTask(
+ FROM_HERE,
base::BindOnce(
IgnoreResult(&TriggerManager::FinishCollectingThreatDetails),
base::Unretained(trigger_manager_), TriggerType::AD_SAMPLE,
@@ -176,4 +194,13 @@ void AdSamplerTrigger::DidFinishLoad(
MAX_ACTIONS);
}
+void AdSamplerTrigger::SetSamplerFrequencyForTest(size_t denominator) {
+ sampler_frequency_denominator_ = denominator;
+}
+
+void AdSamplerTrigger::SetTaskRunnerForTest(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ task_runner_ = task_runner;
+}
+
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/triggers/ad_sampler_trigger.h b/chromium/components/safe_browsing/triggers/ad_sampler_trigger.h
index 21ca643dc20..20190be11ff 100644
--- a/chromium/components/safe_browsing/triggers/ad_sampler_trigger.h
+++ b/chromium/components/safe_browsing/triggers/ad_sampler_trigger.h
@@ -6,6 +6,7 @@
#define COMPONENTS_SAFE_BROWSING_TRIGGERS_AD_SAMPLER_TRIGGER_H_
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
@@ -80,10 +81,24 @@ class AdSamplerTrigger : public content::WebContentsObserver,
net::URLRequestContextGetter* request_context,
history::HistoryService* history_service);
+ // Called to create an ad sample report.
+ void CreateAdSampleReport();
+
+ // Sets |sampler_frequency_denominator_| for tests.
+ void SetSamplerFrequencyForTest(size_t denominator);
+
+ // Sets a task runner to use for tests.
+ void SetTaskRunnerForTest(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
// Ad samples will be collected with frequency
// 1/|sampler_frequency_denominator_|
size_t sampler_frequency_denominator_;
+ // The delay (in milliseconds) to wait before starting a report. Can be
+ // ovewritten for tests.
+ int64_t start_report_delay_ms_;
+
// The delay (in milliseconds) to wait before finishing a report. Can be
// overwritten for tests.
int64_t finish_report_delay_ms_;
@@ -96,6 +111,12 @@ class AdSamplerTrigger : public content::WebContentsObserver,
net::URLRequestContextGetter* request_context_;
history::HistoryService* history_service_;
+ // Task runner for posting delayed tasks. Normally set to the runner for the
+ // UI thread, but can be overwritten for tests.
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ base::WeakPtrFactory<AdSamplerTrigger> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(AdSamplerTrigger);
};
diff --git a/chromium/components/safe_browsing/triggers/ad_sampler_trigger_unittest.cc b/chromium/components/safe_browsing/triggers/ad_sampler_trigger_unittest.cc
index 02bc9e56057..2eba249b2de 100644
--- a/chromium/components/safe_browsing/triggers/ad_sampler_trigger_unittest.cc
+++ b/chromium/components/safe_browsing/triggers/ad_sampler_trigger_unittest.cc
@@ -7,6 +7,7 @@
#include "base/metrics/field_trial_params.h"
#include "base/test/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
+#include "base/test/test_simple_task_runner.h"
#include "components/prefs/testing_pref_service.h"
#include "components/safe_browsing/features.h"
#include "components/safe_browsing/triggers/trigger_manager.h"
@@ -58,7 +59,7 @@ class MockTriggerManager : public TriggerManager {
class AdSamplerTriggerTest : public content::RenderViewHostTestHarness {
public:
- AdSamplerTriggerTest() {}
+ AdSamplerTriggerTest() : task_runner_(new base::TestSimpleTaskRunner) {}
~AdSamplerTriggerTest() override {}
void SetUp() override {
@@ -74,10 +75,13 @@ class AdSamplerTriggerTest : public content::RenderViewHostTestHarness {
void CreateTriggerWithFrequency(const size_t denominator) {
safe_browsing::AdSamplerTrigger::CreateForWebContents(
web_contents(), &trigger_manager_, &prefs_, nullptr, nullptr);
- safe_browsing::AdSamplerTrigger::FromWebContents(web_contents())
- ->sampler_frequency_denominator_ = denominator;
- safe_browsing::AdSamplerTrigger::FromWebContents(web_contents())
- ->finish_report_delay_ms_ = 0;
+
+ safe_browsing::AdSamplerTrigger* ad_sampler =
+ safe_browsing::AdSamplerTrigger::FromWebContents(web_contents());
+ ad_sampler->SetSamplerFrequencyForTest(denominator);
+
+ // Give the trigger a test task runner that we can synchronize on.
+ ad_sampler->SetTaskRunnerForTest(task_runner_);
}
// Returns the final RenderFrameHost after navigation commits.
@@ -110,6 +114,11 @@ class AdSamplerTriggerTest : public content::RenderViewHostTestHarness {
return NavigateFrame(url, subframe);
}
+ void WaitForTaskRunnerIdle() {
+ task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ }
+
MockTriggerManager* get_trigger_manager() { return &trigger_manager_; }
base::HistogramTester* get_histograms() { return &histograms_; }
@@ -117,6 +126,7 @@ class AdSamplerTriggerTest : public content::RenderViewHostTestHarness {
TestingPrefServiceSimple prefs_;
MockTriggerManager trigger_manager_;
base::HistogramTester histograms_;
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
};
TEST_F(AdSamplerTriggerTest, TriggerDisabledBySamplingFrequency) {
@@ -188,6 +198,9 @@ TEST_F(AdSamplerTriggerTest, PageWithMultipleAds) {
CreateAndNavigateSubFrame(kAdUrl, kNonAdName, main_frame);
CreateAndNavigateSubFrame(kNonAdUrl, kAdName, main_frame);
+ // Wait for any posted tasks to finish.
+ WaitForTaskRunnerIdle();
+
// Three navigations (main frame, two subframes). Main frame with no ads, and
// two sampled ads
get_histograms()->ExpectBucketCount(kAdSamplerTriggerActionMetricName,
@@ -217,6 +230,9 @@ TEST_F(AdSamplerTriggerTest, ReportRejectedByTriggerManager) {
CreateAndNavigateSubFrame(kAdUrl, kNonAdName, main_frame);
CreateAndNavigateSubFrame(kNonAdUrl, kNonAdName, main_frame);
+ // Wait for any posted tasks to finish.
+ WaitForTaskRunnerIdle();
+
// Three navigations (main frame, two subframes). Two frames with no ads, and
// one ad rejected by trigger manager.
get_histograms()->ExpectBucketCount(kAdSamplerTriggerActionMetricName,
diff --git a/chromium/components/safe_browsing/triggers/trigger_manager.cc b/chromium/components/safe_browsing/triggers/trigger_manager.cc
index 9ce8fad1504..ad7a05f8f8a 100644
--- a/chromium/components/safe_browsing/triggers/trigger_manager.cc
+++ b/chromium/components/safe_browsing/triggers/trigger_manager.cc
@@ -105,6 +105,7 @@ SBErrorOptions TriggerManager::GetSBErrorDisplayOptions(
web_contents.GetBrowserContext()->IsOffTheRecord(),
IsExtendedReportingEnabled(pref_service),
IsScout(pref_service),
+ IsExtendedReportingPolicyManaged(pref_service),
/*is_proceed_anyway_disabled=*/false,
/*should_open_links_in_new_tab=*/false,
/*show_back_to_safety_button=*/true,
diff --git a/chromium/components/safe_browsing/triggers/trigger_manager_unittest.cc b/chromium/components/safe_browsing/triggers/trigger_manager_unittest.cc
index 2a2893ee2b5..316addac3e0 100644
--- a/chromium/components/safe_browsing/triggers/trigger_manager_unittest.cc
+++ b/chromium/components/safe_browsing/triggers/trigger_manager_unittest.cc
@@ -82,6 +82,10 @@ class TriggerManagerTest : public ::testing::Test {
pref_service_.SetBoolean(pref, value);
}
+ void SetManagedPref(const std::string& pref, bool value) {
+ pref_service_.SetManagedPref(pref, std::make_unique<base::Value>(value));
+ }
+
bool GetPref(const std::string& pref) {
return pref_service_.GetBoolean(pref);
}
@@ -340,6 +344,20 @@ TEST_F(TriggerManagerTest, NoCollectionWhenOutOfQuota) {
EXPECT_EQ(nullptr, data_collectors_map().at(web_contents).threat_details);
}
+TEST_F(TriggerManagerTest, NoCollectionWhenSBERDisabledByPolicy) {
+ // Confirm that disabling SBER through an enterprise policy does disable
+ // triggers.
+ content::WebContents* web_contents = CreateWebContents();
+
+ SetManagedPref(prefs::kSafeBrowsingScoutReportingEnabled, false);
+ EXPECT_FALSE(
+ StartCollectingThreatDetails(TriggerType::AD_SAMPLE, web_contents));
+ EXPECT_TRUE(data_collectors_map().empty());
+ EXPECT_FALSE(FinishCollectingThreatDetails(TriggerType::AD_SAMPLE,
+ web_contents, false));
+ EXPECT_TRUE(data_collectors_map().empty());
+}
+
TEST_F(TriggerManagerTest, AdSamplerTrigger) {
// Check the conditions required for the Ad Sampler trigger to fire. It needs
// opt-in to start collecting data, scout opt-in, and quota.
diff --git a/chromium/components/safe_browsing/triggers/trigger_throttler.cc b/chromium/components/safe_browsing/triggers/trigger_throttler.cc
index 85e0da91af1..1f10f982a9a 100644
--- a/chromium/components/safe_browsing/triggers/trigger_throttler.cc
+++ b/chromium/components/safe_browsing/triggers/trigger_throttler.cc
@@ -98,15 +98,15 @@ size_t GetDailyQuotaForTrigger(
} // namespace
-TriggerThrottler::TriggerThrottler() : clock_(new base::DefaultClock()) {
+TriggerThrottler::TriggerThrottler()
+ : clock_(base::DefaultClock::GetInstance()) {
ParseTriggerTypeAndQuotaParam(&trigger_type_and_quota_list_);
}
TriggerThrottler::~TriggerThrottler() {}
-void TriggerThrottler::SetClockForTesting(
- std::unique_ptr<base::Clock> test_clock) {
- clock_ = std::move(test_clock);
+void TriggerThrottler::SetClockForTesting(base::Clock* test_clock) {
+ clock_ = test_clock;
}
bool TriggerThrottler::TriggerCanFire(const TriggerType trigger_type) const {
diff --git a/chromium/components/safe_browsing/triggers/trigger_throttler.h b/chromium/components/safe_browsing/triggers/trigger_throttler.h
index cc74c555ab0..b5b2b6447bd 100644
--- a/chromium/components/safe_browsing/triggers/trigger_throttler.h
+++ b/chromium/components/safe_browsing/triggers/trigger_throttler.h
@@ -53,7 +53,7 @@ class TriggerThrottler {
void TriggerFired(TriggerType trigger_type);
protected:
- void SetClockForTesting(std::unique_ptr<base::Clock> test_clock);
+ void SetClockForTesting(base::Clock* test_clock);
private:
friend class TriggerThrottlerTest;
@@ -62,7 +62,7 @@ class TriggerThrottler {
void CleanupOldEvents();
// Can be set for testing.
- std::unique_ptr<base::Clock> clock_;
+ base::Clock* clock_;
// Stores each trigger type that fired along with the timestamps of when it
// fired.
diff --git a/chromium/components/safe_browsing/triggers/trigger_throttler_unittest.cc b/chromium/components/safe_browsing/triggers/trigger_throttler_unittest.cc
index a2e7ee73ec1..f5a6308f73d 100644
--- a/chromium/components/safe_browsing/triggers/trigger_throttler_unittest.cc
+++ b/chromium/components/safe_browsing/triggers/trigger_throttler_unittest.cc
@@ -26,7 +26,7 @@ class TriggerThrottlerTest : public ::testing::Test {
TriggerThrottler* throttler() { return &trigger_throttler_; }
void SetTestClock(base::Clock* clock) {
- trigger_throttler_.SetClockForTesting(base::WrapUnique(clock));
+ trigger_throttler_.SetClockForTesting(clock);
}
std::vector<time_t> GetEventTimestampsForTriggerType(
@@ -98,11 +98,11 @@ TEST_F(TriggerThrottlerTest, TriggerQuotaResetsAfterOneDay) {
// We initialize the test clock to several days ago and fire some events to
// use up quota. We then advance the clock by a day and ensure quota is
// available again.
- base::SimpleTestClock* test_clock(new base::SimpleTestClock);
- test_clock->SetNow(base::Time::Now() - base::TimeDelta::FromDays(10));
- time_t base_ts = test_clock->Now().ToTimeT();
+ base::SimpleTestClock test_clock;
+ test_clock.SetNow(base::Time::Now() - base::TimeDelta::FromDays(10));
+ time_t base_ts = test_clock.Now().ToTimeT();
- SetTestClock(test_clock);
+ SetTestClock(&test_clock);
SetQuotaForTriggerType(TriggerType::AD_SAMPLE, 2);
// First two triggers should work
@@ -122,9 +122,9 @@ TEST_F(TriggerThrottlerTest, TriggerQuotaResetsAfterOneDay) {
// Move the clock forward by 1 day (and a bit) and try the trigger again,
// quota should be available now.
- test_clock->Advance(base::TimeDelta::FromDays(1) +
- base::TimeDelta::FromSeconds(1));
- time_t advanced_ts = test_clock->Now().ToTimeT();
+ test_clock.Advance(base::TimeDelta::FromDays(1) +
+ base::TimeDelta::FromSeconds(1));
+ time_t advanced_ts = test_clock.Now().ToTimeT();
EXPECT_TRUE(throttler()->TriggerCanFire(TriggerType::AD_SAMPLE));
// The previous time stamps should remain in the throttler.
diff --git a/chromium/components/search_engines/BUILD.gn b/chromium/components/search_engines/BUILD.gn
index 06519c8395d..90e00b4b68a 100644
--- a/chromium/components/search_engines/BUILD.gn
+++ b/chromium/components/search_engines/BUILD.gn
@@ -121,6 +121,7 @@ source_set("unit_tests") {
"keyword_table_unittest.cc",
"search_engine_data_type_controller_unittest.cc",
"search_host_to_urls_map_unittest.cc",
+ "template_url_data_unittest.cc",
"template_url_prepopulate_data_unittest.cc",
"template_url_service_util_unittest.cc",
"template_url_unittest.cc",
diff --git a/chromium/components/search_engines/search_terms_data.cc b/chromium/components/search_engines/search_terms_data.cc
index 8226775f861..1bd615e5bb4 100644
--- a/chromium/components/search_engines/search_terms_data.cc
+++ b/chromium/components/search_engines/search_terms_data.cc
@@ -65,3 +65,7 @@ std::string SearchTermsData::GetYandexReferralID() const {
std::string SearchTermsData::GetMailRUReferralID() const {
return std::string();
}
+
+size_t SearchTermsData::EstimateMemoryUsage() const {
+ return 0;
+}
diff --git a/chromium/components/search_engines/search_terms_data.h b/chromium/components/search_engines/search_terms_data.h
index c8a67af9acc..5f399b2ebd7 100644
--- a/chromium/components/search_engines/search_terms_data.h
+++ b/chromium/components/search_engines/search_terms_data.h
@@ -61,6 +61,10 @@ class SearchTermsData {
// from the omnibox (returns the empty string if not supported/applicable).
virtual std::string GetMailRUReferralID() const;
+ // Estimates dynamic memory usage.
+ // See base/trace_event/memory_usage_estimator.h for more info.
+ virtual size_t EstimateMemoryUsage() const;
+
private:
DISALLOW_COPY_AND_ASSIGN(SearchTermsData);
};
diff --git a/chromium/components/search_engines/template_url.cc b/chromium/components/search_engines/template_url.cc
index 3cdecf9c9f6..93b00686d26 100644
--- a/chromium/components/search_engines/template_url.cc
+++ b/chromium/components/search_engines/template_url.cc
@@ -21,6 +21,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/memory_usage_estimator.h"
#include "build/build_config.h"
#include "components/google/core/browser/google_util.h"
#include "components/search_engines/search_engines_switches.h"
@@ -70,19 +71,23 @@ const char kOutputEncodingType[] = "UTF-8";
// Attempts to encode |terms| and |original_query| in |encoding| and escape
// them. |terms| may be escaped as path or query depending on |is_in_query|;
-// |original_query| is always escaped as query. Returns whether the encoding
-// process succeeded.
+// |original_query| is always escaped as query. If |force_encode| is true
+// encoding ignores errors and function always returns true. Otherwise function
+// returns whether the encoding process succeeded.
bool TryEncoding(const base::string16& terms,
const base::string16& original_query,
const char* encoding,
bool is_in_query,
+ bool force_encode,
base::string16* escaped_terms,
base::string16* escaped_original_query) {
DCHECK(escaped_terms);
DCHECK(escaped_original_query);
+ base::OnStringConversionError::Type error_handling =
+ force_encode ? base::OnStringConversionError::SKIP
+ : base::OnStringConversionError::FAIL;
std::string encoded_terms;
- if (!base::UTF16ToCodepage(terms, encoding,
- base::OnStringConversionError::SKIP, &encoded_terms))
+ if (!base::UTF16ToCodepage(terms, encoding, error_handling, &encoded_terms))
return false;
*escaped_terms = base::UTF8ToUTF16(is_in_query ?
net::EscapeQueryParamValue(encoded_terms, true) :
@@ -90,8 +95,8 @@ bool TryEncoding(const base::string16& terms,
if (original_query.empty())
return true;
std::string encoded_original_query;
- if (!base::UTF16ToCodepage(original_query, encoding,
- base::OnStringConversionError::SKIP, &encoded_original_query))
+ if (!base::UTF16ToCodepage(original_query, encoding, error_handling,
+ &encoded_original_query))
return false;
*escaped_original_query = base::UTF8ToUTF16(
net::EscapeQueryParamValue(encoded_original_query, true));
@@ -196,6 +201,24 @@ TemplateURLRef::SearchTermsArgs::SearchTermsArgs(const SearchTermsArgs& other) =
TemplateURLRef::SearchTermsArgs::~SearchTermsArgs() {
}
+size_t TemplateURLRef::SearchTermsArgs::EstimateMemoryUsage() const {
+ size_t res = 0;
+
+ res += base::trace_event::EstimateMemoryUsage(search_terms);
+ res += base::trace_event::EstimateMemoryUsage(original_query);
+ res += base::trace_event::EstimateMemoryUsage(assisted_query_stats);
+ res += base::trace_event::EstimateMemoryUsage(current_page_url);
+ res += base::trace_event::EstimateMemoryUsage(session_token);
+ res += base::trace_event::EstimateMemoryUsage(prefetch_query);
+ res += base::trace_event::EstimateMemoryUsage(prefetch_query_type);
+ res += base::trace_event::EstimateMemoryUsage(suggest_query_params);
+ res += base::trace_event::EstimateMemoryUsage(image_thumbnail_content);
+ res += base::trace_event::EstimateMemoryUsage(image_url);
+ res += base::trace_event::EstimateMemoryUsage(contextual_search_params);
+
+ return res;
+}
+
TemplateURLRef::SearchTermsArgs::ContextualSearchParams::
ContextualSearchParams()
: version(-1),
@@ -216,6 +239,12 @@ TemplateURLRef::SearchTermsArgs::ContextualSearchParams::
~ContextualSearchParams() {
}
+size_t
+TemplateURLRef::SearchTermsArgs::ContextualSearchParams::EstimateMemoryUsage()
+ const {
+ return base::trace_event::EstimateMemoryUsage(home_country);
+}
+
// TemplateURLRef -------------------------------------------------------------
TemplateURLRef::TemplateURLRef(const TemplateURL* owner, Type type)
@@ -282,6 +311,32 @@ bool TemplateURLRef::UsesPOSTMethod(
return !post_params_.empty();
}
+size_t TemplateURLRef::EstimateMemoryUsage() const {
+ size_t res = 0;
+
+ res += base::trace_event::EstimateMemoryUsage(parsed_url_);
+ res += base::trace_event::EstimateMemoryUsage(replacements_);
+ res += base::trace_event::EstimateMemoryUsage(host_);
+ res += base::trace_event::EstimateMemoryUsage(port_);
+ res += base::trace_event::EstimateMemoryUsage(path_);
+ res += base::trace_event::EstimateMemoryUsage(search_term_key_);
+ res += base::trace_event::EstimateMemoryUsage(search_term_value_prefix_);
+ res += base::trace_event::EstimateMemoryUsage(search_term_value_suffix_);
+ res += base::trace_event::EstimateMemoryUsage(post_params_);
+
+ return res;
+}
+
+size_t TemplateURLRef::PostParam::EstimateMemoryUsage() const {
+ size_t res = 0;
+
+ res += base::trace_event::EstimateMemoryUsage(name);
+ res += base::trace_event::EstimateMemoryUsage(value);
+ res += base::trace_event::EstimateMemoryUsage(content_type);
+
+ return res;
+}
+
bool TemplateURLRef::EncodeFormData(const PostParams& post_params,
PostContent* post_content) const {
if (post_params.empty())
@@ -1153,6 +1208,10 @@ TemplateURL::AssociatedExtensionInfo::AssociatedExtensionInfo(
TemplateURL::AssociatedExtensionInfo::~AssociatedExtensionInfo() {
}
+size_t TemplateURL::AssociatedExtensionInfo::EstimateMemoryUsage() const {
+ return base::trace_event::EstimateMemoryUsage(extension_id);
+}
+
TemplateURL::TemplateURL(const TemplateURLData& data, Type type)
: data_(data),
suggestions_url_ref_(this, TemplateURLRef::SUGGEST),
@@ -1370,11 +1429,11 @@ void TemplateURL::EncodeSearchTerms(
std::vector<std::string> encodings(input_encodings());
if (std::find(encodings.begin(), encodings.end(), "UTF-8") == encodings.end())
encodings.push_back("UTF-8");
- for (std::vector<std::string>::const_iterator i(encodings.begin());
- i != encodings.end(); ++i) {
+ for (auto i = encodings.begin(); i != encodings.end(); ++i) {
if (TryEncoding(search_terms_args.search_terms,
- search_terms_args.original_query, i->c_str(),
- is_in_query, encoded_terms, encoded_original_query)) {
+ search_terms_args.original_query, i->c_str(), is_in_query,
+ std::next(i) == encodings.end(), encoded_terms,
+ encoded_original_query)) {
*input_encoding = *i;
return;
}
@@ -1448,6 +1507,20 @@ void TemplateURL::InvalidateCachedValues() const {
contextual_search_url_ref_.InvalidateCachedValues();
}
+size_t TemplateURL::EstimateMemoryUsage() const {
+ size_t res = 0;
+
+ res += base::trace_event::EstimateMemoryUsage(data_);
+ res += base::trace_event::EstimateMemoryUsage(url_refs_);
+ res += base::trace_event::EstimateMemoryUsage(suggestions_url_ref_);
+ res += base::trace_event::EstimateMemoryUsage(image_url_ref_);
+ res += base::trace_event::EstimateMemoryUsage(new_tab_url_ref_);
+ res += base::trace_event::EstimateMemoryUsage(contextual_search_url_ref_);
+ res += base::trace_event::EstimateMemoryUsage(extension_info_);
+
+ return res;
+}
+
void TemplateURL::ResizeURLRefVector() {
const size_t new_size = data_.alternate_urls.size() + 1;
if (url_refs_.size() == new_size)
diff --git a/chromium/components/search_engines/template_url.h b/chromium/components/search_engines/template_url.h
index c6e517191eb..57b7666b6d4 100644
--- a/chromium/components/search_engines/template_url.h
+++ b/chromium/components/search_engines/template_url.h
@@ -5,8 +5,7 @@
#ifndef COMPONENTS_SEARCH_ENGINES_TEMPLATE_URL_H_
#define COMPONENTS_SEARCH_ENGINES_TEMPLATE_URL_H_
-#include <stddef.h>
-
+#include <cstddef>
#include <memory>
#include <string>
#include <utility>
@@ -89,6 +88,10 @@ class TemplateURLRef {
ContextualSearchParams(const ContextualSearchParams& other);
~ContextualSearchParams();
+ // Estimates dynamic memory usage.
+ // See base/trace_event/memory_usage_estimator.h for more info.
+ size_t EstimateMemoryUsage() const;
+
// The version of contextual search.
int version;
@@ -102,6 +105,10 @@ class TemplateURLRef {
std::string home_country;
};
+ // Estimates dynamic memory usage.
+ // See base/trace_event/memory_usage_estimator.h for more info.
+ size_t EstimateMemoryUsage() const;
+
// The search terms (query).
base::string16 search_terms;
@@ -274,6 +281,10 @@ class TemplateURLRef {
// Whether the URL uses POST (as opposed to GET).
bool UsesPOSTMethod(const SearchTermsData& search_terms_data) const;
+ // Estimates dynamic memory usage.
+ // See base/trace_event/memory_usage_estimator.h for more info.
+ size_t EstimateMemoryUsage() const;
+
private:
friend class TemplateURL;
friend class TemplateURLTest;
@@ -339,6 +350,10 @@ class TemplateURLRef {
std::string name;
std::string value;
std::string content_type;
+
+ // Estimates dynamic memory usage.
+ // See base/trace_event/memory_usage_estimator.h for more info.
+ size_t EstimateMemoryUsage() const;
};
// The list of elements to replace.
@@ -485,6 +500,10 @@ class TemplateURL {
bool wants_to_be_default_engine);
~AssociatedExtensionInfo();
+ // Estimates dynamic memory usage.
+ // See base/trace_event/memory_usage_estimator.h for more info.
+ size_t EstimateMemoryUsage() const;
+
std::string extension_id;
// Used to resolve conflicts when there are multiple extensions specifying
@@ -668,6 +687,10 @@ class TemplateURL {
// it should be called after SearchTermsData has been changed.
void InvalidateCachedValues() const;
+ // Estimates dynamic memory usage.
+ // See base/trace_event/memory_usage_estimator.h for more info.
+ size_t EstimateMemoryUsage() const;
+
private:
friend class TemplateURLService;
diff --git a/chromium/components/search_engines/template_url_data.cc b/chromium/components/search_engines/template_url_data.cc
index a607cd64c94..1bf7f24272c 100644
--- a/chromium/components/search_engines/template_url_data.cc
+++ b/chromium/components/search_engines/template_url_data.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/memory_usage_estimator.h"
#include "base/values.h"
TemplateURLData::TemplateURLData()
@@ -87,9 +88,35 @@ void TemplateURLData::SetKeyword(const base::string16& keyword) {
// Case sensitive keyword matching is confusing. As such, we force all
// keywords to be lower case.
keyword_ = base::i18n::ToLower(keyword);
+
+ base::TrimWhitespace(keyword_, base::TRIM_ALL, &keyword_);
}
void TemplateURLData::SetURL(const std::string& url) {
DCHECK(!url.empty());
url_ = url;
}
+
+size_t TemplateURLData::EstimateMemoryUsage() const {
+ size_t res = 0;
+
+ res += base::trace_event::EstimateMemoryUsage(suggestions_url);
+ res += base::trace_event::EstimateMemoryUsage(image_url);
+ res += base::trace_event::EstimateMemoryUsage(new_tab_url);
+ res += base::trace_event::EstimateMemoryUsage(contextual_search_url);
+ res += base::trace_event::EstimateMemoryUsage(logo_url);
+ res += base::trace_event::EstimateMemoryUsage(doodle_url);
+ res += base::trace_event::EstimateMemoryUsage(search_url_post_params);
+ res += base::trace_event::EstimateMemoryUsage(suggestions_url_post_params);
+ res += base::trace_event::EstimateMemoryUsage(image_url_post_params);
+ res += base::trace_event::EstimateMemoryUsage(favicon_url);
+ res += base::trace_event::EstimateMemoryUsage(originating_url);
+ res += base::trace_event::EstimateMemoryUsage(input_encodings);
+ res += base::trace_event::EstimateMemoryUsage(sync_guid);
+ res += base::trace_event::EstimateMemoryUsage(alternate_urls);
+ res += base::trace_event::EstimateMemoryUsage(short_name_);
+ res += base::trace_event::EstimateMemoryUsage(keyword_);
+ res += base::trace_event::EstimateMemoryUsage(url_);
+
+ return res;
+}
diff --git a/chromium/components/search_engines/template_url_data.h b/chromium/components/search_engines/template_url_data.h
index a8d8239054d..3d8c8a3efed 100644
--- a/chromium/components/search_engines/template_url_data.h
+++ b/chromium/components/search_engines/template_url_data.h
@@ -23,6 +23,7 @@ class ListValue;
struct TemplateURLData {
TemplateURLData();
TemplateURLData(const TemplateURLData& other);
+
// Creates a TemplateURLData suitable for prepopulated engines.
// Note that unlike in the default constructor, |safe_for_autoreplace| will
// be set to true. date_created and last_modified will be set to null time
@@ -63,6 +64,10 @@ struct TemplateURLData {
void SetURL(const std::string& url);
const std::string& url() const { return url_; }
+ // Estimates dynamic memory usage.
+ // See base/trace_event/memory_usage_estimator.h for more info.
+ size_t EstimateMemoryUsage() const;
+
// Optional additional raw URLs.
std::string suggestions_url;
std::string image_url;
diff --git a/chromium/components/search_engines/template_url_data_unittest.cc b/chromium/components/search_engines/template_url_data_unittest.cc
new file mode 100644
index 00000000000..1ee8ec6c1ec
--- /dev/null
+++ b/chromium/components/search_engines/template_url_data_unittest.cc
@@ -0,0 +1,29 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/search_engines/template_url_data.h"
+
+#include "base/strings/string_piece.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(TemplateURLDataTest, Trim) {
+ TemplateURLData data(
+ base::ASCIIToUTF16(" shortname "), base::ASCIIToUTF16(" keyword "),
+ "https://cs.chromium.org", base::StringPiece(), base::StringPiece(),
+ base::StringPiece(), base::StringPiece(), base::StringPiece(),
+ base::StringPiece(), base::StringPiece(), base::StringPiece(),
+ base::StringPiece(), base::StringPiece(), base::StringPiece(),
+ base::ListValue(), 0);
+
+ EXPECT_EQ(base::ASCIIToUTF16("shortname"), data.short_name());
+ EXPECT_EQ(base::ASCIIToUTF16("keyword"), data.keyword());
+
+ data.SetShortName(base::ASCIIToUTF16(" othershortname "));
+ data.SetKeyword(base::ASCIIToUTF16(" otherkeyword "));
+
+ EXPECT_EQ(base::ASCIIToUTF16("othershortname"), data.short_name());
+ EXPECT_EQ(base::ASCIIToUTF16("otherkeyword"), data.keyword());
+}
diff --git a/chromium/components/search_engines/template_url_fetcher.cc b/chromium/components/search_engines/template_url_fetcher.cc
index a48af4c97cc..abb6005095d 100644
--- a/chromium/components/search_engines/template_url_fetcher.cc
+++ b/chromium/components/search_engines/template_url_fetcher.cc
@@ -154,16 +154,6 @@ void TemplateURLFetcher::RequestDelegate::OnURLFetchComplete(
return;
}
- if (keyword_.empty()) {
- // Use the parser-generated new keyword from the URL in the OSDD for the
- // non-autodetected case. The existing |keyword_| was generated from the
- // URL that hosted the OSDD, which results in the wrong keyword when the
- // OSDD was located on a third-party site that has nothing in common with
- // search engine described by OSDD.
- keyword_ = template_url_->keyword();
- DCHECK(!keyword_.empty());
- }
-
// Wait for the model to be loaded before adding the provider.
if (!fetcher_->template_url_service_->loaded())
return;
diff --git a/chromium/components/search_engines/template_url_unittest.cc b/chromium/components/search_engines/template_url_unittest.cc
index 60ea384c522..0c69f957ab6 100644
--- a/chromium/components/search_engines/template_url_unittest.cc
+++ b/chromium/components/search_engines/template_url_unittest.cc
@@ -522,18 +522,14 @@ TEST_F(TemplateURLTest, ReplaceArbitrarySearchTerms) {
const std::string url;
const std::string expected_result;
} test_data[] = {
- { "BIG5", base::WideToUTF16(L"\x60BD"),
- "http://foo/?{searchTerms}{inputEncoding}",
- "http://foo/?%B1~BIG5" },
- { "UTF-8", ASCIIToUTF16("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"},
+ {"BIG5", base::WideToUTF16(L"\x60BD"),
+ "http://foo/?{searchTerms}{inputEncoding}", "http://foo/?%B1~BIG5"},
+ {"UTF-8", ASCIIToUTF16("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"},
};
TemplateURLData data;
for (size_t i = 0; i < arraysize(test_data); ++i) {
@@ -551,6 +547,57 @@ TEST_F(TemplateURLTest, ReplaceArbitrarySearchTerms) {
}
}
+// Test that encoding with several optional codepages works as intended.
+// Codepages are tried in order, fallback is UTF-8.
+TEST_F(TemplateURLTest, ReplaceSearchTermsMultipleEncodings) {
+ struct TestData {
+ const std::vector<std::string> encodings;
+ const base::string16 search_term;
+ const std::string url;
+ const std::string expected_result;
+ } test_data[] = {
+ // First and third encodings are valid. First is used.
+ {{"windows-1251", "cp-866", "UTF-8"},
+ base::UTF8ToUTF16("\xD1\x8F"),
+ "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"),
+ "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"),
+ "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"),
+ "http://foo/?{searchTerms}{inputEncoding}",
+ "http://foo/?%E7%8B%97UTF-8"},
+ // No encodings are given, fallback to UTF-8.
+ {{},
+ base::UTF8ToUTF16("\xE7\x8B\x97"),
+ "http://foo/?{searchTerms}{inputEncoding}",
+ "http://foo/?%E7%8B%97UTF-8"},
+ };
+
+ TemplateURLData data;
+ for (size_t i = 0; i < arraysize(test_data); ++i) {
+ data.SetURL(test_data[i].url);
+ data.input_encodings = test_data[i].encodings;
+ TemplateURL url(data);
+ EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
+ ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
+ GURL result(url.url_ref().ReplaceSearchTerms(
+ TemplateURLRef::SearchTermsArgs(test_data[i].search_term),
+ search_terms_data_));
+ ASSERT_TRUE(result.is_valid());
+ EXPECT_EQ(test_data[i].expected_result, result.spec());
+ }
+}
+
// Tests replacing assisted query stats (AQS) in various scenarios.
TEST_F(TemplateURLTest, ReplaceAssistedQueryStats) {
struct TestData {
diff --git a/chromium/components/search_engines/testing_search_terms_data.cc b/chromium/components/search_engines/testing_search_terms_data.cc
index 9fed5cfb0ed..ac476a04974 100644
--- a/chromium/components/search_engines/testing_search_terms_data.cc
+++ b/chromium/components/search_engines/testing_search_terms_data.cc
@@ -30,3 +30,7 @@ std::string TestingSearchTermsData::GetSearchClient() const {
std::string TestingSearchTermsData::GoogleImageSearchSource() const {
return "google_image_search_source";
}
+
+size_t TestingSearchTermsData::EstimateMemoryUsage() const {
+ return 0;
+}
diff --git a/chromium/components/search_engines/testing_search_terms_data.h b/chromium/components/search_engines/testing_search_terms_data.h
index 083d0253fdb..2e21f2e99e2 100644
--- a/chromium/components/search_engines/testing_search_terms_data.h
+++ b/chromium/components/search_engines/testing_search_terms_data.h
@@ -18,6 +18,10 @@ class TestingSearchTermsData : public SearchTermsData {
std::string GetSearchClient() const override;
std::string GoogleImageSearchSource() const override;
+ // Estimates dynamic memory usage.
+ // See base/trace_event/memory_usage_estimator.h for more info.
+ size_t EstimateMemoryUsage() const override;
+
void set_google_base_url(const std::string& google_base_url) {
google_base_url_ = google_base_url;
}
diff --git a/chromium/components/search_provider_logos/fixed_logo_api.cc b/chromium/components/search_provider_logos/fixed_logo_api.cc
index f9a5f5e6362..c41c8a82bc2 100644
--- a/chromium/components/search_provider_logos/fixed_logo_api.cc
+++ b/chromium/components/search_provider_logos/fixed_logo_api.cc
@@ -4,7 +4,8 @@
#include "components/search_provider_logos/fixed_logo_api.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "base/memory/ref_counted_memory.h"
#include "components/search_provider_logos/logo_common.h"
#include "url/gurl.h"
@@ -15,7 +16,7 @@ std::unique_ptr<EncodedLogo> ParseFixedLogoResponse(
std::unique_ptr<std::string> response,
base::Time response_time,
bool* parsing_failed) {
- auto logo = base::MakeUnique<EncodedLogo>();
+ auto logo = std::make_unique<EncodedLogo>();
logo->encoded_image = base::RefCountedString::TakeString(response.get());
// If |can_show_after_expiration| is true, the |expiration_time| has little
diff --git a/chromium/components/search_provider_logos/google_logo_api.cc b/chromium/components/search_provider_logos/google_logo_api.cc
index 2be8262aa58..ab753b9a29c 100644
--- a/chromium/components/search_provider_logos/google_logo_api.cc
+++ b/chromium/components/search_provider_logos/google_logo_api.cc
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <algorithm>
+#include <memory>
#include "base/base64.h"
#include "base/bind.h"
@@ -14,7 +15,6 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/json/json_reader.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_piece.h"
@@ -172,7 +172,7 @@ std::unique_ptr<EncodedLogo> ParseDoodleLogoResponse(
return nullptr;
}
- auto logo = base::MakeUnique<EncodedLogo>();
+ auto logo = std::make_unique<EncodedLogo>();
std::string doodle_type;
logo->metadata.type = LogoType::SIMPLE;
diff --git a/chromium/components/search_provider_logos/logo_cache.cc b/chromium/components/search_provider_logos/logo_cache.cc
index e4f0af64863..7336f0f44e7 100644
--- a/chromium/components/search_provider_logos/logo_cache.cc
+++ b/chromium/components/search_provider_logos/logo_cache.cc
@@ -7,12 +7,12 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <utility>
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
@@ -105,7 +105,7 @@ void LogoCache::UpdateCachedLogoMetadata(const LogoMetadata& metadata) {
DCHECK(metadata_);
DCHECK_EQ(metadata_->fingerprint, metadata.fingerprint);
- UpdateMetadata(base::MakeUnique<LogoMetadata>(metadata));
+ UpdateMetadata(std::make_unique<LogoMetadata>(metadata));
WriteMetadata();
}
@@ -119,7 +119,7 @@ void LogoCache::SetCachedLogo(const EncodedLogo* logo) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::unique_ptr<LogoMetadata> metadata;
if (logo) {
- metadata = base::MakeUnique<LogoMetadata>(logo->metadata);
+ metadata = std::make_unique<LogoMetadata>(logo->metadata);
logo_num_bytes_ = static_cast<int>(logo->encoded_image->size());
}
UpdateMetadata(std::move(metadata));
diff --git a/chromium/components/search_provider_logos/logo_cache_unittest.cc b/chromium/components/search_provider_logos/logo_cache_unittest.cc
index 188b73770c8..cc1b4575151 100644
--- a/chromium/components/search_provider_logos/logo_cache_unittest.cc
+++ b/chromium/components/search_provider_logos/logo_cache_unittest.cc
@@ -7,13 +7,13 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <string>
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -63,14 +63,14 @@ base::RefCountedString* CreateExampleImage(size_t num_bytes) {
}
std::unique_ptr<EncodedLogo> GetExampleLogo() {
- auto logo = base::MakeUnique<EncodedLogo>();
+ auto logo = std::make_unique<EncodedLogo>();
logo->encoded_image = CreateExampleImage(837);
logo->metadata = GetExampleMetadata();
return logo;
}
std::unique_ptr<EncodedLogo> GetExampleLogo2() {
- auto logo = base::MakeUnique<EncodedLogo>();
+ auto logo = std::make_unique<EncodedLogo>();
logo->encoded_image = CreateExampleImage(345);
logo->metadata = GetExampleMetadata2();
return logo;
@@ -117,7 +117,7 @@ class LogoCacheTest : public ::testing::Test {
}
void InitCache() {
- cache_ = base::MakeUnique<LogoCache>(
+ cache_ = std::make_unique<LogoCache>(
cache_parent_dir_.GetPath().Append(FILE_PATH_LITERAL("cache")));
}
diff --git a/chromium/components/search_provider_logos/logo_tracker.cc b/chromium/components/search_provider_logos/logo_tracker.cc
index 4a42d13cca9..3e11082f8e4 100644
--- a/chromium/components/search_provider_logos/logo_tracker.cc
+++ b/chromium/components/search_provider_logos/logo_tracker.cc
@@ -449,11 +449,11 @@ void LogoTracker::OnURLFetchComplete(const net::URLFetcher* source) {
FROM_HERE,
{base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
- base::Bind(parse_logo_response_func_, base::Passed(&response),
- response_time, parsing_failed),
- base::Bind(&LogoTracker::OnFreshLogoParsed,
- weak_ptr_factory_.GetWeakPtr(), base::Owned(parsing_failed),
- from_http_cache));
+ base::BindOnce(parse_logo_response_func_, std::move(response),
+ response_time, parsing_failed),
+ base::BindOnce(&LogoTracker::OnFreshLogoParsed,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Owned(parsing_failed), from_http_cache));
}
void LogoTracker::OnURLFetchDownloadProgress(const net::URLFetcher* source,
diff --git a/chromium/components/security_interstitials/core/bad_clock_ui.cc b/chromium/components/security_interstitials/core/bad_clock_ui.cc
index 87933c8be9b..cfa1df8c5bc 100644
--- a/chromium/components/security_interstitials/core/bad_clock_ui.cc
+++ b/chromium/components/security_interstitials/core/bad_clock_ui.cc
@@ -118,6 +118,7 @@ void BadClockUI::HandleCommand(SecurityInterstitialCommand command) {
case CMD_REPORT_PHISHING_ERROR:
// Not supported by the bad clock error page.
NOTREACHED() << "Unsupported command: " << command;
+ break;
case CMD_ERROR:
case CMD_TEXT_FOUND:
case CMD_TEXT_NOT_FOUND:
diff --git a/chromium/components/security_interstitials/core/base_safe_browsing_error_ui.cc b/chromium/components/security_interstitials/core/base_safe_browsing_error_ui.cc
index c584234cb91..64485386604 100644
--- a/chromium/components/security_interstitials/core/base_safe_browsing_error_ui.cc
+++ b/chromium/components/security_interstitials/core/base_safe_browsing_error_ui.cc
@@ -30,6 +30,7 @@ BaseSafeBrowsingErrorUI::SBErrorDisplayOptions::SBErrorDisplayOptions(
bool is_off_the_record,
bool is_extended_reporting_enabled,
bool is_scout_reporting_enabled,
+ bool is_extended_reporting_policy_managed,
bool is_proceed_anyway_disabled,
bool should_open_links_in_new_tab,
bool always_show_back_to_safety,
@@ -40,6 +41,8 @@ BaseSafeBrowsingErrorUI::SBErrorDisplayOptions::SBErrorDisplayOptions(
is_off_the_record(is_off_the_record),
is_extended_reporting_enabled(is_extended_reporting_enabled),
is_scout_reporting_enabled(is_scout_reporting_enabled),
+ is_extended_reporting_policy_managed(
+ is_extended_reporting_policy_managed),
is_proceed_anyway_disabled(is_proceed_anyway_disabled),
should_open_links_in_new_tab(should_open_links_in_new_tab),
always_show_back_to_safety(always_show_back_to_safety),
@@ -53,6 +56,8 @@ BaseSafeBrowsingErrorUI::SBErrorDisplayOptions::SBErrorDisplayOptions(
is_off_the_record(other.is_off_the_record),
is_extended_reporting_enabled(other.is_extended_reporting_enabled),
is_scout_reporting_enabled(other.is_scout_reporting_enabled),
+ is_extended_reporting_policy_managed(
+ other.is_extended_reporting_policy_managed),
is_proceed_anyway_disabled(other.is_proceed_anyway_disabled),
should_open_links_in_new_tab(other.should_open_links_in_new_tab),
always_show_back_to_safety(other.always_show_back_to_safety),
diff --git a/chromium/components/security_interstitials/core/base_safe_browsing_error_ui.h b/chromium/components/security_interstitials/core/base_safe_browsing_error_ui.h
index ae50946e814..a7faf197838 100644
--- a/chromium/components/security_interstitials/core/base_safe_browsing_error_ui.h
+++ b/chromium/components/security_interstitials/core/base_safe_browsing_error_ui.h
@@ -31,6 +31,7 @@ class BaseSafeBrowsingErrorUI {
bool is_off_the_record,
bool is_extended_reporting_enabled,
bool is_scout_reporting_enabled,
+ bool is_extended_reporting_policy_managed,
bool is_proceed_anyway_disabled,
bool should_open_links_in_new_tab,
bool always_show_back_to_safety,
@@ -59,6 +60,10 @@ class BaseSafeBrowsingErrorUI {
// |is_extended_reporting_enabled| to see if the user is opted-in.
bool is_scout_reporting_enabled;
+ // Whether the SBER pref is being managed by enterprise policy, meaning the
+ // user is unable to change the pref.
+ bool is_extended_reporting_policy_managed;
+
// Indicates if kSafeBrowsingProceedAnywayDisabled preference is set.
bool is_proceed_anyway_disabled;
@@ -108,6 +113,10 @@ class BaseSafeBrowsingErrorUI {
return display_options_.is_scout_reporting_enabled;
}
+ bool is_extended_reporting_policy_managed() const {
+ return display_options_.is_extended_reporting_policy_managed;
+ }
+
bool is_proceed_anyway_disabled() const {
return display_options_.is_proceed_anyway_disabled;
}
@@ -128,11 +137,14 @@ class BaseSafeBrowsingErrorUI {
return display_options_;
}
- // Checks if we should even show the extended reporting option. We don't show
- // it in incognito mode or if kSafeBrowsingExtendedReportingOptInAllowed
- // preference is disabled.
+ // Checks if we should even show the extended reporting option.
+ // We don't show it:
+ // - in incognito mode
+ // - if kSafeBrowsingExtendedReportingOptInAllowed preference is disabled.
+ // - if kSafeBrowsingExtendedReporting is managed by enterprise policy.
bool CanShowExtendedReportingOption() {
- return !is_off_the_record() && is_extended_reporting_opt_in_allowed();
+ return !is_off_the_record() && is_extended_reporting_opt_in_allowed() &&
+ !is_extended_reporting_policy_managed();
}
SBInterstitialReason interstitial_reason() const {
diff --git a/chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.css b/chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.css
index 50c858c297c..fe9ff5de784 100644
--- a/chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.css
+++ b/chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.css
@@ -61,8 +61,8 @@ h1 {
background-position: center;
height: 20vh;
margin: 0 auto;
- max-height: 24px;
- max-width: 24px;
+ max-height: 48px;
+ max-width: 48px;
min-height: 18px;
min-width: 18px;
opacity: .54;
@@ -97,11 +97,6 @@ h1 {
@media (min-height:25em) and (min-width:37.5em),
(min-height:37.5em) and (min-width:25em) {
- .icon {
- max-height: 36px;
- max-width: 36px;
- }
-
.interstitial-wrapper {
padding: 48px;
}
@@ -111,6 +106,11 @@ h1 {
@media (max-height:11.25em) and (max-width:18.75em),
(max-height:18.75em) and (max-width:11.25em),
(max-height:5em), (max-width:5em) {
+ .icon {
+ max-height: 24px;
+ max-width: 24px;
+ }
+
#details,
#main-message {
display: none;
diff --git a/chromium/components/security_interstitials/core/common/resources/interstitial_common.css b/chromium/components/security_interstitials/core/common/resources/interstitial_common.css
index d1b833c267f..bb1ca4f6502 100644
--- a/chromium/components/security_interstitials/core/common/resources/interstitial_common.css
+++ b/chromium/components/security_interstitials/core/common/resources/interstitial_common.css
@@ -25,6 +25,7 @@ button {
.main-frame-blocked button,
.neterror button,
.offline button,
+.pdf button,
.ssl button {
background: rgb(66, 133, 244);
}
diff --git a/chromium/components/security_interstitials/core/common/resources/interstitial_core.css b/chromium/components/security_interstitials/core/common/resources/interstitial_core.css
index 32a27b997ff..5ec9a2ba1fb 100644
--- a/chromium/components/security_interstitials/core/common/resources/interstitial_core.css
+++ b/chromium/components/security_interstitials/core/common/resources/interstitial_core.css
@@ -9,6 +9,7 @@ a {
body {
background-color: rgb(247, 247, 247);
color: rgb(100, 100, 100);
+ word-wrap: break-word;
}
#details-button {
diff --git a/chromium/components/security_interstitials/core/metrics_helper.cc b/chromium/components/security_interstitials/core/metrics_helper.cc
index 5a061fca4c1..75e442c46fe 100644
--- a/chromium/components/security_interstitials/core/metrics_helper.cc
+++ b/chromium/components/security_interstitials/core/metrics_helper.cc
@@ -132,7 +132,6 @@ void MetricsHelper::RecordUserDecision(Decision decision) {
}
MaybeRecordDecisionAsAction(decision, settings_.metric_prefix);
- RecordExtraUserDecisionMetrics(decision);
}
void MetricsHelper::RecordUserDecisionToMetrics(
@@ -156,7 +155,6 @@ void MetricsHelper::RecordUserInteraction(Interaction interaction) {
}
MaybeRecordInteractionAsAction(interaction, settings_.metric_prefix);
- RecordExtraUserInteractionMetrics(interaction);
}
void MetricsHelper::RecordShutdownMetrics() {
diff --git a/chromium/components/security_interstitials/core/mitm_software_ui.cc b/chromium/components/security_interstitials/core/mitm_software_ui.cc
index 0afdb393c0c..db2b27607c4 100644
--- a/chromium/components/security_interstitials/core/mitm_software_ui.cc
+++ b/chromium/components/security_interstitials/core/mitm_software_ui.cc
@@ -96,6 +96,7 @@ void MITMSoftwareUI::HandleCommand(SecurityInterstitialCommand command) {
case CMD_REPORT_PHISHING_ERROR:
// Not supported by the SSL error page.
NOTREACHED() << "Unsupported command: " << command;
+ break;
case CMD_ERROR:
case CMD_TEXT_FOUND:
case CMD_TEXT_NOT_FOUND:
diff --git a/chromium/components/security_interstitials/core/safe_browsing_loud_error_ui.cc b/chromium/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
index ca910948cf9..4e40f5c59f9 100644
--- a/chromium/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
+++ b/chromium/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
@@ -119,8 +119,9 @@ void SafeBrowsingLoudErrorUI::HandleCommand(
controller()->Proceed();
break;
}
+ // If the user can't proceed, fall through to CMD_DONT_PROCEED.
+ FALLTHROUGH;
}
- // If the user can't proceed, fall through to CMD_DONT_PROCEED.
case CMD_DONT_PROCEED: {
// User pressed on the button to return to safety.
// Don't record the user action here because there are other ways of
diff --git a/chromium/components/security_interstitials/core/ssl_error_ui.cc b/chromium/components/security_interstitials/core/ssl_error_ui.cc
index 5fc7a318850..f8d7c294ebc 100644
--- a/chromium/components/security_interstitials/core/ssl_error_ui.cc
+++ b/chromium/components/security_interstitials/core/ssl_error_ui.cc
@@ -216,6 +216,7 @@ void SSLErrorUI::HandleCommand(SecurityInterstitialCommand command) {
case CMD_REPORT_PHISHING_ERROR:
// Not supported by the SSL error page.
NOTREACHED() << "Unsupported command: " << command;
+ break;
case CMD_ERROR:
case CMD_TEXT_FOUND:
case CMD_TEXT_NOT_FOUND:
diff --git a/chromium/components/security_interstitials_strings.grdp b/chromium/components/security_interstitials_strings.grdp
index ce5dc63473f..4e853aa45be 100644
--- a/chromium/components/security_interstitials_strings.grdp
+++ b/chromium/components/security_interstitials_strings.grdp
@@ -302,5 +302,54 @@
<message name="IDS_PHISHING_WEBVIEW_EXPLANATION_PARAGRAPH" desc="The explanation of why Safe Browsing has blocked the page. Allows the user to proceed using a link.">
This content might try to trick you into installing software or revealing personal information. <ph name="BEGIN_LINK">&lt;a href="#" id="proceed-link"&gt;</ph>Show anyway<ph name="END_LINK">&lt;/a&gt;</ph>
</message>
-
+ <message name="IDS_CONNECTION_HELP_TITLE" desc="The title for the chrome://connection-help site">
+ Connection Help
+ </message>
+ <message name="IDS_CONNECTION_HELP_HTML" desc="The HTML for the chrome://connection-help site that is shown when visiting the online help center triggers an SSL interstitial, this is a simplified version of the content at https://support.google.com/chrome/answer/6098869.">
+ &lt;h1&gt;Fix connection errors&lt;/h1&gt;
+ &lt;p&gt;If you get an error message when you try to visit a website, try these fixes.&lt;/p&gt;
+ &lt;h2&gt;Fix most connection errors&lt;/h2&gt;
+ &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;
+ &lt;ol&gt;
+ &lt;li&gt;Check the web address for typos.&lt;/li&gt;
+ &lt;li&gt;Make sure your internet connection is working normally.&lt;/li&gt;
+ &lt;li&gt;Contact the website owner.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Get help with a specific error message&lt;/h2&gt;
+ &lt;h3&gt;"Your connection is not private" or "NET::ERR_CERT_AUTHORITY_INVALID" or "ERR_CERT_COMMON_NAME_INVALID" or "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" or "SSL certificate error"&lt;/h3&gt;
+ &lt;h4&gt;Step 1: Sign in to the portal&lt;/h4&gt;
+ &lt;p&gt;Wi-Fi networks at places like cafes or airports need you to sign in. To see the sign-in page, visit a page that uses&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Go to any website starting with &lt;code&gt;http://&lt;/code&gt;, like &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;On the sign-in page that opens, sign in to use the internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Step 2: Open the page in Incognito mode (computer only)&lt;/h4&gt;
+ &lt;p&gt;Open the page you were visiting in an Incognito window.&lt;/p&gt;
+ &lt;p&gt;If the page opens, a Chrome extension isn't working right. To fix the error, turn off the extension.&lt;/p&gt;
+ &lt;h4&gt;Step 3: Update your operating system&lt;/h4&gt;
+ &lt;p&gt;Make sure your device is up-to-date.&lt;/p&gt;
+ &lt;h4&gt;Step 4: Temporarily turn off your antivirus&lt;/h4&gt;
+ &lt;p&gt;You'll see this error if you have antivirus software that provides "HTTPS protection" or "HTTPS scanning." The antivirus is preventing Chrome from providing security.&lt;/p&gt;
+ &lt;p&gt;To fix the problem, turn off your antivirus software. If the page works after turning off the software, turn off this software when you use secure sites.&lt;/p&gt;
+ &lt;p&gt;Remember to turn your antivirus program back on when you're done.&lt;/p&gt;
+ &lt;h4&gt;Step 5: Get extra help&lt;/h4&gt;
+ &lt;p&gt;If you still see the error, contact the website owner.&lt;/p&gt;
+ &lt;h3&gt;"Connect to network"&lt;/h3&gt;
+ &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 you're trying to open.&lt;/p&gt;
+ &lt;h3&gt;"Your clock is behind" or "Your clock is ahead" or "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;You'll see this error if your computer or mobile device's date and time are inaccurate.&lt;/p&gt;
+ &lt;p&gt;To fix the error, open your device's clock. Make sure the time and date are correct.&lt;/p&gt;
+ &lt;h3&gt;"Software on your computer is stopping Chrome from safely connecting to the web" (Windows computers only)&lt;/h3&gt;
+ &lt;p&gt;You'll see this error if you have Superfish software on your Windows computer.&lt;/p&gt;
+ &lt;p&gt;Follow these steps to temporarily disable the software so you can get on the web. You'll need administrator privileges.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Click &lt;strong&gt;Start&lt;/strong&gt;, then search for and select &lt;strong&gt;"View local services"&lt;/strong&gt;
+ &lt;li&gt;Select &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Under &lt;strong&gt;Startup type&lt;/strong&gt;, select &lt;strong&gt;Disabled&lt;/strong&gt;
+ &lt;li&gt;Under &lt;strong&gt;Service status&lt;/strong&gt;, click &lt;strong&gt;Stop&lt;/strong&gt;
+ &lt;li&gt;Click &lt;strong&gt;Apply&lt;/strong&gt;, then click &lt;strong&gt;OK&lt;/strong&gt;
+ &lt;li&gt;Visit the &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome help center&lt;/a&gt; to learn how to permanently remove the software from your computer
+ &lt;/ol&gt;
+ </message>
</grit-part>
diff --git a/chromium/components/security_state/content/content_utils.cc b/chromium/components/security_state/content/content_utils.cc
index 7ec6cc668ba..0d437ff84ae 100644
--- a/chromium/components/security_state/content/content_utils.cc
+++ b/chromium/components/security_state/content/content_utils.cc
@@ -4,10 +4,10 @@
#include "components/security_state/content/content_utils.h"
+#include <memory>
#include <string>
#include <vector>
-#include "base/memory/ptr_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -394,7 +394,7 @@ void ExplainContentSecurity(
std::unique_ptr<security_state::VisibleSecurityState> GetVisibleSecurityState(
content::WebContents* web_contents) {
- auto state = base::MakeUnique<security_state::VisibleSecurityState>();
+ auto state = std::make_unique<security_state::VisibleSecurityState>();
content::NavigationEntry* entry =
web_contents->GetController().GetVisibleEntry();
diff --git a/chromium/components/security_state/content/content_utils_browsertest.cc b/chromium/components/security_state/content/content_utils_browsertest.cc
index 9207cc6ebe2..7d87162d4ce 100644
--- a/chromium/components/security_state/content/content_utils_browsertest.cc
+++ b/chromium/components/security_state/content/content_utils_browsertest.cc
@@ -83,7 +83,7 @@ IN_PROC_BROWSER_TEST_F(SecurityStateContentUtilsBrowserTest,
events.password_field_shown = true;
events.credit_card_field_edited = true;
ssl_status.user_data =
- base::MakeUnique<security_state::SSLStatusInputEventData>(events);
+ std::make_unique<security_state::SSLStatusInputEventData>(events);
std::unique_ptr<security_state::VisibleSecurityState>
visible_security_state_sensitive_inputs =
@@ -120,7 +120,7 @@ IN_PROC_BROWSER_TEST_F(SecurityStateContentUtilsBrowserTest,
// Simulate a field edit and update the SSLStatus' |user_data|.
events.insecure_field_edited = true;
ssl_status.user_data =
- base::MakeUnique<security_state::SSLStatusInputEventData>(events);
+ std::make_unique<security_state::SSLStatusInputEventData>(events);
// Verify the field edit was recorded properly in the |user_data|.
ssl_status_input_events =
diff --git a/chromium/components/security_state/content/ssl_status_input_event_data.cc b/chromium/components/security_state/content/ssl_status_input_event_data.cc
index cfb66fff8b2..2dc69e9b6db 100644
--- a/chromium/components/security_state/content/ssl_status_input_event_data.cc
+++ b/chromium/components/security_state/content/ssl_status_input_event_data.cc
@@ -7,8 +7,6 @@
#include <memory>
#include <utility>
-#include "base/memory/ptr_util.h"
-
namespace security_state {
SSLStatusInputEventData::SSLStatusInputEventData() {}
@@ -23,7 +21,7 @@ InsecureInputEventData* SSLStatusInputEventData::input_events() {
}
std::unique_ptr<SSLStatus::UserData> SSLStatusInputEventData::Clone() {
- return base::MakeUnique<SSLStatusInputEventData>(data_);
+ return std::make_unique<SSLStatusInputEventData>(data_);
}
} // namespace security_state
diff --git a/chromium/components/security_state/core/security_state.h b/chromium/components/security_state/core/security_state.h
index d518cd58eee..4ca022bea15 100644
--- a/chromium/components/security_state/core/security_state.h
+++ b/chromium/components/security_state/core/security_state.h
@@ -228,8 +228,7 @@ void GetSecurityInfo(
// |kHttpFormWarningFeature| feature.
bool IsHttpWarningInFormEnabled();
-// Returns true for a valid |url| with a cryptographic scheme, e.g., HTTPS,
-// HTTPS-SO, WSS.
+// Returns true for a valid |url| with a cryptographic scheme, e.g., HTTPS, WSS.
bool IsSchemeCryptographic(const GURL& url);
// Returns true for a valid |url| with localhost or file:// scheme origin.
diff --git a/chromium/components/security_state/core/security_state_unittest.cc b/chromium/components/security_state/core/security_state_unittest.cc
index 511670e6140..c93aa0d2bf9 100644
--- a/chromium/components/security_state/core/security_state_unittest.cc
+++ b/chromium/components/security_state/core/security_state_unittest.cc
@@ -5,11 +5,11 @@
#include "components/security_state/core/security_state.h"
#include <stdint.h>
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/memory/ptr_util.h"
#include "base/test/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "components/security_state/core/features.h"
@@ -28,7 +28,6 @@ namespace {
const char kHttpsUrl[] = "https://foo.test/";
const char kHttpUrl[] = "http://foo.test/";
-const char kHttpsSoUrl[] = "https-so://foo.test/";
const char kLocalhostUrl[] = "http://localhost";
const char kFileOrigin[] = "file://example_file";
const char kWssUrl[] = "wss://foo.test/";
@@ -113,7 +112,7 @@ class TestSecurityStateHelper {
void SetUrl(const GURL& url) { url_ = url; }
std::unique_ptr<VisibleSecurityState> GetVisibleSecurityState() const {
- auto state = base::MakeUnique<VisibleSecurityState>();
+ auto state = std::make_unique<VisibleSecurityState>();
state->connection_info_initialized = true;
state->url = url_;
state->certificate = cert_;
@@ -610,8 +609,6 @@ TEST(SecurityStateTest, FieldEdit) {
TEST(SecurityStateTest, CryptographicSchemeUrl) {
// HTTPS is a cryptographic scheme.
EXPECT_TRUE(IsSchemeCryptographic(GURL(kHttpsUrl)));
- // HTTPS-SO is a cryptographic scheme.
- EXPECT_TRUE(IsSchemeCryptographic(GURL(kHttpsSoUrl)));
// WSS is a cryptographic scheme.
EXPECT_TRUE(IsSchemeCryptographic(GURL(kWssUrl)));
// HTTP is not a cryptographic scheme.
diff --git a/chromium/components/security_state/ios/ssl_status_input_event_data.mm b/chromium/components/security_state/ios/ssl_status_input_event_data.mm
index 3b84a2fdccb..eb728d4018c 100644
--- a/chromium/components/security_state/ios/ssl_status_input_event_data.mm
+++ b/chromium/components/security_state/ios/ssl_status_input_event_data.mm
@@ -4,6 +4,8 @@
#include "components/security_state/ios/ssl_status_input_event_data.h"
+#include <memory>
+
namespace security_state {
SSLStatusInputEventData::SSLStatusInputEventData() {}
@@ -20,7 +22,7 @@ SSLStatusInputEventData::input_events() {
}
std::unique_ptr<web::SSLStatus::UserData> SSLStatusInputEventData::Clone() {
- return base::MakeUnique<SSLStatusInputEventData>(data_);
+ return std::make_unique<SSLStatusInputEventData>(data_);
}
} // namespace security_state
diff --git a/chromium/components/sessions/core/base_session_service.cc b/chromium/components/sessions/core/base_session_service.cc
index ba4a3683e65..3e76628e6a2 100644
--- a/chromium/components/sessions/core/base_session_service.cc
+++ b/chromium/components/sessions/core/base_session_service.cc
@@ -39,7 +39,7 @@ void PostOrRunInternalGetCommandsCallback(
callback.Run(std::move(commands));
} else {
task_runner->PostTask(FROM_HERE,
- base::Bind(callback, base::Passed(&commands)));
+ base::BindOnce(callback, std::move(commands)));
}
}
@@ -139,9 +139,8 @@ void BaseSessionService::Save() {
// We create a new vector which will receive all elements from the
// current commands. This will also clear the current list.
RunTaskOnBackendThread(
- FROM_HERE,
- base::BindOnce(&SessionBackend::AppendCommands, backend_,
- base::Passed(&pending_commands_), pending_reset_));
+ FROM_HERE, base::BindOnce(&SessionBackend::AppendCommands, backend_,
+ std::move(pending_commands_), pending_reset_));
if (pending_reset_) {
commands_since_reset_ = 0;
diff --git a/chromium/components/sessions/core/in_memory_tab_restore_service.cc b/chromium/components/sessions/core/in_memory_tab_restore_service.cc
index cdc31f19474..bfbf7ae9bfb 100644
--- a/chromium/components/sessions/core/in_memory_tab_restore_service.cc
+++ b/chromium/components/sessions/core/in_memory_tab_restore_service.cc
@@ -46,6 +46,11 @@ void InMemoryTabRestoreService::ClearEntries() {
helper_.ClearEntries();
}
+void InMemoryTabRestoreService::DeleteNavigationEntries(
+ const DeletionPredicate& predicate) {
+ helper_.DeleteNavigationEntries(predicate);
+}
+
const TabRestoreService::Entries& InMemoryTabRestoreService::entries() const {
return helper_.entries();
}
diff --git a/chromium/components/sessions/core/in_memory_tab_restore_service.h b/chromium/components/sessions/core/in_memory_tab_restore_service.h
index c6174c32b0e..b2ca707aad1 100644
--- a/chromium/components/sessions/core/in_memory_tab_restore_service.h
+++ b/chromium/components/sessions/core/in_memory_tab_restore_service.h
@@ -39,6 +39,7 @@ class SESSIONS_EXPORT InMemoryTabRestoreService : public TabRestoreService {
void BrowserClosing(LiveTabContext* context) override;
void BrowserClosed(LiveTabContext* context) override;
void ClearEntries() override;
+ void DeleteNavigationEntries(const DeletionPredicate& predicate) override;
const Entries& entries() const override;
std::vector<LiveTab*> RestoreMostRecentEntry(
LiveTabContext* context) override;
diff --git a/chromium/components/sessions/core/persistent_tab_restore_service.cc b/chromium/components/sessions/core/persistent_tab_restore_service.cc
index d07439909d4..a8dd9e47a50 100644
--- a/chromium/components/sessions/core/persistent_tab_restore_service.cc
+++ b/chromium/components/sessions/core/persistent_tab_restore_service.cc
@@ -352,6 +352,7 @@ class PersistentTabRestoreService::Delegate
// TabRestoreServiceHelper::Observer:
void OnClearEntries() override;
+ void OnNavigationEntriesDeleted() override;
void OnRestoreEntryById(SessionID::id_type id,
Entries::const_iterator entry_iterator) override;
void OnAddEntry() override;
@@ -533,7 +534,17 @@ void PersistentTabRestoreService::Delegate::OnClearEntries() {
// Schedule a pending reset so that we nuke the file on next write.
base_session_service_->set_pending_reset(true);
+ // Schedule a command, otherwise if there are no pending commands Save does
+ // nothing.
+ base_session_service_->ScheduleCommand(CreateRestoredEntryCommand(1));
+}
+
+void PersistentTabRestoreService::Delegate::OnNavigationEntriesDeleted() {
+ // Rewrite all entries.
+ entries_to_write_ = tab_restore_service_helper_->entries().size();
+ // Schedule a pending reset so that we nuke the file on next write.
+ base_session_service_->set_pending_reset(true);
// Schedule a command, otherwise if there are no pending commands Save does
// nothing.
base_session_service_->ScheduleCommand(CreateRestoredEntryCommand(1));
@@ -1120,6 +1131,12 @@ void PersistentTabRestoreService::ClearEntries() {
helper_.ClearEntries();
}
+void PersistentTabRestoreService::DeleteNavigationEntries(
+ const DeletionPredicate& predicate) {
+ DCHECK(IsLoaded());
+ helper_.DeleteNavigationEntries(predicate);
+}
+
const TabRestoreService::Entries& PersistentTabRestoreService::entries() const {
return helper_.entries();
}
diff --git a/chromium/components/sessions/core/persistent_tab_restore_service.h b/chromium/components/sessions/core/persistent_tab_restore_service.h
index 9d2eaa869c2..206ca4aec7d 100644
--- a/chromium/components/sessions/core/persistent_tab_restore_service.h
+++ b/chromium/components/sessions/core/persistent_tab_restore_service.h
@@ -35,6 +35,7 @@ class SESSIONS_EXPORT PersistentTabRestoreService : public TabRestoreService {
void BrowserClosing(LiveTabContext* context) override;
void BrowserClosed(LiveTabContext* context) override;
void ClearEntries() override;
+ void DeleteNavigationEntries(const DeletionPredicate& predicate) override;
const Entries& entries() const override;
std::vector<LiveTab*> RestoreMostRecentEntry(
LiveTabContext* context) override;
diff --git a/chromium/components/sessions/core/tab_restore_service.h b/chromium/components/sessions/core/tab_restore_service.h
index 47bd4048c33..5a84024da9d 100644
--- a/chromium/components/sessions/core/tab_restore_service.h
+++ b/chromium/components/sessions/core/tab_restore_service.h
@@ -143,6 +143,8 @@ class SESSIONS_EXPORT TabRestoreService : public KeyedService {
};
typedef std::list<std::unique_ptr<Entry>> Entries;
+ typedef base::RepeatingCallback<bool(const SerializedNavigationEntry& entry)>
+ DeletionPredicate;
~TabRestoreService() override;
@@ -169,6 +171,10 @@ class SESSIONS_EXPORT TabRestoreService : public KeyedService {
// of tabs has changed.
virtual void ClearEntries() = 0;
+ // Removes all SerializedNavigationEntries matching |predicate| and notifies
+ // observers the list of tabs has changed.
+ virtual void DeleteNavigationEntries(const DeletionPredicate& predicate) = 0;
+
// Returns the entries, ordered with most recently closed entries at the
// front.
virtual const Entries& entries() const = 0;
diff --git a/chromium/components/sessions/core/tab_restore_service_helper.cc b/chromium/components/sessions/core/tab_restore_service_helper.cc
index a18f3bc1000..3d00472cd6d 100644
--- a/chromium/components/sessions/core/tab_restore_service_helper.cc
+++ b/chromium/components/sessions/core/tab_restore_service_helper.cc
@@ -34,6 +34,8 @@ TabRestoreServiceHelper::Observer::~Observer() {}
void TabRestoreServiceHelper::Observer::OnClearEntries() {}
+void TabRestoreServiceHelper::Observer::OnNavigationEntriesDeleted() {}
+
void TabRestoreServiceHelper::Observer::OnRestoreEntryById(
SessionID::id_type id,
Entries::const_iterator entry_iterator) {
@@ -140,6 +142,83 @@ void TabRestoreServiceHelper::ClearEntries() {
NotifyTabsChanged();
}
+bool TabRestoreServiceHelper::DeleteFromTab(const DeletionPredicate& predicate,
+ Tab* tab) {
+ std::vector<SerializedNavigationEntry> new_navigations;
+ int deleted_navigations = 0;
+ for (auto& navigation : tab->navigations) {
+ if (predicate.Run(navigation)) {
+ // If the current navigation is deleted, remove this tab.
+ if (tab->current_navigation_index == navigation.index())
+ return true;
+ deleted_navigations++;
+ } else {
+ // Adjust indices according to number of deleted navigations.
+ if (tab->current_navigation_index == navigation.index())
+ tab->current_navigation_index -= deleted_navigations;
+ navigation.set_index(navigation.index() - deleted_navigations);
+ new_navigations.push_back(std::move(navigation));
+ }
+ }
+ tab->navigations = std::move(new_navigations);
+ DCHECK(tab->navigations.empty() || ValidateTab(*tab));
+ return tab->navigations.empty();
+}
+
+bool TabRestoreServiceHelper::DeleteFromWindow(
+ const DeletionPredicate& predicate,
+ Window* window) {
+ std::vector<std::unique_ptr<Tab>> new_tabs;
+ int deleted_tabs = 0;
+ for (auto& tab : window->tabs) {
+ if (DeleteFromTab(predicate, tab.get())) {
+ if (window->tabs[window->selected_tab_index] == tab)
+ window->selected_tab_index = 0;
+ deleted_tabs++;
+ } else {
+ // Adjust indices according to number of deleted tabs.
+ if (window->tabs[window->selected_tab_index] == tab)
+ window->selected_tab_index -= deleted_tabs;
+ if (tab->tabstrip_index >= 0)
+ tab->tabstrip_index -= deleted_tabs;
+ new_tabs.push_back(std::move(tab));
+ }
+ }
+ window->tabs = std::move(new_tabs);
+ DCHECK(window->tabs.empty() || ValidateWindow(*window));
+ return window->tabs.empty();
+}
+
+void TabRestoreServiceHelper::DeleteNavigationEntries(
+ const DeletionPredicate& predicate) {
+ Entries new_entries;
+ for (std::unique_ptr<Entry>& entry : entries_) {
+ switch (entry->type) {
+ case TabRestoreService::TAB: {
+ Tab* tab = static_cast<Tab*>(entry.get());
+ if (!DeleteFromTab(predicate, tab))
+ new_entries.push_back(std::move(entry));
+ break;
+ }
+ case TabRestoreService::WINDOW: {
+ Window* window = static_cast<Window*>(entry.get());
+ if (!DeleteFromWindow(predicate, window)) {
+ // If only a single tab is left, just keep the tab.
+ if (window->tabs.size() == 1U)
+ new_entries.push_back(std::move(window->tabs.front()));
+ else
+ new_entries.push_back(std::move(entry));
+ }
+ break;
+ }
+ }
+ }
+ entries_ = std::move(new_entries);
+ if (observer_)
+ observer_->OnNavigationEntriesDeleted();
+ NotifyTabsChanged();
+}
+
const TabRestoreService::Entries& TabRestoreServiceHelper::entries() const {
return entries_;
}
diff --git a/chromium/components/sessions/core/tab_restore_service_helper.h b/chromium/components/sessions/core/tab_restore_service_helper.h
index 1d503b08cfe..abeb588d1ee 100644
--- a/chromium/components/sessions/core/tab_restore_service_helper.h
+++ b/chromium/components/sessions/core/tab_restore_service_helper.h
@@ -31,6 +31,7 @@ class TimeFactory;
class SESSIONS_EXPORT TabRestoreServiceHelper
: public base::trace_event::MemoryDumpProvider {
public:
+ typedef TabRestoreService::DeletionPredicate DeletionPredicate;
typedef TabRestoreService::Entries Entries;
typedef TabRestoreService::Entry Entry;
typedef TabRestoreService::Tab Tab;
@@ -44,6 +45,9 @@ class SESSIONS_EXPORT TabRestoreServiceHelper
// Invoked before the entries are cleared.
virtual void OnClearEntries();
+ // Invoked when navigations from entries have been deleted.
+ virtual void OnNavigationEntriesDeleted();
+
// Invoked before the entry is restored. |entry_iterator| points to the
// entry corresponding to the session identified by |id|.
virtual void OnRestoreEntryById(SessionID::id_type id,
@@ -78,6 +82,8 @@ class SESSIONS_EXPORT TabRestoreServiceHelper
void BrowserClosing(LiveTabContext* context);
void BrowserClosed(LiveTabContext* context);
void ClearEntries();
+ void DeleteNavigationEntries(const DeletionPredicate& predicate);
+
const Entries& entries() const;
std::vector<LiveTab*> RestoreMostRecentEntry(LiveTabContext* context);
std::unique_ptr<Tab> RemoveTabEntryById(SessionID::id_type id);
@@ -144,6 +150,15 @@ class SESSIONS_EXPORT TabRestoreServiceHelper
// Validates all the tabs in a window, plus the window's active tab index.
static bool ValidateWindow(const Window& window);
+ // Removes all navigation entries matching |predicate| from |tab|.
+ // Returns true if |tab| should be deleted because it is empty.
+ static bool DeleteFromTab(const DeletionPredicate& predicate, Tab* tab);
+
+ // Removes all navigation entries matching |predicate| from tabs in |window|.
+ // Returns true if |window| should be deleted because it is empty.
+ static bool DeleteFromWindow(const DeletionPredicate& predicate,
+ Window* window);
+
// Returns true if |tab| is one we care about restoring.
bool IsTabInteresting(const Tab& tab);
diff --git a/chromium/components/sessions/core/tab_restore_service_observer.h b/chromium/components/sessions/core/tab_restore_service_observer.h
index 7ddd644a8d3..96bb9ba3016 100644
--- a/chromium/components/sessions/core/tab_restore_service_observer.h
+++ b/chromium/components/sessions/core/tab_restore_service_observer.h
@@ -16,7 +16,7 @@ class TabRestoreService;
class SESSIONS_EXPORT TabRestoreServiceObserver {
public:
// Sent when the set of entries changes in some way.
- virtual void TabRestoreServiceChanged(TabRestoreService* service) = 0;
+ virtual void TabRestoreServiceChanged(TabRestoreService* service) {}
// Sent to all remaining Observers when TabRestoreService's
// destructor is run.
diff --git a/chromium/components/signin/core/browser/BUILD.gn b/chromium/components/signin/core/browser/BUILD.gn
index 9bbfc294c4f..cf446098cc5 100644
--- a/chromium/components/signin/core/browser/BUILD.gn
+++ b/chromium/components/signin/core/browser/BUILD.gn
@@ -70,8 +70,8 @@ static_library("browser") {
"profile_oauth2_token_service.h",
"signin_client.cc",
"signin_client.h",
- "signin_cookie_changed_subscription.cc",
- "signin_cookie_changed_subscription.h",
+ "signin_cookie_change_subscription.cc",
+ "signin_cookie_change_subscription.h",
"signin_error_controller.cc",
"signin_error_controller.h",
"signin_header_helper.cc",
@@ -118,17 +118,20 @@ static_library("browser") {
"//components/signin/core/browser:signin_features",
"//google_apis",
"//net",
+ "//ui/gfx",
"//url",
]
deps = [
"//base:i18n",
"//components/data_use_measurement/core",
"//components/google/core/browser",
+ "//components/image_fetcher/core",
"//components/metrics",
"//components/os_crypt",
"//components/pref_registry",
"//components/webdata/common",
"//crypto",
+ "//skia",
"//sql",
"//third_party/icu",
"//third_party/re2",
@@ -181,11 +184,13 @@ static_library("test_support") {
deps = [
"//base/test:test_support",
+ "//ui/gfx:test_support",
]
public_deps = [
":browser",
"//base",
+ "//components/image_fetcher/core/",
"//components/prefs:test_support",
"//components/webdata/common",
"//google_apis:test_support",
diff --git a/chromium/components/signin/core/browser/DEPS b/chromium/components/signin/core/browser/DEPS
index 1daccb8ffbd..88087707fcd 100644
--- a/chromium/components/signin/core/browser/DEPS
+++ b/chromium/components/signin/core/browser/DEPS
@@ -1,8 +1,10 @@
include_rules = [
"+components/data_use_measurement/core",
+ "+components/image_fetcher/core",
"+components/invalidation/public",
"+components/metrics",
"+google/cacheinvalidation",
"+jni",
"+third_party/re2",
+ "+ui/gfx",
]
diff --git a/chromium/components/signin/core/browser/about_signin_internals.cc b/chromium/components/signin/core/browser/about_signin_internals.cc
index eadf3b5b3a6..c0ae1ef02d5 100644
--- a/chromium/components/signin/core/browser/about_signin_internals.cc
+++ b/chromium/components/signin/core/browser/about_signin_internals.cc
@@ -22,7 +22,6 @@
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_client.h"
#include "components/signin/core/browser/signin_internals_util.h"
@@ -164,8 +163,9 @@ void ClearPref(PrefService* prefs, TimedSigninStatusField field) {
prefs->ClearPref(time_pref);
}
-std::string GetAccountConsistencyDescription() {
- switch (signin::GetAccountConsistencyMethod()) {
+std::string GetAccountConsistencyDescription(
+ signin::AccountConsistencyMethod method) {
+ switch (method) {
case signin::AccountConsistencyMethod::kDisabled:
return "None";
case signin::AccountConsistencyMethod::kMirror:
@@ -173,9 +173,6 @@ std::string GetAccountConsistencyDescription() {
case signin::AccountConsistencyMethod::kDiceFixAuthErrors:
return "DICE fixing auth errors";
case signin::AccountConsistencyMethod::kDicePrepareMigration:
- return "DICE preparing migration";
- case signin::AccountConsistencyMethod::
- kDicePrepareMigrationChromeSyncEndpoint:
return "DICE preparing migration with Chrome sync Gaia endpoint";
case signin::AccountConsistencyMethod::kDiceMigration:
return "DICE migration";
@@ -193,13 +190,15 @@ AboutSigninInternals::AboutSigninInternals(
AccountTrackerService* account_tracker,
SigninManagerBase* signin_manager,
SigninErrorController* signin_error_controller,
- GaiaCookieManagerService* cookie_manager_service)
+ GaiaCookieManagerService* cookie_manager_service,
+ signin::AccountConsistencyMethod account_consistency)
: token_service_(token_service),
account_tracker_(account_tracker),
signin_manager_(signin_manager),
client_(nullptr),
signin_error_controller_(signin_error_controller),
- cookie_manager_service_(cookie_manager_service) {}
+ cookie_manager_service_(cookie_manager_service),
+ account_consistency_(account_consistency) {}
AboutSigninInternals::~AboutSigninInternals() {}
@@ -315,16 +314,17 @@ void AboutSigninInternals::NotifyObservers() {
std::unique_ptr<base::DictionaryValue> signin_status_value =
signin_status_.ToValue(account_tracker_, signin_manager_,
signin_error_controller_, token_service_,
- cookie_manager_service_, client_);
+ cookie_manager_service_, client_,
+ account_consistency_);
for (auto& observer : signin_observers_)
observer.OnSigninStateChanged(signin_status_value.get());
}
std::unique_ptr<base::DictionaryValue> AboutSigninInternals::GetSigninStatus() {
- return signin_status_.ToValue(account_tracker_, signin_manager_,
- signin_error_controller_, token_service_,
- cookie_manager_service_, client_);
+ return signin_status_.ToValue(
+ account_tracker_, signin_manager_, signin_error_controller_,
+ token_service_, cookie_manager_service_, client_, account_consistency_);
}
void AboutSigninInternals::OnAccessTokenRequested(
@@ -524,7 +524,8 @@ AboutSigninInternals::SigninStatus::ToValue(
SigninErrorController* signin_error_controller,
ProfileOAuth2TokenService* token_service,
GaiaCookieManagerService* cookie_manager_service,
- SigninClient* signin_client) {
+ SigninClient* signin_client,
+ signin::AccountConsistencyMethod account_consistency) {
auto signin_status = std::make_unique<base::DictionaryValue>();
auto signin_info = std::make_unique<base::ListValue>();
@@ -534,7 +535,7 @@ AboutSigninInternals::SigninStatus::ToValue(
AddSectionEntry(basic_info, "Chrome Version",
signin_client->GetProductVersion());
AddSectionEntry(basic_info, "Account Consistency",
- GetAccountConsistencyDescription());
+ GetAccountConsistencyDescription(account_consistency));
AddSectionEntry(basic_info, "Signin Status",
signin_manager->IsAuthenticated() ? "Signed In" : "Not Signed In");
OAuth2TokenServiceDelegate::LoadCredentialsState load_tokens_state =
@@ -653,14 +654,5 @@ AboutSigninInternals::SigninStatus::ToValue(
}
signin_status->Set("accountInfo", std::move(account_info));
-
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
- if (signin::IsDiceEnabledForProfile(signin_client->GetPrefs())) {
- auto dice_info = std::make_unique<base::DictionaryValue>();
- dice_info->SetBoolean("isSignedIn", signin_manager->IsAuthenticated());
- signin_status->Set("dice", std::move(dice_info));
- }
-#endif
-
return signin_status;
}
diff --git a/chromium/components/signin/core/browser/about_signin_internals.h b/chromium/components/signin/core/browser/about_signin_internals.h
index 8e530ab55b3..5ae815e9f64 100644
--- a/chromium/components/signin/core/browser/about_signin_internals.h
+++ b/chromium/components/signin/core/browser/about_signin_internals.h
@@ -57,7 +57,8 @@ class AboutSigninInternals
AccountTrackerService* account_tracker,
SigninManagerBase* signin_manager,
SigninErrorController* signin_error_controller,
- GaiaCookieManagerService* cookie_manager_service);
+ GaiaCookieManagerService* cookie_manager_service,
+ signin::AccountConsistencyMethod account_consistency);
~AboutSigninInternals() override;
// Registers the preferences used by AboutSigninInternals.
@@ -164,7 +165,8 @@ class AboutSigninInternals
SigninErrorController* signin_error_controller,
ProfileOAuth2TokenService* token_service,
GaiaCookieManagerService* cookie_manager_service_,
- SigninClient* signin_client);
+ SigninClient* signin_client,
+ signin::AccountConsistencyMethod account_consistency);
};
// SigninManager::SigninDiagnosticsObserver implementation.
@@ -223,6 +225,8 @@ class AboutSigninInternals
// Most of the values are mirrored in the prefs for persistence.
SigninStatus signin_status_;
+ signin::AccountConsistencyMethod account_consistency_;
+
base::ObserverList<Observer> signin_observers_;
DISALLOW_COPY_AND_ASSIGN(AboutSigninInternals);
diff --git a/chromium/components/signin/core/browser/account_fetcher_service.cc b/chromium/components/signin/core/browser/account_fetcher_service.cc
index ce779419f32..7027fef0164 100644
--- a/chromium/components/signin/core/browser/account_fetcher_service.cc
+++ b/chromium/components/signin/core/browser/account_fetcher_service.cc
@@ -10,10 +10,13 @@
#include "base/metrics/field_trial.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "components/image_fetcher/core/image_decoder.h"
+#include "components/image_fetcher/core/image_fetcher_impl.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/account_info_fetcher.h"
#include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/core/browser/avatar_icon_util.h"
#include "components/signin/core/browser/child_account_info_fetcher.h"
#include "components/signin/core/browser/signin_client.h"
#include "components/signin/core/browser/signin_switches.h"
@@ -24,6 +27,8 @@ namespace {
const base::TimeDelta kRefreshFromTokenServiceDelay =
base::TimeDelta::FromHours(24);
+constexpr int kAccountImageDownloadSize = 64;
+
bool AccountSupportsUserInfo(const std::string& account_id) {
// Supervised users use a specially scoped token which when used for general
// purposes causes the token service to raise spurious auth errors.
@@ -32,7 +37,7 @@ bool AccountSupportsUserInfo(const std::string& account_id) {
return account_id != "managed_user@localhost";
}
-}
+} // namespace
// This pref used to be in the AccountTrackerService, hence its string value.
const char AccountFetcherService::kLastUpdatePref[] =
@@ -65,7 +70,8 @@ void AccountFetcherService::RegisterPrefs(
void AccountFetcherService::Initialize(
SigninClient* signin_client,
OAuth2TokenService* token_service,
- AccountTrackerService* account_tracker_service) {
+ AccountTrackerService* account_tracker_service,
+ std::unique_ptr<image_fetcher::ImageDecoder> image_decoder) {
DCHECK(signin_client);
DCHECK(!signin_client_);
signin_client_ = signin_client;
@@ -76,6 +82,9 @@ void AccountFetcherService::Initialize(
DCHECK(!token_service_);
token_service_ = token_service;
token_service_->AddObserver(this);
+ DCHECK(image_decoder);
+ DCHECK(!image_decoder_);
+ image_decoder_ = std::move(image_decoder);
last_updated_ = base::Time::FromInternalValue(
signin_client_->GetPrefs()->GetInt64(kLastUpdatePref));
@@ -247,9 +256,60 @@ void AccountFetcherService::OnUserInfoFetchSuccess(
std::unique_ptr<base::DictionaryValue> user_info) {
account_tracker_service_->SetAccountStateFromUserInfo(account_id,
user_info.get());
+ FetchAccountImage(account_id);
user_info_requests_.erase(account_id);
}
+image_fetcher::ImageFetcherImpl*
+AccountFetcherService::GetOrCreateImageFetcher() {
+ // Lazy initialization of |image_fetcher_| because the request context might
+ // not be available yet when |Initialize| is called.
+ if (!image_fetcher_) {
+ image_fetcher_ = std::make_unique<image_fetcher::ImageFetcherImpl>(
+ std::move(image_decoder_), signin_client_->GetURLRequestContext());
+ image_fetcher_->SetImageFetcherDelegate(this);
+ }
+ return image_fetcher_.get();
+}
+
+void AccountFetcherService::FetchAccountImage(const std::string& account_id) {
+ DCHECK(signin_client_);
+ std::string picture_url_string =
+ account_tracker_service_->GetAccountInfo(account_id).picture_url;
+ GURL picture_url(picture_url_string);
+ if (!picture_url.is_valid()) {
+ DVLOG(1) << "Invalid avatar picture URL: \"" + picture_url_string + "\"";
+ return;
+ }
+ net::NetworkTrafficAnnotationTag traffic_annotation =
+ net::DefineNetworkTrafficAnnotation("accounts_image_fetcher", R"(
+ semantics {
+ sender: "Image fetcher for GAIA accounts"
+ description:
+ "To use a GAIA web account to log into Chrome in the user menu, the"
+ "account images of the signed-in GAIA accounts are displayed."
+ trigger: "At startup."
+ data: "Account picture URL of signed-in GAIA accounts."
+ destination: GOOGLE_OWNED_SERVICE
+ }
+ policy {
+ cookies_allowed: YES
+ cookies_store: "user"
+ setting: "This feature cannot be disabled by settings, "
+ "however, it will only be requested if the user "
+ "has signed into the web."
+ policy_exception_justification:
+ "Not implemented, considered not useful as no content is being "
+ "uploaded or saved; this request merely downloads the web account"
+ "profile image."
+ })");
+ GURL image_url_with_size(signin::GetAvatarImageURLWithOptions(
+ picture_url, kAccountImageDownloadSize, true /* no_silhouette */));
+ GetOrCreateImageFetcher()->StartOrQueueNetworkRequest(
+ account_id, image_url_with_size,
+ image_fetcher::ImageFetcher::ImageFetcherCallback(), traffic_annotation);
+}
+
void AccountFetcherService::SetIsChildAccount(const std::string& account_id,
bool is_child_account) {
if (child_request_account_id_ == account_id)
@@ -306,3 +366,8 @@ void AccountFetcherService::OnRefreshTokensLoaded() {
refresh_tokens_loaded_ = true;
MaybeEnableNetworkFetches();
}
+
+void AccountFetcherService::OnImageFetched(const std::string& id,
+ const gfx::Image& image) {
+ account_tracker_service_->SetAccountImage(id, image);
+}
diff --git a/chromium/components/signin/core/browser/account_fetcher_service.h b/chromium/components/signin/core/browser/account_fetcher_service.h
index d8abc509631..6e864355521 100644
--- a/chromium/components/signin/core/browser/account_fetcher_service.h
+++ b/chromium/components/signin/core/browser/account_fetcher_service.h
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "base/timer/timer.h"
+#include "components/image_fetcher/core/image_fetcher_delegate.h"
#include "components/keyed_service/core/keyed_service.h"
#include "google_apis/gaia/oauth2_token_service.h"
@@ -22,6 +23,11 @@ class ChildAccountInfoFetcher;
class OAuth2TokenService;
class SigninClient;
+namespace image_fetcher {
+class ImageDecoder;
+class ImageFetcherImpl;
+} // namespace image_fetcher
+
namespace invalidation {
class InvalidationService;
}
@@ -34,7 +40,8 @@ class PrefRegistrySyncable;
// to child account info fetching.
class AccountFetcherService : public KeyedService,
- public OAuth2TokenService::Observer {
+ public OAuth2TokenService::Observer,
+ public image_fetcher::ImageFetcherDelegate {
public:
// Name of the preference that tracks the int64_t representation of the last
// time the AccountTrackerService was updated.
@@ -48,7 +55,8 @@ class AccountFetcherService : public KeyedService,
void Initialize(SigninClient* signin_client,
OAuth2TokenService* token_service,
- AccountTrackerService* account_tracker_service);
+ AccountTrackerService* account_tracker_service,
+ std::unique_ptr<image_fetcher::ImageDecoder> image_decoder);
// KeyedService implementation
void Shutdown() override;
@@ -112,6 +120,14 @@ class AccountFetcherService : public KeyedService,
std::unique_ptr<base::DictionaryValue> user_info);
void OnUserInfoFetchFailure(const std::string& account_id);
+ image_fetcher::ImageFetcherImpl* GetOrCreateImageFetcher();
+
+ // Called in |OnUserInfoFetchSuccess| after the account info has been fetched.
+ void FetchAccountImage(const std::string& account_id);
+
+ // image_fetcher::ImageFetcherDelegate:
+ void OnImageFetched(const std::string& id, const gfx::Image& image) override;
+
AccountTrackerService* account_tracker_service_; // Not owned.
OAuth2TokenService* token_service_; // Not owned.
SigninClient* signin_client_; // Not owned.
@@ -132,6 +148,10 @@ class AccountFetcherService : public KeyedService,
std::unordered_map<std::string, std::unique_ptr<AccountInfoFetcher>>
user_info_requests_;
+ // Used for fetching the account images.
+ std::unique_ptr<image_fetcher::ImageFetcherImpl> image_fetcher_;
+ std::unique_ptr<image_fetcher::ImageDecoder> image_decoder_;
+
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(AccountFetcherService);
diff --git a/chromium/components/signin/core/browser/account_info.cc b/chromium/components/signin/core/browser/account_info.cc
index 50c89ba6823..326350ba4c7 100644
--- a/chromium/components/signin/core/browser/account_info.cc
+++ b/chromium/components/signin/core/browser/account_info.cc
@@ -34,6 +34,12 @@ AccountInfo::AccountInfo()
AccountInfo::AccountInfo(const AccountInfo& other) = default;
AccountInfo::~AccountInfo() {}
+bool AccountInfo::IsEmpty() const {
+ return account_id.empty() && email.empty() && gaia.empty() &&
+ hosted_domain.empty() && full_name.empty() && given_name.empty() &&
+ locale.empty() && picture_url.empty();
+}
+
bool AccountInfo::IsValid() const {
return !account_id.empty() && !email.empty() && !gaia.empty() &&
!hosted_domain.empty() && !full_name.empty() && !given_name.empty() &&
diff --git a/chromium/components/signin/core/browser/account_info.h b/chromium/components/signin/core/browser/account_info.h
index 2ac96d89740..e54e9849229 100644
--- a/chromium/components/signin/core/browser/account_info.h
+++ b/chromium/components/signin/core/browser/account_info.h
@@ -23,7 +23,12 @@ struct AccountInfo {
std::string picture_url;
bool is_child_account;
+ // Returns true if all fields in the account info are empty.
+ bool IsEmpty() const;
+
+ // Returns true if all fields in this account info are filled.
bool IsValid() const;
+
// Updates the empty fields of |this| with |other|. Returns whether at least
// one field was updated.
bool UpdateWith(const AccountInfo& other);
diff --git a/chromium/components/signin/core/browser/account_info_unittest.cc b/chromium/components/signin/core/browser/account_info_unittest.cc
index 663ad4efecf..844632d7134 100644
--- a/chromium/components/signin/core/browser/account_info_unittest.cc
+++ b/chromium/components/signin/core/browser/account_info_unittest.cc
@@ -7,6 +7,28 @@
class AccountInfoTest : public testing::Test {};
+TEST_F(AccountInfoTest, IsEmpty) {
+ {
+ AccountInfo info_empty;
+ EXPECT_TRUE(info_empty.IsEmpty());
+ }
+ {
+ AccountInfo info_with_account_id;
+ info_with_account_id.account_id = "test_id";
+ EXPECT_FALSE(info_with_account_id.IsEmpty());
+ }
+ {
+ AccountInfo info_with_email;
+ info_with_email.email = "test_email@email.com";
+ EXPECT_FALSE(info_with_email.IsEmpty());
+ }
+ {
+ AccountInfo info_with_gaia;
+ info_with_gaia.gaia = "test_gaia";
+ EXPECT_FALSE(info_with_gaia.IsEmpty());
+ }
+}
+
// Tests that IsValid() returns true only when all the fields are non-empty.
TEST_F(AccountInfoTest, IsValid) {
AccountInfo info;
diff --git a/chromium/components/signin/core/browser/account_reconcilor.h b/chromium/components/signin/core/browser/account_reconcilor.h
index 4870e8d40ea..db4adb51b2a 100644
--- a/chromium/components/signin/core/browser/account_reconcilor.h
+++ b/chromium/components/signin/core/browser/account_reconcilor.h
@@ -123,6 +123,8 @@ class AccountReconcilor : public KeyedService,
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, UnverifiedAccountMerge);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, DiceMigrationAfterNoop);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
+ DiceNoMigrationWhenTokensNotReady);
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
DiceNoMigrationAfterReconcile);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
DiceReconcileReuseGaiaFirstAccount);
diff --git a/chromium/components/signin/core/browser/account_reconcilor_unittest.cc b/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
index ed2d43b787d..abbd9b6df6a 100644
--- a/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -17,6 +17,7 @@
#include "base/time/time.h"
#include "base/timer/mock_timer.h"
#include "build/build_config.h"
+#include "components/pref_registry/pref_registry_syncable.h"
#include "components/signin/core/browser/account_reconcilor.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/fake_gaia_cookie_manager_service.h"
@@ -25,10 +26,10 @@
#include "components/signin/core/browser/mirror_account_reconcilor_delegate.h"
#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/scoped_account_consistency.h"
#include "components/signin/core/browser/signin_features.h"
#include "components/signin/core/browser/signin_manager.h"
#include "components/signin/core/browser/signin_metrics.h"
+#include "components/signin/core/browser/signin_pref_names.h"
#include "components/signin/core/browser/test_signin_client.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
@@ -156,13 +157,11 @@ class DummyAccountReconcilorWithDelegate : public AccountReconcilor {
case signin::AccountConsistencyMethod::kDiceFixAuthErrors:
return std::make_unique<signin::AccountReconcilorDelegate>();
case signin::AccountConsistencyMethod::kDicePrepareMigration:
- case signin::AccountConsistencyMethod::
- kDicePrepareMigrationChromeSyncEndpoint:
case signin::AccountConsistencyMethod::kDiceMigration:
case signin::AccountConsistencyMethod::kDice:
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
return std::make_unique<signin::DiceAccountReconcilorDelegate>(
- signin_client);
+ signin_client, account_consistency);
#else
NOTREACHED();
return nullptr;
@@ -277,7 +276,6 @@ class AccountReconcilorTest : public ::testing::Test {
private:
base::MessageLoop loop;
signin::AccountConsistencyMethod account_consistency_;
- std::unique_ptr<signin::ScopedAccountConsistency> scoped_account_consistency_;
sync_preferences::TestingPrefServiceSyncable pref_service_;
FakeProfileOAuth2TokenService token_service_;
DiceTestSigninClient test_signin_client_;
@@ -311,6 +309,8 @@ AccountReconcilorTest::AccountReconcilorTest()
AccountTrackerService::RegisterPrefs(pref_service_.registry());
SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
SigninManagerBase::RegisterPrefs(pref_service_.registry());
+ pref_service_.registry()->RegisterBooleanPref(
+ prefs::kTokenServiceDiceCompatible, false);
get_check_connection_info_url_ =
GaiaUrls::GetInstance()->GetCheckConnectionInfoURLWithSource(
GaiaConstants::kChromeSource);
@@ -390,8 +390,6 @@ void AccountReconcilorTest::SimulateCookieContentSettingsChanged(
void AccountReconcilorTest::SetAccountConsistency(
signin::AccountConsistencyMethod method) {
account_consistency_ = method;
- scoped_account_consistency_ =
- std::make_unique<signin::ScopedAccountConsistency>(method);
}
TEST_F(AccountReconcilorTest, Basic) {
@@ -1020,6 +1018,7 @@ TEST_F(AccountReconcilorTest, UnverifiedAccountMerge) {
TEST_F(AccountReconcilorTest, DiceMigrationAfterNoop) {
// Enable Dice migration.
SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration);
+ pref_service()->SetBoolean(prefs::kTokenServiceDiceCompatible, true);
// Chrome account is consistent with the cookie.
const std::string account_id =
@@ -1029,7 +1028,6 @@ TEST_F(AccountReconcilorTest, DiceMigrationAfterNoop) {
"12345");
AccountReconcilor* reconcilor = GetMockReconcilor();
// Dice is not enabled by default.
- ASSERT_FALSE(signin::IsDiceEnabledForProfile(pref_service()));
EXPECT_FALSE(reconcilor->delegate_->IsAccountConsistencyEnforced());
// No-op reconcile.
@@ -1045,10 +1043,39 @@ TEST_F(AccountReconcilorTest, DiceMigrationAfterNoop) {
EXPECT_TRUE(test_signin_client()->is_ready_for_dice_migration());
}
+// Tests that the Dice no migration happens if the token service is not ready.
+TEST_F(AccountReconcilorTest, DiceNoMigrationWhenTokensNotReady) {
+ // Enable Dice migration.
+ SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration);
+
+ // Chrome account is consistent with the cookie.
+ const std::string account_id =
+ PickAccountIdForAccount("12345", "user@gmail.com");
+ token_service()->UpdateCredentials(account_id, "refresh_token");
+ cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com",
+ "12345");
+ AccountReconcilor* reconcilor = GetMockReconcilor();
+ // Dice is not enabled by default.
+ EXPECT_FALSE(reconcilor->delegate_->IsAccountConsistencyEnforced());
+
+ // No-op reconcile.
+ EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(testing::_)).Times(0);
+ EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()).Times(0);
+ reconcilor->StartReconcile();
+ ASSERT_TRUE(reconcilor->is_reconcile_started_);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_FALSE(reconcilor->is_reconcile_started_);
+ ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
+
+ // Migration did not happen.
+ EXPECT_FALSE(test_signin_client()->is_ready_for_dice_migration());
+}
+
// Tests that the Dice migration does not happen after a busy reconcile.
TEST_F(AccountReconcilorTest, DiceNoMigrationAfterReconcile) {
// Enable Dice migration.
SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration);
+ pref_service()->SetBoolean(prefs::kTokenServiceDiceCompatible, true);
// Add a token in Chrome.
const std::string account_id =
@@ -1057,7 +1084,6 @@ TEST_F(AccountReconcilorTest, DiceNoMigrationAfterReconcile) {
AccountReconcilor* reconcilor = GetMockReconcilor();
// Dice is not enabled by default.
- ASSERT_FALSE(signin::IsDiceEnabledForProfile(pref_service()));
EXPECT_FALSE(reconcilor->delegate_->IsAccountConsistencyEnforced());
// Busy reconcile.
@@ -1079,6 +1105,7 @@ TEST_F(AccountReconcilorTest, DiceNoMigrationAfterReconcile) {
TEST_F(AccountReconcilorTest, MigrationClearSecondaryTokens) {
// Enable Dice migration.
SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration);
+ pref_service()->SetBoolean(prefs::kTokenServiceDiceCompatible, true);
// Add a tokens in Chrome, signin to Sync, but no Gaia cookies.
const std::string account_id_1 =
@@ -1113,6 +1140,7 @@ TEST_F(AccountReconcilorTest, MigrationClearSecondaryTokens) {
TEST_F(AccountReconcilorTest, MigrationClearAllTokens) {
// Enable Dice migration.
SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration);
+ pref_service()->SetBoolean(prefs::kTokenServiceDiceCompatible, true);
// Add a tokens in Chrome but no Gaia cookies.
const std::string account_id_1 =
diff --git a/chromium/components/signin/core/browser/account_tracker_service.cc b/chromium/components/signin/core/browser/account_tracker_service.cc
index 2b0173c4d50..e2613bd1475 100644
--- a/chromium/components/signin/core/browser/account_tracker_service.cc
+++ b/chromium/components/signin/core/browser/account_tracker_service.cc
@@ -8,10 +8,14 @@
#include "base/callback.h"
#include "base/command_line.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner_util.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/pref_registry/pref_registry_syncable.h"
@@ -44,6 +48,44 @@ void RemoveDeprecatedServiceFlags(PrefService* pref_service) {
}
}
+// Reads a PNG image from disk and decodes it. If the reading/decoding attempt
+// was unsuccessful, an empty image is returned.
+gfx::Image ReadImage(const base::FilePath& image_path) {
+ base::AssertBlockingAllowed();
+
+ if (!base::PathExists(image_path))
+ return gfx::Image();
+ std::string image_data;
+ if (!base::ReadFileToString(image_path, &image_data)) {
+ LOG(ERROR) << "Failed to read image from disk: " << image_path;
+ return gfx::Image();
+ }
+ return gfx::Image::CreateFrom1xPNGBytes(
+ base::RefCountedString::TakeString(&image_data));
+}
+
+// Saves |png_data| to disk at |image_path|.
+void SaveImage(scoped_refptr<base::RefCountedMemory> png_data,
+ const base::FilePath& image_path) {
+ base::AssertBlockingAllowed();
+ // Make sure the destination directory exists.
+ base::FilePath dir = image_path.DirName();
+ if (!base::DirectoryExists(dir) && !base::CreateDirectory(dir)) {
+ LOG(ERROR) << "Failed to create parent directory of: " << image_path;
+ return;
+ }
+ if (base::WriteFile(image_path, png_data->front_as<char>(),
+ png_data->size()) == -1) {
+ LOG(ERROR) << "Failed to save image to file: " << image_path;
+ }
+}
+
+// Removes the image at path |image_path|.
+void RemoveImage(const base::FilePath& image_path) {
+ if (!base::DeleteFile(image_path, false /* recursive */))
+ LOG(ERROR) << "Failed to delete image.";
+}
+
} // namespace
const char AccountTrackerService::kAccountInfoPref[] = "account_info";
@@ -56,7 +98,11 @@ const char AccountTrackerService::kNoHostedDomainFound[] = "NO_HOSTED_DOMAIN";
// This must be a string which can never be a valid picture URL.
const char AccountTrackerService::kNoPictureURLFound[] = "NO_PICTURE_URL";
-AccountTrackerService::AccountTrackerService() : signin_client_(nullptr) {}
+const char AccountTrackerService::kAccountsFolder[] = "Accounts";
+const char AccountTrackerService::kAvatarImagesFolder[] = "Avatar Images";
+
+AccountTrackerService::AccountTrackerService()
+ : signin_client_(nullptr), weak_factory_(this) {}
AccountTrackerService::~AccountTrackerService() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -70,11 +116,21 @@ void AccountTrackerService::RegisterPrefs(
AccountTrackerService::MIGRATION_NOT_STARTED);
}
-void AccountTrackerService::Initialize(SigninClient* signin_client) {
+void AccountTrackerService::Initialize(SigninClient* signin_client,
+ const base::FilePath& user_data_dir) {
DCHECK(signin_client);
DCHECK(!signin_client_);
signin_client_ = signin_client;
LoadFromPrefs();
+ user_data_dir_ = user_data_dir;
+ if (!user_data_dir_.empty()) {
+ // |image_storage_task_runner_| is a sequenced runner because we want to
+ // avoid read and write operations to the same file at the same time.
+ image_storage_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
+ LoadAccountImagesFromDisk();
+ }
}
void AccountTrackerService::Shutdown() {
@@ -145,6 +201,12 @@ AccountInfo AccountTrackerService::FindAccountInfoByEmail(
return AccountInfo();
}
+gfx::Image AccountTrackerService::GetAccountImage(
+ const std::string& account_id) {
+ return base::ContainsKey(accounts_, account_id) ? accounts_[account_id].image
+ : gfx::Image();
+}
+
AccountTrackerService::AccountIdMigrationState
AccountTrackerService::GetMigrationState() const {
return GetMigrationState(signin_client_->GetPrefs());
@@ -172,6 +234,13 @@ void AccountTrackerService::NotifyAccountUpdated(const AccountState& state) {
observer.OnAccountUpdated(state.info);
}
+void AccountTrackerService::NotifyAccountImageUpdated(
+ const std::string& account_id,
+ const gfx::Image& image) {
+ for (auto& observer : observer_list_)
+ observer.OnAccountImageUpdated(account_id, image);
+}
+
void AccountTrackerService::NotifyAccountUpdateFailed(
const std::string& account_id) {
for (auto& observer : observer_list_)
@@ -198,12 +267,13 @@ void AccountTrackerService::StartTrackingAccount(
void AccountTrackerService::StopTrackingAccount(const std::string& account_id) {
DVLOG(1) << "StopTracking " << account_id;
if (base::ContainsKey(accounts_, account_id)) {
- AccountState& state = accounts_[account_id];
+ AccountState state = std::move(accounts_[account_id]);
RemoveFromPrefs(state);
+ RemoveAccountImageFromDisk(account_id);
+ accounts_.erase(account_id);
+
if (!state.info.gaia.empty())
NotifyAccountRemoved(state);
-
- accounts_.erase(account_id);
}
}
@@ -243,6 +313,15 @@ void AccountTrackerService::SetAccountStateFromUserInfo(
SaveToPrefs(state);
}
+void AccountTrackerService::SetAccountImage(const std::string& account_id,
+ const gfx::Image& image) {
+ if (!base::ContainsKey(accounts_, account_id))
+ return;
+ accounts_[account_id].image = image;
+ SaveAccountImageToDisk(account_id, image);
+ NotifyAccountImageUpdated(account_id, image);
+}
+
void AccountTrackerService::SetIsChildAccount(const std::string& account_id,
const bool& is_child_account) {
DCHECK(base::ContainsKey(accounts_, account_id));
@@ -295,6 +374,7 @@ void AccountTrackerService::MigrateToGaiaId() {
if (base::ContainsKey(accounts_, account_id)) {
AccountState& state = accounts_[account_id];
RemoveFromPrefs(state);
+ RemoveAccountImageFromDisk(account_id);
accounts_.erase(account_id);
}
}
@@ -306,6 +386,53 @@ void AccountTrackerService::MigrateToGaiaId() {
}
}
+base::FilePath AccountTrackerService::GetImagePathFor(
+ const std::string& account_id) {
+ return user_data_dir_.AppendASCII(kAccountsFolder)
+ .AppendASCII(kAvatarImagesFolder)
+ .AppendASCII(account_id);
+}
+
+void AccountTrackerService::OnAccountImageLoaded(const std::string& account_id,
+ gfx::Image image) {
+ if (base::ContainsKey(accounts_, account_id) &&
+ accounts_[account_id].image.IsEmpty()) {
+ accounts_[account_id].image = image;
+ NotifyAccountImageUpdated(account_id, image);
+ }
+}
+
+void AccountTrackerService::LoadAccountImagesFromDisk() {
+ if (!image_storage_task_runner_)
+ return;
+ for (const std::pair<std::string, AccountState>& account : accounts_) {
+ const std::string& account_id = account.second.info.account_id;
+ PostTaskAndReplyWithResult(
+ image_storage_task_runner_.get(), FROM_HERE,
+ base::BindOnce(&ReadImage, GetImagePathFor(account_id)),
+ base::BindOnce(&AccountTrackerService::OnAccountImageLoaded,
+ weak_factory_.GetWeakPtr(), account_id));
+ }
+}
+
+void AccountTrackerService::SaveAccountImageToDisk(
+ const std::string& account_id,
+ const gfx::Image& image) {
+ if (!image_storage_task_runner_)
+ return;
+ image_storage_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&SaveImage, image.As1xPNGBytes(),
+ GetImagePathFor(account_id)));
+}
+
+void AccountTrackerService::RemoveAccountImageFromDisk(
+ const std::string& account_id) {
+ if (!image_storage_task_runner_)
+ return;
+ image_storage_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&RemoveImage, GetImagePathFor(account_id)));
+}
+
void AccountTrackerService::LoadFromPrefs() {
const base::ListValue* list =
signin_client_->GetPrefs()->GetList(kAccountInfoPref);
@@ -375,6 +502,7 @@ void AccountTrackerService::LoadFromPrefs() {
AccountState state;
state.info.account_id = account_id;
RemoveFromPrefs(state);
+ RemoveAccountImageFromDisk(account_id);
}
if (GetMigrationState() != MIGRATION_DONE) {
diff --git a/chromium/components/signin/core/browser/account_tracker_service.h b/chromium/components/signin/core/browser/account_tracker_service.h
index 128dc73d723..c734d9c11c9 100644
--- a/chromium/components/signin/core/browser/account_tracker_service.h
+++ b/chromium/components/signin/core/browser/account_tracker_service.h
@@ -10,6 +10,7 @@
#include <string>
#include <vector>
+#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
@@ -18,6 +19,7 @@
#include "components/keyed_service/core/keyed_service.h"
#include "components/signin/core/browser/account_info.h"
#include "google_apis/gaia/gaia_auth_util.h"
+#include "ui/gfx/image/image.h"
class PrefService;
class SigninClient;
@@ -51,12 +53,18 @@ class AccountTrackerService : public KeyedService {
// Child account service flag name.
static const char kChildAccountServiceFlag[];
+ // Account folders used for storing account related data at disk.
+ static const char kAccountsFolder[];
+ static const char kAvatarImagesFolder[];
+
// Clients of AccountTrackerService can implement this interface and register
// with AddObserver() to learn about account information changes.
class Observer {
public:
virtual ~Observer() {}
virtual void OnAccountUpdated(const AccountInfo& info) {}
+ virtual void OnAccountImageUpdated(const std::string& account_id,
+ const gfx::Image& image) {}
virtual void OnAccountUpdateFailed(const std::string& account_id) {}
virtual void OnAccountRemoved(const AccountInfo& info) {}
};
@@ -85,7 +93,10 @@ class AccountTrackerService : public KeyedService {
// Take a SigninClient rather than a PrefService and a URLRequestContextGetter
// since RequestContext cannot be created at startup.
// (see http://crbug.com/171406)
- void Initialize(SigninClient* signin_client);
+ // If |user_data_dir| is empty, images will not be saved to or loaded from
+ // disk.
+ void Initialize(SigninClient* signin_client,
+ const base::FilePath& user_data_dir = base::FilePath());
// Returns the list of known accounts and for which gaia IDs
// have been fetched.
@@ -94,6 +105,10 @@ class AccountTrackerService : public KeyedService {
AccountInfo FindAccountInfoByGaiaId(const std::string& gaia_id) const;
AccountInfo FindAccountInfoByEmail(const std::string& email) const;
+ // Returns the account image associated to the account id |account_id|.
+ // If the account id is not known an empty image is returned.
+ gfx::Image GetAccountImage(const std::string& account_id);
+
// Picks the correct account_id for the specified account depending on the
// migration state.
std::string PickAccountIdForAccount(const std::string& gaia,
@@ -129,14 +144,21 @@ class AccountTrackerService : public KeyedService {
void SetAccountStateFromUserInfo(const std::string& account_id,
const base::DictionaryValue* user_info);
+ // Updates the account image. Does nothing if |account_id| does not exist in
+ // |accounts_|.
+ void SetAccountImage(const std::string& account_id, const gfx::Image& image);
+
private:
friend class AccountFetcherService;
friend class FakeAccountFetcherService;
struct AccountState {
AccountInfo info;
+ gfx::Image image;
};
void NotifyAccountUpdated(const AccountState& state);
+ void NotifyAccountImageUpdated(const std::string& account_id,
+ const gfx::Image& image);
void NotifyAccountUpdateFailed(const std::string& account_id);
void NotifyAccountRemoved(const AccountState& state);
@@ -148,6 +170,14 @@ class AccountTrackerService : public KeyedService {
void SaveToPrefs(const AccountState& account);
void RemoveFromPrefs(const AccountState& account);
+ // Used to load/save account images from/to disc.
+ base::FilePath GetImagePathFor(const std::string& account_id);
+ void OnAccountImageLoaded(const std::string& account_id, gfx::Image image);
+ void LoadAccountImagesFromDisk();
+ void SaveAccountImageToDisk(const std::string& account_id,
+ const gfx::Image& image);
+ void RemoveAccountImageFromDisk(const std::string& account_id);
+
// Gaia id migration.
bool IsMigratable() const;
void MigrateToGaiaId();
@@ -157,8 +187,17 @@ class AccountTrackerService : public KeyedService {
std::map<std::string, AccountState> accounts_;
base::ObserverList<Observer> observer_list_;
+ base::FilePath user_data_dir_;
+
+ // Task runner used for file operations on avatar images.
+ scoped_refptr<base::SequencedTaskRunner> image_storage_task_runner_;
+
SEQUENCE_CHECKER(sequence_checker_);
+ // Used to pass weak pointers of |this| to tasks created by
+ // |image_storage_task_runner_|.
+ base::WeakPtrFactory<AccountTrackerService> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(AccountTrackerService);
};
diff --git a/chromium/components/signin/core/browser/account_tracker_service_unittest.cc b/chromium/components/signin/core/browser/account_tracker_service_unittest.cc
index 8b5cb75f07c..99b8e645d33 100644
--- a/chromium/components/signin/core/browser/account_tracker_service_unittest.cc
+++ b/chromium/components/signin/core/browser/account_tracker_service_unittest.cc
@@ -7,9 +7,11 @@
#include <utility>
#include <vector>
-#include "base/message_loop/message_loop.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/strings/stringprintf.h"
+#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
+#include "components/image_fetcher/core/image_data_fetcher.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/prefs/testing_pref_service.h"
@@ -50,6 +52,7 @@ const std::string kTokenInfoIncompleteResponseFormat =
enum TrackingEventType {
UPDATED,
+ IMAGE_UPDATED,
REMOVED,
};
@@ -74,7 +77,8 @@ std::string AccountIdToLocale(const std::string& account_id) {
}
std::string AccountIdToPictureURL(const std::string& account_id) {
- return "picture_url-" + account_id;
+ return "https://example.com/-" + account_id +
+ "/AAAAAAAAAAI/AAAAAAAAACQ/Efg/photo.jpg";
}
void CheckAccountDetails(const std::string& account_id,
@@ -124,6 +128,9 @@ class TrackingEvent {
case UPDATED:
typestr = "UPD";
break;
+ case IMAGE_UPDATED:
+ typestr = "IMG_UPD";
+ break;
case REMOVED:
typestr = "REM";
break;
@@ -179,6 +186,8 @@ class AccountTrackerObserver : public AccountTrackerService::Observer {
private:
// AccountTrackerService::Observer implementation
void OnAccountUpdated(const AccountInfo& ids) override;
+ void OnAccountImageUpdated(const std::string& account_id,
+ const gfx::Image& image) override;
void OnAccountRemoved(const AccountInfo& ids) override;
testing::AssertionResult CheckEvents(
@@ -191,6 +200,12 @@ void AccountTrackerObserver::OnAccountUpdated(const AccountInfo& ids) {
events_.push_back(TrackingEvent(UPDATED, ids.account_id, ids.gaia));
}
+void AccountTrackerObserver::OnAccountImageUpdated(
+ const std::string& account_id,
+ const gfx::Image& image) {
+ events_.push_back(TrackingEvent(IMAGE_UPDATED, account_id));
+}
+
void AccountTrackerObserver::OnAccountRemoved(const AccountInfo& ids) {
events_.push_back(TrackingEvent(REMOVED, ids.account_id, ids.gaia));
}
@@ -252,7 +267,9 @@ testing::AssertionResult AccountTrackerObserver::CheckEvents(
class AccountTrackerServiceTest : public testing::Test {
public:
- AccountTrackerServiceTest() {}
+ AccountTrackerServiceTest()
+ : next_image_data_fetcher_id_(
+ image_fetcher::ImageDataFetcher::kFirstUrlFetcherId) {}
~AccountTrackerServiceTest() override {}
@@ -270,15 +287,16 @@ class AccountTrackerServiceTest : public testing::Test {
AccountFetcherService::kLastUpdatePref, 0);
signin_client_.reset(new TestSigninClient(&pref_service_));
signin_client_.get()->SetURLRequestContext(
- new net::TestURLRequestContextGetter(message_loop_.task_runner()));
+ new net::TestURLRequestContextGetter(
+ scoped_task_environment_.GetMainThreadTaskRunner()));
account_tracker_.reset(new AccountTrackerService());
account_tracker_->Initialize(signin_client_.get());
account_fetcher_.reset(new AccountFetcherService());
- account_fetcher_->Initialize(signin_client_.get(),
- fake_oauth2_token_service_.get(),
- account_tracker_.get());
+ account_fetcher_->Initialize(
+ signin_client_.get(), fake_oauth2_token_service_.get(),
+ account_tracker_.get(), std::make_unique<TestImageDecoder>());
account_fetcher_->EnableNetworkFetchesForTest();
}
@@ -320,9 +338,11 @@ class AccountTrackerServiceTest : public testing::Test {
AccountIdToGaiaId(account_id).c_str(),
AccountIdToEmail(account_id).c_str());
}
- void ReturnOAuthUrlFetchSuccess(const std::string& account_id);
- void ReturnOAuthUrlFetchSuccessIncomplete(const std::string& account_id);
- void ReturnOAuthUrlFetchFailure(const std::string& account_id);
+ void ReturnAccountInfoFetchSuccess(const std::string& account_id);
+ void ReturnAccountInfoFetchSuccessIncomplete(const std::string& account_id);
+ void ReturnAccountInfoFetchFailure(const std::string& account_id);
+ void ReturnAccountImageFetchSuccess(const std::string& account_id);
+ void ReturnAccountImageFetchFailure(const std::string& account_id);
net::TestURLFetcherFactory* test_fetcher_factory() {
return &test_fetcher_factory_;
@@ -334,24 +354,28 @@ class AccountTrackerServiceTest : public testing::Test {
}
SigninClient* signin_client() { return signin_client_.get(); }
+ protected:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+
private:
- void ReturnOAuthUrlFetchResults(int fetcher_id,
- net::HttpStatusCode response_code,
- const std::string& response_string);
+ void ReturnFetchResults(int fetcher_id,
+ net::HttpStatusCode response_code,
+ const std::string& response_string);
- base::MessageLoopForIO message_loop_;
net::TestURLFetcherFactory test_fetcher_factory_;
std::unique_ptr<FakeOAuth2TokenService> fake_oauth2_token_service_;
TestingPrefServiceSimple pref_service_;
std::unique_ptr<AccountFetcherService> account_fetcher_;
std::unique_ptr<AccountTrackerService> account_tracker_;
std::unique_ptr<TestSigninClient> signin_client_;
+
+ int next_image_data_fetcher_id_;
};
-void AccountTrackerServiceTest::ReturnOAuthUrlFetchResults(
+void AccountTrackerServiceTest::ReturnFetchResults(
int fetcher_id,
net::HttpStatusCode response_code,
- const std::string& response_string) {
+ const std::string& response_string) {
net::TestURLFetcher* fetcher =
test_fetcher_factory_.GetFetcherByID(fetcher_id);
ASSERT_TRUE(fetcher);
@@ -360,27 +384,35 @@ void AccountTrackerServiceTest::ReturnOAuthUrlFetchResults(
fetcher->delegate()->OnURLFetchComplete(fetcher);
}
-void AccountTrackerServiceTest::ReturnOAuthUrlFetchSuccess(
+void AccountTrackerServiceTest::ReturnAccountInfoFetchSuccess(
const std::string& account_id) {
IssueAccessToken(account_id);
- ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId,
- net::HTTP_OK,
- GenerateValidTokenInfoResponse(account_id));
+ ReturnFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_OK,
+ GenerateValidTokenInfoResponse(account_id));
}
-void AccountTrackerServiceTest::ReturnOAuthUrlFetchSuccessIncomplete(
+void AccountTrackerServiceTest::ReturnAccountInfoFetchSuccessIncomplete(
const std::string& account_id) {
IssueAccessToken(account_id);
- ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId,
- net::HTTP_OK,
- GenerateIncompleteTokenInfoResponse(account_id));
+ ReturnFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_OK,
+ GenerateIncompleteTokenInfoResponse(account_id));
}
-void AccountTrackerServiceTest::ReturnOAuthUrlFetchFailure(
+void AccountTrackerServiceTest::ReturnAccountInfoFetchFailure(
const std::string& account_id) {
IssueAccessToken(account_id);
- ReturnOAuthUrlFetchResults(
- gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_BAD_REQUEST, "");
+ ReturnFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId,
+ net::HTTP_BAD_REQUEST, "");
+}
+
+void AccountTrackerServiceTest::ReturnAccountImageFetchSuccess(
+ const std::string& account_id) {
+ ReturnFetchResults(next_image_data_fetcher_id_++, net::HTTP_OK, "image data");
+}
+
+void AccountTrackerServiceTest::ReturnAccountImageFetchFailure(
+ const std::string& account_id) {
+ ReturnFetchResults(next_image_data_fetcher_id_++, net::HTTP_BAD_REQUEST, "");
}
TEST_F(AccountTrackerServiceTest, Basic) {
@@ -405,13 +437,34 @@ TEST_F(AccountTrackerServiceTest, TokenAvailable_Revoked) {
account_tracker()->RemoveObserver(&observer);
}
-TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo) {
+TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo_ImageSuccess) {
+ AccountTrackerObserver observer;
+ account_tracker()->AddObserver(&observer);
+ SimulateTokenAvailable("alpha");
+ ReturnAccountInfoFetchSuccess("alpha");
+ ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
+ ASSERT_TRUE(observer.CheckEvents(TrackingEvent(UPDATED, "alpha")));
+
+ ASSERT_TRUE(account_tracker()->GetAccountImage("alpha").IsEmpty());
+ ReturnAccountImageFetchSuccess("alpha");
+ ASSERT_TRUE(observer.CheckEvents(TrackingEvent(IMAGE_UPDATED, "alpha")));
+ ASSERT_FALSE(account_tracker()->GetAccountImage("alpha").IsEmpty());
+
+ account_tracker()->RemoveObserver(&observer);
+}
+
+TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo_ImageFailure) {
AccountTrackerObserver observer;
account_tracker()->AddObserver(&observer);
SimulateTokenAvailable("alpha");
- ReturnOAuthUrlFetchSuccess("alpha");
+ ReturnAccountInfoFetchSuccess("alpha");
ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
ASSERT_TRUE(observer.CheckEvents(TrackingEvent(UPDATED, "alpha")));
+
+ ASSERT_TRUE(account_tracker()->GetAccountImage("alpha").IsEmpty());
+ ReturnAccountImageFetchFailure("alpha");
+ ASSERT_TRUE(account_tracker()->GetAccountImage("alpha").IsEmpty());
+
account_tracker()->RemoveObserver(&observer);
}
@@ -419,7 +472,7 @@ TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfo_Revoked) {
AccountTrackerObserver observer;
account_tracker()->AddObserver(&observer);
SimulateTokenAvailable("alpha");
- ReturnOAuthUrlFetchSuccess("alpha");
+ ReturnAccountInfoFetchSuccess("alpha");
ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
ASSERT_TRUE(observer.CheckEvents(TrackingEvent(UPDATED, "alpha")));
SimulateTokenRevoked("alpha");
@@ -431,7 +484,7 @@ TEST_F(AccountTrackerServiceTest, TokenAvailable_UserInfoFailed) {
AccountTrackerObserver observer;
account_tracker()->AddObserver(&observer);
SimulateTokenAvailable("alpha");
- ReturnOAuthUrlFetchFailure("alpha");
+ ReturnAccountInfoFetchFailure("alpha");
ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
ASSERT_TRUE(observer.CheckEvents());
account_tracker()->RemoveObserver(&observer);
@@ -441,7 +494,7 @@ TEST_F(AccountTrackerServiceTest, TokenAvailableTwice_UserInfoOnce) {
AccountTrackerObserver observer;
account_tracker()->AddObserver(&observer);
SimulateTokenAvailable("alpha");
- ReturnOAuthUrlFetchSuccess("alpha");
+ ReturnAccountInfoFetchSuccess("alpha");
ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
ASSERT_TRUE(observer.CheckEvents(TrackingEvent(UPDATED, "alpha")));
@@ -460,7 +513,8 @@ TEST_F(AccountTrackerServiceTest, TokenAlreadyExists) {
tracker.AddObserver(&observer);
tracker.Initialize(signin_client());
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
fetcher.EnableNetworkFetchesForTest();
ASSERT_FALSE(fetcher.IsAllUserInfoFetched());
ASSERT_TRUE(observer.CheckEvents());
@@ -474,8 +528,8 @@ TEST_F(AccountTrackerServiceTest, TwoTokenAvailable_TwoUserInfo) {
account_tracker()->AddObserver(&observer);
SimulateTokenAvailable("alpha");
SimulateTokenAvailable("beta");
- ReturnOAuthUrlFetchSuccess("alpha");
- ReturnOAuthUrlFetchSuccess("beta");
+ ReturnAccountInfoFetchSuccess("alpha");
+ ReturnAccountInfoFetchSuccess("beta");
ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
ASSERT_TRUE(observer.CheckEvents(TrackingEvent(UPDATED, "alpha"),
TrackingEvent(UPDATED, "beta")));
@@ -487,10 +541,10 @@ TEST_F(AccountTrackerServiceTest, TwoTokenAvailable_OneUserInfo) {
account_tracker()->AddObserver(&observer);
SimulateTokenAvailable("alpha");
SimulateTokenAvailable("beta");
- ReturnOAuthUrlFetchSuccess("beta");
+ ReturnAccountInfoFetchSuccess("beta");
ASSERT_FALSE(account_fetcher()->IsAllUserInfoFetched());
ASSERT_TRUE(observer.CheckEvents(TrackingEvent(UPDATED, "beta")));
- ReturnOAuthUrlFetchSuccess("alpha");
+ ReturnAccountInfoFetchSuccess("alpha");
ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
ASSERT_TRUE(observer.CheckEvents(TrackingEvent(UPDATED, "alpha")));
account_tracker()->RemoveObserver(&observer);
@@ -500,9 +554,9 @@ TEST_F(AccountTrackerServiceTest, GetAccounts) {
SimulateTokenAvailable("alpha");
SimulateTokenAvailable("beta");
SimulateTokenAvailable("gamma");
- ReturnOAuthUrlFetchSuccess("alpha");
- ReturnOAuthUrlFetchSuccess("beta");
- ReturnOAuthUrlFetchSuccess("gamma");
+ ReturnAccountInfoFetchSuccess("alpha");
+ ReturnAccountInfoFetchSuccess("beta");
+ ReturnAccountInfoFetchSuccess("gamma");
std::vector<AccountInfo> infos = account_tracker()->GetAccounts();
@@ -527,7 +581,7 @@ TEST_F(AccountTrackerServiceTest, GetAccountInfo_TokenAvailable) {
TEST_F(AccountTrackerServiceTest, GetAccountInfo_TokenAvailable_UserInfo) {
SimulateTokenAvailable("alpha");
- ReturnOAuthUrlFetchSuccess("alpha");
+ ReturnAccountInfoFetchSuccess("alpha");
AccountInfo info = account_tracker()->GetAccountInfo("alpha");
CheckAccountDetails("alpha", info);
}
@@ -542,7 +596,8 @@ TEST_F(AccountTrackerServiceTest, GetAccountInfo_TokenAvailable_EnableNetwork) {
tracker.Initialize(signin_client());
AccountFetcherService fetcher_service;
- fetcher_service.Initialize(signin_client(), token_service(), &tracker);
+ fetcher_service.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
SimulateTokenAvailable("alpha");
IssueAccessToken("alpha");
@@ -555,7 +610,7 @@ TEST_F(AccountTrackerServiceTest, GetAccountInfo_TokenAvailable_EnableNetwork) {
fetcher_service.EnableNetworkFetchesForTest();
// Fetcher was created and executes properly.
- ReturnOAuthUrlFetchSuccess("alpha");
+ ReturnAccountInfoFetchSuccess("alpha");
AccountInfo info = tracker.GetAccountInfo("alpha");
CheckAccountDetails("alpha", info);
@@ -565,7 +620,7 @@ TEST_F(AccountTrackerServiceTest, GetAccountInfo_TokenAvailable_EnableNetwork) {
TEST_F(AccountTrackerServiceTest, FindAccountInfoByGaiaId) {
SimulateTokenAvailable("alpha");
- ReturnOAuthUrlFetchSuccess("alpha");
+ ReturnAccountInfoFetchSuccess("alpha");
std::string gaia_id = AccountIdToGaiaId("alpha");
AccountInfo info = account_tracker()->FindAccountInfoByGaiaId(gaia_id);
@@ -579,7 +634,7 @@ TEST_F(AccountTrackerServiceTest, FindAccountInfoByGaiaId) {
TEST_F(AccountTrackerServiceTest, FindAccountInfoByEmail) {
SimulateTokenAvailable("alpha");
- ReturnOAuthUrlFetchSuccess("alpha");
+ ReturnAccountInfoFetchSuccess("alpha");
std::string email = AccountIdToEmail("alpha");
AccountInfo info = account_tracker()->FindAccountInfoByEmail(email);
@@ -600,27 +655,37 @@ TEST_F(AccountTrackerServiceTest, FindAccountInfoByEmail) {
}
TEST_F(AccountTrackerServiceTest, Persistence) {
+ // Define a user data directory for the account image storage.
+ base::ScopedTempDir scoped_user_data_dir;
+ ASSERT_TRUE(scoped_user_data_dir.CreateUniqueTempDir());
// Create a tracker and add two accounts. This should cause the accounts
// to be saved to persistence.
{
AccountTrackerService tracker;
- tracker.Initialize(signin_client());
+ tracker.Initialize(signin_client(), scoped_user_data_dir.GetPath());
SimulateTokenAvailable("alpha");
- ReturnOAuthUrlFetchSuccess("alpha");
+ ReturnAccountInfoFetchSuccess("alpha");
+ ReturnAccountImageFetchSuccess("alpha");
SimulateTokenAvailable("beta");
- ReturnOAuthUrlFetchSuccess("beta");
+ ReturnAccountInfoFetchSuccess("beta");
+ ReturnAccountImageFetchSuccess("beta");
tracker.Shutdown();
}
- // Create a new tracker and make sure it loads the accounts correctly from
- // persistence.
+ // Create a new tracker and make sure it loads the accounts (including the
+ // images) correctly from persistence.
{
AccountTrackerService tracker;
AccountTrackerObserver observer;
tracker.AddObserver(&observer);
- tracker.Initialize(signin_client());
+ tracker.Initialize(signin_client(), scoped_user_data_dir.GetPath());
ASSERT_TRUE(observer.CheckEvents(TrackingEvent(UPDATED, "alpha"),
TrackingEvent(UPDATED, "beta")));
+ // Wait until all account images are loaded.
+ scoped_task_environment_.RunUntilIdle();
+ ASSERT_TRUE(observer.CheckEvents(TrackingEvent(IMAGE_UPDATED, "alpha"),
+ TrackingEvent(IMAGE_UPDATED, "beta")));
+
tracker.RemoveObserver(&observer);
std::vector<AccountInfo> infos = tracker.GetAccounts();
@@ -629,7 +694,8 @@ TEST_F(AccountTrackerServiceTest, Persistence) {
CheckAccountDetails("beta", infos[1]);
FakeAccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
fetcher.EnableNetworkFetchesForTest();
// Remove an account.
// This will allow testing removal as well as child accounts which is only
@@ -727,10 +793,11 @@ TEST_F(AccountTrackerServiceTest, UpgradeToFullAccountInfo) {
AccountTrackerService tracker;
tracker.Initialize(signin_client());
AccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
fetcher.EnableNetworkFetchesForTest();
SimulateTokenAvailable("incomplete");
- ReturnOAuthUrlFetchSuccessIncomplete("incomplete");
+ ReturnAccountInfoFetchSuccessIncomplete("incomplete");
tracker.Shutdown();
fetcher.Shutdown();
}
@@ -739,7 +806,8 @@ TEST_F(AccountTrackerServiceTest, UpgradeToFullAccountInfo) {
AccountTrackerService tracker;
tracker.Initialize(signin_client());
AccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
fetcher.EnableNetworkFetchesForTest();
// Validate that the loaded AccountInfo from prefs is considered invalid.
std::vector<AccountInfo> infos = tracker.GetAccounts();
@@ -748,7 +816,7 @@ TEST_F(AccountTrackerServiceTest, UpgradeToFullAccountInfo) {
// Simulate the same account getting a refresh token with all the info.
SimulateTokenAvailable("incomplete");
- ReturnOAuthUrlFetchSuccess("incomplete");
+ ReturnAccountInfoFetchSuccess("incomplete");
// Validate that the account is now considered valid.
infos = tracker.GetAccounts();
@@ -767,7 +835,8 @@ TEST_F(AccountTrackerServiceTest, UpgradeToFullAccountInfo) {
tracker.AddObserver(&observer);
tracker.Initialize(signin_client());
AccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
ASSERT_TRUE(observer.CheckEvents(TrackingEvent(UPDATED, "incomplete")));
// Enabling network fetches shouldn't cause any actual fetch since the
@@ -793,12 +862,13 @@ TEST_F(AccountTrackerServiceTest, TimerRefresh) {
AccountTrackerService tracker;
tracker.Initialize(signin_client());
AccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
fetcher.EnableNetworkFetchesForTest();
SimulateTokenAvailable("alpha");
- ReturnOAuthUrlFetchSuccess("alpha");
+ ReturnAccountInfoFetchSuccess("alpha");
SimulateTokenAvailable("beta");
- ReturnOAuthUrlFetchSuccess("beta");
+ ReturnAccountInfoFetchSuccess("beta");
tracker.Shutdown();
fetcher.Shutdown();
}
@@ -816,7 +886,8 @@ TEST_F(AccountTrackerServiceTest, TimerRefresh) {
AccountTrackerService tracker;
tracker.Initialize(signin_client());
AccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
ASSERT_TRUE(fetcher.IsAllUserInfoFetched());
std::vector<AccountInfo> infos = tracker.GetAccounts();
@@ -842,7 +913,8 @@ TEST_F(AccountTrackerServiceTest, TimerRefresh) {
AccountTrackerService tracker;
tracker.Initialize(signin_client());
AccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
ASSERT_TRUE(fetcher.IsAllUserInfoFetched());
std::vector<AccountInfo> infos = tracker.GetAccounts();
@@ -865,12 +937,13 @@ TEST_F(AccountTrackerServiceTest, LegacyDottedAccountIds) {
AccountTrackerService tracker;
tracker.Initialize(signin_client());
AccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
fetcher.EnableNetworkFetchesForTest();
SimulateTokenAvailable("foo.bar@gmail.com");
SimulateTokenAvailable("foobar@gmail.com");
- ReturnOAuthUrlFetchSuccess("foo.bar@gmail.com");
- ReturnOAuthUrlFetchSuccess("foobar@gmail.com");
+ ReturnAccountInfoFetchSuccess("foo.bar@gmail.com");
+ ReturnAccountInfoFetchSuccess("foobar@gmail.com");
tracker.Shutdown();
fetcher.Shutdown();
}
@@ -885,7 +958,8 @@ TEST_F(AccountTrackerServiceTest, LegacyDottedAccountIds) {
AccountTrackerService tracker;
tracker.Initialize(signin_client());
AccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
ASSERT_TRUE(fetcher.IsAllUserInfoFetched());
std::vector<AccountInfo> infos = tracker.GetAccounts();
@@ -1085,7 +1159,8 @@ TEST_F(AccountTrackerServiceTest, ChildAccountBasic) {
AccountTrackerService tracker;
tracker.Initialize(signin_client());
FakeAccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
fetcher.EnableNetworkFetchesForTest();
AccountTrackerObserver observer;
tracker.AddObserver(&observer);
@@ -1114,7 +1189,8 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedAndRevoked) {
AccountTrackerService tracker;
tracker.Initialize(signin_client());
FakeAccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
fetcher.EnableNetworkFetchesForTest();
AccountTrackerObserver observer;
tracker.AddObserver(&observer);
@@ -1143,7 +1219,8 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedAndRevokedWithUpdate) {
AccountTrackerService tracker;
tracker.Initialize(signin_client());
FakeAccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
fetcher.EnableNetworkFetchesForTest();
AccountTrackerObserver observer;
tracker.AddObserver(&observer);
@@ -1178,7 +1255,8 @@ TEST_F(AccountTrackerServiceTest, ChildAccountUpdatedTwiceThenRevoked) {
AccountTrackerService tracker;
tracker.Initialize(signin_client());
FakeAccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
fetcher.EnableNetworkFetchesForTest();
AccountTrackerObserver observer;
tracker.AddObserver(&observer);
@@ -1215,7 +1293,8 @@ TEST_F(AccountTrackerServiceTest, ChildAccountGraduation) {
AccountTrackerService tracker;
tracker.Initialize(signin_client());
FakeAccountFetcherService fetcher;
- fetcher.Initialize(signin_client(), token_service(), &tracker);
+ fetcher.Initialize(signin_client(), token_service(), &tracker,
+ std::make_unique<TestImageDecoder>());
fetcher.EnableNetworkFetchesForTest();
AccountTrackerObserver observer;
tracker.AddObserver(&observer);
@@ -1252,3 +1331,18 @@ TEST_F(AccountTrackerServiceTest, ChildAccountGraduation) {
fetcher.Shutdown();
tracker.Shutdown();
}
+
+TEST_F(AccountTrackerServiceTest, RemoveAccountBeforeImageFetchDone) {
+ AccountTrackerObserver observer;
+ account_tracker()->AddObserver(&observer);
+ SimulateTokenAvailable("alpha");
+
+ ReturnAccountInfoFetchSuccess("alpha");
+ ASSERT_TRUE(observer.CheckEvents(TrackingEvent(UPDATED, "alpha")));
+
+ SimulateTokenRevoked("alpha");
+ ReturnAccountImageFetchFailure("alpha");
+ ASSERT_TRUE(observer.CheckEvents(TrackingEvent(REMOVED, "alpha")));
+
+ account_tracker()->RemoveObserver(&observer);
+}
diff --git a/chromium/components/signin/core/browser/android/BUILD.gn b/chromium/components/signin/core/browser/android/BUILD.gn
index e1310453807..2c571ace8a7 100644
--- a/chromium/components/signin/core/browser/android/BUILD.gn
+++ b/chromium/components/signin/core/browser/android/BUILD.gn
@@ -49,6 +49,7 @@ junit_binary("components_signin_junit_tests") {
":signin_java_test_support",
"//base:base_java",
"//base:base_java_test_support",
+ "//base:base_junit_test_support",
"//third_party/android_tools:android_support_annotations_java",
"//third_party/junit",
]
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 2c050d11338..58c60a4b4c5 100644
--- a/chromium/components/signin/core/browser/chrome_connected_header_helper.cc
+++ b/chromium/components/signin/core/browser/chrome_connected_header_helper.cc
@@ -11,7 +11,6 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "components/google/core/browser/google_util.h"
-#include "components/signin/core/browser/profile_management_switches.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "url/gurl.h"
@@ -49,17 +48,18 @@ GAIAServiceType GetGAIAServiceTypeFromHeader(const std::string& header_value) {
} // namespace
-ChromeConnectedHeaderHelper::ChromeConnectedHeaderHelper(bool is_mirror_enabled)
- : is_mirror_enabled_(is_mirror_enabled) {}
+ChromeConnectedHeaderHelper::ChromeConnectedHeaderHelper(
+ AccountConsistencyMethod account_consistency)
+ : account_consistency_(account_consistency) {}
// static
std::string ChromeConnectedHeaderHelper::BuildRequestCookieIfPossible(
const GURL& url,
const std::string& account_id,
+ AccountConsistencyMethod account_consistency,
const content_settings::CookieSettings* cookie_settings,
int profile_mode_mask) {
- ChromeConnectedHeaderHelper chrome_connected_helper(
- IsAccountConsistencyMirrorEnabled());
+ ChromeConnectedHeaderHelper chrome_connected_helper(account_consistency);
if (!chrome_connected_helper.ShouldBuildRequestHeader(url, cookie_settings))
return "";
return chrome_connected_helper.BuildRequestHeader(
@@ -141,7 +141,9 @@ bool ChromeConnectedHeaderHelper::IsUrlEligibleForRequestHeader(
google_util::DISALLOW_NON_STANDARD_PORTS) ||
google_util::IsYoutubeDomainUrl(url, google_util::ALLOW_SUBDOMAIN,
google_util::DISALLOW_NON_STANDARD_PORTS);
- return (is_mirror_enabled_ && is_google_url) || IsDriveOrigin(origin) ||
+ bool is_mirror_enabled =
+ account_consistency_ == AccountConsistencyMethod::kMirror;
+ return (is_mirror_enabled && is_google_url) || IsDriveOrigin(origin) ||
gaia::IsGaiaSignonRealm(origin);
}
@@ -172,8 +174,10 @@ std::string ChromeConnectedHeaderHelper::BuildRequestHeader(
parts.push_back(
base::StringPrintf("%s=%s", kProfileModeAttrName,
base::IntToString(profile_mode_mask).c_str()));
+ bool is_mirror_enabled =
+ account_consistency_ == AccountConsistencyMethod::kMirror;
parts.push_back(base::StringPrintf("%s=%s", kEnableAccountConsistencyAttrName,
- is_mirror_enabled_ ? "true" : "false"));
+ is_mirror_enabled ? "true" : "false"));
return base::JoinString(parts, is_header_request ? "," : ":");
}
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 fab3eedc720..034de4fb069 100644
--- a/chromium/components/signin/core/browser/chrome_connected_header_helper.h
+++ b/chromium/components/signin/core/browser/chrome_connected_header_helper.h
@@ -7,6 +7,7 @@
#include <string>
+#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/signin_header_helper.h"
class GURL;
@@ -16,7 +17,8 @@ namespace signin {
// SigninHeaderHelper implementation managing the "X-Chrome-Connected" header.
class ChromeConnectedHeaderHelper : public SigninHeaderHelper {
public:
- ChromeConnectedHeaderHelper(bool is_mirror_enabled);
+ explicit ChromeConnectedHeaderHelper(
+ AccountConsistencyMethod account_consistency);
~ChromeConnectedHeaderHelper() override {}
// Returns the Chrome-Connected cookie, or an empty string if it should not be
@@ -24,6 +26,7 @@ class ChromeConnectedHeaderHelper : public SigninHeaderHelper {
static std::string BuildRequestCookieIfPossible(
const GURL& url,
const std::string& account_id,
+ AccountConsistencyMethod account_consistency,
const content_settings::CookieSettings* cookie_settings,
int profile_mode_mask);
@@ -41,7 +44,7 @@ class ChromeConnectedHeaderHelper : public SigninHeaderHelper {
private:
// Whether mirror account consistency should be used.
- bool is_mirror_enabled_ = false;
+ AccountConsistencyMethod account_consistency_;
// Returns whether the URL is eligible for the Gaia ID parameter.
bool IsUrlEligibleToIncludeGaiaId(const GURL& url, bool is_header_request);
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 dd10ef55da3..eeadbe97c15 100644
--- a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc
+++ b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc
@@ -9,23 +9,26 @@
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
-#include "components/signin/core/browser/profile_management_switches.h"
+#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/core/browser/signin_pref_names.h"
namespace signin {
DiceAccountReconcilorDelegate::DiceAccountReconcilorDelegate(
- SigninClient* signin_client)
- : signin_client_(signin_client) {
+ SigninClient* signin_client,
+ AccountConsistencyMethod account_consistency)
+ : signin_client_(signin_client), account_consistency_(account_consistency) {
DCHECK(signin_client_);
}
bool DiceAccountReconcilorDelegate::IsReconcileEnabled() const {
- return IsDicePrepareMigrationEnabled();
+ return DiceMethodGreaterOrEqual(
+ account_consistency_, AccountConsistencyMethod::kDicePrepareMigration);
}
bool DiceAccountReconcilorDelegate::IsAccountConsistencyEnforced() const {
- return IsDiceEnabledForProfile(signin_client_->GetPrefs());
+ return account_consistency_ == AccountConsistencyMethod::kDice;
}
// - On first execution, the candidates are examined in this order:
@@ -102,8 +105,10 @@ bool DiceAccountReconcilorDelegate::
const std::vector<gaia::ListedAccount>& gaia_accounts) {
// During the Dice migration step, before Dice is actually enabled, chrome
// tokens must be cleared when the cookies are cleared.
- return signin::IsDicePrepareMigrationEnabled() &&
- !signin::IsDiceEnabledForProfile(signin_client_->GetPrefs()) &&
+ return DiceMethodGreaterOrEqual(
+ account_consistency_,
+ AccountConsistencyMethod::kDicePrepareMigration) &&
+ (account_consistency_ != AccountConsistencyMethod::kDice) &&
gaia_accounts.empty();
}
@@ -112,9 +117,15 @@ void DiceAccountReconcilorDelegate::OnReconcileFinished(
bool reconcile_is_noop) {
last_known_first_account_ = first_account;
- // Migration happens on startup if the last reconcile was a no-op.
- if (IsDicePrepareMigrationEnabled())
- signin_client_->SetReadyForDiceMigration(reconcile_is_noop);
+ // Migration happens on startup if the last reconcile was a no-op and the
+ // refresh tokens are Dice-compatible.
+ if (DiceMethodGreaterOrEqual(
+ account_consistency_,
+ AccountConsistencyMethod::kDicePrepareMigration)) {
+ signin_client_->SetReadyForDiceMigration(
+ reconcile_is_noop && signin_client_->GetPrefs()->GetBoolean(
+ prefs::kTokenServiceDiceCompatible));
+ }
}
} // namespace signin
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 9fd07856551..7acc62604fd 100644
--- a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h
+++ b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
+#include "components/signin/core/browser/profile_management_switches.h"
class SigninClient;
@@ -17,7 +18,8 @@ namespace signin {
// AccountReconcilorDelegate specialized for Dice.
class DiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
public:
- DiceAccountReconcilorDelegate(SigninClient* signin_client);
+ DiceAccountReconcilorDelegate(SigninClient* signin_client,
+ AccountConsistencyMethod account_consistency);
~DiceAccountReconcilorDelegate() override {}
// AccountReconcilorDelegate:
@@ -35,6 +37,7 @@ class DiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
private:
SigninClient* signin_client_;
+ AccountConsistencyMethod account_consistency_;
// Last known "first account". Used when cookies are lost as a best guess.
std::string last_known_first_account_;
diff --git a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
index be3753ae250..784dcddb25f 100644
--- a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
+++ b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
@@ -6,26 +6,42 @@
#include <vector>
+#include "components/pref_registry/pref_registry_syncable.h"
#include "components/signin/core/browser/profile_management_switches.h"
-#include "components/signin/core/browser/scoped_account_consistency.h"
+#include "components/signin/core/browser/signin_pref_names.h"
#include "components/signin/core/browser/test_signin_client.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "google_apis/gaia/gaia_auth_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace {
+
+class DiceTestSigninClient : public testing::StrictMock<TestSigninClient> {
+ public:
+ DiceTestSigninClient(PrefService* prefs)
+ : testing::StrictMock<TestSigninClient>(prefs) {}
+
+ MOCK_METHOD1(SetReadyForDiceMigration, void(bool is_ready));
+};
+
+} // namespace
+
+namespace signin {
+
TEST(DiceAccountReconcilorDelegateTest, RevokeTokens) {
sync_preferences::TestingPrefServiceSyncable pref_service;
- signin::RegisterAccountConsistencyProfilePrefs(pref_service.registry());
TestSigninClient client(&pref_service);
- signin::DiceAccountReconcilorDelegate delegate(&client);
{
// Dice is enabled, don't revoke.
- signin::ScopedAccountConsistencyDice scoped_dice;
+ DiceAccountReconcilorDelegate delegate(&client,
+ AccountConsistencyMethod::kDice);
EXPECT_FALSE(delegate.ShouldRevokeAllSecondaryTokensBeforeReconcile(
std::vector<gaia::ListedAccount>()));
}
{
- signin::ScopedAccountConsistencyDiceMigration scoped_dice_migration;
+ DiceAccountReconcilorDelegate delegate(
+ &client, AccountConsistencyMethod::kDiceMigration);
// Gaia accounts are not empty, don't revoke.
gaia::ListedAccount gaia_account;
gaia_account.id = "other";
@@ -36,3 +52,52 @@ TEST(DiceAccountReconcilorDelegateTest, RevokeTokens) {
std::vector<gaia::ListedAccount>()));
}
}
+
+TEST(DiceAccountReconcilorDelegateTest, OnReconcileFinished) {
+ sync_preferences::TestingPrefServiceSyncable pref_service;
+ pref_service.registry()->RegisterBooleanPref(
+ prefs::kTokenServiceDiceCompatible, false);
+
+ DiceTestSigninClient client(&pref_service);
+
+ {
+ // Dice migration not enabled.
+ testing::InSequence mock_sequence;
+ EXPECT_CALL(client, SetReadyForDiceMigration(testing::_)).Times(0);
+ DiceAccountReconcilorDelegate delegate(
+ &client, AccountConsistencyMethod::kDiceFixAuthErrors);
+ delegate.OnReconcileFinished("account", true /* is_reconcile_noop */);
+ }
+
+ {
+ // Dice migration enabled, but token service is not ready.
+ testing::InSequence mock_sequence;
+ EXPECT_CALL(client, SetReadyForDiceMigration(false)).Times(1);
+ DiceAccountReconcilorDelegate delegate(
+ &client, AccountConsistencyMethod::kDicePrepareMigration);
+ delegate.OnReconcileFinished("account", true /* is_reconcile_noop */);
+ }
+
+ pref_service.SetBoolean(prefs::kTokenServiceDiceCompatible, true);
+
+ {
+ // Dice migration enabled, token service is ready, but reconcile is not
+ // no-op.
+ testing::InSequence mock_sequence;
+ EXPECT_CALL(client, SetReadyForDiceMigration(false)).Times(1);
+ DiceAccountReconcilorDelegate delegate(
+ &client, AccountConsistencyMethod::kDicePrepareMigration);
+ delegate.OnReconcileFinished("account", false /* is_reconcile_noop */);
+ }
+
+ {
+ // Ready for migration.
+ testing::InSequence mock_sequence;
+ EXPECT_CALL(client, SetReadyForDiceMigration(true)).Times(1);
+ DiceAccountReconcilorDelegate delegate(
+ &client, AccountConsistencyMethod::kDicePrepareMigration);
+ delegate.OnReconcileFinished("account", true /* is_reconcile_noop */);
+ }
+}
+
+} // namespace signin
diff --git a/chromium/components/signin/core/browser/dice_header_helper.cc b/chromium/components/signin/core/browser/dice_header_helper.cc
index 186d3b7fc2a..3f9b76cf797 100644
--- a/chromium/components/signin/core/browser/dice_header_helper.cc
+++ b/chromium/components/signin/core/browser/dice_header_helper.cc
@@ -9,7 +9,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "components/signin/core/browser/profile_management_switches.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/gaia_urls.h"
@@ -51,8 +50,10 @@ DiceAction GetDiceActionFromHeader(const std::string& value) {
} // namespace
-DiceHeaderHelper::DiceHeaderHelper(bool signed_in_with_auth_error)
- : signed_in_with_auth_error_(signed_in_with_auth_error) {}
+DiceHeaderHelper::DiceHeaderHelper(bool signed_in_with_auth_error,
+ AccountConsistencyMethod account_consistency)
+ : signed_in_with_auth_error_(signed_in_with_auth_error),
+ account_consistency_(account_consistency) {}
// static
DiceResponseParams DiceHeaderHelper::BuildDiceSigninResponseParams(
@@ -181,14 +182,15 @@ DiceResponseParams DiceHeaderHelper::BuildDiceSignoutResponseParams(
}
bool DiceHeaderHelper::IsUrlEligibleForRequestHeader(const GURL& url) {
- if (!IsDiceFixAuthErrorsEnabled())
+ if (account_consistency_ == AccountConsistencyMethod::kDisabled ||
+ account_consistency_ == AccountConsistencyMethod::kMirror) {
return false;
+ }
// With kDiceFixAuthError, only set the request header if the user is signed
// in and has an authentication error.
if (!signed_in_with_auth_error_ &&
- (GetAccountConsistencyMethod() ==
- AccountConsistencyMethod::kDiceFixAuthErrors)) {
+ (account_consistency_ == AccountConsistencyMethod::kDiceFixAuthErrors)) {
return false;
}
@@ -196,13 +198,12 @@ bool DiceHeaderHelper::IsUrlEligibleForRequestHeader(const GURL& url) {
}
std::string DiceHeaderHelper::BuildRequestHeader(
- const std::string& sync_account_id,
- SignoutMode signout_mode) {
+ const std::string& sync_account_id) {
// When fixing auth errors, only add the header when Sync is actually in error
// state.
- DCHECK(signed_in_with_auth_error_ ||
- (GetAccountConsistencyMethod() !=
- AccountConsistencyMethod::kDiceFixAuthErrors));
+ DCHECK(
+ signed_in_with_auth_error_ ||
+ (account_consistency_ != AccountConsistencyMethod::kDiceFixAuthErrors));
DCHECK(!(sync_account_id.empty() && signed_in_with_auth_error_));
std::vector<std::string> parts;
@@ -213,23 +214,17 @@ std::string DiceHeaderHelper::BuildRequestHeader(
parts.push_back("sync_account_id=" + sync_account_id);
// Restrict Signin to Sync account only when fixing auth errors.
- std::string signin_mode = (GetAccountConsistencyMethod() ==
- AccountConsistencyMethod::kDiceFixAuthErrors)
- ? kRequestSigninSyncAccount
- : kRequestSigninAll;
+ std::string signin_mode =
+ (account_consistency_ == AccountConsistencyMethod::kDiceFixAuthErrors)
+ ? kRequestSigninSyncAccount
+ : kRequestSigninAll;
parts.push_back("signin_mode=" + signin_mode);
// Show the signout confirmation only when Dice is fully enabled.
- const char* signout_mode_value = nullptr;
- switch (signout_mode) {
- case SignoutMode::kNoSignoutConfirmation:
- signout_mode_value = kRequestSignoutNoConfirmation;
- break;
- case SignoutMode::kShowSignoutConfirmation:
- signout_mode_value = kRequestSignoutShowConfirmation;
- break;
- }
- DCHECK(signout_mode_value);
+ const char* signout_mode_value =
+ (account_consistency_ == AccountConsistencyMethod::kDice)
+ ? kRequestSignoutShowConfirmation
+ : kRequestSignoutNoConfirmation;
parts.push_back(base::StringPrintf("signout_mode=%s", signout_mode_value));
return base::JoinString(parts, ",");
diff --git a/chromium/components/signin/core/browser/dice_header_helper.h b/chromium/components/signin/core/browser/dice_header_helper.h
index 3cd0b316515..e7b51f68b09 100644
--- a/chromium/components/signin/core/browser/dice_header_helper.h
+++ b/chromium/components/signin/core/browser/dice_header_helper.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/macros.h"
+#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/signin_header_helper.h"
class GURL;
@@ -20,15 +21,8 @@ extern const char kDiceProtocolVersion[];
// SigninHeaderHelper implementation managing the Dice header.
class DiceHeaderHelper : public SigninHeaderHelper {
public:
- // Signout mode for Gaia.
- enum class SignoutMode {
- // Gaia does not show a signout confirmation dialog.
- kNoSignoutConfirmation,
- // Gaia shows a signout confirmation dialog for the Sync account.
- kShowSignoutConfirmation
- };
-
- explicit DiceHeaderHelper(bool signed_in_with_auth_error);
+ explicit DiceHeaderHelper(bool signed_in_with_auth_error,
+ AccountConsistencyMethod account_consistency);
~DiceHeaderHelper() override {}
// Returns the parameters contained in the X-Chrome-ID-Consistency-Response
@@ -47,14 +41,14 @@ class DiceHeaderHelper : public SigninHeaderHelper {
// account.
// |show_signout_confirmation| is true if Gaia must display the signout
// confirmation dialog.
- std::string BuildRequestHeader(const std::string& sync_account_id,
- SignoutMode signout_mode);
+ std::string BuildRequestHeader(const std::string& sync_account_id);
private:
// SigninHeaderHelper implementation:
bool IsUrlEligibleForRequestHeader(const GURL& url) override;
bool signed_in_with_auth_error_;
+ AccountConsistencyMethod account_consistency_;
DISALLOW_COPY_AND_ASSIGN(DiceHeaderHelper);
};
diff --git a/chromium/components/signin/core/browser/fake_account_fetcher_service.cc b/chromium/components/signin/core/browser/fake_account_fetcher_service.cc
index 21eb31b63ec..bf1b4596007 100644
--- a/chromium/components/signin/core/browser/fake_account_fetcher_service.cc
+++ b/chromium/components/signin/core/browser/fake_account_fetcher_service.cc
@@ -7,6 +7,7 @@
#include "base/values.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "ui/gfx/image/image_unittest_util.h"
FakeAccountFetcherService::FakeAccountFetcherService() {}
@@ -46,3 +47,15 @@ void FakeAccountFetcherService::StartFetchingChildInfo(
const std::string& account_id) {
// In tests, don't do actual network fetch.
}
+
+TestImageDecoder::TestImageDecoder() = default;
+
+TestImageDecoder::~TestImageDecoder() = default;
+
+void TestImageDecoder::DecodeImage(
+ const std::string& image_data,
+ const gfx::Size& desired_image_frame_size,
+ const image_fetcher::ImageDecodedCallback& callback) {
+ callback.Run(image_data.empty() ? gfx::Image()
+ : gfx::test::CreateImage(64, 64));
+}
diff --git a/chromium/components/signin/core/browser/fake_account_fetcher_service.h b/chromium/components/signin/core/browser/fake_account_fetcher_service.h
index 84d67138b27..f9d8d158216 100644
--- a/chromium/components/signin/core/browser/fake_account_fetcher_service.h
+++ b/chromium/components/signin/core/browser/fake_account_fetcher_service.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/macros.h"
+#include "components/image_fetcher/core/image_decoder.h"
#include "components/signin/core/browser/account_fetcher_service.h"
class KeyedService;
@@ -44,4 +45,24 @@ class FakeAccountFetcherService : public AccountFetcherService {
DISALLOW_COPY_AND_ASSIGN(FakeAccountFetcherService);
};
+// This dummy class implements |image_fetcher::ImageDecoder|, and is passed
+// as an argument to |AccountFetcherService::Initialize|.
+class TestImageDecoder : public image_fetcher::ImageDecoder {
+ public:
+ TestImageDecoder();
+ ~TestImageDecoder() override;
+
+ // image_fetcher::Decoder implementation:
+
+ // If |image_data| is non-empty, a blank 64x64 image is passed to callback.
+ // Otherwise an empty image is passed.
+ void DecodeImage(
+ const std::string& image_data,
+ const gfx::Size& desired_image_frame_size,
+ const image_fetcher::ImageDecodedCallback& callback) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestImageDecoder);
+};
+
#endif // COMPONENTS_SIGNIN_CORE_BROWSER_FAKE_ACCOUNT_FETCHER_SERVICE_H_
diff --git a/chromium/components/signin/core/browser/fake_signin_manager.cc b/chromium/components/signin/core/browser/fake_signin_manager.cc
index 9a212146ea7..ab4c9747d9c 100644
--- a/chromium/components/signin/core/browser/fake_signin_manager.cc
+++ b/chromium/components/signin/core/browser/fake_signin_manager.cc
@@ -36,7 +36,8 @@ FakeSigninManager::FakeSigninManager(
token_service,
account_tracker_service,
cookie_manager_service,
- signin_error_controller),
+ signin_error_controller,
+ signin::AccountConsistencyMethod::kDisabled),
token_service_(token_service) {}
FakeSigninManager::~FakeSigninManager() {}
@@ -62,12 +63,7 @@ void FakeSigninManager::StartSignInWithRefreshToken(
void FakeSigninManager::CompletePendingSignin() {
SetAuthenticatedAccountId(GetAccountIdForAuthInProgress());
set_auth_in_progress(std::string());
- for (auto& observer : observer_list_) {
- observer.GoogleSigninSucceeded(authenticated_account_id_, username_);
- observer.GoogleSigninSucceeded(GetAuthenticatedAccountInfo());
- observer.GoogleSigninSucceededWithPassword(authenticated_account_id_,
- username_, password_);
- }
+ FireGoogleSigninSucceeded();
}
void FakeSigninManager::SignIn(const std::string& gaia_id,
@@ -104,10 +100,7 @@ void FakeSigninManager::DoSignOut(
if (token_service_ && remove_all_accounts)
token_service_->RevokeAllCredentials();
- for (auto& observer : observer_list_) {
- observer.GoogleSignedOut(account_id, username);
- observer.GoogleSignedOut(account_info);
- }
+ FireGoogleSignedOut(account_id, account_info);
}
#endif // !defined (OS_CHROMEOS)
diff --git a/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc b/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc
index ab43c8c09d4..68124de94a7 100644
--- a/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc
+++ b/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -342,14 +342,14 @@ GaiaCookieManagerService::~GaiaCookieManagerService() {
}
void GaiaCookieManagerService::Init() {
- cookie_changed_subscription_ = signin_client_->AddCookieChangedCallback(
+ cookie_change_subscription_ = signin_client_->AddCookieChangeCallback(
GaiaUrls::GetInstance()->google_url(), kGaiaCookieName,
- base::Bind(&GaiaCookieManagerService::OnCookieChanged,
- base::Unretained(this)));
+ base::BindRepeating(&GaiaCookieManagerService::OnCookieChange,
+ base::Unretained(this)));
}
void GaiaCookieManagerService::Shutdown() {
- cookie_changed_subscription_.reset();
+ cookie_change_subscription_.reset();
}
@@ -426,14 +426,14 @@ void GaiaCookieManagerService::TriggerListAccounts(const std::string& source) {
}
}
-void GaiaCookieManagerService::ForceOnCookieChangedProcessing() {
+void GaiaCookieManagerService::ForceOnCookieChangeProcessing() {
GURL google_url = GaiaUrls::GetInstance()->google_url();
std::unique_ptr<net::CanonicalCookie> cookie(
std::make_unique<net::CanonicalCookie>(
kGaiaCookieName, std::string(), "." + google_url.host(), "/",
base::Time(), base::Time(), base::Time(), false, false,
net::CookieSameSite::DEFAULT_MODE, net::COOKIE_PRIORITY_DEFAULT));
- OnCookieChanged(*cookie, net::CookieStore::ChangeCause::UNKNOWN_DELETION);
+ OnCookieChange(*cookie, net::CookieChangeCause::UNKNOWN_DELETION);
}
void GaiaCookieManagerService::LogOutAllAccounts(const std::string& source) {
@@ -523,9 +523,9 @@ std::string GaiaCookieManagerService::GetDefaultSourceForRequest() {
return source_;
}
-void GaiaCookieManagerService::OnCookieChanged(
+void GaiaCookieManagerService::OnCookieChange(
const net::CanonicalCookie& cookie,
- net::CookieStore::ChangeCause cause) {
+ net::CookieChangeCause cause) {
DCHECK_EQ(kGaiaCookieName, cookie.Name());
DCHECK(cookie.IsDomainMatch(GaiaUrls::GetInstance()->google_url().host()));
list_accounts_stale_ = true;
@@ -538,37 +538,25 @@ void GaiaCookieManagerService::OnCookieChanged(
// Build gaia "source" based on cause to help track down channel id issues.
std::string source(GetDefaultSourceForRequest());
switch (cause) {
- case net::CookieStore::ChangeCause::INSERTED:
+ case net::CookieChangeCause::INSERTED:
source += "INSERTED";
break;
- case net::CookieStore::ChangeCause::EXPLICIT:
+ case net::CookieChangeCause::EXPLICIT:
source += "EXPLICIT";
break;
- case net::CookieStore::ChangeCause::EXPLICIT_DELETE_BETWEEN:
- source += "EXPLICIT_DELETE_BETWEEN";
- break;
- case net::CookieStore::ChangeCause::EXPLICIT_DELETE_PREDICATE:
- source += "EXPLICIT_DELETE_PREDICATE";
- break;
- case net::CookieStore::ChangeCause::EXPLICIT_DELETE_SINGLE:
- source += "EXPLICIT_DELETE_SINGLE";
- break;
- case net::CookieStore::ChangeCause::EXPLICIT_DELETE_CANONICAL:
- source += "EXPLICIT_DELETE_CANONICAL";
- break;
- case net::CookieStore::ChangeCause::UNKNOWN_DELETION:
+ case net::CookieChangeCause::UNKNOWN_DELETION:
source += "UNKNOWN_DELETION";
break;
- case net::CookieStore::ChangeCause::OVERWRITE:
+ case net::CookieChangeCause::OVERWRITE:
source += "OVERWRITE";
break;
- case net::CookieStore::ChangeCause::EXPIRED:
+ case net::CookieChangeCause::EXPIRED:
source += "EXPIRED";
break;
- case net::CookieStore::ChangeCause::EVICTED:
+ case net::CookieChangeCause::EVICTED:
source += "EVICTED";
break;
- case net::CookieStore::ChangeCause::EXPIRED_OVERWRITE:
+ case net::CookieChangeCause::EXPIRED_OVERWRITE:
source += "EXPIRED_OVERWRITE";
break;
}
diff --git a/chromium/components/signin/core/browser/gaia_cookie_manager_service.h b/chromium/components/signin/core/browser/gaia_cookie_manager_service.h
index 9c8091e642d..d8c3cbc5e8b 100644
--- a/chromium/components/signin/core/browser/gaia_cookie_manager_service.h
+++ b/chromium/components/signin/core/browser/gaia_cookie_manager_service.h
@@ -194,10 +194,10 @@ class GaiaCookieManagerService : public KeyedService,
// that a check which GAIA should be done can force it.
void TriggerListAccounts(const std::string& source);
- // Forces the processing of OnCookieChanged. This is public so that callers
+ // Forces the processing of OnCookieChange. This is public so that callers
// that know the GAIA APISID cookie might have changed can inform the
// service. Virtual for testing.
- virtual void ForceOnCookieChangedProcessing();
+ virtual void ForceOnCookieChangeProcessing();
// Add or remove observers of this helper.
void AddObserver(Observer* observer);
@@ -248,8 +248,8 @@ class GaiaCookieManagerService : public KeyedService,
// Called when a cookie changes. If the cookie relates to a GAIA APISID
// cookie, then we call ListAccounts and fire OnGaiaAccountsInCookieUpdated.
- void OnCookieChanged(const net::CanonicalCookie& cookie,
- net::CookieStore::ChangeCause cause);
+ void OnCookieChange(const net::CanonicalCookie& cookie,
+ net::CookieChangeCause cause);
// Overridden from UbertokenConsumer.
void OnUbertokenSuccess(const std::string& token) override;
@@ -306,8 +306,8 @@ class GaiaCookieManagerService : public KeyedService,
std::string access_token_;
// Subscription to be called whenever the GAIA cookies change.
- std::unique_ptr<SigninClient::CookieChangedSubscription>
- cookie_changed_subscription_;
+ std::unique_ptr<SigninClient::CookieChangeSubscription>
+ cookie_change_subscription_;
// A worklist for this class. Stores any pending requests that couldn't be
// executed right away, since this class only permits one request to be
diff --git a/chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc b/chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
index ae0ad57ba59..63645420f9d 100644
--- a/chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
+++ b/chromium/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
@@ -657,7 +657,7 @@ TEST_F(GaiaCookieManagerServiceTest, ListAccountsAcceptsNull) {
ASSERT_EQ(1u, accounts.size());
}
-TEST_F(GaiaCookieManagerServiceTest, ListAccountsAfterOnCookieChanged) {
+TEST_F(GaiaCookieManagerServiceTest, ListAccountsAfterOnCookieChange) {
InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
MockObserver observer(&helper);
@@ -688,9 +688,9 @@ TEST_F(GaiaCookieManagerServiceTest, ListAccountsAfterOnCookieChanged) {
OnGaiaAccountsInCookieUpdated(
ListedAccountEquals(empty_list_accounts),
ListedAccountEquals(empty_signed_out_accounts), no_error()));
- helper.ForceOnCookieChangedProcessing();
+ helper.ForceOnCookieChangeProcessing();
- // OnCookieChanged should invalidate cached data.
+ // OnCookieChange should invalidate cached data.
ASSERT_FALSE(helper.ListAccounts(&list_accounts, &signed_out_accounts,
GaiaConstants::kChromeSource));
ASSERT_TRUE(list_accounts.empty());
diff --git a/chromium/components/signin/core/browser/profile_management_switches.cc b/chromium/components/signin/core/browser/profile_management_switches.cc
index 7cf6fc47fd6..851bf9f851b 100644
--- a/chromium/components/signin/core/browser/profile_management_switches.cc
+++ b/chromium/components/signin/core/browser/profile_management_switches.cc
@@ -38,7 +38,6 @@ bool IsDiceEnabledForPrefValue(bool dice_pref_value) {
case AccountConsistencyMethod::kMirror:
case AccountConsistencyMethod::kDiceFixAuthErrors:
case AccountConsistencyMethod::kDicePrepareMigration:
- case AccountConsistencyMethod::kDicePrepareMigrationChromeSyncEndpoint:
return false;
case AccountConsistencyMethod::kDice:
return true;
@@ -71,13 +70,17 @@ const char kAccountConsistencyFeatureMethodMirror[] = "mirror";
const char kAccountConsistencyFeatureMethodDiceFixAuthErrors[] =
"dice_fix_auth_errors";
const char kAccountConsistencyFeatureMethodDicePrepareMigration[] =
- "dice_prepare_migration";
-const char
- kAccountConsistencyFeatureMethodDicePrepareMigrationChromeSyncEndpoint[] =
- "dice_prepare_migration_new_endpoint";
+ "dice_prepare_migration_new_endpoint";
const char kAccountConsistencyFeatureMethodDiceMigration[] = "dice_migration";
const char kAccountConsistencyFeatureMethodDice[] = "dice";
+bool DiceMethodGreaterOrEqual(AccountConsistencyMethod a,
+ AccountConsistencyMethod b) {
+ DCHECK_NE(AccountConsistencyMethod::kMirror, a);
+ DCHECK_NE(AccountConsistencyMethod::kMirror, b);
+ return AccountConsistencyMethodGreaterOrEqual(a, b);
+}
+
void RegisterAccountConsistencyProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
#if defined(OS_CHROMEOS)
@@ -93,44 +96,38 @@ AccountConsistencyMethod GetAccountConsistencyMethod() {
#if BUILDFLAG(ENABLE_MIRROR)
// Mirror is always enabled on Android and iOS.
return AccountConsistencyMethod::kMirror;
-#else
+#endif
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
DCHECK(!GetIsGaiaIsolatedCallback()->is_null());
- if (!GetIsGaiaIsolatedCallback()->Run()) {
- // Because of limitations in base::Feature, always return kDisabled when
- // Gaia is not isolated, even though it's not technically a requirement for
- // all account consistency methods (i.e. kDiceFixAuthErrors could be
- // allowed).
- return AccountConsistencyMethod::kDisabled;
- }
-#endif // BUILDFLAG(ENABLE_DICE_SUPPORT)
+ const AccountConsistencyMethod kDefaultMethod =
+ AccountConsistencyMethod::kDiceFixAuthErrors;
+
+ if (!GetIsGaiaIsolatedCallback()->Run())
+ return kDefaultMethod;
+#else
+ const AccountConsistencyMethod kDefaultMethod =
+ AccountConsistencyMethod::kDisabled;
+#endif
if (!base::FeatureList::IsEnabled(kAccountConsistencyFeature))
- return AccountConsistencyMethod::kDisabled;
+ return kDefaultMethod;
std::string method_value = base::GetFieldTrialParamValueByFeature(
kAccountConsistencyFeature, kAccountConsistencyFeatureMethodParameter);
- if (method_value == kAccountConsistencyFeatureMethodMirror)
- return AccountConsistencyMethod::kMirror;
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
- else if (method_value == kAccountConsistencyFeatureMethodDiceFixAuthErrors)
+ if (method_value == kAccountConsistencyFeatureMethodDiceFixAuthErrors)
return AccountConsistencyMethod::kDiceFixAuthErrors;
else if (method_value == kAccountConsistencyFeatureMethodDicePrepareMigration)
return AccountConsistencyMethod::kDicePrepareMigration;
- else if (
- method_value ==
- kAccountConsistencyFeatureMethodDicePrepareMigrationChromeSyncEndpoint) {
- return AccountConsistencyMethod::kDicePrepareMigrationChromeSyncEndpoint;
- } else if (method_value == kAccountConsistencyFeatureMethodDiceMigration)
+ else if (method_value == kAccountConsistencyFeatureMethodDiceMigration)
return AccountConsistencyMethod::kDiceMigration;
else if (method_value == kAccountConsistencyFeatureMethodDice)
return AccountConsistencyMethod::kDice;
-#endif // BUILDFLAG(ENABLE_DICE_SUPPORT)
+ else if (method_value == kAccountConsistencyFeatureMethodMirror)
+ return AccountConsistencyMethod::kMirror;
- return AccountConsistencyMethod::kDisabled;
-#endif // BUILDFLAG(ENABLE_MIRROR)
+ return kDefaultMethod;
}
bool IsAccountConsistencyMirrorEnabled() {
@@ -143,12 +140,6 @@ bool IsDicePrepareMigrationEnabled() {
AccountConsistencyMethod::kDicePrepareMigration);
}
-bool IsDicePrepareMigrationChromeSyncEndpointEnabled() {
- return AccountConsistencyMethodGreaterOrEqual(
- GetAccountConsistencyMethod(),
- AccountConsistencyMethod::kDicePrepareMigrationChromeSyncEndpoint);
-}
-
bool IsDiceMigrationEnabled() {
return AccountConsistencyMethodGreaterOrEqual(
GetAccountConsistencyMethod(), AccountConsistencyMethod::kDiceMigration);
diff --git a/chromium/components/signin/core/browser/profile_management_switches.h b/chromium/components/signin/core/browser/profile_management_switches.h
index c4751fc77c7..330a1a37a13 100644
--- a/chromium/components/signin/core/browser/profile_management_switches.h
+++ b/chromium/components/signin/core/browser/profile_management_switches.h
@@ -34,8 +34,6 @@ extern const char kAccountConsistencyFeatureMethodParameter[];
extern const char kAccountConsistencyFeatureMethodMirror[];
extern const char kAccountConsistencyFeatureMethodDiceFixAuthErrors[];
extern const char kAccountConsistencyFeatureMethodDicePrepareMigration[];
-extern const char
- kAccountConsistencyFeatureMethodDicePrepareMigrationChromeSyncEndpoint[];
extern const char kAccountConsistencyFeatureMethodDiceMigration[];
extern const char kAccountConsistencyFeatureMethodDice[];
@@ -53,13 +51,9 @@ enum class AccountConsistencyMethod : int {
kDiceFixAuthErrors,
// Chrome uses the Dice signin flow and silently collects tokens associated
- // with Gaia cookies to prepare for the migration.
- kDicePrepareMigration,
-
- // Chrome uses the Dice signin flow and silently collects tokens associated
// with Gaia cookies to prepare for the migration. Uses the Chrome sync Gaia
// endpoint to enable sync.
- kDicePrepareMigrationChromeSyncEndpoint,
+ kDicePrepareMigration,
// Account management UI on Gaia webpages is enabled once the accounts become
// consistent.
@@ -71,9 +65,17 @@ enum class AccountConsistencyMethod : int {
kDice
};
+// Returns true if the |a| comes after |b| in the AccountConsistencyMethod enum.
+// Should not be used for Mirror.
+bool DiceMethodGreaterOrEqual(AccountConsistencyMethod a,
+ AccountConsistencyMethod b);
+
////////////////////////////////////////////////////////////////////////////////
// AccountConsistencyMethod related functions:
+// WARNING: DEPRECATED. These methods are global, but account consistency is per
+// profile.
+
// Returns the account consistency method.
AccountConsistencyMethod GetAccountConsistencyMethod();
@@ -85,13 +87,9 @@ bool IsAccountConsistencyMirrorEnabled();
// greater.
bool IsDiceFixAuthErrorsEnabled();
-// Returns true if the account consistency method is kDicePrepareMigration or
-// greater.
-bool IsDicePrepareMigrationEnabled();
-
// Returns true if the account consistency method is
-// kDicePrepareMigrationChromeSyncEndpoint or greater.
-bool IsDicePrepareMigrationChromeSyncEndpointEnabled();
+// kDicePrepareMigration or greater.
+bool IsDicePrepareMigrationEnabled();
// Returns true if Dice account consistency is enabled or if the Dice migration
// process is in progress (account consistency method is kDice or
diff --git a/chromium/components/signin/core/browser/profile_management_switches_unittest.cc b/chromium/components/signin/core/browser/profile_management_switches_unittest.cc
index bc1f10317fa..8aa9c2b2907 100644
--- a/chromium/components/signin/core/browser/profile_management_switches_unittest.cc
+++ b/chromium/components/signin/core/browser/profile_management_switches_unittest.cc
@@ -37,8 +37,19 @@ TEST(ProfileManagementSwitchesTest, GetAccountConsistencyMethod) {
std::unique_ptr<BooleanPrefMember> dice_pref_member =
CreateDicePrefMember(&pref_service);
- // By default account consistency is disabled.
+// Check the default account consistency method.
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+ EXPECT_EQ(AccountConsistencyMethod::kDiceFixAuthErrors,
+ GetAccountConsistencyMethod());
+#else
EXPECT_EQ(AccountConsistencyMethod::kDisabled, GetAccountConsistencyMethod());
+ EXPECT_FALSE(IsAccountConsistencyMirrorEnabled());
+ EXPECT_FALSE(IsDiceFixAuthErrorsEnabled());
+ EXPECT_FALSE(IsDiceMigrationEnabled());
+ EXPECT_FALSE(IsDicePrepareMigrationEnabled());
+ EXPECT_FALSE(IsDiceEnabledForProfile(&pref_service));
+ EXPECT_FALSE(IsDiceEnabled(dice_pref_member.get()));
+#endif
struct TestCase {
AccountConsistencyMethod method;
@@ -49,15 +60,11 @@ TEST(ProfileManagementSwitchesTest, GetAccountConsistencyMethod) {
bool expect_dice_migration;
bool expect_dice_enabled_for_profile;
} test_cases[] = {
- {AccountConsistencyMethod::kDisabled, false, false, false, false, false,
- false},
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
{AccountConsistencyMethod::kDiceFixAuthErrors, false, true, false, false,
false, false},
- {AccountConsistencyMethod::kDicePrepareMigration, false, true, true, false,
+ {AccountConsistencyMethod::kDicePrepareMigration, false, true, true, true,
false, false},
- {AccountConsistencyMethod::kDicePrepareMigrationChromeSyncEndpoint, false,
- true, true, true, false, false},
{AccountConsistencyMethod::kDiceMigration, false, true, true, true, true,
false},
{AccountConsistencyMethod::kDice, false, true, true, true, true, true},
@@ -73,10 +80,8 @@ TEST(ProfileManagementSwitchesTest, GetAccountConsistencyMethod) {
EXPECT_EQ(test_case.expect_dice_fix_auth_errors,
IsDiceFixAuthErrorsEnabled());
EXPECT_EQ(test_case.expect_dice_migration, IsDiceMigrationEnabled());
- EXPECT_EQ(test_case.expect_dice_prepare_migration,
- IsDicePrepareMigrationEnabled());
EXPECT_EQ(test_case.expect_dice_prepare_migration_new_endpoint,
- IsDicePrepareMigrationChromeSyncEndpointEnabled());
+ IsDicePrepareMigrationEnabled());
EXPECT_EQ(test_case.expect_dice_enabled_for_profile,
IsDiceEnabledForProfile(&pref_service));
EXPECT_EQ(test_case.expect_dice_enabled_for_profile,
@@ -100,15 +105,11 @@ TEST(ProfileManagementSwitchesTest, DiceMigration) {
struct TestCase {
AccountConsistencyMethod method;
bool expect_dice_enabled_for_profile;
- } test_cases[] = {
- {AccountConsistencyMethod::kDisabled, false},
- {AccountConsistencyMethod::kDiceFixAuthErrors, false},
- {AccountConsistencyMethod::kDicePrepareMigration, false},
- {AccountConsistencyMethod::kDicePrepareMigrationChromeSyncEndpoint,
- false},
- {AccountConsistencyMethod::kDiceMigration, true},
- {AccountConsistencyMethod::kDice, true},
- {AccountConsistencyMethod::kMirror, false}};
+ } test_cases[] = {{AccountConsistencyMethod::kDiceFixAuthErrors, false},
+ {AccountConsistencyMethod::kDicePrepareMigration, false},
+ {AccountConsistencyMethod::kDiceMigration, true},
+ {AccountConsistencyMethod::kDice, true},
+ {AccountConsistencyMethod::kMirror, false}};
for (const TestCase& test_case : test_cases) {
ScopedAccountConsistency scoped_method(test_case.method);
diff --git a/chromium/components/signin/core/browser/resources/signin_index.css b/chromium/components/signin/core/browser/resources/signin_index.css
index 34531a7ceac..ebcc78732f1 100644
--- a/chromium/components/signin/core/browser/resources/signin_index.css
+++ b/chromium/components/signin/core/browser/resources/signin_index.css
@@ -76,13 +76,3 @@ tr[highlighted]:nth-child(odd) {
-webkit-animation-name: highlight2;
-webkit-animation-timing-function: linear;
}
-
-paper-button.dice-primary-action {
- --paper-button-flat-keyboard-focus: {
- background: rgb(58, 117, 215);
- font-weight: 500;
- margin-top: 20;
- };
- background: var(--google-blue-500);
- color: white;
-}
diff --git a/chromium/components/signin/core/browser/resources/signin_index.html b/chromium/components/signin/core/browser/resources/signin_index.html
index 4bc9c10d3d6..ae197e87986 100644
--- a/chromium/components/signin/core/browser/resources/signin_index.html
+++ b/chromium/components/signin/core/browser/resources/signin_index.html
@@ -2,12 +2,6 @@
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
- <if expr="not is_android and not is_ios">
- <link rel="import" href="chrome://resources/html/polymer.html">
- <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
- <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
- </if>
- <title>Signin Internals</title>
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/util.js"></script>
<script src="chrome://resources/js/load_time_data.js"></script>
@@ -95,17 +89,6 @@
</table>
</div>
</div>
- <div id="diceSection" hidden="true">
- <h2>Desktop Identity Consistency</h2>
- <div class="action-container">
- <paper-button class="dice-primary-action" id="enableSyncButton">
- Enable Sync
- </paper-button>
- <paper-button class="dice-primary-action" id="disableSyncButton">
- Disable Sync
- </paper-button>
- </div>
- </div>
<script src="chrome://resources/js/i18n_template.js"></script>
<script src="chrome://resources/js/jstemplate_compiled.js"></script>
<script src="chrome://signin-internals/signin_internals.js"></script>
diff --git a/chromium/components/signin/core/browser/resources/signin_internals.js b/chromium/components/signin/core/browser/resources/signin_internals.js
index 38b02a33fa7..5ac1b25eeb8 100644
--- a/chromium/components/signin/core/browser/resources/signin_internals.js
+++ b/chromium/components/signin/core/browser/resources/signin_internals.js
@@ -161,42 +161,6 @@ for (var i = 0; i < signinFunctions.length; ++i) {
chrome.signin[signinFunction] = makeSigninFunction(signinFunction);
}
-cr.define('chrome.signin.dice', function() {
- 'use strict';
-
- function initialize() {
- $('enableSyncButton').addEventListener('click', function(e) {
- chrome.send("enableSync");
- });
- $('disableSyncButton').addEventListener('click', function(e) {
- chrome.send("disableSync");
- });
- }
-
- function refreshUI(signinInfo) {
- var diceInfo = signinInfo.dice;
-
- if (diceInfo == undefined) {
- $('diceSection').hidden = true;
- return;
- }
-
- $('diceSection').hidden = false;
- if (diceInfo.isSignedIn) {
- $('enableSyncButton').hidden = true;
- $('disableSyncButton').hidden = false;
- } else {
- $('disableSyncButton').hidden = true;
- $('enableSyncButton').hidden = false;
- }
- }
-
- return {
- initialize: initialize,
- refreshUI: refreshUI,
- };
-});
-
chrome.signin.internalsInfo = {};
// Replace the displayed values with the latest fetched ones.
@@ -205,9 +169,6 @@ function refreshSigninInfo(signinInfo) {
jstProcess(new JsEvalContext(signinInfo), $('signin-info'));
jstProcess(new JsEvalContext(signinInfo), $('token-info'));
jstProcess(new JsEvalContext(signinInfo), $('account-info'));
-
- // Refresh the DICE section if needed.
- chrome.signin.dice.refreshUI(signinInfo);
}
// Replace the cookie information with the fetched values.
@@ -222,7 +183,6 @@ function onLoad() {
chrome.signin.onSigninInfoChanged.addListener(refreshSigninInfo);
chrome.signin.onCookieAccountsFetched.addListener(updateCookieAccounts);
- chrome.signin.dice.initialize();
}
document.addEventListener('DOMContentLoaded', onLoad, false);
diff --git a/chromium/components/signin/core/browser/scoped_account_consistency.cc b/chromium/components/signin/core/browser/scoped_account_consistency.cc
index 6d111d09501..952a08f0188 100644
--- a/chromium/components/signin/core/browser/scoped_account_consistency.cc
+++ b/chromium/components/signin/core/browser/scoped_account_consistency.cc
@@ -18,6 +18,7 @@ namespace signin {
ScopedAccountConsistency::ScopedAccountConsistency(
AccountConsistencyMethod method) {
+ DCHECK_NE(AccountConsistencyMethod::kDisabled, method);
#if !BUILDFLAG(ENABLE_DICE_SUPPORT)
DCHECK_NE(AccountConsistencyMethod::kDice, method);
DCHECK_NE(AccountConsistencyMethod::kDiceFixAuthErrors, method);
@@ -30,12 +31,6 @@ ScopedAccountConsistency::ScopedAccountConsistency(
signin::SetGaiaOriginIsolatedCallback(base::Bind([] { return true; }));
- if (method == AccountConsistencyMethod::kDisabled) {
- scoped_feature_list_.InitAndDisableFeature(kAccountConsistencyFeature);
- DCHECK_EQ(method, GetAccountConsistencyMethod());
- return;
- }
-
// Set up the account consistency method.
std::string feature_value;
switch (method) {
@@ -51,10 +46,6 @@ ScopedAccountConsistency::ScopedAccountConsistency(
case AccountConsistencyMethod::kDicePrepareMigration:
feature_value = kAccountConsistencyFeatureMethodDicePrepareMigration;
break;
- case AccountConsistencyMethod::kDicePrepareMigrationChromeSyncEndpoint:
- feature_value =
- kAccountConsistencyFeatureMethodDicePrepareMigrationChromeSyncEndpoint;
- break;
case AccountConsistencyMethod::kDiceMigration:
feature_value = kAccountConsistencyFeatureMethodDiceMigration;
break;
diff --git a/chromium/components/signin/core/browser/scoped_account_consistency.h b/chromium/components/signin/core/browser/scoped_account_consistency.h
index 5fa97733fd5..0b9db2fd696 100644
--- a/chromium/components/signin/core/browser/scoped_account_consistency.h
+++ b/chromium/components/signin/core/browser/scoped_account_consistency.h
@@ -40,8 +40,6 @@ class ScopedAccountConsistency {
DISALLOW_COPY_AND_ASSIGN(ScopedAccountConsistency##method); \
}
-// ScopedAccountConsistencyDisabled:
-SCOPED_ACCOUNT_CONSISTENCY_SPECIALIZATION(Disabled);
// ScopedAccountConsistencyMirror:
SCOPED_ACCOUNT_CONSISTENCY_SPECIALIZATION(Mirror);
// ScopedAccountConsistencyDiceFixAuthErrors:
diff --git a/chromium/components/signin/core/browser/signin_client.h b/chromium/components/signin/core/browser/signin_client.h
index 0589e6efc84..eba0efb418d 100644
--- a/chromium/components/signin/core/browser/signin_client.h
+++ b/chromium/components/signin/core/browser/signin_client.h
@@ -16,7 +16,7 @@
#include "components/signin/core/browser/signin_metrics.h"
#include "components/signin/core/browser/webdata/token_web_data.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
-#include "net/cookies/cookie_store.h"
+#include "net/cookies/cookie_change_dispatcher.h"
#include "url/gurl.h"
class PrefService;
@@ -35,12 +35,12 @@ class URLRequestContextGetter;
class SigninClient : public KeyedService {
public:
// The subcription for cookie changed notifications.
- class CookieChangedSubscription {
+ class CookieChangeSubscription {
public:
- virtual ~CookieChangedSubscription() {}
+ virtual ~CookieChangeSubscription() = default;
};
- ~SigninClient() override {}
+ ~SigninClient() override = default;
// If |for_ephemeral| is true, special kind of device ID for ephemeral users
// is generated.
@@ -83,11 +83,11 @@ class SigninClient : public KeyedService {
// Adds a callback to be called each time a cookie for |url| with name |name|
// changes.
// Note that |callback| will always be called on the thread that
- // |AddCookieChangedCallback| was called on.
- virtual std::unique_ptr<CookieChangedSubscription> AddCookieChangedCallback(
+ // |AddCookieChangeCallback| was called on.
+ virtual std::unique_ptr<CookieChangeSubscription> AddCookieChangeCallback(
const GURL& url,
const std::string& name,
- const net::CookieStore::CookieChangedCallback& callback) = 0;
+ net::CookieChangeCallback callback) = 0;
// Called after Google signin has succeeded.
virtual void OnSignedIn(const std::string& account_id,
diff --git a/chromium/components/signin/core/browser/signin_cookie_change_subscription.cc b/chromium/components/signin/core/browser/signin_cookie_change_subscription.cc
new file mode 100644
index 00000000000..8a38880d1bd
--- /dev/null
+++ b/chromium/components/signin/core/browser/signin_cookie_change_subscription.cc
@@ -0,0 +1,104 @@
+// 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/signin/core/browser/signin_cookie_change_subscription.h"
+
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "net/cookies/cookie_change_dispatcher.h"
+#include "net/cookies/cookie_store.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
+
+SigninCookieChangeSubscription::SubscriptionHolder::SubscriptionHolder() =
+ default;
+
+SigninCookieChangeSubscription::SubscriptionHolder::~SubscriptionHolder() =
+ default;
+
+SigninCookieChangeSubscription::SigninCookieChangeSubscription(
+ scoped_refptr<net::URLRequestContextGetter> context_getter,
+ const GURL& url,
+ const std::string& name,
+ net::CookieChangeCallback callback)
+ : context_getter_(std::move(context_getter)),
+ subscription_holder_io_(std::make_unique<SubscriptionHolder>()),
+ callback_(std::move(callback)) {
+ RegisterForCookieChangeNotifications(url, name);
+}
+
+SigninCookieChangeSubscription::~SigninCookieChangeSubscription() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ scoped_refptr<base::SingleThreadTaskRunner> network_task_runner =
+ context_getter_->GetNetworkTaskRunner();
+ if (network_task_runner->BelongsToCurrentThread()) {
+ subscription_holder_io_.reset();
+ } else {
+ network_task_runner->DeleteSoon(FROM_HERE,
+ subscription_holder_io_.release());
+ }
+}
+
+void SigninCookieChangeSubscription::RegisterForCookieChangeNotifications(
+ const GURL& url,
+ const std::string& name) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ // The cookie store can only be accessed from the context getter which lives
+ // on the network thread. As |AddCookieChangeCallback| is called from the
+ // main thread, a thread jump is needed to register for cookie changed
+ // notifications.
+ net::CookieChangeCallback run_on_current_thread_callback =
+ base::BindRepeating(
+ &SigninCookieChangeSubscription::RunAsyncOnCookieChange,
+ base::ThreadTaskRunnerHandle::Get(), this->AsWeakPtr());
+ base::OnceClosure register_closure =
+ base::BindOnce(&RegisterForCookieChangesOnIOThread, context_getter_, url,
+ name, std::move(run_on_current_thread_callback),
+ base::Unretained(subscription_holder_io_.get()));
+ scoped_refptr<base::SingleThreadTaskRunner> network_task_runner =
+ context_getter_->GetNetworkTaskRunner();
+ if (network_task_runner->BelongsToCurrentThread()) {
+ std::move(register_closure).Run();
+ } else {
+ network_task_runner->PostTask(FROM_HERE, std::move(register_closure));
+ }
+}
+
+// static
+void SigninCookieChangeSubscription::RegisterForCookieChangesOnIOThread(
+ scoped_refptr<net::URLRequestContextGetter> context_getter,
+ const GURL url,
+ const std::string name,
+ net::CookieChangeCallback callback,
+ SigninCookieChangeSubscription::SubscriptionHolder*
+ out_subscription_holder) {
+ DCHECK(out_subscription_holder);
+ net::CookieStore* cookie_store =
+ context_getter->GetURLRequestContext()->cookie_store();
+ DCHECK(cookie_store);
+ out_subscription_holder->subscription =
+ cookie_store->GetChangeDispatcher().AddCallbackForCookie(
+ url, name, std::move(callback));
+}
+
+// static
+void SigninCookieChangeSubscription::RunAsyncOnCookieChange(
+ scoped_refptr<base::TaskRunner> proxy,
+ base::WeakPtr<SigninCookieChangeSubscription> subscription,
+ const net::CanonicalCookie& cookie,
+ net::CookieChangeCause cause) {
+ proxy->PostTask(
+ FROM_HERE, base::BindOnce(&SigninCookieChangeSubscription::OnCookieChange,
+ subscription, cookie, cause));
+}
+
+void SigninCookieChangeSubscription::OnCookieChange(
+ const net::CanonicalCookie& cookie,
+ net::CookieChangeCause cause) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (!callback_.is_null()) {
+ callback_.Run(cookie, cause);
+ }
+}
diff --git a/chromium/components/signin/core/browser/signin_cookie_changed_subscription.h b/chromium/components/signin/core/browser/signin_cookie_change_subscription.h
index d1569863c22..8b4ac3767f5 100644
--- a/chromium/components/signin/core/browser/signin_cookie_changed_subscription.h
+++ b/chromium/components/signin/core/browser/signin_cookie_change_subscription.h
@@ -2,34 +2,38 @@
// 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_SIGNIN_COOKIE_CHANGED_SUBSCRIPTION_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_COOKIE_CHANGED_SUBSCRIPTION_H_
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_COOKIE_CHANGE_SUBSCRIPTION_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_COOKIE_CHANGE_SUBSCRIPTION_H_
+
+#include <memory>
+#include <string>
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "components/signin/core/browser/signin_client.h"
+#include "net/cookies/cookie_change_dispatcher.h"
#include "net/url_request/url_request_context_getter.h"
-// The subscription for a cookie changed events. This class lives on the
-// main thread.
-class SigninCookieChangedSubscription
- : public SigninClient::CookieChangedSubscription,
- public base::SupportsWeakPtr<SigninCookieChangedSubscription> {
+// The subscription for cookie changes. This class lives on the main thread.
+class SigninCookieChangeSubscription
+ : public SigninClient::CookieChangeSubscription,
+ public base::SupportsWeakPtr<SigninCookieChangeSubscription> {
public:
- // Creates a cookie changed subscription and registers for cookie changed
+ // Creates a cookie change subscription and registers for cookie changed
// events.
- SigninCookieChangedSubscription(
+ SigninCookieChangeSubscription(
scoped_refptr<net::URLRequestContextGetter> context_getter,
const GURL& url,
const std::string& name,
- const net::CookieStore::CookieChangedCallback& callback);
- ~SigninCookieChangedSubscription() override;
+ net::CookieChangeCallback callback);
+ ~SigninCookieChangeSubscription() override;
private:
// Holder of a cookie store cookie changed subscription.
struct SubscriptionHolder {
- std::unique_ptr<net::CookieStore::CookieChangedSubscription> subscription;
+ std::unique_ptr<net::CookieChangeSubscription> subscription;
SubscriptionHolder();
~SubscriptionHolder();
};
@@ -40,26 +44,26 @@ class SigninCookieChangedSubscription
scoped_refptr<net::URLRequestContextGetter> context_getter,
const GURL url,
const std::string name,
- const net::CookieStore::CookieChangedCallback callback,
- SigninCookieChangedSubscription::SubscriptionHolder*
+ net::CookieChangeCallback callback,
+ SigninCookieChangeSubscription::SubscriptionHolder*
out_subscription_holder);
- void RegisterForCookieChangedNotifications(const GURL& url,
- const std::string& name);
+ void RegisterForCookieChangeNotifications(const GURL& url,
+ const std::string& name);
- // Posts a task on the |proxy| task runner that calls |OnCookieChanged| on
+ // Posts a task on the |proxy| task runner that calls |OnCookieChange| on
// |subscription|.
// Note that this method is called on the network thread, so |subscription|
// must not be used here, it is only passed around.
- static void RunAsyncOnCookieChanged(
+ static void RunAsyncOnCookieChange(
scoped_refptr<base::TaskRunner> proxy,
- base::WeakPtr<SigninCookieChangedSubscription> subscription,
+ base::WeakPtr<SigninCookieChangeSubscription> subscription,
const net::CanonicalCookie& cookie,
- net::CookieStore::ChangeCause cause);
+ net::CookieChangeCause cause);
- // Handler for cookie changed events.
- void OnCookieChanged(const net::CanonicalCookie& cookie,
- net::CookieStore::ChangeCause cause);
+ // Handler for cookie change events.
+ void OnCookieChange(const net::CanonicalCookie& cookie,
+ net::CookieChangeCause cause);
// The context getter.
scoped_refptr<net::URLRequestContextGetter> context_getter_;
@@ -69,11 +73,11 @@ class SigninCookieChangedSubscription
std::unique_ptr<SubscriptionHolder> subscription_holder_io_;
// Callback to be run on cookie changed events.
- net::CookieStore::CookieChangedCallback callback_;
+ net::CookieChangeCallback callback_;
- base::ThreadChecker thread_checker_;
+ THREAD_CHECKER(thread_checker_);
- DISALLOW_COPY_AND_ASSIGN(SigninCookieChangedSubscription);
+ DISALLOW_COPY_AND_ASSIGN(SigninCookieChangeSubscription);
};
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_COOKIE_CHANGED_SUBSCRIPTION_H_
+#endif // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_COOKIE_CHANGE_SUBSCRIPTION_H_
diff --git a/chromium/components/signin/core/browser/signin_cookie_changed_subscription.cc b/chromium/components/signin/core/browser/signin_cookie_changed_subscription.cc
deleted file mode 100644
index f32bd19b083..00000000000
--- a/chromium/components/signin/core/browser/signin_cookie_changed_subscription.cc
+++ /dev/null
@@ -1,104 +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/signin/core/browser/signin_cookie_changed_subscription.h"
-
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "net/cookies/cookie_store.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-
-SigninCookieChangedSubscription::SubscriptionHolder::SubscriptionHolder() {
-}
-
-SigninCookieChangedSubscription::SubscriptionHolder::~SubscriptionHolder() {
-}
-
-SigninCookieChangedSubscription::SigninCookieChangedSubscription(
- scoped_refptr<net::URLRequestContextGetter> context_getter,
- const GURL& url,
- const std::string& name,
- const net::CookieStore::CookieChangedCallback& callback)
- : context_getter_(context_getter),
- subscription_holder_io_(new SubscriptionHolder),
- callback_(callback) {
- RegisterForCookieChangedNotifications(url, name);
-}
-
-SigninCookieChangedSubscription::~SigninCookieChangedSubscription() {
- DCHECK(thread_checker_.CalledOnValidThread());
- scoped_refptr<base::SingleThreadTaskRunner> network_task_runner =
- context_getter_->GetNetworkTaskRunner();
- if (network_task_runner->BelongsToCurrentThread()) {
- subscription_holder_io_.reset();
- } else {
- network_task_runner->DeleteSoon(FROM_HERE,
- subscription_holder_io_.release());
- }
-}
-
-void SigninCookieChangedSubscription::RegisterForCookieChangedNotifications(
- const GURL& url,
- const std::string& name) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // The cookie store can only be accessed from the context getter which lives
- // on the network thread. As |AddCookieChangedCallback| is called from the
- // main thread, a thread jump is needed to register for cookie changed
- // notifications.
- net::CookieStore::CookieChangedCallback run_on_current_thread_callback =
- base::Bind(&SigninCookieChangedSubscription::RunAsyncOnCookieChanged,
- base::ThreadTaskRunnerHandle::Get(), this->AsWeakPtr());
- base::Closure register_closure =
- base::Bind(&RegisterForCookieChangesOnIOThread,
- context_getter_,
- url,
- name,
- run_on_current_thread_callback,
- base::Unretained(subscription_holder_io_.get()));
- scoped_refptr<base::SingleThreadTaskRunner> network_task_runner =
- context_getter_->GetNetworkTaskRunner();
- if (network_task_runner->BelongsToCurrentThread()) {
- register_closure.Run();
- } else {
- network_task_runner->PostTask(FROM_HERE, register_closure);
- }
-}
-
-// static
-void SigninCookieChangedSubscription::RegisterForCookieChangesOnIOThread(
- scoped_refptr<net::URLRequestContextGetter> context_getter,
- const GURL url,
- const std::string name,
- const net::CookieStore::CookieChangedCallback callback,
- SigninCookieChangedSubscription::SubscriptionHolder*
- out_subscription_holder) {
- DCHECK(out_subscription_holder);
- net::CookieStore* cookie_store =
- context_getter->GetURLRequestContext()->cookie_store();
- DCHECK(cookie_store);
- out_subscription_holder->subscription =
- cookie_store->AddCallbackForCookie(url, name, callback);
-}
-
-// static
-void SigninCookieChangedSubscription::RunAsyncOnCookieChanged(
- scoped_refptr<base::TaskRunner> proxy,
- base::WeakPtr<SigninCookieChangedSubscription> subscription,
- const net::CanonicalCookie& cookie,
- net::CookieStore::ChangeCause cause) {
- proxy->PostTask(FROM_HERE,
- base::Bind(&SigninCookieChangedSubscription::OnCookieChanged,
- subscription, cookie, cause));
-}
-
-void SigninCookieChangedSubscription::OnCookieChanged(
- const net::CanonicalCookie& cookie,
- net::CookieStore::ChangeCause cause) {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!callback_.is_null()) {
- callback_.Run(cookie, cause);
- }
-}
diff --git a/chromium/components/signin/core/browser/signin_header_helper.cc b/chromium/components/signin/core/browser/signin_header_helper.cc
index f889e633bc6..6c5a0eca4aa 100644
--- a/chromium/components/signin/core/browser/signin_header_helper.cc
+++ b/chromium/components/signin/core/browser/signin_header_helper.cc
@@ -12,7 +12,6 @@
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/google/core/browser/google_util.h"
#include "components/signin/core/browser/chrome_connected_header_helper.h"
-#include "components/signin/core/browser/profile_management_switches.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/base/escape.h"
@@ -79,10 +78,11 @@ bool SettingsAllowSigninCookies(
std::string BuildMirrorRequestCookieIfPossible(
const GURL& url,
const std::string& account_id,
+ AccountConsistencyMethod account_consistency,
const content_settings::CookieSettings* cookie_settings,
int profile_mode_mask) {
- return signin::ChromeConnectedHeaderHelper::BuildRequestCookieIfPossible(
- url, account_id, cookie_settings, profile_mode_mask);
+ return ChromeConnectedHeaderHelper::BuildRequestCookieIfPossible(
+ url, account_id, account_consistency, cookie_settings, profile_mode_mask);
}
bool SigninHeaderHelper::AppendOrRemoveRequestHeader(
@@ -147,11 +147,11 @@ void AppendOrRemoveMirrorRequestHeader(
net::URLRequest* request,
const GURL& redirect_url,
const std::string& account_id,
+ AccountConsistencyMethod account_consistency,
const content_settings::CookieSettings* cookie_settings,
- bool is_mirror_enabled,
int profile_mode_mask) {
const GURL& url = redirect_url.is_empty() ? request->url() : redirect_url;
- ChromeConnectedHeaderHelper chrome_connected_helper(is_mirror_enabled);
+ ChromeConnectedHeaderHelper chrome_connected_helper(account_consistency);
std::string chrome_connected_header_value;
if (chrome_connected_helper.ShouldBuildRequestHeader(url, cookie_settings)) {
chrome_connected_header_value = chrome_connected_helper.BuildRequestHeader(
@@ -168,20 +168,17 @@ bool AppendOrRemoveDiceRequestHeader(
const std::string& account_id,
bool sync_enabled,
bool sync_has_auth_error,
- BooleanPrefMember* dice_pref_member,
+ AccountConsistencyMethod account_consistency,
const content_settings::CookieSettings* cookie_settings) {
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
const GURL& url = redirect_url.is_empty() ? request->url() : redirect_url;
- DiceHeaderHelper dice_helper(!account_id.empty() && sync_has_auth_error &&
- sync_enabled);
+ DiceHeaderHelper dice_helper(
+ !account_id.empty() && sync_has_auth_error && sync_enabled,
+ account_consistency);
std::string dice_header_value;
if (dice_helper.ShouldBuildRequestHeader(url, cookie_settings)) {
- DiceHeaderHelper::SignoutMode signout_mode =
- IsDiceEnabled(dice_pref_member)
- ? DiceHeaderHelper::SignoutMode::kShowSignoutConfirmation
- : DiceHeaderHelper::SignoutMode::kNoSignoutConfirmation;
dice_header_value = dice_helper.BuildRequestHeader(
- sync_enabled ? account_id : std::string(), signout_mode);
+ sync_enabled ? account_id : std::string());
}
return dice_helper.AppendOrRemoveRequestHeader(
request, redirect_url, kDiceRequestHeader, dice_header_value);
diff --git a/chromium/components/signin/core/browser/signin_header_helper.h b/chromium/components/signin/core/browser/signin_header_helper.h
index 4eef05ded11..2d0f0b2ae49 100644
--- a/chromium/components/signin/core/browser/signin_header_helper.h
+++ b/chromium/components/signin/core/browser/signin_header_helper.h
@@ -10,6 +10,7 @@
#include <vector>
#include "components/prefs/pref_member.h"
+#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/signin_features.h"
#include "url/gurl.h"
@@ -186,6 +187,7 @@ bool SettingsAllowSigninCookies(
std::string BuildMirrorRequestCookieIfPossible(
const GURL& url,
const std::string& account_id,
+ AccountConsistencyMethod account_consistency,
const content_settings::CookieSettings* cookie_settings,
int profile_mode_mask);
@@ -196,8 +198,8 @@ void AppendOrRemoveMirrorRequestHeader(
net::URLRequest* request,
const GURL& redirect_url,
const std::string& account_id,
+ AccountConsistencyMethod account_consistency,
const content_settings::CookieSettings* cookie_settings,
- bool is_mirror_enabled,
int profile_mode_mask);
// Adds the Dice to all Gaia requests from a connected profile, with the
@@ -210,7 +212,7 @@ bool AppendOrRemoveDiceRequestHeader(
const std::string& account_id,
bool sync_enabled,
bool sync_has_auth_error,
- BooleanPrefMember* dice_pref_member,
+ AccountConsistencyMethod account_consistency,
const content_settings::CookieSettings* cookie_settings);
// Returns the parameters contained in the X-Chrome-Manage-Accounts response
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 fc8db3fbbb6..9056b83e57f 100644
--- a/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -14,7 +14,6 @@
#include "components/prefs/pref_member.h"
#include "components/signin/core/browser/chrome_connected_header_helper.h"
#include "components/signin/core/browser/profile_management_switches.h"
-#include "components/signin/core/browser/scoped_account_consistency.h"
#include "components/signin/core/browser/signin_features.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "google_apis/gaia/gaia_urls.h"
@@ -34,14 +33,12 @@ class SigninHeaderHelperTest : public testing::Test {
void SetUp() override {
content_settings::CookieSettings::RegisterProfilePrefs(prefs_.registry());
HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
- signin::RegisterAccountConsistencyProfilePrefs(prefs_.registry());
settings_map_ = new HostContentSettingsMap(
&prefs_, false /* incognito_profile */, false /* guest_profile */,
false /* store_last_modified */);
cookie_settings_ =
new content_settings::CookieSettings(settings_map_.get(), &prefs_, "");
- dice_enabled_pref_member_ = signin::CreateDicePrefMember(&prefs_);
}
void TearDown() override { settings_map_->ShutdownOnUIThread(); }
@@ -49,10 +46,10 @@ class SigninHeaderHelperTest : public testing::Test {
void CheckMirrorCookieRequest(const GURL& url,
const std::string& account_id,
const std::string& expected_request) {
- EXPECT_EQ(
- BuildMirrorRequestCookieIfPossible(
- url, account_id, cookie_settings_.get(), PROFILE_MODE_DEFAULT),
- expected_request);
+ EXPECT_EQ(BuildMirrorRequestCookieIfPossible(
+ url, account_id, account_consistency_, cookie_settings_.get(),
+ PROFILE_MODE_DEFAULT),
+ expected_request);
}
std::unique_ptr<net::URLRequest> CreateRequest(
@@ -62,12 +59,11 @@ class SigninHeaderHelperTest : public testing::Test {
url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr,
TRAFFIC_ANNOTATION_FOR_TESTS);
AppendOrRemoveMirrorRequestHeader(
- url_request.get(), GURL(), account_id, cookie_settings_.get(),
- IsAccountConsistencyMirrorEnabled(), PROFILE_MODE_DEFAULT);
- AppendOrRemoveDiceRequestHeader(url_request.get(), GURL(), account_id,
- sync_enabled_, sync_has_auth_error_,
- dice_enabled_pref_member_.get(),
- cookie_settings_.get());
+ url_request.get(), GURL(), account_id, account_consistency_,
+ cookie_settings_.get(), PROFILE_MODE_DEFAULT);
+ AppendOrRemoveDiceRequestHeader(
+ url_request.get(), GURL(), account_id, sync_enabled_,
+ sync_has_auth_error_, account_consistency_, cookie_settings_.get());
return url_request;
}
@@ -113,20 +109,21 @@ class SigninHeaderHelperTest : public testing::Test {
bool sync_enabled_ = false;
bool sync_has_auth_error_ = false;
+ AccountConsistencyMethod account_consistency_ =
+ AccountConsistencyMethod::kDisabled;
sync_preferences::TestingPrefServiceSyncable prefs_;
net::TestURLRequestContext url_request_context_;
scoped_refptr<HostContentSettingsMap> settings_map_;
scoped_refptr<content_settings::CookieSettings> cookie_settings_;
- std::unique_ptr<BooleanPrefMember> dice_enabled_pref_member_;
};
#if defined(OS_CHROMEOS)
// Tests that Mirror request is returned on Chrome OS for Public Sessions (no
// account id).
TEST_F(SigninHeaderHelperTest, TestMirrorRequestNoAccountIdChromeOS) {
- ScopedAccountConsistencyMirror scoped_mirror;
+ account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(GURL("https://docs.google.com"), "",
"mode=0,enable_account_consistency=true");
CheckMirrorCookieRequest(GURL("https://docs.google.com"), "",
@@ -136,7 +133,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestNoAccountIdChromeOS) {
// 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) {
- ScopedAccountConsistencyMirror scoped_mirror;
+ account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(GURL("https://docs.google.com"), "", "");
CheckMirrorCookieRequest(GURL("https://docs.google.com"), "", "");
}
@@ -145,7 +142,7 @@ TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestNoAccountId) {
// Tests that no Mirror request is returned when the cookies aren't allowed to
// be set.
TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestCookieSettingBlocked) {
- ScopedAccountConsistencyMirror scoped_mirror;
+ account_consistency_ = AccountConsistencyMethod::kMirror;
cookie_settings_->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
CheckMirrorHeaderRequest(GURL("https://docs.google.com"), "0123456789", "");
CheckMirrorCookieRequest(GURL("https://docs.google.com"), "0123456789", "");
@@ -153,7 +150,7 @@ TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestCookieSettingBlocked) {
// Tests that no Mirror request is returned when the target is a non-Google URL.
TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestExternalURL) {
- ScopedAccountConsistencyMirror scoped_mirror;
+ account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(GURL("https://foo.com"), "0123456789", "");
CheckMirrorCookieRequest(GURL("https://foo.com"), "0123456789", "");
}
@@ -161,7 +158,7 @@ TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestExternalURL) {
// Tests that the Mirror request is returned without the GAIA Id when the target
// is a google TLD domain.
TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleTLD) {
- ScopedAccountConsistencyMirror scoped_mirror;
+ account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(GURL("https://google.fr"), "0123456789",
"mode=0,enable_account_consistency=true");
CheckMirrorCookieRequest(GURL("https://google.de"), "0123456789",
@@ -171,7 +168,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleTLD) {
// Tests that the Mirror request is returned when the target is the domain
// google.com, and that the GAIA Id is only attached for the cookie.
TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleCom) {
- ScopedAccountConsistencyMirror scoped_mirror;
+ account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(GURL("https://www.google.com"), "0123456789",
"mode=0,enable_account_consistency=true");
CheckMirrorCookieRequest(
@@ -186,21 +183,22 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleComNoProfileConsistency) {
net::DEFAULT_PRIORITY, nullptr,
TRAFFIC_ANNOTATION_FOR_TESTS);
AppendOrRemoveMirrorRequestHeader(
- url_request.get(), GURL(), "0123456789", cookie_settings_.get(),
- false /* is_mirror_enabled */, PROFILE_MODE_DEFAULT);
+ url_request.get(), GURL(), "0123456789", account_consistency_,
+ cookie_settings_.get(), PROFILE_MODE_DEFAULT);
CheckAccountConsistencyHeaderRequest(url_request.get(),
kChromeConnectedHeader, "");
}
// Tests that header sent when mirror account consistency is requested.
TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleComProfileConsistency) {
+ account_consistency_ = AccountConsistencyMethod::kMirror;
std::unique_ptr<net::URLRequest> url_request =
url_request_context_.CreateRequest(GURL("https://www.google.com"),
net::DEFAULT_PRIORITY, nullptr,
TRAFFIC_ANNOTATION_FOR_TESTS);
AppendOrRemoveMirrorRequestHeader(
- url_request.get(), GURL(), "0123456789", cookie_settings_.get(),
- true /* is_mirror_enabled */, PROFILE_MODE_DEFAULT);
+ url_request.get(), GURL(), "0123456789", account_consistency_,
+ cookie_settings_.get(), PROFILE_MODE_DEFAULT);
CheckAccountConsistencyHeaderRequest(
url_request.get(), kChromeConnectedHeader,
"mode=0,enable_account_consistency=true");
@@ -213,8 +211,6 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleComProfileConsistency) {
// Tests that the Mirror request is returned when the target is a Gaia URL, even
// if account consistency is disabled.
TEST_F(SigninHeaderHelperTest, TestMirrorRequestGaiaURL) {
- ScopedAccountConsistencyDisabled scoped_no_consistency;
- ASSERT_FALSE(IsAccountConsistencyMirrorEnabled());
CheckMirrorHeaderRequest(GURL("https://accounts.google.com"), "0123456789",
"mode=0,enable_account_consistency=false");
CheckMirrorCookieRequest(
@@ -224,7 +220,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGaiaURL) {
// Tests Dice requests.
TEST_F(SigninHeaderHelperTest, TestDiceRequest) {
- ScopedAccountConsistencyDice scoped_dice;
+ account_consistency_ = AccountConsistencyMethod::kDice;
// ChromeConnected but no Dice for Docs URLs.
CheckDiceHeaderRequest(
GURL("https://docs.google.com"), "0123456789",
@@ -258,7 +254,7 @@ TEST_F(SigninHeaderHelperTest, TestDiceRequest) {
// Tests that no Dice request is returned when Dice is not enabled.
TEST_F(SigninHeaderHelperTest, TestNoDiceRequestWhenDisabled) {
- ScopedAccountConsistencyMirror scoped_mirror;
+ account_consistency_ = AccountConsistencyMethod::kMirror;
CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "0123456789",
"mode=0,enable_account_consistency=true", "");
}
@@ -266,7 +262,7 @@ TEST_F(SigninHeaderHelperTest, TestNoDiceRequestWhenDisabled) {
// Tests that the signout confirmation is requested iff the Dice migration is
// complete.
TEST_F(SigninHeaderHelperTest, TestDiceMigration) {
- ScopedAccountConsistencyDiceMigration scoped_dice_migration;
+ account_consistency_ = AccountConsistencyMethod::kDiceMigration;
std::string client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
ASSERT_FALSE(client_id.empty());
@@ -279,7 +275,7 @@ TEST_F(SigninHeaderHelperTest, TestDiceMigration) {
kDiceProtocolVersion, client_id.c_str()));
// Signout confirmation after the migration is complete.
- MigrateProfileToDice(&prefs_);
+ account_consistency_ = AccountConsistencyMethod::kDice;
CheckDiceHeaderRequest(
GURL("https://accounts.google.com"), "0123456789",
"mode=0,enable_account_consistency=false",
@@ -291,7 +287,7 @@ TEST_F(SigninHeaderHelperTest, TestDiceMigration) {
// Tests that a Dice request is returned only when there is an authentication
// error if the method is kDiceFixAuthErrors.
TEST_F(SigninHeaderHelperTest, TestDiceFixAuthError) {
- ScopedAccountConsistencyDiceFixAuthErrors scoped_dice_fix_auth_errors;
+ account_consistency_ = AccountConsistencyMethod::kDiceFixAuthErrors;
// No Dice request unless all conditions are met.
CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "0123456789",
"mode=0,enable_account_consistency=false", "");
@@ -322,8 +318,6 @@ TEST_F(SigninHeaderHelperTest, TestDiceFixAuthError) {
// Tests that the Mirror request is returned with the GAIA Id on Drive origin,
// even if account consistency is disabled.
TEST_F(SigninHeaderHelperTest, TestMirrorRequestDrive) {
- ScopedAccountConsistencyDisabled scoped_no_consistency;
- ASSERT_FALSE(IsAccountConsistencyMirrorEnabled());
CheckMirrorHeaderRequest(
GURL("https://docs.google.com/document"), "0123456789",
"id=0123456789,mode=0,enable_account_consistency=false");
@@ -332,7 +326,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestDrive) {
"id=0123456789:mode=0:enable_account_consistency=false");
// Enable Account Consistency will override the disable.
- ScopedAccountConsistencyMirror scoped_mirror;
+ account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(
GURL("https://docs.google.com/document"), "0123456789",
"id=0123456789,mode=0,enable_account_consistency=true");
@@ -452,7 +446,7 @@ TEST_F(SigninHeaderHelperTest, TestBuildDiceResponseParams) {
// Tests that the Mirror header request is returned normally when the redirect
// URL is eligible.
TEST_F(SigninHeaderHelperTest, TestMirrorHeaderEligibleRedirectURL) {
- ScopedAccountConsistencyMirror scoped_mirror;
+ account_consistency_ = AccountConsistencyMethod::kMirror;
const GURL url("https://docs.google.com/document");
const GURL redirect_url("https://www.google.com");
const std::string account_id = "0123456789";
@@ -460,8 +454,8 @@ TEST_F(SigninHeaderHelperTest, TestMirrorHeaderEligibleRedirectURL) {
url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr,
TRAFFIC_ANNOTATION_FOR_TESTS);
AppendOrRemoveMirrorRequestHeader(
- url_request.get(), redirect_url, account_id, cookie_settings_.get(),
- IsAccountConsistencyMirrorEnabled(), PROFILE_MODE_DEFAULT);
+ url_request.get(), redirect_url, account_id, account_consistency_,
+ cookie_settings_.get(), PROFILE_MODE_DEFAULT);
EXPECT_TRUE(
url_request->extra_request_headers().HasHeader(kChromeConnectedHeader));
}
@@ -469,7 +463,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorHeaderEligibleRedirectURL) {
// Tests that the Mirror header request is stripped when the redirect URL is not
// eligible.
TEST_F(SigninHeaderHelperTest, TestMirrorHeaderNonEligibleRedirectURL) {
- ScopedAccountConsistencyMirror scoped_mirror;
+ account_consistency_ = AccountConsistencyMethod::kMirror;
const GURL url("https://docs.google.com/document");
const GURL redirect_url("http://www.foo.com");
const std::string account_id = "0123456789";
@@ -477,8 +471,8 @@ TEST_F(SigninHeaderHelperTest, TestMirrorHeaderNonEligibleRedirectURL) {
url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr,
TRAFFIC_ANNOTATION_FOR_TESTS);
AppendOrRemoveMirrorRequestHeader(
- url_request.get(), redirect_url, account_id, cookie_settings_.get(),
- IsAccountConsistencyMirrorEnabled(), PROFILE_MODE_DEFAULT);
+ url_request.get(), redirect_url, account_id, account_consistency_,
+ cookie_settings_.get(), PROFILE_MODE_DEFAULT);
EXPECT_FALSE(
url_request->extra_request_headers().HasHeader(kChromeConnectedHeader));
}
@@ -486,7 +480,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorHeaderNonEligibleRedirectURL) {
// Tests that the Mirror header, whatever its value is, is untouched when both
// the current and the redirect URL are non-eligible.
TEST_F(SigninHeaderHelperTest, TestIgnoreMirrorHeaderNonEligibleURLs) {
- ScopedAccountConsistencyMirror scoped_mirror;
+ account_consistency_ = AccountConsistencyMethod::kMirror;
const GURL url("https://www.bar.com");
const GURL redirect_url("http://www.foo.com");
const std::string account_id = "0123456789";
@@ -497,8 +491,8 @@ TEST_F(SigninHeaderHelperTest, TestIgnoreMirrorHeaderNonEligibleURLs) {
url_request->SetExtraRequestHeaderByName(kChromeConnectedHeader, fake_header,
false);
AppendOrRemoveMirrorRequestHeader(
- url_request.get(), redirect_url, account_id, cookie_settings_.get(),
- IsAccountConsistencyMirrorEnabled(), PROFILE_MODE_DEFAULT);
+ url_request.get(), redirect_url, account_id, account_consistency_,
+ cookie_settings_.get(), PROFILE_MODE_DEFAULT);
std::string header;
EXPECT_TRUE(url_request->extra_request_headers().GetHeader(
kChromeConnectedHeader, &header));
diff --git a/chromium/components/signin/core/browser/signin_manager.cc b/chromium/components/signin/core/browser/signin_manager.cc
index ac3697257f4..a7460b60024 100644
--- a/chromium/components/signin/core/browser/signin_manager.cc
+++ b/chromium/components/signin/core/browser/signin_manager.cc
@@ -15,7 +15,6 @@
#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/gaia_cookie_manager_service.h"
-#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/signin_client.h"
#include "components/signin/core/browser/signin_internals_util.h"
#include "components/signin/core/browser/signin_metrics.h"
@@ -28,19 +27,23 @@
using namespace signin_internals_util;
-SigninManager::SigninManager(SigninClient* client,
- ProfileOAuth2TokenService* token_service,
- AccountTrackerService* account_tracker_service,
- GaiaCookieManagerService* cookie_manager_service,
- SigninErrorController* signin_error_controller)
+SigninManager::SigninManager(
+ SigninClient* client,
+ ProfileOAuth2TokenService* token_service,
+ AccountTrackerService* account_tracker_service,
+ GaiaCookieManagerService* cookie_manager_service,
+ SigninErrorController* signin_error_controller,
+ signin::AccountConsistencyMethod account_consistency)
: SigninManagerBase(client,
account_tracker_service,
signin_error_controller),
prohibit_signout_(false),
type_(SIGNIN_TYPE_NONE),
client_(client),
+ diagnostics_client_(nullptr),
token_service_(token_service),
cookie_manager_service_(cookie_manager_service),
+ account_consistency_(account_consistency),
signin_manager_signed_in_(false),
user_info_fetched_by_account_tracker_(false),
weak_pointer_factory_(this) {}
@@ -158,7 +161,7 @@ void SigninManager::SignOut(
signin_metrics::ProfileSignout signout_source_metric,
signin_metrics::SignoutDelete signout_delete_metric) {
StartSignOut(signout_source_metric, signout_delete_metric,
- !signin::IsDiceEnabledForProfile(client_->GetPrefs()));
+ account_consistency_ != signin::AccountConsistencyMethod::kDice);
}
void SigninManager::SignOutAndRemoveAllAccounts(
@@ -244,10 +247,7 @@ void SigninManager::DoSignOut(
token_service_->RevokeAllCredentials();
}
- for (auto& observer : observer_list_) {
- observer.GoogleSignedOut(account_id, username);
- observer.GoogleSignedOut(account_info);
- }
+ FireGoogleSignedOut(account_id, account_info);
}
void SigninManager::Initialize(PrefService* local_state) {
@@ -344,6 +344,12 @@ bool SigninManager::IsUsernameAllowedByPolicy(const std::string& username,
return !!match; // !! == convert from UBool to bool.
}
+// static
+SigninManager* SigninManager::FromSigninManagerBase(
+ SigninManagerBase* manager) {
+ return static_cast<SigninManager*>(manager);
+}
+
bool SigninManager::IsAllowedUsername(const std::string& username) const {
const PrefService* local_state = local_state_pref_registrar_.prefs();
if (!local_state)
@@ -437,6 +443,11 @@ void SigninManager::OnSignedIn() {
}
void SigninManager::FireGoogleSigninSucceeded() {
+ if (diagnostics_client_) {
+ diagnostics_client_->WillFireGoogleSigninSucceeded(
+ GetAuthenticatedAccountInfo());
+ }
+
std::string account_id = GetAuthenticatedAccountId();
std::string email = GetAuthenticatedAccountInfo().email;
for (auto& observer : observer_list_) {
@@ -446,6 +457,18 @@ void SigninManager::FireGoogleSigninSucceeded() {
}
}
+void SigninManager::FireGoogleSignedOut(const std::string& account_id,
+ const AccountInfo& account_info) {
+ if (diagnostics_client_) {
+ diagnostics_client_->WillFireGoogleSignedOut(account_info);
+ }
+
+ for (auto& observer : observer_list_) {
+ observer.GoogleSignedOut(account_id, account_info.email);
+ observer.GoogleSignedOut(account_info);
+ }
+}
+
void SigninManager::PostSignedIn() {
if (!signin_manager_signed_in_ || !user_info_fetched_by_account_tracker_)
return;
diff --git a/chromium/components/signin/core/browser/signin_manager.h b/chromium/components/signin/core/browser/signin_manager.h
index 8408e0af898..72f26974c6f 100644
--- a/chromium/components/signin/core/browser/signin_manager.h
+++ b/chromium/components/signin/core/browser/signin_manager.h
@@ -34,6 +34,7 @@
#include "components/prefs/pref_member.h"
#include "components/signin/core/browser/account_info.h"
#include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_internals_util.h"
#include "components/signin/core/browser/signin_manager_base.h"
@@ -47,6 +48,10 @@ class ProfileOAuth2TokenService;
class SigninClient;
class SigninErrorController;
+namespace identity {
+class IdentityManager;
+}
+
class SigninManager : public SigninManagerBase,
public AccountTrackerService::Observer,
public OAuth2TokenService::Observer {
@@ -68,13 +73,19 @@ class SigninManager : public SigninManagerBase,
ProfileOAuth2TokenService* token_service,
AccountTrackerService* account_tracker_service,
GaiaCookieManagerService* cookie_manager_service,
- SigninErrorController* signin_error_controller);
+ SigninErrorController* signin_error_controller,
+ signin::AccountConsistencyMethod account_consistency);
~SigninManager() override;
// Returns true if the username is allowed based on the policy string.
static bool IsUsernameAllowedByPolicy(const std::string& username,
const std::string& policy);
+ // Returns |manager| as a SigninManager instance. Relies on the fact that on
+ // platforms where signin_manager.* is built, all SigninManagerBase instances
+ // are actually SigninManager instances.
+ static SigninManager* FromSigninManagerBase(SigninManagerBase* manager);
+
// Attempt to sign in this user with a refresh token.
// If |refresh_token| is not empty, then SigninManager will add it to the
// |token_service_| when the sign-in flow is completed.
@@ -175,6 +186,23 @@ class SigninManager : public SigninManagerBase,
bool remove_all_accounts);
private:
+ // Interface that gives information on internal SigninManager operations. Only
+ // for use by IdentityManager during the conversion of the codebase to use
+ // //services/identity/public/cpp.
+ class DiagnosticsClient {
+ public:
+ // Sent just before GoogleSigninSucceeded() is fired on observers.
+ virtual void WillFireGoogleSigninSucceeded(
+ const AccountInfo& account_info) = 0;
+ // Sent just before GoogleSignedOut() is fired on observers.
+ virtual void WillFireGoogleSignedOut(const AccountInfo& account_info) = 0;
+ };
+
+ void set_diagnostics_client(DiagnosticsClient* diagnostics_client) {
+ DCHECK(!diagnostics_client_ || !diagnostics_client);
+ diagnostics_client_ = diagnostics_client;
+ }
+
enum SigninType {
SIGNIN_TYPE_NONE,
SIGNIN_TYPE_WITH_REFRESH_TOKEN,
@@ -183,6 +211,7 @@ class SigninManager : public SigninManagerBase,
std::string SigninTypeToString(SigninType type);
friend class FakeSigninManager;
+ friend class identity::IdentityManager;
FRIEND_TEST_ALL_PREFIXES(SigninManagerTest, ClearTransientSigninData);
FRIEND_TEST_ALL_PREFIXES(SigninManagerTest, ProvideSecondFactorSuccess);
FRIEND_TEST_ALL_PREFIXES(SigninManagerTest, ProvideSecondFactorFailure);
@@ -208,6 +237,10 @@ class SigninManager : public SigninManagerBase,
// Send all observers |GoogleSigninSucceeded| notifications.
void FireGoogleSigninSucceeded();
+ // Send all observers |GoogleSignedOut| notifications.
+ void FireGoogleSignedOut(const std::string& account_id,
+ const AccountInfo& account_info);
+
// Waits for the AccountTrackerService, then sends GoogleSigninSucceeded to
// the client and clears the local password.
void PostSignedIn();
@@ -255,6 +288,9 @@ class SigninManager : public SigninManagerBase,
// object.
SigninClient* client_;
+ // The DiagnosticsClient object associated with this object. May be null.
+ DiagnosticsClient* diagnostics_client_;
+
// The ProfileOAuth2TokenService instance associated with this object. Must
// outlive this object.
ProfileOAuth2TokenService* token_service_;
@@ -269,6 +305,8 @@ class SigninManager : public SigninManagerBase,
// Helper object to listen for changes to the signin allowed preference.
BooleanPrefMember signin_allowed_;
+ signin::AccountConsistencyMethod account_consistency_;
+
// Two gate conditions for when PostSignedIn should be called. Verify
// that the SigninManager has reached OnSignedIn() and the AccountTracker
// has completed calling GetUserInfo.
diff --git a/chromium/components/signin/core/browser/signin_manager_unittest.cc b/chromium/components/signin/core/browser/signin_manager_unittest.cc
index 90eb20beab5..7fa807de9d3 100644
--- a/chromium/components/signin/core/browser/signin_manager_unittest.cc
+++ b/chromium/components/signin/core/browser/signin_manager_unittest.cc
@@ -88,16 +88,15 @@ class SigninManagerTest : public testing::Test {
url_fetcher_factory_(nullptr) {
test_signin_client_.SetURLRequestContext(
new net::TestURLRequestContextGetter(loop_.task_runner()));
- signin::SetGaiaOriginIsolatedCallback(base::Bind([] { return true; }));
cookie_manager_service_.Init(&url_fetcher_factory_);
- signin::RegisterAccountConsistencyProfilePrefs(user_prefs_.registry());
AccountFetcherService::RegisterPrefs(user_prefs_.registry());
AccountTrackerService::RegisterPrefs(user_prefs_.registry());
SigninManagerBase::RegisterProfilePrefs(user_prefs_.registry());
SigninManagerBase::RegisterPrefs(local_state_.registry());
account_tracker_.Initialize(&test_signin_client_);
account_fetcher_.Initialize(&test_signin_client_, &token_service_,
- &account_tracker_);
+ &account_tracker_,
+ std::make_unique<TestImageDecoder>());
}
~SigninManagerTest() override {
@@ -131,7 +130,8 @@ class SigninManagerTest : public testing::Test {
DCHECK(!manager_);
manager_ = std::make_unique<SigninManager>(
&test_signin_client_, &token_service_, &account_tracker_,
- &cookie_manager_service_, nullptr /* signin_error_controller */);
+ &cookie_manager_service_, nullptr /* signin_error_controller */,
+ signin::AccountConsistencyMethod::kDisabled);
manager_->Initialize(&local_state_);
manager_->AddObserver(&test_observer_);
}
diff --git a/chromium/components/signin/core/browser/signin_pref_names.cc b/chromium/components/signin/core/browser/signin_pref_names.cc
index 7ec48b9756b..efc5bf6d9c3 100644
--- a/chromium/components/signin/core/browser/signin_pref_names.cc
+++ b/chromium/components/signin/core/browser/signin_pref_names.cc
@@ -95,6 +95,9 @@ const char kSignedInTime[] = "signin.signedin_time";
// Boolean which stores if the user is allowed to signin to chrome.
const char kSigninAllowed[] = "signin.allowed";
+// True if the token service has been prepared for Dice migration.
+const char kTokenServiceDiceCompatible[] = "token_service.dice_compatible";
+
// Boolean which stores if the OAuth2TokenService should ignore secondary
// accounts.
const char kTokenServiceExcludeAllSecondaryAccounts[] =
diff --git a/chromium/components/signin/core/browser/signin_pref_names.h b/chromium/components/signin/core/browser/signin_pref_names.h
index fec221ef25b..7e6afad8390 100644
--- a/chromium/components/signin/core/browser/signin_pref_names.h
+++ b/chromium/components/signin/core/browser/signin_pref_names.h
@@ -27,6 +27,7 @@ extern const char kReverseAutologinEnabled[];
extern const char kReverseAutologinRejectedEmailList[];
extern const char kSignedInTime[];
extern const char kSigninAllowed[];
+extern const char kTokenServiceDiceCompatible[];
extern const char kTokenServiceExcludeAllSecondaryAccounts[];
extern const char kTokenServiceExcludedSecondaryAccounts[];
diff --git a/chromium/components/signin/core/browser/test_signin_client.cc b/chromium/components/signin/core/browser/test_signin_client.cc
index 002f697768a..63a7e044708 100644
--- a/chromium/components/signin/core/browser/test_signin_client.cc
+++ b/chromium/components/signin/core/browser/test_signin_client.cc
@@ -4,8 +4,9 @@
#include "components/signin/core/browser/test_signin_client.h"
+#include <memory>
+
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/signin/core/browser/webdata/token_service_table.h"
#include "components/webdata/common/web_data_service_base.h"
@@ -71,12 +72,11 @@ bool TestSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() {
return true;
}
-std::unique_ptr<SigninClient::CookieChangedSubscription>
-TestSigninClient::AddCookieChangedCallback(
- const GURL& url,
- const std::string& name,
- const net::CookieStore::CookieChangedCallback& callback) {
- return base::WrapUnique(new SigninClient::CookieChangedSubscription);
+std::unique_ptr<SigninClient::CookieChangeSubscription>
+TestSigninClient::AddCookieChangeCallback(const GURL& url,
+ const std::string& name,
+ net::CookieChangeCallback callback) {
+ return std::make_unique<SigninClient::CookieChangeSubscription>();
}
bool TestSigninClient::IsFirstRun() const {
diff --git a/chromium/components/signin/core/browser/test_signin_client.h b/chromium/components/signin/core/browser/test_signin_client.h
index 40b6c672bc7..b3f416b509a 100644
--- a/chromium/components/signin/core/browser/test_signin_client.h
+++ b/chromium/components/signin/core/browser/test_signin_client.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "components/signin/core/browser/signin_client.h"
+#include "net/cookies/cookie_change_dispatcher.h"
#include "net/url_request/url_request_test_util.h"
class PrefService;
@@ -68,11 +69,10 @@ class TestSigninClient : public SigninClient {
// Registers |callback| and returns the subscription.
// Note that |callback| will never be called.
- std::unique_ptr<SigninClient::CookieChangedSubscription>
- AddCookieChangedCallback(
- const GURL& url,
- const std::string& name,
- const net::CookieStore::CookieChangedCallback& callback) override;
+ std::unique_ptr<SigninClient::CookieChangeSubscription>
+ AddCookieChangeCallback(const GURL& url,
+ const std::string& name,
+ net::CookieChangeCallback callback) override;
void set_are_signin_cookies_allowed(bool value) {
are_signin_cookies_allowed_ = value;
diff --git a/chromium/components/signin/ios/browser/account_consistency_service.mm b/chromium/components/signin/ios/browser/account_consistency_service.mm
index a5305e1be0d..6d45d9f03aa 100644
--- a/chromium/components/signin/ios/browser/account_consistency_service.mm
+++ b/chromium/components/signin/ios/browser/account_consistency_service.mm
@@ -14,6 +14,7 @@
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/signin/core/browser/account_reconcilor.h"
+#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/signin_client.h"
#include "components/signin/core/browser/signin_header_helper.h"
#include "ios/web/public/browser_state.h"
@@ -364,7 +365,8 @@ void AccountConsistencyService::ApplyCookieRequests() {
case ADD_CHROME_CONNECTED_COOKIE:
cookie_value = signin::BuildMirrorRequestCookieIfPossible(
url, signin_manager_->GetAuthenticatedAccountInfo().gaia,
- cookie_settings_.get(), signin::PROFILE_MODE_DEFAULT);
+ signin::AccountConsistencyMethod::kMirror, cookie_settings_.get(),
+ signin::PROFILE_MODE_DEFAULT);
if (cookie_value.empty()) {
// Don't add the cookie. Tentatively correct |last_cookie_update_map_|.
last_cookie_update_map_.erase(cookie_requests_.front().domain);
@@ -473,7 +475,7 @@ void AccountConsistencyService::OnBrowsingDataRemoved() {
signin_client_->GetPrefs()->Set(kDomainsWithCookiePref, dict);
// APISID cookie has been removed, notify the GCMS.
- gaia_cookie_manager_service_->ForceOnCookieChangedProcessing();
+ gaia_cookie_manager_service_->ForceOnCookieChangeProcessing();
}
void AccountConsistencyService::OnAddAccountToCookieCompleted(
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 5b14e314c15..82dcd9a6c93 100644
--- a/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
+++ b/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -90,14 +90,14 @@ class MockAccountReconcilor : public AccountReconcilor {
MOCK_METHOD1(OnReceivedManageAccountsResponse, void(signin::GAIAServiceType));
};
-// Mock GaiaCookieManagerService to catch call to ForceOnCookieChangedProcessing
+// Mock GaiaCookieManagerService to catch call to ForceOnCookieChangeProcessing
class MockGaiaCookieManagerService : public GaiaCookieManagerService {
public:
MockGaiaCookieManagerService()
: GaiaCookieManagerService(nullptr,
GaiaConstants::kChromeSource,
nullptr) {}
- MOCK_METHOD0(ForceOnCookieChangedProcessing, void());
+ MOCK_METHOD0(ForceOnCookieChangeProcessing, void());
};
// TestWebState that allows control over its policy decider.
@@ -446,7 +446,7 @@ TEST_F(AccountConsistencyServiceTest, DomainsClearedOnBrowsingDataRemoved) {
prefs_.GetDictionary(AccountConsistencyService::kDomainsWithCookiePref);
EXPECT_EQ(2u, dict->size());
- EXPECT_CALL(*gaia_cookie_manager_service_, ForceOnCookieChangedProcessing())
+ EXPECT_CALL(*gaia_cookie_manager_service_, ForceOnCookieChangeProcessing())
.Times(1);
account_consistency_service_->OnBrowsingDataRemoved();
dict =
@@ -463,7 +463,7 @@ TEST_F(AccountConsistencyServiceTest, DomainsClearedOnBrowsingDataRemoved2) {
AddPageLoadedExpectation(kGoogleUrl, false /* continue_navigation */);
SimulateGaiaCookieManagerServiceLogout(false);
- EXPECT_CALL(*gaia_cookie_manager_service_, ForceOnCookieChangedProcessing())
+ EXPECT_CALL(*gaia_cookie_manager_service_, ForceOnCookieChangeProcessing())
.Times(1);
account_consistency_service_->OnBrowsingDataRemoved();
EXPECT_TRUE(remove_cookie_callback_called_);
diff --git a/chromium/components/spellcheck/browser/BUILD.gn b/chromium/components/spellcheck/browser/BUILD.gn
index b8069c146ce..dd0e7c9ff89 100644
--- a/chromium/components/spellcheck/browser/BUILD.gn
+++ b/chromium/components/spellcheck/browser/BUILD.gn
@@ -10,11 +10,11 @@ source_set("browser") {
sources = [
"pref_names.cc",
"pref_names.h",
+ "spell_check_host_impl.cc",
+ "spell_check_host_impl.h",
"spellcheck_dictionary.h",
"spellcheck_host_metrics.cc",
"spellcheck_host_metrics.h",
- "spellcheck_message_filter_platform.h",
- "spellcheck_message_filter_platform_android.cc",
"spellcheck_platform.h",
"spellcheck_platform_android.cc",
"spellcheck_platform_mac.mm",
@@ -58,6 +58,7 @@ source_set("unit_tests") {
"//components/spellcheck/common",
"//components/variations",
"//content/test:test_support",
+ "//mojo/public/cpp/bindings",
"//net:test_support",
"//testing/gtest",
]
diff --git a/chromium/components/spellcheck/browser/DEPS b/chromium/components/spellcheck/browser/DEPS
index b843201b602..f55de2481af 100644
--- a/chromium/components/spellcheck/browser/DEPS
+++ b/chromium/components/spellcheck/browser/DEPS
@@ -8,5 +8,6 @@ include_rules = [
"+crypto",
"+google_apis",
"+jni",
+ "+mojo/public/cpp/bindings",
"+net",
]
diff --git a/chromium/components/spellcheck/browser/spell_check_host_impl.cc b/chromium/components/spellcheck/browser/spell_check_host_impl.cc
new file mode 100644
index 00000000000..c8d396e4496
--- /dev/null
+++ b/chromium/components/spellcheck/browser/spell_check_host_impl.cc
@@ -0,0 +1,92 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/spellcheck/browser/spell_check_host_impl.h"
+
+#include "base/memory/ptr_util.h"
+#include "content/public/browser/browser_thread.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+SpellCheckHostImpl::SpellCheckHostImpl() = default;
+SpellCheckHostImpl::~SpellCheckHostImpl() = default;
+
+// static
+void SpellCheckHostImpl::Create(
+ spellcheck::mojom::SpellCheckHostRequest request) {
+ mojo::MakeStrongBinding(std::make_unique<SpellCheckHostImpl>(),
+ std::move(request));
+}
+
+void SpellCheckHostImpl::RequestDictionary() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // This API requires Chrome-only features.
+ return;
+}
+
+void SpellCheckHostImpl::NotifyChecked(const base::string16& word,
+ bool misspelled) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // This API requires Chrome-only features.
+ return;
+}
+
+#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+void SpellCheckHostImpl::CallSpellingService(
+ const base::string16& text,
+ CallSpellingServiceCallback callback) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ if (text.empty())
+ mojo::ReportBadMessage(__FUNCTION__);
+
+ // This API requires Chrome-only features.
+ std::move(callback).Run(false, std::vector<SpellCheckResult>());
+}
+#endif // !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+
+#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+void SpellCheckHostImpl::RequestTextCheck(const base::string16& text,
+ int route_id,
+ RequestTextCheckCallback callback) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ if (text.empty())
+ mojo::ReportBadMessage(__FUNCTION__);
+
+#if defined(OS_ANDROID)
+ session_bridge_.RequestTextCheck(text, std::move(callback));
+#else
+ // This API requires Chrome-only features on the platform.
+ std::move(callback).Run(std::vector<SpellCheckResult>());
+#endif
+}
+
+void SpellCheckHostImpl::ToggleSpellCheck(bool enabled, bool checked) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+#if defined(OS_ANDROID)
+ if (!enabled)
+ session_bridge_.DisconnectSession();
+#endif
+}
+
+void SpellCheckHostImpl::CheckSpelling(const base::string16& word,
+ int route_id,
+ CheckSpellingCallback callback) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // This API requires Chrome-only features.
+ std::move(callback).Run(false);
+}
+
+void SpellCheckHostImpl::FillSuggestionList(
+ const base::string16& word,
+ FillSuggestionListCallback callback) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // This API requires Chrome-only features.
+ std::move(callback).Run(std::vector<base::string16>());
+}
+#endif // BUILDFLAG(USE_BROWSER_SPELLCHECKER)
diff --git a/chromium/components/spellcheck/browser/spell_check_host_impl.h b/chromium/components/spellcheck/browser/spell_check_host_impl.h
new file mode 100644
index 00000000000..189800703dc
--- /dev/null
+++ b/chromium/components/spellcheck/browser/spell_check_host_impl.h
@@ -0,0 +1,65 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SPELLCHECK_BROWSER_SPELL_CHECK_HOST_IMPL_H_
+#define COMPONENTS_SPELLCHECK_BROWSER_SPELL_CHECK_HOST_IMPL_H_
+
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "components/spellcheck/common/spellcheck.mojom.h"
+#include "components/spellcheck/spellcheck_build_features.h"
+
+#if defined(OS_ANDROID)
+#include "components/spellcheck/browser/spellchecker_session_bridge_android.h"
+#endif
+
+#if !BUILDFLAG(ENABLE_SPELLCHECK)
+#error "Spellcheck should be enabled."
+#endif
+
+class SpellCheckerSessionBridge;
+
+// A basic implementation of SpellCheckHost without using any Chrome-only
+// feature, so that there is still basic spellcheck support when those features
+// are not available (e.g., on Android WebView). The full implementation
+// involving Chrome-only features is in SpellCheckHostChromeImpl.
+class SpellCheckHostImpl : public spellcheck::mojom::SpellCheckHost {
+ public:
+ SpellCheckHostImpl();
+ ~SpellCheckHostImpl() override;
+
+ static void Create(spellcheck::mojom::SpellCheckHostRequest request);
+
+ protected:
+ // spellcheck::mojom::SpellCheckHost:
+ void RequestDictionary() override;
+ void NotifyChecked(const base::string16& word, bool misspelled) override;
+
+#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+ void CallSpellingService(const base::string16& text,
+ CallSpellingServiceCallback callback) override;
+#endif // !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+
+#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+ void RequestTextCheck(const base::string16& text,
+ int route_id,
+ RequestTextCheckCallback callback) override;
+ void ToggleSpellCheck(bool enabled, bool checked) override;
+ void CheckSpelling(const base::string16& word,
+ int route_id,
+ CheckSpellingCallback callback) override;
+ void FillSuggestionList(const base::string16& word,
+ FillSuggestionListCallback callback) override;
+#endif // BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+
+ private:
+#if defined(OS_ANDROID)
+ // Android-specific object used to query the Android spellchecker.
+ SpellCheckerSessionBridge session_bridge_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(SpellCheckHostImpl);
+};
+
+#endif // COMPONENTS_SPELLCHECK_BROWSER_SPELL_CHECK_HOST_IMPL_H_
diff --git a/chromium/components/spellcheck/browser/spellcheck_message_filter_platform.h b/chromium/components/spellcheck/browser/spellcheck_message_filter_platform.h
deleted file mode 100644
index 430a7ba06d3..00000000000
--- a/chromium/components/spellcheck/browser/spellcheck_message_filter_platform.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SPELLCHECK_BROWSER_SPELLCHECK_MESSAGE_FILTER_PLATFORM_H_
-#define COMPONENTS_SPELLCHECK_BROWSER_SPELLCHECK_MESSAGE_FILTER_PLATFORM_H_
-
-#include <map>
-
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "components/spellcheck/browser/spelling_service_client.h"
-#include "components/spellcheck/common/spellcheck_result.h"
-#include "content/public/browser/browser_message_filter.h"
-
-class SpellCheckerSessionBridge;
-
-// A message filter implementation that receives
-// the platform-specific spell checker requests from SpellCheckProvider.
-class SpellCheckMessageFilterPlatform : public content::BrowserMessageFilter {
- public:
- explicit SpellCheckMessageFilterPlatform(int render_process_id);
-
- // BrowserMessageFilter implementation.
- void OverrideThreadForMessage(const IPC::Message& message,
- content::BrowserThread::ID* thread) override;
- bool OnMessageReceived(const IPC::Message& message) override;
-
-#if defined(OS_MACOSX)
- // Adjusts remote_results by examining local_results. Any result that's both
- // local and remote stays type SPELLING, all others are flagged GRAMMAR.
- // (This is needed to force gray underline for remote-only results.)
- static void CombineResults(
- std::vector<SpellCheckResult>* remote_results,
- const std::vector<SpellCheckResult>& local_results);
-#endif
-
- private:
- friend class TestingSpellCheckMessageFilter;
- friend class SpellcheckMessageFilterPlatformMacTest;
-
- ~SpellCheckMessageFilterPlatform() override;
-
- void OnRequestTextCheck(int route_id,
- int identifier,
- const base::string16& text);
-
- int render_process_id_;
-
-#if defined(OS_ANDROID)
- friend struct content::BrowserThread::DeleteOnThread<
- content::BrowserThread::UI>;
- friend class base::DeleteHelper<SpellCheckMessageFilterPlatform>;
-
- void OnToggleSpellCheck(bool enabled, bool checked);
- void OnDestruct() const override;
-
- // Android-specific object used to query the Android spellchecker.
- std::unique_ptr<SpellCheckerSessionBridge> impl_;
-#endif
-
-#if defined(OS_MACOSX)
- void OnCheckSpelling(const base::string16& word, int route_id, bool* correct);
- void OnFillSuggestionList(const base::string16& word,
- std::vector<base::string16>* suggestions);
-
- int ToDocumentTag(int route_id);
- void RetireDocumentTag(int route_id);
- std::map<int, int> tag_map_;
-
- // A JSON-RPC client that calls the Spelling service in the background.
- std::unique_ptr<SpellingServiceClient> client_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(SpellCheckMessageFilterPlatform);
-};
-
-#endif // COMPONENTS_SPELLCHECK_BROWSER_SPELLCHECK_MESSAGE_FILTER_PLATFORM_H_
diff --git a/chromium/components/spellcheck/browser/spellcheck_message_filter_platform_android.cc b/chromium/components/spellcheck/browser/spellcheck_message_filter_platform_android.cc
deleted file mode 100644
index ca3fade94ee..00000000000
--- a/chromium/components/spellcheck/browser/spellcheck_message_filter_platform_android.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/spellcheck/browser/spellcheck_message_filter_platform.h"
-
-#include "components/spellcheck/browser/spellchecker_session_bridge_android.h"
-#include "components/spellcheck/common/spellcheck_messages.h"
-#include "components/spellcheck/common/spellcheck_result.h"
-#include "content/public/browser/browser_thread.h"
-
-using content::BrowserThread;
-
-SpellCheckMessageFilterPlatform::SpellCheckMessageFilterPlatform(
- int render_process_id)
- : BrowserMessageFilter(SpellCheckMsgStart),
- render_process_id_(render_process_id),
- impl_(new SpellCheckerSessionBridge(render_process_id)) {}
-
-void SpellCheckMessageFilterPlatform::OverrideThreadForMessage(
- const IPC::Message& message, BrowserThread::ID* thread) {
- switch (message.type()) {
- case SpellCheckHostMsg_RequestTextCheck::ID:
- case SpellCheckHostMsg_ToggleSpellCheck::ID:
- *thread = BrowserThread::UI;
- break;
- default:
- break;
- }
-}
-
-bool SpellCheckMessageFilterPlatform::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(SpellCheckMessageFilterPlatform, message)
- IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RequestTextCheck, OnRequestTextCheck)
- IPC_MESSAGE_HANDLER(SpellCheckHostMsg_ToggleSpellCheck, OnToggleSpellCheck)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-SpellCheckMessageFilterPlatform::~SpellCheckMessageFilterPlatform() {}
-
-void SpellCheckMessageFilterPlatform::OnRequestTextCheck(
- int route_id,
- int identifier,
- const base::string16& text) {
- DCHECK(!text.empty());
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- impl_->RequestTextCheck(route_id, identifier, text);
-}
-
-void SpellCheckMessageFilterPlatform::OnToggleSpellCheck(
- bool enabled,
- bool checked) {
- if (!enabled)
- impl_->DisconnectSession();
-}
-
-void SpellCheckMessageFilterPlatform::OnDestruct() const {
- // Needs to be destroyed on the UI thread, to avoid race conditions
- // on the java side during clean-up.
- BrowserThread::DeleteOnUIThread::Destruct(this);
-}
diff --git a/chromium/components/spellcheck/browser/spellcheck_platform.h b/chromium/components/spellcheck/browser/spellcheck_platform.h
index c9ff4959c50..0153eb90ead 100644
--- a/chromium/components/spellcheck/browser/spellcheck_platform.h
+++ b/chromium/components/spellcheck/browser/spellcheck_platform.h
@@ -87,8 +87,6 @@ void IgnoreWord(const base::string16& word);
void CloseDocumentWithTag(int tag);
// Requests an asyncronous spell and grammar checking.
-// The result is returned to an IPC message to |destination| thus it should
-// not be null.
void RequestTextCheck(int document_tag,
const base::string16& text,
TextCheckCompleteCallback callback);
diff --git a/chromium/components/spellcheck/browser/spellcheck_platform_mac.mm b/chromium/components/spellcheck/browser/spellcheck_platform_mac.mm
index a6373ec8bb1..80c7a509ad1 100644
--- a/chromium/components/spellcheck/browser/spellcheck_platform_mac.mm
+++ b/chromium/components/spellcheck/browser/spellcheck_platform_mac.mm
@@ -16,11 +16,9 @@
#include "base/time/time.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "components/spellcheck/common/spellcheck_result.h"
-#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
using base::TimeTicks;
-using content::BrowserMessageFilter;
using content::BrowserThread;
namespace {
diff --git a/chromium/components/spellcheck/browser/spellchecker_session_bridge_android.cc b/chromium/components/spellcheck/browser/spellchecker_session_bridge_android.cc
index 2b4ba92adea..bfc0165d307 100644
--- a/chromium/components/spellcheck/browser/spellchecker_session_bridge_android.cc
+++ b/chromium/components/spellcheck/browser/spellchecker_session_bridge_android.cc
@@ -10,7 +10,6 @@
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/metrics/histogram_macros.h"
-#include "components/spellcheck/common/spellcheck_messages.h"
#include "components/spellcheck/common/spellcheck_result.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
@@ -26,10 +25,8 @@ void RecordAvailabilityUMA(bool spellcheck_available) {
} // namespace
-SpellCheckerSessionBridge::SpellCheckerSessionBridge(int render_process_id)
- : render_process_id_(render_process_id),
- java_object_initialization_failed_(false),
- active_session_(false) {}
+SpellCheckerSessionBridge::SpellCheckerSessionBridge()
+ : java_object_initialization_failed_(false), active_session_(false) {}
SpellCheckerSessionBridge::~SpellCheckerSessionBridge() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -37,9 +34,9 @@ SpellCheckerSessionBridge::~SpellCheckerSessionBridge() {
DisconnectSession();
}
-void SpellCheckerSessionBridge::RequestTextCheck(int route_id,
- int identifier,
- const base::string16& text) {
+void SpellCheckerSessionBridge::RequestTextCheck(
+ const base::string16& text,
+ RequestTextCheckCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// SpellCheckerSessionBridge#create() will return null if spell checker
// service is unavailable.
@@ -51,8 +48,8 @@ void SpellCheckerSessionBridge::RequestTextCheck(int route_id,
return;
}
- // RequestTextCheck IPC arrives at the message filter before
- // ToggleSpellCheck IPC when the user focuses an input field that already
+ // RequestTextCheck API call arrives at the SpellCheckHost before
+ // ToggleSpellCheck when the user focuses an input field that already
// contains completed text. We need to initialize the spellchecker here
// rather than in response to ToggleSpellCheck so that the existing text
// will be spellchecked immediately.
@@ -74,11 +71,11 @@ void SpellCheckerSessionBridge::RequestTextCheck(int route_id,
// If multiple requests arrive during one active request, only the most
// recent request will run (the others get overwritten).
if (active_request_) {
- pending_request_.reset(new SpellingRequest(route_id, identifier, text));
+ pending_request_.reset(new SpellingRequest(text, std::move(callback)));
return;
}
- active_request_.reset(new SpellingRequest(route_id, identifier, text));
+ active_request_.reset(new SpellingRequest(text, std::move(callback)));
JNIEnv* env = base::android::AttachCurrentThread();
Java_SpellCheckerSessionBridge_requestTextCheck(
@@ -110,21 +107,14 @@ void SpellCheckerSessionBridge::ProcessSpellCheckResults(
lengths[i], suggestions_for_word));
}
- content::RenderProcessHost* sender =
- content::RenderProcessHost::FromID(render_process_id_);
-
- if (sender != nullptr) {
- sender->Send(new SpellCheckMsg_RespondTextCheck(
- active_request_->route_id, active_request_->identifier,
- active_request_->text, results));
- }
+ std::move(active_request_->callback_).Run(results);
active_request_ = std::move(pending_request_);
if (active_request_) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_SpellCheckerSessionBridge_requestTextCheck(
env, java_object_,
- base::android::ConvertUTF16ToJavaString(env, active_request_->text));
+ base::android::ConvertUTF16ToJavaString(env, active_request_->text_));
}
}
@@ -145,9 +135,8 @@ void SpellCheckerSessionBridge::DisconnectSession() {
}
SpellCheckerSessionBridge::SpellingRequest::SpellingRequest(
- int route_id,
- int identifier,
- const base::string16& text)
- : route_id(route_id), identifier(identifier), text(text) {}
+ const base::string16& text,
+ RequestTextCheckCallback callback)
+ : text_(text), callback_(std::move(callback)) {}
SpellCheckerSessionBridge::SpellingRequest::~SpellingRequest() {}
diff --git a/chromium/components/spellcheck/browser/spellchecker_session_bridge_android.h b/chromium/components/spellcheck/browser/spellchecker_session_bridge_android.h
index 0845133a577..2ba2dbd4c0a 100644
--- a/chromium/components/spellcheck/browser/spellchecker_session_bridge_android.h
+++ b/chromium/components/spellcheck/browser/spellchecker_session_bridge_android.h
@@ -12,21 +12,23 @@
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "base/strings/string16.h"
+#include "components/spellcheck/common/spellcheck.mojom.h"
// A class used to interface between the Java class of the same name and the
-// android message filter. This class receives text to be spellchecked
-// from the message filter, sends that text to the Java side via JNI to be
-// spellchecked, and then sends those results to the renderer.
+// android SpellCheckHost. This class receives text to be spellchecked, sends
+// that text to the Java side via JNI to be spellchecked, and then sends those
+// results to the renderer.
class SpellCheckerSessionBridge {
public:
- explicit SpellCheckerSessionBridge(int render_process_id);
+ SpellCheckerSessionBridge();
~SpellCheckerSessionBridge();
- // Receives text to be checked from the message filter and sends it to Java
- // to be spellchecked.
- void RequestTextCheck(int route_id,
- int identifier,
- const base::string16& text);
+ using RequestTextCheckCallback =
+ spellcheck::mojom::SpellCheckHost::RequestTextCheckCallback;
+
+ // Receives text to be checked and sends it to Java to be spellchecked.
+ void RequestTextCheck(const base::string16& text,
+ RequestTextCheckCallback callback);
// Receives information from Java side about the typos in a given string
// of text, processes these and sends them to the renderer.
@@ -42,16 +44,18 @@ class SpellCheckerSessionBridge {
void DisconnectSession();
private:
- struct SpellingRequest {
- SpellingRequest(int route_id, int identifier, const base::string16& text);
+ class SpellingRequest {
+ public:
+ SpellingRequest(const base::string16& text,
+ RequestTextCheckCallback callback);
~SpellingRequest();
- int route_id;
- int identifier;
- base::string16 text;
- };
+ base::string16 text_;
+ RequestTextCheckCallback callback_;
- int render_process_id_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SpellingRequest);
+ };
std::unique_ptr<SpellingRequest> active_request_;
std::unique_ptr<SpellingRequest> pending_request_;
diff --git a/chromium/components/spellcheck/browser/spelling_service_client.cc b/chromium/components/spellcheck/browser/spelling_service_client.cc
index 5ab8b6bced6..e8afa352631 100644
--- a/chromium/components/spellcheck/browser/spelling_service_client.cc
+++ b/chromium/components/spellcheck/browser/spelling_service_client.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <algorithm>
+#include <memory>
#include "base/json/json_reader.h"
#include "base/json/string_escape.h"
@@ -147,7 +148,7 @@ bool SpellingServiceClient::RequestTextCheck(
fetcher->SetUploadData("application/json", request);
fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SAVE_COOKIES);
- spellcheck_fetchers_[fetcher] = base::MakeUnique<TextCheckCallbackData>(
+ spellcheck_fetchers_[fetcher] = std::make_unique<TextCheckCallbackData>(
base::WrapUnique(fetcher), std::move(callback), text);
fetcher->Start();
return true;
@@ -279,7 +280,7 @@ bool SpellingServiceClient::ParseResponse(
SpellingServiceClient::TextCheckCallbackData::TextCheckCallbackData(
std::unique_ptr<net::URLFetcher> fetcher,
- TextCheckCompleteCallback&& callback,
+ TextCheckCompleteCallback callback,
base::string16 text)
: fetcher(std::move(fetcher)), callback(std::move(callback)), text(text) {}
diff --git a/chromium/components/spellcheck/browser/spelling_service_client.h b/chromium/components/spellcheck/browser/spelling_service_client.h
index c3d4c08e579..1093b48b8f9 100644
--- a/chromium/components/spellcheck/browser/spelling_service_client.h
+++ b/chromium/components/spellcheck/browser/spelling_service_client.h
@@ -97,8 +97,9 @@ class SpellingServiceClient : public net::URLFetcherDelegate {
private:
struct TextCheckCallbackData {
+ public:
TextCheckCallbackData(std::unique_ptr<net::URLFetcher> fetcher,
- TextCheckCompleteCallback&& callback,
+ TextCheckCompleteCallback callback,
base::string16 text);
~TextCheckCallbackData();
@@ -111,6 +112,9 @@ class SpellingServiceClient : public net::URLFetcherDelegate {
// The text checked by the Spelling service.
base::string16 text;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextCheckCallbackData);
};
// net::URLFetcherDelegate implementation.
diff --git a/chromium/components/spellcheck/common/BUILD.gn b/chromium/components/spellcheck/common/BUILD.gn
index cac33a0394f..ad6a9cf9864 100644
--- a/chromium/components/spellcheck/common/BUILD.gn
+++ b/chromium/components/spellcheck/common/BUILD.gn
@@ -11,9 +11,6 @@ source_set("common") {
"spellcheck_common.h",
"spellcheck_features.cc",
"spellcheck_features.h",
- "spellcheck_message_generator.cc",
- "spellcheck_message_generator.h",
- "spellcheck_messages.h",
"spellcheck_result.cc",
"spellcheck_result.h",
"spellcheck_struct_traits.cc",
@@ -46,4 +43,11 @@ mojom("interfaces") {
public_deps = [
"//mojo/common:common_custom_types",
]
+
+ enabled_features = []
+ if (use_browser_spellchecker) {
+ enabled_features += [ "USE_BROWSER_SPELLCHECKER" ]
+ } else {
+ enabled_features += [ "USE_RENDERER_SPELLCHECKER" ]
+ }
}
diff --git a/chromium/components/spellcheck/common/DEPS b/chromium/components/spellcheck/common/DEPS
index 1c40d981eb6..9ae30d0ed41 100644
--- a/chromium/components/spellcheck/common/DEPS
+++ b/chromium/components/spellcheck/common/DEPS
@@ -1,3 +1,4 @@
include_rules = [
"+ipc",
+ "+mojo/public",
]
diff --git a/chromium/components/spellcheck/common/spellcheck.mojom b/chromium/components/spellcheck/common/spellcheck.mojom
index 2475c1c06dd..f3caeb82d18 100644
--- a/chromium/components/spellcheck/common/spellcheck.mojom
+++ b/chromium/components/spellcheck/common/spellcheck.mojom
@@ -5,7 +5,7 @@
module spellcheck.mojom;
import "mojo/common/file.mojom";
-import "mojo/common/string16.mojom";
+import "mojo/public/mojom/base/string16.mojom";
// Render process interface exposed to the browser for receiving process-
// wide spellcheck control and updates from the browser process.
@@ -40,14 +40,40 @@ interface SpellCheckHost {
// Tracks spell checking occurrences to collect histograms, where |word|
// was checked, and |misspelled| is true if |word| was misspelt.
- NotifyChecked(mojo.common.mojom.String16 word, bool misspelled);
+ NotifyChecked(mojo_base.mojom.String16 word, bool misspelled);
// Asks the host to spellcheck the |text| using a remote Spelling server
// to do the spellchecking. If the remote Spelling server is available,
- // returns |success| true, and the spellchecked |results|. Note this API
- // requires a !BUILDFLAG(USE_BROWSER_SPELLCHECKER) build.
- CallSpellingService(mojo.common.mojom.String16 text) =>
+ // returns |success| true, and the spellchecked |results|.
+ [EnableIf=USE_RENDERER_SPELLCHECKER]
+ CallSpellingService(mojo_base.mojom.String16 text) =>
(bool success, array<SpellCheckResult> results);
+
+ // Asks the host to spellcheck the |text| using a platform-specific spell
+ // checker, and returns the spellchecked |results|.
+ // TODO(crbug.com/812959): Try not to pass |route_id|. What SpellCheckHost
+ // needs is the render frame id, which should be passed in a cleaner way.
+ [EnableIf=USE_BROWSER_SPELLCHECKER]
+ RequestTextCheck(mojo_base.mojom.String16 text, int32 route_id) =>
+ (array<SpellCheckResult> results);
+
+ // Toggles the enabled state of the platform-specific spell checker.
+ [EnableIf=USE_BROWSER_SPELLCHECKER]
+ ToggleSpellCheck(bool enabled, bool checked);
+
+ // Checks the correctness of a word with a platform-specific spell checker.
+ // TODO(groby): This needs to originate from SpellcheckProvider.
+ // TODO(crbug.com/812959): Try not to pass |route_id|. What SpellCheckHost
+ // needs is the render frame id, which should be passed in a cleaner way.
+ [EnableIf=USE_BROWSER_SPELLCHECKER, Sync]
+ CheckSpelling(mojo_base.mojom.String16 word, int32 route_id)
+ => (bool correct);
+
+ // Returns a list of suggestions for a given word with a platform-specific
+ // spell checker.
+ [EnableIf=USE_BROWSER_SPELLCHECKER, Sync]
+ FillSuggestionList(mojo_base.mojom.String16 word) =>
+ (array<mojo_base.mojom.String16> suggestions);
};
enum Decoration {
@@ -59,5 +85,5 @@ struct SpellCheckResult {
Decoration decoration;
int32 location;
int32 length;
- array<string> replacements;
+ array<mojo_base.mojom.String16> replacements;
};
diff --git a/chromium/components/spellcheck/common/spellcheck_common.cc b/chromium/components/spellcheck/common/spellcheck_common.cc
index ccd7ada59b8..2523bdde478 100644
--- a/chromium/components/spellcheck/common/spellcheck_common.cc
+++ b/chromium/components/spellcheck/common/spellcheck_common.cc
@@ -36,7 +36,7 @@ static constexpr LanguageRegion kSupportedSpellCheckerLanguages[] = {
{"da", "da-DK"},
{"de", "de-DE"},
{"el", "el-GR"},
- {"en-AU", "en-GB"},
+ {"en-AU", "en-AU"},
{"en-CA", "en-CA"},
{"en-GB", "en-GB"},
{"en-US", "en-US"},
@@ -89,16 +89,16 @@ bool IsValidRegion(const std::string& region) {
// This function returns the language-region version of language name.
// e.g. returns hi-IN for hi.
-std::string GetSpellCheckLanguageRegion(const std::string& input_language) {
+std::string GetSpellCheckLanguageRegion(base::StringPiece input_language) {
for (const auto& lang_region : kSupportedSpellCheckerLanguages) {
if (lang_region.language == input_language)
- return std::string(lang_region.language_region);
+ return lang_region.language_region;
}
- return input_language;
+ return input_language.as_string();
}
-base::FilePath GetVersionedFileName(const std::string& input_language,
+base::FilePath GetVersionedFileName(base::StringPiece input_language,
const base::FilePath& dict_dir) {
// The default dictionary version is 3-0. This version indicates that the bdic
// file contains a checksum.
@@ -138,13 +138,13 @@ base::FilePath GetVersionedFileName(const std::string& input_language,
return dict_dir.AppendASCII(versioned_bdict_file_name);
}
-std::string GetCorrespondingSpellCheckLanguage(const std::string& language) {
+std::string GetCorrespondingSpellCheckLanguage(base::StringPiece language) {
std::string best_match;
// Look for exact match in the Spell Check language list.
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;
+ return language.as_string();
// 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/common/spellcheck_common.h b/chromium/components/spellcheck/common/spellcheck_common.h
index 364a236ef5c..10ab733d164 100644
--- a/chromium/components/spellcheck/common/spellcheck_common.h
+++ b/chromium/components/spellcheck/common/spellcheck_common.h
@@ -10,6 +10,8 @@
#include <string>
#include <vector>
+#include "base/strings/string_piece.h"
+
namespace base {
class FilePath;
}
@@ -21,14 +23,14 @@ static const int kMaxSuggestions = 5;
// Maximum number of words in the custom spellcheck dictionary that can be
// synced.
-static const size_t MAX_SYNCABLE_DICTIONARY_WORDS = 1300;
+static const size_t kMaxSyncableDictionaryWords = 1300;
// Maximum number of bytes in a word that can be added to the custom spellcheck
// dictionary. When changing this value, also change the corresponding value in
-// /src/chrome/browser/resources/settings/languages_page/edit_dictionary_page.js
-static const size_t MAX_CUSTOM_DICTIONARY_WORD_BYTES = 99;
+// chrome/browser/resources/settings/languages_page/edit_dictionary_page.js
+static const size_t kMaxCustomDictionaryWordBytes = 99;
-base::FilePath GetVersionedFileName(const std::string& input_language,
+base::FilePath GetVersionedFileName(base::StringPiece input_language,
const base::FilePath& dict_dir);
// Returns the spellcheck language that should be used for |language|. For
@@ -39,7 +41,7 @@ base::FilePath GetVersionedFileName(const std::string& input_language,
// Returns an empty string if no spellcheck language found. For example, there's
// no single dictionary for English, so this function returns an empty string
// for "en".
-std::string GetCorrespondingSpellCheckLanguage(const std::string& language);
+std::string GetCorrespondingSpellCheckLanguage(base::StringPiece language);
// Get SpellChecker supported languages.
std::vector<std::string> SpellCheckLanguages();
diff --git a/chromium/components/spellcheck/common/spellcheck_message_generator.cc b/chromium/components/spellcheck/common/spellcheck_message_generator.cc
deleted file mode 100644
index f4096f6202a..00000000000
--- a/chromium/components/spellcheck/common/spellcheck_message_generator.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Get basic type definitions.
-#define IPC_MESSAGE_IMPL
-#include "components/spellcheck/common/spellcheck_message_generator.h"
-
-// Generate constructors.
-#include "ipc/struct_constructor_macros.h"
-#include "components/spellcheck/common/spellcheck_message_generator.h"
-
-// Generate destructors.
-#include "ipc/struct_destructor_macros.h"
-#include "components/spellcheck/common/spellcheck_message_generator.h"
-
-// Generate param traits write methods.
-#include "ipc/param_traits_write_macros.h"
-namespace IPC {
-#include "components/spellcheck/common/spellcheck_message_generator.h"
-} // namespace IPC
-
-// Generate param traits read methods.
-#include "ipc/param_traits_read_macros.h"
-namespace IPC {
-#include "components/spellcheck/common/spellcheck_message_generator.h"
-} // namespace IPC
-
-// Generate param traits log methods.
-#include "ipc/param_traits_log_macros.h"
-namespace IPC {
-#include "components/spellcheck/common/spellcheck_message_generator.h"
-} // namespace IPC
diff --git a/chromium/components/spellcheck/common/spellcheck_message_generator.h b/chromium/components/spellcheck/common/spellcheck_message_generator.h
deleted file mode 100644
index ccd76dd0e25..00000000000
--- a/chromium/components/spellcheck/common/spellcheck_message_generator.h
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Multiply-included file, hence no include guard.
-
-#include "components/spellcheck/spellcheck_build_features.h"
-
-#if BUILDFLAG(ENABLE_SPELLCHECK)
-#include "components/spellcheck/common/spellcheck_messages.h"
-#endif
diff --git a/chromium/components/spellcheck/common/spellcheck_messages.h b/chromium/components/spellcheck/common/spellcheck_messages.h
deleted file mode 100644
index c2952701d35..00000000000
--- a/chromium/components/spellcheck/common/spellcheck_messages.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// IPC messages for spellcheck.
-// Multiply-included message file, hence no include guard.
-
-#include <stdint.h>
-
-#include "components/spellcheck/common/spellcheck_result.h"
-#include "components/spellcheck/spellcheck_build_features.h"
-#include "ipc/ipc_message_macros.h"
-
-#if !BUILDFLAG(ENABLE_SPELLCHECK)
-#error "Spellcheck should be enabled."
-#endif
-
-#define IPC_MESSAGE_START SpellCheckMsgStart
-
-IPC_ENUM_TRAITS_MAX_VALUE(SpellCheckResult::Decoration, SpellCheckResult::LAST)
-
-IPC_STRUCT_TRAITS_BEGIN(SpellCheckResult)
- IPC_STRUCT_TRAITS_MEMBER(decoration)
- IPC_STRUCT_TRAITS_MEMBER(location)
- IPC_STRUCT_TRAITS_MEMBER(length)
- IPC_STRUCT_TRAITS_MEMBER(replacements)
-IPC_STRUCT_TRAITS_END()
-
-// Messages sent from the browser to the renderer.
-
-#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
-// Sends when NSSpellChecker finishes checking text received by a preceding
-// SpellCheckHostMsg_RequestTextCheck message.
-IPC_MESSAGE_ROUTED3(SpellCheckMsg_RespondTextCheck,
- int /* request identifier given by WebKit */,
- base::string16 /* sentence */,
- std::vector<SpellCheckResult>)
-#endif
-
-// Messages sent from the renderer to the browser.
-
-#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
-// TODO(groby): This needs to originate from SpellcheckProvider.
-IPC_SYNC_MESSAGE_CONTROL2_1(SpellCheckHostMsg_CheckSpelling,
- base::string16 /* word */,
- int /* route_id */,
- bool /* correct */)
-
-IPC_SYNC_MESSAGE_CONTROL1_1(SpellCheckHostMsg_FillSuggestionList,
- base::string16 /* word */,
- std::vector<base::string16> /* suggestions */)
-
-IPC_MESSAGE_CONTROL3(SpellCheckHostMsg_RequestTextCheck,
- int /* route_id for response */,
- int /* request identifier given by WebKit */,
- base::string16 /* sentence */)
-
-IPC_MESSAGE_ROUTED2(SpellCheckHostMsg_ToggleSpellCheck,
- bool /* enabled */,
- bool /* checked */)
-#endif // USE_BROWSER_SPELLCHECKER
diff --git a/chromium/components/spellcheck/common/spellcheck_panel.mojom b/chromium/components/spellcheck/common/spellcheck_panel.mojom
index f50096bceb6..4808379b695 100644
--- a/chromium/components/spellcheck/common/spellcheck_panel.mojom
+++ b/chromium/components/spellcheck/common/spellcheck_panel.mojom
@@ -4,7 +4,7 @@
module spellcheck.mojom;
-import "mojo/common/string16.mojom";
+import "mojo/public/mojom/base/string16.mojom";
// Render frame interface exposed to the browser for sending messages when
// the OSX BUILDFLAG(HAS_SPELLCHECK_PANEL) spelling and grammar checking
@@ -31,5 +31,5 @@ interface SpellCheckPanelHost {
ShowSpellingPanel(bool show);
// Tells the browser to update the spelling panel with the given |word|.
- UpdateSpellingPanelWithMisspelledWord(mojo.common.mojom.String16 word);
+ UpdateSpellingPanelWithMisspelledWord(mojo_base.mojom.String16 word);
};
diff --git a/chromium/components/spellcheck/common/spellcheck_result.h b/chromium/components/spellcheck/common/spellcheck_result.h
index 5ee9cfdd7b4..db875d2fe6c 100644
--- a/chromium/components/spellcheck/common/spellcheck_result.h
+++ b/chromium/components/spellcheck/common/spellcheck_result.h
@@ -24,7 +24,6 @@ struct SpellCheckResult {
LAST = GRAMMAR,
};
- // Default values are so we have a default constructor for IPC::ReadParam()
explicit SpellCheckResult(
Decoration d = SPELLING,
int loc = 0,
diff --git a/chromium/components/spellcheck/common/spellcheck_struct_traits.cc b/chromium/components/spellcheck/common/spellcheck_struct_traits.cc
index 5b8e5042419..2f0c4efc373 100644
--- a/chromium/components/spellcheck/common/spellcheck_struct_traits.cc
+++ b/chromium/components/spellcheck/common/spellcheck_struct_traits.cc
@@ -4,6 +4,8 @@
#include "components/spellcheck/common/spellcheck_struct_traits.h"
+#include "mojo/public/cpp/base/string16_mojom_traits.h"
+
namespace mojo {
spellcheck::mojom::Decoration
diff --git a/chromium/components/spellcheck/renderer/BUILD.gn b/chromium/components/spellcheck/renderer/BUILD.gn
index 96c1cb91a78..0d0fa0071dd 100644
--- a/chromium/components/spellcheck/renderer/BUILD.gn
+++ b/chromium/components/spellcheck/renderer/BUILD.gn
@@ -67,6 +67,8 @@ source_set("unit_tests") {
testonly = true
sources = [
"custom_dictionary_engine_unittest.cc",
+ "empty_local_interface_provider.cc",
+ "empty_local_interface_provider.h",
"spellcheck_provider_mac_unittest.cc",
"spellcheck_provider_test.cc",
"spellcheck_provider_test.h",
@@ -92,6 +94,7 @@ source_set("unit_tests") {
deps = [
":renderer",
"//base:i18n",
+ "//base/test:test_support",
"//components/spellcheck/common",
"//ipc:ipc",
"//testing/gtest",
diff --git a/chromium/components/spellcheck/renderer/empty_local_interface_provider.cc b/chromium/components/spellcheck/renderer/empty_local_interface_provider.cc
new file mode 100644
index 00000000000..c40df97dfaa
--- /dev/null
+++ b/chromium/components/spellcheck/renderer/empty_local_interface_provider.cc
@@ -0,0 +1,13 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/spellcheck/renderer/empty_local_interface_provider.h"
+
+namespace spellcheck {
+
+void EmptyLocalInterfaceProvider::GetInterface(
+ const std::string& name,
+ mojo::ScopedMessagePipeHandle request_handle) {}
+
+} // namespace spellcheck
diff --git a/chromium/components/spellcheck/renderer/empty_local_interface_provider.h b/chromium/components/spellcheck/renderer/empty_local_interface_provider.h
new file mode 100644
index 00000000000..9fe12c4d2d6
--- /dev/null
+++ b/chromium/components/spellcheck/renderer/empty_local_interface_provider.h
@@ -0,0 +1,24 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SPELLCHECK_EMPTY_LOCAL_INTERFACE_PROVIDER_H_
+#define COMPONENTS_SPELLCHECK_EMPTY_LOCAL_INTERFACE_PROVIDER_H_
+
+#include "services/service_manager/public/cpp/local_interface_provider.h"
+
+namespace spellcheck {
+
+// A dummy LocalInterfaceProvider that doesn't bind any remote application.
+// May require a base::test::ScopedTaskEnvironment if GetInterface() is expected
+// to be called.
+class EmptyLocalInterfaceProvider
+ : public service_manager::LocalInterfaceProvider {
+ public:
+ void GetInterface(const std::string& name,
+ mojo::ScopedMessagePipeHandle request_handle) override;
+};
+
+} // namespace spellcheck
+
+#endif // COMPONENTS_SPELLCHECK_EMPTY_LOCAL_INTERFACE_PROVIDER_H_
diff --git a/chromium/components/spellcheck/renderer/hunspell_engine.cc b/chromium/components/spellcheck/renderer/hunspell_engine.cc
index fd9383f56fb..f7080e5e8ef 100644
--- a/chromium/components/spellcheck/renderer/hunspell_engine.cc
+++ b/chromium/components/spellcheck/renderer/hunspell_engine.cc
@@ -39,6 +39,7 @@ namespace {
#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
SpellingEngine* CreateNativeSpellingEngine(
service_manager::LocalInterfaceProvider* embedder_provider) {
+ DCHECK(embedder_provider);
return new HunspellEngine(embedder_provider);
}
#endif
@@ -123,12 +124,9 @@ void HunspellEngine::FillSuggestionList(
bool HunspellEngine::InitializeIfNeeded() {
if (!initialized_ && !dictionary_requested_) {
- // |embedder_provider_| will be nullptr in tests.
- if (embedder_provider_) {
- spellcheck::mojom::SpellCheckHostPtr spell_check_host;
- embedder_provider_->GetInterface(&spell_check_host);
- spell_check_host->RequestDictionary();
- }
+ spellcheck::mojom::SpellCheckHostPtr spell_check_host;
+ embedder_provider_->GetInterface(&spell_check_host);
+ spell_check_host->RequestDictionary();
dictionary_requested_ = true;
return true;
}
diff --git a/chromium/components/spellcheck/renderer/platform_spelling_engine.cc b/chromium/components/spellcheck/renderer/platform_spelling_engine.cc
index e351edceedc..2828538a14b 100644
--- a/chromium/components/spellcheck/renderer/platform_spelling_engine.cc
+++ b/chromium/components/spellcheck/renderer/platform_spelling_engine.cc
@@ -4,14 +4,30 @@
#include "components/spellcheck/renderer/platform_spelling_engine.h"
-#include "components/spellcheck/common/spellcheck_messages.h"
#include "content/public/renderer/render_thread.h"
+#include "services/service_manager/public/cpp/local_interface_provider.h"
using content::RenderThread;
SpellingEngine* CreateNativeSpellingEngine(
service_manager::LocalInterfaceProvider* embedder_provider) {
- return new PlatformSpellingEngine();
+ DCHECK(embedder_provider);
+ return new PlatformSpellingEngine(embedder_provider);
+}
+
+PlatformSpellingEngine::PlatformSpellingEngine(
+ service_manager::LocalInterfaceProvider* embedder_provider)
+ : embedder_provider_(embedder_provider) {}
+
+PlatformSpellingEngine::~PlatformSpellingEngine() = default;
+
+spellcheck::mojom::SpellCheckHost&
+PlatformSpellingEngine::GetOrBindSpellCheckHost() {
+ if (spell_check_host_)
+ return *spell_check_host_;
+
+ embedder_provider_->GetInterface(&spell_check_host_);
+ return *spell_check_host_;
}
void PlatformSpellingEngine::Init(base::File bdict_file) {
@@ -32,8 +48,7 @@ bool PlatformSpellingEngine::IsEnabled() {
bool PlatformSpellingEngine::CheckSpelling(const base::string16& word_to_check,
int tag) {
bool word_correct = false;
- RenderThread::Get()->Send(new SpellCheckHostMsg_CheckSpelling(
- word_to_check, tag, &word_correct));
+ GetOrBindSpellCheckHost().CheckSpelling(word_to_check, tag, &word_correct);
return word_correct;
}
@@ -43,6 +58,6 @@ bool PlatformSpellingEngine::CheckSpelling(const base::string16& word_to_check,
void PlatformSpellingEngine::FillSuggestionList(
const base::string16& wrong_word,
std::vector<base::string16>* optional_suggestions) {
- RenderThread::Get()->Send(new SpellCheckHostMsg_FillSuggestionList(
- wrong_word, optional_suggestions));
+ GetOrBindSpellCheckHost().FillSuggestionList(wrong_word,
+ optional_suggestions);
}
diff --git a/chromium/components/spellcheck/renderer/platform_spelling_engine.h b/chromium/components/spellcheck/renderer/platform_spelling_engine.h
index 294d826258f..fa2b04d104d 100644
--- a/chromium/components/spellcheck/renderer/platform_spelling_engine.h
+++ b/chromium/components/spellcheck/renderer/platform_spelling_engine.h
@@ -6,10 +6,15 @@
#define COMPONENTS_SPELLCHECK_RENDERER_PLATFORM_SPELLING_ENGINE_H_
#include "base/compiler_specific.h"
+#include "components/spellcheck/common/spellcheck.mojom.h"
#include "components/spellcheck/renderer/spelling_engine.h"
class PlatformSpellingEngine : public SpellingEngine {
public:
+ explicit PlatformSpellingEngine(
+ service_manager::LocalInterfaceProvider* embedder_provider);
+ ~PlatformSpellingEngine() override;
+
void Init(base::File bdict_file) override;
bool InitializeIfNeeded() override;
bool IsEnabled() override;
@@ -17,6 +22,14 @@ class PlatformSpellingEngine : public SpellingEngine {
void FillSuggestionList(
const base::string16& wrong_word,
std::vector<base::string16>* optional_suggestions) override;
+
+ private:
+ spellcheck::mojom::SpellCheckHost& GetOrBindSpellCheckHost();
+
+ // Not owned. |embedder_provider_| outlives PlatformSpellingEngine.
+ service_manager::LocalInterfaceProvider* embedder_provider_;
+
+ spellcheck::mojom::SpellCheckHostPtr spell_check_host_;
};
#endif // COMPONENTS_SPELLCHECK_RENDERER_PLATFORM_SPELLING_ENGINE_H_
diff --git a/chromium/components/spellcheck/renderer/spellcheck.cc b/chromium/components/spellcheck/renderer/spellcheck.cc
index 387beca7edc..3c0016d394b 100644
--- a/chromium/components/spellcheck/renderer/spellcheck.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -30,7 +31,6 @@
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_frame_visitor.h"
#include "content/public/renderer/render_thread.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
@@ -171,22 +171,17 @@ class SpellCheck::SpellcheckRequest {
// values.
// TODO(groby): Simplify this.
SpellCheck::SpellCheck(
+ service_manager::BinderRegistry* registry,
service_manager::LocalInterfaceProvider* embedder_provider)
- : embedder_provider_(embedder_provider), spellcheck_enabled_(true) {
- if (!content::ChildThread::Get())
+ : embedder_provider_(embedder_provider),
+ spellcheck_enabled_(true),
+ weak_factory_(this) {
+ DCHECK(embedder_provider);
+ if (!registry)
return; // Can be NULL in tests.
-
- auto* service_manager_connection =
- content::ChildThread::Get()->GetServiceManagerConnection();
- DCHECK(service_manager_connection);
-
- auto registry = base::MakeUnique<service_manager::BinderRegistry>();
registry->AddInterface(base::BindRepeating(&SpellCheck::SpellCheckerRequest,
- base::Unretained(this)),
+ weak_factory_.GetWeakPtr()),
base::ThreadTaskRunnerHandle::Get());
-
- service_manager_connection->AddConnectionFilter(
- base::MakeUnique<content::SimpleConnectionFilter>(std::move(registry)));
}
SpellCheck::~SpellCheck() {
@@ -265,7 +260,7 @@ void SpellCheck::CustomDictionaryChanged(
void SpellCheck::AddSpellcheckLanguage(base::File file,
const std::string& language) {
languages_.push_back(
- base::MakeUnique<SpellcheckLanguage>(embedder_provider_));
+ std::make_unique<SpellcheckLanguage>(embedder_provider_));
languages_.back()->Init(std::move(file), language);
}
diff --git a/chromium/components/spellcheck/renderer/spellcheck.h b/chromium/components/spellcheck/renderer/spellcheck.h
index b7ec4aa7f80..630b47998cf 100644
--- a/chromium/components/spellcheck/renderer/spellcheck.h
+++ b/chromium/components/spellcheck/renderer/spellcheck.h
@@ -18,8 +18,8 @@
#include "components/spellcheck/common/spellcheck.mojom.h"
#include "components/spellcheck/renderer/custom_dictionary_engine.h"
#include "components/spellcheck/spellcheck_build_features.h"
-#include "content/public/renderer/render_thread_observer.h"
#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
class SpellcheckLanguage;
struct SpellCheckResult;
@@ -38,8 +38,7 @@ class LocalInterfaceProvider;
// See http://crbug.com/73699.
// Shared spellchecking logic/data for a RenderProcess. All RenderViews use
// this object to perform spellchecking tasks.
-class SpellCheck : public content::RenderThreadObserver,
- public base::SupportsWeakPtr<SpellCheck>,
+class SpellCheck : public base::SupportsWeakPtr<SpellCheck>,
public spellcheck::mojom::SpellChecker {
public:
// TODO(groby): I wonder if this can be private, non-mac only.
@@ -49,8 +48,8 @@ class SpellCheck : public content::RenderThreadObserver,
USE_NATIVE_CHECKER, // Use native checker to double-check.
};
- explicit SpellCheck(
- service_manager::LocalInterfaceProvider* embedder_provider);
+ SpellCheck(service_manager::BinderRegistry* registry,
+ service_manager::LocalInterfaceProvider* embedder_provider);
~SpellCheck() override;
void AddSpellcheckLanguage(base::File file, const std::string& language);
@@ -167,6 +166,8 @@ class SpellCheck : public content::RenderThreadObserver,
// Remember state for spellchecking.
bool spellcheck_enabled_;
+ base::WeakPtrFactory<SpellCheck> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(SpellCheck);
};
diff --git a/chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc b/chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
index 3dd2a5c356c..0b37828668d 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
@@ -14,8 +14,10 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "components/spellcheck/common/spellcheck_result.h"
+#include "components/spellcheck/renderer/empty_local_interface_provider.h"
#include "components/spellcheck/renderer/spellcheck.h"
#include "components/spellcheck/renderer/spellcheck_provider_test.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -50,8 +52,9 @@ class MultilingualSpellCheckTest : public testing::Test {
MultilingualSpellCheckTest() {}
void ReinitializeSpellCheck(const std::string& unsplit_languages) {
- spellcheck_ = new SpellCheck(nullptr);
- provider_.reset(new TestingSpellCheckProvider(spellcheck_));
+ spellcheck_ = new SpellCheck(nullptr, &embedder_provider_);
+ provider_.reset(
+ new TestingSpellCheckProvider(spellcheck_, &embedder_provider_));
InitializeSpellCheck(unsplit_languages);
}
@@ -111,6 +114,9 @@ class MultilingualSpellCheckTest : public testing::Test {
}
private:
+ base::test::ScopedTaskEnvironment task_environment_;
+ spellcheck::EmptyLocalInterfaceProvider embedder_provider_;
+
// Owned by |provider_|.
SpellCheck* spellcheck_;
std::unique_ptr<TestingSpellCheckProvider> provider_;
diff --git a/chromium/components/spellcheck/renderer/spellcheck_panel.cc b/chromium/components/spellcheck/renderer/spellcheck_panel.cc
index 4aebd5a1aad..c8010bdf7c5 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_panel.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck_panel.cc
@@ -21,6 +21,7 @@ SpellCheckPanel::SpellCheckPanel(
spelling_panel_visible_(false),
embedder_provider_(embedder_provider) {
DCHECK(render_frame);
+ DCHECK(embedder_provider);
registry->AddInterface(base::BindRepeating(
&SpellCheckPanel::SpellCheckPanelRequest, base::Unretained(this)));
render_frame->GetWebFrame()->SetSpellCheckPanelHostClient(this);
@@ -64,7 +65,7 @@ void SpellCheckPanel::ToggleSpellPanel(bool visible) {
DCHECK(render_frame->GetWebFrame());
// Tell our frame whether the spelling panel is visible or not so
- // that it won't need to make ipc calls later.
+ // that it won't need to make mojo calls later.
spelling_panel_visible_ = visible;
render_frame->GetWebFrame()->ExecuteCommand(
diff --git a/chromium/components/spellcheck/renderer/spellcheck_provider.cc b/chromium/components/spellcheck/renderer/spellcheck_provider.cc
index 54e0d03dc9a..94b4fb93992 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_provider.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck_provider.cc
@@ -7,7 +7,6 @@
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "components/spellcheck/common/spellcheck.mojom.h"
-#include "components/spellcheck/common/spellcheck_messages.h"
#include "components/spellcheck/common/spellcheck_result.h"
#include "components/spellcheck/renderer/spellcheck.h"
#include "components/spellcheck/renderer/spellcheck_language.h"
@@ -46,8 +45,10 @@ SpellCheckProvider::SpellCheckProvider(
: content::RenderFrameObserver(render_frame),
content::RenderFrameObserverTracker<SpellCheckProvider>(render_frame),
spellcheck_(spellcheck),
- embedder_provider_(embedder_provider) {
+ embedder_provider_(embedder_provider),
+ weak_factory_(this) {
DCHECK(spellcheck_);
+ DCHECK(embedder_provider);
if (render_frame) // NULL in unit tests.
render_frame->GetWebFrame()->SetTextCheckClient(this);
}
@@ -59,9 +60,7 @@ spellcheck::mojom::SpellCheckHost& SpellCheckProvider::GetSpellCheckHost() {
if (spell_check_host_)
return *spell_check_host_;
- // nullptr in tests.
- if (embedder_provider_)
- embedder_provider_->GetInterface(&spell_check_host_);
+ embedder_provider_->GetInterface(&spell_check_host_);
return *spell_check_host_;
}
@@ -85,35 +84,20 @@ void SpellCheckProvider::RequestTextChecking(
last_identifier_ = text_check_completions_.Add(completion);
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
- // TODO(crbug.com/714480): convert the RequestTextCheck IPC to mojo.
// Text check (unified request for grammar and spell check) is only
// available for browser process, so we ask the system spellchecker
- // over IPC or return an empty result if the checker is not available.
- Send(new SpellCheckHostMsg_RequestTextCheck(routing_id(), last_identifier_,
- text));
+ // over mojo or return an empty result if the checker is not available.
+ GetSpellCheckHost().RequestTextCheck(
+ text, routing_id(),
+ base::BindOnce(&SpellCheckProvider::OnRespondTextCheck,
+ weak_factory_.GetWeakPtr(), last_identifier_, text));
#else
- if (!spell_check_host_ && !content::RenderThread::Get())
- return; // NULL in tests that do not provide a spell_check_host_.
GetSpellCheckHost().CallSpellingService(
text, base::BindOnce(&SpellCheckProvider::OnRespondSpellingService,
- base::Unretained(this), last_identifier_, text));
+ weak_factory_.GetWeakPtr(), last_identifier_, text));
#endif // !USE_BROWSER_SPELLCHECKER
}
-bool SpellCheckProvider::OnMessageReceived(const IPC::Message& message) {
-#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(SpellCheckProvider, message)
- // TODO(crbug.com/714480): convert the RequestTextCheck IPC to mojo.
- IPC_MESSAGE_HANDLER(SpellCheckMsg_RespondTextCheck, OnRespondTextCheck)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-#else
- return false;
-#endif
-}
-
void SpellCheckProvider::FocusedNodeChanged(const blink::WebNode& unused) {
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
WebLocalFrame* frame = render_frame()->GetWebFrame();
@@ -122,9 +106,7 @@ void SpellCheckProvider::FocusedNodeChanged(const blink::WebNode& unused) {
: frame->GetDocument().FocusedElement();
bool enabled = !element.IsNull() && element.IsEditable();
bool checked = enabled && IsSpellCheckingEnabled();
-
- // TODO(crbug.com/714480): convert the ToggleSpellCheck IPC to mojo.
- Send(new SpellCheckHostMsg_ToggleSpellCheck(routing_id(), enabled, checked));
+ GetSpellCheckHost().ToggleSpellCheck(enabled, checked);
#endif // USE_BROWSER_SPELLCHECKER
}
@@ -154,8 +136,6 @@ void SpellCheckProvider::CheckSpelling(
UMA_HISTOGRAM_COUNTS("SpellCheck.api.check", word.size());
// If optional_suggestions is not requested, the API is called
// for marking. So we use this for counting markable words.
- if (!spell_check_host_ && !content::RenderThread::Get())
- return; // NULL in tests that do not provide a spell_check_host_.
GetSpellCheckHost().NotifyChecked(word, 0 < length);
}
}
diff --git a/chromium/components/spellcheck/renderer/spellcheck_provider.h b/chromium/components/spellcheck/renderer/spellcheck_provider.h
index 8a4260eed5e..c82bef364e7 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_provider.h
+++ b/chromium/components/spellcheck/renderer/spellcheck_provider.h
@@ -59,7 +59,6 @@ class SpellCheckProvider
void set_spellcheck(SpellCheck* spellcheck) { spellcheck_ = spellcheck; }
// content::RenderFrameObserver:
- bool OnMessageReceived(const IPC::Message& message) override;
void FocusedNodeChanged(const blink::WebNode& node) override;
private:
@@ -124,11 +123,14 @@ class SpellCheckProvider
// Weak pointer to shared (per renderer) spellcheck data.
SpellCheck* spellcheck_;
+ // Not owned. |embedder_provider_| should outlive SpellCheckProvider.
service_manager::LocalInterfaceProvider* embedder_provider_;
// Interface to the SpellCheckHost.
spellcheck::mojom::SpellCheckHostPtr spell_check_host_;
+ base::WeakPtrFactory<SpellCheckProvider> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(SpellCheckProvider);
};
diff --git a/chromium/components/spellcheck/renderer/spellcheck_provider_mac_unittest.cc b/chromium/components/spellcheck/renderer/spellcheck_provider_mac_unittest.cc
index 44d0f117da9..b92aab3cac5 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_provider_mac_unittest.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck_provider_mac_unittest.cc
@@ -5,8 +5,8 @@
#include <tuple>
#include <vector>
+#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
-#include "components/spellcheck/common/spellcheck_messages.h"
#include "components/spellcheck/common/spellcheck_result.h"
#include "components/spellcheck/renderer/spellcheck_provider_test.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -15,36 +15,27 @@ namespace {
class SpellCheckProviderMacTest : public SpellCheckProviderTest {};
-void FakeMessageArrival(
- SpellCheckProvider* provider,
- const SpellCheckHostMsg_RequestTextCheck::Param& parameters) {
- std::vector<SpellCheckResult> fake_result;
- bool handled = provider->OnMessageReceived(
- SpellCheckMsg_RespondTextCheck(
- 0,
- std::get<1>(parameters),
- base::ASCIIToUTF16("test"),
- fake_result));
- EXPECT_TRUE(handled);
-}
-
TEST_F(SpellCheckProviderMacTest, SingleRoundtripSuccess) {
FakeTextCheckingCompletion completion;
provider_.RequestTextChecking(base::ASCIIToUTF16("hello "), &completion);
EXPECT_EQ(completion.completion_count_, 0U);
- EXPECT_EQ(provider_.messages_.size(), 1U);
+ EXPECT_EQ(provider_.text_check_requests_.size(), 1U);
EXPECT_EQ(provider_.pending_text_request_size(), 1U);
- SpellCheckHostMsg_RequestTextCheck::Param read_parameters1;
- bool ok = SpellCheckHostMsg_RequestTextCheck::Read(
- provider_.messages_[0].get(), &read_parameters1);
- EXPECT_TRUE(ok);
- EXPECT_EQ(std::get<2>(read_parameters1), base::ASCIIToUTF16("hello "));
+ const auto& text = provider_.text_check_requests_.back().first;
+ auto& callback = provider_.text_check_requests_.back().second;
+ EXPECT_EQ(text, base::ASCIIToUTF16("hello "));
+ EXPECT_TRUE(callback);
+
+ std::vector<SpellCheckResult> fake_results;
+ std::move(callback).Run(fake_results);
+ base::RunLoop().RunUntilIdle();
- FakeMessageArrival(&provider_, read_parameters1);
EXPECT_EQ(completion.completion_count_, 1U);
EXPECT_EQ(provider_.pending_text_request_size(), 0U);
+
+ provider_.text_check_requests_.clear();
}
TEST_F(SpellCheckProviderMacTest, TwoRoundtripSuccess) {
@@ -55,30 +46,34 @@ TEST_F(SpellCheckProviderMacTest, TwoRoundtripSuccess) {
EXPECT_EQ(completion1.completion_count_, 0U);
EXPECT_EQ(completion2.completion_count_, 0U);
- EXPECT_EQ(provider_.messages_.size(), 2U);
+ EXPECT_EQ(provider_.text_check_requests_.size(), 2U);
EXPECT_EQ(provider_.pending_text_request_size(), 2U);
- SpellCheckHostMsg_RequestTextCheck::Param read_parameters1;
- bool ok = SpellCheckHostMsg_RequestTextCheck::Read(
- provider_.messages_[0].get(), &read_parameters1);
- EXPECT_TRUE(ok);
- EXPECT_EQ(std::get<2>(read_parameters1), base::UTF8ToUTF16("hello "));
+ const auto& text1 = provider_.text_check_requests_[0].first;
+ auto& callback1 = provider_.text_check_requests_[0].second;
+ EXPECT_EQ(text1, base::ASCIIToUTF16("hello "));
+ EXPECT_TRUE(callback1);
+
+ const auto& text2 = provider_.text_check_requests_[1].first;
+ auto& callback2 = provider_.text_check_requests_[1].second;
+ EXPECT_EQ(text2, base::ASCIIToUTF16("bye "));
+ EXPECT_TRUE(callback2);
- SpellCheckHostMsg_RequestTextCheck::Param read_parameters2;
- ok = SpellCheckHostMsg_RequestTextCheck::Read(provider_.messages_[1].get(),
- &read_parameters2);
- EXPECT_TRUE(ok);
- EXPECT_EQ(std::get<2>(read_parameters2), base::UTF8ToUTF16("bye "));
+ std::vector<SpellCheckResult> fake_results;
- FakeMessageArrival(&provider_, read_parameters1);
+ std::move(callback1).Run(fake_results);
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(completion1.completion_count_, 1U);
EXPECT_EQ(completion2.completion_count_, 0U);
EXPECT_EQ(provider_.pending_text_request_size(), 1U);
- FakeMessageArrival(&provider_, read_parameters2);
+ std::move(callback2).Run(fake_results);
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(completion1.completion_count_, 1U);
EXPECT_EQ(completion2.completion_count_, 1U);
EXPECT_EQ(provider_.pending_text_request_size(), 0U);
+
+ provider_.text_check_requests_.clear();
}
} // namespace
diff --git a/chromium/components/spellcheck/renderer/spellcheck_provider_test.cc b/chromium/components/spellcheck/renderer/spellcheck_provider_test.cc
index 779c881d68b..1d5fdf2c30a 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_provider_test.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck_provider_test.cc
@@ -4,6 +4,8 @@
#include "components/spellcheck/renderer/spellcheck_provider_test.h"
+#include <memory>
+
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
@@ -11,7 +13,6 @@
#include "components/spellcheck/common/spellcheck_result.h"
#include "components/spellcheck/renderer/spellcheck.h"
#include "components/spellcheck/spellcheck_build_features.h"
-#include "ipc/ipc_message.h"
FakeTextCheckingCompletion::FakeTextCheckingCompletion()
: completion_count_(0), cancellation_count_(0) {}
@@ -28,14 +29,17 @@ void FakeTextCheckingCompletion::DidCancelCheckingText() {
++cancellation_count_;
}
-TestingSpellCheckProvider::TestingSpellCheckProvider()
- : SpellCheckProvider(nullptr, new SpellCheck(nullptr), nullptr),
- spelling_service_call_count_(0),
+TestingSpellCheckProvider::TestingSpellCheckProvider(
+ service_manager::LocalInterfaceProvider* embedder_provider)
+ : SpellCheckProvider(nullptr,
+ new SpellCheck(nullptr, embedder_provider),
+ embedder_provider),
binding_(this) {}
-TestingSpellCheckProvider::TestingSpellCheckProvider(SpellCheck* spellcheck)
- : SpellCheckProvider(nullptr, spellcheck, nullptr),
- spelling_service_call_count_(0),
+TestingSpellCheckProvider::TestingSpellCheckProvider(
+ SpellCheck* spellcheck,
+ service_manager::LocalInterfaceProvider* embedder_provider)
+ : SpellCheckProvider(nullptr, spellcheck, embedder_provider),
binding_(this) {}
TestingSpellCheckProvider::~TestingSpellCheckProvider() {
@@ -46,9 +50,8 @@ TestingSpellCheckProvider::~TestingSpellCheckProvider() {
void TestingSpellCheckProvider::RequestTextChecking(
const base::string16& text,
blink::WebTextCheckingCompletion* completion) {
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
if (!loop_ && !base::MessageLoop::current())
- loop_ = base::MakeUnique<base::MessageLoop>();
+ loop_ = std::make_unique<base::MessageLoop>();
if (!binding_.is_bound()) {
spellcheck::mojom::SpellCheckHostPtr host_proxy;
binding_.Bind(mojo::MakeRequest(&host_proxy));
@@ -56,14 +59,6 @@ void TestingSpellCheckProvider::RequestTextChecking(
}
SpellCheckProvider::RequestTextChecking(text, completion);
base::RunLoop().RunUntilIdle();
-#else
- SpellCheckProvider::RequestTextChecking(text, completion);
-#endif
-}
-
-bool TestingSpellCheckProvider::Send(IPC::Message* message) {
- messages_.push_back(base::WrapUnique<IPC::Message>(message));
- return true;
}
void TestingSpellCheckProvider::RequestDictionary() {}
@@ -71,20 +66,16 @@ void TestingSpellCheckProvider::RequestDictionary() {}
void TestingSpellCheckProvider::NotifyChecked(const base::string16& word,
bool misspelled) {}
+#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
void TestingSpellCheckProvider::CallSpellingService(
const base::string16& text,
CallSpellingServiceCallback callback) {
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
OnCallSpellingService(text);
std::move(callback).Run(true, std::vector<SpellCheckResult>());
-#else
- NOTREACHED();
-#endif
}
void TestingSpellCheckProvider::OnCallSpellingService(
const base::string16& text) {
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
++spelling_service_call_count_;
blink::WebTextCheckingCompletion* completion =
text_check_completions_.Lookup(last_identifier_);
@@ -101,14 +92,36 @@ void TestingSpellCheckProvider::OnCallSpellingService(
completion->DidFinishCheckingText(results);
last_request_ = text;
last_results_ = results;
-#else
- NOTREACHED();
-#endif
}
void TestingSpellCheckProvider::ResetResult() {
text_.clear();
}
+#endif // !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+
+#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+void TestingSpellCheckProvider::RequestTextCheck(
+ const base::string16& text,
+ int,
+ RequestTextCheckCallback callback) {
+ text_check_requests_.push_back(std::make_pair(text, std::move(callback)));
+}
+
+void TestingSpellCheckProvider::ToggleSpellCheck(bool, bool) {
+ NOTREACHED();
+}
+
+void TestingSpellCheckProvider::CheckSpelling(const base::string16&,
+ int,
+ CheckSpellingCallback) {
+ NOTREACHED();
+}
+
+void TestingSpellCheckProvider::FillSuggestionList(const base::string16&,
+ FillSuggestionListCallback) {
+ NOTREACHED();
+}
+#endif // BUILDFLAG(USE_BROWSER_SPELLCHECKER)
void TestingSpellCheckProvider::SetLastResults(
const base::string16 last_request,
@@ -123,5 +136,6 @@ bool TestingSpellCheckProvider::SatisfyRequestFromCache(
return SpellCheckProvider::SatisfyRequestFromCache(text, completion);
}
-SpellCheckProviderTest::SpellCheckProviderTest() {}
+SpellCheckProviderTest::SpellCheckProviderTest()
+ : provider_(&embedder_provider_) {}
SpellCheckProviderTest::~SpellCheckProviderTest() {}
diff --git a/chromium/components/spellcheck/renderer/spellcheck_provider_test.h b/chromium/components/spellcheck/renderer/spellcheck_provider_test.h
index aa2cb77058f..b117067498d 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_provider_test.h
+++ b/chromium/components/spellcheck/renderer/spellcheck_provider_test.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/strings/string16.h"
+#include "components/spellcheck/renderer/empty_local_interface_provider.h"
#include "components/spellcheck/renderer/spellcheck_provider.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -20,10 +21,6 @@ namespace base {
class MessageLoop;
}
-namespace IPC {
-class Message;
-}
-
// A fake completion object for verification.
class FakeTextCheckingCompletion : public blink::WebTextCheckingCompletion {
public:
@@ -42,35 +39,60 @@ class FakeTextCheckingCompletion : public blink::WebTextCheckingCompletion {
class TestingSpellCheckProvider : public SpellCheckProvider,
public spellcheck::mojom::SpellCheckHost {
public:
- TestingSpellCheckProvider();
+ explicit TestingSpellCheckProvider(service_manager::LocalInterfaceProvider*);
// Takes ownership of |spellcheck|.
- explicit TestingSpellCheckProvider(SpellCheck* spellcheck);
+ TestingSpellCheckProvider(SpellCheck* spellcheck,
+ service_manager::LocalInterfaceProvider*);
~TestingSpellCheckProvider() override;
void RequestTextChecking(const base::string16& text,
blink::WebTextCheckingCompletion* completion);
- bool Send(IPC::Message* message) override;
- void OnCallSpellingService(const base::string16& text);
- void ResetResult();
-
void SetLastResults(
const base::string16 last_request,
blink::WebVector<blink::WebTextCheckingResult>& last_results);
bool SatisfyRequestFromCache(const base::string16& text,
blink::WebTextCheckingCompletion* completion);
+#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+ void ResetResult();
+
+ // Variables logging CallSpellingService() mojo calls.
base::string16 text_;
- std::vector<std::unique_ptr<IPC::Message>> messages_;
- size_t spelling_service_call_count_;
+ size_t spelling_service_call_count_ = 0;
+#endif
+
+#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+ // Variables logging RequestTextCheck() mojo calls.
+ using RequestTextCheckParams =
+ std::pair<base::string16, RequestTextCheckCallback>;
+ std::vector<RequestTextCheckParams> text_check_requests_;
+#endif
private:
- // spellcheck::mojom::SpellCheckerHost:
+ // spellcheck::mojom::SpellCheckHost:
void RequestDictionary() override;
void NotifyChecked(const base::string16& word, bool misspelled) override;
+
+#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
void CallSpellingService(const base::string16& text,
CallSpellingServiceCallback callback) override;
+ void OnCallSpellingService(const base::string16& text);
+#endif
+
+#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+ void RequestTextCheck(const base::string16&,
+ int,
+ RequestTextCheckCallback) override;
+ void ToggleSpellCheck(bool, bool) override;
+ using SpellCheckProvider::CheckSpelling;
+ void CheckSpelling(const base::string16&,
+ int,
+ CheckSpellingCallback) override;
+ void FillSuggestionList(const base::string16&,
+ FillSuggestionListCallback) override;
+#endif
// Message loop (if needed) to deliver the SpellCheckHost request flow.
std::unique_ptr<base::MessageLoop> loop_;
@@ -86,6 +108,7 @@ class SpellCheckProviderTest : public testing::Test {
~SpellCheckProviderTest() override;
protected:
+ spellcheck::EmptyLocalInterfaceProvider embedder_provider_;
TestingSpellCheckProvider provider_;
};
diff --git a/chromium/components/spellcheck/renderer/spellcheck_unittest.cc b/chromium/components/spellcheck/renderer/spellcheck_unittest.cc
index d608849c908..0101e851ca2 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_unittest.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck_unittest.cc
@@ -20,6 +20,7 @@
#include "build/build_config.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "components/spellcheck/common/spellcheck_result.h"
+#include "components/spellcheck/renderer/empty_local_interface_provider.h"
#include "components/spellcheck/renderer/hunspell_engine.h"
#include "components/spellcheck/renderer/spellcheck_language.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -59,7 +60,7 @@ class SpellCheckTest : public testing::Test {
}
void UninitializeSpellCheck() {
- spell_check_ = std::make_unique<SpellCheck>(nullptr);
+ spell_check_ = std::make_unique<SpellCheck>(nullptr, &embedder_provider_);
}
bool InitializeIfNeeded() {
@@ -76,9 +77,9 @@ class SpellCheckTest : public testing::Test {
// TODO(groby): Forcing spellcheck to use hunspell, even on OSX.
// Instead, tests should exercise individual spelling engines.
spell_check_->languages_.push_back(
- std::make_unique<SpellcheckLanguage>(nullptr));
+ std::make_unique<SpellcheckLanguage>(&embedder_provider_));
spell_check_->languages_.front()->platform_spelling_engine_ =
- std::make_unique<HunspellEngine>(nullptr);
+ std::make_unique<HunspellEngine>(&embedder_provider_);
spell_check_->languages_.front()->Init(std::move(file), language);
#else
spell_check_->AddSpellcheckLanguage(std::move(file), language);
@@ -124,6 +125,7 @@ class SpellCheckTest : public testing::Test {
#endif
private:
+ spellcheck::EmptyLocalInterfaceProvider embedder_provider_;
std::unique_ptr<SpellCheck> spell_check_;
base::MessageLoop loop_;
};
diff --git a/chromium/components/ssl_config/ssl_config_prefs.cc b/chromium/components/ssl_config/ssl_config_prefs.cc
index 978ee3ae6da..790159d7228 100644
--- a/chromium/components/ssl_config/ssl_config_prefs.cc
+++ b/chromium/components/ssl_config/ssl_config_prefs.cc
@@ -12,8 +12,8 @@ const char kCertRevocationCheckingEnabled[] = "ssl.rev_checking.enabled";
const char kCertRevocationCheckingRequiredLocalAnchors[] =
"ssl.rev_checking.required_for_local_anchors";
const char kCertEnableSha1LocalAnchors[] = "ssl.sha1_enabled_for_local_anchors";
-const char kCertEnableCommonNameFallbackLocalAnchors[] =
- "ssl.common_name_fallback_enabled_for_local_anchors";
+const char kCertEnableSymantecLegacyInfrastructure[] =
+ "ssl.enable_symantec_legacy_infrastructure";
const char kSSLVersionMin[] = "ssl.version_min";
const char kSSLVersionMax[] = "ssl.version_max";
const char kTLS13Variant[] = "ssl.tls13_variant";
diff --git a/chromium/components/ssl_config/ssl_config_prefs.h b/chromium/components/ssl_config/ssl_config_prefs.h
index 55121fc5af8..3f3b8b83960 100644
--- a/chromium/components/ssl_config/ssl_config_prefs.h
+++ b/chromium/components/ssl_config/ssl_config_prefs.h
@@ -11,7 +11,7 @@ namespace prefs {
extern const char kCertRevocationCheckingEnabled[];
extern const char kCertRevocationCheckingRequiredLocalAnchors[];
extern const char kCertEnableSha1LocalAnchors[];
-extern const char kCertEnableCommonNameFallbackLocalAnchors[];
+extern const char kCertEnableSymantecLegacyInfrastructure[];
extern const char kSSLVersionMin[];
extern const char kSSLVersionMax[];
extern const char kTLS13Variant[];
diff --git a/chromium/components/ssl_config/ssl_config_service_manager_pref.cc b/chromium/components/ssl_config/ssl_config_service_manager_pref.cc
index f924fe268f0..bd0ba311df2 100644
--- a/chromium/components/ssl_config/ssl_config_service_manager_pref.cc
+++ b/chromium/components/ssl_config/ssl_config_service_manager_pref.cc
@@ -171,7 +171,7 @@ class SSLConfigServiceManagerPref : public ssl_config::SSLConfigServiceManager {
BooleanPrefMember rev_checking_enabled_;
BooleanPrefMember rev_checking_required_local_anchors_;
BooleanPrefMember sha1_local_anchors_enabled_;
- BooleanPrefMember common_name_fallback_local_anchors_enabled_;
+ BooleanPrefMember symantec_legacy_infrastructure_enabled_;
StringPrefMember ssl_version_min_;
StringPrefMember ssl_version_max_;
StringPrefMember tls13_variant_;
@@ -196,27 +196,21 @@ SSLConfigServiceManagerPref::SSLConfigServiceManagerPref(
const std::string tls13_variant =
base::GetFieldTrialParamValue(kTLS13VariantExperimentName, "variant");
const char* tls13_value = nullptr;
- const char* experiment_value = nullptr;
+ const char* version_value = nullptr;
if (tls13_variant == "disabled") {
tls13_value = switches::kTLS13VariantDisabled;
- } else if (tls13_variant == "draft22") {
- tls13_value = switches::kTLS13VariantDraft22;
- experiment_value = switches::kSSLVersionTLSv13;
} else if (tls13_variant == "draft23") {
tls13_value = switches::kTLS13VariantDraft23;
- experiment_value = switches::kSSLVersionTLSv13;
- } else if (tls13_variant == "experiment2") {
- tls13_value = switches::kTLS13VariantExperiment2;
- experiment_value = switches::kSSLVersionTLSv13;
+ version_value = switches::kSSLVersionTLSv13;
}
if (tls13_value) {
local_state->SetDefaultPrefValue(ssl_config::prefs::kTLS13Variant,
base::Value(tls13_value));
}
- if (experiment_value) {
+ if (version_value) {
local_state->SetDefaultPrefValue(ssl_config::prefs::kSSLVersionMax,
- base::Value(experiment_value));
+ base::Value(version_value));
}
PrefChangeRegistrar::NamedChangeCallback local_state_callback =
@@ -231,8 +225,8 @@ SSLConfigServiceManagerPref::SSLConfigServiceManagerPref(
sha1_local_anchors_enabled_.Init(
ssl_config::prefs::kCertEnableSha1LocalAnchors, local_state,
local_state_callback);
- common_name_fallback_local_anchors_enabled_.Init(
- ssl_config::prefs::kCertEnableCommonNameFallbackLocalAnchors, local_state,
+ symantec_legacy_infrastructure_enabled_.Init(
+ ssl_config::prefs::kCertEnableSymantecLegacyInfrastructure, local_state,
local_state_callback);
ssl_version_min_.Init(ssl_config::prefs::kSSLVersionMin, local_state,
local_state_callback);
@@ -264,7 +258,8 @@ void SSLConfigServiceManagerPref::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(ssl_config::prefs::kCertEnableSha1LocalAnchors,
false);
registry->RegisterBooleanPref(
- ssl_config::prefs::kCertEnableCommonNameFallbackLocalAnchors, false);
+ ssl_config::prefs::kCertEnableSymantecLegacyInfrastructure,
+ default_config.symantec_enforcement_disabled);
registry->RegisterStringPref(ssl_config::prefs::kSSLVersionMin,
std::string());
registry->RegisterStringPref(ssl_config::prefs::kSSLVersionMax,
@@ -305,8 +300,8 @@ void SSLConfigServiceManagerPref::GetSSLConfigFromPrefs(
config->rev_checking_required_local_anchors =
rev_checking_required_local_anchors_.GetValue();
config->sha1_local_anchors_enabled = sha1_local_anchors_enabled_.GetValue();
- config->common_name_fallback_local_anchors_enabled =
- common_name_fallback_local_anchors_enabled_.GetValue();
+ config->symantec_enforcement_disabled =
+ symantec_legacy_infrastructure_enabled_.GetValue();
std::string version_min_str = ssl_version_min_.GetValue();
std::string version_max_str = ssl_version_max_.GetValue();
std::string tls13_variant_str = tls13_variant_.GetValue();
@@ -324,12 +319,8 @@ void SSLConfigServiceManagerPref::GetSSLConfigFromPrefs(
if (tls13_variant_str == switches::kTLS13VariantDisabled) {
if (config->version_max > net::SSL_PROTOCOL_VERSION_TLS1_2)
config->version_max = net::SSL_PROTOCOL_VERSION_TLS1_2;
- } else if (tls13_variant_str == switches::kTLS13VariantDraft22) {
- config->tls13_variant = net::kTLS13VariantDraft22;
} else if (tls13_variant_str == switches::kTLS13VariantDraft23) {
config->tls13_variant = net::kTLS13VariantDraft23;
- } else if (tls13_variant_str == switches::kTLS13VariantExperiment2) {
- config->tls13_variant = net::kTLS13VariantExperiment2;
}
config->disabled_cipher_suites = disabled_cipher_suites_;
diff --git a/chromium/components/ssl_config/ssl_config_service_manager_pref_unittest.cc b/chromium/components/ssl_config/ssl_config_service_manager_pref_unittest.cc
index a53bd9b3378..5ab7d10352a 100644
--- a/chromium/components/ssl_config/ssl_config_service_manager_pref_unittest.cc
+++ b/chromium/components/ssl_config/ssl_config_service_manager_pref_unittest.cc
@@ -6,7 +6,6 @@
#include <utility>
#include "base/command_line.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
@@ -68,7 +67,7 @@ TEST_F(SSLConfigServiceManagerPrefTest, GoodDisabledCipherSuites) {
config_service->GetSSLConfig(&old_config);
EXPECT_TRUE(old_config.disabled_cipher_suites.empty());
- auto list_value = base::MakeUnique<base::ListValue>();
+ auto list_value = std::make_unique<base::ListValue>();
list_value->AppendString("0x0004");
list_value->AppendString("0x0005");
local_state.SetUserPref(ssl_config::prefs::kCipherSuiteBlacklist,
@@ -105,7 +104,7 @@ TEST_F(SSLConfigServiceManagerPrefTest, BadDisabledCipherSuites) {
config_service->GetSSLConfig(&old_config);
EXPECT_TRUE(old_config.disabled_cipher_suites.empty());
- auto list_value = base::MakeUnique<base::ListValue>();
+ auto list_value = std::make_unique<base::ListValue>();
list_value->AppendString("0x0004");
list_value->AppendString("TLS_NOT_WITH_A_CIPHER_SUITE");
list_value->AppendString("0x0005");
@@ -171,7 +170,7 @@ TEST_F(SSLConfigServiceManagerPrefTest, NoSSL3) {
TestingPrefServiceSimple local_state;
local_state.SetUserPref(ssl_config::prefs::kSSLVersionMin,
- base::MakeUnique<base::Value>("ssl3"));
+ std::make_unique<base::Value>("ssl3"));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager(
@@ -187,13 +186,13 @@ TEST_F(SSLConfigServiceManagerPrefTest, NoSSL3) {
EXPECT_LE(net::SSL_PROTOCOL_VERSION_TLS1, ssl_config.version_min);
}
-// Tests that SSL max version correctly sets the maximum version.
-TEST_F(SSLConfigServiceManagerPrefTest, SSLVersionMax) {
+// Tests that SSLVersionMin correctly sets the minimum version.
+TEST_F(SSLConfigServiceManagerPrefTest, SSLVersionMin) {
scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
TestingPrefServiceSimple local_state;
- local_state.SetUserPref(ssl_config::prefs::kSSLVersionMax,
- base::MakeUnique<base::Value>("tls1.3"));
+ local_state.SetUserPref(ssl_config::prefs::kSSLVersionMin,
+ std::make_unique<base::Value>("tls1.1"));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager(
@@ -205,16 +204,16 @@ TEST_F(SSLConfigServiceManagerPrefTest, SSLVersionMax) {
SSLConfig ssl_config;
config_service->GetSSLConfig(&ssl_config);
- EXPECT_EQ(net::SSL_PROTOCOL_VERSION_TLS1_3, ssl_config.version_max);
+ EXPECT_EQ(net::SSL_PROTOCOL_VERSION_TLS1_1, ssl_config.version_min);
}
-// Tests that SSL max version can not be set below TLS 1.2.
-TEST_F(SSLConfigServiceManagerPrefTest, NoTLS11Max) {
+// Tests that SSL max version correctly sets the maximum version.
+TEST_F(SSLConfigServiceManagerPrefTest, SSLVersionMax) {
scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
TestingPrefServiceSimple local_state;
local_state.SetUserPref(ssl_config::prefs::kSSLVersionMax,
- base::MakeUnique<base::Value>("tls1.1"));
+ std::make_unique<base::Value>("tls1.3"));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager(
@@ -226,56 +225,36 @@ TEST_F(SSLConfigServiceManagerPrefTest, NoTLS11Max) {
SSLConfig ssl_config;
config_service->GetSSLConfig(&ssl_config);
- // The command-line option must not have been honored.
- EXPECT_LE(net::SSL_PROTOCOL_VERSION_TLS1_2, ssl_config.version_max);
-}
-
-// Tests that TLS 1.3 can be disabled via field trials.
-TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantFeatureDisabled) {
- // Toggle the field trial.
- variations::testing::VariationParamsManager variation_params(
- "TLS13Variant", {{"variant", "disabled"}});
-
- TestingPrefServiceSimple local_state;
- SSLConfigServiceManager::RegisterPrefs(local_state.registry());
-
- std::unique_ptr<SSLConfigServiceManager> config_manager(
- SSLConfigServiceManager::CreateDefaultManager(
- &local_state, base::ThreadTaskRunnerHandle::Get()));
- scoped_refptr<SSLConfigService> config_service(config_manager->Get());
- ASSERT_TRUE(config_service.get());
-
- SSLConfig ssl_config;
- config_service->GetSSLConfig(&ssl_config);
- EXPECT_EQ(net::SSL_PROTOCOL_VERSION_TLS1_2, ssl_config.version_max);
+ EXPECT_EQ(net::SSL_PROTOCOL_VERSION_TLS1_3, ssl_config.version_max);
}
-// Tests that Experiment2 TLS 1.3 can be enabled via field trials.
-TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantFeatureExperiment2) {
- // Toggle the field trial.
- variations::testing::VariationParamsManager variation_params(
- "TLS13Variant", {{"variant", "experiment2"}});
+// Tests that SSL max version can not be set below TLS 1.2.
+TEST_F(SSLConfigServiceManagerPrefTest, NoTLS11Max) {
+ scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
TestingPrefServiceSimple local_state;
+ local_state.SetUserPref(ssl_config::prefs::kSSLVersionMax,
+ std::make_unique<base::Value>("tls1.1"));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager(
SSLConfigServiceManager::CreateDefaultManager(
&local_state, base::ThreadTaskRunnerHandle::Get()));
+ ASSERT_TRUE(config_manager.get());
scoped_refptr<SSLConfigService> config_service(config_manager->Get());
ASSERT_TRUE(config_service.get());
SSLConfig ssl_config;
config_service->GetSSLConfig(&ssl_config);
- EXPECT_EQ(net::SSL_PROTOCOL_VERSION_TLS1_3, ssl_config.version_max);
- EXPECT_EQ(net::kTLS13VariantExperiment2, ssl_config.tls13_variant);
+ // The command-line option must not have been honored.
+ EXPECT_LE(net::SSL_PROTOCOL_VERSION_TLS1_2, ssl_config.version_max);
}
-// Tests that Draft22 TLS 1.3 can be enabled via field trials.
-TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantFeatureDraft22) {
+// Tests that TLS 1.3 can be disabled via field trials.
+TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantFeatureDisabled) {
// Toggle the field trial.
variations::testing::VariationParamsManager variation_params(
- "TLS13Variant", {{"variant", "draft22"}});
+ "TLS13Variant", {{"variant", "disabled"}});
TestingPrefServiceSimple local_state;
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
@@ -288,8 +267,7 @@ TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantFeatureDraft22) {
SSLConfig ssl_config;
config_service->GetSSLConfig(&ssl_config);
- EXPECT_EQ(net::SSL_PROTOCOL_VERSION_TLS1_3, ssl_config.version_max);
- EXPECT_EQ(net::kTLS13VariantDraft22, ssl_config.tls13_variant);
+ EXPECT_EQ(net::SSL_PROTOCOL_VERSION_TLS1_2, ssl_config.version_max);
}
// Tests that Draft23 TLS 1.3 can be enabled via field trials.
@@ -320,11 +298,11 @@ TEST_F(SSLConfigServiceManagerPrefTest, TLS13SSLVersionMax) {
// Toggle the field trial.
variations::testing::VariationParamsManager variation_params(
- "TLS13Variant", {{"variant", "experiment"}});
+ "TLS13Variant", {{"variant", "draft23"}});
TestingPrefServiceSimple local_state;
local_state.SetUserPref(ssl_config::prefs::kSSLVersionMax,
- base::MakeUnique<base::Value>("tls1.2"));
+ std::make_unique<base::Value>("tls1.2"));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager(
@@ -346,11 +324,11 @@ TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantOverrideDisable) {
// Toggle the field trial.
variations::testing::VariationParamsManager variation_params(
- "TLS13Variant", {{"variant", "experiment"}});
+ "TLS13Variant", {{"variant", "draft23"}});
TestingPrefServiceSimple local_state;
local_state.SetUserPref(ssl_config::prefs::kTLS13Variant,
- base::MakeUnique<base::Value>("disabled"));
+ std::make_unique<base::Value>("disabled"));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager(
@@ -375,9 +353,9 @@ TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantOverrideEnable) {
TestingPrefServiceSimple local_state;
local_state.SetUserPref(ssl_config::prefs::kSSLVersionMax,
- base::MakeUnique<base::Value>("tls1.3"));
+ std::make_unique<base::Value>("tls1.3"));
local_state.SetUserPref(ssl_config::prefs::kTLS13Variant,
- base::MakeUnique<base::Value>("experiment2"));
+ std::make_unique<base::Value>("draft23"));
SSLConfigServiceManager::RegisterPrefs(local_state.registry());
std::unique_ptr<SSLConfigServiceManager> config_manager(
@@ -390,7 +368,7 @@ TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantOverrideEnable) {
SSLConfig ssl_config;
config_service->GetSSLConfig(&ssl_config);
EXPECT_EQ(net::SSL_PROTOCOL_VERSION_TLS1_3, ssl_config.version_max);
- EXPECT_EQ(net::kTLS13VariantExperiment2, ssl_config.tls13_variant);
+ EXPECT_EQ(net::kTLS13VariantDraft23, ssl_config.tls13_variant);
}
// Tests that SHA-1 signatures for local trust anchors can be enabled.
@@ -421,7 +399,7 @@ TEST_F(SSLConfigServiceManagerPrefTest, SHA1ForLocalAnchors) {
// Enabling the local preference should result in SHA-1 local trust anchors
// being enabled.
local_state.SetUserPref(ssl_config::prefs::kCertEnableSha1LocalAnchors,
- base::MakeUnique<base::Value>(true));
+ std::make_unique<base::Value>(true));
// Pump the message loop to notify the SSLConfigServiceManagerPref that the
// preferences changed.
base::RunLoop().RunUntilIdle();
@@ -433,7 +411,7 @@ TEST_F(SSLConfigServiceManagerPrefTest, SHA1ForLocalAnchors) {
// Disabling the local preference should result in SHA-1 local trust
// anchors being disabled.
local_state.SetUserPref(ssl_config::prefs::kCertEnableSha1LocalAnchors,
- base::MakeUnique<base::Value>(false));
+ std::make_unique<base::Value>(false));
// Pump the message loop to notify the SSLConfigServiceManagerPref that the
// preferences changed.
base::RunLoop().RunUntilIdle();
@@ -442,3 +420,55 @@ TEST_F(SSLConfigServiceManagerPrefTest, SHA1ForLocalAnchors) {
config_service->GetSSLConfig(&config4);
EXPECT_FALSE(config4.sha1_local_anchors_enabled);
}
+
+// Tests that Symantec's legacy infrastructure can be enabled.
+TEST_F(SSLConfigServiceManagerPrefTest, SymantecLegacyInfrastructure) {
+ scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
+
+ TestingPrefServiceSimple local_state;
+ SSLConfigServiceManager::RegisterPrefs(local_state.registry());
+
+ std::unique_ptr<SSLConfigServiceManager> config_manager(
+ SSLConfigServiceManager::CreateDefaultManager(
+ &local_state, base::ThreadTaskRunnerHandle::Get()));
+ ASSERT_TRUE(config_manager);
+ scoped_refptr<SSLConfigService> config_service(config_manager->Get());
+ ASSERT_TRUE(config_service);
+
+ // By default, Symantec's legacy infrastructure should be disabled when
+ // not using any pref service.
+ SSLConfig config1;
+ EXPECT_FALSE(config1.symantec_enforcement_disabled);
+
+ // Using a pref service without any preference set should result in
+ // Symantec's legacy infrastructure being disabled.
+ SSLConfig config2;
+ config_service->GetSSLConfig(&config2);
+ EXPECT_FALSE(config2.symantec_enforcement_disabled);
+
+ // Enabling the local preference should result in Symantec's legacy
+ // infrastructure being enabled.
+ local_state.SetUserPref(
+ ssl_config::prefs::kCertEnableSymantecLegacyInfrastructure,
+ std::make_unique<base::Value>(true));
+ // Pump the message loop to notify the SSLConfigServiceManagerPref that the
+ // preferences changed.
+ base::RunLoop().RunUntilIdle();
+
+ SSLConfig config3;
+ config_service->GetSSLConfig(&config3);
+ EXPECT_TRUE(config3.symantec_enforcement_disabled);
+
+ // Disabling the local preference should result in Symantec's legacy
+ // infrastructure being disabled.
+ local_state.SetUserPref(
+ ssl_config::prefs::kCertEnableSymantecLegacyInfrastructure,
+ std::make_unique<base::Value>(false));
+ // Pump the message loop to notify the SSLConfigServiceManagerPref that the
+ // preferences changed.
+ base::RunLoop().RunUntilIdle();
+
+ SSLConfig config4;
+ config_service->GetSSLConfig(&config4);
+ EXPECT_FALSE(config4.symantec_enforcement_disabled);
+}
diff --git a/chromium/components/ssl_config/ssl_config_switches.cc b/chromium/components/ssl_config/ssl_config_switches.cc
index 49434ac4e8c..e1b350bf1f9 100644
--- a/chromium/components/ssl_config/ssl_config_switches.cc
+++ b/chromium/components/ssl_config/ssl_config_switches.cc
@@ -25,8 +25,6 @@ const char kSSLVersionTLSv12[] = "tls1.2";
const char kSSLVersionTLSv13[] = "tls1.3";
const char kTLS13VariantDisabled[] = "disabled";
-const char kTLS13VariantDraft22[] = "draft22";
const char kTLS13VariantDraft23[] = "draft23";
-const char kTLS13VariantExperiment2[] = "experiment2";
} // namespace switches
diff --git a/chromium/components/ssl_config/ssl_config_switches.h b/chromium/components/ssl_config/ssl_config_switches.h
index a80adaa8f83..9916b6fdeaf 100644
--- a/chromium/components/ssl_config/ssl_config_switches.h
+++ b/chromium/components/ssl_config/ssl_config_switches.h
@@ -15,9 +15,7 @@ extern const char kSSLVersionTLSv11[];
extern const char kSSLVersionTLSv12[];
extern const char kSSLVersionTLSv13[];
extern const char kTLS13VariantDisabled[];
-extern const char kTLS13VariantDraft22[];
extern const char kTLS13VariantDraft23[];
-extern const char kTLS13VariantExperiment2[];
} // namespace switches
diff --git a/chromium/components/ssl_errors/error_classification_unittest.cc b/chromium/components/ssl_errors/error_classification_unittest.cc
index c4c2c45e9ef..9f96ea36b02 100644
--- a/chromium/components/ssl_errors/error_classification_unittest.cc
+++ b/chromium/components/ssl_errors/error_classification_unittest.cc
@@ -4,8 +4,9 @@
#include "components/ssl_errors/error_classification.h"
+#include <memory>
+
#include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_split.h"
#include "base/test/histogram_tester.h"
@@ -249,8 +250,8 @@ TEST_F(SSLErrorClassificationTest, GetClockState) {
network_time::NetworkTimeTracker::RegisterPrefs(pref_service.registry());
base::MessageLoop loop;
network_time::NetworkTimeTracker network_time_tracker(
- base::MakeUnique<base::DefaultClock>(),
- base::MakeUnique<base::DefaultTickClock>(), &pref_service,
+ std::make_unique<base::DefaultClock>(),
+ std::make_unique<base::DefaultTickClock>(), &pref_service,
new net::TestURLRequestContextGetter(
base::ThreadTaskRunnerHandle::Get()));
diff --git a/chromium/components/ssl_errors/error_info.cc b/chromium/components/ssl_errors/error_info.cc
index a6bed5cea72..1ed896c0c59 100644
--- a/chromium/components/ssl_errors/error_info.cc
+++ b/chromium/components/ssl_errors/error_info.cc
@@ -96,6 +96,7 @@ ErrorInfo ErrorInfo::CreateError(ErrorType error_type,
}
break;
case CERT_AUTHORITY_INVALID:
+ case CERT_SYMANTEC_LEGACY:
details =
l10n_util::GetStringFUTF16(IDS_CERT_ERROR_AUTHORITY_INVALID_DETAILS,
UTF8ToUTF16(request_url.host()));
@@ -216,6 +217,8 @@ ErrorInfo::ErrorType ErrorInfo::NetErrorToErrorType(int net_error) {
return CERT_PINNED_KEY_MISSING;
case net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED:
return CERTIFICATE_TRANSPARENCY_REQUIRED;
+ case net::ERR_CERT_SYMANTEC_LEGACY:
+ return CERT_SYMANTEC_LEGACY;
default:
NOTREACHED();
return UNKNOWN;
@@ -241,6 +244,7 @@ void ErrorInfo::GetErrorsForCertStatus(
net::CERT_STATUS_NAME_CONSTRAINT_VIOLATION,
net::CERT_STATUS_VALIDITY_TOO_LONG,
net::CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED,
+ net::CERT_STATUS_SYMANTEC_LEGACY,
};
const ErrorType kErrorTypes[] = {
@@ -256,6 +260,7 @@ void ErrorInfo::GetErrorsForCertStatus(
CERT_NAME_CONSTRAINT_VIOLATION,
CERT_VALIDITY_TOO_LONG,
CERTIFICATE_TRANSPARENCY_REQUIRED,
+ CERT_SYMANTEC_LEGACY,
};
DCHECK(arraysize(kErrorFlags) == arraysize(kErrorTypes));
diff --git a/chromium/components/ssl_errors/error_info.h b/chromium/components/ssl_errors/error_info.h
index fd7da2d013a..571a65e3c06 100644
--- a/chromium/components/ssl_errors/error_info.h
+++ b/chromium/components/ssl_errors/error_info.h
@@ -41,6 +41,7 @@ class ErrorInfo {
CERT_PINNED_KEY_MISSING = 13,
CERT_VALIDITY_TOO_LONG = 14,
CERTIFICATE_TRANSPARENCY_REQUIRED = 15,
+ CERT_SYMANTEC_LEGACY = 16,
END_OF_ENUM
};
diff --git a/chromium/components/startup_metric_utils/browser/startup_metric_host_impl.cc b/chromium/components/startup_metric_utils/browser/startup_metric_host_impl.cc
index 236442328b5..b7f0cf9650e 100644
--- a/chromium/components/startup_metric_utils/browser/startup_metric_host_impl.cc
+++ b/chromium/components/startup_metric_utils/browser/startup_metric_host_impl.cc
@@ -4,7 +4,8 @@
#include "components/startup_metric_utils/browser/startup_metric_host_impl.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "components/startup_metric_utils/browser/startup_metric_utils.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -17,7 +18,7 @@ StartupMetricHostImpl::~StartupMetricHostImpl() = default;
// static
void StartupMetricHostImpl::Create(
mojom::StartupMetricHostRequest request) {
- mojo::MakeStrongBinding(base::MakeUnique<StartupMetricHostImpl>(),
+ mojo::MakeStrongBinding(std::make_unique<StartupMetricHostImpl>(),
std::move(request));
}
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 08e93ee1c72..a6ef802aeaf 100644
--- a/chromium/components/startup_metric_utils/browser/startup_metric_utils.cc
+++ b/chromium/components/startup_metric_utils/browser/startup_metric_utils.cc
@@ -716,10 +716,6 @@ void RecordFirstWebContentsMainNavigationStart(base::TimeTicks ticks,
UMA_HISTOGRAM_LONG_TIMES_100,
"Startup.FirstWebContents.MainNavigationStart", g_process_creation_ticks,
ticks);
- UMA_HISTOGRAM_WITH_TEMPERATURE(
- UMA_HISTOGRAM_LONG_TIMES_100,
- "Startup.BrowserMessageLoopStart.To.MainNavigationStart",
- ticks - g_message_loop_start_ticks);
// Log extra information about this startup's workload. Only added to this
// histogram as this extra suffix can help making it less noisy but isn't
diff --git a/chromium/components/storage_monitor/BUILD.gn b/chromium/components/storage_monitor/BUILD.gn
index 6c565d3f65f..87f15eb336a 100644
--- a/chromium/components/storage_monitor/BUILD.gn
+++ b/chromium/components/storage_monitor/BUILD.gn
@@ -62,6 +62,8 @@ static_library("storage_monitor") {
sources += [
"media_transfer_protocol_device_observer_chromeos.cc",
"media_transfer_protocol_device_observer_chromeos.h",
+ "storage_info_utils.cc",
+ "storage_info_utils.h",
]
}
diff --git a/chromium/components/storage_monitor/media_storage_util_unittest.cc b/chromium/components/storage_monitor/media_storage_util_unittest.cc
index fc9f5b352ae..0bb998a0a33 100644
--- a/chromium/components/storage_monitor/media_storage_util_unittest.cc
+++ b/chromium/components/storage_monitor/media_storage_util_unittest.cc
@@ -4,6 +4,7 @@
#include <string>
+#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
@@ -119,15 +120,13 @@ TEST_F(MediaStorageUtilTest, DetectDeviceFiltered) {
MediaStorageUtil::DeviceIdSet devices;
devices.insert(kImageCaptureDeviceId);
- MediaStorageUtil::FilterAttachedDevices(&devices,
- base::Bind(&base::DoNothing));
+ MediaStorageUtil::FilterAttachedDevices(&devices, base::DoNothing());
RunUntilIdle();
EXPECT_FALSE(devices.find(kImageCaptureDeviceId) != devices.end());
ProcessAttach(kImageCaptureDeviceId, FILE_PATH_LITERAL("/location"));
devices.insert(kImageCaptureDeviceId);
- MediaStorageUtil::FilterAttachedDevices(&devices,
- base::Bind(&base::DoNothing));
+ MediaStorageUtil::FilterAttachedDevices(&devices, base::DoNothing());
RunUntilIdle();
EXPECT_TRUE(devices.find(kImageCaptureDeviceId) != devices.end());
diff --git a/chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.cc b/chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.cc
index f1487e760d3..a008b667aaf 100644
--- a/chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.cc
+++ b/chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.cc
@@ -6,94 +6,12 @@
#include <vector>
-#include "base/files/file_path.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
-#include "components/storage_monitor/removable_device_constants.h"
+#include "components/storage_monitor/storage_info.h"
+#include "components/storage_monitor/storage_info_utils.h"
namespace storage_monitor {
-namespace {
-
-// Device root path constant.
-const char kRootPath[] = "/";
-
-// Constructs and returns the location of the device using the |storage_name|.
-std::string GetDeviceLocationFromStorageName(const std::string& storage_name) {
- // Construct a dummy device path using the storage name. This is only used
- // for registering device media file system.
- // E.g.: If the |storage_name| is "usb:2,2:12345" then "/usb:2,2:12345" is the
- // device location.
- DCHECK(!storage_name.empty());
- return kRootPath + storage_name;
-}
-
-// Returns the storage identifier of the device from the given |storage_name|.
-// E.g. If the |storage_name| is "usb:2,2:65537", the storage identifier is
-// "65537".
-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();
-}
-
-// Returns a unique device id from the given |storage_info|.
-std::string GetDeviceIdFromStorageInfo(
- const device::mojom::MtpStorageInfo& storage_info) {
- const std::string storage_id =
- GetStorageIdFromStorageName(storage_info.storage_name);
- if (storage_id.empty())
- return std::string();
-
- // Some devices have multiple data stores. Therefore, include storage id as
- // part of unique id along with vendor, model and volume information.
- const std::string vendor_id = base::UintToString(storage_info.vendor_id);
- const std::string model_id = base::UintToString(storage_info.product_id);
- return StorageInfo::MakeDeviceId(
- StorageInfo::MTP_OR_PTP,
- kVendorModelVolumeStoragePrefix + vendor_id + ":" + model_id + ":" +
- storage_info.volume_identifier + ":" + storage_id);
-}
-
-// Returns the |data_store_id| string in the required format.
-// If the |data_store_id| is 65537, this function returns " (65537)".
-std::string GetFormattedIdString(const std::string& data_store_id) {
- return ("(" + data_store_id + ")");
-}
-
-// Helper function to get device label from storage information.
-base::string16 GetDeviceLabelFromStorageInfo(
- const device::mojom::MtpStorageInfo& storage_info) {
- std::string device_label;
- const std::string& vendor_name = storage_info.vendor;
- device_label = vendor_name;
-
- const std::string& product_name = storage_info.product;
- if (!product_name.empty()) {
- if (!device_label.empty())
- device_label += " ";
- device_label += product_name;
- }
-
- // Add the data store id to the device label.
- if (!device_label.empty()) {
- const std::string& volume_id = storage_info.volume_identifier;
- if (!volume_id.empty()) {
- device_label += GetFormattedIdString(volume_id);
- } else {
- const std::string data_store_id =
- GetStorageIdFromStorageName(storage_info.storage_name);
- if (!data_store_id.empty())
- device_label += GetFormattedIdString(data_store_id);
- }
- }
- return base::UTF8ToUTF16(device_label);
-}
-
-} // namespace
-
MediaTransferProtocolDeviceObserverChromeOS::
MediaTransferProtocolDeviceObserverChromeOS(
StorageMonitor::Receiver* receiver,
@@ -104,8 +22,11 @@ MediaTransferProtocolDeviceObserverChromeOS::
base::Unretained(mtp_manager_))),
notifications_(receiver),
weak_ptr_factory_(this) {
- mtp_manager_->AddObserver(this);
- EnumerateStorages();
+ mtp_manager_->AddObserverAndEnumerateStorages(
+ this,
+ base::BindOnce(
+ &MediaTransferProtocolDeviceObserverChromeOS::OnReceivedStorages,
+ weak_ptr_factory_.GetWeakPtr()));
}
// This constructor is only used by unit tests.
@@ -113,7 +34,7 @@ MediaTransferProtocolDeviceObserverChromeOS::
MediaTransferProtocolDeviceObserverChromeOS(
StorageMonitor::Receiver* receiver,
device::MediaTransferProtocolManager* mtp_manager,
- GetMtpStorageInfoCallback get_mtp_storage_info_cb)
+ const GetMtpStorageInfoCallback& get_mtp_storage_info_cb)
: mtp_manager_(mtp_manager),
get_mtp_storage_info_cb_(get_mtp_storage_info_cb),
notifications_(receiver),
@@ -160,38 +81,39 @@ void MediaTransferProtocolDeviceObserverChromeOS::EjectDevice(
// TODO(thestig): Change this to tell the mtp manager to eject the device.
- StorageChanged(false, location);
+ StorageDetached(location);
callback.Run(StorageMonitor::EJECT_OK);
}
// device::MediaTransferProtocolManager::Observer override.
-void MediaTransferProtocolDeviceObserverChromeOS::StorageChanged(
- bool is_attached,
+void MediaTransferProtocolDeviceObserverChromeOS::StorageAttached(
+ const device::mojom::MtpStorageInfo& mtp_storage_info) {
+ DoAttachStorage(&mtp_storage_info);
+}
+
+// device::MediaTransferProtocolManager::Observer override.
+void MediaTransferProtocolDeviceObserverChromeOS::StorageDetached(
const std::string& storage_name) {
DCHECK(!storage_name.empty());
- // Existing storage is detached.
- if (!is_attached) {
- StorageLocationToInfoMap::iterator it =
- storage_map_.find(GetDeviceLocationFromStorageName(storage_name));
- if (it == storage_map_.end())
- return;
- notifications_->ProcessDetach(it->second.device_id());
- storage_map_.erase(it);
+ StorageLocationToInfoMap::iterator it =
+ storage_map_.find(GetDeviceLocationFromStorageName(storage_name));
+ if (it == storage_map_.end())
return;
- }
-
- // New storage is attached.
- const device::mojom::MtpStorageInfo* mtp_storage_info =
- get_mtp_storage_info_cb_.Run(storage_name);
+ notifications_->ProcessDetach(it->second.device_id());
+ storage_map_.erase(it);
+}
+void MediaTransferProtocolDeviceObserverChromeOS::DoAttachStorage(
+ const device::mojom::MtpStorageInfo* mtp_storage_info) {
if (!mtp_storage_info)
return;
std::string device_id = GetDeviceIdFromStorageInfo(*mtp_storage_info);
base::string16 storage_label =
GetDeviceLabelFromStorageInfo(*mtp_storage_info);
- std::string location = GetDeviceLocationFromStorageName(storage_name);
+ std::string location =
+ GetDeviceLocationFromStorageName(mtp_storage_info->storage_name);
base::string16 vendor_name = base::UTF8ToUTF16(mtp_storage_info->vendor);
base::string16 product_name = base::UTF8ToUTF16(mtp_storage_info->product);
@@ -206,18 +128,10 @@ void MediaTransferProtocolDeviceObserverChromeOS::StorageChanged(
notifications_->ProcessAttach(storage_info);
}
-void MediaTransferProtocolDeviceObserverChromeOS::EnumerateStorages() {
- mtp_manager_->GetStorages(base::BindOnce(
- &MediaTransferProtocolDeviceObserverChromeOS::OnReceivedStorages,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
void MediaTransferProtocolDeviceObserverChromeOS::OnReceivedStorages(
- const std::vector<std::string>& storages) {
- typedef std::vector<std::string> StorageList;
- for (StorageList::const_iterator storage_iter = storages.begin();
- storage_iter != storages.end(); ++storage_iter) {
- StorageChanged(true, *storage_iter);
+ std::vector<const device::mojom::MtpStorageInfo*> storage_info_list) {
+ for (const auto* storage_info : storage_info_list) {
+ DoAttachStorage(storage_info);
}
}
@@ -231,7 +145,6 @@ bool MediaTransferProtocolDeviceObserverChromeOS::GetLocationForDeviceId(
return true;
}
}
-
return false;
}
diff --git a/chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.h b/chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.h
index 0d51e93bffa..23f7074a906 100644
--- a/chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.h
+++ b/chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.h
@@ -21,9 +21,9 @@ class FilePath;
namespace storage_monitor {
// Gets the mtp device information given a |storage_name|.
-using GetMtpStorageInfoCallback =
- base::RepeatingCallback<const device::mojom::MtpStorageInfo*(
- const std::string&)>;
+using GetMtpStorageInfoCallback = base::RepeatingCallback<void(
+ const std::string&,
+ device::MediaTransferProtocolManager::GetStorageInfoCallback)>;
// Helper class to send MTP storage attachment and detachment events to
// StorageMonitor.
@@ -48,22 +48,24 @@ class MediaTransferProtocolDeviceObserverChromeOS
MediaTransferProtocolDeviceObserverChromeOS(
StorageMonitor::Receiver* receiver,
device::MediaTransferProtocolManager* mtp_manager,
- GetMtpStorageInfoCallback get_mtp_storage_info_cb);
+ const GetMtpStorageInfoCallback& get_mtp_storage_info_cb);
// device::MediaTransferProtocolManager::Observer implementation.
// Exposed for unit tests.
- void StorageChanged(bool is_attached,
- const std::string& storage_name) override;
+ void StorageAttached(
+ const device::mojom::MtpStorageInfo& storage_info) override;
+ void StorageDetached(const std::string& storage_name) override;
private:
// Mapping of storage location and mtp storage info object.
typedef std::map<std::string, StorageInfo> StorageLocationToInfoMap;
- // Enumerate existing mtp storage devices.
- void EnumerateStorages();
+ // The async handler for newly attached storage.
+ void DoAttachStorage(const device::mojom::MtpStorageInfo* mtp_storage_info);
- // The callback for EnumerateStorages().
- void OnReceivedStorages(const std::vector<std::string>& storages);
+ // Enumerate existing mtp storage devices.
+ void OnReceivedStorages(
+ std::vector<const device::mojom::MtpStorageInfo*> storage_info_list);
// Find the |storage_map_| key for the record with this |device_id|. Returns
// true on success, false on failure.
diff --git a/chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos_unittest.cc b/chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos_unittest.cc
index 26e20533189..17aaaf97ceb 100644
--- a/chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos_unittest.cc
+++ b/chromium/components/storage_monitor/media_transfer_protocol_device_observer_chromeos_unittest.cc
@@ -9,11 +9,13 @@
#include <memory>
#include <string>
+#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "components/storage_monitor/mock_removable_storage_observer.h"
#include "components/storage_monitor/storage_info.h"
+#include "components/storage_monitor/storage_info_utils.h"
#include "components/storage_monitor/storage_monitor.h"
#include "components/storage_monitor/test_storage_monitor.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -41,20 +43,20 @@ const uint64_t kStorageFreeSpaceInObjects = 0x04000000; // 64M Objects left
const char kStorageDescription[] = "ExampleDescription";
const char kStorageVolumeIdentifier[] = "ExampleVolumeId";
-std::map<std::string, device::mojom::MtpStorageInfo> fake_storage_info_map;
+base::LazyInstance<std::map<std::string, device::mojom::MtpStorageInfo>>::Leaky
+ g_fake_storage_info_map = LAZY_INSTANCE_INITIALIZER;
-// Helper function to get fake MTP device details.
-const device::mojom::MtpStorageInfo* GetFakeMtpStorageInfo(
+const device::mojom::MtpStorageInfo* GetFakeMtpStorageInfoSync(
const std::string& storage_name) {
// Fill the map out if it is empty.
- if (fake_storage_info_map.empty()) {
+ if (g_fake_storage_info_map.Get().empty()) {
// Add the invalid MTP storage info.
auto storage_info = device::mojom::MtpStorageInfo();
storage_info.storage_name = kStorageWithInvalidInfo;
- fake_storage_info_map.insert(
+ g_fake_storage_info_map.Get().insert(
std::make_pair(kStorageWithInvalidInfo, storage_info));
// Add the valid MTP storage info.
- fake_storage_info_map.insert(std::make_pair(
+ g_fake_storage_info_map.Get().insert(std::make_pair(
kStorageWithValidInfo,
device::mojom::MtpStorageInfo(
kStorageWithValidInfo, kStorageVendor, kStorageVendorId,
@@ -65,8 +67,15 @@ const device::mojom::MtpStorageInfo* GetFakeMtpStorageInfo(
kStorageVolumeIdentifier)));
}
- const auto it = fake_storage_info_map.find(storage_name);
- return it != fake_storage_info_map.end() ? &it->second : nullptr;
+ const auto it = g_fake_storage_info_map.Get().find(storage_name);
+ return it != g_fake_storage_info_map.Get().end() ? &it->second : nullptr;
+}
+
+// Helper function to get fake MTP device details.
+void GetFakeMtpStorageInfo(
+ const std::string& storage_name,
+ device::MediaTransferProtocolManager::GetStorageInfoCallback callback) {
+ std::move(callback).Run(GetFakeMtpStorageInfoSync(storage_name));
}
class TestMediaTransferProtocolDeviceObserverChromeOS
@@ -84,7 +93,10 @@ class TestMediaTransferProtocolDeviceObserverChromeOS
// of
// mtp storage device given the |storage_name|.
void MtpStorageAttached(const std::string& storage_name) {
- StorageChanged(true, storage_name);
+ auto* storage_info = GetFakeMtpStorageInfoSync(storage_name);
+ DCHECK(storage_info);
+
+ StorageAttached(*storage_info);
base::RunLoop().RunUntilIdle();
}
@@ -92,7 +104,7 @@ class TestMediaTransferProtocolDeviceObserverChromeOS
// of
// mtp storage device given the |storage_name|.
void MtpStorageDetached(const std::string& storage_name) {
- StorageChanged(false, storage_name);
+ StorageDetached(storage_name);
base::RunLoop().RunUntilIdle();
}
@@ -147,12 +159,17 @@ class MediaTransferProtocolDeviceObserverChromeOSTest : public testing::Test {
// Test to verify basic mtp storage attach and detach notifications.
TEST_F(MediaTransferProtocolDeviceObserverChromeOSTest, BasicAttachDetach) {
+ auto* mtpStorageInfo = GetFakeMtpStorageInfoSync(kStorageWithValidInfo);
+ std::string device_id = GetDeviceIdFromStorageInfo(*mtpStorageInfo);
// Attach a mtp storage.
mtp_device_observer()->MtpStorageAttached(kStorageWithValidInfo);
EXPECT_EQ(1, observer().attach_calls());
EXPECT_EQ(0, observer().detach_calls());
+ 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),
@@ -163,6 +180,7 @@ TEST_F(MediaTransferProtocolDeviceObserverChromeOSTest, BasicAttachDetach) {
EXPECT_EQ(1, observer().attach_calls());
EXPECT_EQ(1, observer().detach_calls());
+ EXPECT_EQ(device_id, observer().last_detached().device_id());
}
// When a mtp storage device with invalid storage label and id is
diff --git a/chromium/components/storage_monitor/storage_info_utils.cc b/chromium/components/storage_monitor/storage_info_utils.cc
new file mode 100644
index 00000000000..0f94ea57eea
--- /dev/null
+++ b/chromium/components/storage_monitor/storage_info_utils.cc
@@ -0,0 +1,98 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/storage_monitor/storage_info_utils.h"
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/storage_monitor/removable_device_constants.h"
+#include "components/storage_monitor/storage_info.h"
+
+namespace storage_monitor {
+
+namespace {
+
+// Device root path constant.
+const char kRootPath[] = "/";
+
+// Returns the storage identifier of the device from the given |storage_name|.
+// E.g. If the |storage_name| is "usb:2,2:65537", the storage identifier is
+// "65537".
+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();
+}
+
+// Returns the |data_store_id| string in the required format.
+// If the |data_store_id| is 65537, this function returns " (65537)".
+std::string GetFormattedIdString(const std::string& data_store_id) {
+ return ("(" + data_store_id + ")");
+}
+
+} // namespace
+
+// Constructs and returns the location of the device using the |storage_name|.
+std::string GetDeviceLocationFromStorageName(const std::string& storage_name) {
+ // Construct a dummy device path using the storage name. This is only used
+ // for registering device media file system.
+ // E.g.: If the |storage_name| is "usb:2,2:12345" then "/usb:2,2:12345" is the
+ // device location.
+ DCHECK(!storage_name.empty());
+ return kRootPath + storage_name;
+}
+
+// Returns a unique device id from the given |storage_info|.
+std::string GetDeviceIdFromStorageInfo(
+ const device::mojom::MtpStorageInfo& storage_info) {
+ const std::string storage_id =
+ GetStorageIdFromStorageName(storage_info.storage_name);
+ if (storage_id.empty())
+ return std::string();
+
+ // Some devices have multiple data stores. Therefore, include storage id as
+ // part of unique id along with vendor, model and volume information.
+ const std::string vendor_id = base::UintToString(storage_info.vendor_id);
+ const std::string model_id = base::UintToString(storage_info.product_id);
+ return StorageInfo::MakeDeviceId(
+ StorageInfo::MTP_OR_PTP,
+ kVendorModelVolumeStoragePrefix + vendor_id + ":" + model_id + ":" +
+ storage_info.volume_identifier + ":" + storage_id);
+}
+
+// Helper function to get device label from storage information.
+base::string16 GetDeviceLabelFromStorageInfo(
+ const device::mojom::MtpStorageInfo& storage_info) {
+ std::string device_label;
+ const std::string& vendor_name = storage_info.vendor;
+ device_label = vendor_name;
+
+ const std::string& product_name = storage_info.product;
+ if (!product_name.empty()) {
+ if (!device_label.empty())
+ device_label += " ";
+ device_label += product_name;
+ }
+
+ // Add the data store id to the device label.
+ if (!device_label.empty()) {
+ const std::string& volume_id = storage_info.volume_identifier;
+ if (!volume_id.empty()) {
+ device_label += GetFormattedIdString(volume_id);
+ } else {
+ const std::string data_store_id =
+ GetStorageIdFromStorageName(storage_info.storage_name);
+ if (!data_store_id.empty())
+ device_label += GetFormattedIdString(data_store_id);
+ }
+ }
+ return base::UTF8ToUTF16(device_label);
+}
+
+} // namespace storage_monitor
diff --git a/chromium/components/storage_monitor/storage_info_utils.h b/chromium/components/storage_monitor/storage_info_utils.h
new file mode 100644
index 00000000000..b471f1c3fdb
--- /dev/null
+++ b/chromium/components/storage_monitor/storage_info_utils.h
@@ -0,0 +1,31 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// StorageInfoUtil provides some general functions to get information
+// from device::mojom::MtpStorageInfo needed by storage_monitor::StorageInfo.
+
+#ifndef COMPONENTS_STORAGE_MONITOR_STORAGE_INFO_UTILS_H_
+#define COMPONENTS_STORAGE_MONITOR_STORAGE_INFO_UTILS_H_
+
+#include <string>
+
+#include "base/strings/string16.h"
+#include "device/media_transfer_protocol/public/mojom/mtp_storage_info.mojom.h"
+
+namespace storage_monitor {
+
+// Constructs and returns the location of the device using the |storage_name|.
+std::string GetDeviceLocationFromStorageName(const std::string& storage_name);
+
+// Returns a unique device id from the given |storage_info|.
+std::string GetDeviceIdFromStorageInfo(
+ const device::mojom::MtpStorageInfo& storage_info);
+
+// Helper function to get device label from storage information.
+base::string16 GetDeviceLabelFromStorageInfo(
+ const device::mojom::MtpStorageInfo& storage_info);
+
+} // namespace storage_monitor
+
+#endif // COMPONENTS_STORAGE_MONITOR_STORAGE_INFO_UTILS_H_
diff --git a/chromium/components/storage_monitor/storage_monitor_chromeos.cc b/chromium/components/storage_monitor/storage_monitor_chromeos.cc
index e17557b80ae..5fe15f96e30 100644
--- a/chromium/components/storage_monitor/storage_monitor_chromeos.cc
+++ b/chromium/components/storage_monitor/storage_monitor_chromeos.cc
@@ -152,7 +152,7 @@ void StorageMonitorCros::CheckExistingMountPoints() {
// AddMountedPath calls.
blocking_task_runner->PostTaskAndReply(
- FROM_HERE, base::Bind(&base::DoNothing),
+ FROM_HERE, base::DoNothing(),
base::Bind(&StorageMonitorCros::MarkInitialized,
weak_ptr_factory_.GetWeakPtr()));
}
diff --git a/chromium/components/storage_monitor/storage_monitor_linux.cc b/chromium/components/storage_monitor/storage_monitor_linux.cc
index 8f674123761..81f60e32bf4 100644
--- a/chromium/components/storage_monitor/storage_monitor_linux.cc
+++ b/chromium/components/storage_monitor/storage_monitor_linux.cc
@@ -13,12 +13,12 @@
#include <limits>
#include <list>
+#include <memory>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
@@ -176,7 +176,7 @@ std::unique_ptr<StorageInfo> GetDeviceInfo(const base::FilePath& device_path,
results_recorder.set_result(true);
- storage_info = base::MakeUnique<StorageInfo>(
+ storage_info = std::make_unique<StorageInfo>(
StorageInfo::MakeDeviceId(type, unique_id), mount_point.value(),
volume_label, vendor_name, model_name,
GetDeviceStorageSize(device_path, device.get()));
@@ -430,7 +430,7 @@ void StorageMonitorLinux::UpdateMtab(const MountPointDeviceMap& new_mtab) {
// AddNewMount calls.
if (!IsInitialized()) {
mounting_task_runner->PostTaskAndReply(
- FROM_HERE, base::Bind(&base::DoNothing),
+ FROM_HERE, base::DoNothing(),
base::Bind(&StorageMonitorLinux::MarkInitialized,
weak_ptr_factory_.GetWeakPtr()));
}
diff --git a/chromium/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc b/chromium/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc
index 8ff26d773b5..a8c6ac2010f 100644
--- a/chromium/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc
+++ b/chromium/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc
@@ -12,7 +12,10 @@ TestMediaTransferProtocolManagerChromeOS::
TestMediaTransferProtocolManagerChromeOS::
~TestMediaTransferProtocolManagerChromeOS() {}
-void TestMediaTransferProtocolManagerChromeOS::AddObserver(Observer* observer) {
+void TestMediaTransferProtocolManagerChromeOS::AddObserverAndEnumerateStorages(
+ Observer* observer,
+ EnumerateStoragesCallback callback) {
+ std::move(callback).Run(std::vector<const device::mojom::MtpStorageInfo*>());
}
void TestMediaTransferProtocolManagerChromeOS::RemoveObserver(
@@ -23,10 +26,10 @@ void TestMediaTransferProtocolManagerChromeOS::GetStorages(
std::move(callback).Run(std::vector<std::string>());
}
-const device::mojom::MtpStorageInfo*
-TestMediaTransferProtocolManagerChromeOS::GetStorageInfo(
- const std::string& storage_name) const {
- return NULL;
+void TestMediaTransferProtocolManagerChromeOS::GetStorageInfo(
+ const std::string& storage_name,
+ GetStorageInfoCallback callback) const {
+ std::move(callback).Run(nullptr);
}
void TestMediaTransferProtocolManagerChromeOS::GetStorageInfoFromDevice(
diff --git a/chromium/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h b/chromium/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h
index 72ec9a2bf02..4db023fdd29 100644
--- a/chromium/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h
+++ b/chromium/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h
@@ -22,11 +22,13 @@ class TestMediaTransferProtocolManagerChromeOS
private:
// device::MediaTransferProtocolManager implementation.
- void AddObserver(Observer* observer) override;
+ void AddObserverAndEnumerateStorages(
+ Observer* observer,
+ EnumerateStoragesCallback callback) override;
void RemoveObserver(Observer* observer) override;
void GetStorages(GetStoragesCallback callback) const override;
- const device::mojom::MtpStorageInfo* GetStorageInfo(
- const std::string& storage_name) const override;
+ void GetStorageInfo(const std::string& storage_name,
+ GetStorageInfoCallback callback) const override;
void GetStorageInfoFromDevice(
const std::string& storage_name,
const GetStorageInfoFromDeviceCallback& callback) override;
diff --git a/chromium/components/strings/BUILD.gn b/chromium/components/strings/BUILD.gn
index a299d38baf7..1f0b61fc4b9 100644
--- a/chromium/components/strings/BUILD.gn
+++ b/chromium/components/strings/BUILD.gn
@@ -4,6 +4,7 @@
import("//build/config/locales.gni")
import("//ppapi/features/features.gni")
+import("//printing/features/features.gni")
import("//tools/grit/grit_rule.gni")
if (is_android) {
@@ -67,7 +68,10 @@ group("strings") {
grit("components_strings") {
source = "../components_strings.grd"
- defines = [ "enable_plugins=$enable_plugins" ]
+ defines = [
+ "enable_plugins=$enable_plugins",
+ "enable_print_preview=$enable_print_preview",
+ ]
outputs = [
"grit/components_strings.h",
diff --git a/chromium/components/strings/components_chromium_strings_sr.xtb b/chromium/components/strings/components_chromium_strings_sr.xtb
index bee837da221..f027efa77fb 100644
--- a/chromium/components/strings/components_chromium_strings_sr.xtb
+++ b/chromium/components/strings/components_chromium_strings_sr.xtb
@@ -4,7 +4,7 @@
<translation id="130631256467250065">Промене ће ступити на снагу када следећи пут поново покренете уређај.</translation>
<translation id="1838412507805038478">Chromium је потврдио да је <ph name="ISSUER" /> издао сертификат овог веб-сајта.</translation>
<translation id="275588974610408078">Извештавање о отказивањима није доступно у Chromium-у.</translation>
-<translation id="3064346599913645280">Прегледате безбедну Chromium страницу.</translation>
+<translation id="3064346599913645280">Гледате безбедну Chromium страницу.</translation>
<translation id="3550966579244642892">Chromium ОС није довршио почетно подешавање.</translation>
<translation id="4365115785552740256">Chromium омогућавају <ph name="BEGIN_LINK_CHROMIUM" />Chromium<ph name="END_LINK_CHROMIUM" /> пројекат отвореног кода и други <ph name="BEGIN_LINK_OSS" />софтвер отвореног кода<ph name="END_LINK_OSS" />.</translation>
<translation id="4559775032954821361">Идите у
diff --git a/chromium/components/strings/components_google_chrome_strings_sr.xtb b/chromium/components/strings/components_google_chrome_strings_sr.xtb
index 96725de5dff..7d6703859a8 100644
--- a/chromium/components/strings/components_google_chrome_strings_sr.xtb
+++ b/chromium/components/strings/components_google_chrome_strings_sr.xtb
@@ -10,7 +10,7 @@
<translation id="3875312571075912821">Дозволите Chrome-у да приступа мрежи у заштитном зиду или антивирусним
подешавањима.</translation>
<translation id="4010643444566880169">Chrome ОС није довршио почетно подешавање.</translation>
-<translation id="4853578032408195113">Прегледате безбедну Google Chrome страницу.</translation>
+<translation id="4853578032408195113">Гледате безбедну Google Chrome страницу.</translation>
<translation id="6011049234605203654">Идите у
Chrome мени &gt;
<ph name="SETTINGS_TITLE" />
diff --git a/chromium/components/strings/components_strings_am.xtb b/chromium/components/strings/components_strings_am.xtb
index 7cd144d9f76..dc520e09479 100644
--- a/chromium/components/strings/components_strings_am.xtb
+++ b/chromium/components/strings/components_strings_am.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;አትም…</translation>
<translation id="1181037720776840403">አስወግድ</translation>
<translation id="1184214524891303587">የደህንነት ሊሆኑ የሚችሉ የክስተቶች ዝርዝሮችን በራስ-ሰር ለGoogle <ph name="BEGIN_WHITEPAPER_LINK" />ሪፖርት ያድርጉ<ph name="END_WHITEPAPER_LINK" />። <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">ክፍያ አልተጠናቀቀም</translation>
<translation id="1201402288615127009">ቀጣይ</translation>
<translation id="1201895884277373915">ተጨማሪ ከዚህ ጣቢያ</translation>
<translation id="1206967143813997005">መጥፎ የመጀመሪያ ፊርማ</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">በ<ph name="CRASH_TIME" /> ላይ የብልሽት ሪፖርት ተይዟል (እስካሁን አልተሰቀለም ወይም ችላ አልተባለም)</translation>
<translation id="1270502636509132238">የመውሰጃ ስልት</translation>
<translation id="1285320974508926690">ይህን ጣቢያ በጭራሽ አትተርጉም</translation>
+<translation id="1294154142200295408">የትእዛዝ መስመር ልዩነቶች</translation>
<translation id="129553762522093515">በቅርብ ጊዜ የተዘጉ</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />ኩኪዎችዎን ማጽዳት ይሞክሩ<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">የእርስዎ እንቅስቃሴ ለሚከተሉት <ph name="BEGIN_EMPHASIS" />አሁንም የሚታይ ሊሆን ይችላል<ph name="END_EMPHASIS" />፦
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">ተቀባይነት ያላቸው ክሬዲት እና ዴቢት ካርዶች</translation>
<translation id="1519264250979466059">የግንብ ቀን</translation>
<translation id="1527263332363067270">ግንኙነትን በመጠበቅ ላይ…</translation>
+<translation id="1532118530259321453">ይህ ገጽ እንዲህ ይላል፦</translation>
<translation id="153384715582417236">ለአሁን ያለው ይኸው ነው</translation>
<translation id="154408704832528245">የማድረሻ አድራሻ ይምረጡ</translation>
<translation id="1549470594296187301">ይህን ባህሪ ለመጠቀም ጃቫስክሪፕት መንቃት አለበት።</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />ወኪሉን እና ኬላውን መፈተሽ<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">ዚፕ ኮድ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 የአስተያየት ጥቆማ}one{# የአስተያየት ጥቆማዎች}other{# የአስተያየት ጥቆማዎች}}</translation>
-<translation id="2065985942032347596">ማረጋገጫ ያስፈልጋል</translation>
<translation id="2079545284768500474">ቀልብስ</translation>
<translation id="20817612488360358">የስርዓት ተኪ ቅንብሮች ስራ ላይ እንዲውሉ ተቀናብረዋል ግን ግልጽ የሆነ የተኪ ውቅርም ተገልጿል።</translation>
<translation id="2091887806945687916">ድምፅ</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">ክፍያን ሰርዝ</translation>
<translation id="2147827593068025794">የጀርባ ስምረት</translation>
<translation id="2148613324460538318">ካርድ አክል</translation>
-<translation id="2149973817440762519">እልባት አርትዕ</translation>
<translation id="2154054054215849342">ስምረት ለእርስዎ ጎራ አይገኝም</translation>
<translation id="2154484045852737596">ካርትን ያርትዑ</translation>
<translation id="2166049586286450108">ሙሉ የአስተዳደር መድረሻ</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">የመውሰጃ አድራሻ ይምረጡ</translation>
<translation id="2740531572673183784">እሺ</translation>
<translation id="2742870351467570537">የተመረጡትን ንጥሎች አስወግድ</translation>
-<translation id="2744590937989388266">በዚህ ገጽ ላይ ካለ የተካተተ ገጽ</translation>
<translation id="277133753123645258">የመላኪያ ዘዴ</translation>
<translation id="277499241957683684">የሚጎድል የመሣሪያ መዝገብ</translation>
<translation id="2784949926578158345">ግንኙነቱ ዳግም እንዲጀምር ተደርጓል።</translation>
<translation id="2788784517760473862">ተቀባይነት ያላቸው ክሬዲት ካርዶች</translation>
<translation id="2794233252405721443">ጣቢያ ታግዷል</translation>
-<translation id="2795286477369100655">ከዚህ ጣቢያ መውጣት ይፈልጋሉ?</translation>
<translation id="2799020568854403057">ቀጥሎ ያለው ጣቢያ ጎጂ መተግበሪያዎች አሉት</translation>
<translation id="2803306138276472711">Google የጥንቃቄ አሰሳ በቅርብ ጊዜ <ph name="SITE" /> ላይ <ph name="BEGIN_LINK" />ተንኮል-አዘል ዌር<ph name="END_LINK" /> አግኝቷል። በመደበኛ ጊዜ ደህንነታቸው የተጠበቁ ድር ጣቢያዎች አንዳንድ ጊዜ በተንኮል-አዘል ዌር ይጠቃሉ።</translation>
<translation id="2824775600643448204">የአድራሻ እና ፍለጋ አሞሌ</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">የዝርዝር ግቤት «<ph name="ENTRY_INDEX" />»፦ <ph name="ERROR" /></translation>
<translation id="301521992641321250">በራስ-ሰር ታግዷል</translation>
<translation id="3024663005179499861">የተሳሳተ የመምሪያ አይነት</translation>
-<translation id="3032412215588512954">ይህን ጣቢያ ዳግም መጫን ይፈልጋሉ?</translation>
<translation id="3037605927509011580">ውይ፣ ተሰናከለ!</translation>
<translation id="3039538478787849737">ካርድ ወደ Google ይቀመጥ?</translation>
<translation id="3041612393474885105">የሰርቲፊኬት መረጃ</translation>
@@ -309,6 +305,7 @@
<translation id="3176929007561373547">ተኪ አገልጋዩ በአግባቡ እየሰራ መሆኑን ለማረጋገጥ የተኪ ቅንብሮችዎን ይፈትሹ ወይም የአውታረ
መረብዎ አስተዳዳሪን ያግኙ። ተኪ አገልጋይ መጠቀም እንደሌለብዎት የሚያምኑ ከሆኑ፦
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> በ<ph name="SERVER_NAME" /> ላይ</translation>
<translation id="320323717674993345">ክፍያን ሰርዝ</translation>
<translation id="3207960819495026254">ዕልባት ተደርጎበታል</translation>
<translation id="3209375525920864198">እባክዎ የሚሠራ የክፍለ-ጊዜ ስም ያስገቡ።</translation>
@@ -366,11 +363,57 @@
<translation id="3556433843310711081">የእርስዎ አስተዳዳሪ እገዳውን ሊያነሱልዎ ይችላሉ</translation>
<translation id="3566021033012934673">ግንኙነትዎ የግል አይደለም</translation>
<translation id="3574305903863751447"><ph name="CITY" />፣ <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" /> ላይ የተካተተ ገጽ እንዲህ ይላል፦</translation>
<translation id="358285529439630156">የክሬዲት እና የቅድመ-ክፍያ ካርዶች ተቀባይነት አላቸው።</translation>
<translation id="3582930987043644930">ስም ያክሉ</translation>
<translation id="3583757800736429874">&amp;ውሰድን ድገም</translation>
<translation id="3586931643579894722">ዝርዝር ደብቅ</translation>
<translation id="3600246354004376029"><ph name="TITLE" />፣ <ph name="DOMAIN" />፣ <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;የግንኙነት ስህተቶችን ያስተካክሉ&lt;/h1&gt;
+ &lt;p&gt;አንድ ድር ጣቢያን ለመጎብኘት ሲሞክሩ የስህተት መልዕክት ካገኙ እነዚህን ማስተካከያዎች ይሞክሩ።&lt;/p&gt;
+ &lt;h2&gt;አብዛኛዎቹን የግንኙነት ስህተቶች ያስተካክሉ&lt;/h2&gt;
+ &lt;p&gt;አንድ ድር ጣቢያን ለመጎብኘት ከሞከሩ እና ካልከፈተ በመጀመሪያ እነዚህን የመላ መፈለጊያ እርምጃዎች በመጠቀም ስህተቱን ለማስተካከል ይሞክሩ፦&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;የድር አድራሻው የአጻጻፍ ግድፈቶች ካለው ይፈትሹ።&lt;/li&gt;
+ &lt;li&gt;የእርስዎ የበይነመረብ ግንኙነት በጤናማ ሁኔታ እየሠራ እንደሆነ ያረጋግጡ።&lt;/li&gt;
+ &lt;li&gt;የድር ጣቢያውን ባለቤት ያነጋግሩ።&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;በተወሰነ የስህተት መልዕክት ላይ እገዛ ያግኙ&lt;/h2&gt;
+ &lt;h3&gt;«የእርስዎ ግንኙነት የግል አይደለም» ወይም «NET::ERR_CERT_AUTHORITY_INVALID» ወይም «ERR_CERT_COMMON_NAME_INVALID» ወይም «NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM» ወይም «የSSL እውቅና ማረጋገጫ ስህተት»&lt;/h3&gt;
+ &lt;h4&gt;እርምጃ 1፦ ወደ መግቢያው በመለያ ይግቡ&lt;/h4&gt;
+ &lt;p&gt;እንደ ካፌዎች ወይም አውሮፕላን ማረፊያዎች ባሉ ቦታዎች ላይ ያሉ የWi-Fi አውታረ መረቦች በመለያ እንዲገቡ ይፈልጋሉ። በመለያ መግቢያውን ገጽ ለማየት &lt;code&gt;http://&lt;/code&gt;ን የሚጠቀምን ገጽ ይጎብኙ&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;እንደ &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt; ያለ በ&lt;code&gt;http://&lt;/code&gt; ወደሚጀምር የሚጀምር ማንኛውም የድር ጣቢያ ይሂዱ።&lt;/li&gt;
+ &lt;li&gt;በሚከፈተው በመለያ መግቢያ ገጽ ላይ በይነመረብን ለመጠቀም በመለያ ይግቡ።&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;እርምጃ 2፦ ገጹን ማንነትን በማያሳውቅ ሁነታ ይክፈቱት (ኮምፒውተር ብቻ)&lt;/h4&gt;
+ &lt;p&gt;እየጎበኙ የነበሩትን ገጽ ማንነትን በማያሳውቅ መስኮት ውስጥ ይክፈቱት።&lt;/p&gt;
+ &lt;p&gt;ገጹ ከተከፈተ የChrome ቅጥያ በትክክል እየሠራ አይደለም ማለት ነው። ይህን ስህተት ለማረም ቅጥያውን ያጥፉት።&lt;/p&gt;
+ &lt;h4&gt;እርምጃ 3፦ የእርስዎን ሥርዓተ ክወና ያዘመኑ&lt;/h4&gt;
+ &lt;p&gt;የእርስዎ መሣሪያ የተዘመነ መሆኑን ያረጋግጡ።&lt;/p&gt;
+ &lt;h4&gt;እርምጃ 4፦ የእርስዎን ፀረ-ቫይረስ ለጊዜው ያጥፉት&lt;/h4&gt;
+ &lt;p&gt;«ኤችቲቲፒኤስ ጥበቃ» ወይም «ኤችቲቲፒኤስ ቅኝት» የሚሰጥ ፀረ-ቫይረስ ሶፍትዌር ካለዎት ይህንን ስህተት ይመለክታሉ።&lt;/p&gt;
+ &lt;p&gt;ችግሩን ለማስተካከል የእርስዎን ፀረ-ቫይረስ ሶፍትዌር ያጥፉት። ሶፍትዌሩ ከጠፋ በኋላ ገጹ ከሠራ ደኅንነታቸው የተጠበቁ ጣቢያዎችን ሲጠቀሙ ይህን ሶፍትዌር ያጥፉት።&lt;/p&gt;
+ &lt;p&gt;ሲጨርሱ የእርስዎን የፀረ-ቫይረስ ፕሮግራም መልሰው ማብራትዎን ያስታውሱ።&lt;/p&gt;
+ &lt;h4&gt;እርምጃ 5፦ ተጨማሪ እገዛ ያግኙ&lt;/h4&gt;
+ &lt;p&gt;አሁንም ስህተቱን ማየትዎትን ከቀጠሉ የድር ጣቢያውን ባለቤት ያነጋግሩ።&lt;/p&gt;
+ &lt;h3&gt;«ከአውታረ መረብ ጋር ይገናኙ»&lt;/h3&gt;
+ &lt;p&gt;መስመር ላይ መሆን ከመቻልዎ በፊት በመለያ ሊገቡበት የሚገባ የWi-Fi መግቢያ እየተጠቀሙ ከሆኑ ይህን ስህተት ይመለከቱታል።&lt;/p&gt;
+ &lt;p&gt;ስህተቱን ለማስተካከል ለመክፈት እየሞከሩ ባሉት ገጽ ላይ &lt;strong&gt;ተገናኝ&lt;/strong&gt;ን ጠቅ ያድርጉ።&lt;/p&gt;
+ &lt;h3&gt;«የእርስዎ ሰዓት ወደ ኋላ ቀርቷል» ወይም «የእርስዎ ሰዓት ወደፊት ቀድሟል» ወይም «NET::ERR_CERT_DATE_INVALID»&lt;/h3&gt;
+ &lt;p&gt;የእርስዎ ኮምፒውተር ወይም ተንቀሳቃሽ መሣሪያ ቀን እና ሰዓት ትክክል ካልሆነ ይህን ስህተት ይመለከታሉ።&lt;/p&gt;
+ &lt;p&gt;ስህተቱን ለማረም የመሣሪያዎን ሰዓት ይክፈቱ። ጊዜው እና ቀኑ ትክክል መሆኑን ያረጋግጡ።&lt;/p&gt;
+ &lt;h3&gt;«በእርስዎ ኮምፒውተር ላይ ያለ ሶፍትዌር Chrome ደህንነቱ በተጠበቀ መንገድ ከድሩ ጋር እንዳይገናኝ እያስቆመው ነው» (Windows ኮምፒውተሮች ብቻ)&lt;/h3&gt;
+ &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;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;ን ጠቅ ያድርጉ
+ &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="3615877443314183785">ትክክለኛ የአገልግሎት ማብቂያ ቀን ያስገቡ</translation>
<translation id="36224234498066874">የአሰሳ ውሂብ አስወግድ…</translation>
<translation id="362276910939193118">ሙሉ ታሪክ አሳይ</translation>
@@ -403,7 +446,6 @@
<translation id="3778403066972421603">ይህን ካርድ በእርስዎ የGoogle መለያ እና በዚህ መሣሪያ ላይ ማስቀመጥ ይፈልጋሉ?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">በ<ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> ላይ የአገልግሎት ጊዜው ያበቃል</translation>
-<translation id="3800436529451849929">ከ<ph name="SITE" /></translation>
<translation id="382518646247711829">ተኪ አገልጋይ የሚጠቀሙ ከሆኑ...</translation>
<translation id="3828924085048779000">ባዶ የይለፍ ሐረግ አይፈቀድም።</translation>
<translation id="385051799172605136">ተመለስ</translation>
@@ -417,6 +459,7 @@
<translation id="3945915738023014686">የተሰቀለ የብልሽት ሪፖርት መታወቂያ <ph name="CRASH_ID" /> (የአካባቢ የብልሽት መታወቂያ፦ <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">ይህ አገልጋይ <ph name="DOMAIN" /> መሆኑን ሊያረጋግጥ አልቻለም፤ የደህንነት ዕውቅና ማረጋገጫው የርዕሰ ጒዳይ አማራጭ ስሞችን አይጠቅስም። ይህ በተሳሳተ ውቅረት የተከሰተ ወይም አጥቂ የእርስዎን ግንኙነት አቋርጦ እየገባ ስለሆነ ሊሆን ይችላል።</translation>
<translation id="3949601375789751990">የአሰሳ ታሪክዎ እዚህ ይመጣል</translation>
+<translation id="3950820424414687140">ይግቡ</translation>
<translation id="3963721102035795474">የአንባቢ ሁነታ</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{ምንም}=1{ከ1 ጣቢያ }one{ከ# ጣቢያዎች }other{ከ# ጣቢያዎች }}</translation>
<translation id="397105322502079400">በማስላት ላይ...</translation>
@@ -433,6 +476,7 @@
<translation id="4103249731201008433">የመሣሪያ መለያ ቁጥር ልክ ያልሆነ ነው</translation>
<translation id="410351446219883937">ራስ-አጫውት</translation>
<translation id="4103763322291513355">የተከለከሉ የዩ አር ኤሎች ዝርዝር እና ሌሎች በስርዓት አስተዳዳሪዎ አስገዳጅነት የተሰጣቸው መመሪያዎችን ለማየት &lt;strong&gt;chrome://policy&lt;/strong&gt;ን ይጎብኙ።</translation>
+<translation id="4110652170750985508">የእርስዎን ክፍያ ይገምግሙ</translation>
<translation id="4116663294526079822">ሁልጊዜ በዚህ ጣቢያ ላይ ፍቀድ</translation>
<translation id="4117700440116928470">የመመሪያ ወሰን አይደገፍም።</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 ሌላ}one{# ሌሎች}other{# ሌሎች}}</translation>
@@ -459,7 +503,6 @@
<translation id="4269787794583293679">(ምንም የተጠቃሚ ስም የለም)</translation>
<translation id="4275830172053184480">መሣሪያዎን ዳግም ያስጀምሩ</translation>
<translation id="4280429058323657511">፣ አገልግሎቱ የሚያበቃው በ<ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">ይግቡ</translation>
<translation id="4312866146174492540">አግድ (ነባሪ)</translation>
<translation id="4325863107915753736">ጽሑፉን ማግኘት አልተቻለም</translation>
<translation id="4326324639298822553">የእርስዎን የአገልግሎት ማብቂያ ቀን ይመልከቱ እና እንደገና ይሞክሩ</translation>
@@ -481,14 +524,12 @@
<translation id="4515275063822566619">ካርዶች እና አድራሻዎች ከChrome እና ከGoogle መለያዎ (<ph name="ACCOUNT_EMAIL" />) የተገኙ ናቸው። በ<ph name="BEGIN_LINK" />ቅንብሮች<ph name="END_LINK" /> ውስጥ ሊያቀናብሯቸው ይችላሉ።</translation>
<translation id="4522570452068850558">ዝርዝሮች</translation>
<translation id="4552089082226364758">ብልጭታ</translation>
-<translation id="4554702541363482291"><ph name="SITE" /> ላይ ካለ የተካተተ ገጽ</translation>
<translation id="4558551763791394412">ቅጥያዎችዎን አሰናክለው ይሞክሩ።</translation>
<translation id="457875822857220463">መላኪያ</translation>
<translation id="4582800630050655161">የGoogle መለያዎን መዳረሻ ሊያጡ ወይም የማንነት ስርቆት ሊያጋጥመዎት ይችላሉ። Chromium የይለፍ ቃልዎን አሁን መቀየር ይመክራል።</translation>
<translation id="4587425331216688090">አድራሻ ከChrome ይወገድ?</translation>
<translation id="4592951414987517459">ወደ የእርስዎ <ph name="DOMAIN" /> ግንኙነት ዘመናዊ የምስጠራ ጥቅል በመጠቀም ተመስጥሯል።</translation>
<translation id="4594403342090139922">&amp;ሰርዝን ቀልብስ</translation>
-<translation id="4611292653554630842">ግባ</translation>
<translation id="4619615317237390068">ከሌሎች መሣሪያዎች የመጡ ትሮች</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">ይህ አገልጋይ <ph name="DOMAIN" /> መሆኑን ሊያረጋግጥ አልቻለም፤ የደህንነት እውቅና ማረጋገጫው ስህተቶች አሉበት። ይሄ በተሳሳተ አወቃቀር ወይም አንድ አጥቂ ግንኙነትዎን በመጥለፉ የተከሰተ ሊሆን ይችላል።</translation>
@@ -498,11 +539,9 @@
<translation id="4708268264240856090">የእርስዎ ግንኙነት ተቋርጧል</translation>
<translation id="471880041731876836">ይህን ጣቢያ የመጎብኘት ፈቃድ የለዎትም</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />የWindows አውታረ መረብ መመርመሪያን በማሄድ ላይ<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">የእርስዎ ክፍያ</translation>
<translation id="4726672564094551039">መምሪያዎችን ዳግም ጫን</translation>
<translation id="4728558894243024398">የመሣሪያ ስርዓት</translation>
<translation id="4736825316280949806">Chromiumን ዳግም ያስጀምሩት</translation>
-<translation id="4737498291095696011">ከዚህ ገጽ</translation>
<translation id="4744603770635761495">የሚፈጸም ዱካ</translation>
<translation id="4749685221585524849">መጨረሻ ላይ ጥቅም ላይ የዋለው በ<ph name="LAST_USED_MONTH" /> ላይ</translation>
<translation id="4750917950439032686">የእርስዎ መረጃ (ለምሳሌ፦ የይለፍ ቃሎች ወይም የክሬዲት ካርድ ቁጥሮች) ወደዚህ ጣቢያ በሚላክበት ጊዜ የግል ነው።</translation>
@@ -521,16 +560,16 @@
<translation id="4850886885716139402">አሳይ</translation>
<translation id="4854362297993841467">የማድረሻ ዘዴው አይገኝም። የተለየ ዘዴ ይሞክሩ።</translation>
<translation id="4858792381671956233">ይህን ገጽ መጎብኘት ችግር ካለው ወላጆችዎንጠይቀዋል</translation>
-<translation id="4871132632506079383"><ph name="SITE" /> ላይ ካለ የተካተተ ገጽ</translation>
<translation id="4880827082731008257">የፍለጋ ታሪክ</translation>
+<translation id="4881695831933465202">ክፈት</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />፣ <ph name="TYPE_2" />፣, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">ማረጋገጫ ያስፈልጋል</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{እና 1 ተጨማሪ ድረ-ገጽ}one{እና # ተጨማሪ ድረ-ገጾች}other{እና # ተጨማሪ ድረ-ገጾች}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">የ<ph name="CREDIT_CARD" /> CVC ያስገቡ። ካረጋገጡ በኋላ የGoogle Payments መለያዎ ካርድ ዝርዝሮች ለዚህ ጣቢያ ይጋራሉ።</translation>
<translation id="4923417429809017348">ገጹ ከማይታወቅ ቋንቋ ወደ <ph name="LANGUAGE_LANGUAGE" /> ተተርጉሟል</translation>
<translation id="4923459931733593730">ክፍያ</translation>
<translation id="4926049483395192435">መገለጽ አለበት።</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> እንዲህ ይላል፦</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">እርምጃዎች</translation>
<translation id="4958444002117714549">ዝርዝሩን ዘርጋ</translation>
@@ -539,7 +578,6 @@
<translation id="5002932099480077015">የነቃ እንደሆነ Chrome ለበለጠ ፈጣን ቅጽ አሞላል ሲባል በዚህ መሳሪያ ላይ ያለው የካርድዎን ቅጂ ያከማቻል።</translation>
<translation id="5018422839182700155">ይህን ገጽ መክፈት አልተቻለም</translation>
<translation id="5019198164206649151">የመጠባበቂያ ማከማቻ በመጥፎ ሁኔታ ላይ</translation>
-<translation id="5020990877659450221">ከዚህ ገጽ</translation>
<translation id="5023310440958281426">የአስተዳዳሪዎ መመሪያዎችን ያረጋግጡ</translation>
<translation id="5029568752722684782">ቅጂን አጽዳ</translation>
<translation id="503069730517007720">ለ«<ph name="SOFTWARE_NAME" />» ስር እውቅና ማረጋገጫ ያስፈልጋል፣ ነገር ግን አልተጫነም። የእርስዎ አይቲ አስተዳዳሪ ይህን ችግር ለመፍታት የ«<ph name="SOFTWARE_NAME" />» ውቅረት መመሪያዎችን መመልከት አለበት። <ph name="FURTHER_EXPLANATION" /></translation>
@@ -565,12 +603,12 @@
<translation id="5172758083709347301">ማሽን</translation>
<translation id="5179510805599951267">በ<ph name="ORIGINAL_LANGUAGE" /> አይደለም? ይህን ስህተት ሪፖርት ያድርጉ</translation>
<translation id="5190835502935405962">የዕልባቶች አሞሌ</translation>
+<translation id="5201306358585911203">በዚህ ድረ-ገጽ ላይ ያለ የተካተተ ገጽ እንዲህ ይላል፦</translation>
<translation id="5205222826937269299">ስም ያስፈልጋል</translation>
<translation id="5222812217790122047">ኢሜይል ያስፈልጋል</translation>
<translation id="522700295135997067">ይህ ጣቢያ አሁን የይለፍ ቃልዎን ሰርቆት ሊሆን ይችላል</translation>
<translation id="5230733896359313003">የሚላክበት አድራሻ</translation>
<translation id="5251803541071282808">ደመና</translation>
-<translation id="5277279256032773186">በሥራ ላይ Chrome እየተጠቀሙ ነዎት? ንግድ ሥራዎች ለሠራተኞቻቸው የChrome ቅንብሮችን ማስተዳደር ይችላሉ። የበለጠ ይረዱ</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />እርስዎ ድር ላይ መሆን እንዲችሉ ሶፍትዌሩን በጊዜያዊነት ለማሰናከል የሚከተሉትን ደረጃዎች ይከተሉ። የአስተዳዳሪ ልዩ መብቶች ሊኖርዎት ይገባል።<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -632,7 +670,6 @@
<translation id="5610142619324316209">ግንኙነቱን መፈተሽ</translation>
<translation id="5610807607761827392">ካርዶችን እና አድራሻዎችን በ<ph name="BEGIN_LINK" />ቅንብሮች<ph name="END_LINK" /> ውስጥ ማቀናበር ይችላሉ።</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> እርስዎን በጣም ብዙ ጊዜ ወደ ሌላ ቦታ መርተዎታል።</translation>
-<translation id="5622887735448669177">ይህን ጣቢያ መውጣት ይፈልጋሉ?</translation>
<translation id="5629630648637658800">የመምሪያ ቅንብሮችን መጫን አልተሳካም</translation>
<translation id="5631439013527180824">ልክ ያልሆነ የመሣሪያ አስተዳደር ማስመሰያ</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>
@@ -655,7 +692,6 @@
<translation id="5786044859038896871">የካርድዎን መረጃ መሙላት ይፈልጋሉ?</translation>
<translation id="5803412860119678065">የእርስዎን <ph name="CARD_DETAIL" /> መሙላት ይፈልጋሉ?</translation>
<translation id="5810442152076338065">ወደ <ph name="DOMAIN" /> ግንኙነትዎ ፍጹማዊ ስነ መሰውር ጥቅል በመጠቀም የተመሳጠረ ነው።</translation>
-<translation id="5810928923025889964">በዚህ ገጽ ላይ ካለ የተካተተ ገጽ</translation>
<translation id="5813119285467412249">&amp;አክልን ድገም</translation>
<translation id="5838278095973806738">በአጥቂዎች ሊሰረቅ ስለሚችል በዚህ ጣቢያ ላይ ማናቸውም አደጋን ሊያስከትል የሚችል መረጃ (ለምሳሌ፦ የይለፍ ቃሎች ወይም የክሬዲት ካርዶች) ማስገባት የለብዎትም።</translation>
<translation id="5866257070973731571">ስልክ ቁጥር ያክሉ</translation>
@@ -729,21 +765,19 @@
<translation id="6446608382365791566">ተጨማሪ መረጃ ያክሉ</translation>
<translation id="6447842834002726250">ኩኪዎች</translation>
<translation id="6451458296329894277">እንደገና ለማስገባት የማረጋገጫ ቅጽ</translation>
-<translation id="6456339708790392414">የእርስዎ ክፍያ</translation>
<translation id="647261751007945333">የመሣሪያ መምሪያዎች</translation>
<translation id="6477321094435799029">Chrome በዚህ ገጽ ላይ ያልተለመደ ኮድ አግኝቷል፣ እና የእርስዎን የግል መረጃ (ለምሳሌ፦ የይለፍ ቃላት፣ ስልክ ቁጥሮች እና ክሬዲት ካርዶች) ለመጠበቅ ሲባል አግዶታል።</translation>
<translation id="6489534406876378309">ድምስሶችን መስቀል ጀምር</translation>
<translation id="6507833130742554667">ክሬዲት እና ዴቢት ካርዶች ተቀባይነት አላቸው።</translation>
<translation id="6508722015517270189">Chromeን ዳግም ያስጀምሩት</translation>
-<translation id="6521373090216409766">ይህን ጣቢያ ዳግም መጫን ይፈልጋሉ?</translation>
<translation id="6529602333819889595">&amp;ሰርዝን ድገም</translation>
<translation id="6534179046333460208">የአካላዊ ድር ጥቆማዎች</translation>
<translation id="6550675742724504774">አማራጮች</translation>
-<translation id="6556239504065605927">ደህንነቱ የተጠበቀ ግንኙነት</translation>
<translation id="6556915248009097796">አገልግሎቱ የሚያበቃው፦ <ph name="EXPIRATION_DATE_ABBR" />፣ ለመጨረሻ ጊዜ ጥቅም ላይ የዋለው በ<ph name="LAST_USED_DATE_NO_DETAIL" /> ላይ</translation>
<translation id="6563469144985748109">የእርስዎ አስተዳዳሪ ገና አላጸደቁትም</translation>
<translation id="6569060085658103619">የቅጥያ ገጽ እየተመለከቱ ነው</translation>
<translation id="6596325263575161958">የምስጠራ አማራጮች</translation>
+<translation id="6604181099783169992">የእንቅስቃሴ ወይም የብርሃን ዳሳሾች</translation>
<translation id="6624427990725312378">የዕውቂያ መረጃ</translation>
<translation id="6626291197371920147">የሚሰራ የካርድ ቁጥር ያክሉ</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> ፍለጋ</translation>
@@ -815,6 +849,7 @@
<translation id="7275334191706090484">የተዳደሩ እልባቶች</translation>
<translation id="7298195798382681320">የተመከሩ</translation>
<translation id="7309308571273880165">በ<ph name="CRASH_TIME" /> ላይ የተነሳ የብልሽት ሪፖርት (ሰቀላ በተጠቃሚ ተጠይቆ ነበር፣ ሆኖም ግን እስካሁን አልተሰቀለም)</translation>
+<translation id="7320336641823683070">የግንኙነት እገዛ</translation>
<translation id="7334320624316649418">&amp;ማስተካከልን ድገም</translation>
<translation id="733923710415886693">የአገልጋዩ የእውቅና ማረጋገጫ በእውቅና ማረጋገጫ ግልጽነት በኩል አልተገለጸም።</translation>
<translation id="7353601530677266744">የትእዛዝ መስመር</translation>
@@ -899,6 +934,7 @@
<translation id="782886543891417279">እየተጠቀሙበት ያለው Wi-Fi (<ph name="WIFI_NAME" />) በመለያ መግቢያ ገጹን እንዲጎበኙ ሊጠይቅዎት ይችላል።</translation>
<translation id="785549533363645510">ሆኖም ግን የማይታዩ አይደሉም። ማንነት የማያሳውቅ ሁነታ መጠቀም የእርስዎን አሰሳ፣ የበይነመረብ አገልግሎት አቅራቢ ወይም የሚጎበኟቸው ድር ጣቢያዎች ከአሰሪዎ አይደብቃቸውም።</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">ከጣቢያ ይወጡ?</translation>
<translation id="7878176543348854470">የዴቢት እና የቅድመ-ክፍያ ካርዶች ተቀባይነት አላቸው።</translation>
<translation id="7878562273885520351">የእርስዎ ይለፍ ቃል ተሰርቆ ሊሆን ይችላል</translation>
<translation id="7887683347370398519">የእርስዎን CVC ይፈትሹ እና እንደገና ይሞክሩ</translation>
@@ -921,6 +957,7 @@
<translation id="8041940743680923270">ሁለንተናዊ ነባሪውን ተጠቀሙ (ጠይቅ)</translation>
<translation id="8042918947222776840">የመውሰጃ ዘዴ ይምረጡ</translation>
<translation id="8057711352706143257">«<ph name="SOFTWARE_NAME" />» በአግባቡ አልተዋቀረም። «<ph name="SOFTWARE_NAME" />»ን ማራገፍ አብዛኛው ጊዜ ችግሩን ይፈታዋል። <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">ጣቢያ ዳግም ይጫን?</translation>
<translation id="8088680233425245692">ጽሑፉን ማየት አልተቻለም።</translation>
<translation id="8091372947890762290">ማግበር በአገልጋዩ ላይ በመጠባበቅ ላይ ነው</translation>
<translation id="8094917007353911263">እየተጠቀሙበት ያለው አውታረ መረብ <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />ን እንዲጎበኙ ሊጠይቅዎት ይችላል።</translation>
@@ -936,6 +973,7 @@
<translation id="8201077131113104583">የማይሰራ የURL ዝማኔ ለቅጥያ ከመታወቂያ «<ph name="EXTENSION_ID" />» ጋር።</translation>
<translation id="8202097416529803614">የትዕዛዝ ማጠቃለያ</translation>
<translation id="8205463626947051446">ጣቢያ ጣልቃ ገቢ ማስታወቂያዎችን የማሳየት አዝማሚያ አለው</translation>
+<translation id="8211406090763984747">ግንኙነት ደኅንነቱ የተጠበቀ ነው</translation>
<translation id="8218327578424803826">የተመደበ መገኛ አካባቢ፦</translation>
<translation id="8225771182978767009">ይህን ኮምፒውተር ያቀናበረው ሰው ይህን ጣቢያ ለማገድ መርጧል።</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />፣ <ph name="TYPE_2" /></translation>
@@ -947,6 +985,7 @@
<translation id="825929999321470778">ሁሉንም የተቀመጡ የይለፍ ቃላትን አሳይ</translation>
<translation id="8261506727792406068">ሰርዝ</translation>
<translation id="8267698848189296333">እንደ <ph name="USERNAME" /> በመግባት ላይ</translation>
+<translation id="8286036467436129157">ግባ</translation>
<translation id="8288807391153049143">የእውቅና ማረጋገጫን አሳይ</translation>
<translation id="8289355894181816810">ይሄ ምን ማለት እንደሆነ እርግጠኛ ካልሆኑ የአውታረ መረብ አስተዳዳሪዎን ያግኙ።</translation>
<translation id="8293206222192510085">እልባት ያክሉ</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">ተቀባይነት ያላቸው የክሬዲት እና የቅድመ-ክፍያ ካርዶች</translation>
<translation id="8759274551635299824">ይህ ካርድ የአገልግሎት ጊዜው አብቅቷል</translation>
<translation id="8761567432415473239">Google የጥንቃቄ አሰሳ በቅርብ ጊዜ በ<ph name="SITE" /> ላይ <ph name="BEGIN_LINK" />ጎጂ ፕሮግርራሞችን አግኝቷል<ph name="END_LINK" />።</translation>
+<translation id="8763927697961133303">የዩኤስቢ መሣሪያ</translation>
<translation id="8790007591277257123">&amp;ሰርዝን ድገም</translation>
<translation id="8800988563907321413">በአቅራቢያዎ ያሉ የአስተያየት ጥቆማዎች እዚህ ይመጣሉ</translation>
<translation id="8820817407110198400">ዕልባቶች</translation>
diff --git a/chromium/components/strings/components_strings_ar.xtb b/chromium/components/strings/components_strings_ar.xtb
index 1e84406fb75..af81e3273e1 100644
--- a/chromium/components/strings/components_strings_ar.xtb
+++ b/chromium/components/strings/components_strings_ar.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">ط&amp;باعة...</translation>
<translation id="1181037720776840403">إزالة</translation>
<translation id="1184214524891303587">‏<ph name="BEGIN_WHITEPAPER_LINK" />إبلاغ Google تلقائيًا<ph name="END_WHITEPAPER_LINK" /> بتفاصيل أي مخاطر أمنية محتملة. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">لم تكتمل عملية الدفع</translation>
<translation id="1201402288615127009">التالي</translation>
<translation id="1201895884277373915">المزيد من هذا الموقع</translation>
<translation id="1206967143813997005">توقيع أوَّلي سيئ</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">تقرير الأعطال الذي تم الحصول عليه في <ph name="CRASH_TIME" /> (لم يتم تحميله بعد أو تجاهله)</translation>
<translation id="1270502636509132238">طريقة الاستلام</translation>
<translation id="1285320974508926690">عدم ترجمة هذا الموقع مطلقًا</translation>
+<translation id="1294154142200295408">صيغ سطر الأوامر</translation>
<translation id="129553762522093515">المغلقة حديثًا</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />جرّب محو ملفات تعريف الارتباط<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">قد يظل <ph name="BEGIN_EMPHASIS" />نشاطك مرئيًا<ph name="END_EMPHASIS" /> للجهات التالية:
@@ -74,9 +74,10 @@
<translation id="1517500485252541695">بطاقات الائتمان وبطاقات السحب الآلي المقبولة</translation>
<translation id="1519264250979466059">تاريخ الإصدار</translation>
<translation id="1527263332363067270">في انتظار الاتصال…</translation>
+<translation id="1532118530259321453">تعرض هذه الصفحة</translation>
<translation id="153384715582417236">هذا كل شيء الآن</translation>
<translation id="154408704832528245">اختيار عنوان التسليم للمستخدم</translation>
-<translation id="1549470594296187301">‏يجب تمكين JavaScript لاستخدام هذه الميزة.</translation>
+<translation id="1549470594296187301">‏يجب تفعيل JavaScript لاستخدام هذه الميزة.</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;
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />التحقق من الخادم الوكيل والجدار الناري<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">الرمز البريدي</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{اقتراح واحد}zero{# اقتراح}two{اقتراحان (#)}few{# اقتراحات}many{# اقتراحًا}other{# اقتراح}}</translation>
-<translation id="2065985942032347596">يجب إدخال اسم المستخدم وكلمة المرور</translation>
<translation id="2079545284768500474">تراجع</translation>
<translation id="20817612488360358">تم تعيين إعدادات الخادم الوكيل ليتم استخدامها وتم أيضًا تحديد تهيئة صريحة للخادم الوكيل.</translation>
<translation id="2091887806945687916">الصوت</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">إلغاء الدفع</translation>
<translation id="2147827593068025794">مزامنة الخلفية</translation>
<translation id="2148613324460538318">إضافة بطاقة</translation>
-<translation id="2149973817440762519">تعديل الإشارة</translation>
<translation id="2154054054215849342">المزامنة غير متاحة لنطاقك</translation>
<translation id="2154484045852737596">تعديل البطاقة</translation>
<translation id="2166049586286450108">الوصول الكامل للمشرف</translation>
@@ -168,7 +167,7 @@
<translation id="2181821976797666341">السياسات</translation>
<translation id="2183608646556468874">رقم الهاتف</translation>
<translation id="2184405333245229118">{COUNT,plural, =1{عنوان واحد}zero{# عنوان}two{عنوانان (#)}few{# عناوين}many{# عنوانًا}other{# عنوان}}</translation>
-<translation id="2187317261103489799">اكتشاف (افتراضي)</translation>
+<translation id="2187317261103489799">اكتشاف (تلقائي)</translation>
<translation id="2202020181578195191">أدخِل سنة تاريخ انتهاء صلاحية صحيحة</translation>
<translation id="2212735316055980242">تعذر العثور على السياسة</translation>
<translation id="2213606439339815911">جارٍ جلب الإدخالات...</translation>
@@ -192,7 +191,7 @@
<translation id="2359808026110333948">المتابعة</translation>
<translation id="2365563543831475020">لم يتم تحميل تقرير الأعطال الذي تم الحصول عليه في <ph name="CRASH_TIME" /></translation>
<translation id="2367567093518048410">المستوى</translation>
-<translation id="2384307209577226199">السياسة افتراضية في المؤسسة ويمكن إلغاؤها</translation>
+<translation id="2384307209577226199">السياسة تلقائية في المؤسسة ويمكن إلغاؤها</translation>
<translation id="2386255080630008482">تم إبطال شهادة الخادم.</translation>
<translation id="2392959068659972793">عرض السياسات التي لم يتم تعيين قيم لها</translation>
<translation id="239429038616798445">طريقة الشحن هذه غير متاحة، جرِّب طريقة أخرى.</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">اختيار عنوان الاستلام من المستخدم</translation>
<translation id="2740531572673183784">موافق</translation>
<translation id="2742870351467570537">إزالة العناصر المحددة</translation>
-<translation id="2744590937989388266">من صفحة مضمّنة في هذه الصفحة</translation>
<translation id="277133753123645258">طريقة الشحن</translation>
<translation id="277499241957683684">سجِلّ الجهاز مفقود</translation>
<translation id="2784949926578158345">تمت إعادة تعيين الاتصال.</translation>
<translation id="2788784517760473862">بطاقات الائتمان المقبولة</translation>
<translation id="2794233252405721443">تم حظر الموقع</translation>
-<translation id="2795286477369100655">هل تريد الخروج من هذا الموقع؟</translation>
<translation id="2799020568854403057">يحتوي موقع الويب المقصود على تطبيقات ضارة</translation>
<translation id="2803306138276472711">‏اكتشف التصفح الآمن من Google مؤخرًا <ph name="BEGIN_LINK" />برامج ضارة<ph name="END_LINK" /> على <ph name="SITE" />. أحيانًا تصاب مواقع الويب الآمنة في الوضع العادي ببرامج ضارة.</translation>
<translation id="2824775600643448204">شريط العناوين والبحث</translation>
@@ -267,7 +264,7 @@
<translation id="2928905813689894207">عنوان إرسال الفواتير</translation>
<translation id="2929525460561903222">{SHIPPING_ADDRESS,plural, =0{<ph name="SHIPPING_ADDRESS_PREVIEW" />}=1{<ph name="SHIPPING_ADDRESS_PREVIEW" /> وعنوان <ph name="NUMBER_OF_ADDITIONAL_ADDRESSES" /> آخر}two{<ph name="SHIPPING_ADDRESS_PREVIEW" /> وعنوانان (<ph name="NUMBER_OF_ADDITIONAL_ADDRESSES" />) آخران}few{<ph name="SHIPPING_ADDRESS_PREVIEW" /> و<ph name="NUMBER_OF_ADDITIONAL_ADDRESSES" /> عناوين أخرى}many{<ph name="SHIPPING_ADDRESS_PREVIEW" /> و<ph name="NUMBER_OF_ADDITIONAL_ADDRESSES" /> عنوانًا آخر}other{<ph name="SHIPPING_ADDRESS_PREVIEW" /> و<ph name="NUMBER_OF_ADDITIONAL_ADDRESSES" /> عنوان آخر}}</translation>
<translation id="2941952326391522266">هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />؛ بل إنه شهادة أمان من <ph name="DOMAIN2" />. وربما سبب ذلك خطأ في التكوين أو مهاجمًا يعترض اتصالك.</translation>
-<translation id="2948083400971632585">يمكنك تعطيل أي خوادم وكيلة تمت تهيئتها لاتصال من صفحة الإعدادات.</translation>
+<translation id="2948083400971632585">يمكنك إيقاف أي خوادم وكيلة تمت تهيئتها لاتصال من صفحة الإعدادات.</translation>
<translation id="2955913368246107853">إغلاق شريط البحث</translation>
<translation id="2958431318199492670">‏لا تتوافق تهيئة الشبكة مع معيار ONC. قد لا يتم استيراد بعض أجزاء التهيئة.</translation>
<translation id="2966678944701946121">تاريخ انتهاء الصلاحية: <ph name="EXPIRATION_DATE_ABBR" />، وتمت الإضافة في <ph name="ADDED_TO_AUTOFILL_MONTH" /></translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">إدخال القائمة "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">تم الحظر تلقائيًا</translation>
<translation id="3024663005179499861">نوع السياسة غير صحيح</translation>
-<translation id="3032412215588512954">هل تريد إعادة تحميل هذا الموقع؟</translation>
<translation id="3037605927509011580">عذرًا!</translation>
<translation id="3039538478787849737">‏هل تريد حفظ البطاقة في Google؟</translation>
<translation id="3041612393474885105">معلومات الشهادة</translation>
@@ -310,6 +306,7 @@
للتأكد من عمل الخادم الوكيل. فإذا كنت لا تعتقد أنه يجب عليك استخدام
خادم وكيل:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> على <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">إلغاء الدفع</translation>
<translation id="3207960819495026254">محدد بعلامة متابعة القراءة</translation>
<translation id="3209375525920864198">يُرجى إدخال اسم صالح للجلسة.</translation>
@@ -348,10 +345,10 @@
<translation id="3399952811970034796">عنوان التسليم</translation>
<translation id="3422248202833853650">جرّب الخروج من البرامج الأخرى لتفريغ مساحة من الذاكرة.</translation>
<translation id="3422472998109090673">يتعذر الوصول إلى <ph name="HOST_NAME" /> حاليًا.</translation>
-<translation id="3427092606871434483">السماح (افتراضي)</translation>
+<translation id="3427092606871434483">السماح (تلقائي)</translation>
<translation id="3427342743765426898">إعادة الت&amp;حرير</translation>
<translation id="3431636764301398940">حفظ هذه البطاقة إلى هذا الجهاز</translation>
-<translation id="3447661539832366887">عطل مالك هذا الجهاز تشغيل لعبة الديناصور.</translation>
+<translation id="3447661539832366887">أوقف مالك هذا الجهاز تشغيل لعبة الديناصور.</translation>
<translation id="3447884698081792621">عرض الشهادة (من إصدار <ph name="ISSUER" />)</translation>
<translation id="3452404311384756672">الفاصل الزمني للجلب:</translation>
<translation id="3462200631372590220">الإخفاء (خيار متقدم)</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">يمكن لمديرك إلغاء الحظر لك</translation>
<translation id="3566021033012934673">اتصالك ليس خاصًا</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">تعرض صفحة مُضمنة في موقع <ph name="SITE" /></translation>
<translation id="358285529439630156">يتم قبول بطاقات الائتمان وبطاقات الدفع المسبق.</translation>
<translation id="3582930987043644930">إضافة اسم</translation>
<translation id="3583757800736429874">إ&amp;عادة النقل</translation>
<translation id="3586931643579894722">إخفاء التفاصيل</translation>
<translation id="3600246354004376029"><ph name="TITLE" />، و<ph name="DOMAIN" />، و<ph name="TIME" /></translation>
+<translation id="3602137825010714926">‏&lt;h1&gt;إصلاح أخطاء الاتصال&lt;/h1&gt;
+ &lt;p&gt;إذا تلقيت رسالة خطأ عند الانتقال إلى أحد مواقع الويب، يمكنك تجربة هذه الإصلاحات.&lt;/p&gt;
+ &lt;h2&gt;إصلاح معظم أخطاء الاتصال&lt;/h2&gt;
+ &lt;p&gt;إذا كنت تحاول الانتقال إلى أحد مواقع الويب وتعذّر فتحه، يُرجى تجربة إصلاح الخطأ أولاً باتباع الخطوات التالية لتحرّي الخلل وإصلاحه:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;تحقق من عنوان الويب بحثًا عن الأخطاء الإملائية.&lt;/li&gt;
+ &lt;li&gt;تأكد من أن اتصال الإنترنت يعمل بشكل طبيعي.&lt;/li&gt;
+ &lt;li&gt;اتّصل بمالك موقع الويب.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;احصل على المساعدة بخصوص رسالة خطأ محددة&lt;/h2&gt;
+ &lt;h3&gt;"اتصالك لا يتمتع بالخصوصية" أو "NET::ERR_CERT_AUTHORITY_INVALID" أو "ERR_CERT_COMMON_NAME_INVALID" أو "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" أو "خطأ في شهادة طبقة المقابس الآمنة (SSL)"&lt;/h3&gt;
+ &lt;h4&gt;الخطوة 1: تسجيل الدخول إلى البوابة&lt;/h4&gt;
+ &lt;p&gt;تتطلب منك شبكات Wi-Fi في أماكن مثل المقاهي أو المطارات تسجيل الدخول. للاطلاع على صفحة تسجيل الدخول، انتقل إلى إحدى الصفحات التي تستخدم&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;انتقل إلى أي موقع ويب يبدأ بـ &lt;code&gt;http://&lt;/code&gt;، مثل &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;عندما تفتح صفحة تسجيل الدخول، سجّل الدخول لاستخدام الإنترنت.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;الخطوة 2: فتح الصفحة في وضع التصفح المتخفي (جهاز الكمبيوتر فقط)&lt;/h4&gt;
+ &lt;p&gt;افتح الصفحة التي كنت تعرضها في نافذة تصفح متخفٍ.&lt;/p&gt;
+ &lt;p&gt;في حال فتح إحدى الصفحات، لا تعمل إضافة Chrome بشكلٍ صحيح. ولإصلاح الخطأ، يمكنك إيقاف الإضافة.&lt;/p&gt;
+ &lt;h4&gt;الخطوة 3: تحديث نظام التشغيل&lt;/h4&gt;
+ &lt;p&gt;تأكد من تحديث نظام التحديث على جهازك.&lt;/p&gt;
+ &lt;h4&gt;الخطوة 4: إيقاف برامج مكافحة الفيروسات مؤقَّتًا&lt;/h4&gt;
+ &lt;p&gt;سيظهر لك هذا الخطأ إذا كان لديك برنامج لمكافحة الفيروسات يوفر "حماية HTTPS" أو "فحص HTTPS"، إذ يعمل برنامج مكافحة الفيروسات على منع متصفح Chrome من توفير الأمان.&lt;/p&gt;
+ &lt;p&gt;لإصلاح المشكلة، أوقف برنامج مكافحة الفيروسات على جهازك. وفي حال استمرار عمل الصفحة بعد إيقاف البرنامج، يمكنك إيقاف هذا البرنامج عند استخدام مواقع آمنة.&lt;/p&gt;
+ &lt;p&gt;ينبغي تفعيل برنامج مكافحة الفيروسات عند الانتهاء.&lt;/p&gt;
+ &lt;h4&gt;الخطوة 5: الحصول على مساعدة إضافية&lt;/h4&gt;
+ &lt;p&gt;في حال استمرار ظهور هذا الخطأ، اتصل بمالك موقع الويب.&lt;/p&gt;
+ &lt;h3&gt;"الاتصال بالشبكة"&lt;/h3&gt;
+ &lt;p&gt;سيظهر لك هذا الخطأ إذا كنت تستخدم بوابة شبكة Wi-Fi تطلب منك تسجيل الدخول قبل أن تتمكن من الاتصال بالإنترنت.&lt;/p&gt;
+ &lt;p&gt;يمكنك إصلاح الخطأ عن طريق النقر على &lt;strong&gt;اتصال&lt;/strong&gt; في الصفحة التي تحاول فتحها.&lt;/p&gt;
+ &lt;h3&gt;"توقيت ساعتك متأخِّر" أو "توقيت ساعتك متقدِّم" أو "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;سيظهر لك هذا الخطأ إذا كان الوقت والتاريخ لجهاز الكمبيوتر أو جهاز الجوّال غير دقيقين.&lt;/p&gt;
+ &lt;p&gt;لإصلاح هذا الخطأ، افتح ساعة جهازك، وتأكد من صحة الوقت والتاريخ.&lt;/p&gt;
+ &lt;h3&gt;"تعمل البرامج على جهاز الكمبيوتر على منع اتصال Chrome بأمان بالويب" (أجهزة الكمبيوتر المزوّدة بنظام التشغيل Windows فقط)&lt;/h3&gt;
+ &lt;p&gt;سيظهر لك هذا الخطأ إذا كان لديك برنامج Superfish على جهاز الكمبيوتر المزوّد بنظام التشغيل Windows.&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;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;.
+ &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="3615877443314183785">أدخِل تاريخ انتهاء صلاحية صحيحًا</translation>
<translation id="36224234498066874">مسح بيانات التصفح...</translation>
<translation id="362276910939193118">عرض السجل بكامله</translation>
@@ -399,12 +442,11 @@
<translation id="3744899669254331632">‏لا يمكنك زيارة <ph name="SITE" /> في الوقت الحالي لأن الموقع أرسل اعتمادات مختلطة حيث لا يستطيع Chromium المعالجة. أخطاء الشبكة وهجماتها عادةً ما تكون مؤقتة، لذلك من المحتمل أن تعمل هذه الصفحة في وقت لاحق.</translation>
<translation id="3748148204939282805">قد يخدعك المهاجمون على <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> لتنفيذ أمور خطيرة، مثل تثبيت البرامج أو نشر معلوماتك الشخصية (على سبيل المثال، كلمات المرور، أو أرقام الهاتف، أو بطاقات الائتمان). <ph name="BEGIN_LEARN_MORE_LINK" />مزيد من المعلومات<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">تعذّرت الترجمة بسبب حدوث خطأ في الخادم.</translation>
-<translation id="3759461132968374835">ليس لديك أي أعطال تم الإبلاغ عنها مؤخرًا. الأعطال التي حدثت عندما تم تعطيل الإبلاغ عن الأعطال لن تظهر هنا.</translation>
+<translation id="3759461132968374835">ليس لديك أي أعطال تم الإبلاغ عنها مؤخرًا. الأعطال التي حدثت عندما تم إيقاف الإبلاغ عن الأعطال لن تظهر هنا.</translation>
<translation id="3765032636089507299">صفحة التصفح الآمن تحت الإنشاء.</translation>
<translation id="3778403066972421603">‏هل تريد حفظ هذه البطاقة في حسابك في Google وعلى هذا الجهاز؟</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">تنتهي في <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">من <ph name="SITE" /></translation>
<translation id="382518646247711829">إذا كنت تستخدم خادمًا وكيلاً...</translation>
<translation id="3828924085048779000">غير مسموح باستخدام عبارة مرور فارغة.</translation>
<translation id="385051799172605136">الرجوع إلى الوراء</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">تحميل مُعرّف تقارير الأعطال <ph name="CRASH_ID" /> (مُعرّف الأعطال المحلية: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">لم يتمكن هذا الخادم من إثبات أنه <ph name="DOMAIN" />؛ بل إن شهادة الأمان التابعة له لا تُحدّد الأسماء البديلة للمضيفات. وربما يكون السبب في ذلك وجود خطأ في التهيئة أو اعتراض أحد المهاجمين للاتصال.</translation>
<translation id="3949601375789751990">يظهر سجلّ التصفّح هنا</translation>
+<translation id="3950820424414687140">تسجيل الدخول</translation>
<translation id="3963721102035795474">وضع القارئ</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{بدون}=1{من موقع واحد }two{من موقعين (#) }few{من # مواقع }many{من # موقعًا }other{من # موقع }}</translation>
<translation id="397105322502079400">جارٍ الحساب...</translation>
@@ -434,13 +477,14 @@
<translation id="4103249731201008433">الرقم التسلسلي للجهاز غير صالح</translation>
<translation id="410351446219883937">تشغيل تلقائي</translation>
<translation id="4103763322291513355">‏انتقل إلى &lt;strong&gt;chrome://policy&lt;/strong&gt; لمشاهدة قائمة بعناوين URL المضافة إلى القائمة السوداء والسياسات الأخرى التي فرضها مشرف النظام.</translation>
+<translation id="4110652170750985508">مراجعة الدفعة</translation>
<translation id="4116663294526079822">إلغاء الحظر دومًا على هذا الموقع</translation>
<translation id="4117700440116928470">نطاق السياسة غير متوافق.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{عنصر واحد آخر}zero{# عنصر آخر}two{عنصران آخران (#)}few{# عناصر أخرى}many{# عنصرًا آخر}other{# عنصر آخر}}</translation>
<translation id="4130226655945681476">التحقق من كابلات الشبكة، والمودم، وجهاز التوجيه</translation>
<translation id="413544239732274901">مزيد من المعلومات</translation>
<translation id="4148925816941278100">American Express</translation>
-<translation id="4151403195736952345">استخدام الإعدادات العمومية الافتراضية (كشف)</translation>
+<translation id="4151403195736952345">استخدام الإعدادات العمومية التلقائية (كشف)</translation>
<translation id="4165986682804962316">إعدادات الموقع</translation>
<translation id="4169947484918424451">‏هل تريد من Chromium حفظ هذه البطاقة؟</translation>
<translation id="4171400957073367226">توقيع تحقق سيئ</translation>
@@ -460,8 +504,7 @@
<translation id="4269787794583293679">(اسم المستخدم غير موجود)</translation>
<translation id="4275830172053184480">إعادة تشغيل جهازك</translation>
<translation id="4280429058323657511">، تاريخ انتهاء الصلاحية <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">تسجيل الدخول</translation>
-<translation id="4312866146174492540">حظر (افتراضي)</translation>
+<translation id="4312866146174492540">حظر (تلقائي)</translation>
<translation id="4325863107915753736">تعذّر العثور على المقالة</translation>
<translation id="4326324639298822553">تحقق من تاريخ انتهاء الصلاحية وأعِد المحاولة مرة أخرى</translation>
<translation id="4331708818696583467">غير آمن</translation>
@@ -474,7 +517,7 @@
<translation id="4415426530740016218">عنوان الاستلام</translation>
<translation id="4424024547088906515">‏هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />؛ بل إنه شهادة أمان غير موثوقة من قبل Chrome. وربما يكون السبب في ذلك خطأ في التكوين أو مهاجمًا يعترض الاتصال.</translation>
<translation id="4432688616882109544">لم يقبل <ph name="HOST_NAME" /> شهادة تسجيل الدخول أو من المحتمل ألا يكون قد تم تقديم واحدة.</translation>
-<translation id="443673843213245140">تم تعطيل استخدام الخادم الوكيل ولكن تم تحديد تهيئة صريحة للخادم الوكيل.</translation>
+<translation id="443673843213245140">تم إيقاف استخدام الخادم الوكيل ولكن تم تحديد تهيئة صريحة للخادم الوكيل.</translation>
<translation id="445100540951337728">بطاقات السحب الآلي المقبولة</translation>
<translation id="4506176782989081258">خطأ في عملية التحقق: <ph name="VALIDATION_ERROR" />.</translation>
<translation id="4506599922270137252">الاتصال بمشرف النظام</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">‏تأتي البطاقات والعناوين من Chrome وحسابك في Google (<ph name="ACCOUNT_EMAIL" />). ويمكنك إدارتها في <ph name="BEGIN_LINK" />الإعدادات<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">التفاصيل</translation>
<translation id="4552089082226364758">الفلاش</translation>
-<translation id="4554702541363482291">من صفحة مُضمنة في <ph name="SITE" /></translation>
-<translation id="4558551763791394412">جرّب تعطيل الإضافات.</translation>
+<translation id="4558551763791394412">جرّب إيقاف الإضافات.</translation>
<translation id="457875822857220463">التسليم</translation>
<translation id="4582800630050655161">‏من الممكن أن تفقد إمكانية الوصول إلى حسابك في Google أو تتعرض لسرقة هويتك. لذا يوصي Chromium بتغيير كلمة مرورك الآن.</translation>
<translation id="4587425331216688090">‏هل تريد إزالة العنوان من Chrome؟</translation>
<translation id="4592951414987517459">يتم ترميز اتصالك بالنطاق <ph name="DOMAIN" /> باستخدام مجموعة تشفير حديثة.</translation>
<translation id="4594403342090139922">تراجع عن الحذ&amp;ف</translation>
-<translation id="4611292653554630842">تسجيل الدخول</translation>
<translation id="4619615317237390068">علامات التبويب من الأجهزة الأخرى</translation>
<translation id="4668929960204016307">،</translation>
<translation id="467662567472608290">هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />؛ بل إنه شهادة أمان تحتوي على أخطاء. وربما يكون السبب في ذلك خطأ في التكوين أو مهاجمًا يعترض اتصالك.</translation>
@@ -499,20 +540,18 @@
<translation id="4708268264240856090">تم قطع اتصالك</translation>
<translation id="471880041731876836">ليس لديك إذن لزيارة هذا الموقع</translation>
<translation id="4722547256916164131">‏<ph name="BEGIN_LINK" />تشغيل بيانات تشخيص شبكة Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">دفعتك</translation>
<translation id="4726672564094551039">إعادة تحميل السياسات</translation>
<translation id="4728558894243024398">النظام الأساسي</translation>
<translation id="4736825316280949806">‏إعادة تشغيل Chromium</translation>
-<translation id="4737498291095696011">من هذه الصفحة</translation>
<translation id="4744603770635761495">المسار التنفيذي</translation>
<translation id="4749685221585524849">تاريخ آخر استخدام: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">إن معلوماتك (على سبيل المثال، كلمات المرور أو أرقام بطاقة الائتمان) تكون خاصة عندما يتم إرسالها إلى هذا الموقع.</translation>
<translation id="4756388243121344051">ال&amp;سجل</translation>
<translation id="4758311279753947758">إضافة معلومات الاتصال</translation>
-<translation id="4759118997339041434">تم تعطيل الملء التلقائي لعملية الدفع</translation>
+<translation id="4759118997339041434">تم إيقاف الملء التلقائي لعملية الدفع</translation>
<translation id="4764776831041365478">قد تكون صفحة الويب على العنوان <ph name="URL" /> غير متاحة مؤقتًا أو قد يكون تم نقلها نهائيًا إلى عنوان ويب جديد.</translation>
<translation id="4771973620359291008">حدث خطأ غير محدّد.</translation>
-<translation id="4792143361752574037">حدثت مشكلة أثناء الوصول إلى ملفات الجلسة. ويتم حاليًا تعطيل الحفظ إلى القرص. يُرجى إعادة تحميل الصفحة للمحاولة مرة أخرى.</translation>
+<translation id="4792143361752574037">حدثت مشكلة أثناء الوصول إلى ملفات الجلسة. ويتم حاليًا إيقاف الحفظ إلى القرص. يُرجى إعادة تحميل الصفحة للمحاولة مرة أخرى.</translation>
<translation id="4800132727771399293">‏تحقق من تاريخ انتهاء الصلاحية ورمز التحقق من البطاقة (CVC) وأعد المحاولة مرة أخرى.</translation>
<translation id="4803924862070940586"><ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
<translation id="4807049035289105102">‏لا يمكنك زيارة <ph name="SITE" /> الآن نظرًا لأن موقع الويب أرسل بيانات اعتماد مختلطة يتعذر على Google Chrome معالجتها. وعادةً ما تكون أخطاء الشبكة والهجمات عليها مؤقتة؛ لذا ستعمل هذه الصفحة لاحقًا على الأرجح.</translation>
@@ -522,25 +561,24 @@
<translation id="4850886885716139402">عرض</translation>
<translation id="4854362297993841467">طريقة التسليم هذه غير متاحة. جرِّب طريقة أخرى.</translation>
<translation id="4858792381671956233">لقد سألت والديك ما إذا كانت زيارة هذا الموقع مناسبةً لك</translation>
-<translation id="4871132632506079383">من صفحة مُضمنة في <ph name="SITE" /></translation>
<translation id="4880827082731008257">سجلّ البحث</translation>
+<translation id="4881695831933465202">فتح</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />، <ph name="TYPE_2" />، <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">المصادقة مطلوبة</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{وصفحة ويب واحدة إضافية}zero{و# صفحة ويب إضافية}two{وصفحتا ويب (#) إضافيتان}few{و# صفحات ويب إضافية}many{و# صفحة ويب إضافية}other{و# صفحة ويب إضافية}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">‏أدخل رمز التحقق من البطاقة (CVC) لـ <ph name="CREDIT_CARD" />. وبعد التأكيد، ستتم مشاركة تفاصيل البطاقة من حساب دفعات Google مع هذا الموقع.</translation>
<translation id="4923417429809017348">تمت ترجمة هذه الصفحة من لغة غير معروفة إلى اللغة <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">الدفع</translation>
<translation id="4926049483395192435">يجب تحديدها.</translation>
+<translation id="4926159001844873046">يعرض موقع <ph name="SITE" /></translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">إجراءات</translation>
<translation id="4958444002117714549">توسيع القائمة</translation>
-<translation id="4974590756084640048">إعادة تمكين التحذيرات</translation>
+<translation id="4974590756084640048">إعادة تفعيل التحذيرات</translation>
<translation id="4989809363548539747">هذا المكوِّن الإضافي غير مدعوم</translation>
<translation id="5002932099480077015">‏إذا تم التمكين، سيخزن Chrome نسخة من بطاقتك على هذا الجهاز لملء النموذج بشكل أسرع.</translation>
<translation id="5018422839182700155">يتعذّر فتح هذه الصفحة</translation>
<translation id="5019198164206649151">التخزين المساعد في حالة سيئة</translation>
-<translation id="5020990877659450221">من هذه الصفحة</translation>
<translation id="5023310440958281426">التحقق من سياسات المشرف</translation>
<translation id="5029568752722684782">محو النسخة</translation>
<translation id="503069730517007720">يلزم شهادة جذر لـ "<ph name="SOFTWARE_NAME" />" ولكن لم يتم تثبيتها. ينبغي على مشرف تقنية المعلومات أن يلقي نظرة على تعليمات التهيئة لـ "<ph name="SOFTWARE_NAME" />" لإصلاح تلك المشكلة. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,18 +604,18 @@
<translation id="5172758083709347301">الجهاز</translation>
<translation id="5179510805599951267">هل الصفحة ليست باللغة <ph name="ORIGINAL_LANGUAGE" />؟ الإبلاغ عن هذا الخطأ</translation>
<translation id="5190835502935405962">شريط الإشارات</translation>
+<translation id="5201306358585911203">تعرض صفحة مضمّنة في هذه الصفحة</translation>
<translation id="5205222826937269299">الاسم مطلوب</translation>
<translation id="5222812217790122047">البريد الإلكتروني مطلوب</translation>
<translation id="522700295135997067">من المحتمل أن يكون موقع الويب هذا قد سرق كلمة مرورك للتو</translation>
<translation id="5230733896359313003">عنوان الشحن</translation>
<translation id="5251803541071282808">السحاب</translation>
-<translation id="5277279256032773186">‏هل تستخدم Chrome في العمل؟ يمكن للأنشطة التجارية إدارة إعدادات Chrome لموظفيها. تعرَّف على المزيد</translation>
-<translation id="5281113152797308730">‏<ph name="BEGIN_PARAGRAPH" />اتبع هذه الخطوات لتعطيل البرامج مؤقتًا حتى يتسنى لك الوصول إلى الويب. سيلزمك الحصول على امتيازات المشرف.<ph name="END_PARAGRAPH" />
+<translation id="5281113152797308730">‏<ph name="BEGIN_PARAGRAPH" />اتبع هذه الخطوات لإيقاف البرامج مؤقتًا حتى يتسنى لك الوصول إلى الويب. سيلزمك الحصول على امتيازات المشرف.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
<ph name="LIST_ITEM" />انقر على <ph name="BEGIN_BOLD" />البدء<ph name="END_BOLD" />، ثم ابحث عن <ph name="BEGIN_BOLD" />"عرض الخدمات المحلية"<ph name="END_BOLD" /> وحدِّده
<ph name="LIST_ITEM" />حدِّد <ph name="BEGIN_BOLD" />VisualDiscovery<ph name="END_BOLD" />
- <ph name="LIST_ITEM" />ضمن <ph name="BEGIN_BOLD" />نوع بدء التشغيل<ph name="END_BOLD" />، حدِّد <ph name="BEGIN_BOLD" />معطَّل<ph name="END_BOLD" />
+ <ph name="LIST_ITEM" />ضمن <ph name="BEGIN_BOLD" />نوع بدء التشغيل<ph name="END_BOLD" />، حدِّد <ph name="BEGIN_BOLD" />غير مفعّل<ph name="END_BOLD" />
<ph name="LIST_ITEM" />ضمن <ph name="BEGIN_BOLD" />حالة التشغيل<ph name="END_BOLD" />، انقر على <ph name="BEGIN_BOLD" />إيقاف<ph name="END_BOLD" />
<ph name="LIST_ITEM" />انقر على <ph name="BEGIN_BOLD" />تطبيق<ph name="END_BOLD" />، ثم انقر على <ph name="BEGIN_BOLD" />موافق<ph name="END_BOLD" />
<ph name="LIST_ITEM" />تفضَّل بزيارة <ph name="BEGIN_LEARN_MORE_LINK" />مركز مساعدة Chrome<ph name="END_LEARN_MORE_LINK" /> للتعرُّف على كيفية إزالة البرامج من جهاز الكمبيوتر نهائيًا
@@ -586,7 +624,7 @@
<translation id="5287240709317226393">عرض ملفات تعريف الارتباط</translation>
<translation id="5299298092464848405">خطأ في تحليل السياسة</translation>
<translation id="5308380583665731573">اتصال</translation>
-<translation id="5308689395849655368">ميزة الإبلاغ عن الأعطال معطلة.</translation>
+<translation id="5308689395849655368">ميزة الإبلاغ عن الأعطال غير مفعّلة.</translation>
<translation id="5317780077021120954">حفظ</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />، <ph name="MATCH_POSITION" /> من <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">اختيار معلومات الاتصال</translation>
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">التحقق من الاتصال</translation>
<translation id="5610807607761827392">يمكنك إدارة البطاقات والعناوين في <ph name="BEGIN_LINK" />الإعدادات<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">أعاد <ph name="HOST_NAME" /> توجيهك مرات كثيرة جدًا.</translation>
-<translation id="5622887735448669177">هل تريد الخروج من هذا الموقع؟</translation>
<translation id="5629630648637658800">تعذّر تحميل إعدادات السياسة</translation>
<translation id="5631439013527180824">الرمز المميز لإدارة الجهاز غير صالح</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">هل تريد ملء معلومات بطاقتك؟</translation>
<translation id="5803412860119678065">هل تريد ملء <ph name="CARD_DETAIL" />؟</translation>
<translation id="5810442152076338065">يتم ترميز اتصالك بالنطاق <ph name="DOMAIN" /> باستخدام مجموعة تشفير قديمة.</translation>
-<translation id="5810928923025889964">من صفحة مضمّنة في هذه الصفحة</translation>
<translation id="5813119285467412249">إعا&amp;دة الإضافة</translation>
<translation id="5838278095973806738">يجب عدم إدخال معلومات حسّاسة على هذا الموقع (على سبيل المثال، كلمات المرور أو بطاقات الائتمان)، نظرًا لأنه قد تتم سرقتها من قِبل المهاجمين.</translation>
<translation id="5866257070973731571">إضافة رقم الهاتف</translation>
@@ -701,7 +737,7 @@
<translation id="6221345481584921695">‏اكتشف التصفح الآمن من Google‬ مؤخرًا <ph name="BEGIN_LINK" />برامج ضارة<ph name="END_LINK" /> على <ph name="SITE" />. أحيانًا تصاب مواقع الويب الآمنة في الوضع العادي ببرامج ضارة. مصدر محتوى البرامج الضارة <ph name="SUBRESOURCE_HOST" />، وهو ناشر معروف للبرامج الضارة.</translation>
<translation id="6251924700383757765">سياسة الخصوصية</translation>
<translation id="6254436959401408446">لا تتوفر ذاكرة كافية لفتح هذه الصفحة</translation>
-<translation id="625755898061068298">لقد اخترت تعطيل تحذيرات الأمان لهذا الموقع.</translation>
+<translation id="625755898061068298">لقد اخترت إيقاف تحذيرات الأمان لهذا الموقع.</translation>
<translation id="6259156558325130047">إعادة إ&amp;جراء الترتيب</translation>
<translation id="6263376278284652872">إشعارات <ph name="DOMAIN" /></translation>
<translation id="6264485186158353794">الرجوع إلى وضع الأمان</translation>
@@ -712,7 +748,7 @@
<translation id="6305205051461490394">يتعذر الوصول إلى <ph name="URL" />.</translation>
<translation id="6319915415804115995">تم استخدامها آخر مرة قبل أكثر من عام</translation>
<translation id="6321917430147971392">التحقق من إعدادات نظام أسماء النطاقات</translation>
-<translation id="6328639280570009161">تجربة تعطيل التنبؤ بإجراءات الشبكة</translation>
+<translation id="6328639280570009161">تجربة إيقاف التنبؤ بإجراءات الشبكة</translation>
<translation id="6328786501058569169">هذا الموقع مخادع</translation>
<translation id="6337133576188860026">يوفِّر أقل من <ph name="SIZE" />. وقد يتم تحميل بعض مواقع الويب بشكل أبطأ عند زيارتها في المرة القادمة.</translation>
<translation id="6337534724793800597">تصفية السياسات بحسب الاسم</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">إضافة مزيد من المعلومات</translation>
<translation id="6447842834002726250">ملفّات تعريف الارتباط</translation>
<translation id="6451458296329894277">تأكيد إعادة إرسال النموذج</translation>
-<translation id="6456339708790392414">دفعتك</translation>
<translation id="647261751007945333">سياسات الأجهزة</translation>
<translation id="6477321094435799029">‏اكتشف Chrome وجود رمز غير عادي على هذه الصفحة وأجرى حظرًا لهذا الرمز لحماية معلوماتك الشخصية (على سبيل المثال، كلمات المرور، وأرقام الهواتف، وبطاقات الائتمان).</translation>
<translation id="6489534406876378309">بدء تحميل الأعطال</translation>
<translation id="6507833130742554667">يتم قبول بطاقات الائتمان وبطاقات السحب الآلي.</translation>
<translation id="6508722015517270189">‏إعادة تشغيل Chrome</translation>
-<translation id="6521373090216409766">هل تريد إعادة تحميل هذا الموقع؟</translation>
<translation id="6529602333819889595">إعادة الح&amp;ذف</translation>
<translation id="6534179046333460208">اقتراحات الشبكة المادية</translation>
<translation id="6550675742724504774">خيارات</translation>
-<translation id="6556239504065605927">اتصال آمن</translation>
<translation id="6556915248009097796">تاريخ انتهاء الصلاحية: <ph name="EXPIRATION_DATE_ABBR" />، وتاريخ آخر استخدام: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">لم يوافق عليه مديرك حتى الآن</translation>
<translation id="6569060085658103619">أنت تعرض صفحة إضافة</translation>
<translation id="6596325263575161958">خيارات التشفير</translation>
+<translation id="6604181099783169992">حساسات الإضاءة والحركة</translation>
<translation id="6624427990725312378">معلومات الاتصال</translation>
<translation id="6626291197371920147">إضافة رقم بطاقة صالح</translation>
<translation id="6628463337424475685">بحث <ph name="ENGINE" /></translation>
@@ -760,7 +794,7 @@
<translation id="6753269504797312559">قيمة السياسة</translation>
<translation id="6757797048963528358">خضع جهازك إلى وضع السكون.</translation>
<translation id="6778737459546443941">لم يوافق عليه والداك حتى الآن</translation>
-<translation id="679355240208270552">تم التجاهل نظرًا لأنه لم يتم تفعيل البحث الافتراضي بواسطة السياسة.</translation>
+<translation id="679355240208270552">تم التجاهل نظرًا لأنه لم يتم تفعيل البحث التلقائي بواسطة السياسة.</translation>
<translation id="681021252041861472">الحقل مطلوب</translation>
<translation id="6810899417690483278">رقم تعريف التخصيص</translation>
<translation id="6820686453637990663">CVC</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">الإشارات المرجعية المُدارة</translation>
<translation id="7298195798382681320">موصى بها</translation>
<translation id="7309308571273880165">تقرير الأعطال الذي تم الحصول عليه في <ph name="CRASH_TIME" /> (التحميل مطلوب بواسطة المستخدم، لم يتم التحميل بعد)</translation>
+<translation id="7320336641823683070">المساعدة بشأن الاتصال</translation>
<translation id="7334320624316649418">إعادة إ&amp;جراء الترتيب</translation>
<translation id="733923710415886693">لم يتم الكشف عن شهادة الخادم عن طريق شهادة الشفافية.</translation>
<translation id="7353601530677266744">سطر الأوامر</translation>
@@ -831,7 +866,7 @@
<translation id="7444046173054089907">تم حظر هذا الموقع</translation>
<translation id="7445762425076701745">لا يمكن التحقق بصورة كاملة من صحة هوية الخادم الذي تتصل به. فأنت متصل بخادم باستخدام اسم صالح فقط ضمن شبكتك، والذي لن يتمكن المرجع المصدق الخارجي من التحقق من ملكيته. وحيث إن بعض المراجع المصدقة تُصدر الشهادات لهذه الأسماء على أي حال، فليست هناك طريقة للتأكد من أنك متصل بموقع الويب المقصود وليس بأحد المهاجمين.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />مزيد من المعلومات<ph name="END_LINK" /> حول هذه المشكلة.</translation>
-<translation id="7455133967321480974">استخدام الإعداد الافتراضي العمومي (حظر)</translation>
+<translation id="7455133967321480974">استخدام الإعداد التلقائي العمومي (حظر)</translation>
<translation id="7460163899615895653">تظهر علامات التبويب الأخيرة من الأجهزة الأخرى هنا</translation>
<translation id="7469372306589899959">جارٍ التاكد من البطاقة</translation>
<translation id="7481312909269577407">إلى الأمام</translation>
@@ -844,7 +879,7 @@
<translation id="7526934274050461096">اتصالك بموقع الويب هذا لا يتمتع بخصوصية</translation>
<translation id="7537536606612762813">إلزامية</translation>
<translation id="7542403920425041731">بعد تأكيدك، ستتم مشاركة تفاصيل بطاقتك مع موقع الويب هذا.</translation>
-<translation id="7542995811387359312">تم تعطيل الملء التلقائي لبطاقة الائتمان لأن هذا النموذج لا يستخدم اتصالاً آمنًا.</translation>
+<translation id="7542995811387359312">تم إيقاف الملء التلقائي لبطاقة الائتمان لأن هذا النموذج لا يستخدم اتصالاً آمنًا.</translation>
<translation id="7543525346216957623">اسأل والديك</translation>
<translation id="7549584377607005141">تتطلب صفحة الويب هذه البيانات التي أدخلتها في وقت سابق لعرضها بشكل صحيح. يمكنك إرسال هذه المعلومات مرة أخرى ولكن بذلك ستكرر أي إجراء اتخذته هذه الصفحة في وقت سابق.</translation>
<translation id="7552846755917812628">جرّب النصائح التالية:</translation>
@@ -852,7 +887,7 @@
<translation id="7567204685887185387">هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />؛ بل إنه شهادة أمان تم إصدارها عن طريق الاحتيال. وربما يكون سبب ذلك خطأ في التكوين أو مهاجمًا يعترض اتصالك.</translation>
<translation id="7568593326407688803">تتوفر هذه الصفحة باللغة<ph name="ORIGINAL_LANGUAGE" />فهل تريد ترجمتها؟</translation>
<translation id="7569952961197462199">‏هل تريد إزالة بطاقة الائتمان من Chrome؟</translation>
-<translation id="7578104083680115302">‏الدفع سريعًا على المواقع والتطبيقات عبر الأجهزة باستخدام البطاقات التي حفظتها في Google.</translation>
+<translation id="7578104083680115302">‏الدفع سريعًا على المواقع والتطبيقات على جميع الأجهزة باستخدام البطاقات التي حفظتها في Google.</translation>
<translation id="7588950540487816470">الشبكة المادية</translation>
<translation id="7592362899630581445">تنتهك شهادة الخادم القيود المفروضة على الاسم.</translation>
<translation id="7598391785903975535">أقل من <ph name="UPPER_ESTIMATE" /></translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">‏قد يتطلب Wi-Fi الذي تستخدمه (<ph name="WIFI_NAME" />) زيارة صفحة تسجيل الدخول.</translation>
<translation id="785549533363645510">ومع ذلك، أنت غير مرئي. لا يخفي الانتقال إلى وضع التخفي التصفح من صاحب العمل أو مزود خدمة الإنترنت أو المواقع التي تزورها.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">هل تريد مغادرة الموقع؟</translation>
<translation id="7878176543348854470">يتم قبول بطاقات السحب الآلي وبطاقات الدفع المسبق.</translation>
<translation id="7878562273885520351">من المحتمل أنه تم اختراق كلمة مرورك</translation>
<translation id="7887683347370398519">‏تحقق من رمز التحقق من البطاقة (CVC) ثم أعد المحاولة.</translation>
@@ -917,13 +953,14 @@
<translation id="8012647001091218357">لم نتمكن من الوصول إلى والديك في الوقت الحالي. يُرجى إعادة المحاولة مرة أخرى.</translation>
<translation id="8025119109950072390">قد يحاول المهاجمون الموجودون على هذا الموقع فعل شيء خطير كتثبيت البرامج أو الكشف عن معلوماتك الشخصية (على سبيل المثال، كلمات المرور أو أرقام الهواتف أو بطاقات الائتمان).</translation>
<translation id="8034522405403831421">هذه الصفحة باللغة <ph name="SOURCE_LANGUAGE" />. هل تريد ترجمتها إلى اللغة <ph name="TARGET_LANGUAGE" />؟</translation>
-<translation id="8037357227543935929">الطلب (افتراضي)</translation>
+<translation id="8037357227543935929">الطلب (تلقائي)</translation>
<translation id="8041089156583427627">إرسال تعليقات</translation>
-<translation id="8041940743680923270">استخدام الإعداد الافتراضي العمومي (طلب)</translation>
+<translation id="8041940743680923270">استخدام الإعداد التلقائي العمومي (طلب)</translation>
<translation id="8042918947222776840">اختيار طريقة الاستلام من المستخدم</translation>
<translation id="8057711352706143257">لم تتم تهيئة "<ph name="SOFTWARE_NAME" />" بشكل صحيح. يؤدي عادةً إلغاء تثبيت "<ph name="SOFTWARE_NAME" />" إلى إصلاح المشكلة. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">هل تريد إعادة تحميل الموقع؟</translation>
<translation id="8088680233425245692">تعذّر عرض المقالة.</translation>
-<translation id="8091372947890762290">التنشيط قيد الانتظار في الخادم</translation>
+<translation id="8091372947890762290">التفعيل قيد الانتظار في الخادم</translation>
<translation id="8094917007353911263">قد تتطلب الشبكة التي تستخدمها زيارة <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
<translation id="8103161714697287722">طريقة الدفع</translation>
<translation id="8118489163946903409">طريقة الدفع</translation>
@@ -931,12 +968,13 @@
<translation id="8131740175452115882">التأكيد</translation>
<translation id="8149426793427495338">خضع جهاز الكمبيوتر إلى وضع السكون.</translation>
<translation id="8150722005171944719">الملف الموجود على <ph name="URL" /> غير قابل للقراءة. ربما تمت إزالته، أو ربما تكون أذونات الملف هي التي تمنع الدخول.</translation>
-<translation id="8184538546369750125">استخدام الإعداد الافتراضي العمومي (سماح)</translation>
+<translation id="8184538546369750125">استخدام الإعداد التلقائي العمومي (سماح)</translation>
<translation id="8191494405820426728">معرّف الأعطال المحلي <ph name="CRASH_LOCAL_ID" /></translation>
<translation id="8194797478851900357">تراجع عن ال&amp;نقل</translation>
<translation id="8201077131113104583">‏عنوان URL لتحديث الإضافة التي تحتوي على رقم التعريف "<ph name="EXTENSION_ID" />" غير صالح.</translation>
<translation id="8202097416529803614">ملخص الطلب</translation>
<translation id="8205463626947051446">يميل الموقع إلى عرض إعلانات متداخلة</translation>
+<translation id="8211406090763984747">الاتصال آمن</translation>
<translation id="8218327578424803826">الموقع الذي تم تعيينه:</translation>
<translation id="8225771182978767009">اختار الشخص الذي أعد جهاز الكمبيوتر حظر موقع الويب هذا.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />، <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">عرض جميع كلمات المرور المحفوظة</translation>
<translation id="8261506727792406068">حذف</translation>
<translation id="8267698848189296333">تسجيل الدخول باسم <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">تسجيل الدخول</translation>
<translation id="8288807391153049143">عرض الشهادة</translation>
<translation id="8289355894181816810">اتصل بمشرف الشبكة إذا لم تكن متأكدًا مما يعنيه هذا.</translation>
<translation id="8293206222192510085">إضافة إشارة مرجعية</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">بطاقات الائتمان وبطاقات الدفع المسبق المقبولة</translation>
<translation id="8759274551635299824">هذه البطاقة منتهية الصلاحية</translation>
<translation id="8761567432415473239">‏عثر ‏‫التصفح الآمن من Google‬ مؤخرًا <ph name="BEGIN_LINK" />على برامج ضارة<ph name="END_LINK" /> في <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">‏جهاز USB</translation>
<translation id="8790007591277257123">إعادة الح&amp;ذف</translation>
<translation id="8800988563907321413">تظهر اقتراحاتك "المجاورة" هنا</translation>
<translation id="8820817407110198400">إشارات</translation>
@@ -1072,7 +1112,7 @@
<translation id="992115559265932548"><ph name="MICROSOFT_ACTIVE_DIRECTORY" /></translation>
<translation id="992432478773561401">‏لم يتم تثبيت "<ph name="SOFTWARE_NAME" />" بطريقة صحيحة على جهاز الكمبيوتر أو الشبكة:
&lt;ul&gt;
- &lt;li&gt;حاوِل إلغاء تثبيت "<ph name="SOFTWARE_NAME" />" أو تعطيل&lt;/li&gt;
+ &lt;li&gt;حاوِل إلغاء تثبيت "<ph name="SOFTWARE_NAME" />" أو إيقاف&lt;/li&gt;
&lt;li&gt;حاوِل الاتصال بشبكة أخرى&lt;/li&gt;
&lt;/ul&gt;</translation>
<translation id="997986563973421916">‏من Google Pay</translation>
diff --git a/chromium/components/strings/components_strings_bg.xtb b/chromium/components/strings/components_strings_bg.xtb
index b629626b16e..c29917d10e4 100644
--- a/chromium/components/strings/components_strings_bg.xtb
+++ b/chromium/components/strings/components_strings_bg.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Печат...</translation>
<translation id="1181037720776840403">Премахване</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Автоматично съобщаване<ph name="END_WHITEPAPER_LINK" /> на Google на подробности за евентуални инциденти, свързани със сигурността. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Плащането не е завършено</translation>
<translation id="1201402288615127009">Напред</translation>
<translation id="1201895884277373915">Още от този сайт</translation>
<translation id="1206967143813997005">Невалиден първоначален подпис</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Сигнал за срив, записан в/ъв <ph name="CRASH_TIME" /> (още не е качен или пренебрегнат)</translation>
<translation id="1270502636509132238">Начин на вземане</translation>
<translation id="1285320974508926690">Този сайт да не се превежда никога</translation>
+<translation id="1294154142200295408">Варианти във формат за командния ред</translation>
<translation id="129553762522093515">Наскоро затворени</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Опитайте да изчистите „бисквитките“ си<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Активността ви <ph name="BEGIN_EMPHASIS" />може да остане видима<ph name="END_EMPHASIS" /> за:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Приемани кредитни и дебитни карти</translation>
<translation id="1519264250979466059">Дата на версията</translation>
<translation id="1527263332363067270">Изчаква се връзка…</translation>
+<translation id="1532118530259321453">Тази страница изпраща съобщение</translation>
<translation id="153384715582417236">Това е всичко засега</translation>
<translation id="154408704832528245">Избиране на адрес за бърза доставка</translation>
<translation id="1549470594296187301">Трябва да активирате JavaScript, за да използвате тази функция.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Проверете прокси сървъра и защитната стена<ph name="END_LINK" />.</translation>
<translation id="2053553514270667976">Пощенски код</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 предложение}other{# предложения}}</translation>
-<translation id="2065985942032347596">Изисква се удостоверяване на самоличността</translation>
<translation id="2079545284768500474">Отмяна</translation>
<translation id="20817612488360358">За използване са зададени системни настройки за прокси сървъра, но е посочена и изрична конфигурация.</translation>
<translation id="2091887806945687916">Звук</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Анулиране на плащането</translation>
<translation id="2147827593068025794">Синхронизиране на заден план</translation>
<translation id="2148613324460538318">Добавяне на карта</translation>
-<translation id="2149973817440762519">Редактиране на отметката</translation>
<translation id="2154054054215849342">Синхронизирането не е налице за въведения от вас домейн</translation>
<translation id="2154484045852737596">Редактиране на картата</translation>
<translation id="2166049586286450108">Пълен администраторски достъп</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Избиране на адрес за вземане</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Премахване на избраните елементи</translation>
-<translation id="2744590937989388266">От страница, вградена в тази</translation>
<translation id="277133753123645258">Начин на доставка</translation>
<translation id="277499241957683684">Липсващ запис за устройството</translation>
<translation id="2784949926578158345">Връзката бе възстановена.</translation>
<translation id="2788784517760473862">Приемани кредитни карти</translation>
<translation id="2794233252405721443">Сайтът е блокиран</translation>
-<translation id="2795286477369100655">Искате ли да напуснете този сайт?</translation>
<translation id="2799020568854403057">На хоризонта се задава сайт с опасни приложения</translation>
<translation id="2803306138276472711">Google Безопасно сърфиране наскоро <ph name="BEGIN_LINK" />откри злонамерен софтуер<ph name="END_LINK" /> на <ph name="SITE" />. Уебсайтовете, които обикновено са надеждни, понякога се заразяват с опасен софтуер.</translation>
<translation id="2824775600643448204">Лента за адреси и за търсене</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Списъчен запис „<ph name="ENTRY_INDEX" />“: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Автоматично блокирано</translation>
<translation id="3024663005179499861">Грешен тип на правилото</translation>
-<translation id="3032412215588512954">Искате ли да презаредите този сайт?</translation>
<translation id="3037605927509011580">Ужас!</translation>
<translation id="3039538478787849737">Картата да се запази ли в Google?</translation>
<translation id="3041612393474885105">Информация за сертификата</translation>
@@ -310,6 +306,7 @@
проверете настройките му или се свържете със системния си администратор. Ако смятате, че не трябва
да използвате прокси сървър:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> на <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Анулиране на плащането</translation>
<translation id="3207960819495026254">С отметка</translation>
<translation id="3209375525920864198">Моля, въведете валидно име на сесия.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Мениджърът ви може да го отблокира за вас</translation>
<translation id="3566021033012934673">Връзката ви не е поверителна</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Вградена страница на адрес <ph name="SITE" /> изпраща съобщение</translation>
<translation id="358285529439630156">Приемат се кредитни и предплатени карти.</translation>
<translation id="3582930987043644930">Добавете име</translation>
<translation id="3583757800736429874">&amp;Възстановяване на преместването</translation>
<translation id="3586931643579894722">Скриване на подробностите</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Отстраняване на грешки във връзката&lt;/h1&gt;
+&lt;p&gt;Ако получите съобщение за грешка, когато опитате да посетите уебсайт, изпробвайте следните решения.&lt;/p&gt;
+&lt;h2&gt;Отстраняване на повечето грешки във връзката&lt;/h2&gt;
+&lt;p&gt;Ако опитате да посетите уебсайт и той не се отваря, първо, пробвайте да изпълните следните стъпки за отстраняване на неизправности:&lt;/p&gt;
+&lt;ol&gt;
+&lt;li&gt;Проверете дали уеб адресът е изписан правилно.&lt;/li&gt;
+&lt;li&gt;Уверете се, че връзката ви с интернет работи нормално.&lt;/li&gt;
+&lt;li&gt;Свържете се със собственика на уебсайта.&lt;/li&gt;
+&lt;/ol&gt;
+&lt;h2&gt;Получаване на помощ за конкретно съобщение за грешка&lt;/h2&gt;
+&lt;h3&gt;„Връзката ви не е частна“, „NET::ERR_CERT_AUTHORITY_INVALID“, „ERR_CERT_COMMON_NAME_INVALID“, „NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM“ или „Грешка при SSL сертификатите“&lt;/h3&gt;
+&lt;h4&gt;Стъпка 1: Влезте в портала&lt;/h4&gt;
+&lt;p&gt;Wi-Fi мрежите на места като кафенета или летища изискват да влезете в профил. За да видите страницата за вход, посетете страница, която използва &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+&lt;ol&gt;
+&lt;li&gt;Посетете който и да е уебсайт, започващ с &lt;code&gt;http://&lt;/code&gt;, като &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+&lt;li&gt;В отворилата се страница за вход влезте, за да използвате интернет.&lt;/li&gt;
+&lt;/ol&gt;
+&lt;h4&gt;Стъпка 2: Отворете страницата в режим „инкогнито“ (само за компютър)&lt;/h4&gt;
+&lt;p&gt;Отворете страницата, която опитвате да посетите, в прозорец в режим „инкогнито“.&lt;/p&gt;
+&lt;p&gt;Ако страницата се отвори, значи дадено разширение за Chrome не работи правилно. Изключете го, за да отстраните грешката.&lt;/p&gt;
+&lt;h4&gt;Стъпка 3: Актуализирайте операционната си система&lt;/h4&gt;
+&lt;p&gt;Уверете се, че операционната система на устройството ви е актуална.&lt;/p&gt;
+&lt;h4&gt;Стъпка 4: Временно изключете антивирусния си софтуер&lt;/h4&gt;
+&lt;p&gt;Ще виждате това съобщение за грешка, ако имате антивирусен софтуер, осигуряващ защита за HTTPS или сканиране на HTTPS. Подобни програми възпрепятстват защитните функции на Chrome.&lt;/p&gt;
+&lt;p&gt;За да отстраните проблема, изключете антивирусния софтуер. Ако след това успеете да отворите страницата, деактивирайте този софтуер, когато посещавате защитени сайтове.&lt;/p&gt;
+&lt;p&gt;Не забравяйте да включите отново антивирусната програма, когато сте готови.&lt;/p&gt;
+&lt;h4&gt;Стъпка 5: Получете допълнителна помощ&lt;/h4&gt;
+&lt;p&gt;Ако продължавате да виждате грешката, свържете се със собственика на уебсайта.&lt;/p&gt;
+&lt;h3&gt;„Свързване с мрежа“&lt;/h3&gt;
+&lt;p&gt;Ще виждате това съобщение за грешка, ако използвате портал за Wi-Fi, където трябва да влезете в профил, преди да можете да преминете онлайн.&lt;/p&gt;
+&lt;p&gt;За да отстраните грешката, кликнете върху &lt;strong&gt;Свързване&lt;/strong&gt; на страницата, която опитвате да отворите.&lt;/p&gt;
+&lt;h3&gt;„Часовникът ви е назад“, „Часовникът ви е напред“ или „NET::ERR_CERT_DATE_INVALID“&lt;/h3&gt;
+&lt;p&gt;Ще виждате това съобщение за грешка, ако датата и часът на компютъра или мобилното ви устройство не са верни.&lt;/p&gt;
+&lt;p&gt;За да отстраните грешката, отворете часовника на устройството си и сверете датата и часа.&lt;/p&gt;
+&lt;h3&gt;„Софтуер на компютъра ви пречи на Chrome да се свърже безопасно с мрежата“ (само за компютри с Windows)&lt;/h3&gt;
+&lt;p&gt;Ще виждате това съобщение за грешка, ако софтуерът Superfish е инсталиран на компютъра ви с Windows.&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;VisualDiscovery&lt;/strong&gt;.
+&lt;li&gt;За &lt;strong&gt;Startup type&lt;/strong&gt; изберете &lt;strong&gt;Disabled&lt;/strong&gt;.
+&lt;li&gt;Под &lt;strong&gt;Service status&lt;/strong&gt; кликнете върху &lt;strong&gt;Stop&lt;/strong&gt;.
+&lt;li&gt;Кликнете върху &lt;strong&gt;Приложи&lt;/strong&gt; и след това – върху &lt;strong&gt;OK&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="3615877443314183785">Въведете валидна дата на изтичане</translation>
<translation id="36224234498066874">Изчистване на данните за сърфирането...</translation>
<translation id="362276910939193118">Показване на пълната история</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Искате ли тази карта да се запази на устройството и в профила ви в Google?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Изтича на <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">От <ph name="SITE" /></translation>
<translation id="382518646247711829">Ако използвате прокси сървър...</translation>
<translation id="3828924085048779000">Не може пропускът да не се попълни.</translation>
<translation id="385051799172605136">Назад</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">Идентификатор на качения сигнал за срив: <ph name="CRASH_ID" /> (локален идентификатор на срива: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Сървърът не можа да докаже, че е <ph name="DOMAIN" />. В сертификата му за сигурност не са посочени алтернативни имена на обекта. Това може да се дължи на неправилно конфигуриране или на прихващане на връзката ви от извършител на атака.</translation>
<translation id="3949601375789751990">Тук се показва историята ви на сърфиране</translation>
+<translation id="3950820424414687140">Вход</translation>
<translation id="3963721102035795474">Режим за четене</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Няма}=1{От 1 сайт }other{От # сайта }}</translation>
<translation id="397105322502079400">Изчислява се...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Серийният номер на устройството е невалиден</translation>
<translation id="410351446219883937">Автоматично възпроизвеждане</translation>
<translation id="4103763322291513355">Посетете &lt;strong&gt;chrome://policy&lt;/strong&gt;, за да видите изброени URL адресите в черния списък и другите правила, наложени от системния ви администратор.</translation>
+<translation id="4110652170750985508">Преглед на плащането ви</translation>
<translation id="4116663294526079822">Разрешаване винаги на този сайт</translation>
<translation id="4117700440116928470">Обхватът на правилата не се поддържа.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{още 1 елемент}other{още # елемента}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Няма потребителско име)</translation>
<translation id="4275830172053184480">Рестартиране на устройството ви</translation>
<translation id="4280429058323657511">, изтича: <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Вход</translation>
<translation id="4312866146174492540">Блокиране (по подразбиране)</translation>
<translation id="4325863107915753736">Намирането на статията не бе успешно</translation>
<translation id="4326324639298822553">Проверете датата на валидност и опитайте отново</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Картите и адресите са от Chrome и профила ви в Google (<ph name="ACCOUNT_EMAIL" />). Можете да ги управлявате от <ph name="BEGIN_LINK" />настройките<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Подробности</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">От вградена страница на адрес <ph name="SITE" /></translation>
<translation id="4558551763791394412">Опитайте да деактивирате разширенията.</translation>
<translation id="457875822857220463">Бърза доставка</translation>
<translation id="4582800630050655161">Възможно е да загубите достъп до профила си в Google или самоличността ви да бъде открадната. Chromium препоръчва да промените паролата си сега.</translation>
<translation id="4587425331216688090">Адресът да се премахне ли от Chrome?</translation>
<translation id="4592951414987517459">Връзката ви с/ъс <ph name="DOMAIN" /> е шифрована със съвременен криптографски пакет.</translation>
<translation id="4594403342090139922">&amp;Отмяна на изтриването</translation>
-<translation id="4611292653554630842">Вход</translation>
<translation id="4619615317237390068">Раздели от други устройства</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Сървърът не можа да докаже, че е <ph name="DOMAIN" />; сертификатът му за сигурност съдържа грешки. Това може да се дължи на неправилно конфигуриране или на прихващане на връзката ви от атакуващ.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Връзката ви бе прекъсната</translation>
<translation id="471880041731876836">Нямате разрешение да посетите този сайт</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Стартирайте мрежова диагностика в Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Вашето плащане</translation>
<translation id="4726672564094551039">Презареждане на правилата</translation>
<translation id="4728558894243024398">Платформа</translation>
<translation id="4736825316280949806">Рестартирайте Chromium.</translation>
-<translation id="4737498291095696011">От тази страница</translation>
<translation id="4744603770635761495">Път към изпълнимия файл</translation>
<translation id="4749685221585524849">Последно използване: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Информацията ви (например пароли или номера на кредитни карти) е частна, когато се изпраща до този сайт.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Изглед</translation>
<translation id="4854362297993841467">Този начин на бърза доставка не се поддържа. Опитайте с друг.</translation>
<translation id="4858792381671956233">Попитахте родителите си дали може да посетите този сайт</translation>
-<translation id="4871132632506079383">От вградена страница на адрес <ph name="SITE" /></translation>
<translation id="4880827082731008257">Търсене в историята</translation>
+<translation id="4881695831933465202">Отваряне</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" /> и <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Изисква се удостоверяване</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{и още 1 уеб страница}other{и още # уеб страници}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Въведете кода за проверка за <ph name="CREDIT_CARD" />. След като потвърдите картата си, данните за нея от профила ви в Google Payments ще бъдат споделени с този сайт.</translation>
<translation id="4923417429809017348">Тази страница е преведена от непознат език на <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Плащане</translation>
<translation id="4926049483395192435">Трябва да се посочи.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> изпраща съобщение</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Действия</translation>
<translation id="4958444002117714549">Разгъване на списъка</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Ако настройката е активирана, копие на картата ви ще се съхранява в Chrome на това устройство с цел по-бързо попълване на формуляри.</translation>
<translation id="5018422839182700155">Тази страница не може да се отвори</translation>
<translation id="5019198164206649151">Допълнителното хранилище е в лошо състояние</translation>
-<translation id="5020990877659450221">От тази страница</translation>
<translation id="5023310440958281426">Проверете правилата на администратора</translation>
<translation id="5029568752722684782">Изчистване на копието</translation>
<translation id="503069730517007720">За <ph name="SOFTWARE_NAME" /> се изисква основен сертификат, но такъв не е инсталиран. Системният ви администратор трябва да прегледа инструкциите за конфигуриране на <ph name="SOFTWARE_NAME" />, за да отстрани проблема. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Машината</translation>
<translation id="5179510805599951267">Не е на <ph name="ORIGINAL_LANGUAGE" />? Подайте сигнал за тази грешка</translation>
<translation id="5190835502935405962">Лента на отметките</translation>
+<translation id="5201306358585911203">Страница, вградена в тази страница, изпраща съобщение</translation>
<translation id="5205222826937269299">Името е задължително</translation>
<translation id="5222812217790122047">Имейл адресът е задължителен</translation>
<translation id="522700295135997067">Възможно е този сайт току-що да е откраднал паролата ви</translation>
<translation id="5230733896359313003">Адрес за доставка</translation>
<translation id="5251803541071282808">Облак</translation>
-<translation id="5277279256032773186">Използвате Chrome на работното си място? Бизнесите могат да управляват настройките на браузъра за служителите си. Научете повече</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Изпълнете следните стъпки, за да деактивирате временно софтуера, така че да можете да се свържете с мрежата. Ще са ви необходими администраторски права.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Проверете връзката.</translation>
<translation id="5610807607761827392">Можете да управлявате картите и адресите от <ph name="BEGIN_LINK" />настройките<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> ви пренасочи твърде много пъти.</translation>
-<translation id="5622887735448669177">Искате ли да напуснете този сайт?</translation>
<translation id="5629630648637658800">Зареждането на настройките за правилото не бе успешно</translation>
<translation id="5631439013527180824">Невалидно означение за управление на устройството</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Искате ли да се попълнят данните за кредитната ви карта?</translation>
<translation id="5803412860119678065">Искате ли да се попълнят данните за <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Връзката ви с/ъс <ph name="DOMAIN" /> е шифрована с остарял криптографски пакет.</translation>
-<translation id="5810928923025889964">От страница, вградена в тази</translation>
<translation id="5813119285467412249">&amp;Възстановяване на добавянето</translation>
<translation id="5838278095973806738">Не ви препоръчваме да въвеждате поверителна информация в този сайт (например пароли или номера на кредитни карти), тъй като може да бъде открадната от извършители на атаки.</translation>
<translation id="5866257070973731571">Добавяне на телефонен номер</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Добавяне на още информация</translation>
<translation id="6447842834002726250">„Бисквитки“</translation>
<translation id="6451458296329894277">Потвърдете повторното изпращане на формуляра</translation>
-<translation id="6456339708790392414">Вашето плащане</translation>
<translation id="647261751007945333">Правила за устройството</translation>
<translation id="6477321094435799029">Chrome откри необичаен код на тази страница и я блокира, за да защити личната ви информация (например пароли, телефонни номера и номера на кредитни карти).</translation>
<translation id="6489534406876378309">Стартиране на качването на сривове</translation>
<translation id="6507833130742554667">Приемат се кредитни и дебитни карти.</translation>
<translation id="6508722015517270189">Рестартирайте Chrome.</translation>
-<translation id="6521373090216409766">Искате ли да презаредите този сайт?</translation>
<translation id="6529602333819889595">&amp;Възстановяване на изтриването</translation>
<translation id="6534179046333460208">Предложения от Физическата мрежа</translation>
<translation id="6550675742724504774">Опции</translation>
-<translation id="6556239504065605927">Защитена връзка</translation>
<translation id="6556915248009097796">Валидност: <ph name="EXPIRATION_DATE_ABBR" />. Последно използване: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Мениджърът ви все още не е одобрил заявката</translation>
<translation id="6569060085658103619">Преглеждате страница на разширение</translation>
<translation id="6596325263575161958">Опции за шифроване</translation>
+<translation id="6604181099783169992">Сензори за движение или светлина</translation>
<translation id="6624427990725312378">Информация за връзка</translation>
<translation id="6626291197371920147">Добавяне на валиден номер на карта</translation>
<translation id="6628463337424475685">Търсене с/ъс <ph name="ENGINE" /></translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Управлявани отметки</translation>
<translation id="7298195798382681320">Препоръчително</translation>
<translation id="7309308571273880165">Сигнал за срив, записан в/ъв <ph name="CRASH_TIME" /> (потребителят е заявил качване, което още не е извършено)</translation>
+<translation id="7320336641823683070">Помощ при проблеми с връзката</translation>
<translation id="7334320624316649418">&amp;Възстановяване на пренареждането</translation>
<translation id="733923710415886693">Сертификатът на сървъра не е разкрит чрез Прозрачност на сертификатите.</translation>
<translation id="7353601530677266744">Команден ред</translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">Използваната от вас Wi-Fi мрежа (<ph name="WIFI_NAME" />) може да изисква да посетите страницата й за вход.</translation>
<translation id="785549533363645510">Сърфирането ви обаче не е невидимо. При преминаване в режим „инкогнито“ то не се скрива от работодателя ви и от доставчика ви на интернет услуги, нито от уебсайтовете, които посещавате.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
+<translation id="7862185352068345852">Искате ли да напуснете сайта?</translation>
<translation id="7878176543348854470">Приемат се дебитни и предплатени карти.</translation>
<translation id="7878562273885520351">Възможно е паролата ви да е компрометирана</translation>
<translation id="7887683347370398519">Прегледайте кода за проверка и опитайте отново</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Използване на глобалната стандартна стойност (запитване)</translation>
<translation id="8042918947222776840">Избиране на начин на вземане</translation>
<translation id="8057711352706143257">Софтуерът <ph name="SOFTWARE_NAME" /> не е конфигуриран правилно. Обикновено проблемът се отстранява с деинсталиране на <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Искате ли да презаредите сайта?</translation>
<translation id="8088680233425245692">Преглеждането на статията не бе успешно.</translation>
<translation id="8091372947890762290">В сървъра се изчаква активиране</translation>
<translation id="8094917007353911263">Използваната от вас мрежа може да изисква да посетите <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">Невалиден URL адрес за актуализиране на разширението с идентификационен номер <ph name="EXTENSION_ID" />.</translation>
<translation id="8202097416529803614">Обобщена информация за поръчката</translation>
<translation id="8205463626947051446">На сайта обикновено се показват натрапчиви реклами</translation>
+<translation id="8211406090763984747">Връзката е защитена</translation>
<translation id="8218327578424803826">Зададено местоположение:</translation>
<translation id="8225771182978767009">Човекът, който е настроил компютъра, е блокирал този сайт.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" /> и <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Показване на всички запазени пароли</translation>
<translation id="8261506727792406068">Изтриване</translation>
<translation id="8267698848189296333">Влизате като <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Вход</translation>
<translation id="8288807391153049143">Показване на сертификата</translation>
<translation id="8289355894181816810">Свържете се със системния си администратор, ако не сте сигурни какво означава това.</translation>
<translation id="8293206222192510085">Добавяне на отметка</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Приемани кредитни и предплатени карти</translation>
<translation id="8759274551635299824">Тази карта е изтекла</translation>
<translation id="8761567432415473239">Google Безопасно сърфиране наскоро <ph name="BEGIN_LINK" />откри опасни програми<ph name="END_LINK" /> на <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">USB устройство</translation>
<translation id="8790007591277257123">&amp;Възстановяване на изтриването</translation>
<translation id="8800988563907321413">Тук ще се показват предложения за неща в близост</translation>
<translation id="8820817407110198400">Отметки</translation>
diff --git a/chromium/components/strings/components_strings_bn.xtb b/chromium/components/strings/components_strings_bn.xtb
index 7f016eaf4f8..2ce885ea244 100644
--- a/chromium/components/strings/components_strings_bn.xtb
+++ b/chromium/components/strings/components_strings_bn.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;প্রিন্ট...</translation>
<translation id="1181037720776840403">সরান</translation>
<translation id="1184214524891303587">নিরাপত্তার সম্ভাব্য লঙ্ঘনের ঘটনাগুলির বিস্তারিত বিবরণ Google এর কাছে <ph name="BEGIN_WHITEPAPER_LINK" />স্বয়ংক্রিয়ভাবে প্রতিবেদন করুন<ph name="END_WHITEPAPER_LINK" />। <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">পেমেন্ট করা যায়নি</translation>
<translation id="1201402288615127009">পরবর্তী</translation>
<translation id="1201895884277373915">এই সাইট থেকে আরও</translation>
<translation id="1206967143813997005">নষ্ট প্রাথমিক স্বাক্ষর</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">ক্র্যাশ প্রতিবেদন <ph name="CRASH_TIME" /> এ ক্যাপচার করা হয়েছে (এখনো আপলোড করা বা উপেক্ষা করা হয়নি)</translation>
<translation id="1270502636509132238">পিক-আপের পদ্ধতি</translation>
<translation id="1285320974508926690">কখনই এই সাইটটিকে অনুবাদ করবেন না</translation>
+<translation id="1294154142200295408">কম্যান্ড লাইনে বিভিন্ন পরিবর্তন</translation>
<translation id="129553762522093515">সম্প্রতি বন্ধ হয়েছে</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />আপনার কুকিজ সাফ করে দেখুন<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">এগুলিতে আপনার কার্যকলাপ <ph name="BEGIN_EMPHASIS" />এখনও দেখা যেতে পারে<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">ক্রেডিট এবং ডেবিট কার্ড গ্রহণ করা হয়</translation>
<translation id="1519264250979466059">নির্মাণের তারিখ</translation>
<translation id="1527263332363067270">সংযোগের জন্য অপেক্ষা করা হচ্ছে...</translation>
+<translation id="1532118530259321453">এই পৃষ্ঠায় এটি দেখানো হচ্ছে</translation>
<translation id="153384715582417236">এখন এই পর্যন্তই</translation>
<translation id="154408704832528245">ডেলিভারি ঠিকানা বেছে নিন</translation>
<translation id="1549470594296187301">এই বৈশিষ্ট্যটি ব্যবহার করার জন্য JavaScript সক্ষম করা প্রয়োজন।</translation>
@@ -147,7 +148,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />প্রক্সি এবং ফায়ারওয়াল পরীক্ষা করে দেখুন<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">পিন কোড</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{১টি প্রস্তাব}one{#টি প্রস্তাব}other{#টি প্রস্তাব}}</translation>
-<translation id="2065985942032347596">প্রমাণীকরণ প্রয়োজন</translation>
<translation id="2079545284768500474">পূর্বাবস্থায় ফিরুন</translation>
<translation id="20817612488360358">সিস্টেম প্রক্সি সেটিংস ব্যবহার করার জন্য সেট আছে কিন্তু একটি সুনির্দিষ্ট প্রক্সি কনফিগারেশনও নির্দিষ্ট করা আছে৷</translation>
<translation id="2091887806945687916">আওয়াজ</translation>
@@ -161,7 +161,6 @@
<translation id="214556005048008348">পেমেন্ট বাতিল করুন</translation>
<translation id="2147827593068025794">পটভূমি সিঙ্ক</translation>
<translation id="2148613324460538318">কার্ড যোগ করুন</translation>
-<translation id="2149973817440762519">বুকমার্ক সম্পাদনা করুন</translation>
<translation id="2154054054215849342">আপনার ডোমেনের জন্য সিঙ্ক উপলব্ধ নেই</translation>
<translation id="2154484045852737596">কার্ড সম্পাদনা করুন</translation>
<translation id="2166049586286450108">পূর্ণ প্রশাসক অ্যাক্সেস</translation>
@@ -169,7 +168,7 @@
<translation id="2181821976797666341">নীতিসমূহ</translation>
<translation id="2183608646556468874">ফোন নম্বর</translation>
<translation id="2184405333245229118">{COUNT,plural, =1{১টি ঠিকানা}one{ #টি ঠিকানা}other{ #টি ঠিকানা}}</translation>
-<translation id="2187317261103489799">সনাক্ত করুন (ডিফল্ট)</translation>
+<translation id="2187317261103489799">শনাক্ত করুন (ডিফল্ট)</translation>
<translation id="2202020181578195191">মেয়াদ শেষ হওয়ার বছরের সঠিক মান লিখুন</translation>
<translation id="2212735316055980242">নীতি পাওয়া যায়নি</translation>
<translation id="2213606439339815911">এন্ট্রিগুলি আনা হচ্ছে...</translation>
@@ -213,7 +212,7 @@
<translation id="2515629240566999685">আপনার এলাকায় সংকেত পরীক্ষা করে দেখুন</translation>
<translation id="2524461107774643265">আরও তথ্য যোগ করুন</translation>
<translation id="2536110899380797252">ঠিকানা যোগ করুন</translation>
-<translation id="2539524384386349900">সনাক্ত করুন</translation>
+<translation id="2539524384386349900">শনাক্ত করুন</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> একটি অবৈধ প্রতিক্রিয়া পাঠিয়েছে।</translation>
<translation id="2556876185419854533">&amp;সম্পাদনাকে পূর্বাবস্থায় ফেরান</translation>
<translation id="2586657967955657006">ক্লিপবোর্ড</translation>
@@ -246,13 +245,11 @@
<translation id="2738330467931008676">পিক-আপের ঠিকানা বেছে নিন</translation>
<translation id="2740531572673183784">ঠিক আছে</translation>
<translation id="2742870351467570537">নির্বাচিত আইটেমগুলি সরান</translation>
-<translation id="2744590937989388266">এই পৃষ্ঠার এম্বেড করা একটি পৃষ্ঠা থেকে</translation>
<translation id="277133753123645258">শিপিংয়ের পদ্ধতি</translation>
<translation id="277499241957683684">ডিভাইস রেকর্ড অনুপস্থিত</translation>
<translation id="2784949926578158345">সংযোগ পুনঃসেট করা হয়েছে৷</translation>
<translation id="2788784517760473862">ক্রেডিট কার্ড গ্রহণ করা হয়</translation>
<translation id="2794233252405721443">সাইট অবরুদ্ধ করা হয়েছে</translation>
-<translation id="2795286477369100655">আপনি কি এই সাইটটি ছেড়ে যেতে চান?</translation>
<translation id="2799020568854403057">যে সাইট খুলতে চলেছেন সেটিতে ক্ষতিকারক অ্যাপ আছে</translation>
<translation id="2803306138276472711">Google নিরাপদ ব্রাউজিং সাম্প্রতিক <ph name="SITE" /> এ <ph name="BEGIN_LINK" />ম্যালওয়্যার শনাক্ত করেছে<ph name="END_LINK" />। যেসব ওয়েবসাইট সাধারণত নিরাপদ থাকে, সেগুলি কখনও কখনও ম্যালওয়্যার দ্বারা আক্রান্ত হয়।</translation>
<translation id="2824775600643448204">ঠিকানা এবং অনুসন্ধান দণ্ড</translation>
@@ -261,7 +258,7 @@
<translation id="2851634818064021665">এই সাইট দেখার জন্য আপনার অনুমতির প্রয়োজন</translation>
<translation id="2856444702002559011">আক্রমণকারীরা হয়ত <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> থেকে আপনার তথ্য (যেমন পাসওয়ার্ড, মেসেজ বা ক্রেডিট কার্ড) চুরি করার চেষ্টা করছে। <ph name="BEGIN_LEARN_MORE_LINK" />আরও জানুন<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2881276955470682203">কার্ড সেভ করবেন?</translation>
-<translation id="2909946352844186028">একটি নেটওয়ার্ক পরিবর্তন সনাক্ত হয়েছে৷</translation>
+<translation id="2909946352844186028">একটি নেটওয়ার্ক পরিবর্তন শনাক্ত হয়েছে৷</translation>
<translation id="2916038427272391327">অন্যান্য প্রোগ্রামগুলি বন্ধ করুন</translation>
<translation id="2922350208395188000">সার্ভারের শংসাপত্র চেক করা যাবে না৷</translation>
<translation id="2925673989565098301">ডেলিভারির পদ্ধতি</translation>
@@ -272,7 +269,7 @@
<translation id="2955913368246107853">খোঁজ দণ্ড বন্ধ করুন</translation>
<translation id="2958431318199492670">নেটওয়ার্ক কনফিগারেশন ONC মানকের সাথে সম্মত নয়৷ কনফিগারেশনের অংশগুলি আমদানিকৃত নাও হতে পারে৷</translation>
<translation id="2966678944701946121">মেয়াদ শেষের তারিখ: <ph name="EXPIRATION_DATE_ABBR" />, যোগ করা হয়েছে <ph name="ADDED_TO_AUTOFILL_MONTH" /></translation>
-<translation id="2969319727213777354">নিরাপদ নেটওয়ার্ক সংযোগ স্থাপন করতে আপনার ঘড়িকে সঠিকভাবে সেট করতে হবে। এমন হওয়ার কারণ হলো, নিরাপদ সংযোগ স্থাপন করার জন্য নিজেদের সনাক্ত করার জন্য ওয়েবসাইটগুলি যে শংসাপত্রগুলি ব্যবহার করে, সেগুলি শুধুমাত্র নির্দিষ্ট সময়ের জন্য বৈধ থাকে। যেহেতু আপনার ডিভাইসের ঘড়িটি ভুল, সেই জন্য Google Chrome সঠিকভাবে শংসাপত্রগুলি পরীক্ষা করতে পারছে না।</translation>
+<translation id="2969319727213777354">নিরাপদ নেটওয়ার্ক সংযোগ স্থাপন করতে আপনার ঘড়িকে সঠিকভাবে সেট করতে হবে। এমন হওয়ার কারণ হলো, নিরাপদ সংযোগ স্থাপন করার জন্য নিজেদের শনাক্ত করার জন্য ওয়েবসাইটগুলি যে শংসাপত্রগুলি ব্যবহার করে, সেগুলি শুধুমাত্র নির্দিষ্ট সময়ের জন্য বৈধ থাকে। যেহেতু আপনার ডিভাইসের ঘড়িটি ভুল, সেই জন্য Google Chrome সঠিকভাবে শংসাপত্রগুলি পরীক্ষা করতে পারছে না।</translation>
<translation id="2972581237482394796">&amp;পুনরায় করুন</translation>
<translation id="2977665033722899841">এখন <ph name="ROW_NAME" /> বেছে নিয়েছেন। <ph name="ROW_CONTENT" /></translation>
<translation id="298138621710431427">এটি ঠিক করতে আমাকে সহায়তা করুন</translation>
@@ -286,7 +283,6 @@
<translation id="3010559122411665027">তালিকার এন্ট্রি " <ph name="ENTRY_INDEX" /> ": <ph name="ERROR" /></translation>
<translation id="301521992641321250">স্বয়ংক্রিয়ভাবে ব্লক করা হয়েছে</translation>
<translation id="3024663005179499861">নীতির ভুল প্রকার</translation>
-<translation id="3032412215588512954">আপনি কি এই সাইটটি পুনরায় লোড করতে চান?</translation>
<translation id="3037605927509011580">ইস!</translation>
<translation id="3039538478787849737">Google এ কার্ড সেভ করবেন?</translation>
<translation id="3041612393474885105">শংসাপত্র তথ্য</translation>
@@ -311,16 +307,17 @@
বা আপনার নেটওয়ার্ক প্রশাসকের সাথে যোগাযোগ করুন৷ আপনি কোনো প্রক্সী সার্ভার
ব্যবহার করবেন না বলে মনে করলে:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="SERVER_NAME" /> এ <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">পেমেন্ট বাতিল করুন</translation>
<translation id="3207960819495026254">বুকমার্ক করা হয়েছে</translation>
<translation id="3209375525920864198">অনুগ্রহ করে একটি সঠিক সেশনের নাম লিখুন।</translation>
<translation id="3211223744486044430">পরের বার আরও দ্রুত পেমেন্ট করা জন্য এই কার্ডটি Google অ্যাকাউন্টে এবং এই ডিভাইসে সেভ করে রাখুন।</translation>
-<translation id="3225919329040284222">সার্ভারটি এমন একটি শংসাপত্র উপস্থাপনা করেছে যা বিল্ট-ইন প্রত্যাশাগুলির সাথে মেলে না৷ এই প্রত্যাশাগুলি আপনাকে সুরক্ষিত করতে কিছু নিশ্চিত, উচ্চ সুরক্ষার ওয়েবসাইটের জন্য অন্তর্ভুক্ত৷</translation>
+<translation id="3225919329040284222">সার্ভারটি এমন একটি শংসাপত্র উপস্থাপনা করেছে যা অন্তর্ভুক্ত প্রত্যাশাগুলির সাথে মেলে না৷ এই প্রত্যাশাগুলি আপনাকে সুরক্ষিত করতে কিছু নিশ্চিত, উচ্চ সুরক্ষার ওয়েবসাইটের জন্য অন্তর্ভুক্ত৷</translation>
<translation id="3226128629678568754">পৃষ্ঠাটি লোড করতে প্রয়োজনীয় ডেটেটি আবার জমা দিতে আবার লোড করার বোতামটি টিপুন৷</translation>
<translation id="3227137524299004712">মাইক্রোফোন</translation>
<translation id="3228969707346345236">পৃষ্ঠাটি ইতিমধ্যে <ph name="LANGUAGE" />-এ থাকার কারণে অনুবাদ ব্যর্থ হয়েছে৷</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> এর CVC লিখুন</translation>
-<translation id="3234666976984236645">এই সাইটে সর্বদা গুরুত্বপূর্ণ সামগ্রী সনাক্ত করুন</translation>
+<translation id="3234666976984236645">এই সাইটে সর্বদা গুরুত্বপূর্ণ সামগ্রী শনাক্ত করুন</translation>
<translation id="3254409185687681395">এই পৃষ্ঠাটি বুকমার্ক করুন</translation>
<translation id="3270847123878663523">&amp;পুনর্বিন্যাসকে পূর্বাবস্থায় ফেরান</translation>
<translation id="3282497668470633863">কার্ডে থাকা নাম যোগ করুন</translation>
@@ -368,11 +365,57 @@
<translation id="3556433843310711081">আপনার পরিচালক আপনার হয়ে এটি অবরোধ মুক্ত করতে পারবে</translation>
<translation id="3566021033012934673">আপনার সংযোগ ব্যক্তিগত নয়</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" /> এ এম্বেডেড করা পৃষ্ঠায় এটি দেখানো হচ্ছে</translation>
<translation id="358285529439630156">ক্রেডিট এবং প্রিপেড কার্ড গ্রহণ করা হয়।</translation>
<translation id="3582930987043644930">নাম যোগ করুন</translation>
<translation id="3583757800736429874">&amp;সরানোর কাজটি আবার করুন</translation>
<translation id="3586931643579894722">বিশদ বিবরণ লুকান</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;কানেকশনের সমস্যাগুলি সমাধান করুন&lt;/h1&gt;
+ &lt;p&gt;ওয়েবসাইট দেখার সময় যদি আপনি সমস্যা সম্পর্কিত কোনও মেসেজ পান তাহলে এই সমাধানগুলি ব্যবহার করে দেখতে পারেন।&lt;/p&gt;
+ &lt;h2&gt;বেশিরভাগ কানেকশনের সমস্যাগুলি সমাধান করুন&lt;/h2&gt;
+ &lt;p&gt;আপনি যদি কোনও ওয়েবসাইট দেখার চেষ্টা করেন এবং সেটি যদি না খোলে তাহলে সমস্যা সমাধানকারী পদক্ষেপগুলি ব্যবহার করে সমস্যা সমাধানের চেষ্টা করুন:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;ওয়েব ঠিকানাটি ঠিকভাবে লেখা হয়েছে তা দেখে নিন।&lt;/li&gt;
+ &lt;li&gt;আপনার ইন্টারনেট কানেকশন ঠিকভাবে কাজ করছে কিনা তা দেখে নিন।&lt;/li&gt;
+ &lt;li&gt;ওয়েবসাইট মালিকের সাথে যোগাযোগ করুন।&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;সমস্যা সম্পর্কিত নির্দিষ্ট মেসেজের বিষয়ে সাহায্য পান&lt;/h2&gt;
+ &lt;h3&gt;‘আপনার কানেকশনটি ব্যক্তিগত নয়’ অথবা "NET::ERR_CERT_AUTHORITY_INVALID" অথবা "ERR_CERT_COMMON_NAME_INVALID" অথবা "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" অথবা ‘SSL সার্টিফিকেটে সমস্যা’&lt;/h3&gt;
+ &lt;h4&gt;ধাপ ১: পোর্টালে সাইন-ইন করুন&lt;/h4&gt;
+ &lt;p&gt;ক্যাফে অথবা এয়ারপোর্টের মতো জায়গায় ওয়াই-ফাই কানেকশন ব্যবহার করার জন্য আপনাকে সাইন-ইন করতে হবে। সাইন-ইন পৃষ্ঠায় যাওয়ার জন্য সেইসব পৃষ্ঠা দেখুন যেগুলি &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt; ব্যবহার করে। &lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;&lt;code&gt;http://&lt;/code&gt; দিয়ে শুরু যেকোনও ওয়েবসাইটে যান, যেমন- &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;সাইন-ইন করার পৃষ্ঠাটি খুলবে, সেখানে ইন্টারনেট ব্যবহার করার জন্য সাইন-ইন করুন।&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;ধাপ ২: ছদ্দবেশী মোডে পৃষ্ঠাটি খুলুন (শুধুমাত্র কম্পিউটার)&lt;/h4&gt;
+ &lt;p&gt;ছদ্দবেশী উইন্ডোতে যে পৃষ্ঠাটি দেখছেন সেটি খুলুন।&lt;/p&gt;
+ &lt;p&gt;যদি পৃষ্ঠাটি খোলে তাহলে Chrome এক্সটেনশন কাজ করবে না। সমস্যাটির সমাধান করতে এক্সটেনশনটি বন্ধ করুন।&lt;/p&gt;
+ &lt;h4&gt;ধাপ ৩: আপনার অপারেটিং সিস্টেমটি আপডেট করুন&lt;/h4&gt;
+ &lt;p&gt;আপনার ডিভাইস আপ-টু-ডেট আছে কিনা তা নিশ্চিত করুন।&lt;/p&gt;
+ &lt;h4&gt;ধাপ ৪: অ্যান্টিভাইরাসটি অস্থায়ীভাবে বন্ধ করুন&lt;/h4&gt;
+ &lt;p&gt;আপনার যদি অ্যান্টিভাইরাস সফ্টওয়্যার যদি "HTTPS সুরক্ষা" অথবা "HTTPS স্ক্যানিং" প্রদান করে তাহলে আপনি এইধরনের সমস্যা দেখতে পাবেন। অ্যান্টিভাইরাসটি Chrome-কে নিরাপত্তা প্রদান করা থেকে বাধা দেয়।&lt;/p&gt;
+ &lt;p&gt;সমস্যাটি সমাধান করতে অ্যান্টিভাইরাস সফ্টওয়্যারটি বন্ধ করুন। যদি সফ্টওয়্যারটি বন্ধ করার পর পৃষ্ঠাটি কাজ করে তাহলে নিরাপদ সাইট ব্যবহার করার সময় এই সফ্টওয়্যারটি বন্ধ রাখুন।&lt;/p&gt;
+ &lt;p&gt;কাজ শেষ হয়ে গেলে অ্যান্টিভাইরাস প্রোগ্রামটি চালু করতে ভুলবেন না।&lt;/p&gt;
+ &lt;h4&gt;ধাপ ৫: অতিরিক্ত সাহায্য পান&lt;/h4&gt;
+ &lt;p&gt;এরপরেও যদি সমস্যার সম্মুখীন হন তাহলে ওয়েবসাইট মালিকের সাথে যোগাযোগ করুন।&lt;/p&gt;
+ &lt;h3&gt;"নেটওয়ার্কে কানেক্ট করুন"&lt;/h3&gt;
+ &lt;p&gt;আপনি যদি অনলাইনে ওয়াই-ফাই পোর্টাল ব্যবহার করতে চান তবে আপনি এই সমস্যাটি দেখতে পাবেন।&lt;/p&gt;
+ &lt;p&gt;সমস্যাটি সমাধানের করতে, আপনি যে পৃষ্ঠাটি খোলার চেষ্টা করছেন সেখানে &lt;strong&gt;Connect&lt;/strong&gt;এ ক্লিক করুন।&lt;/p&gt;
+ &lt;h3&gt;"আপনার ঘড়িটি স্লো হয়ে গেছে" or "আপনার ঘড়িটি ফাস্ট চলছে" or "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;আপনার কম্পিউটার অথবা মোবাইল ডিভাইসের তারিখ এবং সময় যথাযথ না হলে আপনি এই সমস্যাটি দেখতে পাবেন।&lt;/p&gt;
+ &lt;p&gt;সমস্যাটি সমাধান করতে আপনার ডিভাইসের ঘড়িটি খুলুন। সময় এবং তারিখটি যথাযথ আছে কিনা তা নিশ্চিত করুন।&lt;/p&gt;
+ &lt;h3&gt;‘আপনার কম্পিউটারে এমন কোনও সফ্টওয়্যার আছে যার জন্য Chrome ওয়েবে নিরাপদে কানেক্ট করতে পারছে না’ (শুধুমাত্র কম্পিউটার)&lt;/h3&gt;
+ &lt;p&gt;আপনার উইন্ডোজ কম্পিউটারে যদি 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;li&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;পরিষেবার স্ট্যাটাস&lt;/strong&gt; এর অধীনে click &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;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome সহায়তা কেন্দ্রে&lt;/a&gt; যান
+ &lt;/ol&gt;</translation>
<translation id="3615877443314183785">মেয়াদ শেষ হওয়ার তারিখের সঠিক মান লিখুন</translation>
<translation id="36224234498066874">ব্রাউজ করা ডেটা সাফ করুন...</translation>
<translation id="362276910939193118">সম্পূর্ণ ইতিহাস দেখুন</translation>
@@ -405,7 +448,6 @@
<translation id="3778403066972421603">আপনি কি এই কার্ডটি আপনার Google অ্যাকাউন্টে ও এই ডিভাইসে সেভ করতে চান?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> এ মেয়াদ শেষ হবে</translation>
-<translation id="3800436529451849929"><ph name="SITE" /> সাইট থেকে</translation>
<translation id="382518646247711829">যদি আপনি একটি প্রক্সি সার্ভার ব্যবহার করেন...</translation>
<translation id="3828924085048779000">ফাঁকা পাসফ্রেজের অনুমতি নেই৷</translation>
<translation id="385051799172605136">ফিরুন</translation>
@@ -419,6 +461,7 @@
<translation id="3945915738023014686">ক্র্যাশ রিপোর্ট আইডি <ph name="CRASH_ID" /> আপলোড করা হয়েছে (স্থানীয় ক্র্যাশ আইডি: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">এই সার্ভারটিকে <ph name="DOMAIN" /> হিসাবে প্রমাণ করা যায়নি; এটির নিরাপত্তা শংসাপত্রে সাবজেক্ট অল্টারনেটিভ নেম্স নির্দিষ্ট করা নেই। কনফিগারেশনের কোনও সমস্যা অথবা আপনার সংযোগে কোনও আক্রমণকারী আড়ি পাতার কারণে এটি হয়ে থাকতে পারে।</translation>
<translation id="3949601375789751990">আপনার ব্রাউজিং এর ইতিহাস এখানে দেখা যায়</translation>
+<translation id="3950820424414687140">প্রবেশ করুন</translation>
<translation id="3963721102035795474">পাঠক মোড</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{কিছুই নয়}=1{১টি সাইট থেকে }one{#টি সাইট থেকে }other{#টি সাইট থেকে }}</translation>
<translation id="397105322502079400">গণনা করা হচ্ছে...</translation>
@@ -435,13 +478,14 @@
<translation id="4103249731201008433">ডিভাইসের ক্রমিক সংখ্যা অবৈধ</translation>
<translation id="410351446219883937">স্বতঃচালানো</translation>
<translation id="4103763322291513355">নিবারিত URLগুলির তালিকা এবং আপনার সিস্টেম প্রশাসকের দ্বারা জারি করা অন্যান্য নীতিগুলি দেখার জন্য &lt;strong&gt;chrome://policy&lt;/strong&gt; এ যান৷</translation>
+<translation id="4110652170750985508">আপনার পেমেন্টের রিভিউ</translation>
<translation id="4116663294526079822">এই সাইটে সর্বদা অনুমতি দিন</translation>
<translation id="4117700440116928470">নীতির সুযোগটি সমর্থিত নয়৷</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{আরও ১টি}one{অন্যান্য #টি}other{অন্যান্য #টি}}</translation>
<translation id="4130226655945681476">নেটওয়ার্কের তার, মডেম, এবং রাউটার পরীক্ষা করুন</translation>
<translation id="413544239732274901">আরও জানুন</translation>
<translation id="4148925816941278100">আমেরিকান এক্সপ্রেস</translation>
-<translation id="4151403195736952345">গ্লোবাল ডিফল্ট (সনাক্ত করুন) ব্যবহার করুন</translation>
+<translation id="4151403195736952345">গ্লোবাল ডিফল্ট (শনাক্ত করুন) ব্যবহার করুন</translation>
<translation id="4165986682804962316">সাইটের সেটিংস</translation>
<translation id="4169947484918424451">আপনি কি চান যে Chromium এই কার্ড সংরক্ষণ করুক?</translation>
<translation id="4171400957073367226">খারাপ যাচাইকরণের স্বাক্ষর</translation>
@@ -461,7 +505,6 @@
<translation id="4269787794583293679">(কোনো ইউজারনেম নেই)</translation>
<translation id="4275830172053184480">আপনার ডিভাইস বন্ধ করে চালু করুন</translation>
<translation id="4280429058323657511">, মেয়াদ শেষ <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">লগ ইন</translation>
<translation id="4312866146174492540">অবরুদ্ধ করুন (ডিফল্ট)</translation>
<translation id="4325863107915753736">নিবন্ধ খুঁজে পেতে ব্যর্থ হয়েছে</translation>
<translation id="4326324639298822553">আপনার মেয়াদ শেষের তারিখ পরীক্ষা করে আবার চেষ্টা করুন</translation>
@@ -483,14 +526,12 @@
<translation id="4515275063822566619">কার্ড ও ঠিকানাগুলি Chrome এবং আপনার Google অ্যাকাউন্ট (<ph name="ACCOUNT_EMAIL" />) থেকে এসেছে। আপনি <ph name="BEGIN_LINK" />সেটিংস<ph name="END_LINK" /> এ গিয়ে সেগুলি পরিচালনা করতে পারবেন।</translation>
<translation id="4522570452068850558">বিশদ বিবরণ</translation>
<translation id="4552089082226364758">ফ্ল্যাশ</translation>
-<translation id="4554702541363482291"><ph name="SITE" /> এ এম্বেড করা পৃষ্ঠায়</translation>
<translation id="4558551763791394412">আপনার এক্সটেনশানগুলি অক্ষম করে দেখুন।</translation>
<translation id="457875822857220463">পৌঁছে দেওয়া</translation>
<translation id="4582800630050655161">আপনি নিজের Google অ্যাকাউন্টে অ্যাক্সেস হারাতে পারেন বা আপনার পরিচয় চুরি হতেই পারে। Chromium এখনই আপনার পাসওয়ার্ড পরিবর্তন করার আর্জি জানাচ্ছে।</translation>
<translation id="4587425331216688090">Chrome থেকে ঠিকানা সরাবেন?</translation>
<translation id="4592951414987517459">একটি আধুনিক সাইফার স্যুট ব্যবহার করে <ph name="DOMAIN" />-এ আপনার সংযোগ এনক্রিপ্ট করা হয়েছে।</translation>
<translation id="4594403342090139922">&amp;মুছে ফেলাকে পূর্বাবস্থায় ফেরান</translation>
-<translation id="4611292653554630842">লগ-ইন করুন</translation>
<translation id="4619615317237390068">অন্যান্য ডিভাইসগুলি থেকে ট্যাব</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">এই সার্ভার প্রমাণ করতে পারেনি যে এটি <ph name="DOMAIN" />; এর নিরাপত্তা শংসাপত্রে কিছু ত্রুটি আছে। কোনো ভুল কনফিগারেশনের কারণে অথবা কোনো আক্রমণকারী আপনার সংযোগ মাঝপথে আটকে দিচ্ছে বলে এমনটা হতে পারে।</translation>
@@ -500,11 +541,9 @@
<translation id="4708268264240856090">আপনার সংযোগ বাধাপ্রাপ্ত হয়েছে</translation>
<translation id="471880041731876836">এই সাইট দেখার অনুমতি আপনার নেই</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows নেটওয়ার্ক ডায়গনিস্টিক্স চালান<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">আপনার অর্থপ্রদান</translation>
<translation id="4726672564094551039">নীতিগুলি পুনঃলোড করুন</translation>
<translation id="4728558894243024398">প্ল্যাটফর্ম</translation>
<translation id="4736825316280949806">Chromium পুনরায় চালু করুন</translation>
-<translation id="4737498291095696011">এই পৃষ্ঠা থেকে</translation>
<translation id="4744603770635761495">সম্পাদনযোগ্য পথ</translation>
<translation id="4749685221585524849">শেষবার ব্যবহার করা হয়েছে <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">আপনার তথ্য (উদাহরণস্বরূপ, পাসওয়ার্ড বা ক্রেডিট কার্ড নম্বর) যখন এই সাইটে পাঠানো হয় তখন সেটি ব্যক্তিগত থাকে।</translation>
@@ -523,16 +562,16 @@
<translation id="4850886885716139402">দেখুন</translation>
<translation id="4854362297993841467">এই পদ্ধতিতে ডেলিভারি করা যাবে না। অন্য পদ্ধতি ব্যবহার করুন।</translation>
<translation id="4858792381671956233">এই সাইটটি দেখার জন্য উপযুক্ত কিনা তা আপনি আপনার পিতামাতাকে জিজ্ঞাসা করেছেন</translation>
-<translation id="4871132632506079383"><ph name="SITE" /> এ এম্বেড করা পৃষ্ঠায়</translation>
<translation id="4880827082731008257">সার্চের ইতিহাস</translation>
+<translation id="4881695831933465202">খুলুন</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">প্রমাণীকরণ প্রয়োজন</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{এবং আরও ১টি ওয়েব পৃষ্ঠা}one{এবং আরও #টি ওয়েব পৃষ্ঠা}other{এবং আরও #টি ওয়েব পৃষ্ঠা}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947"><ph name="CREDIT_CARD" /> এর জন্য সিভিসি লিখুন। আপনি নিশ্চিত করার পর আপনার Google অর্থ প্রদান অ্যাকাউন্ট থেকে কার্ডের বিবরণ এই সাইটে শেয়ার করা হবে।</translation>
<translation id="4923417429809017348">এই পৃষ্ঠাটি কোন অজানা ভাষা থেকে <ph name="LANGUAGE_LANGUAGE" />-এ অনুবাদ করা হয়েছে</translation>
<translation id="4923459931733593730">অর্থপ্রদান</translation>
<translation id="4926049483395192435">নির্দিষ্ট করা উচিত৷</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> এ এটি দেখানো হচ্ছে</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">ক্রিয়াসমূহ</translation>
<translation id="4958444002117714549">তালিকা প্রসারিত করুন</translation>
@@ -541,7 +580,6 @@
<translation id="5002932099480077015">সক্রিয় করা হলে, ফর্ম পূরনের কাজ দ্রুত করতে Chrome এই ডিভাইসে আপনার কার্ডের একটি প্রতিলিপি সংরক্ষণ করবে।</translation>
<translation id="5018422839182700155">এই পৃষ্ঠাটি খোলা যাচ্ছে না</translation>
<translation id="5019198164206649151">ব্যাকিং স্টোরটি ত্রুটিপূর্ণ অবস্থায় আছে</translation>
-<translation id="5020990877659450221">এই পৃষ্ঠা থেকে</translation>
<translation id="5023310440958281426">আপনার প্রশাসকের নীতিগুলি দেখুন</translation>
<translation id="5029568752722684782">প্রতিলিপি সাফ করুন</translation>
<translation id="503069730517007720">"<ph name="SOFTWARE_NAME" />" এর জন্য একটি রুট সার্টিফিকেট প্রয়োজন কিন্তু সেটি ইনস্টল করা নেই। এই সমস্যাটি সমাধান করতে আপনার IT প্রশাসককে "<ph name="SOFTWARE_NAME" />" এর কনফিগারেশন নির্দেশ ভাল করে দেখে নিতে হবে। <ph name="FURTHER_EXPLANATION" /></translation>
@@ -567,12 +605,12 @@
<translation id="5172758083709347301">যন্ত্র</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" />-এ নেই? এই ত্রুটি রিপোর্ট করুন</translation>
<translation id="5190835502935405962">বুকমার্ক দণ্ড</translation>
+<translation id="5201306358585911203">এই পৃষ্ঠার এম্বেডেড করা একটি পৃষ্ঠায় এটি দেখানো হচ্ছে</translation>
<translation id="5205222826937269299">নাম প্রয়োজন</translation>
<translation id="5222812217790122047">ইমেল প্রয়োজন</translation>
<translation id="522700295135997067">এই সাইট হয়ত আপনার পাসওয়ার্ড চুরি করেছে</translation>
<translation id="5230733896359313003">শিপিংয়ের ঠিকানা</translation>
<translation id="5251803541071282808">ক্লাউড</translation>
-<translation id="5277279256032773186">কর্মক্ষেত্রে Chrome ব্যবহার করছেন? ব্যবসাগুলো তাদের কর্মচারীদের জন্য Chrome সেটিংস পরিচালনা করতে পারে। আরও জানুন</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />সফ্টওয়্যারটি সাময়িকভাবে নিষ্ক্রিয় করার জন্য এই পদক্ষেপগুলি অনুসরণ করুন যাতে আপনি ওয়েবে যেতে পারেন। আপনার প্রশাসকের অধিকার প্রয়োজন হবে।<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -634,7 +672,6 @@
<translation id="5610142619324316209">সংযোগ পরীক্ষা করে দেখুন</translation>
<translation id="5610807607761827392">আপনি <ph name="BEGIN_LINK" />সেটিংস<ph name="END_LINK" /> থেকে কার্ড এবং ঠিকানাগুলি পরিচালনা করতে পারেন।</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> আপনাকে অনেক বেশিবার পুনঃনির্দেশিত করেছে।</translation>
-<translation id="5622887735448669177">আপনি কি এই সাইটটি ছেড়ে যেতে চান?</translation>
<translation id="5629630648637658800">নীতি সেটিংস লোড করতে ব্যর্থ হয়েছে</translation>
<translation id="5631439013527180824">অবৈধ ডিভাইস পরিচালনা টোকেন</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>
@@ -657,7 +694,6 @@
<translation id="5786044859038896871">আপনি কি আপনার কার্ডের তথ্য পূরণ করতে চান?</translation>
<translation id="5803412860119678065">আপনি কি আপনার <ph name="CARD_DETAIL" /> এর তথ্য পূরণ করতে চান?</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" />-এ আপনার সংযোগ একটি অপ্রচলিত সাইফার স্যুট ব্যবহার করে এনক্রিপ্ট করা হয়েছে৷</translation>
-<translation id="5810928923025889964">এই পৃষ্ঠার এম্বেড করা একটি পৃষ্ঠা থেকে</translation>
<translation id="5813119285467412249">&amp;যোগ করাকে পুনরায় করুন</translation>
<translation id="5838278095973806738">এই সাইটে আপনার কোনো সংবেদনশীল তথ্য দেওয়া উচিত হবে না (উদাহরণস্বরূপ, পাসওয়ার্ড বা ক্রেডিট কার্ড) কারণ আক্রমণকারীরা এগুলি চুরি করতে পারে।</translation>
<translation id="5866257070973731571">ফোন নম্বর যোগ করুন</translation>
@@ -667,7 +703,7 @@
<translation id="5908541034548427511"><ph name="TYPE_1" /> (সিঙ্ক হয়েছে)</translation>
<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{১টি ব্যবহৃত হচ্ছে}one{#টি ব্যবহৃত হচ্ছে}other{#টি ব্যবহৃত হচ্ছে}}</translation>
<translation id="5939518447894949180">রিসেট করুন</translation>
-<translation id="5959728338436674663">বিপজ্জনক অ্যাপ্লিকেশান ও সাইটগুলি সনাক্ত করতে Google এর কাছে কিছু<ph name="BEGIN_WHITEPAPER_LINK" /> সিস্টেম তথ্য ও পৃষ্ঠার সামগ্রী<ph name="END_WHITEPAPER_LINK" /> স্বয়ংক্রিয়ভাবে পাঠান। <ph name="PRIVACY_PAGE_LINK" /></translation>
+<translation id="5959728338436674663">বিপজ্জনক অ্যাপ্লিকেশান ও সাইটগুলি শনাক্ত করতে Google এর কাছে কিছু<ph name="BEGIN_WHITEPAPER_LINK" /> সিস্টেম তথ্য ও পৃষ্ঠার সামগ্রী<ph name="END_WHITEPAPER_LINK" /> স্বয়ংক্রিয়ভাবে পাঠান। <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="5967592137238574583">পরিচিতির তথ্য সম্পাদনা করুন</translation>
<translation id="5967867314010545767">ইতিহাস থেকে সরান</translation>
<translation id="5972020793760134803">ট্যাবে পরিবর্তন করুন</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">আরও তথ্য যোগ করুন</translation>
<translation id="6447842834002726250">কুকিজ</translation>
<translation id="6451458296329894277">ফর্ম পুনঃজমা নিশ্চিত করুন</translation>
-<translation id="6456339708790392414">আপনার অর্থপ্রদান</translation>
<translation id="647261751007945333">ডিভাইস নীতিগুলি</translation>
<translation id="6477321094435799029">Chrome এই পৃষ্ঠাতে অস্বাভাবিক কোড পেয়েছে এবং আপনার ব্যক্তিগত তথ্যের (উদাহরণস্বরূপ, পাসওয়ার্ড, ফোন নম্বর, এবং ক্রেডিট কার্ড) সুরক্ষার জন্য এটি অবরুদ্ধ করেছে।</translation>
<translation id="6489534406876378309">ক্র্যাশগুলি আপলোড করা শুরু করুন</translation>
<translation id="6507833130742554667">ক্রেডিট ও ডেবিট কার্ড গ্রহণ করা হয়।</translation>
<translation id="6508722015517270189">Chrome পুনরায় চালু করুন</translation>
-<translation id="6521373090216409766">আপনি কি এই সাইটটি আবার লোড করতে চান?</translation>
<translation id="6529602333819889595">&amp;মুছে ফেলাকে আবার করুন</translation>
<translation id="6534179046333460208">বাস্তবিক ওয়েব প্রস্তাবনাগুলি</translation>
<translation id="6550675742724504774">বিকল্পসমূহ</translation>
-<translation id="6556239504065605927">সুরক্ষিত সংযোগ</translation>
<translation id="6556915248009097796">মেয়াদ শেষের তারিখ: <ph name="EXPIRATION_DATE_ABBR" />, শেষবার ব্যবহার করা হয়েছে <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">আপনার পরিচালক এখনও এটি অনুমোদন করেন নি</translation>
<translation id="6569060085658103619">আপনি একটি এক্সটেনশান পৃষ্ঠা দেখছেন</translation>
<translation id="6596325263575161958">এনক্রিপশন বিকল্পগুলি</translation>
+<translation id="6604181099783169992">মোশন বা হাল্কা সেন্সর</translation>
<translation id="6624427990725312378">পরিচিতির তথ্য</translation>
<translation id="6626291197371920147">বৈধ কার্ড নম্বর যোগ করুন</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> অনুসন্ধান</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">পরিচালিত বুকমার্কগুলি</translation>
<translation id="7298195798382681320">প্রস্তাবিত</translation>
<translation id="7309308571273880165"><ph name="CRASH_TIME" /> এ ক্র্যাশ প্রতিবেদন ক্যাপচার করা হয়েছে (ব্যবহারকারী দ্বারা আপলোডের অনুরোধ করা হয়েছে, এখনও আপলোড করা হয়নি)</translation>
+<translation id="7320336641823683070">কানেকশন সহায়তা</translation>
<translation id="7334320624316649418">&amp;পুনর্বিন্যাসকে আবার করুন</translation>
<translation id="733923710415886693">সার্ভারের শংসাপত্রটি শংসাপত্রের স্বচ্ছতার মাধ্যমে প্রকাশ করা হয়নি।</translation>
<translation id="7353601530677266744">কম্যান্ড লাইন</translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">আপনি যে (<ph name="WIFI_NAME" />) Wi-Fiটি ব্যবহার করছেন সেটির জন্য অপনাকে এটির লগ ইন পৃষ্ঠাতে যেতে হতে পরে৷</translation>
<translation id="785549533363645510">আপনি অবশ্য অদৃশ্য থাকবেন না। ছদ্মবেশী মোডে গেলেও তা আপনার নিয়োগকর্তা, আপনার ইন্টারনেট পরিষেবা প্রদানকারী অথবা আপনার পরিদর্শন করা ওয়েবসাইট থেকে আপনার ব্রাউজিংকে আড়াল করবে না।</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">সাইট ছেড়ে যাবেন?</translation>
<translation id="7878176543348854470">ডেবিট ও প্রিপেড কার্ড গ্রহণ করা হয়।</translation>
<translation id="7878562273885520351">আপনার পাসওয়ার্ড অন্য কেউ পরিবর্তন করার চেষ্টা করেছে</translation>
<translation id="7887683347370398519">আপনার CVC পরীক্ষা করুন এবং আবার চেষ্টা করুন</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">বিশ্বব্যাপী ডিফল্ট ব্যবহার করুন (জানতে চান)</translation>
<translation id="8042918947222776840">পিক-আপের পদ্ধতি বেছে নিন</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" সঠিকভাবে কনফিগার হয়নি। সাধারণত "<ph name="SOFTWARE_NAME" />" আন-ইনস্টল করা হলে সমস্যার সমাধান হয়ে যায়। <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">সাইটটি আবার লোড করবেন?</translation>
<translation id="8088680233425245692">নিবন্ধ দেখতে ব্যর্থ হয়েছে৷</translation>
<translation id="8091372947890762290">সার্ভারে সক্রিয়করণ বাকি আছে</translation>
<translation id="8094917007353911263">আপনি যে নেটওয়ার্কটি ব্যবহার করছেন সেটির জন্য অপনাকে <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />-তে যেতে হতে পারে৷</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" ID যুক্ত এক্সটেনশানের অবৈধ আপডেট URL।</translation>
<translation id="8202097416529803614">অর্ডারের সারসংক্ষেপ</translation>
<translation id="8205463626947051446">সাইটটিতে বিরক্তিকরভাবে বিজ্ঞাপন দেখানো হয়</translation>
+<translation id="8211406090763984747">কানেকশনটি নিরাপদ</translation>
<translation id="8218327578424803826">নির্ধারিত অবস্থান:</translation>
<translation id="8225771182978767009">এই কম্পিউটার যিনি সেট আপ করেছেন তিনি এই সাইটটি অবরুদ্ধ করার বিষয়টি চয়ন করেছেন।</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">সেভ করা সমস্ত পাসওয়ার্ড দেখান</translation>
<translation id="8261506727792406068">মুছুন</translation>
<translation id="8267698848189296333"><ph name="USERNAME" /> হিসেবে প্রবেশ করুন করছেন</translation>
+<translation id="8286036467436129157">প্রবেশ করুন</translation>
<translation id="8288807391153049143">সার্টিফিকেট দেখান</translation>
<translation id="8289355894181816810">যদি আপনি এর অর্থের ব্যাপারে নিশ্চিত না হন তাহলে আপনার নেটওয়ার্ক প্রশাসকের সঙ্গে যোগাযোগ করুন৷</translation>
<translation id="8293206222192510085">বুকমার্ক যুক্ত করুন</translation>
@@ -993,11 +1032,12 @@
<translation id="8725066075913043281">আবার চেষ্টা করুন</translation>
<translation id="8728672262656704056">আপনি গুপ্ত মোডে চলে গেছেন</translation>
<translation id="8730621377337864115">হয়ে গেছে</translation>
-<translation id="8738058698779197622">নিরাপদ নেটওয়ার্ক সংযোগ স্থাপন করতে আপনার ঘড়িকে সঠিকভাবে সেট করতে হবে৷ নিরাপদ সংযোগ স্থাপন করার জন্য নিজেদের সনাক্ত করার জন্য ওয়েবসাইটগুলি যে শংসাপত্রগুলি ব্যবহার করে, সেগুলি শুধুমাত্র নির্দিষ্ট সময়ের জন্য বৈধ থাকে৷ যেহেতু আপনার ডিভাইসের ঘড়িটি ভুল, সেই জন্য Chromium সঠিকভাবে শংসাপত্রগুলি পরীক্ষা করতে পারে না৷</translation>
+<translation id="8738058698779197622">নিরাপদ নেটওয়ার্ক সংযোগ স্থাপন করতে আপনার ঘড়িকে সঠিকভাবে সেট করতে হবে৷ নিরাপদ সংযোগ স্থাপন করার জন্য নিজেদের শনাক্ত করার জন্য ওয়েবসাইটগুলি যে শংসাপত্রগুলি ব্যবহার করে, সেগুলি শুধুমাত্র নির্দিষ্ট সময়ের জন্য বৈধ থাকে৷ যেহেতু আপনার ডিভাইসের ঘড়িটি ভুল, সেই জন্য Chromium সঠিকভাবে শংসাপত্রগুলি পরীক্ষা করতে পারে না৷</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" /> এর &lt;abbr id="dnsDefinition"&gt;DNS ঠিকানা&lt;/abbr&gt; পাওয়া যায়নি। সমস্যা নির্ণয় করা হচ্ছে।</translation>
<translation id="874846938927089722">এই ক্রেডিট ও প্রিপেড কার্ডগুলি গ্রহণ করা হয়</translation>
<translation id="8759274551635299824">এই কার্ডটির মেয়াদ শেষ হয়েছে</translation>
<translation id="8761567432415473239">Google নিরাপদ ব্রাউজিং সম্প্রতি <ph name="SITE" /> এ <ph name="BEGIN_LINK" />ক্ষতিকারক প্রোগ্রামগুলি খুঁজে পেয়েছে<ph name="END_LINK" />৷</translation>
+<translation id="8763927697961133303">USB ডিভাইস</translation>
<translation id="8790007591277257123">&amp;মুছে ফেলাকে আবার করুন</translation>
<translation id="8800988563907321413">আপনার জন্য আশেপাশের প্রস্তাবনাগুলি এখানে দেখা যাবে</translation>
<translation id="8820817407110198400">বুকমার্ক</translation>
diff --git a/chromium/components/strings/components_strings_ca.xtb b/chromium/components/strings/components_strings_ca.xtb
index 3bde2d29960..1d4f09a15cb 100644
--- a/chromium/components/strings/components_strings_ca.xtb
+++ b/chromium/components/strings/components_strings_ca.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Imprimeix...</translation>
<translation id="1181037720776840403">Suprimeix</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Informa automàticament<ph name="END_WHITEPAPER_LINK" /> Google dels detalls sobre possibles incidències de seguretat. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">No s'ha completat el pagament</translation>
<translation id="1201402288615127009">Següent</translation>
<translation id="1201895884277373915">Més entrades d'aquest lloc</translation>
<translation id="1206967143813997005">Signatura inicial incorrecta</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">S'ha capturat un informe d'error (<ph name="CRASH_TIME" />) (encara no s'ha penjat ni ignorat)</translation>
<translation id="1270502636509132238">Mètode de recollida</translation>
<translation id="1285320974508926690">No tradueixis mai aquest lloc</translation>
+<translation id="1294154142200295408">Variacions de la línia d'ordres</translation>
<translation id="129553762522093515">Tancades recentment</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Esborreu les galetes<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">És possible que la teva activitat <ph name="BEGIN_EMPHASIS" />continuï sent visible<ph name="END_EMPHASIS" /> en:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Targetes de crèdit i de dèbit acceptades</translation>
<translation id="1519264250979466059">Data de creació</translation>
<translation id="1527263332363067270">S'està esperant que hi hagi connexió…</translation>
+<translation id="1532118530259321453">Aquesta pàgina diu</translation>
<translation id="153384715582417236">De moment, això és tot</translation>
<translation id="154408704832528245">Tria l'adreça d'entrega</translation>
<translation id="1549470594296187301">Heu d'activar el JavaScript per utilitzar aquesta funció.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Comproveu el servidor intermediari i el tallafoc<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Codi postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggeriment}other{# suggeriments}}</translation>
-<translation id="2065985942032347596">Es necessita autenticació</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="2091887806945687916">So</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Cancel·la el pagament</translation>
<translation id="2147827593068025794">Sincronització en segon pla</translation>
<translation id="2148613324460538318">Afegeix una targeta</translation>
-<translation id="2149973817440762519">Edita l'adreça d'interès</translation>
<translation id="2154054054215849342">La sincronització no està disponible per al teu domini</translation>
<translation id="2154484045852737596">Edita la targeta</translation>
<translation id="2166049586286450108">Accés complet d'administrador</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Tria l'adreça de recollida</translation>
<translation id="2740531572673183784">D'acord</translation>
<translation id="2742870351467570537">Suprimeix els elements seleccionats</translation>
-<translation id="2744590937989388266">D'una pàgina inserida en aquesta pàgina</translation>
<translation id="277133753123645258">Mètode d'enviament</translation>
<translation id="277499241957683684">Falta el registre del dispositiu</translation>
<translation id="2784949926578158345">S'ha restablert la connexió.</translation>
<translation id="2788784517760473862">Targetes de crèdit acceptades</translation>
<translation id="2794233252405721443">Lloc bloquejat</translation>
-<translation id="2795286477369100655">Vols sortir d'aquest lloc web?</translation>
<translation id="2799020568854403057">Aquest lloc web conté aplicacions perjudicials</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="2824775600643448204">Barra d'adreces i de cerca</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Entrada de llista "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Bloquejada automàticament</translation>
<translation id="3024663005179499861">Tipus de política incorrecte</translation>
-<translation id="3032412215588512954">Voleu tornar a carregar aquest lloc?</translation>
<translation id="3037605927509011580">Oh, no!</translation>
<translation id="3039538478787849737">Vols desar la targeta a Google?</translation>
<translation id="3041612393474885105">Informació del certificat</translation>
@@ -310,10 +306,11 @@
assegurar-vos que el servidor intermediari funcioni correctament. Si creieu que no és necessari
utilitzar un servidor intermediari:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> a <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Cancel·la el pagament</translation>
<translation id="3207960819495026254">S'ha afegit a les adreces d'interès.</translation>
<translation id="3209375525920864198">Introdueix un nom de sessió vàlid.</translation>
-<translation id="3211223744486044430">Perquè la propera vegada puguis pagar més ràpidament, desa la targeta al teu compte de Google i en aquest dispositiu.</translation>
+<translation id="3211223744486044430">Perquè la propera vegada puguis pagar més ràpidament, desa la targeta al compte de Google i en aquest dispositiu.</translation>
<translation id="3225919329040284222">El servidor ha presentat un certificat que no coincideix amb les expectatives integrades. Les expectatives s'inclouen perquè determinats llocs web d'alta seguretat us protegeixin.</translation>
<translation id="3226128629678568754">Premeu el botó de tornar a carregar per tornar a enviar les dades necessàries per carregar la pàgina.</translation>
<translation id="3227137524299004712">Micròfon</translation>
@@ -365,13 +362,59 @@
<translation id="3542684924769048008">Utilitzar la contrasenya per a:</translation>
<translation id="3549644494707163724">Encripta totes les dades sincronitzades amb la teva frase de contrasenya de sincronització</translation>
<translation id="3556433843310711081">El teu gestor te'l pot desbloquejar</translation>
-<translation id="3566021033012934673">La vostra connexió no és privada</translation>
+<translation id="3566021033012934673">La connexió no és privada</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Una pàgina inserida a <ph name="SITE" /> diu</translation>
<translation id="358285529439630156">S'accepten targetes de crèdit i de prepagament.</translation>
<translation id="3582930987043644930">Afegeix el nom</translation>
<translation id="3583757800736429874">&amp;Refés el moviment</translation>
<translation id="3586931643579894722">Oculta els detalls</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Solucionar errors de connexió&lt;/h1&gt;
+ &lt;p&gt;Si veieu un missatge d'error en visitar un lloc web, proveu aquestes solucions.&lt;/p&gt;
+ &lt;h2&gt;Solucionar la majoria d'errors de connexió&lt;/h2&gt;
+ &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;
+ &lt;ol&gt;
+ &lt;li&gt;Comproveu si hi ha errors ortogràfics a l'adreça web.&lt;/li&gt;
+ &lt;li&gt;Comproveu que la connexió a Internet funcioni amb normalitat.&lt;/li&gt;
+ &lt;li&gt;Contacteu amb el propietari del lloc web.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Obtenir ajuda amb un missatge d'error específic&lt;/h2&gt;
+ &lt;h3&gt;"La connexió no és privada", "NET::ERR_CERT_AUTHORITY_INVALID", "ERR_CERT_COMMON_NAME_INVALID", "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" o "Error de certificat SSL"&lt;/h3&gt;
+ &lt;h4&gt;Pas 1: inicieu la sessió al portal&lt;/h4&gt;
+ &lt;p&gt;Les xarxes Wi-Fi de llocs com ara cafeteries o aeroports requereixen que inicieu la sessió. Per veure la pàgina d'inici de sessió, aneu a una pàgina que faci servir &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Aneu a qualsevol lloc web que comenci per &lt;code&gt;http://&lt;/code&gt;, com ara &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;A la pàgina d'inici de sessió que s'obrirà, inicieu la sessió per utilitzar Internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Pas 2: obriu la pàgina en mode d'incògnit (només a l'ordinador)&lt;/h4&gt;
+ &lt;p&gt;Obriu en una finestra d'incògnit la pàgina que estàveu visitant.&lt;/p&gt;
+ &lt;p&gt;Si la pàgina s'obre, significa que alguna extensió de Chrome no funciona bé. Per solucionar l'error, desactiveu l'extensió.&lt;/p&gt;
+ &lt;h4&gt;Pas 3: actualitzeu el sistema operatiu&lt;/h4&gt;
+ &lt;p&gt;Assegureu-vos que el dispositiu estigui actualitzat.&lt;/p&gt;
+ &lt;h4&gt;Pas 4: desactiveu l'antivirus temporalment&lt;/h4&gt;
+ &lt;p&gt;Aquest error es mostra si teniu un programari antivirus amb "protecció d'HTTPS" o "anàlisi d'HTTPS". L'antivirus interfereix amb les funcions de seguretat de Chrome.&lt;/p&gt;
+ &lt;p&gt;Per solucionar el problema, desactiveu el programari antivirus. Si així funciona la pàgina, desactiveu-lo per consultar llocs web segurs.&lt;/p&gt;
+ &lt;p&gt;Recordeu que heu de tornar a activar el programari antivirus quan hàgiu acabat.&lt;/p&gt;
+ &lt;h4&gt;Pas 5: obteniu més ajuda&lt;/h4&gt;
+ &lt;p&gt;Si encara veieu l'error, contacteu amb el propietari del lloc web.&lt;/p&gt;
+ &lt;h3&gt;"Connecta't a la xarxa"&lt;/h3&gt;
+ &lt;p&gt;Veureu aquest error 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.&lt;/p&gt;
+ &lt;h3&gt;"El rellotge està endarrerit", "El rellotge està avançat" o "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Veureu aquest error si la data i l'hora de l'ordinador o del dispositiu mòbil són incorrectes.&lt;/p&gt;
+ &lt;p&gt;Per solucionar l'error, obriu el rellotge del dispositiu i comproveu que la data i l'hora siguin correctes.&lt;/p&gt;
+ &lt;h3&gt;"L'ordinador conté programari que impedeix que Chrome es connecti de manera segura al web" (només en ordinadors Windows)&lt;/h3&gt;
+ &lt;p&gt;Veureu aquest error si teniu el programari Superfish en un ordinador Windows.&lt;/p&gt;
+ &lt;p&gt;Seguiu aquests passos per desactivar temporalment el programari i poder accedir al web. Per fer-ho, necessitareu privilegis d'administrador.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Feu clic a &lt;strong&gt;Inicia&lt;/strong&gt; i, a continuació, cerqueu i seleccioneu &lt;strong&gt;Visualitza els serveis locals&lt;/strong&gt;.
+ &lt;li&gt;Seleccioneu &lt;strong&gt;VisualDiscovery&lt;/strong&gt;.
+ &lt;li&gt;A &lt;strong&gt;Tipus d'inici&lt;/strong&gt;, seleccioneu &lt;strong&gt;Inhabilitat&lt;/strong&gt;.
+ &lt;li&gt;A &lt;strong&gt;Estat del servei&lt;/strong&gt;, feu clic a &lt;strong&gt;Atura&lt;/strong&gt;.
+ &lt;li&gt;Feu clic a &lt;strong&gt;Aplica&lt;/strong&gt; i, a continuació, a &lt;strong&gt;D'acord&lt;/strong&gt;.
+ &lt;li&gt;Aneu al &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="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>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Vols desar aquesta targeta al teu compte de Google i en aquest dispositiu?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Data de caducitat: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Del lloc web <ph name="SITE" /></translation>
<translation id="382518646247711829">Si feu servir un servidor intermediari...</translation>
<translation id="3828924085048779000">Les frases de contrasenya no poder estar buides.</translation>
<translation id="385051799172605136">Enrere</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">S'ha penjat l'identificador <ph name="CRASH_ID" /> de l'informe d'error (identificador d'error local: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Aquest servidor no ha pogut demostrar que sigui <ph name="DOMAIN" />, perquè el seu certificat de seguretat no especifica noms alternatius per a l'assumpte. Això pot ser a causa d'una configuració incorrecta o d'un atacant que intercepta la connexió.</translation>
<translation id="3949601375789751990">Aquí es mostra l'historial de navegació</translation>
+<translation id="3950820424414687140">Inicia la sessió</translation>
<translation id="3963721102035795474">Mode de lector</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Cap}=1{D'1 lloc }other{De # llocs }}</translation>
<translation id="397105322502079400">S’està calculant...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">El número de sèrie del dispositiu no és vàlid</translation>
<translation id="410351446219883937">Reproducció automàtica</translation>
<translation id="4103763322291513355">Visiteu &lt;strong&gt;chrome://policy&lt;/strong&gt; per veure la llista d'URL inclosos a la llista negra i altres polítiques aplicades per l'administrador del sistema.</translation>
+<translation id="4110652170750985508">Revisa el pagament</translation>
<translation id="4116663294526079822">Permet sempre en aquest lloc web</translation>
<translation id="4117700440116928470">L'àmbit de la política no s'admet.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 element més}other{# elements més}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Sense nom d'usuari)</translation>
<translation id="4275830172053184480">Reinici del dispositiu</translation>
<translation id="4280429058323657511">, caduca el dia <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Accedeix</translation>
<translation id="4312866146174492540">Bloqueja (opció predeterminada)</translation>
<translation id="4325863107915753736">No s'ha pogut trobar l'article</translation>
<translation id="4326324639298822553">Comprova la data de caducitat i torna-ho a provar</translation>
@@ -482,28 +525,24 @@
<translation id="4515275063822566619">Les targetes i les adreces s'obtenen de Chrome i del teu compte de Google (<ph name="ACCOUNT_EMAIL" />). Pots gestionar-les des de <ph name="BEGIN_LINK" />Configuració<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Detalls</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">D'una pàgina inserida a <ph name="SITE" /></translation>
<translation id="4558551763791394412">Desactiveu les extensions</translation>
<translation id="457875822857220463">Entrega</translation>
<translation id="4582800630050655161">Podries perdre l'accés al compte de Google o tenir problemes de suplantació d'identitat. Chromium et recomana que canviïs la contrasenya ara.</translation>
<translation id="4587425331216688090">Voleu suprimir l'adreça de Chrome?</translation>
<translation id="4592951414987517459">La connexió a <ph name="DOMAIN" /> s'ha encriptat amb un sistema de xifratge modern.</translation>
<translation id="4594403342090139922">&amp;Desfés la supressió</translation>
-<translation id="4611292653554630842">Inicia la sessió</translation>
<translation id="4619615317237390068">Pestanyes d'altres dispositius</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">El servidor no ha pogut comprovar que sigui <ph name="DOMAIN" /> perquè el seu certificat de seguretat conté errors. Això pot ser a causa d'una configuració incorrecta o d'un atacant que intercepta la vostra connexió.</translation>
<translation id="4690462567478992370">Deixa de fer servir un certificat no vàlid</translation>
-<translation id="4690954380545377795">Podries perdre l'accés al compte de Google o o tenir problemes de suplantació d'identitat. Chrome et recomana que canviïs la contrasenya ara.</translation>
+<translation id="4690954380545377795">Podries perdre l'accés al compte de Google o tenir problemes de suplantació d'identitat. Chrome et recomana que canviïs la contrasenya ara.</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">La connexió s'ha interromput</translation>
<translation id="471880041731876836">No tens permís per visitar aquest lloc web</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Executa el Diagnòstic de xarxa de Windows<ph name="END_LINK" />.</translation>
-<translation id="472349245089439925">El teu pagament</translation>
<translation id="4726672564094551039">Torna a carregar les polítiques</translation>
<translation id="4728558894243024398">Plataforma</translation>
<translation id="4736825316280949806">Reinicia Chromium</translation>
-<translation id="4737498291095696011">D'aquesta pàgina</translation>
<translation id="4744603770635761495">Camí executable</translation>
<translation id="4749685221585524849">Última utilització: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">La teva informació (com ara les contrasenyes o els números de targeta de crèdit) es considera privada quan s'envia a aquest lloc.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Mostra</translation>
<translation id="4854362297993841467">Aquest mètode d'entrega no està disponible. Prova'n un altre.</translation>
<translation id="4858792381671956233">Has demanat permís als teus pares per visitar aquest lloc</translation>
-<translation id="4871132632506079383">D'una pàgina inserida a <ph name="SITE" /></translation>
<translation id="4880827082731008257">Cerca a l'historial</translation>
+<translation id="4881695831933465202">Obre</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Cal autenticació</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{i 1 pàgina web més}other{i # pàgines web més}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Introdueix el CVC de la targeta <ph name="CREDIT_CARD" />. Un cop confirmada, els detalls de la targeta del compte de pagaments de Google es compartirà amb aquest lloc web.</translation>
<translation id="4923417429809017348">Aquesta pàgina s'ha traduït des d'un idioma desconegut a: <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Pagament</translation>
<translation id="4926049483395192435">S'ha d'especificar.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> diu</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Accions</translation>
<translation id="4958444002117714549">Desplega la llista</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Si s'activa, Chrome emmagatzemarà una còpia de la targeta en aquest dispositiu per agilitzar l'emplenament de formularis.</translation>
<translation id="5018422839182700155">No es pot obrir aquesta pàgina</translation>
<translation id="5019198164206649151">L'emmagatzematge de la còpia de seguretat està en mal estat</translation>
-<translation id="5020990877659450221">D'aquesta pàgina</translation>
<translation id="5023310440958281426">Consulteu les polítiques de l'administrador</translation>
<translation id="5029568752722684782">Esborra la còpia</translation>
<translation id="503069730517007720"><ph name="SOFTWARE_NAME" /> requereix un certificat arrel, però no està instal·lat. Per resoldre aquest problema, l'administrador de TI ha de consultar les instruccions per configurar <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Automàtica</translation>
<translation id="5179510805599951267">No està escrita en <ph name="ORIGINAL_LANGUAGE" />? Informa d'aquest error</translation>
<translation id="5190835502935405962">Barra d'adreces d'interès</translation>
+<translation id="5201306358585911203">Una pàgina inserida en aquesta pàgina diu</translation>
<translation id="5205222826937269299">El nom és obligatori</translation>
<translation id="5222812217790122047">El correu electrònic és obligatori</translation>
<translation id="522700295135997067">És possible que aquest lloc web t'acabi de robar la contrasenya</translation>
<translation id="5230733896359313003">Adreça d'enviament</translation>
<translation id="5251803541071282808">Núvol</translation>
-<translation id="5277279256032773186">Fas servir Chrome a la feina? Les empreses poden gestionar la configuració de Chrome dels empleats. Més informació</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Segueix aquests passos per desactivar temporalment el programari perquè puguis accedir al web. Per fer-ho, necessitaràs privilegis d'administrador.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Comproveu la connexió</translation>
<translation id="5610807607761827392">Pots gestionar les targetes i les adreces a <ph name="BEGIN_LINK" />Configuració<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> us ha redirigit massa vegades.</translation>
-<translation id="5622887735448669177">Voleu sortir d'aquest lloc?</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="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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Vols emplenar la informació de la teva targeta?</translation>
<translation id="5803412860119678065">Vols emplenar la informació de la teva targeta <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">La connexió a <ph name="DOMAIN" /> s'ha encriptat amb un sistema de xifratge obsolet.</translation>
-<translation id="5810928923025889964">D'una pàgina inserida en aquesta pàgina</translation>
<translation id="5813119285467412249">&amp;Refés l'addició</translation>
<translation id="5838278095973806738">No introdueixis informació confidencial en aquest lloc (com ara contrasenyes o targetes de crèdit), ja que alguns atacants podrien robar-la.</translation>
<translation id="5866257070973731571">Afegeix un número de telèfon</translation>
@@ -666,7 +702,7 @@
<translation id="5908541034548427511"><ph name="TYPE_1" /> (informació sincronitzada)</translation>
<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 en ús}other{# en ús}}</translation>
<translation id="5939518447894949180">Restableix</translation>
-<translation id="5959728338436674663">Envia automàticament algunes <ph name="BEGIN_WHITEPAPER_LINK" />dades del sistema i contingut de les pàgines<ph name="END_WHITEPAPER_LINK" /> a Google per ajudar a detectar les aplicacions i els llocs perillosos. <ph name="PRIVACY_PAGE_LINK" /></translation>
+<translation id="5959728338436674663">Envia automàticament algunes <ph name="BEGIN_WHITEPAPER_LINK" />dades del sistema i contingut de les pàgines<ph name="END_WHITEPAPER_LINK" /> a Google per ajudar a detectar les aplicacions i els llocs web perillosos. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="5967592137238574583">Edita la informació de contacte</translation>
<translation id="5967867314010545767">Elimina de l'historial</translation>
<translation id="5972020793760134803">Canvia a la pestanya</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Afegeix més informació</translation>
<translation id="6447842834002726250">Galetes</translation>
<translation id="6451458296329894277">Confirma el reenviament del formulari</translation>
-<translation id="6456339708790392414">El teu pagament</translation>
<translation id="647261751007945333">Polítiques de dispositius</translation>
<translation id="6477321094435799029">Chrome ha detectat codi poc comú en aquesta pàgina i, per tant, l'ha bloquejat per protegir la teva informació personal (per exemple, contrasenyes, números de telèfon i targetes de crèdit).</translation>
<translation id="6489534406876378309">Comença a penjar els errors</translation>
<translation id="6507833130742554667">S'accepten targetes de crèdit i de dèbit.</translation>
<translation id="6508722015517270189">Reinicia Chrome</translation>
-<translation id="6521373090216409766">Vols tornar a carregar aquest lloc web?</translation>
<translation id="6529602333819889595">&amp;Refés la supressió</translation>
<translation id="6534179046333460208">Suggeriments del Web físic</translation>
<translation id="6550675742724504774">Opcions</translation>
-<translation id="6556239504065605927">Connexió segura</translation>
<translation id="6556915248009097796">Data de caducitat: <ph name="EXPIRATION_DATE_ABBR" />; última utilització: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">El teu gestor encara no ho ha aprovat</translation>
<translation id="6569060085658103619">Estàs consultant la pàgina d'una extensió</translation>
<translation id="6596325263575161958">Opcions d'encriptació</translation>
+<translation id="6604181099783169992">Sensors de moviment o de llum</translation>
<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>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Adreces d'interès gestionades</translation>
<translation id="7298195798382681320">Recomanada</translation>
<translation id="7309308571273880165">S'ha capturat un informe d'error (<ph name="CRASH_TIME" />) (pujada sol·licitada per l'usuari, encara no s'ha dut a terme)</translation>
+<translation id="7320336641823683070">Ajuda amb la connexió</translation>
<translation id="7334320624316649418">&amp;Refés el canvi d'ordre</translation>
<translation id="733923710415886693">El certificat del servidor no s'ha divulgat mitjançant la Transparència de certificats.</translation>
<translation id="7353601530677266744">Línia d'ordres</translation>
@@ -887,7 +922,7 @@
<translation id="7764225426217299476">Afegeix una adreça</translation>
<translation id="777702478322588152">Prefectura</translation>
<translation id="7791543448312431591">Afegeix</translation>
-<translation id="7793553086574152071">Perquè la propera vegada puguis pagar més ràpidament, desa la targeta al teu compte de Google.</translation>
+<translation id="7793553086574152071">Perquè la propera vegada puguis pagar més ràpidament, desa la targeta al compte de Google.</translation>
<translation id="7793809570500803535">És possible que la pàgina web de <ph name="SITE" /> estigui temporalment inactiva o que s'hagi desplaçat permanentment a una adreça web nova.</translation>
<translation id="7800304661137206267">La connexió està encriptada mitjançant <ph name="CIPHER" />, amb <ph name="MAC" /> per a l'autenticació de missatges i amb <ph name="KX" /> com a mecanisme d'intercanvi clau.</translation>
<translation id="7802523362929240268">El lloc web és legítim</translation>
@@ -900,6 +935,7 @@
<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="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="7862185352068345852">Vols sortir del lloc web?</translation>
<translation id="7878176543348854470">S'accepten targetes de dèbit i de prepagament.</translation>
<translation id="7878562273885520351">La teva contrasenya pot estar en perill</translation>
<translation id="7887683347370398519">Comproveu el CVC i torneu-ho a provar</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Utilitza l'opció predeterminada global (Pregunta)</translation>
<translation id="8042918947222776840">Tria un mètode de recollida</translation>
<translation id="8057711352706143257"><ph name="SOFTWARE_NAME" /> no s'ha configurat correctament. Normalment el problema se soluciona desinstal·lant <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Vols tornar a carregar el lloc web?</translation>
<translation id="8088680233425245692">No s'ha pogut consultar l'article.</translation>
<translation id="8091372947890762290">L'activació està pendent al servidor</translation>
<translation id="8094917007353911263">És possible que la xarxa que esteu fent servir requereixi que visiteu <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<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>
<translation id="8205463626947051446">El lloc web acostuma a mostrar anuncis intrusius</translation>
+<translation id="8211406090763984747">La connexió és segura</translation>
<translation id="8218327578424803826">Ubicació assignada:</translation>
<translation id="8225771182978767009">La persona que ha configurat l'ordinador ha bloquejat aquest lloc.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Mostra totes les contrasenyes desades</translation>
<translation id="8261506727792406068">Suprimeix</translation>
<translation id="8267698848189296333">S'està iniciant la sessió com a <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Inicia la sessió</translation>
<translation id="8288807391153049143">Mostra el certificat</translation>
<translation id="8289355894181816810">Si no esteu segur de què significa això, contacteu amb l'administrador de la xarxa.</translation>
<translation id="8293206222192510085">Afegeix una adreça d'interès</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Targetes de crèdit i de prepagament acceptades</translation>
<translation id="8759274551635299824">Aquesta targeta ha caducat</translation>
<translation id="8761567432415473239">Recentment, amb Navegació segura de Google s'han <ph name="BEGIN_LINK" />detectat programes perjudicials<ph name="END_LINK" /> al lloc <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Dispositiu USB</translation>
<translation id="8790007591277257123">&amp;Refés la supressió</translation>
<translation id="8800988563907321413">Els suggeriments més propers es mostren aquí</translation>
<translation id="8820817407110198400">Adreces d'interès</translation>
@@ -1042,7 +1082,7 @@
<translation id="9103872766612412690"><ph name="SITE" /> utilitza normalment l'encriptació per protegir la vostra informació. En aquesta ocasió, quan Chromium ha provat de connectar-se a <ph name="SITE" />, el lloc web ha enviat credencials poc comunes i incorrectes. Pot ser que un atacant estigui provant de fer-se passar per <ph name="SITE" /> o que una pantalla d'inici de sessió a la xarxa Wi-Fi hagi interromput la connexió. En qualsevol cas, la vostra informació continua estant segura, perquè Chromium ha aturat la connexió abans no s'intercanviés cap dada.</translation>
<translation id="9106062320799175032">Afegeix una adreça de facturació</translation>
<translation id="910908805481542201">Ajuda'm a solucionar-ho</translation>
-<translation id="9128870381267983090">Connecteu-vos a la xarxa</translation>
+<translation id="9128870381267983090">Connecta't a la xarxa</translation>
<translation id="9137013805542155359">Mostra l'original</translation>
<translation id="9137248913990643158">Obre Chrome i inicia-hi la sessió abans d'utilitzar aquesta aplicació.</translation>
<translation id="9148088599418889305">Tria un mètode d'enviament</translation>
diff --git a/chromium/components/strings/components_strings_cs.xtb b/chromium/components/strings/components_strings_cs.xtb
index d431f7f46a1..90c2a1140bf 100644
--- a/chromium/components/strings/components_strings_cs.xtb
+++ b/chromium/components/strings/components_strings_cs.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">Tisk...</translation>
<translation id="1181037720776840403">Odebrat</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Automaticky Googlu hlásit<ph name="END_WHITEPAPER_LINK" /> podrobnosti o možných bezpečnostních incidentech. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Platba nebyla dokončena</translation>
<translation id="1201402288615127009">Další</translation>
<translation id="1201895884277373915">Více z tohoto webu</translation>
<translation id="1206967143813997005">Chybný počáteční podpis</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Zpráva o selhání pořízená <ph name="CRASH_TIME" /> (dosud nenahrána nebo ignorována)</translation>
<translation id="1270502636509132238">Způsob vyzvednutí</translation>
<translation id="1285320974508926690">Tento web nikdy nepřekládat</translation>
+<translation id="1294154142200295408">Varianty pro příkazový řádek</translation>
<translation id="129553762522093515">Nedávno zavřené</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Zkuste vymazat soubory cookie<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Vaše aktivita <ph name="BEGIN_EMPHASIS" />může být nadále viditelná<ph name="END_EMPHASIS" /> pro následující subjekty:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Přijímané kreditní a debetní karty</translation>
<translation id="1519264250979466059">Datum sestavení</translation>
<translation id="1527263332363067270">Čeká se na připojení…</translation>
+<translation id="1532118530259321453">Tato stránka říká</translation>
<translation id="153384715582417236">To je prozatím vše</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>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Zkontrolovat proxy server a firewall<ph name="END_LINK" /></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="2065985942032347596">Vyžaduje se ověření</translation>
<translation id="2079545284768500474" />
<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="2091887806945687916">Zvuk</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Zrušit platbu</translation>
<translation id="2147827593068025794">Synchronizace na pozadí</translation>
<translation id="2148613324460538318">Přidat kartu</translation>
-<translation id="2149973817440762519">Upravit záložku</translation>
<translation id="2154054054215849342">Synchronizace není pro vaši doménu k dispozici</translation>
<translation id="2154484045852737596">Úprava karty</translation>
<translation id="2166049586286450108">Úplný přístup administrátora</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Vybrat adresu vyzvednutí</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Odstranit vybrané položky</translation>
-<translation id="2744590937989388266">Ze stránky vložené na této stránce</translation>
<translation id="277133753123645258">Způsob dopravy</translation>
<translation id="277499241957683684">Chybějící záznam zařízení</translation>
<translation id="2784949926578158345">Připojení bylo resetováno.</translation>
<translation id="2788784517760473862">Přijímané kreditní karty</translation>
<translation id="2794233252405721443">Web je blokován</translation>
-<translation id="2795286477369100655">Chcete tento web opustit?</translation>
<translation id="2799020568854403057">Web, na který se chystáte přejít, obsahuje škodlivé aplikace</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="2824775600643448204">Adresní a vyhledávací řádek</translation>
@@ -279,13 +276,12 @@
<translation id="2985398929374701810">Zadejte platnou adresu</translation>
<translation id="2986368408720340940">Tento způsob vyzvednutí není k dispozici. Zkuste použít jiný způsob.</translation>
<translation id="2991174974383378012">Sdílení s weby</translation>
-<translation id="2991571918955627853">Web <ph name="SITE" /> nyní nemůžete navštívit, protože používá zabezpečení HSTS. Síťové chyby a útoky jsou obvykle dočasné, tato stránka pravděpodobně později bude fungovat.</translation>
+<translation id="2991571918955627853">Web <ph name="SITE" /> teď nemůžete navštívit, protože používá zabezpečení HSTS. Síťové chyby a útoky jsou obvykle dočasné, tato stránka pravděpodobně později bude fungovat.</translation>
<translation id="3005723025932146533">Zobrazit uloženou kopii</translation>
<translation id="3008447029300691911">Zadejte kód CVC karty <ph name="CREDIT_CARD" />. Po ověření budou údaje o kartě sdíleny s tímto webem.</translation>
<translation id="3010559122411665027">Položka seznamu „<ph name="ENTRY_INDEX" />“: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automaticky blokováno</translation>
<translation id="3024663005179499861">Chybný typ zásady</translation>
-<translation id="3032412215588512954">Chcete tento web načíst znovu?</translation>
<translation id="3037605927509011580">Aj, chyba!</translation>
<translation id="3039538478787849737">Uložit kartu do Googlu?</translation>
<translation id="3041612393474885105">Informace o certifikátu</translation>
@@ -307,6 +303,7 @@
<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>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> na serveru <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Zrušit platbu</translation>
<translation id="3207960819495026254">Přidáno do záložek</translation>
<translation id="3209375525920864198">Zadejte prosím platný název relace.</translation>
@@ -364,11 +361,57 @@
<translation id="3556433843310711081">Správce vám jej může odblokovat.</translation>
<translation id="3566021033012934673">Vaše připojení není soukromé</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Vložená stránka na webu <ph name="SITE" /> říká</translation>
<translation id="358285529439630156">Obchodník přijímá kreditní a předplacené karty.</translation>
<translation id="3582930987043644930">Přidejte jméno</translation>
<translation id="3583757800736429874">&amp;Opakovat přesunutí</translation>
<translation id="3586931643579894722">Skrýt podrobnosti</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Oprava chyb připojení&lt;/h1&gt;
+ &lt;p&gt;Pokud se vám při pokusu o návštěvu webu zobrazí chybová zpráva, vyzkoušejte tato řešení.&lt;/p&gt;
+ &lt;h2&gt;Oprava většiny chyb připojení&lt;/h2&gt;
+ &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;
+ &lt;ol&gt;
+ &lt;li&gt;Zkontrolujte, zda ve webové adrese nemáte překlepy.&lt;/li&gt;
+ &lt;li&gt;Zkontrolujte, zda připojení k internetu normálně funguje.&lt;/li&gt;
+ &lt;li&gt;Kontaktujte vlastníka webu.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Nápověda ke konkrétní chybové zprávě&lt;/h2&gt;
+ &lt;h3&gt;Vaše připojení není soukromé, NET::ERR_CERT_AUTHORITY_INVALID, ERR_CERT_COMMON_NAME_INVALID nebo NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM nebo Chyba certifikátu SSL&lt;/h3&gt;
+ &lt;h4&gt;Krok 1: Přihlaste se do portálu&lt;/h4&gt;
+ &lt;p&gt;Wi-Fi sítě v místech, jako jsou kavárny nebo letiště, vyžadují přihlášení. Chcete-li zobrazit přihlašovací stránku, přejděte na stránku, která používá schéma &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Přejděte na libovolný web začínající schématem &lt;code&gt;http://&lt;/code&gt;, například &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Na přihlašovací stránce, která se otevře, se přihlaste, abyste mohli používat internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Krok 2: Otevřete stránku v anonymním režimu (pouze na počítači)&lt;/h4&gt;
+ &lt;p&gt;Stránku, na kterou chcete přejít, otevřete v anonymním okně.&lt;/p&gt;
+ &lt;p&gt;Pokud se otevře, znamená to, že chybu způsobuje některé rozšíření Chromu. Odstraníte ji vypnutím příslušného rozšíření.&lt;/p&gt;
+ &lt;h4&gt;Krok 3: Aktualizujte operační systém&lt;/h4&gt;
+ &lt;p&gt;Zkontrolujte, zda je vaše zařízení aktuální.&lt;/p&gt;
+ &lt;h4&gt;Krok 4: Dočasně vypněte antivirus&lt;/h4&gt;
+ &lt;p&gt;Tato chyba se zobrazuje, pokud máte antivirový software s funkcí ochrany HTTPS nebo kontroly HTTPS. Antivirový software v takovém případě Chromu znemožňuje poskytovat zabezpečení.&lt;/p&gt;
+ &lt;p&gt;Problém vyřešíte tím, že antivirový software vypnete. Pokud po vypnutí antiviru bude stránka fungovat, vypněte jej při každé návštěvě zabezpečeného webu.&lt;/p&gt;
+ &lt;p&gt;Až budete hotovi, nezapomeňte antivirový program zase zapnout.&lt;/p&gt;
+ &lt;h4&gt;Krok 5: Požádejte o další pomoc&lt;/h4&gt;
+ &lt;p&gt;Pokud se chyba zobrazuje i nadále, kontaktujte vlastníka webu.&lt;/p&gt;
+ &lt;h3&gt;Připojit k síti&lt;/h3&gt;
+ &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;
+ &lt;h3&gt;Vaše hodiny se zpožďují, Vaše hodiny jdou napřed nebo NET::ERR_CERT_DATE_INVALID&lt;/h3&gt;
+ &lt;p&gt;Tato chyba se zobrazuje, pokud máte v počítači nebo mobilním zařízení nastaveno nepřesné datum a čas.&lt;/p&gt;
+ &lt;p&gt;Chcete-li tuto chybu odstranit, otevřete v zařízení hodiny. Zkontrolujte, zda jsou datum a čas nastaveny správně.&lt;/p&gt;
+ &lt;h3&gt;Software na počítači Chromu brání v bezpečném připojení k webu (pouze počítače se systémem Windows)&lt;/h3&gt;
+ &lt;p&gt;Tato chyba se zobrazuje, pokud v počítači se systémem Windows máte software Superfish.&lt;/p&gt;
+ &lt;p&gt;Abyste se mohli dostat na web, podle těchto pokynů tento software dočasně zakažte. Budete potřebovat administrátorská práva.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Klikněte na &lt;strong&gt;Start&lt;/strong&gt;, vyhledejte položku &lt;strong&gt;Zobrazit místní služby&lt;/strong&gt; a vyberte ji.
+ &lt;li&gt;Vyberte &lt;strong&gt;VisualDiscovery&lt;/strong&gt;.
+ &lt;li&gt;V poli &lt;strong&gt;Typ spouštění&lt;/strong&gt; vyberte &lt;strong&gt;Zakázáno&lt;/strong&gt;.
+ &lt;li&gt;Pod položkou &lt;strong&gt;Stav služby&lt;/strong&gt; klikněte na &lt;strong&gt;Zastavit&lt;/strong&gt;.
+ &lt;li&gt;Klikněte na &lt;strong&gt;Použít&lt;/strong&gt; a poté na &lt;strong&gt;OK&lt;/strong&gt;.
+ &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="3615877443314183785">Zadejte platné datum vypršení platnosti</translation>
<translation id="36224234498066874">Smazat údaje o prohlížení...</translation>
<translation id="362276910939193118">Zobrazit celou historii</translation>
@@ -392,7 +435,7 @@
<translation id="372429172604983730">Tuto chybu mohou způsobovat aplikace, jako jsou antivirové programy, firewally a software na filtrování nebo zprostředkování webového provozu.</translation>
<translation id="3736520371357197498">Pokud bezpečnostní rizika chápete, můžete <ph name="BEGIN_LINK" />tento nespolehlivý web navštívit<ph name="END_LINK" /> ještě před tím, než budou nebezpečné programy odstraněny.</translation>
<translation id="3739623965217189342">Zkopírovaný odkaz</translation>
-<translation id="3744899669254331632">Web <ph name="SITE" /> nyní nelze navštívit, protože tento web odeslal nesprávné identifikační údaje, které prohlížeč Chromium nedokáže zpracovat. Síťové chyby a útoky jsou obvykle dočasné, tato stránka pravděpodobně později bude fungovat.</translation>
+<translation id="3744899669254331632">Web <ph name="SITE" /> teď nelze navštívit, protože tento web odeslal nesprávné identifikační údaje, které prohlížeč Chromium nedokáže zpracovat. Síťové chyby a útoky jsou obvykle dočasné, tato stránka pravděpodobně později bude fungovat.</translation>
<translation id="3748148204939282805">Útočníci na webu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> vás mohou podvodem přimět k nebezpečnému chování, jako je instalace softwaru nebo vyzrazení osobních údajů (například hesel, telefonních čísel nebo platebních karet). <ph name="BEGIN_LEARN_MORE_LINK" />Další informace<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Z důvodu chyby serveru se překlad nezdařil.</translation>
<translation id="3759461132968374835">Nemáte žádná nedávno hlášená selhání. Selhání, ke kterým došlo, když byla služba hlášení o selháních vypnutá, se zde nezobrazují.</translation>
@@ -400,7 +443,6 @@
<translation id="3778403066972421603">Chcete tuto kartu uložit do svého účtu Google a do tohoto zařízení?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Platnost do: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Z webu <ph name="SITE" /></translation>
<translation id="382518646247711829">Pokud používáte proxy server...</translation>
<translation id="3828924085048779000">Prázdná heslová fráze není povolena.</translation>
<translation id="385051799172605136">Zpět</translation>
@@ -414,6 +456,7 @@
<translation id="3945915738023014686">ID nahrané zprávy o selhání <ph name="CRASH_ID" /> (místní ID selhání: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Server nedokázal prokázat, že patří doméně <ph name="DOMAIN" />. V jeho bezpečnostním certifikátu nejsou uvedeny alternativní názvy subjektu. Může to být způsobeno nesprávnou konfigurací nebo tím, že vaše připojení zachytává útočník.</translation>
<translation id="3949601375789751990">Zde se zobrazuje vaše historie prohlížení</translation>
+<translation id="3950820424414687140">Přihlaste se</translation>
<translation id="3963721102035795474">Režim čtečky</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Žádné}=1{Z 1 webu }few{Z # webů }many{Z # webu }other{Z # webů }}</translation>
<translation id="397105322502079400">Probíhá výpočet…</translation>
@@ -430,6 +473,7 @@
<translation id="4103249731201008433">Sériové číslo zařízení je neplatné</translation>
<translation id="410351446219883937">Automatické přehrávání</translation>
<translation id="4103763322291513355">Na stránce &lt;strong&gt;chrome://policy&lt;/strong&gt; naleznete seznam zakázaných adres URL a další zásady vynucené vaším správcem systému.</translation>
+<translation id="4110652170750985508">Kontrola platby</translation>
<translation id="4116663294526079822">Povolit vždy na tomto webu</translation>
<translation id="4117700440116928470">Rozsah zásady není podporován.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 další}few{# další}many{# další}other{# dalších}}</translation>
@@ -456,7 +500,6 @@
<translation id="4269787794583293679">(Žádné uživatelské jméno)</translation>
<translation id="4275830172053184480">Restartovat zařízení</translation>
<translation id="4280429058323657511">s platností do <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Přihlásit se</translation>
<translation id="4312866146174492540">Blokovat (výchozí)</translation>
<translation id="4325863107915753736">Článek nebyl nalezen</translation>
<translation id="4326324639298822553">Zkontrolujte datum vypršení platnosti a zkuste to znovu.</translation>
@@ -478,14 +521,12 @@
<translation id="4515275063822566619">Karty a adresy pocházejí z Chromu a z vašeho účtu Google (<ph name="ACCOUNT_EMAIL" />). Můžete je spravovat v <ph name="BEGIN_LINK" />Nastavení<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Podrobnosti</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Z vložené stránky na webu <ph name="SITE" /></translation>
<translation id="4558551763791394412">Zkuste zakázat rozšíření.</translation>
<translation id="457875822857220463">Doručení</translation>
<translation id="4582800630050655161">Mohli byste ztratit přístup k účtu Google nebo by mohlo dojít k odcizení vaší identity. Chromium doporučuje okamžitě změnit heslo.</translation>
<translation id="4587425331216688090">Odstranit adresu z Chromu?</translation>
<translation id="4592951414987517459">Vaše připojení k doméně <ph name="DOMAIN" /> je šifrováno za použití moderní šifrovací sady.</translation>
<translation id="4594403342090139922">&amp;Vrátit smazání zpět</translation>
-<translation id="4611292653554630842">Přihlásit se</translation>
<translation id="4619615317237390068">Karty z ostatních zařízení</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Server nedokázal prokázat, že patří doméně <ph name="DOMAIN" />, protože jeho bezpečnostní certifikát obsahuje chyby. Může to být způsobeno nesprávnou konfigurací nebo tím, že vaše připojení zachytává útočník.</translation>
@@ -495,11 +536,9 @@
<translation id="4708268264240856090">Připojení bylo přerušeno</translation>
<translation id="471880041731876836">K návštěvě tohoto webu nemáte povolení</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Spustit Diagnostiku sítě systému Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Vaše platba</translation>
<translation id="4726672564094551039">Znovu načíst zásady</translation>
<translation id="4728558894243024398">Platforma</translation>
<translation id="4736825316280949806">Restartujte Chromium</translation>
-<translation id="4737498291095696011">Z této stránky</translation>
<translation id="4744603770635761495">Spustitelná cesta</translation>
<translation id="4749685221585524849">Naposledy použito <ph name="LAST_USED_MONTH" /></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>
@@ -511,23 +550,23 @@
<translation id="4792143361752574037">Při pokusu o přístup k souborům došlo k chybě. Ukládání na disk je v současné době zakázáno. Chcete-li to zkusit znovu, obnovte stránku.</translation>
<translation id="4800132727771399293">Zkontrolujte datum vypršení platnosti a kód CVC a zkuste to znovu.</translation>
<translation id="4803924862070940586"><ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="4807049035289105102">Web <ph name="SITE" /> nyní nemůžete navštívit, protože webové stránky odeslaly zakódované identifikační údaje, které Chrome nedokáže zpracovat. Síťové chyby a útoky jsou obvykle dočasné, tato stránka pravděpodobně později bude fungovat.</translation>
+<translation id="4807049035289105102">Web <ph name="SITE" /> teď nemůžete navštívit, protože webové stránky odeslaly zakódované identifikační údaje, které Chrome nedokáže zpracovat. Síťové chyby a útoky jsou obvykle dočasné, tato stránka pravděpodobně později bude fungovat.</translation>
<translation id="4813512666221746211">Chyba sítě</translation>
<translation id="4816492930507672669">Přizpůsobit na stránku</translation>
<translation id="483020001682031208">Nejsou k dispozici žádné stránky fyzického webu, které by bylo možné zobrazit</translation>
<translation id="4850886885716139402">Zobrazit</translation>
<translation id="4854362297993841467">Tento způsob doručení není k dispozici. Zkuste použít jiný způsob.</translation>
<translation id="4858792381671956233">Požádal(a) jsi rodiče o povolení návštěvy tohoto webu.</translation>
-<translation id="4871132632506079383">Z vložené stránky na webu <ph name="SITE" /></translation>
<translation id="4880827082731008257">Hledat v historii</translation>
+<translation id="4881695831933465202">Otevřít</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Je vyžadováno ověření</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{a 1 další webová stránka}few{a # další webové stránky}many{a # další webové stránky}other{a # dalších webových stránek}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Zadejte kód CVC karty <ph name="CREDIT_CARD" />. Po ověření budou údaje o kartě z vašeho účtu Google Payments poskytnuty tomuto webu.</translation>
<translation id="4923417429809017348">Tato stránka byla přeložena z neznámého jazyka do jazyka <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Platba</translation>
<translation id="4926049483395192435">Musí být uvedeno</translation>
+<translation id="4926159001844873046">Web <ph name="SITE" /> říká</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Akce</translation>
<translation id="4958444002117714549">Rozbalit seznam</translation>
@@ -536,7 +575,6 @@
<translation id="5002932099480077015">Pokud je tato možnost aktivována, Chrome do zařízení uloží kopii karty za účelem rychlejšího vyplňování formulářů.</translation>
<translation id="5018422839182700155">Tuto stránku nelze otevřít</translation>
<translation id="5019198164206649151">Záložní úložiště je ve špatném stavu</translation>
-<translation id="5020990877659450221">Z této stránky</translation>
<translation id="5023310440958281426">Zkontrolujte zásady svého správce</translation>
<translation id="5029568752722684782">Vymazat kopii</translation>
<translation id="503069730517007720">Je vyžadován kořenový certifikát pro software <ph name="SOFTWARE_NAME" />, ale není nainstalován. Při řešení tohoto problému by si měl administrátor IT prostudovat pokyny ke konfiguraci softwaru <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -562,12 +600,12 @@
<translation id="5172758083709347301">Počítač</translation>
<translation id="5179510805599951267">Nejedná se o jazyk <ph name="ORIGINAL_LANGUAGE" />? Nahlaste tuto chybu.</translation>
<translation id="5190835502935405962">Lišta záložek</translation>
+<translation id="5201306358585911203">Stránka vložená na této stránce říká</translation>
<translation id="5205222826937269299">Je nutné zadat jméno</translation>
<translation id="5222812217790122047">Je nutné zadat e-mail</translation>
<translation id="522700295135997067">Tento web vám možná právě odcizil heslo</translation>
<translation id="5230733896359313003">Dodací adresa</translation>
<translation id="5251803541071282808">Cloud</translation>
-<translation id="5277279256032773186">Používáte Chrome v práci? Firmy mohou spravovat nastavení prohlížeče Chrome pro své zaměstnance. Další informace</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Abyste se mohli dostat na web, podle těchto pokynů software dočasně zakažte. Budete potřebovat administrátorská práva.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -588,7 +626,7 @@
<translation id="5324080437450482387">Vybrat kontaktní údaje</translation>
<translation id="5327248766486351172">Název</translation>
<translation id="5332219387342487447">Způsob dopravy</translation>
-<translation id="5355557959165512791">Web <ph name="SITE" /> nyní 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="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="5386426401304769735">Řetězec certifikátů tohoto webu obsahuje certifikát podepsaný algoritmem SHA-1.</translation>
<translation id="5402410679244714488">Platnost do: <ph name="EXPIRATION_DATE_ABBR" />, naposledy použito více než před rokem</translation>
@@ -629,7 +667,6 @@ Kontaktujte administrátora systému.</translation>
<translation id="5610142619324316209">Zkontrolovat připojení</translation>
<translation id="5610807607761827392">Karty a adresy můžete spravovat v <ph name="BEGIN_LINK" />Nastavení<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Web <ph name="HOST_NAME" /> vás přesměroval příliš mnohokrát.</translation>
-<translation id="5622887735448669177">Chcete tento web opustit?</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="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>
@@ -652,7 +689,6 @@ Kontaktujte administrátora systému.</translation>
<translation id="5786044859038896871">Chcete vyplnit informace o kartě?</translation>
<translation id="5803412860119678065">Chcete vyplnit informace o kartě <ph name="CARD_DETAIL" />?</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="5810928923025889964">Ze stránky vložené na této stránce</translation>
<translation id="5813119285467412249">&amp;Opakovat přidání</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>
<translation id="5866257070973731571">Přidání telefonního čísla</translation>
@@ -680,7 +716,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="6040143037577758943">Zavřít</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="6051221802930200923">Web <ph name="SITE" /> nyní 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="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="6080696365213338172">Získali jste přístup k obsahu pomocí certifikátu poskytnutého správcem. Údaje poskytovaná doméně <ph name="DOMAIN" /> bude správce moci zachytit.</translation>
<translation id="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="6144381551823904650">{COUNT,plural, =0{Žádné}=1{1 heslo (synchronizováno)}few{# hesla (synchronizováno)}many{# hesla (synchronizováno)}other{# hesel (synchronizováno)}}</translation>
@@ -725,21 +761,19 @@ Kontaktujte administrátora systému.</translation>
<translation id="6446608382365791566">Přidání dalších informací</translation>
<translation id="6447842834002726250">Soubory cookie</translation>
<translation id="6451458296329894277">Potvrdit nové odeslání formuláře</translation>
-<translation id="6456339708790392414">Vaše platba</translation>
<translation id="647261751007945333">Zásady zařízení</translation>
<translation id="6477321094435799029">Chrome na této stránce zjistil neobvyklý kód a z důvodu ochrany vašich osobních údajů (například hesel, telefonních čísel a platebních karet) ji zablokoval.</translation>
<translation id="6489534406876378309">Začít nahrávat zprávy o selhání</translation>
<translation id="6507833130742554667">Obchodník přijímá kreditní a debetní karty.</translation>
<translation id="6508722015517270189">Restartujte Chrome</translation>
-<translation id="6521373090216409766">Chcete tento web načíst znovu?</translation>
<translation id="6529602333819889595">&amp;Opakovat smazání</translation>
<translation id="6534179046333460208">Návrhy fyzického webu</translation>
<translation id="6550675742724504774">Možnosti</translation>
-<translation id="6556239504065605927">Zabezpečené připojení</translation>
<translation id="6556915248009097796">Platnost do <ph name="EXPIRATION_DATE_ABBR" />, naposledy použito <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Správce vám přístup na web dosud neschválil.</translation>
<translation id="6569060085658103619">Prohlížíte si stránku rozšíření</translation>
<translation id="6596325263575161958">Možnosti šifrování</translation>
+<translation id="6604181099783169992">Senzory pohybu nebo světla</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>
@@ -811,6 +845,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="7275334191706090484">Spravované záložky</translation>
<translation id="7298195798382681320">Doporučeno</translation>
<translation id="7309308571273880165">Zpráva o selhání pořízená <ph name="CRASH_TIME" /> (o nahrání požádal uživatel, dosud nenahrána)</translation>
+<translation id="7320336641823683070">Pomoc s připojením</translation>
<translation id="7334320624316649418">&amp;Opakovat změnu uspořádání</translation>
<translation id="733923710415886693">Certifikát serveru nebyl zveřejněn prostřednictvím projektu Certificate Transparency.</translation>
<translation id="7353601530677266744">Příkazový řádek</translation>
@@ -895,6 +930,7 @@ 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="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="7862185352068345852">Opustit web?</translation>
<translation id="7878176543348854470">Obchodník přijímá debetní a předplacené karty.</translation>
<translation id="7878562273885520351">Heslo může být prolomeno</translation>
<translation id="7887683347370398519">Zkontrolujte kód CVC a zkuste to znovu</translation>
@@ -917,6 +953,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="8041940743680923270">Použít výchozí globální hodnotu (Dotázat se)</translation>
<translation id="8042918947222776840">Vybrat způsob vyzvednutí</translation>
<translation id="8057711352706143257">Software <ph name="SOFTWARE_NAME" /> není nakonfigurován správně. Tento problém lze obvykle vyřešit odinstalováním softwaru <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Načíst web znovu?</translation>
<translation id="8088680233425245692">Zobrazení článku se nezdařilo.</translation>
<translation id="8091372947890762290">Čeká se na aktivaci na serveru</translation>
<translation id="8094917007353911263">Síť, kterou používáte, může vyžadovat, abyste navštívili stránku <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -932,6 +969,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="8201077131113104583">Neplatná adresa URL aktualizace rozšíření s ID <ph name="EXTENSION_ID" />.</translation>
<translation id="8202097416529803614">Shrnutí objednávky</translation>
<translation id="8205463626947051446">Tento web často zobrazuje rušivé reklamy</translation>
+<translation id="8211406090763984747">Spojení je bezpečné</translation>
<translation id="8218327578424803826">Přiřazené místo:</translation>
<translation id="8225771182978767009">Uživatel, který tento počítač nastavoval, se rozhodl tento web blokovat.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -943,6 +981,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="825929999321470778">Zobrazit všechna uložená hesla</translation>
<translation id="8261506727792406068">Smazat</translation>
<translation id="8267698848189296333">Přihlašování pomocí účtu <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Přihlásit se</translation>
<translation id="8288807391153049143">Zobrazit certifikát</translation>
<translation id="8289355894181816810">Pokud nevíte, co dělat, obraťte se na svého správce sítě.</translation>
<translation id="8293206222192510085">Přidat záložku</translation>
@@ -994,6 +1033,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="874846938927089722">Přijímané kreditní a předplacené karty</translation>
<translation id="8759274551635299824">Platnost této karty vypršela</translation>
<translation id="8761567432415473239">Bezpečné prohlížení Google na webu <ph name="SITE" /> nedávno <ph name="BEGIN_LINK" />nalezlo škodlivé programy<ph name="END_LINK" />.</translation>
+<translation id="8763927697961133303">Zařízení USB</translation>
<translation id="8790007591277257123">&amp;Opakovat smazání</translation>
<translation id="8800988563907321413">Zde se zobrazí návrhy funkce Nablízku</translation>
<translation id="8820817407110198400">Záložky</translation>
diff --git a/chromium/components/strings/components_strings_da.xtb b/chromium/components/strings/components_strings_da.xtb
index 854a7901466..ff7f6a06bb8 100644
--- a/chromium/components/strings/components_strings_da.xtb
+++ b/chromium/components/strings/components_strings_da.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Udskriv...</translation>
<translation id="1181037720776840403">Fjern</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Rapportér automatisk<ph name="END_WHITEPAPER_LINK" /> oplysninger om mulige sikkerhedsproblemer til Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Betalingen blev ikke gennemført</translation>
<translation id="1201402288615127009">Næste</translation>
<translation id="1201895884277373915">Mere fra dette website</translation>
<translation id="1206967143813997005">Ugyldig første signatur</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Der blev registreret en nedbrudsrapport <ph name="CRASH_TIME" /> (endnu ikke uploadet eller ignoreret)</translation>
<translation id="1270502636509132238">Afhentningsmetode</translation>
<translation id="1285320974508926690">Oversæt aldrig dette website</translation>
+<translation id="1294154142200295408">Variationer i kommandolinjer</translation>
<translation id="129553762522093515">Senest lukkede</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Prøv at rydde dine cookies<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Din aktivitet <ph name="BEGIN_EMPHASIS" />er muligvis stadig synlig<ph name="END_EMPHASIS" /> for:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Accepterede betalingskort</translation>
<translation id="1519264250979466059">Versionsdato</translation>
<translation id="1527263332363067270">Venter på forbindelse…</translation>
+<translation id="1532118530259321453">Denne side siger</translation>
<translation id="153384715582417236">Det var det hele indtil videre.</translation>
<translation id="154408704832528245">Vælg leveringsadresse</translation>
<translation id="1549470594296187301">JavaScript skal være aktiveret, før du kan bruge denne funktion.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Kontrollere din proxy og din firewall<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Postnummer</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 forslag}one{# forslag}other{# forslag}}</translation>
-<translation id="2065985942032347596">Godkendelse påkrævet</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="2091887806945687916">Lyd</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Annuller betaling</translation>
<translation id="2147827593068025794">Synkronisering i baggrunden</translation>
<translation id="2148613324460538318">Tilføj kort</translation>
-<translation id="2149973817440762519">Rediger bogmærke</translation>
<translation id="2154054054215849342">Synkronisering er ikke tilgængelig for dit domæne</translation>
<translation id="2154484045852737596">Rediger kort</translation>
<translation id="2166049586286450108">Fuld administratoradgang</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Vælg afhentningsadresse</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Fjern valgte elementer</translation>
-<translation id="2744590937989388266">Fra en integreret side på denne side</translation>
<translation id="277133753123645258">Forsendelsesmetode</translation>
<translation id="277499241957683684">Manglende enhedsregistrering</translation>
<translation id="2784949926578158345">Forbindelsen blev nulstillet.</translation>
<translation id="2788784517760473862">Accepterede kreditkort</translation>
<translation id="2794233252405721443">Websitet er blokeret</translation>
-<translation id="2795286477369100655">Vil du forlade dette website?</translation>
<translation id="2799020568854403057">Det website, du er på vej til, indeholder skadelige apps</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="2824775600643448204">Adresse og søgelinje</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Angiv posten "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automatisk blokering</translation>
<translation id="3024663005179499861">Forkert politiktype</translation>
-<translation id="3032412215588512954">Vil du genindlæse denne side?</translation>
<translation id="3037605927509011580">Øv, surt!</translation>
<translation id="3039538478787849737">Vil du gemme kortet på din Google-konto?</translation>
<translation id="3041612393474885105">Certifikatoplysninger</translation>
@@ -310,6 +306,7 @@
for at sikre, at proxyserveren fungerer. Hvis du ikke mener,
at du skal bruge en proxyserver, skal du:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> på <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Annuller betaling</translation>
<translation id="3207960819495026254">Bogmærket</translation>
<translation id="3209375525920864198">Angiv et gyldigt sessionsnavn.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Din administrator kan fjerne blokeringen for dig</translation>
<translation id="3566021033012934673">Din forbindelse er ikke privat</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">En integreret side på <ph name="SITE" /> siger</translation>
<translation id="358285529439630156">Kreditkort og forudbetalte kort accepteres.</translation>
<translation id="3582930987043644930">Tilføj navn</translation>
<translation id="3583757800736429874">&amp;Annuller fortryd flytning</translation>
<translation id="3586931643579894722">Skjul oplysninger</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Ret forbindelsesfejl&lt;/h1&gt;
+ &lt;p&gt;Hvis der vises en fejlmeddelelse, når du forsøger at besøge et website, kan du prøve disse løsninger.&lt;/p&gt;
+ &lt;h2&gt;Ret de fleste forbindelsesfejl&lt;/h2&gt;
+ &lt;p&gt;Hvis du forsøger at gå til et website, som ikke åbnes, kan du starte med at prøve disse fejlfindingstrin:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Tjek, om der er tastefejl i webadressen.&lt;/li&gt;
+ &lt;li&gt;Tjek, at din internetforbindelse fungerer normalt.&lt;/li&gt;
+ &lt;li&gt;Kontakt ejeren af websitet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Få hjælp til en bestemt fejlmeddelelse&lt;/h2&gt;
+ &lt;h3&gt;"Din forbindelse er ikke privat" eller "NET::ERR_CERT_AUTHORITY_INVALID" eller "ERR_CERT_COMMON_NAME_INVALID" eller "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" eller "SSL-certifikatfejl"&lt;/h3&gt;
+ &lt;h4&gt;Trin 1: Log ind på portalen&lt;/h4&gt;
+ &lt;p&gt;Wi-Fi-netværk på steder som f.eks. caféer eller lufthavne kræver login. Du kan se loginsiden ved at gå til en side, der anvender&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Gå til et website, der starter med &lt;code&gt;http://&lt;/code&gt;, f.eks. &lt;a&gt; href="http://eksempel.dk" target="_blank"&gt;http://eksempel.dk&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Log ind på den loginside, der åbnes, for at få adgang til internettet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Trin 2: Åbn siden i inkognitotilstand (kun på computere)&lt;/h4&gt;
+ &lt;p&gt;Åbn den side, du vil besøge, i et inkognitovindue.&lt;/p&gt;
+ &lt;p&gt;Hvis siden åbnes, skyldes problemet, at en Chrome-udvidelse ikke fungerer korrekt. Ret fejlen ved at deaktivere udvidelsen.&lt;/p&gt;
+ &lt;h4&gt;Trin 3: Opdater dit operativsystem&lt;/h4&gt;
+ &lt;p&gt;Tjek, at din enhed er opdateret.&lt;/p&gt;
+ &lt;h4&gt;Trin 4: Deaktiver din antivirussoftware midlertidigt&lt;/h4&gt;
+ &lt;p&gt;Denne fejlmeddelelse vises, hvis du har installeret antivirussoftware, der leverer "HTTPS-beskyttelse" eller "HTTPS-scanning". Antivirussoftwaren forhindrer Chrome i at beskytte enheden.&lt;/p&gt;
+ &lt;p&gt;Løs problemet ved at deaktivere din antivirussoftware. Hvis siden fungerer, efter du har deaktiveret softwaren, skal du deaktivere denne software, når du bruger sikre websites.&lt;/p&gt;
+ &lt;p&gt;Husk at aktivere antivirusprogrammet igen, når du er færdig.&lt;/p&gt;
+ &lt;h4&gt;Trin 5: Få yderligere hjælp&lt;/h4&gt;
+ &lt;p&gt;Hvis fejlen stadig vises, bør du kontakte ejeren af websitet.&lt;/p&gt;
+ &lt;h3&gt;"Opret forbindelse til netværk"&lt;/h3&gt;
+ &lt;p&gt;Denne fejlmeddelelse vises, hvis du bruger en Wi-Fi-portal, hvor du skal logge ind, før du kan oprette forbindelse til internettet.&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;
+ &lt;h3&gt;"Dit ur er bagud" eller "Dit ur er foran" eller "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Denne fejlmeddelelse vises, hvis dato og tid på din computer eller mobilenhed er forkerte.&lt;/p&gt;
+ &lt;p&gt;Du kan rette fejlen ved at åbne uret på enheden. Sørg for, at dato og klokkeslæt er indstillet korrekt.&lt;/p&gt;
+ &lt;h3&gt;"Der er software på computeren, som forhindrer, at Chrome kan oprette en sikker forbindelse til nettet" (kun på Windows-computere)&lt;/h3&gt;
+ &lt;p&gt;Denne fejlmeddelelse vises, hvis du har installeret Superfish-software på din Windows-computer.&lt;/p&gt;
+ &lt;p&gt;Følg denne vejledning for at deaktivere softwaren midlertidigt, så du kan komme på nettet. Du skal have administratorrettigheder.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Klik på &lt;strong&gt;Start&lt;/strong&gt;, og søg efter og vælg &lt;strong&gt;"Vis lokale tjenester"&lt;/strong&gt;&lt;/li&gt;
+ &lt;li&gt;Vælg &lt;strong&gt;VisualDiscovery&lt;/strong&gt;&lt;/li&gt;
+ &lt;li&gt;Vælg &lt;strong&gt;Deaktiveret&lt;/strong&gt; under &lt;strong&gt;Starttype&lt;/strong&gt;&lt;/li&gt;
+ &lt;li&gt;Klik på &lt;strong&gt;Stop&lt;/strong&gt; under &lt;strong&gt;Tjenestestatus&lt;/strong&gt;&lt;/li&gt;
+ &lt;li&gt;Klik på &lt;strong&gt;Anvend&lt;/strong&gt; og derefter på &lt;strong&gt;OK&lt;/strong&gt;&lt;/li&gt;
+ &lt;li&gt;Gå til &lt;a&gt; href="https://support.google.com/chrome/answer/6098869"&gt;Hjælp til Chrome&lt;/a&gt; for at få flere oplysninger om, hvordan du permanent fjerner softwaren fra din computer&lt;/li&gt;
+ &lt;/ol&gt;</translation>
<translation id="3615877443314183785">Angiv en gyldig udløbsdato</translation>
<translation id="36224234498066874">Ryd browserdata...</translation>
<translation id="362276910939193118">Vis hele historikken</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Vil du gemme dette kort på din Google-konto og på denne enhed?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Udløber <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Fra <ph name="SITE" /></translation>
<translation id="382518646247711829">Hvis du bruger en proxyserver...</translation>
<translation id="3828924085048779000">Tomme adgangssætninger er ikke tilladt.</translation>
<translation id="385051799172605136">Tilbage</translation>
@@ -412,12 +454,13 @@
<translation id="3884278016824448484">Modstridende enheds-id</translation>
<translation id="3885155851504623709">Sogn</translation>
<translation id="3886446263141354045">Din anmodning om adgang til dette website er blevet sendt til <ph name="NAME" />.</translation>
-<translation id="3890664840433101773">Tilføj e-mail</translation>
+<translation id="3890664840433101773">Tilføj mail</translation>
<translation id="3901925938762663762">Kortet er udløbet</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
<translation id="3945915738023014686">Uploadet nedbruds-id <ph name="CRASH_ID" /> (lokalt nedbruds-id: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Denne server kunne ikke bevise, at den er <ph name="DOMAIN" />, da sikkerhedscertifikatet ikke angiver alternative navne på emner. Dette kan skyldes en fejlkonfiguration, eller at en hacker har opfanget din forbindelse.</translation>
<translation id="3949601375789751990">Din browserhistorik vises her</translation>
+<translation id="3950820424414687140">Log ind</translation>
<translation id="3963721102035795474">Læser-tilstand</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Ingen}=1{1 website }one{# website }other{# websites }}</translation>
<translation id="397105322502079400">Beregner...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Enhedens serienummer er ugyldigt</translation>
<translation id="410351446219883937">Autoplay</translation>
<translation id="4103763322291513355">Gå til &lt;strong&gt;chrome://policy&lt;/strong&gt; for at se listen over sortlistede webadresser og andre politikker, din systemadministrator har igangsat.</translation>
+<translation id="4110652170750985508">Gennemgå din betaling</translation>
<translation id="4116663294526079822">Tillad altid på dette website</translation>
<translation id="4117700440116928470">Politikkens omfang understøttes ikke.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 anden/andet}one{# anden/andet}other{# andre}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Intet brugernavn)</translation>
<translation id="4275830172053184480">Genstart din enhed</translation>
<translation id="4280429058323657511">udløber <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Log ind</translation>
<translation id="4312866146174492540">Bloker (standardindstilling)</translation>
<translation id="4325863107915753736">Artiklen blev ikke fundet.</translation>
<translation id="4326324639298822553">Kontrollér, om udløbsdatoen er korrekt, og prøv igen.</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Kort og adresser er fra Chrome og din Google-konto (<ph name="ACCOUNT_EMAIL" />). Du kan administrere dem i <ph name="BEGIN_LINK" />Indstillinger<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Detaljer</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Fra en integreret side på <ph name="SITE" /></translation>
<translation id="4558551763791394412">Prøv at deaktivere dine udvidelser.</translation>
<translation id="457875822857220463">Levering</translation>
<translation id="4582800630050655161">Du kan miste adgang til din Google-konto eller udsættes for identitetstyveri. Chromium anbefaler, at du skifter din adgangskode nu.</translation>
<translation id="4587425331216688090">Vil du fjerne adressen fra Chrome?</translation>
<translation id="4592951414987517459">Din forbindelse til <ph name="DOMAIN" /> er krypteret ved hjælp af en moderne krypteringspakke.</translation>
<translation id="4594403342090139922">&amp;Fortryd sletning</translation>
-<translation id="4611292653554630842">Log ind</translation>
<translation id="4619615317237390068">Faner fra andre enheder</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Denne server kunne ikke bevise, at den er <ph name="DOMAIN" />, da sikkerhedscertifikatet indeholder fejl. Dette kan skyldes en fejlkonfiguration, eller at en hacker har opfanget din forbindelse.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Din forbindelse blev afbrudt</translation>
<translation id="471880041731876836">Du har ikke tilladelse til at besøge dette website</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Køre Windows Netværksdiagnosticering<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Din betaling</translation>
<translation id="4726672564094551039">Opdater politikker</translation>
<translation id="4728558894243024398">Platform</translation>
<translation id="4736825316280949806">Genstart Chromium</translation>
-<translation id="4737498291095696011">Fra denne side</translation>
<translation id="4744603770635761495">Eksekverbar sti</translation>
<translation id="4749685221585524849">Sidst anvendt <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Dine oplysninger (f.eks. adgangskoder eller kreditkortnumre) er private, når de sendes til dette website.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Vis</translation>
<translation id="4854362297993841467">Denne leveringsmetode er ikke tilgængelig. Prøv en anden metode.</translation>
<translation id="4858792381671956233">Du har spurgt dine forældre, om det er i orden at besøge dette website.</translation>
-<translation id="4871132632506079383">Fra en integreret side på <ph name="SITE" /></translation>
<translation id="4880827082731008257">Søg i historikken</translation>
+<translation id="4881695831933465202">Åbn</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Godkendelse er påkrævet</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{og 1 anden webside}one{og # anden webside}other{og # andre websider}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Indtast kontrolkoden for <ph name="CREDIT_CARD" />. Når du bekræfter, deles kortoplysningerne på din konto i Google Payments med dette website.</translation>
<translation id="4923417429809017348">Denne side er oversat fra et ukendt sprog til <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Betaling</translation>
<translation id="4926049483395192435">Skal angives.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> siger</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Handlinger</translation>
<translation id="4958444002117714549">Udvid liste</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Hvis denne indstilling er slået til, gemmer Chrome en kopi af dit kort på denne enhed for at gøre det hurtigere at udfylde formularer.</translation>
<translation id="5018422839182700155">Denne side kan ikke åbnes</translation>
<translation id="5019198164206649151">Sikkerhedskopien er fejlbehæftet</translation>
-<translation id="5020990877659450221">Fra denne side</translation>
<translation id="5023310440958281426">Læs din administrators politikker</translation>
<translation id="5029568752722684782">Slet kopi</translation>
<translation id="503069730517007720">Et rodcertifikat for "<ph name="SOFTWARE_NAME" />" er påkrævet, men ikke installeret. Din IT-administrator bør kigge på konfigurationsvejledningen til "<ph name="SOFTWARE_NAME" />" for at løse dette problem. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Maskine</translation>
<translation id="5179510805599951267">Ikke på <ph name="ORIGINAL_LANGUAGE" />? Rapporter denne fejl</translation>
<translation id="5190835502935405962">Bogmærkelinje</translation>
+<translation id="5201306358585911203">En integreret side på denne side siger</translation>
<translation id="5205222826937269299">Navn påkrævet</translation>
-<translation id="5222812217790122047">E-mail påkrævet</translation>
+<translation id="5222812217790122047">Mail påkrævet</translation>
<translation id="522700295135997067">Dette website kan have stjålet din adgangskode</translation>
<translation id="5230733896359313003">Leveringsadresse</translation>
<translation id="5251803541071282808">Skyen</translation>
-<translation id="5277279256032773186">Bruger du Chrome på arbejdet? Virksomheder kan administrere Chrome-indstillinger for deres medarbejdere. Få flere oplysninger</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Følg denne vejledning for at deaktivere softwaren midlertidigt, så du kan komme på nettet. Du skal have administratorrettigheder.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,12 +671,11 @@
<translation id="5610142619324316209">Kontrollere forbindelsen</translation>
<translation id="5610807607761827392">Du kan administrere kort og adresser i <ph name="BEGIN_LINK" />Indstillinger<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> omdirigerede dig for mange gange.</translation>
-<translation id="5622887735448669177">Vil du forlade denne side?</translation>
<translation id="5629630648637658800">Der kunne ikke indlæses indstillinger for politik</translation>
<translation id="5631439013527180824">Ugyldigt token for enhedsadministration</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="5659593005791499971">E-mail</translation>
+<translation id="5659593005791499971">Mail</translation>
<translation id="5675650730144413517">Denne side virker ikke</translation>
<translation id="5685654322157854305">Tilføj leveringsadresse</translation>
<translation id="5689199277474810259">Eksportér i JSON</translation>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Skal dine kortoplysninger udfyldes?</translation>
<translation id="5803412860119678065">Skal <ph name="CARD_DETAIL" /> udfyldes?</translation>
<translation id="5810442152076338065">Din forbindelse til <ph name="DOMAIN" /> er krypteret ved hjælp af en forældet krypteringspakke.</translation>
-<translation id="5810928923025889964">Fra en integreret side på denne side</translation>
<translation id="5813119285467412249">&amp;Annuller fortryd tilføjelse</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>
<translation id="5866257070973731571">Tilføj telefonnummer</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Tilføj flere oplysninger</translation>
<translation id="6447842834002726250">Cookies</translation>
<translation id="6451458296329894277">Bekræft genindsendelse af formular</translation>
-<translation id="6456339708790392414">Din betaling</translation>
<translation id="647261751007945333">Enhedspolitikker</translation>
<translation id="6477321094435799029">Chrome registrerede usædvanlig kode på denne side og blokerede den for at beskytte dine personlige oplysninger (f.eks. adgangskoder, telefonnumre eller kreditkort).</translation>
<translation id="6489534406876378309">Start upload af nedbrud</translation>
<translation id="6507833130742554667">Betalingskort accepteres.</translation>
<translation id="6508722015517270189">Genstart Chrome</translation>
-<translation id="6521373090216409766">Vil du genindlæse dette website?</translation>
<translation id="6529602333819889595">&amp;Annuller fortryd slet</translation>
<translation id="6534179046333460208">Forslag til Fysisk web</translation>
<translation id="6550675742724504774">Valgmuligheder</translation>
-<translation id="6556239504065605927">Sikker forbindelse</translation>
<translation id="6556915248009097796">Udløbsdato: <ph name="EXPIRATION_DATE_ABBR" />. Sidst anvendt <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Din administrator har ikke godkendt det endnu</translation>
<translation id="6569060085658103619">Du ser en udvidelsesside</translation>
<translation id="6596325263575161958">Krypteringsmuligheder</translation>
+<translation id="6604181099783169992">Bevægelses- eller lyssensorer</translation>
<translation id="6624427990725312378">Kontaktoplysninger</translation>
<translation id="6626291197371920147">Tilføj gyldigt kortnummer</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> -søgning</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Administrerede bogmærker</translation>
<translation id="7298195798382681320">Anbefalet</translation>
<translation id="7309308571273880165">Nedbrudsrapport registreret <ph name="CRASH_TIME" /> (upload, som brugeren anmodede om, er endnu ikke uploadet)</translation>
+<translation id="7320336641823683070">Hjælp til at oprette forbindelse</translation>
<translation id="7334320624316649418">&amp;Annuller fortryd omarrangering</translation>
<translation id="733923710415886693">Servercertifikatet blev ikke fremvist via Certifikatsgennemsigtighed.</translation>
<translation id="7353601530677266744">Kommandolinje</translation>
@@ -900,6 +935,7 @@
<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="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="7862185352068345852">Vil du forlade websitet?</translation>
<translation id="7878176543348854470">Betalingskort accepteres.</translation>
<translation id="7878562273885520351">Din adgangskode kan være kompromitteret</translation>
<translation id="7887683347370398519">Kontrollér, om din kontrolkode er korrekt, og prøv igen.</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Brug global standard (spørg)</translation>
<translation id="8042918947222776840">Vælg afhentningsmetode</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" er ikke konfigureret korrekt. Problemet kan normalt løses ved at afinstallere "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Vil du genindlæse websitet?</translation>
<translation id="8088680233425245692">Artiklen kunne ikke vises.</translation>
<translation id="8091372947890762290">Aktivering afventer serveren</translation>
<translation id="8094917007353911263">Det netværk, du bruger, kan kræve, at du går til <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">Ugyldig webadresse til opdatering for udvidelse med id'et "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Ordreoversigt</translation>
<translation id="8205463626947051446">Websitet har tendens til at vise påtrængende annoncer</translation>
+<translation id="8211406090763984747">Forbindelsen er sikker</translation>
<translation id="8218327578424803826">Tildelt placering:</translation>
<translation id="8225771182978767009">Den person, der har konfigureret denne computer, har valgt at blokere dette website.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Se alle gemte adgangskoder</translation>
<translation id="8261506727792406068">Slet</translation>
<translation id="8267698848189296333">Logger ind som <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Log ind</translation>
<translation id="8288807391153049143">Vis certifikat</translation>
<translation id="8289355894181816810">Kontakt din netværksadministrator, hvis du ikke er sikker på, hvad det betyder.</translation>
<translation id="8293206222192510085">Tilføj bogmærke</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">Accepterede kreditkort og forudbetalte kort</translation>
<translation id="8759274551635299824">Kortet er udløbet</translation>
<translation id="8761567432415473239">Beskyttet browsing i Google har for nylig <ph name="BEGIN_LINK" />fundet skadelige programmer<ph name="END_LINK" /> på <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">USB-enhed</translation>
<translation id="8790007591277257123">&amp;Annuller fortryd sletning</translation>
<translation id="8800988563907321413">Her vises de forslag, der er tæt på dig</translation>
<translation id="8820817407110198400">Bogmærker</translation>
diff --git a/chromium/components/strings/components_strings_de.xtb b/chromium/components/strings/components_strings_de.xtb
index e506f70e058..5a0af22387c 100644
--- a/chromium/components/strings/components_strings_de.xtb
+++ b/chromium/components/strings/components_strings_de.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Drucken...</translation>
<translation id="1181037720776840403">Entfernen</translation>
<translation id="1184214524891303587">Informationen zu sicherheitsrelevanten Zwischenfällen <ph name="BEGIN_WHITEPAPER_LINK" />automatisch Google melden<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Zahlung nicht abgeschlossen</translation>
<translation id="1201402288615127009">Weiter</translation>
<translation id="1201895884277373915">Mehr von dieser Website</translation>
<translation id="1206967143813997005">Erste Signatur ungültig</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Absturzbericht erfasst am <ph name="CRASH_TIME" />, wurde noch nicht hochgeladen oder wurde ignoriert</translation>
<translation id="1270502636509132238">Abholoption</translation>
<translation id="1285320974508926690">Diese Website nie übersetzen</translation>
+<translation id="1294154142200295408">Befehlszeilen-Varianten</translation>
<translation id="129553762522093515">Kürzlich geschlossen</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Löschen Sie Ihre Cookies<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Ihre Aktivitäten <ph name="BEGIN_EMPHASIS" />sind eventuell weiterhin sichtbar<ph name="END_EMPHASIS" /> für:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Akzeptierte Kredit- und Debitkarten</translation>
<translation id="1519264250979466059">Build-Datum</translation>
<translation id="1527263332363067270">Warten auf Verbindung…</translation>
+<translation id="1532118530259321453">Auf dieser Seite wird Folgendes angezeigt</translation>
<translation id="153384715582417236">Das ist im Moment alles</translation>
<translation id="154408704832528245">Lieferadresse auswählen</translation>
<translation id="1549470594296187301">Für diese Funktion muss JavaScript aktiviert sein.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Proxy und Firewall prüfen<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Postleitzahl</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 Vorschlag}other{# Vorschläge}}</translation>
-<translation id="2065985942032347596">Authentifizierung erforderlich</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="2091887806945687916">Ton</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Zahlung abbrechen</translation>
<translation id="2147827593068025794">Hintergrundsynchronisierung</translation>
<translation id="2148613324460538318">Karte hinzufügen</translation>
-<translation id="2149973817440762519">Lesezeichen bearbeiten</translation>
<translation id="2154054054215849342">Die Synchronisierung ist für Ihre Domain nicht verfügbar</translation>
<translation id="2154484045852737596">Karte bearbeiten</translation>
<translation id="2166049586286450108">Vollständiger Administratorzugriff</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Abholadresse auswählen</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Ausgewählte Einträge entfernen</translation>
-<translation id="2744590937989388266">Von einer auf dieser Webseite eingebetteten Seite</translation>
<translation id="277133753123645258">Versandart</translation>
<translation id="277499241957683684">Fehlender Gerätedatensatz</translation>
<translation id="2784949926578158345">Verbindung wurde zurückgesetzt.</translation>
<translation id="2788784517760473862">Akzeptierte Kreditkarten</translation>
<translation id="2794233252405721443">Website blockiert</translation>
-<translation id="2795286477369100655">Möchten Sie diese Website verlassen?</translation>
<translation id="2799020568854403057">Die Website, die Sie aufrufen möchten, enthält schädliche Apps</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="2824775600643448204">Adress- und Suchleiste</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Listeneintrag "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automatisch blockiert</translation>
<translation id="3024663005179499861">Falscher Richtlinientyp</translation>
-<translation id="3032412215588512954">Möchten Sie diese Website neu laden?</translation>
<translation id="3037605927509011580">Oh nein!</translation>
<translation id="3039538478787849737">Karte in Google speichern?</translation>
<translation id="3041612393474885105">Zertifikatinformationen</translation>
@@ -310,6 +306,7 @@
Proxyeinstellungen oder wenden Sie sich an Ihren Netzwerkadministrator.
Falls Sie keinen Proxyserver verwenden möchten, deaktivieren Sie ihn wie
folgt: <ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> auf <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Zahlung abbrechen</translation>
<translation id="3207960819495026254">Mit einem Lesezeichen versehen</translation>
<translation id="3209375525920864198">Bitte geben Sie einen gültigen Sitzungsnamen ein.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Dein Administrator kann die Blockierung aufheben</translation>
<translation id="3566021033012934673">Dies ist keine sichere Verbindung</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Auf einer in <ph name="SITE" /> eingebetteten Seite wird Folgendes angezeigt</translation>
<translation id="358285529439630156">Kredit- und Prepaidkarten werden akzeptiert.</translation>
<translation id="3582930987043644930">Namen hinzufügen</translation>
<translation id="3583757800736429874">&amp;Verschieben wiederholen</translation>
<translation id="3586931643579894722">Details ausblenden</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Verbindungsfehler beheben&lt;/h1&gt;
+ &lt;p&gt;Wenn Sie beim Versuch, eine Website aufzurufen, eine Fehlermeldung erhalten, können Sie die folgenden Schritte ausprobieren, um das Problem zu beheben.&lt;/p&gt;
+ &lt;h2&gt;Die häufigsten Verbindungsfehler beheben&lt;/h2&gt;
+ &lt;p&gt;Wenn Sie eine bestimmte Website nicht aufrufen können, versuchen Sie zuerst Folgendes:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Überprüfen Sie die Webadresse auf Tippfehler.&lt;/li&gt;
+ &lt;li&gt;Kontrollieren Sie, ob Ihre Internetverbindung richtig funktioniert.&lt;/li&gt;
+ &lt;li&gt;Kontaktieren Sie den Websiteinhaber.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Hilfe bei bestimmten Fehlermeldungen&lt;/h2&gt;
+ &lt;h3&gt;"Dies ist keine sichere Verbindung", "NET::ERR_CERT_AUTHORITY_INVALID", "ERR_CERT_COMMON_NAME_INVALID", "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" oder "SSL-Zertifikatfehler"&lt;/h3&gt;
+ &lt;h4&gt;Schritt 1: Im Portal anmelden&lt;/h4&gt;
+ &lt;p&gt;An manchen Orten, wie in Cafés oder auf Flughäfen, müssen Sie sich für die WLAN-Nutzung anmelden. Um zur Anmeldeseite zu gelangen, besuchen Sie eine Seite, die mit &lt;code&gt;http://&lt;/code&gt; beginnt.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Rufen Sie eine beliebige Website auf, deren URL mit &lt;code&gt;http://&lt;/code&gt; beginnt, z. B. &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Die Anmeldeseite wird geöffnet. Melden Sie sich dort an, um das Internet zu nutzen.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Schritt 2: Webseite im Inkognitomodus öffnen (nur Computer)&lt;/h4&gt;
+ &lt;p&gt;Öffnen Sie die besuchte Seite in einem Inkognitofenster.&lt;/p&gt;
+ &lt;p&gt;Wenn die Seite geöffnet wird, verursacht eine Chrome-Erweiterung das Problem. Deaktivieren Sie diese, um den Fehler zu beheben.&lt;/p&gt;
+ &lt;h4&gt;Schritt 3: Betriebssystem aktualisieren&lt;/h4&gt;
+ &lt;p&gt;Sorgen Sie dafür, dass Ihr Gerät auf dem neuesten Stand ist.&lt;/p&gt;
+ &lt;h4&gt;Schritt 4: Antivirenprogramm vorübergehend deaktivieren&lt;/h4&gt;
+ &lt;p&gt;Sie erhalten diese Fehlermeldung, wenn Sie eine Antivirensoftware mit "HTTPS-Schutz" oder "HTTPS-Scanning" verwenden, die die Sicherheitsfunktionen von Chrome beeinträchtigt.&lt;/p&gt;
+ &lt;p&gt;Deaktivieren Sie die Antivirensoftware, um das Problem zu beheben. Wenn die Seite danach funktioniert, deaktivieren Sie diese Software immer dann, wenn Sie sichere Websites besuchen.&lt;/p&gt;
+ &lt;p&gt;Denken Sie daran, das Antivirenprogramm wieder zu aktivieren, sobald Sie fertig sind.&lt;/p&gt;
+ &lt;h4&gt;Schritt 5: Weitere Hilfe erhalten&lt;/h4&gt;
+ &lt;p&gt;Wenn der Fehler noch immer angezeigt wird, wenden Sie sich an den Inhaber der Website.&lt;/p&gt;
+ &lt;h3&gt;"Mit Netzwerk verbinden"&lt;/h3&gt;
+ &lt;p&gt;Diese Fehlermeldung erscheint, 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 das Problem zu beheben.&lt;/p&gt;
+ &lt;h3&gt;"Ihre Uhr geht nach", "Ihre Uhr geht vor" oder "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Diese Fehlermeldung wird angezeigt, wenn das Datum bzw. die Uhrzeit auf Ihrem Computer oder Mobilgerät nicht korrekt ist.&lt;/p&gt;
+ &lt;p&gt;Korrigieren Sie die Uhrzeit und das Datum in den Geräteeinstellungen, um den Fehler zu beheben.&lt;/p&gt;
+ &lt;h3&gt;"Software auf Ihrem Computer verhindert, dass Chrome eine sichere Internetverbindung herstellt" (nur Windows-Computer)&lt;/h3&gt;
+ &lt;p&gt;Sie erhalten diese Fehlermeldung, wenn auf Ihrem Windows-Computer Superfish-Software installiert ist.&lt;/p&gt;
+ &lt;p&gt;Führen Sie die folgenden Schritte aus, um die Software vorübergehend zu deaktivieren, damit Sie auf das Internet zugreifen können. Zum Deaktivieren der Software benötigen Sie Administratorberechtigungen.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Klicken Sie auf &lt;strong&gt;Start&lt;/strong&gt;, suchen Sie nach &lt;strong&gt;Lokale Dienste anzeigen&lt;/strong&gt; und wählen Sie die Option aus.
+ &lt;li&gt;Klicken Sie auf &lt;strong&gt;VisualDiscovery&lt;/strong&gt;.
+ &lt;li&gt;Wählen Sie unter &lt;strong&gt;Starttyp&lt;/strong&gt; die Option &lt;strong&gt;Deaktiviert&lt;/strong&gt; aus.
+ &lt;li&gt;Klicken Sie unter &lt;strong&gt;Dienststatus&lt;/strong&gt; auf &lt;strong&gt;Beenden&lt;/strong&gt;.
+ &lt;li&gt;Klicken Sie auf &lt;strong&gt;Übernehmen&lt;/strong&gt; und anschließend auf &lt;strong&gt;OK&lt;/strong&gt;.
+ &lt;li&gt;Wenn Sie wissen möchten, wie Sie die Software endgültig von Ihrem Computer entfernen können, finden Sie in der Chrome-Hilfe &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;eine entsprechende Anleitung&lt;/a&gt;.
+ &lt;/ol&gt;</translation>
<translation id="3615877443314183785">Geben Sie ein gültiges Ablaufdatum ein</translation>
<translation id="36224234498066874">Browserdaten löschen...</translation>
<translation id="362276910939193118">Gesamtverlauf anzeigen</translation>
@@ -381,7 +424,7 @@
<translation id="3655670868607891010">Sollte Ihnen diese Meldung häufiger angezeigt werden, sehen Sie sich unsere <ph name="HELP_LINK" /> an.</translation>
<translation id="3658742229777143148">Überarbeitung</translation>
<translation id="3678029195006412963">Anfrage konnte nicht signiert werden</translation>
-<translation id="3678529606614285348">Seite in einem neuen Inkognitofenster öffnen (Strg + Shift + N)</translation>
+<translation id="3678529606614285348">Seite in einem neuen Inkognitofenster öffnen (Strg + Umschalttaste + N)</translation>
<translation id="3679803492151881375">Absturz am <ph name="CRASH_TIME" /> erfasst und am <ph name="UPLOAD_TIME" /> hochgeladen</translation>
<translation id="3681007416295224113">Zertifikatinformationen</translation>
<translation id="3690164694835360974">Log-in nicht sicher</translation>
@@ -403,7 +446,6 @@
<translation id="3778403066972421603">Möchten Sie diese Karte in Ihrem Google-Konto und auf diesem Gerät speichern?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Ablaufdatum: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Von <ph name="SITE" /></translation>
<translation id="382518646247711829">Falls Sie einen Proxyserver verwenden...</translation>
<translation id="3828924085048779000">Eine leere Passphrase ist nicht zulässig.</translation>
<translation id="385051799172605136">Zurück</translation>
@@ -417,6 +459,7 @@
<translation id="3945915738023014686">ID des hochgeladenen Absturzberichts: <ph name="CRASH_ID" /> (lokale Absturz-ID: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Dieser Server konnte nicht beweisen, dass er <ph name="DOMAIN" /> ist. Sein Sicherheitszertifikat gibt keine alternativen Namen an. Mögliche Gründe sind eine fehlerhafte Konfiguration oder ein Angreifer, der Ihre Verbindung abfängt.</translation>
<translation id="3949601375789751990">Hier wird Ihr Browserverlauf angezeigt</translation>
+<translation id="3950820424414687140">Anmelden</translation>
<translation id="3963721102035795474">Lesemodus</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Keine}=1{Von 1 Website }other{Von # Websites }}</translation>
<translation id="397105322502079400">Wird berechnet...</translation>
@@ -433,10 +476,11 @@
<translation id="4103249731201008433">Seriennummer des Geräts ist ungültig.</translation>
<translation id="410351446219883937">Autoplay</translation>
<translation id="4103763322291513355">Unter &lt;strong&gt;chrome://policy&lt;/strong&gt; finden Sie eine Liste der blockierten URLs und andere Richtlinien, die durch Ihren Systemadministrator erzwungen werden.</translation>
+<translation id="4110652170750985508">Zahlung überprüfen</translation>
<translation id="4116663294526079822">Auf dieser Website immer zulassen</translation>
<translation id="4117700440116928470">Richtlinienbereich wird nicht unterstützt.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 weiterer}other{# weitere}}</translation>
-<translation id="4130226655945681476">Prüfen Sie Netzwerkkabel, Modem und Router</translation>
+<translation id="4130226655945681476">Netzwerkkabel, Modem und Router prüfen</translation>
<translation id="413544239732274901">Weitere Informationen</translation>
<translation id="4148925816941278100">American Express</translation>
<translation id="4151403195736952345">Globalen Standard verwenden (Erkennen)</translation>
@@ -459,7 +503,6 @@
<translation id="4269787794583293679">(Kein Nutzername)</translation>
<translation id="4275830172053184480">Gerät neu starten</translation>
<translation id="4280429058323657511">Gültig bis: <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Anmelden</translation>
<translation id="4312866146174492540">Blockieren (Standardeinstellung)</translation>
<translation id="4325863107915753736">Der Artikel wurde nicht gefunden.</translation>
<translation id="4326324639298822553">Prüfen Sie Ihr Ablaufdatum und versuchen Sie es dann erneut</translation>
@@ -481,14 +524,12 @@
<translation id="4515275063822566619">Karten und Adressen stammen aus Chrome und aus Ihrem Google-Konto (<ph name="ACCOUNT_EMAIL" />). Sie können sie in den <ph name="BEGIN_LINK" />Einstellungen<ph name="END_LINK" /> verwalten.</translation>
<translation id="4522570452068850558">Details</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Von einer auf <ph name="SITE" /> eingebetteten Seite</translation>
<translation id="4558551763791394412">Deaktivieren Sie Ihre Erweiterungen.</translation>
<translation id="457875822857220463">Lieferung</translation>
<translation id="4582800630050655161">Sie könnten den Zugriff auf Ihr Google-Konto verlieren oder zum Opfer von Identitätsdiebstahl werden. Chromium empfiehlt Ihnen, Ihr Passwort jetzt zu ändern.</translation>
<translation id="4587425331216688090">Adresse aus Chrome entfernen?</translation>
<translation id="4592951414987517459">Ihre Verbindung zu <ph name="DOMAIN" /> ist mit einer modernen Codier-Suite verschlüsselt.</translation>
<translation id="4594403342090139922">&amp;Löschen rückgängig machen</translation>
-<translation id="4611292653554630842">Anmelden</translation>
<translation id="4619615317237390068">Tabs von anderen Geräten</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Dieser Server konnte nicht beweisen, dass er <ph name="DOMAIN" /> ist. Sein Sicherheitszertifikat enthält Fehler. Mögliche Gründe sind eine fehlerhafte Konfiguration oder ein Angreifer, der Ihre Verbindung abfängt.</translation>
@@ -498,11 +539,9 @@
<translation id="4708268264240856090">Die Verbindung wurde unterbrochen</translation>
<translation id="471880041731876836">Sie sind nicht berechtigt, auf diese Website zuzugreifen</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows-Netzwerkdiagnose ausführen<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Bezahlung</translation>
<translation id="4726672564094551039">Richtlinien neu laden</translation>
<translation id="4728558894243024398">Plattform</translation>
<translation id="4736825316280949806">Chromium neu starten</translation>
-<translation id="4737498291095696011">Von dieser Webseite</translation>
<translation id="4744603770635761495">Ausführbarer Pfad</translation>
<translation id="4749685221585524849">Zuletzt verwendet: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Ihre Daten wie Passwörter oder Kreditkartennummern sind privat, wenn Sie sie an diese Website senden.</translation>
@@ -521,16 +560,16 @@
<translation id="4850886885716139402">Anzeigen</translation>
<translation id="4854362297993841467">Diese Lieferoption ist nicht verfügbar. Bitte wählen Sie eine andere Option aus.</translation>
<translation id="4858792381671956233">Du hast deine Eltern gefragt, ob du diese Website besuchen darfst</translation>
-<translation id="4871132632506079383">Von einer auf <ph name="SITE" /> eingebetteten Seite</translation>
<translation id="4880827082731008257">Im Verlauf suchen</translation>
+<translation id="4881695831933465202">Öffnen</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Authentifizierung erforderlich</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{und 1 weitere Webseite}other{und # weitere Webseiten}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Geben Sie den CVC für <ph name="CREDIT_CARD" /> ein. Nach erfolgter Bestätigung werden die Kartendetails Ihres Google Payments-Kontos an diese Website weitergegeben.</translation>
<translation id="4923417429809017348">Diese Seite wurde von einer unbekannten Sprache in <ph name="LANGUAGE_LANGUAGE" /> übersetzt.</translation>
<translation id="4923459931733593730">Zahlung</translation>
<translation id="4926049483395192435">Angabe erforderlich</translation>
+<translation id="4926159001844873046">Auf <ph name="SITE" /> wird Folgendes angezeigt</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Aktionen</translation>
<translation id="4958444002117714549">Liste einblenden</translation>
@@ -539,7 +578,6 @@
<translation id="5002932099480077015">Wenn diese Funktion aktiviert ist, speichert Chrome eine Kopie Ihrer Karte auf diesem Gerät, um ein Ausfüllen von Formularen zu beschleunigen.</translation>
<translation id="5018422839182700155">Diese Seite kann nicht geöffnet werden</translation>
<translation id="5019198164206649151">Sicherungsspeicher ist fehlerhaft.</translation>
-<translation id="5020990877659450221">Von dieser Webseite</translation>
<translation id="5023310440958281426">Informieren Sie sich über die von Ihrem Administrator festgelegten Richtlinien.</translation>
<translation id="5029568752722684782">Kopie löschen</translation>
<translation id="503069730517007720">Für "<ph name="SOFTWARE_NAME" />" ist ein Stammzertifikat erforderlich, das nicht installiert ist. Ihr IT-Administrator sollte die Konfigurationsanweisungen für "<ph name="SOFTWARE_NAME" />" lesen, um das Problem zu beheben. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -565,12 +603,12 @@
<translation id="5172758083709347301">Computer</translation>
<translation id="5179510805599951267">Nicht auf <ph name="ORIGINAL_LANGUAGE" />? Diesen Fehler melden</translation>
<translation id="5190835502935405962">Lesezeichenleiste</translation>
+<translation id="5201306358585911203">Auf einer in dieser Seite eingebetteten Seite wird Folgendes angezeigt</translation>
<translation id="5205222826937269299">Name erforderlich</translation>
<translation id="5222812217790122047">E-Mail-Adresse erforderlich</translation>
<translation id="522700295135997067">Diese Website hat möglicherweise gerade Ihr Passwort gestohlen</translation>
<translation id="5230733896359313003">Versandadresse</translation>
<translation id="5251803541071282808">Cloud</translation>
-<translation id="5277279256032773186">Nutzen Sie Chrome bei der Arbeit? Unternehmen können Chrome-Einstellungen für ihre Mitarbeiter verwalten. Weitere Informationen</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Führen Sie die folgenden Schritte aus, um die Software vorübergehend zu deaktivieren und dann auf das Internet zuzugreifen. Zum Deaktivieren der Software benötigen Sie Administratorrechte.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -632,7 +670,6 @@
<translation id="5610142619324316209">Verbindung prüfen</translation>
<translation id="5610807607761827392"><ph name="BEGIN_LINK" />Karten und Adressen können Sie in den Einstellungen verwalten.<ph name="END_LINK" /></translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> hat Sie zu oft weitergeleitet.</translation>
-<translation id="5622887735448669177">Möchten Sie diese Website verlassen?</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="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>
@@ -655,7 +692,6 @@
<translation id="5786044859038896871">Möchten Sie Ihre Kreditkarteninformationen eingeben?</translation>
<translation id="5803412860119678065">Möchten Sie die Daten Ihrer <ph name="CARD_DETAIL" /> eingeben?</translation>
<translation id="5810442152076338065">Ihre Verbindung zu <ph name="DOMAIN" /> ist mit einer veralteten Codier-Suite verschlüsselt.</translation>
-<translation id="5810928923025889964">Von einer auf dieser Webseite eingebetteten Seite</translation>
<translation id="5813119285467412249">&amp;Hinzufügen wiederholen</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>
<translation id="5866257070973731571">Telefonnummer hinzufügen</translation>
@@ -676,7 +712,7 @@
<translation id="5990559369517809815">Anfragen an den Server wurden durch eine Erweiterung blockiert.</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6016158022840135739">{COUNT,plural, =1{Seite 1}other{Seite #}}</translation>
-<translation id="6017850046339264347">Angreifer auf der Website <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> könnten betrügerische Apps installieren, die scheinbar einem anderen Zweck dienen oder Daten sammeln, um Sie auszuspionieren. <ph name="BEGIN_LEARN_MORE_LINK" />Weitere Informationen<ph name="END_LEARN_MORE_LINK" /></translation>
+<translation id="6017850046339264347">Angreifer auf der Website <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> könnten betrügerische Apps installieren, die scheinbar einem anderen Zweck dienen oder Daten erfassen, um Sie auszuspionieren. <ph name="BEGIN_LEARN_MORE_LINK" />Weitere Informationen<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (synchronisiert)</translation>
<translation id="6027201098523975773">Geben Sie einen Namen ein</translation>
<translation id="6039846035001940113">Falls das Problem weiterhin besteht, wenden Sie sich an den Inhaber der Website.</translation>
@@ -729,21 +765,19 @@
<translation id="6446608382365791566">Weitere Informationen hinzufügen</translation>
<translation id="6447842834002726250">Cookies</translation>
<translation id="6451458296329894277">Erneute Formular-Übermittlung bestätigen</translation>
-<translation id="6456339708790392414">Bezahlung</translation>
<translation id="647261751007945333">Geräterichtlinien</translation>
<translation id="6477321094435799029">Chrome hat auf dieser Seite ungewöhnlichen Code erfasst und diese Seite daher blockiert, um Ihre personenbezogenen Daten wie Passwörter, Telefonnummern oder Kreditkarteninformationen zu schützen.</translation>
<translation id="6489534406876378309">Hochladen von Abstürzen starten</translation>
<translation id="6507833130742554667">Kredit- und Debitkarten werden akzeptiert.</translation>
<translation id="6508722015517270189">Chrome neu starten</translation>
-<translation id="6521373090216409766">Möchten Sie diese Website neu laden?</translation>
<translation id="6529602333819889595">&amp;Löschen wiederholen</translation>
<translation id="6534179046333460208">Physical Web-Vorschläge</translation>
<translation id="6550675742724504774">Optionen</translation>
-<translation id="6556239504065605927">Sichere Verbindung</translation>
<translation id="6556915248009097796">Gültig bis: <ph name="EXPIRATION_DATE_ABBR" />, zuletzt verwendet: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Der Administrator hat die Berechtigung noch nicht erteilt</translation>
<translation id="6569060085658103619">Dies ist eine Erweiterungsseite</translation>
<translation id="6596325263575161958">Verschlüsselungsoptionen</translation>
+<translation id="6604181099783169992">Bewegungs- oder Lichtsensoren</translation>
<translation id="6624427990725312378">Kontaktdaten</translation>
<translation id="6626291197371920147">Gültige Kartennummer hinzufügen</translation>
<translation id="6628463337424475685"><ph name="ENGINE" />-Suche</translation>
@@ -760,7 +794,7 @@
<translation id="6757797048963528358">Ihr Gerät ist im Ruhemodus.</translation>
<translation id="6778737459546443941">Dein Elternteil hat die Berechtigung noch nicht erteilt</translation>
<translation id="679355240208270552">Ignoriert, da die Standardsuchmaschine durch die Richtlinie deaktiviert ist.</translation>
-<translation id="681021252041861472">Erforderliches Feld</translation>
+<translation id="681021252041861472">Pflichtfeld</translation>
<translation id="6810899417690483278">Personalisierungs-ID</translation>
<translation id="6820686453637990663">CVC</translation>
<translation id="6824266427216888781">Fehler beim Laden der Regionsdaten</translation>
@@ -815,6 +849,7 @@
<translation id="7275334191706090484">Verwaltete Lesezeichen</translation>
<translation id="7298195798382681320">Empfohlen</translation>
<translation id="7309308571273880165">Absturzbericht erfasst: <ph name="CRASH_TIME" /> (Upload wurde vom Nutzer angefordert, aber noch nicht abgeschlossen)</translation>
+<translation id="7320336641823683070">Hilfe bei der Verbindungsherstellung</translation>
<translation id="7334320624316649418">&amp;Neu anordnen wiederholen</translation>
<translation id="733923710415886693">Das Serverzertifikat wurde nicht über die Zertifikatstransparenz offengelegt.</translation>
<translation id="7353601530677266744">Befehlszeile</translation>
@@ -899,6 +934,7 @@
<translation id="782886543891417279">Unter Umständen müssen Sie die Anmeldeseite des verwendeten WLAN-Netzwerken (<ph name="WIFI_NAME" />) aufrufen.</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="7862185352068345852">Website verlassen?</translation>
<translation id="7878176543348854470">Debit- und Prepaidkarten werden akzeptiert.</translation>
<translation id="7878562273885520351">Ihr Passwort könnte gefährdet sein</translation>
<translation id="7887683347370398519">Prüfen Sie Ihren CVC und versuchen Sie es dann erneut.</translation>
@@ -921,6 +957,7 @@
<translation id="8041940743680923270">Globalen Standard verwenden (Fragen)</translation>
<translation id="8042918947222776840">Abholoption auswählen</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" ist nicht ordnungsgemäß konfiguriert. Durch die Deinstallation von "<ph name="SOFTWARE_NAME" />" sollte das Problem behoben werden. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Website neu laden?</translation>
<translation id="8088680233425245692">Der Artikel kann nicht angezeigt werden.</translation>
<translation id="8091372947890762290">Aktivierung auf dem Server steht noch aus.</translation>
<translation id="8094917007353911263">Unter Umständen erfordert das von Ihnen verwendete Netzwerk, dass Sie <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> aufrufen.</translation>
@@ -936,6 +973,7 @@
<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>
<translation id="8205463626947051446">Website zeigt für gewöhnlich aufdringliche Werbeanzeigen an</translation>
+<translation id="8211406090763984747">Verbindung ist sicher</translation>
<translation id="8218327578424803826">Zugewiesener Standort:</translation>
<translation id="8225771182978767009">Die Person, die diesen Computer eingerichtet hat, hat diese Website gesperrt.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -947,6 +985,7 @@
<translation id="825929999321470778">Alle gespeicherten Passwörter anzeigen</translation>
<translation id="8261506727792406068">Löschen</translation>
<translation id="8267698848189296333">Als <ph name="USERNAME" /> anmelden</translation>
+<translation id="8286036467436129157">Anmelden</translation>
<translation id="8288807391153049143">Zertifikat anzeigen</translation>
<translation id="8289355894181816810">Wenn Sie weitere Informationen dazu benötigen, kann Ihnen Ihr Netzwerkadministrator weiterhelfen.</translation>
<translation id="8293206222192510085">Lesezeichen hinzufügen</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Akzeptierte Kredit- und Prepaidkarten</translation>
<translation id="8759274551635299824">Diese Karte ist abgelaufen</translation>
<translation id="8761567432415473239">Google Safe Browsing hat vor Kurzem <ph name="BEGIN_LINK" />schädliche Programme<ph name="END_LINK" /> auf <ph name="SITE" /> gefunden.</translation>
+<translation id="8763927697961133303">USB-Gerät</translation>
<translation id="8790007591277257123">&amp;Löschen wiederholen</translation>
<translation id="8800988563907321413">Hier werden Ihre Vorschläge in der Nähe angezeigt</translation>
<translation id="8820817407110198400">Lesezeichen</translation>
diff --git a/chromium/components/strings/components_strings_el.xtb b/chromium/components/strings/components_strings_el.xtb
index 94fec0ebd75..38afd26d9af 100644
--- a/chromium/components/strings/components_strings_el.xtb
+++ b/chromium/components/strings/components_strings_el.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Εκτύπωση...</translation>
<translation id="1181037720776840403">Κατάργηση</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Αυτόματη αναφορά<ph name="END_WHITEPAPER_LINK" /> στην Google λεπτομερειών σχετικά με πιθανά περιστατικά ασφάλειας.<ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Η πληρωμή δεν ολοκληρώθηκε</translation>
<translation id="1201402288615127009">Επόμενο</translation>
<translation id="1201895884277373915">Περισσότερα από αυτόν τον ιστότοπο</translation>
<translation id="1206967143813997005">Εσφαλμένη αρχική υπογραφή</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Καταγράφηκαν αναφορές σφαλμάτων <ph name="CRASH_TIME" /> (δεν έχουν ακόμη μεταφορτωθεί ή παραβλεφθεί)</translation>
<translation id="1270502636509132238">Τρόπος παραλαβής</translation>
<translation id="1285320974508926690">Να μην γίνεται ποτέ μετάφραση αυτού του ιστότοπου</translation>
+<translation id="1294154142200295408">Παραλλαγές γραμμής εντολών</translation>
<translation id="129553762522093515">Έκλεισαν πρόσφατα</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Δοκιμάστε να διαγράψετε τα cookie σας<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Η δραστηριότητά σας <ph name="BEGIN_EMPHASIS" />μπορεί να εξακολουθήσει να είναι ορατή<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Αποδεκτές πιστωτικές και χρεωστικές κάρτες</translation>
<translation id="1519264250979466059">Ημερομηνία κατασκευής</translation>
<translation id="1527263332363067270">Αναμονή για σύνδεση…</translation>
+<translation id="1532118530259321453">Αυτή η σελίδα λέει</translation>
<translation id="153384715582417236">Αυτά προς το παρόν</translation>
<translation id="154408704832528245">Επιλογή διεύθυνσης παράδοσης</translation>
<translation id="1549470594296187301">Θα πρέπει να ενεργοποιηθεί η JavaScript για τη χρήση αυτής της λειτουργίας.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Ελέγξτε το διακομιστή μεσολάβησης και το τείχος προστασίας<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Ταχυδρομικός κώδικας</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 πρόταση}other{# προτάσεις}}</translation>
-<translation id="2065985942032347596">Απαιτείται έλεγχος ταυτότητας</translation>
<translation id="2079545284768500474">Αναίρεση</translation>
<translation id="20817612488360358">Οι ρυθμίσεις διακομιστή μεσολάβησης του συστήματος έχουν οριστεί για να χρησιμοποιηθούν, αλλά καθορίζεται επίσης μια ρητή διαμόρφωση του διακομιστή μεσολάβησης.</translation>
<translation id="2091887806945687916">Ήχος</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Ακύρωση πληρωμής</translation>
<translation id="2147827593068025794">Συγχρονισμός παρασκηνίου</translation>
<translation id="2148613324460538318">Προσθήκη κάρτας</translation>
-<translation id="2149973817440762519">Επεξεργασία σελιδοδείκτη</translation>
<translation id="2154054054215849342">Ο συγχρονισμός δεν είναι διαθέσιμος για τον τομέα σας</translation>
<translation id="2154484045852737596">Επεξεργασία κάρτας</translation>
<translation id="2166049586286450108">Πλήρης πρόσβαση διαχειριστή</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Επιλογή διεύθυνσης παραλαβής</translation>
<translation id="2740531572673183784">ΟK</translation>
<translation id="2742870351467570537">Κατάργηση επιλεγμένων στοιχείων</translation>
-<translation id="2744590937989388266">Από μια Ενσωματωμένη Σελίδα σε Αυτήν τη Σελίδα</translation>
<translation id="277133753123645258">Τρόπος αποστολής</translation>
<translation id="277499241957683684">Λείπει κάποιο αρχείο συσκευής</translation>
<translation id="2784949926578158345">Έγινε επαναφορά της σύνδεσης.</translation>
<translation id="2788784517760473862">Αποδεκτές πιστωτικές κάρτες</translation>
<translation id="2794233252405721443">Ο ιστότοπος έχει αποκλειστεί</translation>
-<translation id="2795286477369100655">Θέλετε να φύγετε από αυτόν τον ιστότοπο;</translation>
<translation id="2799020568854403057">Ο ιστότοπος που πρόκειται να επισκεφτείτε περιέχει επιβλαβείς εφαρμογές</translation>
<translation id="2803306138276472711">Πρόσφατα η Ασφαλής περιήγηση Google <ph name="BEGIN_LINK" />εντόπισε κακόβουλο λογισμικό<ph name="END_LINK" /> στον ιστότοπο <ph name="SITE" />. Οι ιστότοποι που είναι ασφαλείς υπό φυσιολογικές συνθήκες μερικές φορές προσβάλλονται από κακόβουλα λογισμικά.</translation>
<translation id="2824775600643448204">Γραμμή διευθύνσεων και αναζήτησης</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Καταχώριση λίστας "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Αποκλείστηκε αυτόματα</translation>
<translation id="3024663005179499861">Λανθασμένος τύπος πολιτικής</translation>
-<translation id="3032412215588512954">Θέλετε να φορτώσετε ξανά αυτόν τον ιστότοπο;</translation>
<translation id="3037605927509011580">Όπα! Κάτι πήγε στραβά!</translation>
<translation id="3039538478787849737">Να αποθηκευτεί η κάρτα στο Google;</translation>
<translation id="3041612393474885105">Πληροφορίες πιστοποιητικού</translation>
@@ -310,6 +306,7 @@
να βεβαιωθείτε ότι ο διακομιστής μεσολάβησης λειτουργεί. Εάν δεν πιστεύετε ότι
απαιτείται η χρήση διακομιστή μεσολάβησης:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> στο <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Ακύρωση πληρωμής</translation>
<translation id="3207960819495026254">Προστέθηκε στους σελιδοδείκτες</translation>
<translation id="3209375525920864198">Εισαγάγετε ένα έγκυρο όνομα περιόδου λειτουργίας.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Ο διαχειριστής σας μπορεί να καταργήσει τον αποκλεισμό του για εσάς</translation>
<translation id="3566021033012934673">Η σύνδεσή σας δεν είναι ιδιωτική</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Μια ενσωματωμένη σελίδα στον ιστότοπο <ph name="SITE" /> λέει</translation>
<translation id="358285529439630156">Οι πιστωτικές και προπληρωμένες κάρτες γίνονται δεκτές.</translation>
<translation id="3582930987043644930">Προσθήκη ονόματος</translation>
<translation id="3583757800736429874">&amp;Επανάληψη μετακίνησης</translation>
<translation id="3586931643579894722">Απόκρυψη λεπτομερειών</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Διόρθωση σφαλμάτων σύνδεσης&lt;/h1&gt;
+ &lt;p&gt;Εάν εμφανιστεί ένα μήνυμα σφάλματος, ενώ προσπαθείτε να επισκεφτείτε κάποιον ιστότοπο, δοκιμάστε αυτές τις διορθώσεις σφαλμάτων.&lt;/p&gt;
+ &lt;h2&gt;Διόρθωση των περισσότερων σφαλμάτων σύνδεσης&lt;/h2&gt;
+ &lt;p&gt;Εάν προσπαθείτε να επισκεφτείτε έναν ιστότοπο και ο ιστότοπος δεν ανοίγει, δοκιμάστε πρώτα να διορθώσετε το σφάλμα, ακολουθώντας τα παρακάτω βήματα αντιμετώπισης προβλημάτων:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Ελέγξτε τη διεύθυνση ιστού για τυχόν σφάλματα πληκτρολόγησης.&lt;/li&gt;
+ &lt;li&gt;Βεβαιωθείτε ότι η σύνδεσή σας στο διαδίκτυο λειτουργεί κανονικά.&lt;/li&gt;
+ &lt;li&gt;Επικοινωνήστε με τον κάτοχο του ιστοτόπου.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Λήψη βοήθειας για συγκεκριμένο μήνυμα σφάλματος&lt;/h2&gt;
+ &lt;h3&gt;"Η σύνδεσή σας δεν είναι ιδιωτική" ή "NET::ERR_CERT_AUTHORITY_INVALID" ή "ERR_CERT_COMMON_NAME_INVALID" ή "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" ή "Σφάλμα πιστοποιητικού SSL"&lt;/h3&gt;
+ &lt;h4&gt;Βήμα 1: Συνδεθείτε στην πύλη&lt;/h4&gt;
+ &lt;p&gt;Τα δίκτυα Wi-Fi σε μέρη όπως καφετέριες ή αεροδρόμια σάς ζητούν να συνδεθείτε. Για να δείτε τη σελίδα σύνδεσης, επισκεφτείτε μια σελίδα που χρησιμοποιεί&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Μεταβείτε σε οποιονδήποτε ιστότοπο ξεκινά με &lt;code&gt;http://&lt;/code&gt;, όπως &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Στη σελίδα σύνδεσης που θα ανοίξει, συνδεθείτε, για να χρησιμοποιήσετε το διαδίκτυο.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Βήμα 2: Ανοίξτε τη σελίδα σε κατάσταση ανώνυμης περιήγησης (μόνο για υπολογιστή)&lt;/h4&gt;
+ &lt;p&gt;Ανοίξτε τη σελίδα που επισκεφτήκατε σε ένα παράθυρο για ανώνυμη περιήγηση.&lt;/p&gt;
+ &lt;p&gt;Εάν η σελίδα ανοίξει, τότε κάποια επέκταση του Chrome δεν λειτουργεί σωστά. Για να διορθώσετε το σφάλμα, απενεργοποιήστε την επέκταση.&lt;/p&gt;
+ &lt;h4&gt;Βήμα 3: Ενημερώστε το λειτουργικό σύστημα&lt;/h4&gt;
+ &lt;p&gt;Βεβαιωθείτε ότι η συσκευή σας είναι ενημερωμένη.&lt;/p&gt;
+ &lt;h4&gt;Βήμα 4: Απενεργοποιήστε προσωρινά το λογισμικό προστασίας από ιούς&lt;/h4&gt;
+ &lt;p&gt;Αυτό το σφάλμα θα παρουσιαστεί εάν χρησιμοποιείτε λογισμικό προστασίας από ιούς που παρέχει "προστασία HTTPS" ή "σάρωση HTTPS". Το λογισμικό προστασίας από ιούς αποτρέπει την παροχή ασφάλειας από το Chrome.&lt;/p&gt;
+ &lt;p&gt;Για να διορθώσετε το πρόβλημα, απενεργοποιήστε το λογισμικό προστασίας από ιούς. Εάν η σελίδα λειτουργεί μετά την απενεργοποίηση του λογισμικού, θα πρέπει να απενεργοποιείτε αυτό το λογισμικό, όταν χρησιμοποιείτε ασφαλείς ιστοτόπους.&lt;/p&gt;
+ &lt;p&gt;Όταν τελειώσετε, μην ξεχάσετε να ενεργοποιήσετε ξανά το πρόγραμμα προστασίας από ιούς.&lt;/p&gt;
+ &lt;h4&gt;Βήμα 5: Λάβετε περισσότερη βοήθεια&lt;/h4&gt;
+ &lt;p&gt;Εάν εξακολουθείτε να βλέπετε το σφάλμα, επικοινωνήστε με τον κάτοχο του ιστοτόπου.&lt;/p&gt;
+ &lt;h3&gt;"Σύνδεση σε δίκτυο"&lt;/h3&gt;
+ &lt;p&gt;Αυτό το σφάλμα παρουσιάζεται, εάν χρησιμοποιείτε μια πύλη Wi-Fi στην οποία πρέπει να συνδέεστε, για να μπορείτε να περιηγείστε στο διαδίκτυο.&lt;/p&gt;
+ &lt;p&gt;Για να διορθώσετε το σφάλμα, πατήστε &lt;strong&gt;Σύνδεση&lt;/strong&gt; στη σελίδα που προσπαθείτε να ανοίξετε.&lt;/p&gt;
+ &lt;h3&gt;"Το ρολόι σας πάει πίσω" ή "Το ρολόι σας πάει μπροστά" ή "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Αυτό το σφάλμα θα παρουσιαστεί, εάν η ημερομηνία και η ώρα του υπολογιστή ή της κινητής συσκευής σας είναι ανακριβείς.&lt;/p&gt;
+ &lt;p&gt;Για να διορθώσετε το σφάλμα, ανοίξτε το ρολόι της συσκευής. Βεβαιωθείτε ότι η ώρα και η ημερομηνία είναι σωστές.&lt;/p&gt;
+ &lt;h3&gt;"Κάποιο λογισμικό στον υπολογιστή σας παρεμποδίζει την ασφαλή σύνδεση του Chrome στον ιστό" (μόνο για υπολογιστές με Windows)&lt;/h3&gt;
+ &lt;p&gt;Αυτό το σφάλμα θα εμφανιστεί, εάν έχετε το λογισμικό Superfish στον υπολογιστή σας με Windows.&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;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;
+ &lt;li&gt;Πατήστε &lt;strong&gt;Εφαρμογή&lt;/strong&gt; και έπειτα πατήστε &lt;strong&gt;OK&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="3615877443314183785">Εισαγάγετε μια έγκυρη ημερομηνία λήξης</translation>
<translation id="36224234498066874">Διαγραφή δεδομένων περιήγησης…</translation>
<translation id="362276910939193118">Εμφάνιση πλήρους ιστορικού</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Θέλετε να αποθηκεύσετε αυτήν την κάρτα στον Λογαριασμό σας Google και σε αυτήν τη συσκευή;</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Λήγει <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Από τον ιστότοπο <ph name="SITE" /></translation>
<translation id="382518646247711829">Εάν χρησιμοποιείτε διακομιστή μεσολάβησης…</translation>
<translation id="3828924085048779000">Δεν επιτρέπεται να είναι κενή η φράση πρόσβασης.</translation>
<translation id="385051799172605136">Πίσω</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">Αναγνωριστικό μεταφορτωμένης αναφοράς σφαλμάτων <ph name="CRASH_ID" /> (Αναγνωριστικό τοπικού σφάλματος: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Αυτός ο διακομιστής δεν μπορεί να αποδείξει ότι είναι ο τομέας <ph name="DOMAIN" />. Το πιστοποιητικό ασφαλείας δεν προσδιορίζει Εναλλακτικά ονόματα θέματος. Αυτό μπορεί να οφείλεται σε εσφαλμένη διαμόρφωση ή σε κάποιον τρίτο που επιτίθεται στη σύνδεσή σας.</translation>
<translation id="3949601375789751990">Το ιστορικό περιήγησής σας εμφανίζεται εδώ</translation>
+<translation id="3950820424414687140">Σύνδεση</translation>
<translation id="3963721102035795474">Λειτουργία αναγνώστη</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Κανένα}=1{Από 1 ιστότοπο }other{Από # ιστοτόπους }}</translation>
<translation id="397105322502079400">Υπολογισμός…</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Ο σειριακός αριθμός της συσκευής δεν είναι έγκυρος</translation>
<translation id="410351446219883937">Αυτόματη αναπαραγωγή</translation>
<translation id="4103763322291513355">Επισκεφτείτε την &lt;strong&gt;chrome://policy&lt;/strong&gt; για να δείτε τη λίστα των ανεπιθύμητων διευθύνσεων URL και άλλες πολιτικές που έχουν τεθεί σε εφαρμογή από το διαχειριστή του συστήματός σας.</translation>
+<translation id="4110652170750985508">Έλεγχος πληρωμής</translation>
<translation id="4116663294526079822">Να επιτρέπεται πάντα σε αυτόν τον ιστότοπο</translation>
<translation id="4117700440116928470">Το εύρος της πολιτικής δεν υποστηρίζεται.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 ακόμα}other{# ακόμα}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Χωρίς όνομα χρήστη)</translation>
<translation id="4275830172053184480">Επανεκκινήστε τη συσκευή σας</translation>
<translation id="4280429058323657511">, λήξη <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Σύνδεση</translation>
<translation id="4312866146174492540">Αποκλεισμός (προεπιλογή)</translation>
<translation id="4325863107915753736">Αποτυχία εύρεσης άρθρου</translation>
<translation id="4326324639298822553">Ελέγξτε την ημερομηνία λήξης σας και δοκιμάστε ξανά</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Οι κάρτες και οι διευθύνσεις προέρχονται από το Chrome και τον Λογαριασμό σας Google (<ph name="ACCOUNT_EMAIL" />). Μπορείτε να τις διαχειριστείτε στις <ph name="BEGIN_LINK" />Ρυθμίσεις<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Λεπτομέρειες</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Από μια Ενσωματωμένη Σελίδα στον Ιστότοπο <ph name="SITE" /></translation>
<translation id="4558551763791394412">Δοκιμάστε να απενεργοποιήσετε τις επεκτάσεις σας.</translation>
<translation id="457875822857220463">Παράδοση</translation>
<translation id="4582800630050655161">Μπορεί να χάσετε την πρόσβαση στον Λογαριασμό σας Google ή να πέσετε θύμα κλοπής στοιχείων ταυτότητας. Το Chromium συνιστά να αλλάξετε τον κωδικό πρόσβασής σας τώρα.</translation>
<translation id="4587425331216688090">Κατάργηση διεύθυνσης από το Chrome;</translation>
<translation id="4592951414987517459">Η σύνδεσή σας στο <ph name="DOMAIN" /> κρυπτογραφείται χρησιμοποιώντας ένα σύγχρονο πρόγραμμα κρυπτογράφησης.</translation>
<translation id="4594403342090139922">&amp;Αναίρεση διαγραφής</translation>
-<translation id="4611292653554630842">Σύνδεση</translation>
<translation id="4619615317237390068">Καρτέλες από άλλες συσκευές</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Ο διακομιστής δεν κατάφερε να αποδείξει ότι είναι <ph name="DOMAIN" />. Το πιστοποιητικό ασφαλείας του περιέχει σφάλματα. Αυτό μπορεί να οφείλεται σε λανθασμένη ρύθμιση ή σε κάποιον τρίτο που επιτίθεται στη σύνδεσή σας.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Η σύνδεσή σας διακόπηκε</translation>
<translation id="471880041731876836">Δεν έχετε άδεια να επισκεφτείτε αυτόν τον ιστότοπο</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Να εκτελέσετε τον Διαγνωστικό έλεγχο δικτύου των Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Η πληρωμή σας</translation>
<translation id="4726672564094551039">Επανάληψη φόρτωσης πολιτικών</translation>
<translation id="4728558894243024398">Πλατφόρμα</translation>
<translation id="4736825316280949806">Επανεκκινήστε το Chromium</translation>
-<translation id="4737498291095696011">Από Αυτήν τη Σελίδα</translation>
<translation id="4744603770635761495">Διαδρομή εκτελέσιμου</translation>
<translation id="4749685221585524849">Τελευταία χρήση <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Οι πληροφορίες σας (για παράδειγμα, οι κωδικοί πρόσβασης ή οι αριθμοί πιστωτικών καρτών) είναι ιδιωτικές κατά την αποστολή σε αυτόν τον ιστότοπο.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Προβολή</translation>
<translation id="4854362297993841467">Αυτός ο τρόπος παράδοσης δεν είναι διαθέσιμος. Δοκιμάστε έναν άλλο τρόπο.</translation>
<translation id="4858792381671956233">Ρώτησες τους γονείς σου εάν σου επιτρέπουν να επισκεφτείς αυτόν τον ιστότοπο</translation>
-<translation id="4871132632506079383">Από μια ενσωματωμένη σελίδα στον ιστότοπο <ph name="SITE" /></translation>
<translation id="4880827082731008257">Αναζήτηση ιστορικού</translation>
+<translation id="4881695831933465202">Άνοιγμα</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Απαιτείται έλεγχος ταυτότητας</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{και 1 ακόμη ιστοσελίδα}other{και # ακόμη ιστοσελίδες}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Εισαγάγετε τον κωδικό CVC για την πιστωτική κάρτα <ph name="CREDIT_CARD" />. Μετά την επιβεβαίωση, τα στοιχεία της κάρτας από τον λογαριασμό πληρωμών Google θα κοινοποιηθούν σε αυτόν τον ιστότοπο.</translation>
<translation id="4923417429809017348">Αυτή η σελίδα έχει μεταφραστεί από μια άγνωστη γλώσσας στα <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Πληρωμή</translation>
<translation id="4926049483395192435">Πρέπει να καθοριστεί.</translation>
+<translation id="4926159001844873046">Ο ιστότοπος <ph name="SITE" /> λέει</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Ενέργειες</translation>
<translation id="4958444002117714549">Ανάπτυξη λίστας</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Εάν ενεργοποιηθεί, το Chrome θα αποθηκεύσει ένα αντίγραφο της κάρτας σας σε αυτήν τη συσκευή για ταχύτερη συμπλήρωση φορμών.</translation>
<translation id="5018422839182700155">Δεν είναι δυνατό το άνοιγμα αυτής της σελίδας</translation>
<translation id="5019198164206649151">Η αποθήκευση αντιγράφων ασφαλείας είναι σε κακή κατάσταση</translation>
-<translation id="5020990877659450221">Από αυτήν τη σελίδα</translation>
<translation id="5023310440958281426">Ελέγξτε τις πολιτικές του διαχειριστή</translation>
<translation id="5029568752722684782">Διαγραφή αντιγράφου</translation>
<translation id="503069730517007720">Απαιτείται πιστοποιητικό ρίζας για το λογισμικό "<ph name="SOFTWARE_NAME" />" αλλά δεν έχει εγκατασταθεί. Ο διαχειριστής IT πρέπει να εξετάσει τις οδηγίες διαμόρφωσης για το λογισμικό "<ph name="SOFTWARE_NAME" />", προκειμένου να διορθώσει αυτό το πρόβλημα. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Υπολογιστής</translation>
<translation id="5179510805599951267">Δεν είναι στα <ph name="ORIGINAL_LANGUAGE" />; Αναφέρετε αυτό το σφάλμα</translation>
<translation id="5190835502935405962">Γραμμή σελιδοδεικτών</translation>
+<translation id="5201306358585911203">Μια ενσωματωμένη σελίδα σε αυτήν τη σελίδα λέει</translation>
<translation id="5205222826937269299">Απαιτείται όνομα</translation>
<translation id="5222812217790122047">Απαιτείται διεύθυνση ηλεκτρονικού ταχυδρομείου</translation>
<translation id="522700295135997067">Αυτός ο ιστότοπος μπορεί να έχει υποκλέψει τον κωδικό πρόσβασής σας</translation>
<translation id="5230733896359313003">Διεύθυνση αποστολής</translation>
<translation id="5251803541071282808">Cloud</translation>
-<translation id="5277279256032773186">Χρησιμοποιείτε το Chrome στη δουλειά σας; Οι επιχειρήσεις μπορούν να διαχειρίζονται τις ρυθμίσεις του Chrome για τους εργαζόμενούς τους. Μάθετε περισσότερα</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Ακολουθήστε αυτά τα βήματα, για να απενεργοποιήσετε προσωρινά το λογισμικό, προκειμένου να συνδεθείτε στον ιστό. Θα πρέπει να έχετε προνόμια προγραμματιστή.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Ελέγξτε τη σύνδεση</translation>
<translation id="5610807607761827392">Μπορείτε να διαχειριστείτε τις κάρτες και τις διευθύνσεις στις <ph name="BEGIN_LINK" />Ρυθμίσεις<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Ο κεντρικός υπολογιστής <ph name="HOST_NAME" /> έκανε πάρα πολλές ανακατευθύνσεις.</translation>
-<translation id="5622887735448669177">Θέλετε να φύγετε από αυτόν τον ιστότοπο;</translation>
<translation id="5629630648637658800">Αποτυχία φόρτωσης ρυθμίσεων πολιτικής</translation>
<translation id="5631439013527180824">Μη έγκυρο διακριτικό διαχείρισης συσκευής</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Θέλετε να συμπληρωθούν τα στοιχεία της κάρτας σας;</translation>
<translation id="5803412860119678065">Θέλετε να συμπληρωθούν τα στοιχεία της κάρτας <ph name="CARD_DETAIL" />;</translation>
<translation id="5810442152076338065">Η σύνδεσή σας στο <ph name="DOMAIN" /> κρυπτογραφείται χρησιμοποιώντας ένα απαρχαιωμένο πρόγραμμα κρυπτογράφησης.</translation>
-<translation id="5810928923025889964">Από μια ενσωματωμένη σελίδα σε αυτήν τη σελίδα</translation>
<translation id="5813119285467412249">&amp;Επανάληψη προσθήκης</translation>
<translation id="5838278095973806738">Δεν θα πρέπει να εισαγάγετε ευαίσθητες πληροφορίες σε αυτόν τον ιστότοπο (για παράδειγμα, κωδικούς πρόσβασης ή πιστωτικές κάρτες), επειδή ενδέχεται να υποκλαπούν από εισβολείς.</translation>
<translation id="5866257070973731571">Προσθήκη αριθμού τηλεφώνου</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Προσθήκη περισσότερων πληροφοριών</translation>
<translation id="6447842834002726250">Cookies</translation>
<translation id="6451458296329894277">Επιβεβαίωση νέας υποβολής φόρμας</translation>
-<translation id="6456339708790392414">Η πληρωμή σας</translation>
<translation id="647261751007945333">Πολιτικές συσκευών </translation>
<translation id="6477321094435799029">Το Chrome εντόπισε ασυνήθιστο κώδικα σε αυτήν τη σελίδα και τον απέκλεισε για να προστατεύσει τα προσωπικά σας στοιχεία (για παράδειγμα, κωδικούς πρόσβασης, αριθμούς τηλεφώνου ή πιστωτικές κάρτες).</translation>
<translation id="6489534406876378309">Έναρξη μεταφόρτωσης σφαλμάτων</translation>
<translation id="6507833130742554667">Οι πιστωτικές και οι χρεωστικές κάρτες γίνονται δεκτές.</translation>
<translation id="6508722015517270189">Επανεκκινήστε το Chrome</translation>
-<translation id="6521373090216409766">Θέλετε να φορτώσετε ξανά αυτόν τον ιστότοπο;</translation>
<translation id="6529602333819889595">&amp;Επανάληψη διαγραφής</translation>
<translation id="6534179046333460208">Προτάσεις Φυσικού δικτύου</translation>
<translation id="6550675742724504774">Επιλογές</translation>
-<translation id="6556239504065605927">Ασφαλής σύνδεση</translation>
<translation id="6556915248009097796">Λήξη: <ph name="EXPIRATION_DATE_ABBR" />, τελευταία χρήση <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Ο διαχειριστής σας δεν τον έχει εγκρίνει ακόμα</translation>
<translation id="6569060085658103619">Βλέπετε μια σελίδα επέκτασης</translation>
<translation id="6596325263575161958">Επιλογές κρυπτογράφησης</translation>
+<translation id="6604181099783169992">Αισθητήρες κίνησης ή φωτός</translation>
<translation id="6624427990725312378">Στοιχεία επικοινωνίας</translation>
<translation id="6626291197371920147">Προσθήκη έγκυρου αριθμού κάρτας</translation>
<translation id="6628463337424475685">Αναζήτηση <ph name="ENGINE" /></translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Διαχειριζόμενοι σελιδοδείκτες</translation>
<translation id="7298195798382681320">Προτεινόμενες</translation>
<translation id="7309308571273880165">Αναφορά σφαλμάτων που καταγράφηκε στις <ph name="CRASH_TIME" /> (η μεταφόρτωση ζητήθηκε από τον χρήστη, δεν έχει μεταφορτωθεί ακόμη)</translation>
+<translation id="7320336641823683070">Βοήθεια σύνδεσης</translation>
<translation id="7334320624316649418">&amp;Επανάληψη αναδιάταξης</translation>
<translation id="733923710415886693">Το πιστοποιητικό του διακομιστή δεν αποκαλύφθηκε μέσω της Διαφάνειας πιστοποιητικών.</translation>
<translation id="7353601530677266744">Γραμμή εντολών</translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">Το Wi-Fi που χρησιμοποιείτε (<ph name="WIFI_NAME" />) ενδέχεται να σας ζητήσει να επισκεφτείτε τη σελίδα σύνδεσής του.</translation>
<translation id="785549533363645510">Ωστόσο, δεν είστε αόρατος/η. Με την κατάσταση ανώνυμης περιήγησης δεν μπορείτε να αποκρύψετε τα στοιχεία της περιήγησής σας από τους εργοδότες σας, τον πάροχο υπηρεσιών διαδικτύου που χρησιμοποιείτε ή τους ιστότοπους που επισκέπτεστε.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">Θέλετε να αποχωρήσετε από τον ιστότοπο;</translation>
<translation id="7878176543348854470">Οι χρεωστικές και οι προπληρωμένες κάρτες γίνονται δεκτές.</translation>
<translation id="7878562273885520351">Ο κωδικός πρόσβασής σας μπορεί να έχει παραβιαστεί</translation>
<translation id="7887683347370398519">Ελέγξτε τον κωδικό σας CVC και δοκιμάστε ξανά</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Χρήση καθολικής προεπιλεγμένης ρύθμισης (Ερώτηση)</translation>
<translation id="8042918947222776840">Επιλογή τρόπου παραλαβής</translation>
<translation id="8057711352706143257">Το λογισμικό "<ph name="SOFTWARE_NAME" />" δεν έχει διαμορφωθεί σωστά. Το πρόβλημα διορθώνεται συνήθως με την απεγκατάσταση του λογισμικού "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Να επαναληφθεί η φόρτωση του ιστοτόπου;</translation>
<translation id="8088680233425245692">Αποτυχία προβολής άρθρου.</translation>
<translation id="8091372947890762290">Η ενεργοποίηση στο διακομιστή εκκρεμεί</translation>
<translation id="8094917007353911263">Το δίκτυο που χρησιμοποιείτε ενδέχεται να σας ζητήσει να επισκεφτείτε τη διεύθυνση <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">Η διεύθυνση URL ενημέρωσης για την επέκταση με αναγνωριστικό ID "<ph name="EXTENSION_ID" />", δεν είναι έγκυρη.</translation>
<translation id="8202097416529803614">Σύνοψη παραγγελίας</translation>
<translation id="8205463626947051446">Ο ιστότοπος τείνει να εμφανίζει παρεμβατικές διαφημίσεις</translation>
+<translation id="8211406090763984747">Η σύνδεση είναι ασφαλής</translation>
<translation id="8218327578424803826">Εκχωρημένη τοποθεσία:</translation>
<translation id="8225771182978767009">Το άτομο που ρύθμισε αυτόν τον υπολογιστή επέλεξε να αποκλείσει αυτόν τον ιστότοπο.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Εμφάνιση όλων των αποθηκευμένων κωδικών πρόσβασης</translation>
<translation id="8261506727792406068">Διαγραφή</translation>
<translation id="8267698848189296333">Σύνδεση ως <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Σύνδεση</translation>
<translation id="8288807391153049143">Εμφάνιση πιστοποιητικού</translation>
<translation id="8289355894181816810">Επικοινωνήστε με το διαχειριστή του δικτύου σας εάν δεν είστε βέβαιοι για το τι σημαίνει αυτό.</translation>
<translation id="8293206222192510085">Προσθήκη σελιδοδείκτη</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">Αποδεκτές πιστωτικές και προπληρωμένες κάρτες</translation>
<translation id="8759274551635299824">Αυτή η κάρτα έχει λήξει</translation>
<translation id="8761567432415473239">Η ασφαλής περιήγηση Google <ph name="BEGIN_LINK" />εντόπισε επιβλαβή προγράμματα<ph name="END_LINK" /> πρόσφατα στο <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Συσκευή USB</translation>
<translation id="8790007591277257123">&amp;Επανάληψη διαγραφής</translation>
<translation id="8800988563907321413">Οι προτάσεις σε κοντινή απόσταση εμφανίζονται εδώ</translation>
<translation id="8820817407110198400">Σελιδοδείκτες</translation>
diff --git a/chromium/components/strings/components_strings_en-GB.xtb b/chromium/components/strings/components_strings_en-GB.xtb
index 845218d4320..4543bc8ea0c 100644
--- a/chromium/components/strings/components_strings_en-GB.xtb
+++ b/chromium/components/strings/components_strings_en-GB.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Print...</translation>
<translation id="1181037720776840403">Remove</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Automatically report<ph name="END_WHITEPAPER_LINK" /> details of possible security incidents to Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Payment Not Completed</translation>
<translation id="1201402288615127009">Next</translation>
<translation id="1201895884277373915">More from this site</translation>
<translation id="1206967143813997005">Bad initial signature</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Crash report captured on <ph name="CRASH_TIME" /> (not yet uploaded or ignored)</translation>
<translation id="1270502636509132238">Pickup Method</translation>
<translation id="1285320974508926690">Never translate this site</translation>
+<translation id="1294154142200295408">Command-line variations</translation>
<translation id="129553762522093515">Recently closed</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Try clearing your cookies<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Your activity <ph name="BEGIN_EMPHASIS" />might still be visible<ph name="END_EMPHASIS" /> to:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Accepted credit and debit cards</translation>
<translation id="1519264250979466059">Build Date</translation>
<translation id="1527263332363067270">Waiting for connection…</translation>
+<translation id="1532118530259321453">This page says</translation>
<translation id="153384715582417236">That’s all for now</translation>
<translation id="154408704832528245">Choose delivery address</translation>
<translation id="1549470594296187301">JavaScript must be enabled to use this feature.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Checking the proxy and the firewall<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">ZIP code</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggestion}other{# suggestions}}</translation>
-<translation id="2065985942032347596">Authentication Required</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="2091887806945687916">Sound</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Cancel payment</translation>
<translation id="2147827593068025794">Background Sync</translation>
<translation id="2148613324460538318">Add Card</translation>
-<translation id="2149973817440762519">Edit Bookmark</translation>
<translation id="2154054054215849342">Sync is not available for your domain</translation>
<translation id="2154484045852737596">Edit card</translation>
<translation id="2166049586286450108">Full Admin Access</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Choose pickup address</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Remove selected items</translation>
-<translation id="2744590937989388266">From an embedded page on this page</translation>
<translation id="277133753123645258">Delivery method</translation>
<translation id="277499241957683684">Missing device record</translation>
<translation id="2784949926578158345">The connection was reset.</translation>
<translation id="2788784517760473862">Accepted credit cards</translation>
<translation id="2794233252405721443">Site blocked</translation>
-<translation id="2795286477369100655">Do You Want to Leave This Site?</translation>
<translation id="2799020568854403057">The site ahead contains harmful apps</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="2824775600643448204">Address and search bar</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">List entry "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automatically blocked</translation>
<translation id="3024663005179499861">Wrong policy type</translation>
-<translation id="3032412215588512954">Do you want to reload this site?</translation>
<translation id="3037605927509011580">Aw, Snap!</translation>
<translation id="3039538478787849737">Save card to Google?</translation>
<translation id="3041612393474885105">Certificate Information</translation>
@@ -310,6 +306,7 @@
make sure that the proxy server is working. If you don't believe you should
be using a proxy server:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> on <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Cancel payment</translation>
<translation id="3207960819495026254">Bookmarked</translation>
<translation id="3209375525920864198">Please enter a valid session name.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Your manager can unblock it for you</translation>
<translation id="3566021033012934673">Your connection is not private</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">An embedded page at <ph name="SITE" /> says</translation>
<translation id="358285529439630156">Credit and prepaid cards are accepted.</translation>
<translation id="3582930987043644930">Add name</translation>
<translation id="3583757800736429874">&amp;Redo Move</translation>
<translation id="3586931643579894722">Hide details</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Fix connection errors&lt;/h1&gt;
+ &lt;p&gt;If you get an error message when you try to visit a website, try these fixes.&lt;/p&gt;
+ &lt;h2&gt;Fix most connection errors&lt;/h2&gt;
+ &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;
+ &lt;ol&gt;
+ &lt;li&gt;Check the web address for typos.&lt;/li&gt;
+ &lt;li&gt;Make sure that your Internet connection is working normally.&lt;/li&gt;
+ &lt;li&gt;Contact the website owner.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Get help with a specific error message&lt;/h2&gt;
+ &lt;h3&gt;'Your connection is not private' or 'NET::ERR_CERT_AUTHORITY_INVALID' or 'ERR_CERT_COMMON_NAME_INVALID' or 'NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM' or 'SSL certificate error'&lt;/h3&gt;
+ &lt;h4&gt;Step 1: Sign in to the portal&lt;/h4&gt;
+ &lt;p&gt;Wi-Fi networks at places like cafes or airports need you to sign in. To see the sign-in page, visit a page that uses&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Go to any website starting with &lt;code&gt;http://&lt;/code&gt;, such as &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;On the sign-in page that opens, sign in to use the Internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Step 2: Open the page in Incognito mode (computer only)&lt;/h4&gt;
+ &lt;p&gt;Open the page that you were visiting in an Incognito window.&lt;/p&gt;
+ &lt;p&gt;If the page opens, a Chrome extension isn't working correctly. To fix the error, turn off the extension.&lt;/p&gt;
+ &lt;h4&gt;Step 3: Update your operating system&lt;/h4&gt;
+ &lt;p&gt;Make sure that your device is up to date.&lt;/p&gt;
+ &lt;h4&gt;Step 4: Temporarily turn off your antivirus&lt;/h4&gt;
+ &lt;p&gt;You'll see this error if you have antivirus software that provides 'HTTPS protection' or 'HTTPS scanning'. The antivirus is preventing Chrome from providing security.&lt;/p&gt;
+ &lt;p&gt;To fix the problem, turn off your antivirus software. If the page works after turning off the software, turn off this software when you use secure sites.&lt;/p&gt;
+ &lt;p&gt;Remember to turn your antivirus program back on when you've finished.&lt;/p&gt;
+ &lt;h4&gt;Step 5: Get extra help&lt;/h4&gt;
+ &lt;p&gt;If you still see the error, contact the website owner.&lt;/p&gt;
+ &lt;h3&gt;'Connect to network'&lt;/h3&gt;
+ &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;
+ &lt;h3&gt;'Your clock is behind' or 'Your clock is ahead' or 'NET::ERR_CERT_DATE_INVALID'&lt;/h3&gt;
+ &lt;p&gt;You'll see this error if your computer or mobile device's date and time are inaccurate.&lt;/p&gt;
+ &lt;p&gt;To fix the error, open your device's clock. Make sure that the time and date are correct.&lt;/p&gt;
+ &lt;h3&gt;'Software on your computer is stopping Chrome from safely connecting to the web' (Windows computers only)&lt;/h3&gt;
+ &lt;p&gt;You'll see this error if you have Superfish software on your Windows computer.&lt;/p&gt;
+ &lt;p&gt;Follow these steps to temporarily disable the software so that you can get on the web. You'll need administrator privileges.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Click &lt;strong&gt;Start&lt;/strong&gt;, then search for and select &lt;strong&gt;'View local services'&lt;/strong&gt;
+ &lt;li&gt;Select &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Under &lt;strong&gt;Startup type&lt;/strong&gt;, select &lt;strong&gt;Disabled&lt;/strong&gt;
+ &lt;li&gt;Under &lt;strong&gt;Service status&lt;/strong&gt;, click &lt;strong&gt;Stop&lt;/strong&gt;
+ &lt;li&gt;Click &lt;strong&gt;Apply&lt;/strong&gt;, then click &lt;strong&gt;OK&lt;/strong&gt;
+ &lt;li&gt;Visit the &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome help centre&lt;/a&gt; to learn how to permanently remove the software from your computer
+ &lt;/ol&gt;</translation>
<translation id="3615877443314183785">Enter a valid expiry date</translation>
<translation id="36224234498066874">Clear Browsing Data...</translation>
<translation id="362276910939193118">Show Full History</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Do you want to save this card to your Google account and on this device?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Expires <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">From <ph name="SITE" /></translation>
<translation id="382518646247711829">If you use a proxy server...</translation>
<translation id="3828924085048779000">Empty passphrase is not allowed.</translation>
<translation id="385051799172605136">Back</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">Uploaded Crash Report ID <ph name="CRASH_ID" /> (Local Crash ID: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">This server could not prove that it is <ph name="DOMAIN" />; its security certificate does not specify Subject Alternative Names. This may be caused by a misconfiguration or an attacker intercepting your connection.</translation>
<translation id="3949601375789751990">Your browsing history appears here</translation>
+<translation id="3950820424414687140">Sign in</translation>
<translation id="3963721102035795474">Reader Mode</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{None}=1{From 1 site }other{From # sites }}</translation>
<translation id="397105322502079400">Calculating...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Device serial number is invalid</translation>
<translation id="410351446219883937">Autoplay</translation>
<translation id="4103763322291513355">Visit &lt;strong&gt;chrome://policy&lt;/strong&gt; to see the list of blacklisted URLs and other policies enforced by your system administrator.</translation>
+<translation id="4110652170750985508">Review your payment</translation>
<translation id="4116663294526079822">Always allow on this site</translation>
<translation id="4117700440116928470">Policy scope is not supported.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 other}other{# others}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(No username)</translation>
<translation id="4275830172053184480">Restart your device</translation>
<translation id="4280429058323657511">, exp <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Log In</translation>
<translation id="4312866146174492540">Block (default)</translation>
<translation id="4325863107915753736">Failed to find article</translation>
<translation id="4326324639298822553">Check your expiry date and try again</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Cards and addresses are from Chrome and your Google account (<ph name="ACCOUNT_EMAIL" />). You can manage them in <ph name="BEGIN_LINK" />Settings<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Details</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">From an embedded page at <ph name="SITE" /></translation>
<translation id="4558551763791394412">Try disabling your extensions.</translation>
<translation id="457875822857220463">Delivery</translation>
<translation id="4582800630050655161">You could lose access to your Google Account or experience identity theft. Chromium recommends that you change your password now.</translation>
<translation id="4587425331216688090">Remove address from Chrome?</translation>
<translation id="4592951414987517459">Your connection to <ph name="DOMAIN" /> is encrypted using a modern cipher suite.</translation>
<translation id="4594403342090139922">&amp;Undo Delete</translation>
-<translation id="4611292653554630842">Log in</translation>
<translation id="4619615317237390068">Tabs from other devices</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">This server could not prove that it is <ph name="DOMAIN" />; its security certificate contains errors. This may be caused by a misconfiguration or an attacker intercepting your connection.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Your connection was interrupted</translation>
<translation id="471880041731876836">You don't have permission to visit this site</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Running Windows Network Diagnostics<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Your payment</translation>
<translation id="4726672564094551039">Reload policies</translation>
<translation id="4728558894243024398">Platform</translation>
<translation id="4736825316280949806">Restart Chromium</translation>
-<translation id="4737498291095696011">From this page</translation>
<translation id="4744603770635761495">Executable Path</translation>
<translation id="4749685221585524849">Last used <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Your information (for example, passwords or credit card numbers) is private when it is sent to this site.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">View</translation>
<translation id="4854362297993841467">This delivery method isn’t available. Try a different method.</translation>
<translation id="4858792381671956233">You asked your parents if it's OK to visit this site</translation>
-<translation id="4871132632506079383">From an embedded page at <ph name="SITE" /></translation>
<translation id="4880827082731008257">Search history</translation>
+<translation id="4881695831933465202">Open</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Authentication required</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{and 1 more web page}other{and # more web pages}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
-<translation id="4919958102839282947">Enter the CVC for <ph name="CREDIT_CARD" />. After you confirm, card details from your Google payments account will be shared with this site.</translation>
+<translation id="4919958102839282947">Enter the CVC for <ph name="CREDIT_CARD" />. After you confirm, card details from your Google Payments account will be shared with this site.</translation>
<translation id="4923417429809017348">This page has been translated from an unknown language into <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Payment</translation>
<translation id="4926049483395192435">Must be specified.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> says</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Actions</translation>
<translation id="4958444002117714549">Expand list</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">If enabled, Chrome will store a copy of your card on this device for faster form filling.</translation>
<translation id="5018422839182700155">Can't open this page</translation>
<translation id="5019198164206649151">Backing store in bad state</translation>
-<translation id="5020990877659450221">From this page</translation>
<translation id="5023310440958281426">Check your administrator's policies</translation>
<translation id="5029568752722684782">Clear copy</translation>
<translation id="503069730517007720">A root certificate for '<ph name="SOFTWARE_NAME" />' is required but isn’t installed. Your IT administrator should look at configuration instructions for '<ph name="SOFTWARE_NAME" />' to fix this problem. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -557,7 +595,7 @@
<translation id="5094747076828555589">This server could not prove that it is <ph name="DOMAIN" />; its security certificate is not trusted by Chromium. This may be caused by a misconfiguration or an attacker intercepting your connection.</translation>
<translation id="5095208057601539847">Province</translation>
<translation id="5115563688576182185">(64-bit)</translation>
-<translation id="5121084798328133320">After you confirm, card details from your Google payments account will be shared with this site.</translation>
+<translation id="5121084798328133320">After you confirm, card details from your Google Payments account will be shared with this site.</translation>
<translation id="5128122789703661928">The session with this name is not valid for deletion.</translation>
<translation id="5141240743006678641">Encrypt synced passwords with your Google credentials</translation>
<translation id="5145883236150621069">Error code present in the policy response</translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Machine</translation>
<translation id="5179510805599951267">Not in <ph name="ORIGINAL_LANGUAGE" />? Report this error</translation>
<translation id="5190835502935405962">Bookmarks Bar</translation>
+<translation id="5201306358585911203">An embedded page on this page says</translation>
<translation id="5205222826937269299">Name required</translation>
<translation id="5222812217790122047">Email (required)</translation>
<translation id="522700295135997067">This site may have just stolen your password</translation>
<translation id="5230733896359313003">Delivery Address</translation>
<translation id="5251803541071282808">Cloud</translation>
-<translation id="5277279256032773186">Using Chrome at work? Businesses can manage Chrome settings for their employees. Find out more</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Follow these steps to temporarily disable the software so that you can get on the web. You'll need administrator privileges.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Checking the connection</translation>
<translation id="5610807607761827392">You can manage cards and addresses in <ph name="BEGIN_LINK" />Settings<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> redirected you too many times.</translation>
-<translation id="5622887735448669177">Do you want to leave this site?</translation>
<translation id="5629630648637658800">Failed to load policy settings</translation>
<translation id="5631439013527180824">Invalid device management token</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Do you want to fill in your card info?</translation>
<translation id="5803412860119678065">Do you want to fill in your <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Your connection to <ph name="DOMAIN" /> is encrypted using an obsolete cipher suite.</translation>
-<translation id="5810928923025889964">From an embedded page on this page</translation>
<translation id="5813119285467412249">&amp;Redo Add</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>
<translation id="5866257070973731571">Add Phone Number</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Add more information</translation>
<translation id="6447842834002726250">Cookies</translation>
<translation id="6451458296329894277">Confirm Form Resubmission</translation>
-<translation id="6456339708790392414">Your Payment</translation>
<translation id="647261751007945333">Device policies</translation>
<translation id="6477321094435799029">Chrome detected unusual code on this page and blocked it to protect your personal information (for example, passwords, phone numbers and credit cards).</translation>
<translation id="6489534406876378309">Start uploading crashes</translation>
<translation id="6507833130742554667">Credit and debit cards are accepted.</translation>
<translation id="6508722015517270189">Restart Chrome</translation>
-<translation id="6521373090216409766">Do You Want to Reload This Site?</translation>
<translation id="6529602333819889595">&amp;Redo Delete</translation>
<translation id="6534179046333460208">Physical Web suggestions</translation>
<translation id="6550675742724504774">Options</translation>
-<translation id="6556239504065605927">Secure connection</translation>
<translation id="6556915248009097796">Exp: <ph name="EXPIRATION_DATE_ABBR" />, last used <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Your manager hasn't approved it yet</translation>
<translation id="6569060085658103619">You're viewing an extension page</translation>
<translation id="6596325263575161958">Encryption options</translation>
+<translation id="6604181099783169992">Motion or light sensors</translation>
<translation id="6624427990725312378">Contact Info</translation>
<translation id="6626291197371920147">Add valid card number</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Search</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Managed Bookmarks</translation>
<translation id="7298195798382681320">Recommended</translation>
<translation id="7309308571273880165">Crash report captured on <ph name="CRASH_TIME" /> (upload requested by user, not yet uploaded)</translation>
+<translation id="7320336641823683070">Connection Help</translation>
<translation id="7334320624316649418">&amp;Redo reorder</translation>
<translation id="733923710415886693">The server's certificate was not disclosed via Certificate Transparency.</translation>
<translation id="7353601530677266744">Command Line</translation>
@@ -900,6 +935,7 @@
<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="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="7862185352068345852">Leave site?</translation>
<translation id="7878176543348854470">Debit and prepaid cards are accepted.</translation>
<translation id="7878562273885520351">Your password may be compromised</translation>
<translation id="7887683347370398519">Check your CVC and try again</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Use global default (Ask)</translation>
<translation id="8042918947222776840">Choose pickup method</translation>
<translation id="8057711352706143257">'<ph name="SOFTWARE_NAME" />' isn’t configured correctly. Uninstalling '<ph name="SOFTWARE_NAME" />' usually fixes the problem. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Reload site?</translation>
<translation id="8088680233425245692">Failed to view article.</translation>
<translation id="8091372947890762290">Activation is pending on the server</translation>
<translation id="8094917007353911263">The network that you are using may require you to visit <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">Invalid update URL for extension with ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Order summary</translation>
<translation id="8205463626947051446">Site tends to show intrusive ads</translation>
+<translation id="8211406090763984747">Connection is secure</translation>
<translation id="8218327578424803826">Assigned Location:</translation>
<translation id="8225771182978767009">The person who set up this computer has chosen to block this site.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Show All Saved Passwords</translation>
<translation id="8261506727792406068">Delete</translation>
<translation id="8267698848189296333">Signing in as <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Sign In</translation>
<translation id="8288807391153049143">Show certificate</translation>
<translation id="8289355894181816810">Contact your network administrator if you're not sure what this means.</translation>
<translation id="8293206222192510085">Add Bookmark</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Accepted Credit and Prepaid Cards</translation>
<translation id="8759274551635299824">This card has expired</translation>
<translation id="8761567432415473239">Google Safe Browsing recently <ph name="BEGIN_LINK" />found harmful programs<ph name="END_LINK" /> on <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">USB device</translation>
<translation id="8790007591277257123">&amp;Redo delete</translation>
<translation id="8800988563907321413">Your nearby suggestions appear here</translation>
<translation id="8820817407110198400">Bookmarks</translation>
@@ -1015,7 +1055,7 @@
<translation id="8932102934695377596">Your clock is behind</translation>
<translation id="893332455753468063">Add Name</translation>
<translation id="8938939909778640821">Accepted credit and prepaid cards</translation>
-<translation id="8952525071319348207">Enter the expiry date and CVC for <ph name="CREDIT_CARD" /> to update your card details. After you confirm, card details from your Google payments account will be shared with this site.</translation>
+<translation id="8952525071319348207">Enter the expiry date and CVC for <ph name="CREDIT_CARD" /> to update your card details. After you confirm, card details from your Google Payments account will be shared with this site.</translation>
<translation id="8957210676456822347">Captive Portal Authorisation</translation>
<translation id="8971063699422889582">Server's certificate has expired.</translation>
<translation id="8978053250194585037">Google Safe Browsing recently <ph name="BEGIN_LINK" />detected phishing<ph name="END_LINK" /> on <ph name="SITE" />. Phishing sites pretend to be other websites to trick you.</translation>
diff --git a/chromium/components/strings/components_strings_es-419.xtb b/chromium/components/strings/components_strings_es-419.xtb
index dd67cecc61b..d762d59abe0 100644
--- a/chromium/components/strings/components_strings_es-419.xtb
+++ b/chromium/components/strings/components_strings_es-419.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">Im&amp;primir...</translation>
<translation id="1181037720776840403">Eliminar</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Informar automáticamente<ph name="END_WHITEPAPER_LINK" /> los detalles de posibles incidentes de seguridad a Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">No se completó el pago</translation>
<translation id="1201402288615127009">Siguiente</translation>
<translation id="1201895884277373915">Más sobre este sitio</translation>
<translation id="1206967143813997005">La firma inicial no es válida</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">El informe de fallos se capturó el <ph name="CRASH_TIME" /> (todavía no se cargó ni se ignoró)</translation>
<translation id="1270502636509132238">Método de retiro</translation>
<translation id="1285320974508926690">Nunca traducir este sitio</translation>
+<translation id="1294154142200295408">Variaciones en la línea de comandos</translation>
<translation id="129553762522093515">Cerrado recientemente</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Intenta borrar tus cookies<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Es posible que tu actividad <ph name="BEGIN_EMPHASIS" />todavía sea visible<ph name="END_EMPHASIS" /> para:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Tarjetas de débito y crédito aceptadas</translation>
<translation id="1519264250979466059">Fecha de compilación</translation>
<translation id="1527263332363067270">Esperando conexión…</translation>
+<translation id="1532118530259321453">Esta página dice</translation>
<translation id="153384715582417236">Eso es todo por ahora</translation>
<translation id="154408704832528245">Elegir dirección de entrega</translation>
<translation id="1549470594296187301">JavaScript debe estar habilitado para usar esta función.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Comprobar el proxy y el firewall<ph name="END_LINK" />.</translation>
<translation id="2053553514270667976">Código Postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugerencia}other{# sugerencias}}</translation>
-<translation id="2065985942032347596">Se requiere autenticación</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="2091887806945687916">Sonido</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Cancelar pago</translation>
<translation id="2147827593068025794">Sincronización en segundo plano</translation>
<translation id="2148613324460538318">Agregar tarjeta</translation>
-<translation id="2149973817440762519">Editar marcador</translation>
<translation id="2154054054215849342">El servicio de sincronización no está disponible para tu dominio</translation>
<translation id="2154484045852737596">Editar tarjeta</translation>
<translation id="2166049586286450108">Acceso de administrador completo</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Elegir dirección de retiro</translation>
<translation id="2740531572673183784">Aceptar</translation>
<translation id="2742870351467570537">Eliminar elementos seleccionados</translation>
-<translation id="2744590937989388266">Desde una página incorporada en esta página</translation>
<translation id="277133753123645258">Método de envío</translation>
<translation id="277499241957683684">Falta un registro de dispositivo.</translation>
<translation id="2784949926578158345">Se ha restablecido la conexión.</translation>
<translation id="2788784517760473862">Tarjetas de crédito aceptadas</translation>
<translation id="2794233252405721443">Sitio bloqueado</translation>
-<translation id="2795286477369100655">¿Quieres salir de este sitio?</translation>
<translation id="2799020568854403057">El siguiente sitio incluye apps dañinas</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="2824775600643448204">Barra de direcciones y de búsqueda</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Entrada de lista "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Bloqueado de forma automática</translation>
<translation id="3024663005179499861">Tipo de política incorrecto</translation>
-<translation id="3032412215588512954">¿Deseas volver a cargar este sitio?</translation>
<translation id="3037605927509011580">¡Oh, no!</translation>
<translation id="3039538478787849737">¿Quieres guardar la tarjeta en Google?</translation>
<translation id="3041612393474885105">Información sobre el certificado</translation>
@@ -311,6 +307,7 @@
servidor proxy esté funcionando. Si consideras
que no necesitas usar un servidor proxy:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> en <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Cancelar pago</translation>
<translation id="3207960819495026254">Agregada a favoritos</translation>
<translation id="3209375525920864198">Ingresa un nombre de sesión válido.</translation>
@@ -368,11 +365,57 @@
<translation id="3556433843310711081">Tu administrador puede desbloquearlo por ti</translation>
<translation id="3566021033012934673">La conexión no es privada</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Una página incorporada en <ph name="SITE" /> dice</translation>
<translation id="358285529439630156">Se aceptan tarjetas de crédito y prepago.</translation>
<translation id="3582930987043644930">Agregar nombre</translation>
<translation id="3583757800736429874">&amp;Rehacer Mover</translation>
<translation id="3586931643579894722">Ocultar detalles</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Corregir errores de conexión&lt;/h1&gt;
+ &lt;p&gt;Si se muestra un mensaje de error cuando intentas visitar un sitio web, prueba estas soluciones.&lt;/p&gt;
+ &lt;h2&gt;Corregir la mayoría de los errores de conexión&lt;/h2&gt;
+ &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;
+ &lt;ol&gt;
+ &lt;li&gt;Verifica que no haya errores de tipeo en la dirección web.&lt;/li&gt;
+ &lt;li&gt;Comprueba que tu conexión a Internet funcione correctamente.&lt;/li&gt;
+ &lt;li&gt;Comunícate con el propietario del sitio web.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Obtener ayuda con un mensaje de error específico&lt;/h2&gt;
+ &lt;h3&gt;"La conexión no es privada", "NET::ERR_CERT_AUTHORITY_INVALID", "ERR_CERT_COMMON_NAME_INVALID", "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" o "Se produjo un error en el certificado SSL"&lt;/h3&gt;
+ &lt;h4&gt;Paso 1: Accede al portal&lt;/h4&gt;
+ &lt;p&gt;Para acceder a las redes Wi‑Fi de sitios como cafeterías o aeropuertos, tienes que iniciar sesión. Para ver la página de acceso, visita una página que comience con &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Visita cualquier sitio web que comience con &lt;code&gt;http://&lt;/code&gt;, como &lt;a href="http://example.com" target="_blank"&gt;http://ejemplo.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;En la página de acceso que se abre, inicia sesión para usar Internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Paso 2: Abre la página en el modo de navegación incógnito (solo en computadoras)&lt;/h4&gt;
+ &lt;p&gt;Abre la página que visitaste en una ventana de incógnito.&lt;/p&gt;
+ &lt;p&gt;Si se abre la página, significa que una extensión de Chrome no está funcionando correctamente. Para solucionar el error, desactiva la extensión.&lt;/p&gt;
+ &lt;h4&gt;Paso 3: Actualiza tu sistema operativo&lt;/h4&gt;
+ &lt;p&gt;Asegúrate de que tu dispositivo esté actualizado.&lt;/p&gt;
+ &lt;h4&gt;Paso 4: Desactiva tu software antivirus de forma temporal&lt;/h4&gt;
+ &lt;p&gt;Este error se muestra si tienes software antivirus con "protección HTTPS" o "análisis HTTPS" que evita que Chrome brinde seguridad.&lt;/p&gt;
+ &lt;p&gt;Para solucionar el problema, desactiva tu software antivirus. Si la página funciona después de esta acción, desactiva este software cuando uses sitios seguros.&lt;/p&gt;
+ &lt;p&gt;Cuando hayas terminado, recuerda volver a activar el programa antivirus.&lt;/p&gt;
+ &lt;h4&gt;Paso 5: Obtén ayuda adicional&lt;/h4&gt;
+ &lt;p&gt;Si todavía se muestra el error, comunícate con el propietario del sitio web.&lt;/p&gt;
+ &lt;h3&gt;"Conectarse a una red"&lt;/h3&gt;
+ &lt;p&gt;Este error se muestra 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 intentas abrir.&lt;/p&gt;
+ &lt;h3&gt;"El reloj está atrasado", "El reloj está adelantado" o "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Este error se muestra si la fecha y hora de tu computadora o dispositivo móvil son incorrectas.&lt;/p&gt;
+ &lt;p&gt;Para solucionar el error, abre el reloj del dispositivo y asegúrate de que la fecha y hora sean correctas.&lt;/p&gt;
+ &lt;h3&gt;"Un software en tu computadora evita que Chrome se conecte de forma segura a la Web" (solo en computadoras con Windows)&lt;/h3&gt;
+ &lt;p&gt;Se muestra este error si tienes el software Superfish en tu computadora con Windows.&lt;/p&gt;
+ &lt;p&gt;Realiza estos pasos para inhabilitar el software de forma temporal para que puedas acceder a la Web. Necesitarás privilegios de administrador.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Haz clic en &lt;strong&gt;Inicio&lt;/strong&gt;; luego, busca &lt;strong&gt;"Ver servicios locales" y selecciónalo&lt;/strong&gt;
+ &lt;li&gt;Selecciona &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;En &lt;strong&gt;Tipo de inicio&lt;/strong&gt;, selecciona &lt;strong&gt;Inhabilitado&lt;/strong&gt;
+ &lt;li&gt;En &lt;strong&gt;Estado del servicio&lt;/strong&gt;, haz clic en &lt;strong&gt;Detener&lt;/strong&gt;
+ &lt;li&gt;Haz clic en &lt;strong&gt;Aplicar&lt;/strong&gt; y, luego, en &lt;strong&gt;Aceptar&lt;/strong&gt;
+ &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="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>
@@ -405,7 +448,6 @@
<translation id="3778403066972421603">¿Deseas guardar esta tarjeta en tu cuenta de Google y en este dispositivo?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Vencimiento: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Desde <ph name="SITE" /></translation>
<translation id="382518646247711829">Si utilizas un servidor proxy...</translation>
<translation id="3828924085048779000">No se permite una frase de contraseña vacía.</translation>
<translation id="385051799172605136">Atrás</translation>
@@ -419,6 +461,7 @@
<translation id="3945915738023014686">ID del informe de fallos <ph name="CRASH_ID" /> cargado (ID de fallo local: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Este servidor no pudo probar que su dominio es <ph name="DOMAIN" />; su certificado de seguridad no especifica la extensión Nombres alternativos del asunto. Es posible que se deba a un error en la configuración o a que haya un atacante que está interceptando tu conexión.</translation>
<translation id="3949601375789751990">Tu historial de navegación aparece aquí</translation>
+<translation id="3950820424414687140">Acceder</translation>
<translation id="3963721102035795474">Modo de lectura</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Ninguno}=1{De 1 sitio }other{De # sitios }}</translation>
<translation id="397105322502079400">Calculando...</translation>
@@ -435,6 +478,7 @@
<translation id="4103249731201008433">El número de serie del dispositivo no es válido.</translation>
<translation id="410351446219883937">Reproducción automática</translation>
<translation id="4103763322291513355">Visita &lt;strong&gt;chrome://policy&lt;/strong&gt; para ver las URL en lista negra y otras políticas que estableció el administrador del sistema.</translation>
+<translation id="4110652170750985508">Revisar el pago</translation>
<translation id="4116663294526079822">Permitir siempre en este sitio</translation>
<translation id="4117700440116928470">No se admite el alcance de la política.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 más}other{# más}}</translation>
@@ -461,7 +505,6 @@
<translation id="4269787794583293679">(Sin nombre de usuario)</translation>
<translation id="4275830172053184480">Reiniciar tu dispositivo</translation>
<translation id="4280429058323657511">, exp <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Acceder</translation>
<translation id="4312866146174492540">Bloquear (predeterminado)</translation>
<translation id="4325863107915753736">No se pudo encontrar el artículo</translation>
<translation id="4326324639298822553">Comprueba la fecha de vencimiento y vuelve a intentarlo</translation>
@@ -483,14 +526,12 @@
<translation id="4515275063822566619">Las tarjetas y direcciones provienen de Chrome y de tu cuenta de Google (<ph name="ACCOUNT_EMAIL" />). Puedes administrar esta información en <ph name="BEGIN_LINK" />Configuración<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Detalles</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Desde una página incorporada en <ph name="SITE" /></translation>
<translation id="4558551763791394412">Intenta inhabilitar tus extensiones.</translation>
<translation id="457875822857220463">Entrega</translation>
<translation id="4582800630050655161">Es posible que hayas perdido el acceso a tu cuenta de Google o sufrido un robo de identidad. Chromium te recomienda que cambies la contraseña ahora.</translation>
<translation id="4587425331216688090">¿Confirmas que quieres quitar la dirección de Chrome?</translation>
<translation id="4592951414987517459">Tu conexión a <ph name="DOMAIN" /> está encriptada con un conjunto de cifrado moderno.</translation>
<translation id="4594403342090139922">&amp;Deshacer Eliminar</translation>
-<translation id="4611292653554630842">Acceder</translation>
<translation id="4619615317237390068">Pestañas de otros dispositivos</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Este servidor no pudo probar que su dominio es <ph name="DOMAIN" />; el certificado de seguridad contiene errores. Es posible que esto se deba a una configuración incorrecta o a que un atacante interceptó la conexión.</translation>
@@ -500,11 +541,9 @@
<translation id="4708268264240856090">Se interrumpió la conexión</translation>
<translation id="471880041731876836">No tienes permiso para visitar este sitio</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Ejecución del Diagnóstico de red de Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Tu pago</translation>
<translation id="4726672564094551039">Volver a cargar políticas</translation>
<translation id="4728558894243024398">Plataforma</translation>
<translation id="4736825316280949806">Reinicia Chromium.</translation>
-<translation id="4737498291095696011">Desde esta página</translation>
<translation id="4744603770635761495">Ruta ejecutable</translation>
<translation id="4749685221585524849">Último uso: <ph name="LAST_USED_MONTH" /></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>
@@ -523,16 +562,16 @@
<translation id="4850886885716139402">Ver</translation>
<translation id="4854362297993841467">Este método de entrega no está disponible. Prueba otro método.</translation>
<translation id="4858792381671956233">Les preguntaste a tus padres si puedes visitar este sitio</translation>
-<translation id="4871132632506079383">Desde una página incorporada en <ph name="SITE" /></translation>
<translation id="4880827082731008257">Buscar historial</translation>
+<translation id="4881695831933465202">Abrir</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Se requiere una autenticación</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{y 1 página web más}other{y # páginas web más}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Ingresa el CVC de la tarjeta <ph name="CREDIT_CARD" />. Después de confirmarla, los datos de tu cuenta en Google Payments se compartirán con este sitio.</translation>
<translation id="4923417429809017348">Esta página ha sido traducida desde un idioma desconocido a <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Pago</translation>
<translation id="4926049483395192435">Debe especificarse un valor.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> dice</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Acciones</translation>
<translation id="4958444002117714549">Mostrar lista</translation>
@@ -541,7 +580,6 @@
<translation id="5002932099480077015">Si se habilita esta opción, Chrome almacenará una copia de la tarjeta en el dispositivo para llenar más rápidamente los formularios.</translation>
<translation id="5018422839182700155">No se puede abrir esta página</translation>
<translation id="5019198164206649151">La memoria auxiliar se encuentra en mal estado.</translation>
-<translation id="5020990877659450221">Desde esta página</translation>
<translation id="5023310440958281426">Revisa las políticas del administrador.</translation>
<translation id="5029568752722684782">Borrar la copia</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>
@@ -567,12 +605,12 @@
<translation id="5172758083709347301">Equipo</translation>
<translation id="5179510805599951267">¿No está en <ph name="ORIGINAL_LANGUAGE" />? Informa este error</translation>
<translation id="5190835502935405962">Barra de favoritos</translation>
+<translation id="5201306358585911203">Una página incorporada en esta página dice</translation>
<translation id="5205222826937269299">Nombre (obligatorio)</translation>
<translation id="5222812217790122047">Correo electrónico (obligatorio)</translation>
<translation id="522700295135997067">Es posible que este sitio haya robado tu contraseña</translation>
<translation id="5230733896359313003">Dirección de envío</translation>
<translation id="5251803541071282808">Nube</translation>
-<translation id="5277279256032773186">¿Usas Chrome en el trabajo? Las empresas pueden administrar la configuración de Chrome para sus empleados. Más información</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Realiza estos pasos para inhabilitar el software de forma temporal, para que puedas acceder a la Web. Necesitarás privilegios de administrador.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -634,7 +672,6 @@
<translation id="5610142619324316209">Comprobar la conexión.</translation>
<translation id="5610807607761827392">Puedes administrar tarjetas y direcciones en <ph name="BEGIN_LINK" />Configuración<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> te redireccionó demasiadas veces.</translation>
-<translation id="5622887735448669177">¿Deseas salir de este sitio?</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="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>
@@ -657,7 +694,6 @@
<translation id="5786044859038896871">¿Deseas llenar los campos con la información de tu tarjeta?</translation>
<translation id="5803412860119678065">¿Deseas llenar los campos con la información de tu tarjeta <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Tu conexión a <ph name="DOMAIN" /> está encriptada con un conjunto de cifrado obsoleto.</translation>
-<translation id="5810928923025889964">Desde una página incorporada en esta página</translation>
<translation id="5813119285467412249">&amp;Rehacer Agregar</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>
<translation id="5866257070973731571">Agregar número de teléfono</translation>
@@ -731,21 +767,19 @@
<translation id="6446608382365791566">Agregar más información</translation>
<translation id="6447842834002726250">Cookies</translation>
<translation id="6451458296329894277">Confirmar reenvío del formulario</translation>
-<translation id="6456339708790392414">Tu pago</translation>
<translation id="647261751007945333">Políticas de dispositivos</translation>
<translation id="6477321094435799029">Chrome detectó código inusual en esta página y la bloqueó para proteger tu información personal (p. ej.: contraseñas, números de teléfono y tarjetas de crédito).</translation>
<translation id="6489534406876378309">Comenzar a cargar fallos</translation>
<translation id="6507833130742554667">Se aceptan tarjetas de crédito y débito.</translation>
<translation id="6508722015517270189">Reinicia Chrome.</translation>
-<translation id="6521373090216409766">¿Quieres volver a cargar este sitio?</translation>
<translation id="6529602333819889595">&amp;Rehacer Eliminar</translation>
<translation id="6534179046333460208">Sugerencias de la Web física</translation>
<translation id="6550675742724504774">Opciones</translation>
-<translation id="6556239504065605927">Conexión segura</translation>
<translation id="6556915248009097796">Venc.: <ph name="EXPIRATION_DATE_ABBR" />, último uso: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Tu administrador aún no lo aprobó</translation>
<translation id="6569060085658103619">Estás viendo la página de una extensión</translation>
<translation id="6596325263575161958">Opciones de encriptación</translation>
+<translation id="6604181099783169992">Sensores de luz o movimiento</translation>
<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>
@@ -817,6 +851,7 @@
<translation id="7275334191706090484">Favoritos administrados</translation>
<translation id="7298195798382681320">Recomendada</translation>
<translation id="7309308571273880165">El informe de fallos se capturó a las <ph name="CRASH_TIME" /> (el usuario solicitó la carga; todavía no se cargó)</translation>
+<translation id="7320336641823683070">Ayuda con la conexión</translation>
<translation id="7334320624316649418">&amp;Rehacer Reorganizar</translation>
<translation id="733923710415886693">El certificado del servidor no se divulgó mediante el Certificado de transparencia.</translation>
<translation id="7353601530677266744">Línea de comandos</translation>
@@ -901,6 +936,7 @@
<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="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="7862185352068345852">¿Deseas abandonar el sitio?</translation>
<translation id="7878176543348854470">Se aceptan tarjetas de débito y prepago.</translation>
<translation id="7878562273885520351">Es posible que tu contraseña esté en peligro</translation>
<translation id="7887683347370398519">Verifica tu CVC y vuelve a intentarlo.</translation>
@@ -923,6 +959,7 @@
<translation id="8041940743680923270">Usar configuración global predeterminada (Preguntar)</translation>
<translation id="8042918947222776840">Elegir método de retiro</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" no se configuró correctamente. Prueba desinstalar "<ph name="SOFTWARE_NAME" />" para corregir el problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">¿Deseas volver a cargar el sitio?</translation>
<translation id="8088680233425245692">Error al visualizar artículo</translation>
<translation id="8091372947890762290">La activación está pendiente en el servidor.</translation>
<translation id="8094917007353911263">Es posible que la red que estás usando requiera que accedas a <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -938,6 +975,7 @@
<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>
<translation id="8205463626947051446">El sitio tiende a mostrar anuncios intrusivos</translation>
+<translation id="8211406090763984747">La conexión es segura</translation>
<translation id="8218327578424803826">Ubicación asignada:</translation>
<translation id="8225771182978767009">La persona que configuró esta computadora decidió bloquear este sitio.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -949,6 +987,7 @@
<translation id="825929999321470778">Mostrar todas las contraseñas guardadas</translation>
<translation id="8261506727792406068">Borrar</translation>
<translation id="8267698848189296333">Acceder como <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Iniciar sesión</translation>
<translation id="8288807391153049143">Mostrar certificado</translation>
<translation id="8289355894181816810">Comunícate con el administrador de red si no entiendes bien lo que significa.</translation>
<translation id="8293206222192510085">Agregar Marcador</translation>
@@ -1000,6 +1039,7 @@
<translation id="874846938927089722">Tarjetas de crédito y prepago aceptadas</translation>
<translation id="8759274551635299824">La tarjeta está vencida</translation>
<translation id="8761567432415473239">La navegación segura de Google <ph name="BEGIN_LINK" />encontró programas peligrosos<ph name="END_LINK" /> recientemente en <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Dispositivo USB</translation>
<translation id="8790007591277257123">&amp;Rehacer Eliminar</translation>
<translation id="8800988563907321413">Las sugerencias de la sección Cercanas aparecen aquí</translation>
<translation id="8820817407110198400">Favoritos</translation>
diff --git a/chromium/components/strings/components_strings_es.xtb b/chromium/components/strings/components_strings_es.xtb
index 2b949f86446..efb44a05fe3 100644
--- a/chromium/components/strings/components_strings_es.xtb
+++ b/chromium/components/strings/components_strings_es.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">Im&amp;primir...</translation>
<translation id="1181037720776840403">Eliminar</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Informar automáticamente<ph name="END_WHITEPAPER_LINK" /> a Google sobre los detalles de posibles incidentes de seguridad. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Pago no completado</translation>
<translation id="1201402288615127009">Siguiente</translation>
<translation id="1201895884277373915">Más entradas de este sitio</translation>
<translation id="1206967143813997005">Firma inicial no válida</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Informe sobre fallos registrado el <ph name="CRASH_TIME" /> (todavía no se ha subido ni ignorado)</translation>
<translation id="1270502636509132238">Método de recogida</translation>
<translation id="1285320974508926690">No traducir nunca este sitio</translation>
+<translation id="1294154142200295408">Variaciones de la línea de comandos</translation>
<translation id="129553762522093515">Cerrado recientemente</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Borrar las cookies<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Es posible que tu actividad <ph name="BEGIN_EMPHASIS" />todavía sea visible<ph name="END_EMPHASIS" /> para:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Tarjetas de débito y crédito aceptadas</translation>
<translation id="1519264250979466059">Fecha de compilación</translation>
<translation id="1527263332363067270">Esperando conexión…</translation>
+<translation id="1532118530259321453">Esta página dice</translation>
<translation id="153384715582417236">Eso es todo por ahora</translation>
<translation id="154408704832528245">Seleccionar dirección de entrega</translation>
<translation id="1549470594296187301">JavaScript debe estar habilitado para utilizar esta función.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Comprobar el proxy y el cortafuegos<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Código postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{Una sugerencia}other{# sugerencias}}</translation>
-<translation id="2065985942032347596">Se requiere autenticación</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="2091887806945687916">Sonido</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Cancelar pago</translation>
<translation id="2147827593068025794">Sincronización en segundo plano</translation>
<translation id="2148613324460538318">Añadir tarjeta</translation>
-<translation id="2149973817440762519">Editar marcador</translation>
<translation id="2154054054215849342">La sincronización no está disponible para tu dominio</translation>
<translation id="2154484045852737596">Editar tarjeta</translation>
<translation id="2166049586286450108">Acceso de administrador completo</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Seleccionar dirección de recogida</translation>
<translation id="2740531572673183784">Aceptar</translation>
<translation id="2742870351467570537">Eliminar elementos seleccionados</translation>
-<translation id="2744590937989388266">De una página insertada en esta</translation>
<translation id="277133753123645258">Método de envío</translation>
<translation id="277499241957683684">Falta un registro de dispositivo.</translation>
<translation id="2784949926578158345">Se ha restablecido la conexión.</translation>
<translation id="2788784517760473862">Tarjetas de crédito aceptadas</translation>
<translation id="2794233252405721443">Sito web bloqueado</translation>
-<translation id="2795286477369100655">¿Quieres salir de este sitio web?</translation>
<translation id="2799020568854403057">El sitio web al que vas a acceder contiene aplicaciones dañinas</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="2824775600643448204">Barra de direcciones y de búsqueda </translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Entrada de lista "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Bloqueado automáticamente</translation>
<translation id="3024663005179499861">Tipo de política incorrecto</translation>
-<translation id="3032412215588512954">¿Quieres volver a cargar este sitio web?</translation>
<translation id="3037605927509011580">¡Oh, no!</translation>
<translation id="3039538478787849737">¿Quieres guardar la tarjeta en Google?</translation>
<translation id="3041612393474885105">Datos del certificado</translation>
@@ -310,6 +306,7 @@
asegurarte de que el servidor proxy funcione correctamente. Si consideras que no necesitas utilizar
un servidor proxy, sigue estas instrucciones:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> de <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Cancelar pago</translation>
<translation id="3207960819495026254">Añadido a marcadores</translation>
<translation id="3209375525920864198">Introduce un nombre de sesión válido.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Tu administrador puede desbloquearlo</translation>
<translation id="3566021033012934673">La conexión no es privada</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Una página insertada en <ph name="SITE" /> dice</translation>
<translation id="358285529439630156">Se aceptan tarjetas prepago y de crédito.</translation>
<translation id="3582930987043644930">Añade un nombre</translation>
<translation id="3583757800736429874">&amp;Rehacer movimiento</translation>
<translation id="3586931643579894722">Ocultar detalles</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Solucionar errores de conexión&lt;/h1&gt;
+ &lt;p&gt;Si aparece un mensaje de error al intentar acceder a un sitio web, prueba estas soluciones.&lt;/p&gt;
+ &lt;h2&gt;Solucionar la mayoría de los errores de conexión&lt;/h2&gt;
+ &lt;p&gt;Si intentas acceder a un sitio web y no se abre, prueba estos pasos para solucionar problemas:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Comprueba si hay algún error ortográfico en la dirección web.&lt;/li&gt;
+ &lt;li&gt;Comprueba que tu conexión a Internet funcione con normalidad.&lt;/li&gt;
+ &lt;li&gt;Ponte en contacto con el propietario del sitio web.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Obtener ayuda con un mensaje de error específico&lt;/h2&gt;
+ &lt;h3&gt;"La conexión no es privada", "NET::ERR_CERT_AUTHORITY_INVALID", "ERR_CERT_COMMON_NAME_INVALID", "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" o "Error de certificado SSL"&lt;/h3&gt;
+ &lt;h4&gt;Paso 1: Inicia sesión en el portal&lt;/h4&gt;
+ &lt;p&gt;Para acceder a las redes Wi‑Fi de sitios como cafeterías o aeropuertos, tienes que iniciar sesión. Para ver la página de inicio de sesión, accede a una página que utilice &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Accede a cualquier sitio web que empiece por &lt;code&gt;http://&lt;/code&gt;, como &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;En la página de inicio de sesión que se abre, inicia sesión para utilizar la conexión a Internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Paso 2: Abre la página en modo incógnito (solo en ordenadores)&lt;/h4&gt;
+ &lt;p&gt;Abre la página que estabas visitando en una ventana de incógnito.&lt;/p&gt;
+ &lt;p&gt;Si la página se abre, significa que una extensión de Chrome no funciona correctamente. Para solucionarlo, desactiva esa extensión.&lt;/p&gt;
+ &lt;h4&gt;Paso 3: Actualiza tu sistema operativo&lt;/h4&gt;
+ &lt;p&gt;Comprueba que tu dispositivo esté actualizado.&lt;/p&gt;
+ &lt;h4&gt;Paso 4: Desactiva tu antivirus temporalmente&lt;/h4&gt;
+ &lt;p&gt;Este error se muestra si tienes software antivirus que ofrezca "protección HTTPS" o "análisis de HTTPS". Este software evita que Chrome proporcione seguridad.&lt;/p&gt;
+ &lt;p&gt;Desactiva el software antivirus para solucionar el problema. Si la página funciona después de desactivar el software antivirus, desactívalo cuando navegues por sitios web seguros.&lt;/p&gt;
+ &lt;p&gt;Recuerda que debes volver a activar el antivirus cuando hayas finalizado.&lt;/p&gt;
+ &lt;h4&gt;Paso 5: Busca más ayuda&lt;/h4&gt;
+ &lt;p&gt;Si el error persiste, ponte en contacto con el propietario del sitio web.&lt;/p&gt;
+ &lt;h3&gt;"Conectarse a la red"&lt;/h3&gt;
+ &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;
+ &lt;h3&gt;"Tu reloj está atrasado", "Tu reloj está adelantado" o "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Este error se muestra si la fecha y la hora de tu ordenador o tu dispositivo móvil no son correctas.&lt;/p&gt;
+ &lt;p&gt;Para solucionar el problema, abre el reloj de tu dispositivo. Comprueba que la fecha y la hora sean correctas.&lt;/p&gt;
+ &lt;h3&gt;"Hay software en tu ordenador que impide que Chrome se conecte a la Web de forma segura" (solo en ordenadores Windows)&lt;/h3&gt;
+ &lt;p&gt;Este error se muestra si tu ordenador Windows tiene software SuperFish.&lt;/p&gt;
+ &lt;p&gt;Sigue estos pasos para inhabilitar temporalmente este software en tu ordenador y acceder a Internet. Necesitarás privilegios de administrador.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Haz clic en&lt;strong&gt;Inicio&lt;/strong&gt;, busca &lt;strong&gt;Ver servicios locales&lt;/strong&gt; y selecciona esta opción.
+ &lt;li&gt;Selecciona &lt;strong&gt;VisualDiscovery&lt;/strong&gt;.
+ &lt;li&gt;En &lt;strong&gt;Tipo de inicio&lt;/strong&gt;, selecciona &lt;strong&gt;Deshabilitado&lt;/strong&gt;.
+ &lt;li&gt;En &lt;strong&gt;Estado del servicio&lt;/strong&gt;, haz clic en &lt;strong&gt;Detener&lt;/strong&gt;.
+ &lt;li&gt;Haz clic en &lt;strong&gt;Aplicar&lt;/strong&gt; y después en &lt;strong&gt;Aceptar&lt;/strong&gt;.
+ &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="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>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">¿Quieres guardar esta tarjeta en tu cuenta de Google y en este dispositivo?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Vencimiento: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">De <ph name="SITE" /></translation>
<translation id="382518646247711829">Si utilizas un servidor proxy...</translation>
<translation id="3828924085048779000">La frase de contraseña no puede estar vacía.</translation>
<translation id="385051799172605136">Atrás</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">ID del informe sobre fallos subido: <ph name="CRASH_ID" /> (ID del fallo local: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Este servidor no ha podido demostrar que es <ph name="DOMAIN" />; su certificado de seguridad no especifica nombres alternativos del sujeto. Este problema puede deberse a una configuración incorrecta o a que un atacante ha interceptado la conexión.</translation>
<translation id="3949601375789751990">Tu historial de navegación aparece aquí</translation>
+<translation id="3950820424414687140">Iniciar sesión</translation>
<translation id="3963721102035795474">Modo de lectura</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Ninguno}=1{De 1 sitio web }other{De # sitios web }}</translation>
<translation id="397105322502079400">Calculando...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">El número de serie del dispositivo no es válido.</translation>
<translation id="410351446219883937">Reproducción automática</translation>
<translation id="4103763322291513355">Accede a la página &lt;strong&gt;chrome://policy&lt;/strong&gt; para ver la lista de URLs no admitidas y otras políticas establecidas por el administrador del sistema.</translation>
+<translation id="4110652170750985508">Revisa tu pago</translation>
<translation id="4116663294526079822">Permitir siempre en este sitio</translation>
<translation id="4117700440116928470">No se admite el alcance de la política.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{Uno más}other{# más}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Ningún nombre de usuario)</translation>
<translation id="4275830172053184480">Reiniciar tu dispositivo</translation>
<translation id="4280429058323657511">Vcto. <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Iniciar sesión</translation>
<translation id="4312866146174492540">Bloquear (predeterminado)</translation>
<translation id="4325863107915753736">Error al buscar el artículo</translation>
<translation id="4326324639298822553">Consulta la fecha de vencimiento y vuelve a intentarlo</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Las tarjetas y las direcciones proceden de Chrome y tu cuenta de Google (<ph name="ACCOUNT_EMAIL" />). Puedes gestionarlas en <ph name="BEGIN_LINK" />Configuración<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Detalles</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">De una página insertada en <ph name="SITE" /></translation>
<translation id="4558551763791394412">Inhabilita las extensiones.</translation>
<translation id="457875822857220463">Envío</translation>
<translation id="4582800630050655161">Podrías perder el acceso a tu cuenta de Google o experimentar problemas de suplantación de identidad. Chromium te recomienda que cambies la contraseña ahora.</translation>
<translation id="4587425331216688090">¿Eliminar dirección de Chrome?</translation>
<translation id="4592951414987517459">Tu conexión con <ph name="DOMAIN" /> está cifrada con un conjunto de cifrado moderno.</translation>
<translation id="4594403342090139922">&amp;Deshacer eliminación</translation>
-<translation id="4611292653554630842">Iniciar sesión</translation>
<translation id="4619615317237390068">Pestañas de otros dispositivos</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Este servidor no ha podido probar que su dominio es <ph name="DOMAIN" />, su certificado de seguridad contiene errores. El problema puede deberse a una configuración incorrecta o a que un atacante haya interceptado la conexión.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Se ha interrumpido la conexión</translation>
<translation id="471880041731876836">No tienes permiso para acceder a este sitio web</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Ejecutar Diagnósticos de red de Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Tu pago</translation>
<translation id="4726672564094551039">Volver a cargar políticas</translation>
<translation id="4728558894243024398">Plataforma</translation>
<translation id="4736825316280949806">Reinicia Chromium</translation>
-<translation id="4737498291095696011">De esta página</translation>
<translation id="4744603770635761495">Ruta del ejecutable</translation>
<translation id="4749685221585524849">Usada por última vez el <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Tu información (por ejemplo, las contraseñas o los números de las tarjetas de crédito) es privada cuando se envía a este sitio web.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Ver</translation>
<translation id="4854362297993841467">Este método de entrega no está disponible. Selecciona otro.</translation>
<translation id="4858792381671956233">Has solicitado permiso a tus padres para poder acceder a este sitio web</translation>
-<translation id="4871132632506079383">De una página insertada en <ph name="SITE" /></translation>
<translation id="4880827082731008257">Buscar en el historial</translation>
+<translation id="4881695831933465202">Abrir</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" /> y <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Autenticación obligatoria</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{ y 1 página web más}other{ y # páginas web más}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Introduce el CVC de <ph name="CREDIT_CARD" />. Una vez que confirmes esta acción, la información de la tarjeta de tu cuenta de pagos de Google se compartirá con este sitio web.</translation>
<translation id="4923417429809017348">Esta página se ha traducido de un idioma desconocido al <ph name="LANGUAGE_LANGUAGE" />.</translation>
<translation id="4923459931733593730">Pago</translation>
<translation id="4926049483395192435">Se debe especificar un valor.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> dice</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Acciones</translation>
<translation id="4958444002117714549">Expandir lista</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Si se habilita esta opción, Chrome guardará una copia de tu tarjeta en este dispositivo para rellenar la información más rápido.</translation>
<translation id="5018422839182700155">No se puede abrir esta página</translation>
<translation id="5019198164206649151">El almacén secundario está en mal estado.</translation>
-<translation id="5020990877659450221">De esta página</translation>
<translation id="5023310440958281426">Consulta las políticas del administrador</translation>
<translation id="5029568752722684782">Borrar copia</translation>
<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>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Equipo</translation>
<translation id="5179510805599951267">¿Esta página no está escrita en <ph name="ORIGINAL_LANGUAGE" />? Informa de este error.</translation>
<translation id="5190835502935405962">Barra de marcadores</translation>
+<translation id="5201306358585911203">Una página insertada en esta dice</translation>
<translation id="5205222826937269299">Nombre obligatorio</translation>
<translation id="5222812217790122047">Correo electrónico obligatorio</translation>
<translation id="522700295135997067">Es posible que este sitio web te acabe de robar la contraseña</translation>
<translation id="5230733896359313003">Dirección de envío</translation>
<translation id="5251803541071282808">Nube</translation>
-<translation id="5277279256032773186">¿Usas Chrome en el trabajo? Las empresas pueden administrar la configuración de Chrome de sus empleados. Más información</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Sigue estos pasos para inhabilitar temporalmente el software y poder acceder a la Web. Necesitarás privilegios de administrador.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Comprobar la conexión</translation>
<translation id="5610807607761827392">Puedes gestionar las tarjetas y las direcciones en <ph name="BEGIN_LINK" />Configuración<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">La página <ph name="HOST_NAME" /> te ha redirigido demasiadas veces.</translation>
-<translation id="5622887735448669177">¿Quieres salir de este sitio web?</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="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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">¿Quieres rellenar la información de la tarjeta?</translation>
<translation id="5803412860119678065">¿Quieres rellenar la información de <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Tu conexión con <ph name="DOMAIN" /> está cifrada con un conjunto de cifrado obsoleto.</translation>
-<translation id="5810928923025889964">De una página insertada en esta</translation>
<translation id="5813119285467412249">&amp;Rehacer acción de añadir</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>
<translation id="5866257070973731571">Añade un número de teléfono</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Añadir más información</translation>
<translation id="6447842834002726250">Cookies</translation>
<translation id="6451458296329894277">Confirmar reenvío del formulario</translation>
-<translation id="6456339708790392414">Tu pago</translation>
<translation id="647261751007945333">Políticas de dispositivos</translation>
<translation id="6477321094435799029">Chrome ha detectado un código inusual en esta página y lo ha bloqueado para proteger tu información personal (por ejemplo, contraseñas, números de teléfono y tarjetas de crédito).</translation>
<translation id="6489534406876378309">Empezar a subir errores</translation>
<translation id="6507833130742554667">Se aceptan tarjetas de crédito y débito.</translation>
<translation id="6508722015517270189">Reinicia Chrome</translation>
-<translation id="6521373090216409766">¿Quieres volver a cargar este sitio web?</translation>
<translation id="6529602333819889595">&amp;Rehacer eliminación</translation>
<translation id="6534179046333460208">Sugerencias de la Web física</translation>
<translation id="6550675742724504774">Configuración</translation>
-<translation id="6556239504065605927">Conexión segura</translation>
<translation id="6556915248009097796">Fecha de caducidad: <ph name="EXPIRATION_DATE_ABBR" /> (usada por última vez el <ph name="LAST_USED_DATE_NO_DETAIL" />)</translation>
<translation id="6563469144985748109">Tu administrador aún no la ha aprobado</translation>
<translation id="6569060085658103619">Estas viendo la página de una extensión</translation>
<translation id="6596325263575161958">Opciones de cifrado</translation>
+<translation id="6604181099783169992">Sensores de luz o movimiento</translation>
<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>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Marcadores administrados</translation>
<translation id="7298195798382681320">Recomendada</translation>
<translation id="7309308571273880165">Informe sobre fallos registrado el <ph name="CRASH_TIME" /> (el usuario ha solicitado que se suba, pero aún no se ha hecho)</translation>
+<translation id="7320336641823683070">Ayuda de conexión</translation>
<translation id="7334320624316649418">&amp;Rehacer reorganización</translation>
<translation id="733923710415886693">El certificado del servidor no se ha revelado a través de la Transparencia en los Certificados.</translation>
<translation id="7353601530677266744">Línea de comandos</translation>
@@ -900,6 +935,7 @@
<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="785549533363645510">Ten en cuenta que tus acciones no serán totalmente invisibles. El uso del modo 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="7862185352068345852">¿Quieres salir del sitio web?</translation>
<translation id="7878176543348854470">Se aceptan tarjetas prepago y de débito.</translation>
<translation id="7878562273885520351">Es posible que tu contraseña se haya vulnerado</translation>
<translation id="7887683347370398519">Comprueba el código CVC y vuelve a intentarlo</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Utilizar valor predeterminado global (Preguntar)</translation>
<translation id="8042918947222776840">Seleccionar método de recogida</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" no se ha configurado correctamente. Normalmente, el problema se soluciona al desinstalar "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">¿Quieres volver a cargar el sitio web?</translation>
<translation id="8088680233425245692">Se ha producido un error al ver el artículo.</translation>
<translation id="8091372947890762290">La activación está pendiente en el servidor.</translation>
<translation id="8094917007353911263">La red que estás utilizando puede requerir que accedas a la página <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<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>
<translation id="8205463626947051446">El sitio web suele mostrar anuncios invasivos</translation>
+<translation id="8211406090763984747">La conexión es segura</translation>
<translation id="8218327578424803826">Ubicación asignada:</translation>
<translation id="8225771182978767009">La persona que ha configurado este ordenador ha elegido bloquear este sitio web.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" /> o <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Mostrar todas las contraseñas guardadas</translation>
<translation id="8261506727792406068">Eliminar</translation>
<translation id="8267698848189296333">Iniciando sesión como <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Iniciar sesión</translation>
<translation id="8288807391153049143">Mostrar certificado</translation>
<translation id="8289355894181816810">Si tienes alguna duda, ponte en contacto con el administrador de red.</translation>
<translation id="8293206222192510085">Añadir marcador</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Tarjetas prepago y de crédito aceptadas</translation>
<translation id="8759274551635299824">La tarjeta ha caducado</translation>
<translation id="8761567432415473239">La función de Navegación Segura de Google <ph name="BEGIN_LINK" />encontró programas dañinos<ph name="END_LINK" /> recientemente en el sitio <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Dispositivo USB</translation>
<translation id="8790007591277257123">&amp;Rehacer eliminación</translation>
<translation id="8800988563907321413">Las sugerencias de la sección Cercanas aparecen aquí</translation>
<translation id="8820817407110198400">Marcadores</translation>
diff --git a/chromium/components/strings/components_strings_et.xtb b/chromium/components/strings/components_strings_et.xtb
index 551ee756d11..833ee3f9a3e 100644
--- a/chromium/components/strings/components_strings_et.xtb
+++ b/chromium/components/strings/components_strings_et.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Prindi...</translation>
<translation id="1181037720776840403">Eemalda</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Teavita Google'it automaatselt<ph name="END_WHITEPAPER_LINK" /> võimalikest turvaintsidentidest. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Makset ei viidud lõpule</translation>
<translation id="1201402288615127009">Edasi</translation>
<translation id="1201895884277373915">Veel sellelt saidilt</translation>
<translation id="1206967143813997005">Sobimatu algne allkiri</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Krahhiaruanne talletati <ph name="CRASH_TIME" /> (ei ole veel üles laaditud ega eiratud)</translation>
<translation id="1270502636509132238">Kättesaamisviis</translation>
<translation id="1285320974508926690">Ära kunagi seda saiti tõlgi</translation>
+<translation id="1294154142200295408">Käsurea variatsioonid</translation>
<translation id="129553762522093515">Viimati suletud</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Kustutage küpsisefailid<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Teie tegevused <ph name="BEGIN_EMPHASIS" />võivad siiski olla nähtavad<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Aktsepteeritavad krediit- ja deebetkaardid</translation>
<translation id="1519264250979466059">Järgu kuupäev</translation>
<translation id="1527263332363067270">Ühenduse ootamine …</translation>
+<translation id="1532118530259321453">Leht ütleb</translation>
<translation id="153384715582417236">See on praeguseks kõik</translation>
<translation id="154408704832528245">Valige kohaletoimetamisaadress</translation>
<translation id="1549470594296187301">Selle funktsiooni kasutamiseks peab JavaScript olema lubatud.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Kontrollige puhverserverit ja tulemüüri<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Postiindeks</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 soovitus}other{# soovitust}}</translation>
-<translation id="2065985942032347596">Vajalik autentimine</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="2091887806945687916">Heli</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Tühista makse</translation>
<translation id="2147827593068025794">Taustal sünkroonimine</translation>
<translation id="2148613324460538318">Lisa kaart</translation>
-<translation id="2149973817440762519">Muuda järjehoidjat</translation>
<translation id="2154054054215849342">Sünkroonimisteenus pole domeeni jaoks saadaval</translation>
<translation id="2154484045852737596">Kaardi muutmine</translation>
<translation id="2166049586286450108">Täielik administraatorijuurdepääs</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Valige kättesaamisaadress</translation>
<translation id="2740531572673183784">Ok</translation>
<translation id="2742870351467570537">Eemalda valitud üksused</translation>
-<translation id="2744590937989388266">Sellel lehel olevalt manustatud lehelt</translation>
<translation id="277133753123645258">Tarneviis</translation>
<translation id="277499241957683684">Seadme kirje puudub</translation>
<translation id="2784949926578158345">Ühendus lähtestati.</translation>
<translation id="2788784517760473862">Aktsepteeritavad krediitkaardid</translation>
<translation id="2794233252405721443">Sait on blokeeritud</translation>
-<translation id="2795286477369100655">Kas soovite sellelt saidilt lahkuda?</translation>
<translation id="2799020568854403057">Sait, mille soovite avada, sisaldab kahjulikke rakendusi</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="2824775600643448204">Aadressi- ja otsinguriba</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Loendi kirje „<ph name="ENTRY_INDEX" />”: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automaatselt blokeeritud</translation>
<translation id="3024663005179499861">Reegli tüüp on vale</translation>
-<translation id="3032412215588512954">Kas soovite selle saidi uuesti laadida?</translation>
<translation id="3037605927509011580">Ups, ebaõnn!</translation>
<translation id="3039538478787849737">Kas salvestada kaart Google'isse?</translation>
<translation id="3041612393474885105">Sertifikaadi andmed</translation>
@@ -310,6 +306,7 @@
ja veenduge, et puhverserver töötaks. Kui arvate, et teil ei ole vaja
puhverserverit kasutada:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956">Printer <ph name="PRINTER_NAME" /> serveris <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Tühista makse</translation>
<translation id="3207960819495026254">Järjehoidjatesse lisatud</translation>
<translation id="3209375525920864198">Sisestage sobiv seansi nimi.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Haldur saab blokeeringu teie eest tühistada</translation>
<translation id="3566021033012934673">Teie ühendus ei ole privaatne</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Manustatud leht saidil <ph name="SITE" /> ütleb</translation>
<translation id="358285529439630156">Kaupmees aktsepteerib ettemakstud ja krediitkaarte.</translation>
<translation id="3582930987043644930">Lisage nimi</translation>
<translation id="3583757800736429874">&amp;Teisalda uuesti</translation>
<translation id="3586931643579894722">Peida üksikasjad</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Ühendusvigade parandamine&lt;/h1&gt;
+ &lt;p&gt;Kui teile kuvatakse veebisaidi külastamisel veateade, proovige neid lahendusi.&lt;/p&gt;
+ &lt;h2&gt;Enamiku ühendusvigade parandamine&lt;/h2&gt;
+ &lt;p&gt;Kui üritate külastada veebisaiti ja see ei avane, proovige vea parandamiseks esmalt neid veaotsingu toiminguid.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Veenduge, et veebiaadressis poleks kirjavigu.&lt;/li&gt;
+ &lt;li&gt;Veenduge, et Interneti-ühendus töötaks tavapäraselt.&lt;/li&gt;
+ &lt;li&gt;Võtke ühendust veebisaidi omanikuga.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Konkreetse veateate puhul abi hankimine&lt;/h2&gt;
+ &lt;h3&gt;„Teie ühendus pole privaatne”, „NET::ERR_CERT_AUTHORITY_INVALID”, „ERR_CERT_COMMON_NAME_INVALID”, „NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM” või „SSL-sertifikaadi viga”&lt;/h3&gt;
+ &lt;h4&gt;1. toiming: logige portaali sisse&lt;/h4&gt;
+ &lt;p&gt;Näiteks kohvikutes või lennujaamades olevad WiFi-võrgud nõuavad teilt sisselogimist. Sisselogimislehe nägemiseks külastage lehte, mis kasutab protokolli &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Minge mis tahes veebisaidile, mis algab protokolliga &lt;code&gt;http://&lt;/code&gt; (nt &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;).&lt;/li&gt;
+ &lt;li&gt;Logige Interneti kasutamiseks sisse avaneval sisselogimislehel.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;2. toiming: avage leht inkognito režiimis (ainult arvutis)&lt;/h4&gt;
+ &lt;p&gt;Avage külastatav leht inkognito aknas.&lt;/p&gt;
+ &lt;p&gt;Kui leht avaneb, ei tööta Chrome'i laiendus õigesti. Vea parandamiseks lülitage laiendus välja.&lt;/p&gt;
+ &lt;h4&gt;3. toiming: värskendage operatsioonisüsteemi&lt;/h4&gt;
+ &lt;p&gt;Veenduge, et teie seade oleks värskendatud.&lt;/p&gt;
+ &lt;h4&gt;4. toiming: lülitage viirusetõrjetarkvara ajutiselt välja&lt;/h4&gt;
+ &lt;p&gt;Seda viga näete siis, kui kasutate HTTPS-i kaitset või HTTPS-i skannimist pakkuvat viirusetõrjetarkvara. See takistab Chrome'il turvalise ühenduse loomist.&lt;/p&gt;
+ &lt;p&gt;Probleemi lahendamiseks lülitage viirusetõrjetarkvara välja. Kui leht pärast viirusetõrjetarkvara väljalülitamist töötab, lülitage see tarkvara turvaliste saitide külastamise ajaks välja.&lt;/p&gt;
+ &lt;p&gt;Kui olete lõpetanud, ärge unustage viirusetõrjeprogrammi uuesti sisse lülitada.&lt;/p&gt;
+ &lt;h4&gt;5. toiming: paluge lisaabi&lt;/h4&gt;
+ &lt;p&gt;Kui näete endiselt viga, võtke ühendust veebisaidi omanikuga.&lt;/p&gt;
+ &lt;h3&gt;„Looge võrguühendus”&lt;/h3&gt;
+ &lt;p&gt;Seda viga näete juhul, kui kasutate WiFi-portaali, mis nõuab enne võrguühenduse loomist sisselogimist.&lt;/p&gt;
+ &lt;p&gt;Vea parandamiseks klõpsake avataval lehel käsul &lt;strong&gt;Ühenda&lt;/strong&gt;.&lt;/p&gt;
+ &lt;h3&gt;„Teie kell on ajast maas”, „Teie kell on ajast ees” või „NET::ERR_CERT_DATE_INVALID”&lt;/h3&gt;
+ &lt;p&gt;Seda viga näete juhul, kui teie arvuti või mobiilseadme kuupäev ja kellaaeg pole õiged.&lt;/p&gt;
+ &lt;p&gt;Vea parandamiseks avage seadme kell. Veenduge, et kellaaeg ja kuupäev oleksid õiged.&lt;/p&gt;
+ &lt;h3&gt;„Teie arvutis olev tarkvara ei luba Chrome'il veebiga turvaliselt ühendust luua” (ainult Windowsi arvutid)&lt;/h3&gt;
+ &lt;p&gt;Kui näete seda viga, on teie Windowsi arvutis tarkvara Superfish.&lt;/p&gt;
+ &lt;p&gt;Tarkvara ajutiseks keelamiseks ja veebi pääsemiseks järgige neid toiminguid. Teil on vaja administraatoriõigusi.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Klõpsake valikul &lt;strong&gt;Start&lt;/strong&gt;, seejärel otsige üksust &lt;strong&gt;„View local services”&lt;/strong&gt; ja valige see.
+ &lt;li&gt;Tehke valik &lt;strong&gt;VisualDiscovery&lt;/strong&gt;.
+ &lt;li&gt;Tehke jaotises &lt;strong&gt;Startup type&lt;/strong&gt; valik &lt;strong&gt;Disabled&lt;/strong&gt;.
+ &lt;li&gt;Klõpsake jaotises &lt;strong&gt;Service status&lt;/strong&gt; käsul &lt;strong&gt;Stop&lt;/strong&gt;.
+ &lt;li&gt;Klõpsake käsul &lt;strong&gt;Apply&lt;/strong&gt; ja siis nupul &lt;strong&gt;OK&lt;/strong&gt;.
+ &lt;li&gt;Külastage &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome'i abikeskust&lt;/a&gt;, kust leiate teavet selle kohta, kuidas tarkvara arvutist jäädavalt eemaldada.
+ &lt;/ol&gt;</translation>
<translation id="3615877443314183785">Sisestage kehtiv aegumiskuupäev</translation>
<translation id="36224234498066874">Sirvimisandmete kustutamine...</translation>
<translation id="362276910939193118">Näita kogu ajalugu</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Kas soovite selle kaardi salvestada oma Google'i kontole ja sellesse seadmesse?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Aegub: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Saidilt <ph name="SITE" /></translation>
<translation id="382518646247711829">Kui kasutate puhverserverit ...</translation>
<translation id="3828924085048779000">Tühi parool ei ole lubatud.</translation>
<translation id="385051799172605136">Tagasi</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">Üleslaaditud krahhiaruande ID <ph name="CRASH_ID" /> (kohaliku krahhi ID: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Server ei suutnud tõestada, et see on domeen <ph name="DOMAIN" />; selle turvasertifikaat ei määra laiendust Subject Alternative Names. Selle põhjuseks võib olla vale seadistus või ründaja, kes on sekkunud teie ühendusse.</translation>
<translation id="3949601375789751990">Siin kuvatakse teie sirvimisajalugu</translation>
+<translation id="3950820424414687140">Sisselogimine</translation>
<translation id="3963721102035795474">Lugejarežiim</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Ükski}=1{1 saidilt }other{# saidilt }}</translation>
<translation id="397105322502079400">Arvutamine ...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Seadme seerianumber on kehtetu</translation>
<translation id="410351446219883937">Automaatesitus</translation>
<translation id="4103763322291513355">Külastage saiti &lt;strong&gt;chrome://policy&lt;/strong&gt;, et näha mustas nimekirjas olevate URL-ide loendit ja teisi reegleid, mille on jõustanud teie süsteemiadministraator.</translation>
+<translation id="4110652170750985508">Vaadake makse üle</translation>
<translation id="4116663294526079822">Luba sellel saidil alati</translation>
<translation id="4117700440116928470">Reegli ulatust ei toetata.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{veel 1}other{veel #}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Kasutajanimi puudub)</translation>
<translation id="4275830172053184480">Taaskäivitage seade</translation>
<translation id="4280429058323657511">, aegub <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Logi sisse</translation>
<translation id="4312866146174492540">Blokeeri (vaikimisi)</translation>
<translation id="4325863107915753736">Artiklit ei leitud</translation>
<translation id="4326324639298822553">Kontrollige aegumiskuupäeva ja proovige uuesti</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Kaardid ja aadressid pärinevad Chrome'ist ning teie Google'i kontolt (<ph name="ACCOUNT_EMAIL" />). Neid saate hallata menüüs <ph name="BEGIN_LINK" />Seaded<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Üksikasjad</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Manustatud lehelt saidil <ph name="SITE" /></translation>
<translation id="4558551763791394412">Keelake laiendused.</translation>
<translation id="457875822857220463">Kohaletoimetamine</translation>
<translation id="4582800630050655161">Võite kaotada juurdepääsu oma Google'i kontole või teie identiteet võidakse varastada. Chromium soovitab teil kohe oma parooli muuta.</translation>
<translation id="4587425331216688090">Kas eemaldada Chrome'ist aadress?</translation>
<translation id="4592951414987517459">Teie ühendus domeeniga <ph name="DOMAIN" /> on krüpteeritud tänapäevase šifreerimiskomplektiga.</translation>
<translation id="4594403342090139922">&amp;Võta kustutamine tagasi</translation>
-<translation id="4611292653554630842">Logi sisse</translation>
<translation id="4619615317237390068">Muudest seadmetest pärinevad vahelehed</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Server ei suutnud tõestada, et see on domeen <ph name="DOMAIN" />, selle turvasertifikaat sisaldab vigu. Selle põhjuseks võib olla vale seadistus või ründaja, kes on sekkunud teie ühendusse.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Teie ühendus katkes</translation>
<translation id="471880041731876836">Teil ei ole selle saidi külastamiseks luba</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windowsi võrgudiagnostika käitamine<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Teie makse</translation>
<translation id="4726672564094551039">Laadi reeglid uuesti</translation>
<translation id="4728558894243024398">Platvorm</translation>
<translation id="4736825316280949806">Taaskäivitage Chromium</translation>
-<translation id="4737498291095696011">Sellelt lehelt</translation>
<translation id="4744603770635761495">Täitmistee</translation>
<translation id="4749685221585524849">Viimati kasutati kuupäeval <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Teie teave (nt paroolid või krediitkaardi numbrid) on sellele saidile saates privaatne.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Kuva</translation>
<translation id="4854362297993841467">See kohaletoimetamisviis pole saadaval. Proovige mõnda teist kohaletoimetamisviisi.</translation>
<translation id="4858792381671956233">Küsisite oma vanematelt, kas võite seda lehte külastada</translation>
-<translation id="4871132632506079383">Manustatud lehelt saidil <ph name="SITE" /></translation>
<translation id="4880827082731008257">Otsi ajaloost</translation>
+<translation id="4881695831933465202">Ava</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Vajalik on autentimine</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{ja veel 1 veebileht}other{ja veel # veebilehte}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Sisestage krediitkaardi <ph name="CREDIT_CARD" /> CVC. Pärast kinnitamist jagatakse teie Google Paymentsi konto kaardi üksikasju selle saidiga.</translation>
<translation id="4923417429809017348">Leht on tõlgitud teadmata keelest <ph name="LANGUAGE_LANGUAGE" /> keelde</translation>
<translation id="4923459931733593730">Makse</translation>
<translation id="4926049483395192435">Tuleb määrata.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> ütleb</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Toimingud</translation>
<translation id="4958444002117714549">Laienda loendit</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Kui see on lubatud, salvestab Chrome teie kaardi koopia vormide kiiremini täitmiseks sellesse seadmesse.</translation>
<translation id="5018422839182700155">Seda lehte ei saa avada</translation>
<translation id="5019198164206649151">Varusalves esineb probleeme</translation>
-<translation id="5020990877659450221">Sellelt lehelt</translation>
<translation id="5023310440958281426">Tutvuge administraatori reeglitega</translation>
<translation id="5029568752722684782">Kustuta koopia</translation>
<translation id="503069730517007720">Vaja on tarkvara „<ph name="SOFTWARE_NAME" />” juursertifikaati, kuid see pole installitud. Teie IT-administraator peaks probleemi lahendamiseks tarkvara „<ph name="SOFTWARE_NAME" />” seadistamisjuhised üle vaatama. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Masin</translation>
<translation id="5179510805599951267">Tegu ei ole <ph name="ORIGINAL_LANGUAGE" /> keelega? Andke veast teada</translation>
<translation id="5190835502935405962">Järjehoidjariba</translation>
+<translation id="5201306358585911203">Selle lehe manustatud leht ütleb</translation>
<translation id="5205222826937269299">Nimi on nõutav</translation>
<translation id="5222812217790122047">E-posti aadress on nõutav</translation>
<translation id="522700295135997067">See sait võis äsja varastada teie parooli</translation>
<translation id="5230733896359313003">Tarneaadress</translation>
<translation id="5251803541071282808">Pilv</translation>
-<translation id="5277279256032773186">Kas kasutate Chrome'i tööl? Ettevõtted võivad hallata töötajate Chrome'i seadeid. Lisateave</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Tarkvara ajutiseks keelamiseks ja veebi pääsemiseks järgige neid toiminguid. Teil on vaja administraatoriõigusi.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Kontrollige ühendust</translation>
<translation id="5610807607761827392">Kaarte ja aadresse saate hallata menüüs <ph name="BEGIN_LINK" />Seaded<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Host <ph name="HOST_NAME" /> suunas teid liiga mitu korda ümber.</translation>
-<translation id="5622887735448669177">Kas soovite sellelt saidilt lahkuda?</translation>
<translation id="5629630648637658800">Reegli seadete laadimine ebaõnnestus</translation>
<translation id="5631439013527180824">Seadme halduse luba on kehtetu</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Kas soovite sisestada oma kaarditeabe?</translation>
<translation id="5803412860119678065">Kas soovite sisestada kirje <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Teie ühendus domeeniga <ph name="DOMAIN" /> on krüpteeritud aegunud šifreerimiskomplektiga.</translation>
-<translation id="5810928923025889964">Sellel lehel olevalt manustatud lehelt</translation>
<translation id="5813119285467412249">&amp;Lisa uuesti</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>
<translation id="5866257070973731571">Telefoninumbri lisamine</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Lisateabe lisamine</translation>
<translation id="6447842834002726250">Küpsised</translation>
<translation id="6451458296329894277">Kinnita vormi uuestiesitamist</translation>
-<translation id="6456339708790392414">Teie makse</translation>
<translation id="647261751007945333">Seadme reeglid</translation>
<translation id="6477321094435799029">Chrome tuvastas sellel lehel ebatavalise koodi ja blokeeris selle, et teie isiklikke andmeid (nt paroolid, telefoninumbrid ja krediitkaardiandmed) kaitsta.</translation>
<translation id="6489534406876378309">Krahhide üleslaadimise alustamine</translation>
<translation id="6507833130742554667">Kaupmees aktsepteerib krediit- ja deebetkaarte.</translation>
<translation id="6508722015517270189">Taaskäivitage Chrome</translation>
-<translation id="6521373090216409766">Kas soovite selle saidi uuesti laadida?</translation>
<translation id="6529602333819889595">&amp;Kustuta uuesti</translation>
<translation id="6534179046333460208">Füüsilise veebi soovitused</translation>
<translation id="6550675742724504774">Valikud</translation>
-<translation id="6556239504065605927">Turvaline ühendus</translation>
<translation id="6556915248009097796">Aegub: <ph name="EXPIRATION_DATE_ABBR" />. Viimati kasutati kuupäeval <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Haldur ei ole seda veel kinnitanud</translation>
<translation id="6569060085658103619">Vaatate laienduse lehte</translation>
<translation id="6596325263575161958">Krüpteerimise valikud</translation>
+<translation id="6604181099783169992">Liikumis- või valgusandurid</translation>
<translation id="6624427990725312378">Kontaktteave</translation>
<translation id="6626291197371920147">Kehtiva kaardinumbri lisamine</translation>
<translation id="6628463337424475685"><ph name="ENGINE" />'i otsing</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Hallatud järjehoidjad</translation>
<translation id="7298195798382681320">Soovitatud</translation>
<translation id="7309308571273880165">Krahhiaruanne jäädvustati ajal <ph name="CRASH_TIME" /> (kasutaja taotles üleslaadimist; pole veel üles laaditud)</translation>
+<translation id="7320336641823683070">Ühendamise abi</translation>
<translation id="7334320624316649418">&amp;Korrasta uuesti</translation>
<translation id="733923710415886693">Serveri sertifikaati ei avalikustatud sertifikaadi läbipaistvuse reegli kaudu.</translation>
<translation id="7353601530677266744">Käsurida</translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">WiFi-võrk, mida kasutate (<ph name="WIFI_NAME" />), võib nõuda sisselogimislehe külastamist.</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="7862185352068345852">Kas lahkuda saidilt?</translation>
<translation id="7878176543348854470">Kaupmees aktsepteerib ettemakstud ja deebetkaarte.</translation>
<translation id="7878562273885520351">Teie parool võib olla ohus</translation>
<translation id="7887683347370398519">Kontrollige CVC-d ja proovige uuesti</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Kasuta globaalset vaikeseadet (küsi)</translation>
<translation id="8042918947222776840">Valige kättesaamisviis</translation>
<translation id="8057711352706143257">Tarkvara „<ph name="SOFTWARE_NAME" />” ei ole õigesti seadistatud. Tarkvara „<ph name="SOFTWARE_NAME" />” desinstallimine lahendab tavaliselt probleemi. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Kas laadida sait uuesti?</translation>
<translation id="8088680233425245692">Artikli kuvamine ebaõnnestus.</translation>
<translation id="8091372947890762290">Aktiveerimine on serveris ootel</translation>
<translation id="8094917007353911263">Võrk, mida kasutate, võib nõuda veebilehe <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> külastamist.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">ID-ga „<ph name="EXTENSION_ID" />” laienduse kehtetu värskendamise URL.</translation>
<translation id="8202097416529803614">Tellimuse kokkuvõte</translation>
<translation id="8205463626947051446">Sait näitab sekkuvaid reklaame</translation>
+<translation id="8211406090763984747">Ühendus on turvaline</translation>
<translation id="8218327578424803826">Määratud asukoht:</translation>
<translation id="8225771182978767009">Arvuti seadistanud inimene blokeeris selle saidi.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Kuva kõik salvestatud paroolid</translation>
<translation id="8261506727792406068">Kustuta</translation>
<translation id="8267698848189296333">Sisselogimine kasutajana <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Logi sisse</translation>
<translation id="8288807391153049143">Kuva sertifikaat</translation>
<translation id="8289355894181816810">Kui te pole kindel, mida see tähendab, võtke ühendust oma võrguadministraatoriga.</translation>
<translation id="8293206222192510085">Lisa järjehoidja</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Aktsepteeritavad ettemakstud ja krediitkaardid</translation>
<translation id="8759274551635299824">See kaart on aegunud</translation>
<translation id="8761567432415473239">Google'i ohutu sirvimine <ph name="BEGIN_LINK" />tuvastas hiljuti kahjulikud programmid<ph name="END_LINK" /> saidil <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">USB-seade</translation>
<translation id="8790007591277257123">&amp;Kustuta uuesti</translation>
<translation id="8800988563907321413">Teie lähedalasuvad soovitused kuvatakse siin</translation>
<translation id="8820817407110198400">Järjehoidjad</translation>
diff --git a/chromium/components/strings/components_strings_fa.xtb b/chromium/components/strings/components_strings_fa.xtb
index 092960f73e1..5bf5c2705d4 100644
--- a/chromium/components/strings/components_strings_fa.xtb
+++ b/chromium/components/strings/components_strings_fa.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;چاپ...</translation>
<translation id="1181037720776840403">حذف</translation>
<translation id="1184214524891303587">‏<ph name="BEGIN_WHITEPAPER_LINK" /> گزارش خودکار <ph name="END_WHITEPAPER_LINK" /> جزئیات حوادث امنیتی احتمالی به Google.‏ <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">پرداخت کامل نشد</translation>
<translation id="1201402288615127009">بعدی</translation>
<translation id="1201895884277373915">موارد بیشتر از این سایت</translation>
<translation id="1206967143813997005">امضای اولیه نادرست</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">گزارش خرابی ثبت‌شده در <ph name="CRASH_TIME" /> (هنوز بارگذاری نشده است یا نادیده‌ گرفته شده است)</translation>
<translation id="1270502636509132238">روش تحویل گرفتن</translation>
<translation id="1285320974508926690">این سایت هرگز ترجمه نشود</translation>
+<translation id="1294154142200295408">انواع مختلف خط فرمان</translation>
<translation id="129553762522093515">اخیراً بسته‌شده</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />کوکی‌ها را پاک کنید<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">فعالیت شما <ph name="BEGIN_EMPHASIS" />ممکن است در موارد زیر قابل‌رؤیت باشد<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">کارت‌های اعتباری و نقدی قابل‌قبول</translation>
<translation id="1519264250979466059">تاریخ ساخت</translation>
<translation id="1527263332363067270">درانتظار برقراری اتصال…‏</translation>
+<translation id="1532118530259321453">این صفحه می‌گوید</translation>
<translation id="153384715582417236">درحال‌حاضر مورد دیگری وجود ندارد</translation>
<translation id="154408704832528245">انتخاب نشانی ارسال</translation>
<translation id="1549470594296187301">برای استفاده از این قابلیت، جاوا اسکریپت باید فعال باشد.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />بررسی پروکسی و دیوار آتش<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">کد پستی</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{۱ پیشنهاد}one{# پیشنهاد}other{# پیشنهاد}}</translation>
-<translation id="2065985942032347596">راستی‌آزمایی لازم است</translation>
<translation id="2079545284768500474">لغو</translation>
<translation id="20817612488360358">تنظیمات پروکسی سیستم تنظیم شده تا مورد استفاده قرار گیرد، اما یک پیکربندی مشخص برای پروکسی نیز تعیین شده است.</translation>
<translation id="2091887806945687916">صدا</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">لغو پرداخت</translation>
<translation id="2147827593068025794">همگام‌سازی پس‌زمینه</translation>
<translation id="2148613324460538318">افزودن کارت</translation>
-<translation id="2149973817440762519">ویرایش نشانک</translation>
<translation id="2154054054215849342">همگام‌سازی برای دامنه شما در دسترس نیست</translation>
<translation id="2154484045852737596">ویرایش کارت</translation>
<translation id="2166049586286450108">دسترسی کامل سرپرست</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">انتخاب نشانی تحویل گرفتن</translation>
<translation id="2740531572673183784">تأیید</translation>
<translation id="2742870351467570537">حذف آیتم های انتخاب شده</translation>
-<translation id="2744590937989388266">از صفحه جاسازی‌شده‌ای در این صفحه</translation>
<translation id="277133753123645258">روش ارسال</translation>
<translation id="277499241957683684">ثبت دستگاه موجود نیست</translation>
<translation id="2784949926578158345">اتصال مجدداً برقرار شد.</translation>
<translation id="2788784517760473862">کارت‌های اعتباری قابل‌قبول</translation>
<translation id="2794233252405721443">سایت مسدودشده</translation>
-<translation id="2795286477369100655">می‌خواهید از این سایت خارج شوید؟</translation>
<translation id="2799020568854403057">سایت پیش‌رو حاوی برنامه‌های خطرناک است</translation>
<translation id="2803306138276472711">‏Google Safe Browsing به تازگی در <ph name="SITE" />، ‏<ph name="BEGIN_LINK" />بدافزار شناسایی کرده است<ph name="END_LINK" />. گاهی اوقات وب‌سایت‌هایی که معمولاً ایمن هستند با بدافزار آلوده می‌شوند.</translation>
<translation id="2824775600643448204">نوار جستجو و آدرس</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">ورودی فهرست "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">مسدود‌شده به‌طور خودکار</translation>
<translation id="3024663005179499861">نوع خط‌مشی اشتباه است</translation>
-<translation id="3032412215588512954">می‌خواهید این سایت را تازه‌سازی کنید؟</translation>
<translation id="3037605927509011580">اوه، نه!</translation>
<translation id="3039538478787849737">‏کارت در Google ذخیره شود؟</translation>
<translation id="3041612393474885105">اطلاعات گواهی</translation>
@@ -310,6 +306,7 @@
مطمئن شوید سرور پروکسی کار می‌کند. اگر مطمئن نیستید که باید از سرور
پروکسی استفاده کنید:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> در <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">لغو پرداخت</translation>
<translation id="3207960819495026254">نشانک‌گذاری شده</translation>
<translation id="3209375525920864198">لطفاً نام جلسه معتبری وارد کنید.</translation>
@@ -367,11 +364,62 @@
<translation id="3556433843310711081">مدیرتان می‌تواند این سایت را برای شما بگشاید</translation>
<translation id="3566021033012934673">اتصال شما خصوصی نیست</translation>
<translation id="3574305903863751447"><ph name="CITY" />، <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">صفحه جاسازی‌شده‌ای در <ph name="SITE" /> می‌گوید</translation>
<translation id="358285529439630156">کارت‌های اعتباری و پیش‌پرداخت پذیرفته می‌شوند.</translation>
<translation id="3582930987043644930">افزودن نام</translation>
<translation id="3583757800736429874">&amp;انجام مجدد انتقال</translation>
<translation id="3586931643579894722">عدم نمایش جزئیات</translation>
<translation id="3600246354004376029"><ph name="TITLE" />، <ph name="DOMAIN" />، <ph name="TIME" /></translation>
+<translation id="3602137825010714926">‏&lt;h1&gt;برطرف کردن خطاهای اتصال&lt;/h1&gt;
+ &lt;p&gt;اگر هنگام تلاش برای بازدید از وب‌سایتی پیام خطایی دریافت می‌کنید، این راه‌حل‌ها را امتحان کنید.
+.&lt;/p&gt;
+ &lt;h2&gt;برطرف کردن اکثر خطاهای اتصال
+&lt;/h2&gt;
+ &lt;p&gt;اگر می‌خواهید از وب‌سایتی بازدید کنید و باز نمی‌شود، ابتدا سعی کنید با این مراحل عیب‌یابی، خطا را برطرف کنید:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;بررسی کنید نشانی وب اشتباه تایپی نداشته باشد.&lt;/li&gt;
+ &lt;li&gt;مطمئن شوید اتصال اینترنت درست کار می‌کند.&lt;/li&gt;
+ &lt;li&gt;با مالک وب‌سایت تماس بگیرید.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;دریافت راهنمایی برای پیام خطایی خاص&lt;/h2&gt;
+ &lt;h3&gt;«اتصال شما خصوصی نیست» یا «NET::ERR_CERT_AUTHORITY_INVALID» یا «ERR_CERT_COMMON_NAME_INVALID» یا «NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM» یا «خطای گواهی ‏‏SSL‏»&lt;/h3&gt;
+ &lt;h4&gt;مرحله ۱: به سیستم پورتال وارد شوید&lt;/h4&gt;
+ &lt;p&gt;شبکه‌های Wi-Fi در مکان‌هایی مانند کافه‌ها یا فرودگاه‌ها از شما می‌خواهند که به سیستم وارد شوید.
+برای دیدن صفحه ورود به سیستم، به صفحه‌ای بروید که از &lt;code&gt;http://&lt;/code&gt;استفاده می‌کند.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;به وب‌سایتی بروید که با &lt;code&gt;http://&lt;/code&gt; شروع می‌شود مانند: &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;در صفحه ورود به سیستمی که باز می‌شود، برای استفاده از اینترنت به سیستم وارد شوید.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;مرحله ۲: صفحه وب را در حالت ناشناس باز کنید (فقط برای رایانه)&lt;/h4&gt;
+ &lt;p&gt;صفحه‌ای را که بازدید می‌کردید در پنجره ناشناس باز کنید.&lt;/p&gt;
+ &lt;p&gt;اگر صفحه باز شد، افزونه Chrome به‌درستی کار نمی‌کند. برای برطرف کردن خطا، افزونه را خاموش کنید.&lt;/p&gt;
+ &lt;h4&gt;مرحله ۳: سیستم عامل را به‌روزرسانی کنید&lt;/h4&gt;
+ &lt;p&gt;مطمئن شوید که دستگاهتان به‌روز است.&lt;/p&gt;
+ &lt;h4&gt;مرحله ۴: ضدویروس را موقتاً خاموش کنید&lt;/h4&gt;
+ &lt;p&gt;اگر ضدویروسی داشته باشید که دارای «محافظت HTTPS» یا «اسکن HTTPS» است، این خطا را خواهید دید. ضدویروس مانع Chrome برای تامین امنیت می‌شود.&lt;/p&gt;
+ &lt;p&gt;برای برطرف کردن مشکل، نرم‌افزار ضدویروستان را خاموش کنید. اگر صفحه بعد از خاموش کردن نرم‌افزار کار کرد، وقتی از سایت‌های ایمن استفاده می‌کنید این نرم‌افزار را خاموش کنید.
+.&lt;/p&gt;
+ &lt;p&gt;وقتی کارتان تمام شد، فراموش نکنید که برنامه آنتی‌ویروس را دوباره روشن کنید.&lt;/p&gt;
+ &lt;h4&gt;مرحله ۵: دریافت راهنمایی بیشتر&lt;/h4&gt;
+ &lt;p&gt;اگر همچنان خطا را می‌بینید، با مالک وب‌سایت تماس بگیرید.&lt;/p&gt;
+ &lt;h3&gt;«اتصال به شبکه»&lt;/h3&gt;
+ &lt;p&gt;اگر از پورتالی از Wi-Fi استفاده می‌کنید که پیش از آنلاین شدن شما را ملزم به ورود به سیستم می‌کند، این خطا را مشاهده می‌کنید.&lt;/p&gt;
+ &lt;p&gt;برای برطرف کردن خطا، در صفحه‌ای که می‌خواهید باز کنید، روی &lt;strong&gt;اتصال&lt;/strong&gt; کلیک کنید.&lt;/p&gt;
+ &lt;h3&gt;«ساعت شما عقب است» یا «ساعت شما جلو است» "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;اگر تاریخ و زمان رایانه یا دستگاه همراهتان درست نباشد این خطا را خواهید دید.&lt;/p&gt;
+ &lt;p&gt;برای برطرف کردن این خطا، ساعت دستگاهتان را باز کنید. مطمئن شوید که ساعت و تاریخ درست باشد.&lt;/p&gt;
+ &lt;h3&gt;«نرم‌افزاری در رایانه شما مانع از اتصال ایمن Chrome به وب می‌شود»
+(فقط رایانه‌های Windows)&lt;/h3&gt;
+ &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;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; کلیک کنید
+ &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="3615877443314183785">تاریخ انقضای معتبری وارد کنید</translation>
<translation id="36224234498066874">پاک کردن داده‌های محصول مرور…</translation>
<translation id="362276910939193118">نمایش کل سابقه</translation>
@@ -404,7 +452,6 @@
<translation id="3778403066972421603">‏آیا می‌خواهید این کارت در حساب Google شما و این دستگاه ذخیره شود؟</translation>
<translation id="3783418713923659662">مسترکارت</translation>
<translation id="3787705759683870569">تاریخ انقضا <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">از <ph name="SITE" /></translation>
<translation id="382518646247711829">اگر از سرور پراکسی استفاده می‌کنید...</translation>
<translation id="3828924085048779000">عبارت عبور خالی مجاز نیست.</translation>
<translation id="385051799172605136">بازگشت</translation>
@@ -418,6 +465,7 @@
<translation id="3945915738023014686">شناسه گزارش خرابی بارگذاری‌شده <ph name="CRASH_ID" /> (شناسه خرابی محلی: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">‏این سرور نتوانست ثابت کند که <ph name="DOMAIN" /> است؛ در گواهی امنیتی آن، Subject Alternative Names مشخص نشده است. ممکن است این مشکل به دلیل پیکربندی نادرست یا قطع اتصال شما توسط مهاجم ایجاد شده باشد.</translation>
<translation id="3949601375789751990">سابقه مرورتان در اینجا نشان داده می‌شود</translation>
+<translation id="3950820424414687140">ورود به سیستم</translation>
<translation id="3963721102035795474">حالت «خواننده»</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{هیچ‌کدام}=1{از ۱ سایت }one{از # سایت }other{از # سایت }}</translation>
<translation id="397105322502079400">در حال محاسبه…</translation>
@@ -434,6 +482,7 @@
<translation id="4103249731201008433">شماره سریال دستگاه نامعتبر است</translation>
<translation id="410351446219883937">پخش خودکار</translation>
<translation id="4103763322291513355">‏برای مشاهده فهرست نشانی‌های وب ممنوع و سایر خط‌مشی‌های اجباری براساس تصمیم سرپرست سیستم خود از &lt;strong&gt;chrome://policy&lt;/strong&gt; بازدید نمایید.</translation>
+<translation id="4110652170750985508">مرور پرداخت</translation>
<translation id="4116663294526079822">همیشه مجاز در این سایت</translation>
<translation id="4117700440116928470">محدوده خط‌مشی پشتیبانی نمی‌شود.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{۱ مورد دیگر}one{# مورد دیگر}other{# مورد دیگر}}</translation>
@@ -460,7 +509,6 @@
<translation id="4269787794583293679">(بدون نام کاربری)</translation>
<translation id="4275830172053184480">راه‌اندازی دستگاه خود</translation>
<translation id="4280429058323657511">، انقضا <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">ورود به سیستم</translation>
<translation id="4312866146174492540">مسدود کردن (پیش‌فرض)</translation>
<translation id="4325863107915753736">مقاله یافت نشد.</translation>
<translation id="4326324639298822553">تاریخ انقضا را بررسی و دوباره امتحان کنید</translation>
@@ -482,14 +530,12 @@
<translation id="4515275063822566619">‏کارت‌ها و نشانی‌ها از Chrome و حساب Google شما (<ph name="ACCOUNT_EMAIL" />) هستند. می‌توانید آن‌ها را در <ph name="BEGIN_LINK" />تنظیمات<ph name="END_LINK" /> مدیریت کنید.</translation>
<translation id="4522570452068850558">جزئیات</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">از صفحه جاسازی‌شده‌ای در <ph name="SITE" /></translation>
<translation id="4558551763791394412">افزونه‌ها را غیرفعال کنید.</translation>
<translation id="457875822857220463">ارسال</translation>
<translation id="4582800630050655161">‏ممکن است دسترسی به حساب Google را از دست بدهید یا به سرقت هویت دچار شوید. Chromium توصیه می‌کند هم‌اکنون گذرواژه‌تان را تغییر دهید.</translation>
<translation id="4587425331216688090">‏آدرس از Chrome پاک شود؟</translation>
<translation id="4592951414987517459">اتصال شما به <ph name="DOMAIN" /> با استفاده از یک مجموعه رمز مدرن، رمزگذاری شده است.</translation>
<translation id="4594403342090139922">&amp;واگرد حذف</translation>
-<translation id="4611292653554630842">ورود به سیستم</translation>
<translation id="4619615317237390068">برگه‌ها از دستگاه‌های دیگر</translation>
<translation id="4668929960204016307">،</translation>
<translation id="467662567472608290">این سرور نتوانست اثبات کند که این <ph name="DOMAIN" /> است؛ گواهی امنیتی آن خطاهایی دارد. ممکن است علت این موضوع پیکربندی اشتباه باشد یا مهاجمی اتصال شما را قطع کرده است.</translation>
@@ -499,11 +545,9 @@
<translation id="4708268264240856090">اتصال شما قطع شد</translation>
<translation id="471880041731876836">برای بازدید کردن از این سایت، مجوز لازم ندارید</translation>
<translation id="4722547256916164131">‏<ph name="BEGIN_LINK" />در حال اجرای Windows Network Diagnostics<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">پرداخت شما</translation>
<translation id="4726672564094551039">تازه‌سازی خط مشی‌ها</translation>
<translation id="4728558894243024398">پلت فورم</translation>
<translation id="4736825316280949806">‏Chromium را راه‌اندازی مجدد کنید</translation>
-<translation id="4737498291095696011">از این صفحه</translation>
<translation id="4744603770635761495">مسیر قابل اجرا</translation>
<translation id="4749685221585524849">آخرین استفاده: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">اطلاعات شما (به‌عنوان مثال، گذرواژه‌ها یا شماره‌ کارت‌های اعتباری) وقتی به این سایت ارسال می‌شوند، خصوصی هستند.</translation>
@@ -522,16 +566,16 @@
<translation id="4850886885716139402">نما</translation>
<translation id="4854362297993841467">این روش تحویل در دسترس نیست. روش دیگری را امتحان کنید.</translation>
<translation id="4858792381671956233">از والدینتان پرسیدید آیا اجازه بازدید از این سایت را دارید</translation>
-<translation id="4871132632506079383">از صفحه جاسازی‌شده‌ای در <ph name="SITE" /></translation>
<translation id="4880827082731008257">سابقه جستجو</translation>
+<translation id="4881695831933465202">باز کردن</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />،‏ <ph name="TYPE_2" />،‏ <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">راستی‌آزمایی لازم است</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{ و ۱ صفحه وب دیگر}one{ و # صفحه وب دیگر}other{ و # صفحه وب دیگر}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">‏CVC را برای <ph name="CREDIT_CARD" /> وارد کنید. بعد از تأیید، جزئیات کارت از حساب پرداخت‌های Google با این سایت هم‌رسانی می‌شود.</translation>
<translation id="4923417429809017348">این صفحه از یک زبان ناشناس به <ph name="LANGUAGE_LANGUAGE" /> ترجمه شده است.</translation>
<translation id="4923459931733593730">پرداخت</translation>
<translation id="4926049483395192435">باید مشخص شود.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> می‌گوید</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">کنش‌ها</translation>
<translation id="4958444002117714549">بزرگ کردن فهرست</translation>
@@ -540,7 +584,6 @@
<translation id="5002932099480077015">‏اگر فعال شود، Chrome یک کپی از کارت شما را برای پرکردن سریع‌تر فرم در این دستگاه ذخیره می‌کند.</translation>
<translation id="5018422839182700155">این صفحه نمی‌تواند باز شود</translation>
<translation id="5019198164206649151">پشتیبان‌گیری ذخیره در وضعیت نادرست است</translation>
-<translation id="5020990877659450221">از این صفحه</translation>
<translation id="5023310440958281426">خط‌مشی‌های سرپرست سیستمتان را بررسی کنید</translation>
<translation id="5029568752722684782">پاک کردن نسخه کپی</translation>
<translation id="503069730517007720">برای «<ph name="SOFTWARE_NAME" />» گواهینامه ریشه‌ لازم است اما نصب نشده است. برای رفع این مشکل، سرپرست فناوری اطلاعات شما باید دستورالعمل‌های پیکربندی مربوط به «<ph name="SOFTWARE_NAME" />» را بررسی کند. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +609,12 @@
<translation id="5172758083709347301">دستگاه</translation>
<translation id="5179510805599951267">به زبان <ph name="ORIGINAL_LANGUAGE" /> نیست؟ گزارش این خطا</translation>
<translation id="5190835502935405962">نوار نشانک‌ها</translation>
+<translation id="5201306358585911203">صفحه جاسازی‌شده‌ای در این صفحه می‌گوید</translation>
<translation id="5205222826937269299">نام ضروری است</translation>
<translation id="5222812217790122047">رایانامه ضروری است</translation>
<translation id="522700295135997067">ممکن است این سایت اخیراً گذرواژه‌تان را سرقت کرده باشد</translation>
<translation id="5230733896359313003">نشانی تحویل کالا</translation>
<translation id="5251803541071282808">Cloud</translation>
-<translation id="5277279256032773186">‏از Chrome در محل کار استفاده می‌کنید؟ کسب و کارها می‌توانند تنظیمات Chrome را برای کارمندانشان مدیریت کنند. بیشتر بدانید</translation>
<translation id="5281113152797308730">‏<ph name="BEGIN_PARAGRAPH" />با دنبال کردن این مراحل، نرم‌افزار را موقتاً غیرفعال کنید تا بتوانید به وب دسترسی داشته باشید. انجام این مراحل به امتیازهای سرپرستی نیاز دارد.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +676,6 @@
<translation id="5610142619324316209">بررسی اتصال</translation>
<translation id="5610807607761827392">می‌توانید در <ph name="BEGIN_LINK" />تنظیمات<ph name="END_LINK" />، کارت‌ها و نشانی‌ها را مدیریت کنید.</translation>
<translation id="5617949217645503996">تعداد دفعاتی که <ph name="HOST_NAME" /> شما را به نشانی‌های دیگر هدایت کرده بیش از حد است.</translation>
-<translation id="5622887735448669177">می‌خواهید از این سایت خارج شوید؟</translation>
<translation id="5629630648637658800">تنظیمات خط‌مشی بارگیری نشد</translation>
<translation id="5631439013527180824">نشانه مدیریت دستگاه نامعتبر است</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>
@@ -656,7 +698,6 @@
<translation id="5786044859038896871">می‌خواهید اطلاعات کارتتان را وارد کنید؟</translation>
<translation id="5803412860119678065">می‌خواهید <ph name="CARD_DETAIL" /> خود را وارد کنید؟</translation>
<translation id="5810442152076338065">اتصال شما به <ph name="DOMAIN" /> با استفاده از یک مجموعه رمز منسوخ، رمزگذاری شده است.</translation>
-<translation id="5810928923025889964">از صفحه جاسازی‌شده‌ای در این صفحه</translation>
<translation id="5813119285467412249">&amp;انجام مجدد افزودن</translation>
<translation id="5838278095973806738">نباید هیچ اطلاعات حساسی (مثل گذرواژه یا کارت اعتباری) را در این سایت وارد کنید، زیرا ممکن است مهاجمین آن‌ها را سرقت کنند.</translation>
<translation id="5866257070973731571">افزودن شماره تلفن</translation>
@@ -730,21 +771,19 @@
<translation id="6446608382365791566">افزودن اطلاعات بیشتر</translation>
<translation id="6447842834002726250">کوکی‌ها</translation>
<translation id="6451458296329894277">تأیید ارسال مجدد فرم</translation>
-<translation id="6456339708790392414">پرداخت شما</translation>
<translation id="647261751007945333">خط‌‌مشی‌های دستگاه</translation>
<translation id="6477321094435799029">‏Chrome کد نامعمول در این این صفحه شناسایی کرده و برای محافظت از اطلاعات شخصی‌تان (مثلاً گذرواژه‌ها، شماره تلفن‌‌ها و کارت‌های اعتباری) آن را مسدود کرده است.</translation>
<translation id="6489534406876378309">شروع بارگذاری کردن خرابی‌ها</translation>
<translation id="6507833130742554667">کارت‌های اعتباری و نقدی پذیرفته می‌شوند.</translation>
<translation id="6508722015517270189">‏Chrome را راه‌اندازی مجدد کنید</translation>
-<translation id="6521373090216409766">می‌خواهید این سایت را تازه‌سازی کنید؟</translation>
<translation id="6529602333819889595">&amp;انجام مجدد حذف</translation>
<translation id="6534179046333460208">پیشنهادهای «وب فیزیکی»</translation>
<translation id="6550675742724504774">گزینه‌ها</translation>
-<translation id="6556239504065605927">اتصال امن</translation>
<translation id="6556915248009097796">تاریخ انقضا: <ph name="EXPIRATION_DATE_ABBR" />، آخرین استفاده: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">مدیرتان هنوز این سایت را تأیید نکرده است</translation>
<translation id="6569060085658103619">درحال مشاهده یک صفحه افزونه هستید</translation>
<translation id="6596325263575161958">گزینه‌های رمزگذاری</translation>
+<translation id="6604181099783169992">حسگرهای نوری یا حرکتی</translation>
<translation id="6624427990725312378">اطلاعات تماس</translation>
<translation id="6626291197371920147">افزودن شماره کارت معتبر</translation>
<translation id="6628463337424475685">جستجوی <ph name="ENGINE" /></translation>
@@ -816,6 +855,7 @@
<translation id="7275334191706090484">نشانک‌های مدیریت شده</translation>
<translation id="7298195798382681320">توصیه می‌شود</translation>
<translation id="7309308571273880165">گزارش خرابی ثبت‌شده در <ph name="CRASH_TIME" /> (کاربر درخواست بارگذاری کرده است، هنوز بارگذاری نشده است)</translation>
+<translation id="7320336641823683070">راهنمای اتصال</translation>
<translation id="7334320624316649418">&amp;انجام مجدد ترتیب‌بندی مجدد</translation>
<translation id="733923710415886693">گواهی سرور از طریق شفافیت گواهینامه نشان داده نشده بود.</translation>
<translation id="7353601530677266744">خط فرمان</translation>
@@ -829,7 +869,7 @@
<translation id="7437289804838430631">افرودن اطلاعات تماس</translation>
<translation id="7441627299479586546">موضوع خط‌مشی اشتباه است</translation>
<translation id="7444046173054089907">این سایت مسدود شده است</translation>
-<translation id="7445762425076701745">هویت سروری که به آن متصل شده‌اید به‌طور کامل راستی‌آزمایی نمی‌شود. با استفاده از نامی به سرور متصل شده‌اید که فقط در شبکه شما معتبر است و ارائه دهنده مجوز خارجی قادر به راستی‌آزمایی مالکیت آن نیست. به دلیل آنکه برخی از ارائه دهندگان مجوز بدون توجه به هر موردی، مجوزهایی را برای این نام‌ها ارائه می‌کنند، روشی برای اطمینان از این امر وجود ندارد که آیا شما به سایت مورد نظر خود متصل شده‌اید یا یک سایت مضر.</translation>
+<translation id="7445762425076701745">هویت سروری که به آن متصل شده‌اید به‌طور کامل راستی‌آزمایی نمی‌شود. با استفاده از نامی به سرور متصل شده‌اید که فقط در شبکه شما معتبر است و ارائه دهنده مجوز خارجی قادر به راستی‌آزمایی مالکیت آن نیست. به دلیل آنکه برخی از ارائه دهندگان مجوز بدون توجه به هر موردی، مجوزهایی را برای این نام‌ها ارائه می‌کنند، روشی برای اطمینان از این امر وجود ندارد که آیا شما به سایت موردنظر خود متصل شده‌اید یا یک سایت مضر.</translation>
<translation id="7451311239929941790">درباره این مشکل <ph name="BEGIN_LINK" />بیشتر بدانید<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">استفاده از پیش‌فرض جهانی (مسدود)</translation>
<translation id="7460163899615895653">برگه‌های اخیر شما از دیگر دستگاه‌ها اینجا نشان داده می‌شوند</translation>
@@ -900,6 +940,7 @@
<translation id="782886543891417279">‏شبکه Wi-Fi (<ph name="WIFI_NAME" />) مورد استفاده‌تان احتمالاً نیاز دارد که به یک صفحه ورود به سیستم بروید.</translation>
<translation id="785549533363645510">اما، شما نامرئی نیستید. با استفاده از حالت ناشناس، مرورتان از چشمان کارفرمای شما، ارائه‌دهنده خدمات اینترنت یا وب‌‌سایت‌هایی که بازدید می‌کنید پنهان نمی‌ماند.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">سایت را ترک می‌کنید؟</translation>
<translation id="7878176543348854470">کارت‌های نقدی و پیش‌پرداخت پذیرفته می‌شوند.</translation>
<translation id="7878562273885520351">ممکن است گذرواژه‌تان درمعرض خطر باشد</translation>
<translation id="7887683347370398519">‏CVC را بررسی کرده و دوباره امتحان کنید</translation>
@@ -922,6 +963,7 @@
<translation id="8041940743680923270">استفاده از پیش‌فرض جهانی (سؤال شود)</translation>
<translation id="8042918947222776840">انتخاب روش تحویل گرفتن</translation>
<translation id="8057711352706143257">«<ph name="SOFTWARE_NAME" />» درست پیکربندی نمی‌شود. معمولاً حذف‌ نصب «<ph name="SOFTWARE_NAME" />» مشکل را برطرف می‌کند. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">سایت تازه‌سازی شود؟</translation>
<translation id="8088680233425245692">مشاهده مقاله ناموفق بود.</translation>
<translation id="8091372947890762290">فعال‌سازی در سرور در حالت تعلیق است</translation>
<translation id="8094917007353911263">شبکه‌ای که از آن استفاده می‌کنید ممکن است از شما بخواهد که <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> را ببینید.</translation>
@@ -937,6 +979,7 @@
<translation id="8201077131113104583">نشانی وب به‌روزرسانی نامعتبر برای برنامه افزودنی با شناسه «<ph name="EXTENSION_ID" />».</translation>
<translation id="8202097416529803614">خلاصه سفارش</translation>
<translation id="8205463626947051446">سایت تمایل دارد آگهی‌ها مزاحم نشان دهد</translation>
+<translation id="8211406090763984747">اتصال امن است</translation>
<translation id="8218327578424803826">مکان اختصاص یافته:</translation>
<translation id="8225771182978767009">شخصی که این رایانه را راه‌اندازی کرده این سایت را مسدود کرده است.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />،‏ <ph name="TYPE_2" /></translation>
@@ -948,6 +991,7 @@
<translation id="825929999321470778">نمایش همه گذرواژه‌های ذخیره‌شده</translation>
<translation id="8261506727792406068">حذف</translation>
<translation id="8267698848189296333">ورود به سیستم به‌عنوان <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">ورود به سیستم</translation>
<translation id="8288807391153049143">نمایش گواهی</translation>
<translation id="8289355894181816810">اگر این موضوع را متوجه نمی‌شوید، با سرپرست شبکه‌تان تماس بگیرید.</translation>
<translation id="8293206222192510085">افزودن نشانک</translation>
@@ -998,6 +1042,7 @@
<translation id="874846938927089722">کارت‌های اعتباری و پیش‌پرداخت قابل‌قبول</translation>
<translation id="8759274551635299824">کارت منقضی شده است</translation>
<translation id="8761567432415473239">‏مرور ایمن Google اخیراً <ph name="BEGIN_LINK" />برنامه‌های خطرناک<ph name="END_LINK" /> را در <ph name="SITE" /> پیدا کرده است.</translation>
+<translation id="8763927697961133303">‏دستگاه USB</translation>
<translation id="8790007591277257123">&amp;انجام مجدد حذف</translation>
<translation id="8800988563907321413">پیشنهادات اطراف شما در اینجا نشان داده می‌شوند</translation>
<translation id="8820817407110198400">نشانک‌ها</translation>
diff --git a/chromium/components/strings/components_strings_fi.xtb b/chromium/components/strings/components_strings_fi.xtb
index 4eb53ea84fc..cc1074e6873 100644
--- a/chromium/components/strings/components_strings_fi.xtb
+++ b/chromium/components/strings/components_strings_fi.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">Tulo&amp;sta...</translation>
<translation id="1181037720776840403">Poista</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Ilmoita Googlelle automaattisesti<ph name="END_WHITEPAPER_LINK" /> mahdollisista turvallisuusongelmista. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Maksua ei suoritettu loppuun</translation>
<translation id="1201402288615127009">Seuraava</translation>
<translation id="1201895884277373915">Lisää tästä sivustosta</translation>
<translation id="1206967143813997005">Virheellinen alkuperäinen allekirjoitus</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Kaatumisraportti tallennettu <ph name="CRASH_TIME" /> (ei vielä lähetetty tai ohitettu)</translation>
<translation id="1270502636509132238">Noutotapa</translation>
<translation id="1285320974508926690">Älä käännä tätä sivustoa</translation>
+<translation id="1294154142200295408">Komentorivin muunnelmat</translation>
<translation id="129553762522093515">Hiljattain suljetut välilehdet</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Tyhjennä evästeet.<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Toimintasi <ph name="BEGIN_EMPHASIS" />saattaa silti näkyä<ph name="END_EMPHASIS" />
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Hyväksytyt luotto- ja maksukortit</translation>
<translation id="1519264250979466059">Koontipäivä</translation>
<translation id="1527263332363067270">Odotetaan yhteyttä…</translation>
+<translation id="1532118530259321453">Viesti tältä sivulta</translation>
<translation id="153384715582417236">Siinä kaikki toistaiseksi</translation>
<translation id="154408704832528245">Valitse jakeluosoite</translation>
<translation id="1549470594296187301">Tämän ominaisuuden käyttö edellyttää JavaScriptiä.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Tarkista välityspalvelimen ja palomuurin määritykset.<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Postinumero</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 ehdotus}other{# ehdotusta}}</translation>
-<translation id="2065985942032347596">Käyttöoikeustarkistus pakollinen</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="2091887806945687916">Ääni</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Peruuta maksu</translation>
<translation id="2147827593068025794">Taustasynkronointi</translation>
<translation id="2148613324460538318">Lisää kortti</translation>
-<translation id="2149973817440762519">Muokkaa kirjanmerkkiä</translation>
<translation id="2154054054215849342">Synkronointi ei ole käytettävissä verkkotunnuksessasi.</translation>
<translation id="2154484045852737596">Muokkaa korttia</translation>
<translation id="2166049586286450108">Järjestelmänvalvojan täydet käyttöoikeudet</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Valitse noutopaikan osoite</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Poista valitut kohteet</translation>
-<translation id="2744590937989388266">Tälle sivulle upotetulta sivulta</translation>
<translation id="277133753123645258">Lähetystapa</translation>
<translation id="277499241957683684">Laitetallenne puuttuu</translation>
<translation id="2784949926578158345">Yhteys katkaistiin.</translation>
<translation id="2788784517760473862">Hyväksytyt luottokortit</translation>
<translation id="2794233252405721443">Sivusto estetty</translation>
-<translation id="2795286477369100655">Haluatko poistua tältä sivustolta?</translation>
<translation id="2799020568854403057">Sivusto sisältää haitallisia sovelluksia</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="2824775600643448204">Osoite- ja hakupalkki</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Luettelokohde "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Estetty automaattisesti</translation>
<translation id="3024663005179499861">Väärä käytäntötyyppi</translation>
-<translation id="3032412215588512954">Haluatko päivittää tämän sivuston?</translation>
<translation id="3037605927509011580">Voi räkä!</translation>
<translation id="3039538478787849737">Tallennetaanko kortti Googleen?</translation>
<translation id="3041612393474885105">Varmenteen tiedot</translation>
@@ -311,6 +307,7 @@
käytössä:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" />, palvelin: <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Peruuta maksu</translation>
<translation id="3207960819495026254">Kirjanmerkeissä</translation>
<translation id="3209375525920864198">Anna kelvollinen istunnon nimi.</translation>
@@ -368,11 +365,57 @@
<translation id="3556433843310711081">Ylläpitäjä voi kumota eston puolestasi.</translation>
<translation id="3566021033012934673">Yhteytesi ei ole salattu</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Viesti upotetulta sivulta osoitteessa <ph name="SITE" /></translation>
<translation id="358285529439630156">Luotto- ja prepaid-kortit hyväksytään.</translation>
<translation id="3582930987043644930">Lisää nimi</translation>
<translation id="3583757800736429874">&amp;Toista siirto</translation>
<translation id="3586931643579894722">Piilota lisätiedot</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Yhteysvirheiden korjaaminen&lt;/h1&gt;
+ &lt;p&gt;Kokeile näitä keinoja, jos näet virheilmoituksen yrittäessäsi siirtyä verkkosivustolle.&lt;/p&gt;
+ &lt;h2&gt;Useimpien yhteysvirheiden korjaaminen&lt;/h2&gt;
+ &lt;p&gt;Jos verkkosivuston avaaminen ei onnistu, kokeile ensin seuraavia vianetsintäkeinoja:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Tarkista verkko-osoitteen oikeinkirjoitus.&lt;/li&gt;
+ &lt;li&gt;Varmista, että internetyhteytesi toimii.&lt;/li&gt;
+ &lt;li&gt;Ota yhteyttä verkkosivuston omistajaan.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Tiettyjä virheviestejä koskevat ohjeet&lt;/h2&gt;
+ &lt;h3&gt;Yhteytesi ei ole salattu, NET::ERR_CERT_AUTHORITY_INVALID, ERR_CERT_COMMON_NAME_INVALID, NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM tai SSL-varmennevirhe&lt;/h3&gt;
+ &lt;h4&gt;Vaihe 1: Kirjaudu sisään portaaliin&lt;/h4&gt;
+ &lt;p&gt;Kahviloiden, lentokenttien ja joidenkin muiden paikkojen Wi-Fi-verkot voivat edellyttää kirjautumista. Avaa kirjautumissivu siirtymällä sivulle, jonka osoitteessa on &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Siirry mille tahansa &lt;code&gt;http://&lt;/code&gt;-alkuiselle sivustolle, esim. &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Kirjaudu sisään avautuvalla sivulla, niin voit käyttää internetiä.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Vaihe 2: Avaa sivu incognito-tilassa (vain tietokoneella)&lt;/h4&gt;
+ &lt;p&gt;Avaa incognito-ikkunassa sivu, jolla olit.&lt;/p&gt;
+ &lt;p&gt;Jos sivu avautuu, ongelman aiheuttaa Chromen laajennus. Korjaa virhe poistamalla laajennus käytöstä.&lt;/p&gt;
+ &lt;h4&gt;Vaihe 3: Päivitä käyttöjärjestelmä&lt;/h4&gt;
+ &lt;p&gt;Varmista, että laitteesi käyttöjärjestelmä on ajan tasalla.&lt;/p&gt;
+ &lt;h4&gt;Vinkki 4: Poista virustorjuntaohjelmisto käytöstä väliaikaisesti&lt;/h4&gt;
+ &lt;p&gt;Näet tämän virheen, jos käyttämäsi virustorjuntaohjelmiston HTTPS-suojaus tai HTTPS-skannaus estää Chromen tietoturvatoimintojen käytön.&lt;/p&gt;
+ &lt;p&gt;Voit korjata ongelman poistamalla virustorjuntaohjelmiston käytöstä. Jos sivu toimii ohjelmiston sammuttamisen jälkeen, poista ohjelmisto käytöstä turvallisilla sivustoilla.&lt;/p&gt;
+ &lt;p&gt;Kun olet valmis, muista ottaa virustorjuntaohjelmistosi taas käyttöön.&lt;/p&gt;
+ &lt;h4&gt;Vaihe 5: Pyydä lisäapua&lt;/h4&gt;
+ &lt;p&gt;Jos näet edelleen virheen, ota yhteyttä verkkosivuston omistajaan.&lt;/p&gt;
+ &lt;h3&gt;Yhdistä verkkoon&lt;/h3&gt;
+ &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 ongelma valitsemalla &lt;strong&gt;Yhdistä&lt;/strong&gt; sivulla, jota yrität avata.&lt;/p&gt;
+ &lt;h3&gt;Kellosi jätättää, Kellosi edistää tai NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Näet tämän virheen, jos tietokoneen tai mobiililaitteen päivämäärä ja aika ovat virheellisiä.&lt;/p&gt;
+ &lt;p&gt;Korjaa ongelma avaamalla laitteen kello ja varmistamalla, että päivämäärä ja aika ovat oikein.&lt;/p&gt;
+ &lt;h3&gt;Tietokoneelle asennettu ohjelmisto estää Chromea muodostamasta turvallista yhteyttä verkkoon (vain Windows-tietokoneilla)&lt;/h3&gt;
+ &lt;p&gt;Näet tämän virheen, jos Windows-tietokoneellesi on asennettu Superfish-ohjelmisto.&lt;/p&gt;
+ &lt;p&gt;Voit poistaa ohjelmiston väliaikaisesti käytöstä ja päästä verkkoon noudattamalla näitä ohjeita. Ne edellyttävät järjestelmänvalvojan käyttöoikeuksia.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Valitse &lt;strong&gt;Käynnistä&lt;/strong&gt;, etsi &lt;strong&gt;Näytä paikalliset palvelut&lt;/strong&gt; ja valitse se.
+ &lt;li&gt;Valitse &lt;strong&gt;VisualDiscovery&lt;/strong&gt;.
+ &lt;li&gt;Valitse &lt;strong&gt;Käynnistystapa&lt;/strong&gt;-kohdasta &lt;strong&gt;Ei käytössä&lt;/strong&gt;.
+ &lt;li&gt;Valitse &lt;strong&gt;Palvelun tila&lt;/strong&gt; ‑kohdasta &lt;strong&gt;Pysäytä&lt;/strong&gt;.
+ &lt;li&gt;Valitse &lt;strong&gt;Käytä&lt;/strong&gt; ja sitten &lt;strong&gt;OK&lt;/strong&gt;.
+ &lt;li&gt;Saat ohjeita ohjelmiston pysyvään poistamiseen tietokoneelta &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chromen ohjekeskuksesta&lt;/a&gt;.
+ &lt;/ol&gt;</translation>
<translation id="3615877443314183785">Anna kelvollinen viimeinen voimassaolopäivä.</translation>
<translation id="36224234498066874">Poista selaustiedot...</translation>
<translation id="362276910939193118">Näytä koko selaushistoria</translation>
@@ -405,7 +448,6 @@
<translation id="3778403066972421603">Haluatko tallentaa tämän kortin Google-tilille ja tälle laitteelle?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Vanhenee <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Sivustolta <ph name="SITE" /></translation>
<translation id="382518646247711829">Jos käytät välityspalvelinta…</translation>
<translation id="3828924085048779000">Tunnuslause ei voi olla tyhjä.</translation>
<translation id="385051799172605136">Edellinen</translation>
@@ -419,6 +461,7 @@
<translation id="3945915738023014686">Kaatumisraportti lähetetty, raporttitunnus: <ph name="CRASH_ID" /> (paikallinen kaatumistunnus: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Palvelin ei voinut todistaa olevansa <ph name="DOMAIN" />; sen suojausvarmenteessa ei määritetä kohteen vaihtoehtoisia nimiä. Tämä voi johtua määritysvirheestä tai verkkoyhteytesi siepanneesta hyökkääjästä.</translation>
<translation id="3949601375789751990">Selaushistoriasi näkyy tässä.</translation>
+<translation id="3950820424414687140">Kirjaudu sisään</translation>
<translation id="3963721102035795474">Lukijatila</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Ei mitään}=1{1 sivustolta }other{# sivustolta }}</translation>
<translation id="397105322502079400">Lasketaan...</translation>
@@ -435,6 +478,7 @@
<translation id="4103249731201008433">Laitteen sarjanumero on virheellinen</translation>
<translation id="410351446219883937">Automaattinen toisto</translation>
<translation id="4103763322291513355">Voit lukea listan kielletyistä URL-osoitteista ja muut järjestelmänvalvojasi määräämät käytännöt osoitteessa &lt;strong&gt;chrome://policy&lt;/strong&gt;.</translation>
+<translation id="4110652170750985508">Tarkasta maksu</translation>
<translation id="4116663294526079822">Salli aina tässä sivustossa</translation>
<translation id="4117700440116928470">Käytännön laajuutta ei tueta.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 muu}other{# muuta}}</translation>
@@ -461,7 +505,6 @@
<translation id="4269787794583293679">(Ei käyttäjänimeä)</translation>
<translation id="4275830172053184480">Käynnistä laite uudelleen</translation>
<translation id="4280429058323657511">, vanhentumispäivä <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Kirjaudu sisään</translation>
<translation id="4312866146174492540">Estä (oletus)</translation>
<translation id="4325863107915753736">Artikkelia ei löydy</translation>
<translation id="4326324639298822553">Tarkista vanhentumispäivä ja yritä uudelleen.</translation>
@@ -483,14 +526,12 @@
<translation id="4515275063822566619">Kortit ja osoitteet ovat peräisin Chromesta ja Google-tililtäsi (<ph name="ACCOUNT_EMAIL" />). Voit hallinnoida niitä <ph name="BEGIN_LINK" />asetuksissa<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Tiedot</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Sivustolla <ph name="SITE" /> olevalta upotetulta sivulta</translation>
<translation id="4558551763791394412">Poista laajennukset käytöstä.</translation>
<translation id="457875822857220463">Toimitus</translation>
<translation id="4582800630050655161">Saatat menettää Google-tilisi käyttöoikeuden tai joutua identiteettivarkauden uhriksi. Chromium suosittelee vaihtamaan salasanan nyt.</translation>
<translation id="4587425331216688090">Poistetaanko osoite Chromen tiedoista?</translation>
<translation id="4592951414987517459">Yhteytesi kohteeseen <ph name="DOMAIN" /> on salattu nykyaikaisella salaustekniikalla.</translation>
<translation id="4594403342090139922">K&amp;umoa poisto</translation>
-<translation id="4611292653554630842">Kirjaudu sisään</translation>
<translation id="4619615317237390068">Välilehdet muista laitteista</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Palvelin ei voinut todistaa olevansa <ph name="DOMAIN" />; sen suojausvarmenne sisältää virheitä. Tämä voi johtua määritysvirheestä tai verkkoyhteytesi siepanneesta hyökkääjästä.</translation>
@@ -500,11 +541,9 @@
<translation id="4708268264240856090">Yhteys keskeytyi</translation>
<translation id="471880041731876836">Sinulla ei ole lupaa siirtyä tälle sivustolle.</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windowsin verkon diagnostiikkaa<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Maksu</translation>
<translation id="4726672564094551039">Päivitä käytännöt</translation>
<translation id="4728558894243024398">Käyttöympäristö</translation>
<translation id="4736825316280949806">Käynnistä Chromium uudelleen.</translation>
-<translation id="4737498291095696011">Tältä sivulta</translation>
<translation id="4744603770635761495">Suoritettavan tiedoston polku</translation>
<translation id="4749685221585524849">Käytetty viimeksi: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Salasanat, luottokorttinumerot ja muut tietosi pysyvät yksityisinä, kun ne lähetetään tälle sivustolle.</translation>
@@ -523,16 +562,16 @@
<translation id="4850886885716139402">Näytä</translation>
<translation id="4854362297993841467">Tämä toimitustapa ei ole käytettävissä. Kokeile toista tapaa.</translation>
<translation id="4858792381671956233">Pyysit vanhemmiltasi lupaa käydä tällä sivustolla.</translation>
-<translation id="4871132632506079383">Sivustolla <ph name="SITE" /> olevalta upotetulta sivulta</translation>
<translation id="4880827082731008257">Haku historiasta</translation>
+<translation id="4881695831933465202">Avaa</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Todennus vaaditaan</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{ja 1 muu verkkosivu}other{ja # muuta verkkosivua}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Anna kortin <ph name="CREDIT_CARD" /> CVC. Vahvistamisen jälkeen Google-maksutilisi korttitiedot jaetaan tämän sivuston kanssa.</translation>
<translation id="4923417429809017348">Tämä sivu on käännetty tuntemattomasta kielestä kielelle <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Maksu</translation>
<translation id="4926049483395192435">On määritettävä.</translation>
+<translation id="4926159001844873046">Viesti osoitteesta <ph name="SITE" /></translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Toiminnot</translation>
<translation id="4958444002117714549">Laajenna luettelo</translation>
@@ -541,7 +580,6 @@
<translation id="5002932099480077015">Kun tämä vaihtoehto on käytössä, Chrome nopeuttaa lomakkeiden täyttämistä tallentamalla kortin tiedot tälle laittelle.</translation>
<translation id="5018422839182700155">Sivun avaaminen epäonnistui</translation>
<translation id="5019198164206649151">Tallennustila on virheellisessä tilassa</translation>
-<translation id="5020990877659450221">Tältä sivulta</translation>
<translation id="5023310440958281426">Tarkista järjestelmänvalvojan käytännöt</translation>
<translation id="5029568752722684782">Poista kopio</translation>
<translation id="503069730517007720">Ohjelmiston <ph name="SOFTWARE_NAME" /> juurivarmennetta edellytetään, mutta sitä ei ole asennettu. IT-järjestelmänvalvojan on tutustuttava ohjelmiston <ph name="SOFTWARE_NAME" /> määritysohjeisiin, jotta hän voi korjata tämän ongelman. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -567,12 +605,12 @@
<translation id="5172758083709347301">Kaikki tietokoneen käyttäjät</translation>
<translation id="5179510805599951267">Eikö kieli ole <ph name="ORIGINAL_LANGUAGE" />? Ilmoita virheestä</translation>
<translation id="5190835502935405962">Kirjanmerkkipalkki</translation>
+<translation id="5201306358585911203">Viesti tälle sivulle upotetulta sivulta</translation>
<translation id="5205222826937269299">Nimi vaaditaan</translation>
<translation id="5222812217790122047">Sähköposti vaaditaan</translation>
<translation id="522700295135997067">Tämä sivusto saattoi juuri varastaa salasanasi.</translation>
<translation id="5230733896359313003">Toimitusosoite</translation>
<translation id="5251803541071282808">Pilvi</translation>
-<translation id="5277279256032773186">Käytätkö Chromea töissä? Yritykset voivat hallita Chromen asetuksia työntekijöidensä puolesta. Lisätietoja</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Voit poistaa ohjelmiston väliaikaisesti käytöstä ja päästä verkkoon noudattamalla näitä ohjeita. Nämä vaiheet edellyttävät järjestelmänvalvojan käyttöoikeuksia.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -634,7 +672,6 @@
<translation id="5610142619324316209">Tarkista yhteys.</translation>
<translation id="5610807607761827392">Voit hallita kortteja ja osoitteita <ph name="BEGIN_LINK" />Asetuksissa<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> uudelleenohjasi sinut liian monta kertaa.</translation>
-<translation id="5622887735448669177">Haluatko poistua tältä sivustolta?</translation>
<translation id="5629630648637658800">Käytännön asetuksien lataaminen epäonnistui</translation>
<translation id="5631439013527180824">Laitteenhallintatunnus on virheellinen</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>
@@ -657,7 +694,6 @@
<translation id="5786044859038896871">Täytetäänkö kortin tiedot?</translation>
<translation id="5803412860119678065">Täytetäänkö kortin <ph name="CARD_DETAIL" /> tiedot?</translation>
<translation id="5810442152076338065">Yhteytesi kohteeseen <ph name="DOMAIN" /> on salattu vanhentuneella salaustekniikalla.</translation>
-<translation id="5810928923025889964">Tälle sivulle upotetulta sivulta</translation>
<translation id="5813119285467412249">&amp;Toista lisäys</translation>
<translation id="5838278095973806738">Älä anna tälle sivustolle salasanoja, luottokorttinumeroita tai muita arkaluonteisia tietoja, sillä hyökkääjät saattavat varastaa ne.</translation>
<translation id="5866257070973731571">Lisää puhelinnumero</translation>
@@ -731,21 +767,19 @@
<translation id="6446608382365791566">Lisää tietoja</translation>
<translation id="6447842834002726250">Evästeet</translation>
<translation id="6451458296329894277">Vahvista lomakkeen uudelleenlähetys</translation>
-<translation id="6456339708790392414">Maksu</translation>
<translation id="647261751007945333">Laitekäytännöt</translation>
<translation id="6477321094435799029">Chrome havaitsi tällä sivulla epätavallista koodia ja esti sen suojellakseen henkilötietojasi (esimerkiksi salasanoja, puhelinnumeroita tai luottokorttitietoja).</translation>
<translation id="6489534406876378309">Aloita kaatumistietojen lähettäminen</translation>
<translation id="6507833130742554667">Luotto- ja maksukortit hyväksytään.</translation>
<translation id="6508722015517270189">Käynnistä Chrome uudelleen.</translation>
-<translation id="6521373090216409766">Haluatko päivittää tämän sivuston?</translation>
<translation id="6529602333819889595">&amp;Toista poisto</translation>
<translation id="6534179046333460208">Fyysisen webin ehdotukset</translation>
<translation id="6550675742724504774">Asetukset</translation>
-<translation id="6556239504065605927">Suojattu yhteys</translation>
<translation id="6556915248009097796">Vanhenee: <ph name="EXPIRATION_DATE_ABBR" />, käytetty viimeksi: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Ylläpitäjä ei ole hyväksynyt sitä vielä.</translation>
<translation id="6569060085658103619">Tämä on laajennussivu.</translation>
<translation id="6596325263575161958">Salausasetukset</translation>
+<translation id="6604181099783169992">Liike- tai valotunnistimet</translation>
<translation id="6624427990725312378">Yhteystiedot</translation>
<translation id="6626291197371920147">Lisää kelvollinen kortin numero</translation>
<translation id="6628463337424475685"><ph name="ENGINE" />-haku</translation>
@@ -817,6 +851,7 @@
<translation id="7275334191706090484">Hallinnoidut kirjanmerkit</translation>
<translation id="7298195798382681320">Suositus</translation>
<translation id="7309308571273880165">Kaatumisraportti tallennettu <ph name="CRASH_TIME" /> (käyttäjä pyysi latausta, ei vielä ladattu)</translation>
+<translation id="7320336641823683070">Yhteysohjeet</translation>
<translation id="7334320624316649418">&amp;Toista uudelleenjärjestely</translation>
<translation id="733923710415886693">Palvelimen varmenteesta ei ole saatu Certificate Transparencyn vaatimia tietoja.</translation>
<translation id="7353601530677266744">Komentorivi</translation>
@@ -901,6 +936,7 @@
<translation id="782886543891417279">Käyttämäsi Wi-Fi (<ph name="WIFI_NAME" />) saattaa edellyttää kirjautumista.</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="7862185352068345852">Poistutaanko sivustolta?</translation>
<translation id="7878176543348854470">Maksu- ja prepaid-kortit hyväksytään.</translation>
<translation id="7878562273885520351">Salasanasi on saattanut vaarantua.</translation>
<translation id="7887683347370398519">Tarkista CVC ja yritä uudelleen.</translation>
@@ -923,6 +959,7 @@
<translation id="8041940743680923270">Käytä yleistä oletusasetusta (kysy)</translation>
<translation id="8042918947222776840">Valitse noutotapa</translation>
<translation id="8057711352706143257"><ph name="SOFTWARE_NAME" /> on määritetty virheellisesti. Ongelma korjaantuu yleensä, jos <ph name="SOFTWARE_NAME" /> poistetaan. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Ladataanko sivusto uudelleen?</translation>
<translation id="8088680233425245692">Artikkelin näyttäminen epäonnistui.</translation>
<translation id="8091372947890762290">Aktivointi odottaa palvelimella</translation>
<translation id="8094917007353911263">Käyttämäsi verkko saattaa edellyttää vierailua osoitteessa <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -938,6 +975,7 @@
<translation id="8201077131113104583">Laajennuksella, jonka tunnus on <ph name="EXTENSION_ID" />, on virheellinen päivitys-URL-osoite.</translation>
<translation id="8202097416529803614">Tilauksen yhteenveto</translation>
<translation id="8205463626947051446">Sivusto näyttää häiritseviä mainoksia.</translation>
+<translation id="8211406090763984747">Yhteys on turvallinen</translation>
<translation id="8218327578424803826">Määrätty sijainti:</translation>
<translation id="8225771182978767009">Tämän tietokoneen määrittänyt henkilö on estänyt tämän sivuston.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -949,6 +987,7 @@
<translation id="825929999321470778">Näytä kaikki tallennetut salasanat</translation>
<translation id="8261506727792406068">Poista</translation>
<translation id="8267698848189296333">Kirjaudutaan käyttäjänä <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Kirjaudu sisään</translation>
<translation id="8288807391153049143">Näytä varmenne</translation>
<translation id="8289355894181816810">Ota yhteyttä verkon ylläpitäjään, jos et tiedä, mitä tämä tarkoittaa.</translation>
<translation id="8293206222192510085">Lisää kirjanmerkki</translation>
@@ -1000,6 +1039,7 @@
<translation id="874846938927089722">Hyväksytyt luotto- ja prepaid-kortit</translation>
<translation id="8759274551635299824">Tämä kortti on vanhentunut.</translation>
<translation id="8761567432415473239">Google-selaussuoja <ph name="BEGIN_LINK" />löysi hiljattain haitallisia ohjelmia<ph name="END_LINK" /> sivustolta <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">USB-laite</translation>
<translation id="8790007591277257123">&amp;Toista poisto</translation>
<translation id="8800988563907321413">Nearby-ehdotuksesi näkyvät tässä.</translation>
<translation id="8820817407110198400">Kirjanmerkit</translation>
diff --git a/chromium/components/strings/components_strings_fil.xtb b/chromium/components/strings/components_strings_fil.xtb
index 0d84e914074..19e3bf400cf 100644
--- a/chromium/components/strings/components_strings_fil.xtb
+++ b/chromium/components/strings/components_strings_fil.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;I-print...</translation>
<translation id="1181037720776840403">Alisin</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Awtomatikong iulat<ph name="END_WHITEPAPER_LINK" /> ang mga detalye ng mga posibleng insidente ng seguridad sa Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Hindi Nakumpleto ang Pagbabayad</translation>
<translation id="1201402288615127009">Susunod</translation>
<translation id="1201895884277373915">Higit pa mula sa site na ito</translation>
<translation id="1206967143813997005">Hindi magandang paunang signature</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Ulat ng pag-crash na nakuha noong <ph name="CRASH_TIME" /> (hindi pa naa-upload o nababalewala)</translation>
<translation id="1270502636509132238">Paraan sa Pag-pick up</translation>
<translation id="1285320974508926690">Huwag isalin kailanman ang site na ito</translation>
+<translation id="1294154142200295408">Mga variation ng command-line</translation>
<translation id="129553762522093515">Kamakailang isinara</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Subukang i-clear ang iyong cookies<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Ang iyong aktibidad <ph name="BEGIN_EMPHASIS" />ay maaari pa ring makita<ph name="END_EMPHASIS" /> ng:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Mga tinatanggap na credit at debit card</translation>
<translation id="1519264250979466059">Petsa ng Build</translation>
<translation id="1527263332363067270">Naghihintay ng koneksyon…</translation>
+<translation id="1532118530259321453">Isinasaad ng page na ito na</translation>
<translation id="153384715582417236">'Yan na muna sa ngayon</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>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Suriin ang proxy at ang firewall<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">ZIP code</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suhestyon}one{# suhestyon}other{# na suhestyon}}</translation>
-<translation id="2065985942032347596">Kinakailangan na Pagpapatunay</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="2091887806945687916">Tunog</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Kanselahin ang pagbabayad</translation>
<translation id="2147827593068025794">Pag-sync sa Background</translation>
<translation id="2148613324460538318">Magdagdag ng Card</translation>
-<translation id="2149973817440762519">I-edit ang Bookmark</translation>
<translation id="2154054054215849342">Hindi available ang pag-sync para sa iyong domain</translation>
<translation id="2154484045852737596">I-edit ang card</translation>
<translation id="2166049586286450108">Ganap na Access ng Admin</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Pumili ng Address sa Pag-pick up</translation>
<translation id="2740531572673183784">Ok</translation>
<translation id="2742870351467570537">Alisin ang mga napiling item</translation>
-<translation id="2744590937989388266">Mula sa Naka-embed na Page sa Page na Ito</translation>
<translation id="277133753123645258">Pamamaraan ng pagpapadala</translation>
<translation id="277499241957683684">Nawawalang tala ng device</translation>
<translation id="2784949926578158345">Na-reset ang koneksyon.</translation>
<translation id="2788784517760473862">Mga tinatanggap na credit card</translation>
<translation id="2794233252405721443">Naka-block ang site</translation>
-<translation id="2795286477369100655">Gusto Mo bang Umalis sa Site na Ito?</translation>
<translation id="2799020568854403057">Naglalaman ng mga mapaminsalang app ang pupuntahang site</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="2824775600643448204">Address bar at bar sa paghahanap</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Listahan ng entry na "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Awtomatikong na-block</translation>
<translation id="3024663005179499861">Maling uri ng patakaran</translation>
-<translation id="3032412215588512954">Gusto mo bang i-reload ang site na ito?</translation>
<translation id="3037605927509011580">Ay, Naku!</translation>
<translation id="3039538478787849737">I-save ang card sa Google?</translation>
<translation id="3041612393474885105">Impormasyon sa Certificate</translation>
@@ -310,6 +306,7 @@
administrator upang matiyak na gumagana ang proxy server. Kung sa palagay mo
ay hindi ka dapat gumagamit ng proxy server:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> sa <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Kanselahin ang Pagbabayad</translation>
<translation id="3207960819495026254">Naka-bookmark</translation>
<translation id="3209375525920864198">Maglagay ng valid na pangalan ng session.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Maaari itong i-unblock ng iyong manager para sa iyo</translation>
<translation id="3566021033012934673">Hindi pribado ang iyong koneksyon</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Isinasaad ng naka-embed na page sa <ph name="SITE" /> na</translation>
<translation id="358285529439630156">Tinatanggap ang mga credit at prepaid card.</translation>
<translation id="3582930987043644930">Magdagdag ng pangalan</translation>
<translation id="3583757800736429874">&amp;Gawing Muli ang Paglilipat</translation>
<translation id="3586931643579894722">Magtago ng mga detalye</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Ayusin ang mga error sa koneksyon&lt;/h1&gt;
+ &lt;p&gt;Kung makatanggap ka ng mensahe ng error kapag sinubukan mong bumisita sa isang website, subukan ang mga pag-aayos na ito.&lt;/p&gt;
+ &lt;h2&gt;Ayusin ang karamihan ng mga error sa koneksyon&lt;/h2&gt;
+ &lt;p&gt;Kung sinubukan mong bumisita sa isang website at hindi ito nagbubukas, subukan munang ayusin ang error sa pamamagitan ng mga hakbang na ito sa pag-troubleshoot:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Suriin kung may mga typo ang address sa web.&lt;/li&gt;
+ &lt;li&gt;Tiyaking gumagana nang normal ang iyong koneksyon sa internet.&lt;/li&gt;
+ &lt;li&gt;Makipag-ugnayan sa may-ari ng website.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Humingi ng tulong tungkol sa isang partikular na mensahe ng error&lt;/h2&gt;
+ &lt;h3&gt;"Hindi pribado ang iyong koneksyon" o "NET::ERR_CERT_AUTHORITY_INVALID" o "ERR_CERT_COMMON_NAME_INVALID" o "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" o "Error sa SSL certificate"&lt;/h3&gt;
+ &lt;h4&gt;Hakbang 1: Mag-sign in sa portal&lt;/h4&gt;
+ &lt;p&gt;Kailangan mong mag-sign in sa mga Wi-Fi network sa mga lugar tulad ng mga cafe o airport. Para makita ang page ng pag-sign in, bisitahin ang isang page na gumagamit ng&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Pumunta sa anumang website na nagsisimula sa &lt;code&gt;http://&lt;/code&gt;, tulad ng &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Sa bubukas na page sa pag-sign in, mag-sign in para magamit ang internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Hakbang 2: Buksan ang page sa Incognito mode (computer lang)&lt;/h4&gt;
+ &lt;p&gt;Buksan ang page na binibisita mo sa isang Incognito window.&lt;/p&gt;
+ &lt;p&gt;Kung bubukas ang page, hindi gumagana nang maayos ang isang extension ng Chrome. Para ayusin ang error, i-off ang extension.&lt;/p&gt;
+ &lt;h4&gt;Hakbang 3: I-update ang iyong operating system&lt;/h4&gt;
+ &lt;p&gt;Tiyaking na-update ang iyong device.&lt;/p&gt;
+ &lt;h4&gt;Hakbang 4: Pansamantalang i-off ang iyong antivirus&lt;/h4&gt;
+ &lt;p&gt;Makikita mo ang error na ito kung mayroon kang antivirus software na nagbibigay ng "Proteksyon sa HTTPS" o "Pag-scan sa HTTPS." Pinipigilan ng antivirus ang Chrome sa pagbibigay ng seguridad.&lt;/p&gt;
+ &lt;p&gt;Para ayusin ang problema, i-off ang iyong antivirus software. Kung gagana ang page pagkatapos i-off ang software, i-off ang software na ito kapag gumagamit ka ng mga secure na site.&lt;/p&gt;
+ &lt;p&gt;Kapag tapos ka na, huwag kalimutang i-on muli ang iyong antivirus program.&lt;/p&gt;
+ &lt;h4&gt;Hakbang 5: Humingi ng karagdagang tulong&lt;/h4&gt;
+ &lt;p&gt;Kung nakikita mo pa rin ang error, makipag-ugnayan sa may-ari ng website.&lt;/p&gt;
+ &lt;h3&gt;"Kumonekta sa network"&lt;/h3&gt;
+ &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 ayusin ang error, i-click ang &lt;strong&gt;Kumonekta&lt;/strong&gt; sa page na sinusubukan mong buksan.&lt;/p&gt;
+ &lt;h3&gt;"Nahuhuli ang iyong orasan" o "Nauuna ang iyong orasan" o "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Makikita mo ang error na ito kung hindi tumpak ang petsa at oras ng iyong computer o mobile device.&lt;/p&gt;
+ &lt;p&gt;Para ayusin ang error, buksan ang orasan ng iyong device. Tiyaking tama ang oras at petsa.&lt;/p&gt;
+ &lt;h3&gt;"Pinipigilan ng software sa iyong computer na makakonekta nang ligtas ang Chrome sa web" (Mga Windows computer lang)&lt;/h3&gt;
+ &lt;p&gt;Makikita mo ang error na ito kung mayroon kang Superfish software sa iyong Windows computer.&lt;/p&gt;
+ &lt;p&gt;Sundin ang mga hakbang na ito para pansamantalang i-disable ang software para makapunta ka sa web. Kakailanganin mo ng mga pribilehiyong pang-administrator.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;I-click ang &lt;strong&gt;Magsimula&lt;/strong&gt;, pagkatapos ay hanapin at piliin ang &lt;strong&gt;"Tingnan ang mga lokal na serbisyo"&lt;/strong&gt;
+ &lt;li&gt;Piliin ang &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Sa ilalim ng &lt;strong&gt;Uri ng startup&lt;/strong&gt;, piliin ang &lt;strong&gt;Naka-disable&lt;/strong&gt;
+ &lt;li&gt;Piliin ang &lt;strong&gt;Status ng serbisyo&lt;/strong&gt;, i-click ang &lt;strong&gt;Ihinto&lt;/strong&gt;
+ &lt;li&gt;I-click ang &lt;strong&gt;Ilapat&lt;/strong&gt;, pagkatapos ay i-click ang &lt;strong&gt;OK&lt;/strong&gt;
+ &lt;li&gt;Bisitahin ang&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;help center ng Chrome &lt;/a&gt; para alamin kung paano permanenteng alisin ang software sa iyong computer
+ &lt;/ol&gt;</translation>
<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>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Gusto mo bang i-save ang card na ito sa iyong Google Account at sa device na ito?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Mag-e-expire sa <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Mula sa <ph name="SITE" /></translation>
<translation id="382518646247711829">Kung gumagamit ka ng proxy server...</translation>
<translation id="3828924085048779000">Hindi pinapayagan ang walang laman na passphrase.</translation>
<translation id="385051799172605136">Bumalik</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">ID ng Na-upload na Ulat ng Pag-crash <ph name="CRASH_ID" /> (ID ng Lokal na Pag-crash: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Hindi mapatunayan ng server na ito na <ph name="DOMAIN" /> ito; hindi tinutukoy ng certificate ng seguridad nito ang Mga Alternatibong Pangalan ng Subject. Maaaring dahil ito sa isang maling configuration o sa isang umaatake na humahadlang sa iyong koneksyon.</translation>
<translation id="3949601375789751990">Lalabas dito ang iyong history ng pag-browse</translation>
+<translation id="3950820424414687140">Mag-sign in</translation>
<translation id="3963721102035795474">Reader Mode</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Wala}=1{Mula sa 1 site }one{Mula sa # site }other{Mula sa # na site }}</translation>
<translation id="397105322502079400">Kinakalkula...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Di-wasto ang serial number ng device</translation>
<translation id="410351446219883937">I-autoplay</translation>
<translation id="4103763322291513355">Bisitahin ang &lt;strong&gt;chrome://policy&lt;/strong&gt; upang makita ang listahan ng mga naka-blacklist na URL at iba pang mga patakaran na ipinapatupad ng iyong system administrator.</translation>
+<translation id="4110652170750985508">Suriin ang iyong pagbabayad</translation>
<translation id="4116663294526079822">Palaging payagan sa site na ito</translation>
<translation id="4117700440116928470">Hindi sinusuportahan ang saklaw ng patakaran.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 pa}one{# pa}other{# pa}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Walang username)</translation>
<translation id="4275830172053184480">I-restart ang iyong device</translation>
<translation id="4280429058323657511">, exp <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Mag-log In</translation>
<translation id="4312866146174492540">I-block (default)</translation>
<translation id="4325863107915753736">Hindi nahanap ang artikulo</translation>
<translation id="4326324639298822553">Tingnan ang iyong petsa ng pag-expire at subukang muli</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Ang mga card at address ay mula sa Chrome at sa iyong Google Account (<ph name="ACCOUNT_EMAIL" />). Maaari mong pamahalaan ang mga ito sa <ph name="BEGIN_LINK" />Mga Setting<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Mga Detalye</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Mula sa Naka-embed na Page sa <ph name="SITE" /></translation>
<translation id="4558551763791394412">Subukang i-disable ang iyong mga extension.</translation>
<translation id="457875822857220463">Paghahatid</translation>
<translation id="4582800630050655161">Maaari kang mawalan ng access sa iyong Google Account o manakawan ng pagkakakilanlan. Inirerekomenda ng Chromium na palitan na ang password mo.</translation>
<translation id="4587425331216688090">Alisin ang address sa Chrome?</translation>
<translation id="4592951414987517459">Naka-encrypt ang iyong koneksyon sa <ph name="DOMAIN" /> gamit ang isang makabagong cipher suite.</translation>
<translation id="4594403342090139922">&amp;I-undo ang Pagtanggal</translation>
-<translation id="4611292653554630842">Mag-log in</translation>
<translation id="4619615317237390068">Mga tab mula sa iba pang mga device</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Hindi mapatunayan ng server na ito na ito ay <ph name="DOMAIN" />; naglalaman ng mga error ang certificate ng seguridad nito. Maaaring dulot ito ng maling configuration o isang umaatake na hinahadlangan ang iyong koneksyon.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Naputol ang iyong koneksyon</translation>
<translation id="471880041731876836">Wala kang pahintulot na bisitahin ang site na ito</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Magpatakbo ng Windows Network Diagnostics<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Iyong pagbabayad</translation>
<translation id="4726672564094551039">I-reload ang mga patakaran</translation>
<translation id="4728558894243024398">Platform</translation>
<translation id="4736825316280949806">I-restart ang Chromium</translation>
-<translation id="4737498291095696011">Mula sa Page na Ito</translation>
<translation id="4744603770635761495">Naipapatupad na Path</translation>
<translation id="4749685221585524849">Huling ginamit noong <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Pribado ang iyong impormasyon (halimbawa, mga password o credit card number) kapag ipinadala ito sa site na ito.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">View</translation>
<translation id="4854362297993841467">Hindi available ang pamamaraan ng paghahatid na ito. Sumubok ng ibang pamamaraan.</translation>
<translation id="4858792381671956233">Tinanong mo sa iyong mga magulang kung maaari mong bisitahin ang site na ito</translation>
-<translation id="4871132632506079383">Mula sa naka-embed na page sa <ph name="SITE" /></translation>
<translation id="4880827082731008257">History ng paghahanap</translation>
+<translation id="4881695831933465202">Buksan</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Kinakailangan ng pag-authenticate</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{at 1 pang web page}one{at # pang web page}other{at # pang web page}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Ilagay ang CVC para sa <ph name="CREDIT_CARD" />. Pagkatapos mong magkumpirma, ibabahagi sa site na ito ang mga detalye ng card mula sa iyong Google Payments account.</translation>
<translation id="4923417429809017348">Na-translate ang pahinang ito mula sa hindi kilalang wika patungo sa <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Pagbabayad</translation>
<translation id="4926049483395192435">Dapat na tukuyin.</translation>
+<translation id="4926159001844873046">Isinasaad ng <ph name="SITE" /> na</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Mga Pagkilos</translation>
<translation id="4958444002117714549">Palawakin ang listahan</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Kung naka-enable, mag-iimbak ang Chrome ng kopya ng iyong card sa device na ito para sa mas mabilis na pagsagot sa form.</translation>
<translation id="5018422839182700155">Hindi mabuksan ang page na ito</translation>
<translation id="5019198164206649151">Hindi maganda ang katayuan ng backing store</translation>
-<translation id="5020990877659450221">Mula sa page na ito</translation>
<translation id="5023310440958281426">Suriin ang mga patakaran ng iyong administrator</translation>
<translation id="5029568752722684782">I-clear ang kopya</translation>
<translation id="503069730517007720">Kinakailangan ang root certificate para sa "<ph name="SOFTWARE_NAME" />" ngunit hindi ito naka-install. Dapat tingnan ng IT administrator ang mga tagubilin sa pag-configure para sa "<ph name="SOFTWARE_NAME" />" upang maayos ang problemang ito. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Computer</translation>
<translation id="5179510805599951267">Wala sa <ph name="ORIGINAL_LANGUAGE" />? Iulat ang error na ito</translation>
<translation id="5190835502935405962">Bar ng Mga Bookmark</translation>
+<translation id="5201306358585911203">Isinasaad ng naka-embed na page sa page na ito na</translation>
<translation id="5205222826937269299">Kailangan ng pangalan</translation>
<translation id="5222812217790122047">Kailangan ng email</translation>
<translation id="522700295135997067">Maaaring ninakaw ng site na ito ang iyong password</translation>
<translation id="5230733896359313003">Address na Padadalhan</translation>
<translation id="5251803541071282808">Cloud</translation>
-<translation id="5277279256032773186">Ginagamit mo ba ang Chrome sa trabaho? Maaaring pamahalaan ng mga negosyo ang mga setting ng Chrome para sa kanilang mga empleyado. Matuto pa</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Sundin ang mga hakbang na ito upang pansamantalang i-disable ang software upang makapunta ka sa web. Kakailanganin mo ang mga pribilehiyong pang-administrator.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Suriin ang koneksyon</translation>
<translation id="5610807607761827392">Maaari mong pamahalaan ang mga card at address sa <ph name="BEGIN_LINK" />Mga Setting<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Masyadong maraming beses kang na-redirect ng <ph name="HOST_NAME" />.</translation>
-<translation id="5622887735448669177">Gusto mo bang umalis sa site na ito?</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="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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Gusto mo bang ilagay ang impormasyon ng iyong card?</translation>
<translation id="5803412860119678065">Gusto mo bang ilagay ang iyong <ph name="CARD_DETAIL" />?</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="5810928923025889964">Mula sa naka-embed na page sa page na ito</translation>
<translation id="5813119285467412249">&amp;Gawing Muli ang Pagdagdag</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>
<translation id="5866257070973731571">Magdagdag ng Numero ng Telepono</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Magdagdag ng higit pang impormasyon</translation>
<translation id="6447842834002726250">Cookies</translation>
<translation id="6451458296329894277">Muling pagsusumite ng Form sa Pagkumpirma</translation>
-<translation id="6456339708790392414">Iyong Pagbabayad</translation>
<translation id="647261751007945333">Mga patakaran sa device</translation>
<translation id="6477321094435799029">May natukoy na kakaibang code ang Chrome sa page na ito at na-block ito upang protektahan ang iyong personal na impormasyon (halimbawa, mga password, numero ng telepono at credit card).</translation>
<translation id="6489534406876378309">Simulang mag-upload ng mga pag-crash</translation>
<translation id="6507833130742554667">Tinatanggap ang mga credit at debit card.</translation>
<translation id="6508722015517270189">I-restart ang Chrome</translation>
-<translation id="6521373090216409766">Gusto Mo bang I-reload ang Site na Ito?</translation>
<translation id="6529602333819889595">&amp;Gawing Muli ang Pagtanggal</translation>
<translation id="6534179046333460208">Mga suhestyon sa Pisikal na Web</translation>
<translation id="6550675742724504774">Mga Pagpipilian</translation>
-<translation id="6556239504065605927">Secure na koneksyon</translation>
<translation id="6556915248009097796">Exp: <ph name="EXPIRATION_DATE_ABBR" />, huling ginamit noong <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Hindi pa ito inaaprubahan ng iyong manager</translation>
<translation id="6569060085658103619">Isang page ng extension ang tinitingnan mo</translation>
<translation id="6596325263575161958">Mga pagpipilian sa pag-encrypt</translation>
+<translation id="6604181099783169992">Mga Motion o Light Sensor</translation>
<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>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Mga Pinamamahalaang Bookmark</translation>
<translation id="7298195798382681320">Inirerekomenda</translation>
<translation id="7309308571273880165">Ulat ng pag-crash na nakuha noong <ph name="CRASH_TIME" /> (humiling ng pag-upload ang user, hindi pa naa-upload)</translation>
+<translation id="7320336641823683070">Tulong sa Koneksyon</translation>
<translation id="7334320624316649418">&amp;Gawing muli ang pagbabago sa ayos</translation>
<translation id="733923710415886693">Ang certificate ng server ay hindi inihayag sa pamamagitan ng Transparency ng Certificate.</translation>
<translation id="7353601530677266744">Command Line</translation>
@@ -900,6 +935,7 @@
<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="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="7862185352068345852">Umalis sa site?</translation>
<translation id="7878176543348854470">Tinatanggap ang mga debit at prepaid card.</translation>
<translation id="7878562273885520351">Maaaring makompromismo ang iyong password</translation>
<translation id="7887683347370398519">Tingnan ang iyong CVC at subukang muli</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Gamitin ang pangkalahatang default (Tanungin)</translation>
<translation id="8042918947222776840">Pumili ng Paraan ng Pag-pick up</translation>
<translation id="8057711352706143257">Hindi maayos na naka-configure ang "<ph name="SOFTWARE_NAME" />." Kadalasang naaayos ang problema kapag in-uninstall ang "<ph name="SOFTWARE_NAME" />." <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">I-reload ang site?</translation>
<translation id="8088680233425245692">Hindi natingnan ang artikulo.</translation>
<translation id="8091372947890762290">Nakabinbin sa server ang pag-activate</translation>
<translation id="8094917007353911263">Maaaring hilingin ng network na ginagamit mo na bisitahin mo ang <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<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>
<translation id="8205463626947051446">Malamang na magpakita ang site ng mga nakakasagabal na ad</translation>
+<translation id="8211406090763984747">Secure ang koneksyon</translation>
<translation id="8218327578424803826">Itinakdang Lokasyon:</translation>
<translation id="8225771182978767009">Pinili ng taong nag-set up ng computer na ito na i-block ang site na ito.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Ipakita ang Lahat ng Naka-save na Password</translation>
<translation id="8261506727792406068">I-delete</translation>
<translation id="8267698848189296333">Nagsa-sign in bilang <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Mag-sign In</translation>
<translation id="8288807391153049143">Ipakita ang certificate</translation>
<translation id="8289355894181816810">Makipag-ugnay sa administrator ng iyong network kung hindi ka sigurado kung ano ang ibig sabihin nito.</translation>
<translation id="8293206222192510085">Magdagdag ng Bookmark</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Mga Tinatanggap na Credit at Prepaid Card</translation>
<translation id="8759274551635299824">Nag-expire na ang card na ito</translation>
<translation id="8761567432415473239">Ang Google Safe Browsing ay may <ph name="BEGIN_LINK" />natagpuang mga nakakasirang program<ph name="END_LINK" /> sa <ph name="SITE" /> kamakailan.</translation>
+<translation id="8763927697961133303">USB device</translation>
<translation id="8790007591277257123">&amp;Gawing muli ang pagtanggal</translation>
<translation id="8800988563907321413">Lalabas dito ang iyong mga suhestyon na malapit</translation>
<translation id="8820817407110198400">Mga Bookmark</translation>
diff --git a/chromium/components/strings/components_strings_fr.xtb b/chromium/components/strings/components_strings_fr.xtb
index ac667abccba..f35d4ed0479 100644
--- a/chromium/components/strings/components_strings_fr.xtb
+++ b/chromium/components/strings/components_strings_fr.xtb
@@ -26,12 +26,11 @@
<translation id="1151972924205500581">Veuillez saisir un mot de passe</translation>
<translation id="1152921474424827756">Accédez à une <ph name="BEGIN_LINK" />copie mise en cache<ph name="END_LINK" /> de <ph name="URL" />.</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> a mis fin à la connexion de manière inattendue.</translation>
-<translation id="1161325031994447685">Se reconnecter au réseau Wi-Fi</translation>
+<translation id="1161325031994447685">Reconnectez-vous au réseau Wi-Fi</translation>
<translation id="1165039591588034296">Erreur</translation>
<translation id="1175364870820465910">Im&amp;primer...</translation>
<translation id="1181037720776840403">Supprimer</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Signaler automatiquement<ph name="END_WHITEPAPER_LINK" /> les incidents de sécurité potentiels à Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Paiement non finalisé</translation>
<translation id="1201402288615127009">Suivant</translation>
<translation id="1201895884277373915">Plus de résultats pour ce site</translation>
<translation id="1206967143813997005">Signature initiale incorrecte</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Rapport d'erreur enregistré le <ph name="CRASH_TIME" /> (pas encore importé ou ignoré)</translation>
<translation id="1270502636509132238">Mode d'enlèvement</translation>
<translation id="1285320974508926690">Ne jamais traduire ce site</translation>
+<translation id="1294154142200295408">Variations de ligne de commande</translation>
<translation id="129553762522093515">Récemment fermés</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Essayez de supprimer les cookies.<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Votre activité <ph name="BEGIN_EMPHASIS" />peut rester visible<ph name="END_EMPHASIS" /> par :
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Cartes de crédit et de débit acceptées</translation>
<translation id="1519264250979466059">Date de création</translation>
<translation id="1527263332363067270">En attente de connexion…</translation>
+<translation id="1532118530259321453">Cette page indique</translation>
<translation id="153384715582417236">C'est tout !</translation>
<translation id="154408704832528245">Sélectionner l'adresse d'expédition</translation>
<translation id="1549470594296187301">Vous devez activer JavaScript pour utiliser cette fonctionnalité.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Vérifier le proxy et le pare-feu<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Code postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggestion}one{# suggestion}other{# suggestions}}</translation>
-<translation id="2065985942032347596">Authentification requise</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="2091887806945687916">Son</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Annuler le paiement</translation>
<translation id="2147827593068025794">Synchronisation en arrière-plan</translation>
<translation id="2148613324460538318">Ajouter une carte</translation>
-<translation id="2149973817440762519">Modifier le favori</translation>
<translation id="2154054054215849342">La synchronisation n'est pas disponible pour votre domaine</translation>
<translation id="2154484045852737596">Modifier la carte</translation>
<translation id="2166049586286450108">Accès administrateur complet</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Sélectionner une adresse d'enlèvement</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Supprimer les éléments sélectionnés</translation>
-<translation id="2744590937989388266">Source : une page intégrée à cette page Web</translation>
<translation id="277133753123645258">Mode d'expédition</translation>
<translation id="277499241957683684">Enregistrement de l'appareil manquant.</translation>
<translation id="2784949926578158345">La connexion a été réinitialisée.</translation>
<translation id="2788784517760473862">Cartes de crédit acceptées</translation>
<translation id="2794233252405721443">Site bloqué</translation>
-<translation id="2795286477369100655">Voulez-vous quitter ce site ?</translation>
<translation id="2799020568854403057">Ce site contient des applications malveillantes</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="2824775600643448204">Barre d'adresse et de recherche</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Entrée de la liste "<ph name="ENTRY_INDEX" />" : <ph name="ERROR" /></translation>
<translation id="301521992641321250">Bloquée automatiquement</translation>
<translation id="3024663005179499861">Type de règle incorrect.</translation>
-<translation id="3032412215588512954">Voulez-vous actualiser ce site ?</translation>
<translation id="3037605927509011580">Aie aie aie</translation>
<translation id="3039538478787849737">Enregistrer la carte dans Google ?</translation>
<translation id="3041612393474885105">Informations relatives au certificat</translation>
@@ -310,6 +306,7 @@
vous assurer que le serveur proxy fonctionne. Si vous
ne pensez pas devoir utiliser de serveur proxy, procédez comme suit :
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> sur <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Annuler le paiement</translation>
<translation id="3207960819495026254">Favori</translation>
<translation id="3209375525920864198">Veuillez saisir un nom de session valide.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Votre responsable peut vous le débloquer</translation>
<translation id="3566021033012934673">Votre connexion n'est pas privée</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Une page intégrée à l'adresse <ph name="SITE" /> indique</translation>
<translation id="358285529439630156">Les cartes de crédit et les cartes prépayées sont acceptées.</translation>
<translation id="3582930987043644930">Ajouter un nom</translation>
<translation id="3583757800736429874">&amp;Rétablir le déplacement</translation>
<translation id="3586931643579894722">Masquer les détails</translation>
<translation id="3600246354004376029">"<ph name="TITLE" />", <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Corriger les erreurs de connexion&lt;/h1&gt;
+ &lt;p&gt;Si un message d'erreur s'affiche lorsque vous tentez de consulter un site Web, essayez les solutions proposées ci-dessous.&lt;/p&gt;
+ &lt;h2&gt;Résoudre la plupart des erreurs de connexion&lt;/h2&gt;
+ &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;
+ &lt;ol&gt;
+ &lt;li&gt;Assurez-vous que l'adresse Web ne contient pas de fautes de frappe.&lt;/li&gt;
+ &lt;li&gt;Vérifiez si votre connexion Internet fonctionne correctement.&lt;/li&gt;
+ &lt;li&gt;Contactez le propriétaire du site Web.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Obtenir de l'aide pour un message d'erreur spécifique&lt;/h2&gt;
+ &lt;h3&gt;"Votre connexion n'est pas privée", "NET::ERR_CERT_AUTHORITY_INVALID", "ERR_CERT_COMMON_NAME_INVALID", "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" ou "Erreur de certificat SSL"&lt;/h3&gt;
+ &lt;h4&gt;Étape 1 : Connectez-vous au portail&lt;/h4&gt;
+ &lt;p&gt;Pour utiliser les réseaux Wi-Fi de lieux publics tels que les cafés ou les aéroports, vous devez vous connecter. Pour afficher la page de connexion, accédez à une page dont l'URL contient &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Accédez à n'importe quel site Web dont l'adresse commence par &lt;code&gt;http://&lt;/code&gt;, telle que &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Sur la page de connexion qui s'affiche, connectez-vous pour utiliser Internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Étape 2 : Ouvrez la page en mode navigation privée (ordinateur uniquement)&lt;/h4&gt;
+ &lt;p&gt;Ouvrez la page que vous consultiez dans une fenêtre de navigation privée.&lt;/p&gt;
+ &lt;p&gt;Si la page s'affiche, cela signifie qu'une extension Chrome ne fonctionne pas correctement. Pour corriger cette erreur, désactivez l'extension en question.&lt;/p&gt;
+ &lt;h4&gt;Étape 3 : Mettez à jour votre système d'exploitation&lt;/h4&gt;
+ &lt;p&gt;Assurez-vous que votre appareil est à jour.&lt;/p&gt;
+ &lt;h4&gt;Étape 4 : Désactivez temporairement votre logiciel antivirus&lt;/h4&gt;
+ &lt;p&gt;Ce message s'affiche si vous avez un logiciel antivirus qui propose une "protection HTTPS" ou une "analyse HTTPS" bloquant la fonctionnalité de sécurité de Chrome.&lt;/p&gt;
+ &lt;p&gt;Pour corriger cette erreur, désactivez votre logiciel antivirus. Si la page fonctionne à la suite de cette opération, désactivez ce logiciel lorsque vous utilisez des sites sécurisés.&lt;/p&gt;
+ &lt;p&gt;N'oubliez pas de le réactiver par la suite.&lt;/p&gt;
+ &lt;h4&gt;Étape 5 : Obtenez de l'aide supplémentaire&lt;/h4&gt;
+ &lt;p&gt;Si le message d'erreur s'affiche toujours, contactez le propriétaire du site.&lt;/p&gt;
+ &lt;h3&gt;"Se connecter au réseau"&lt;/h3&gt;
+ &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;Connexion&lt;/strong&gt; sur la page que vous essayez d'ouvrir.&lt;/p&gt;
+ &lt;h3&gt;"Votre horloge est en retard", "Votre horloge est en avance" ou "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Ce message s'affiche si la date et l'heure de votre ordinateur ou de votre appareil mobile sont incorrectes.&lt;/p&gt;
+ &lt;p&gt;Pour corriger cette erreur, ouvrez l'horloge de votre appareil et assurez-vous que l'heure et la date sont correctes.&lt;/p&gt;
+ &lt;h3&gt;"Un logiciel installé sur votre ordinateur empêche Chrome de se connecter au Web de manière sécurisée" (sous Windows uniquement)&lt;/h3&gt;
+ &lt;p&gt;Ce message d'erreur s'affiche si le logiciel Superfish est installé sur votre ordinateur Windows.&lt;/p&gt;
+ &lt;p&gt;Suivez ces étapes pour désactiver temporairement le logiciel afin d'accéder au Web. Vous devez disposer des droits d'administrateur.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Cliquez sur &lt;strong&gt;Démarrer&lt;/strong&gt;, puis recherchez et sélectionnez l'option &lt;strong&gt;Afficher les services locaux&lt;/strong&gt;.
+ &lt;li&gt;Sélectionnez &lt;strong&gt;VisualDiscovery&lt;/strong&gt;.
+ &lt;li&gt;Sous &lt;strong&gt;Type de démarrage&lt;/strong&gt;, sélectionnez &lt;strong&gt;Désactivé&lt;/strong&gt;.
+ &lt;li&gt;Sous &lt;strong&gt;État du service&lt;/strong&gt;, cliquez sur &lt;strong&gt;Arrêter&lt;/strong&gt;.
+ &lt;li&gt;Cliquez sur &lt;strong&gt;Appliquer&lt;/strong&gt;, puis sur &lt;strong&gt;OK&lt;/strong&gt;.
+ &lt;li&gt;Accédez au &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centre d'aide Chrome&lt;/a&gt; pour découvrir comment supprimer définitivement le logiciel de votre ordinateur.
+ &lt;/ol&gt;</translation>
<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>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Voulez-vous enregistrer cette carte dans votre compte Google et sur cet appareil ?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Expire en <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Source : <ph name="SITE" /></translation>
<translation id="382518646247711829">Si vous utilisez un serveur proxy…</translation>
<translation id="3828924085048779000">La phrase secrète est obligatoire.</translation>
<translation id="385051799172605136">Retour</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">ID du rapport d'erreur importé : <ph name="CRASH_ID" /> (ID de plantage local : <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Impossible de vérifier que ce serveur est bien <ph name="DOMAIN" />, car son certificat de sécurité ne contient pas l'extension "Subject Alternative Names" (Autres noms de l'objet). Cela peut être dû à une mauvaise configuration ou à l'interception de votre connexion par un pirate informatique.</translation>
<translation id="3949601375789751990">Votre historique de navigation s'affiche ici</translation>
+<translation id="3950820424414687140">Ouvrir une session</translation>
<translation id="3963721102035795474">Mode lecture</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Aucun}=1{De 1 site }one{De # site }other{De # sites }}</translation>
<translation id="397105322502079400">Calcul en cours…</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Le numéro de série de l'appareil n'est pas valide.</translation>
<translation id="410351446219883937">Lecture automatique</translation>
<translation id="4103763322291513355">Accédez à &lt;strong&gt;chrome://policy&lt;/strong&gt; pour consulter une liste des URL ajoutées à la liste noire et des autres règles définies par votre administrateur système.</translation>
+<translation id="4110652170750985508">Vérifier votre paiement</translation>
<translation id="4116663294526079822">Toujours autoriser sur ce site</translation>
<translation id="4117700440116928470">La portée de la règle n'est pas compatible.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 autre}one{# autre}other{# autres}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(aucun nom d'utilisateur)</translation>
<translation id="4275830172053184480">Redémarrer l'appareil</translation>
<translation id="4280429058323657511">, expiration le <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Se connecter</translation>
<translation id="4312866146174492540">Bloquer (par défaut)</translation>
<translation id="4325863107915753736">Échec de la recherche de l'article.</translation>
<translation id="4326324639298822553">Veuillez vérifier la date d'expiration, puis réessayer</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Les cartes et les adresses proviennent de Chrome et de votre compte Google (<ph name="ACCOUNT_EMAIL" />). Vous pouvez les gérer dans les <ph name="BEGIN_LINK" />Paramètres<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Détails</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Source : une page intégrée à l'adresse <ph name="SITE" /></translation>
<translation id="4558551763791394412">Essayez de désactiver les extensions.</translation>
<translation id="457875822857220463">Livraison</translation>
<translation id="4582800630050655161">Vous pourriez perdre l'accès à votre compte Google ou vous faire dérober votre identité. L'équipe Chromium vous recommande de modifier votre mot de passe maintenant.</translation>
<translation id="4587425331216688090">Supprimer l'adresse de Chrome ?</translation>
<translation id="4592951414987517459">Votre connexion à <ph name="DOMAIN" /> est chiffrée à l'aide d'une méthode de chiffrement récente.</translation>
<translation id="4594403342090139922">&amp;Annuler la suppression</translation>
-<translation id="4611292653554630842">Connexion</translation>
<translation id="4619615317237390068">Onglets d'autres appareils</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Impossible de vérifier sur le serveur qu'il s'agit bien du domaine <ph name="DOMAIN" />, car son certificat de sécurité contient des erreurs. Cela peut être dû à une mauvaise configuration ou bien à l'interception de votre connexion par un pirate informatique.</translation>
@@ -498,12 +539,10 @@
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Votre connexion a été interrompue</translation>
<translation id="471880041731876836">Vous n'êtes pas autorisé à consulter ce site</translation>
-<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Exécuter les diagnostics réseau de Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Votre paiement</translation>
+<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Exécutez les diagnostics réseau de Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Actualiser les règles</translation>
<translation id="4728558894243024398">Plate-forme</translation>
<translation id="4736825316280949806">Relancez Chromium</translation>
-<translation id="4737498291095696011">Source : cette page</translation>
<translation id="4744603770635761495">Chemin d'accès exécutable</translation>
<translation id="4749685221585524849">Dernière utilisation : <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Vos informations, par exemple vos mots de passe ou vos numéros de carte de paiement, sont privées lorsqu'elles sont transmises à ce site.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Afficher</translation>
<translation id="4854362297993841467">Mode de livraison non disponible. Choisissez-en un autre.</translation>
<translation id="4858792381671956233">Une demande d'autorisation a été envoyée à tes parents pour la consultation de ce site</translation>
-<translation id="4871132632506079383">Source : une page intégrée à l'adresse <ph name="SITE" /></translation>
<translation id="4880827082731008257">Rechercher dans l'historique</translation>
+<translation id="4881695831933465202">Ouvrir</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Authentification requise</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{et 1 autre page Web}one{et # autre page Web}other{et # autres pages Web}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Saisissez le code CVC de la carte <ph name="CREDIT_CARD" />. Une fois la validation terminée, les informations relatives à la carte de votre compte Google Payments seront partagées avec ce site.</translation>
<translation id="4923417429809017348">Cette page rédigée dans une langue non identifiée a été traduite en <ph name="LANGUAGE_LANGUAGE" />.</translation>
<translation id="4923459931733593730">Paiement</translation>
<translation id="4926049483395192435">Doit être spécifié.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> indique</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Actions</translation>
<translation id="4958444002117714549">Développer la liste</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Si cette option est activée, Chrome enregistre une copie de votre carte sur cet appareil pour vous permettre de remplir plus rapidement les formulaires.</translation>
<translation id="5018422839182700155">Impossible d'ouvrir cette page</translation>
<translation id="5019198164206649151">L'espace de stockage destiné à la sauvegarde est en mauvais état.</translation>
-<translation id="5020990877659450221">Source : cette page</translation>
<translation id="5023310440958281426">Vérifiez les règles définies par votre administrateur</translation>
<translation id="5029568752722684782">Effacer la copie</translation>
<translation id="503069730517007720">Veuillez installer un certificat racine pour "<ph name="SOFTWARE_NAME" />". Nous recommandons à votre administrateur informatique de lire les instructions de configuration du logiciel "<ph name="SOFTWARE_NAME" />" afin de remédier à la situation. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Ordinateur</translation>
<translation id="5179510805599951267">Cette page n'est pas rédigée en <ph name="ORIGINAL_LANGUAGE" /> ? Signaler l'erreur</translation>
<translation id="5190835502935405962">Barre de favoris</translation>
+<translation id="5201306358585911203">Une page intégrée à cette page Web indique</translation>
<translation id="5205222826937269299">Veuillez saisir un nom</translation>
<translation id="5222812217790122047">Veuillez saisir une adresse e-mail</translation>
<translation id="522700295135997067">Ce site vient peut-être de dérober votre mot de passe</translation>
<translation id="5230733896359313003">Adresse de livraison</translation>
<translation id="5251803541071282808">Cloud</translation>
-<translation id="5277279256032773186">Vous utilisez Chrome au travail ? Les entreprises peuvent gérer les paramètres Chrome de leurs employés. En savoir plus</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Suivez ces étapes pour désactiver temporairement le logiciel afin d'accéder au Web. Vous devez disposer des droits d'administrateur.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Vérifier la connexion</translation>
<translation id="5610807607761827392">Vous pouvez gérer les cartes et les adresses dans les <ph name="BEGIN_LINK" />paramètres<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> vous a redirigé à de trop nombreuses reprises.</translation>
-<translation id="5622887735448669177">Voulez-vous quitter ce site ?</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="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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Souhaitez-vous indiquer vos informations de carte de paiement ?</translation>
<translation id="5803412860119678065">Souhaitez-vous indiquer les informations "<ph name="CARD_DETAIL" />" ?</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="5810928923025889964">Source : une page intégrée à cette page Web</translation>
<translation id="5813119285467412249">&amp;Rétablir l'ajout</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>
<translation id="5866257070973731571">Ajouter un numéro de téléphone</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Ajouter d'autres informations</translation>
<translation id="6447842834002726250">Cookies</translation>
<translation id="6451458296329894277">Confirmer le nouvel envoi du formulaire</translation>
-<translation id="6456339708790392414">Votre paiement</translation>
<translation id="647261751007945333">Règles relatives aux appareils</translation>
<translation id="6477321094435799029">Chrome a détecté un code inhabituel sur cette page et a bloqué cette dernière pour protéger vos informations personnelles (mots de passe, numéros de téléphone et de cartes de paiement).</translation>
<translation id="6489534406876378309">Lancer l'importation des plantages</translation>
<translation id="6507833130742554667">Les cartes de crédit et de débit sont acceptées.</translation>
<translation id="6508722015517270189">Relancez Chrome</translation>
-<translation id="6521373090216409766">Voulez-vous actualiser ce site ?</translation>
<translation id="6529602333819889595">&amp;Rétablir la suppression</translation>
<translation id="6534179046333460208">Suggestions pour le Web physique</translation>
<translation id="6550675742724504774">Options</translation>
-<translation id="6556239504065605927">Connexion sécurisée</translation>
<translation id="6556915248009097796">Date d'expiration : <ph name="EXPIRATION_DATE_ABBR" />, dernière utilisation : <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Votre responsable ne l'a pas encore autorisé</translation>
<translation id="6569060085658103619">Vous consultez actuellement une page d'extension</translation>
<translation id="6596325263575161958">Options de chiffrement</translation>
+<translation id="6604181099783169992">Capteurs de mouvement ou de lumière</translation>
<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>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Favoris gérés</translation>
<translation id="7298195798382681320">Recommandé</translation>
<translation id="7309308571273880165">Rapport d'erreur enregistré le <ph name="CRASH_TIME" /> (importation demandée par l'utilisateur, mais non effectuée)</translation>
+<translation id="7320336641823683070">Aide à la connexion</translation>
<translation id="7334320624316649418">&amp;Rétablir la réorganisation</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="7353601530677266744">Ligne de commande</translation>
@@ -900,6 +935,7 @@
<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="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="7862185352068345852">Quitter le site Web ?</translation>
<translation id="7878176543348854470">Les cartes de débit et les cartes prépayées sont acceptées.</translation>
<translation id="7878562273885520351">Votre mot de passe a peut-être été piraté</translation>
<translation id="7887683347370398519">Veuillez vérifier votre code CVC et réessayer.</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Utiliser le paramètre global par défaut ("Demander")</translation>
<translation id="8042918947222776840">Sélectionner un mode d'enlèvement</translation>
<translation id="8057711352706143257">Le logiciel "<ph name="SOFTWARE_NAME" />" n'est pas configuré correctement. En général, la désinstallation de "<ph name="SOFTWARE_NAME" />" permet de remédier à la situation. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Actualiser le site Web ?</translation>
<translation id="8088680233425245692">Échec de l'affichage de l'article.</translation>
<translation id="8091372947890762290">Activation en attente sur le serveur.</translation>
<translation id="8094917007353911263">Pour utiliser ce réseau, il est possible que deviez vous rendre sur la page <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<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>
<translation id="8205463626947051446">Le site a tendance à afficher des annonces intrusives</translation>
+<translation id="8211406090763984747">La connexion est sécurisée</translation>
<translation id="8218327578424803826">Position attribuée :</translation>
<translation id="8225771182978767009">La personne qui a configuré cet ordinateur a choisi de bloquer ce site.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Afficher tous les mots de passe enregistrés</translation>
<translation id="8261506727792406068">Supprimer</translation>
<translation id="8267698848189296333">Connexion en tant que <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Connexion</translation>
<translation id="8288807391153049143">Afficher le certificat</translation>
<translation id="8289355894181816810">Contactez votre administrateur réseau si vous n'êtes pas sûr de vous.</translation>
<translation id="8293206222192510085">Ajouter aux favoris</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Cartes de crédit et cartes prépayées acceptées</translation>
<translation id="8759274551635299824">Carte arrivée à expiration</translation>
<translation id="8761567432415473239">La fonctionnalité de navigation sécurisée a récemment permis de <ph name="BEGIN_LINK" />détecter des programmes dangereux<ph name="END_LINK" /> sur le site <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Périphérique USB</translation>
<translation id="8790007591277257123">&amp;Rétablir la suppression</translation>
<translation id="8800988563907321413">Vos suggestions à proximité s'affichent ici</translation>
<translation id="8820817407110198400">Favoris</translation>
@@ -1042,7 +1082,7 @@
<translation id="9103872766612412690">Un chiffrement est normalement utilisé sur le site <ph name="SITE" /> pour protéger vos informations. Lors de la dernière tentative de connexion de Chromium au site <ph name="SITE" />, des identifiants inhabituels et incorrects ont été retournés. Il est possible qu'un individu malveillant tente de se faire passer pour <ph name="SITE" /> ou qu'un écran de connexion Wi-Fi ait interrompu la connexion. Vos informations restent sécurisées, car nous avons arrêté la connexion avant l'échange des données.</translation>
<translation id="9106062320799175032">Ajouter une adresse de facturation</translation>
<translation id="910908805481542201">M'aider à régler le problème</translation>
-<translation id="9128870381267983090">Connexion au réseau</translation>
+<translation id="9128870381267983090">Se connecter au réseau</translation>
<translation id="9137013805542155359">Afficher l'original</translation>
<translation id="9137248913990643158">Veuillez démarrer Chrome et vous connecter à votre compte avant d'utiliser cette application</translation>
<translation id="9148088599418889305">Sélectionner un mode de livraison</translation>
diff --git a/chromium/components/strings/components_strings_gu.xtb b/chromium/components/strings/components_strings_gu.xtb
index b71aba29b34..d0a5100e292 100644
--- a/chromium/components/strings/components_strings_gu.xtb
+++ b/chromium/components/strings/components_strings_gu.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;છાપો...</translation>
<translation id="1181037720776840403">દૂર કરો</translation>
<translation id="1184214524891303587">Google ને સંભવિત સુરક્ષા ઘટનાઓની વિગતોની <ph name="BEGIN_WHITEPAPER_LINK" />આપમેળે જાણ કરો<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">ચુકવણી પૂર્ણ થઇ નથી</translation>
<translation id="1201402288615127009">આગલું</translation>
<translation id="1201895884277373915">આ સાઇટથી વધુ</translation>
<translation id="1206967143813997005">ખોટી નાની સહી</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575"><ph name="CRASH_TIME" /> એ ક્રેશ રિપોર્ટ કૅપ્ચર કરવામાં આવી (હજી સુધી અપલોડ કરવામાં કે અવગણવામાં આવેલ નથી)</translation>
<translation id="1270502636509132238">પિકઅપ પદ્ધતિ</translation>
<translation id="1285320974508926690">આ સાઇટનું ક્યારેય ભાષાંતર કરશો નહીં</translation>
+<translation id="1294154142200295408">આદેશ વાક્યમાં વિવિધતા</translation>
<translation id="129553762522093515">તાજેતરમાં બંધ કરેલા</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />તમારી કૂકીઝને સાફ કરવાનો પ્રયાસ કરો<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">તમારી પ્રવૃત્તિ <ph name="BEGIN_EMPHASIS" />હજીપણ દૃશ્યક્ષમ હોઈ શકે છે<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">સ્વીકૃત ક્રેડિટ અને ડેબિટ કાર્ડ</translation>
<translation id="1519264250979466059">નિર્માણ તારીખ</translation>
<translation id="1527263332363067270">કનેક્શનની રાહ જોઈ રહ્યાં છીએ...</translation>
+<translation id="1532118530259321453">આ પેજ કહે છે કે</translation>
<translation id="153384715582417236">હમણાં માટે બસ આટલું પૂરતું છે</translation>
<translation id="154408704832528245">વિતરણ માટેનું સરનામું પસંદ કરો</translation>
<translation id="1549470594296187301">આ સુવિધાનો ઉપયોગ કરવા માટે JavaScript સક્ષમ કરેલ હોવી આવશ્યક છે.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />પ્રોક્સી અને ફાયરવોલ તપાસીને<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">પિન કોડ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 સૂચન}one{# સૂચન}other{# સૂચન}}</translation>
-<translation id="2065985942032347596">પ્રમાણીકરણ આવશ્યક</translation>
<translation id="2079545284768500474">પૂર્વવત કરો</translation>
<translation id="20817612488360358">સિસ્ટમ પ્રોક્સી સેટિંગ્સ ઉપયોગમાં લેવા માટે સેટ છે પણ એક સ્પષ્ટ પ્રોક્સી ગોઠવણી પણ ઉલ્લેખિત કરેલી છે.</translation>
<translation id="2091887806945687916">ધ્વનિ</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">ચુકવણી રદ કરો</translation>
<translation id="2147827593068025794">પૃષ્ઠભૂમિ સમન્વયન</translation>
<translation id="2148613324460538318">કાર્ડ ઉમેરો</translation>
-<translation id="2149973817440762519">બુકમાર્ક સંપાદિત કરો</translation>
<translation id="2154054054215849342">સમન્વયન તમારા ડોમેન માટે ઉપલબ્ધ નથી.</translation>
<translation id="2154484045852737596">કાર્ડ સંપાદિત કરો</translation>
<translation id="2166049586286450108">સંપૂર્ણ વ્યવસ્થાપક ઍક્સેસ</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">પિકઅપ માટેનું સરનામું પસંદ કરો</translation>
<translation id="2740531572673183784">બરાબર, સમજાઇ ગયું</translation>
<translation id="2742870351467570537">પસંદ કરેલી આઇટમ્સને દૂર કરો</translation>
-<translation id="2744590937989388266">આ પેજ પરના શામેલ કરેલ પેજ પરથી</translation>
<translation id="277133753123645258">વિતરણ પદ્ધતિ</translation>
<translation id="277499241957683684">ઉપકરણ રેકોર્ડ ખૂટે છે</translation>
<translation id="2784949926578158345">કનેક્શન ફરીથી સેટ થયું.</translation>
<translation id="2788784517760473862">સ્વીકૃત ક્રેડિટ કાર્ડ</translation>
<translation id="2794233252405721443">સાઇટ અવરોધિત કરી</translation>
-<translation id="2795286477369100655">શું તમે આ સાઇટ છોડવા માગો છો?</translation>
<translation id="2799020568854403057">સાઇટ આગળ હાનિકારક ઍપ્લિકેશનો ધરાવે છે</translation>
<translation id="2803306138276472711">Google Safe Browsing ને તાજેતરમાં <ph name="SITE" /> પર <ph name="BEGIN_LINK" />મૉલવેર મળ્યું<ph name="END_LINK" />. વેબસાઇટ્સ કે જે સામાન્ય રીતે સુરક્ષિત છે તે ક્યારેક મૉલવેરથી દૂષિત હોય છે.</translation>
<translation id="2824775600643448204">સરનામું અને શોધ બાર</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">"<ph name="ENTRY_INDEX" />" એન્ટ્રીને સૂચિબદ્ધ કરો: <ph name="ERROR" /></translation>
<translation id="301521992641321250">આપમેળે અવરોધિત</translation>
<translation id="3024663005179499861">ખોટો નીતિ પ્રકાર</translation>
-<translation id="3032412215588512954">શું તમે આ સાઇટ ફરીથી લોડ કરવા માંગો છો?</translation>
<translation id="3037605927509011580">અરર કંઇક ભુલ થઇ!</translation>
<translation id="3039538478787849737">કાર્ડને Google પર સાચવીએ?</translation>
<translation id="3041612393474885105">પ્રમાણપત્ર માહિતી</translation>
@@ -310,6 +306,7 @@
અથવા તમારા નેટવર્ક વ્યવસ્થાપકનો સંપર્ક કરો. જો તમે પ્રોક્સી સર્વરનો ઉપયોગ કરવો 
જોઇએ એવું ન માનતા હો:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="SERVER_NAME" /> પર <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">ચુકવણી રદ કરો</translation>
<translation id="3207960819495026254">બુકમાર્ક કરેલ</translation>
<translation id="3209375525920864198">કૃપા કરીને સત્રનું માન્ય નામ દાખલ કરો.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">તમારા માટે તમારા સંચાલક તેને અનાવરોધિત કરી શકે છે</translation>
<translation id="3566021033012934673">તમારું કનેક્શન ખાનગી નથી</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" /> પરનું શામેલ કરેલ પેજ કહે છે કે</translation>
<translation id="358285529439630156">ક્રેડિટ અને પ્રીપેઇડ કાર્ડ સ્વીકારવામાં આવે છે.</translation>
<translation id="3582930987043644930">નામ ઉમેરો</translation>
<translation id="3583757800736429874">&amp;ખસેડવું ફરી કરો</translation>
<translation id="3586931643579894722">વિગતો છુપાવો</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;કનેક્શન ભૂલો ઠીક કરો&lt;/h1&gt;
+ &lt;p&gt;જ્યારે તમે વેબસાઇટની મુલાકાત લેવાનો પ્રયાસ કરો ત્યારે જો તમને ભૂલનો સંદેશ મળે, તો આ સુધારાઓનો પ્રયાસ કરો.&lt;/p&gt;
+ &lt;h2&gt;મોટાભાગની કનેક્શન ભૂલો ઠીક કરો&lt;/h2&gt;
+ &lt;p&gt;જો તમે વેબસાઇટની મુલાકાત લેવાનો પ્રયાસ કરો અને તે ન ખુલે, તો પ્રથમ આ સમસ્યા નિવારણનાં પગલાં વડે ભૂલ ઠીક કરવાનો પ્રયાસ કરો:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;ટાઇપિંગની ભૂલો માટે વેબ ઍડ્રેસ ચેક કરો.&lt;/li&gt;
+ &lt;li&gt;ખાતરી કરો કે તમારું ઇન્ટરનેટ કનેક્શન સામાન્ય રીતે કાર્ય કરી રહ્યું છે.&lt;/li&gt;
+ &lt;li&gt;વેબસાઇટના માલિકનો સંપર્ક કરો.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;ભૂલના વિશિષ્ટ સંદેશ માટે સહાય મેળવો&lt;/h2&gt;
+ &lt;h3&gt;"તમારું કનેક્શન ખાનગી નથી" અથવા "NET::ERR_CERT_AUTHORITY_INVALID" અથવા "ERR_CERT_COMMON_NAME_INVALID" અથવા "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" અથવા "SSL પ્રમાણપત્ર ભૂલ"&lt;/h3&gt;
+ &lt;h4&gt;પગલું 1: પોર્ટલમાં સાઇન ઇન કરો&lt;/h4&gt;
+ &lt;p&gt;કૅફૅ અથવા એરપોર્ટ જેવી જગ્યાના વાઇ-ફાઇ નેટવર્કમાં તમારે સાઇન ઇન કરવું જરૂરી હોય છે. સાઇન-ઇન પેજ જોવા માટે, &lt;code&gt;http://&lt;/code&gt;નો ઉપયોગ કરતા પેજની મુલાકાત લો.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;&lt;code&gt;http://&lt;/code&gt;થી શરૂ થતી કોઈપણ વેબસાઇટ પર જાઓ, જેવી કે &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;જે ખુલે એ સાઇન ઇન પેજ પર, ઇન્ટરનેટનો ઉપયોગ કરવા માટે સાઇન ઇન કરો.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;પગલું 2: પેજને છૂપા મોડમાં ખોલો (માત્ર કમ્પ્યુટર)&lt;/h4&gt;
+ &lt;p&gt;તમે મુલાકાત લઈ રહેલા પેજને છૂપા મોડમાં ખોલો.&lt;/p&gt;
+ &lt;p&gt;જો પેજ ખુલે, તો Chrome એક્સ્ટેન્શન યોગ્ય રીતે કાર્ય કરતું નથી. ભૂલને ઠીક કરવા માટે, એક્સ્ટેન્શન બંધ કરો.&lt;/p&gt;
+ &lt;h4&gt;પગલું 3: તમારી ઑપરેટિંગ સિસ્ટમને અપડેટ કરો&lt;/h4&gt;
+ &lt;p&gt;ખાતરી કરો કે તમારું ઉપકરણ અપ ટૂ ડેટ છે.&lt;/p&gt;
+ &lt;h4&gt;પગલું 4: તમારું ઍન્ટિવાયરસ હંગામી ધોરણે બંધ કરો&lt;/h4&gt;
+ &lt;p&gt;જો તમારું ઍન્ટિવાયરસ સૉફ્ટવેર એવું હોય જે "HTTPS સુરક્ષા" or "HTTPS સ્કૅનિંગ" પ્રદાન કરે છે તો તમને આ ભૂલ આવશે. ઍન્ટિવાયરસ Chromeને સુરક્ષા પ્રદાન કરવાથી અટકાવતું હોઈ શકે છે.&lt;/p&gt;
+ &lt;p&gt;સમસ્યાને ઠીક કરવા માટે, તમારા ઍન્ટિવાયરસ સૉફ્ટવેર બંધ કરો. જો સૉફ્ટવેર બંધ કર્યા પછી પેજ કાર્ય કરે, તો તમે જ્યારે સુરક્ષિત સાઇટનો ઉપયોગ કરો ત્યારે આ સૉફ્ટવેર બંધ કરો.&lt;/p&gt;
+ &lt;p&gt;તમારું કાર્ય થઈ ગયા પછી તમારો ઍન્ટિવાયરસ પ્રોગ્રામ ફરી ચાલુ કરવાનું યાદ રાખશો.&lt;/p&gt;
+ &lt;h4&gt;પગલું 5: અતિરિક્ત સહાય મેળવો&lt;/h4&gt;
+ &lt;p&gt;જો તમને હજી પણ ભૂલ આવે, તો વેબસાઇટના માલિકનો સંપર્ક કરો.&lt;/p&gt;
+ &lt;h3&gt;"નેટવર્ક સાથે કનેક્ટ કરો"&lt;/h3&gt;
+ &lt;p&gt;જ્યાં તમારે ઑનલાઇન થવા માટે પહેલાં સાઇન ઇન કરવું પડે ત્યાં જો તમે વાઇ-ફાઇ પોર્ટલનો ઉપયોગ કરતા હશો, તો તમને આ ભૂલ આવશે.&lt;/p&gt;
+ &lt;p&gt;ભૂલને ઠીક કરવા માટે, તમે જે પેજ ખોલવાનો પ્રયાસ કરી રહ્યા હો તેના પર &lt;strong&gt;કનેક્ટ કરો&lt;/strong&gt; પર ક્લિક કરો.&lt;/p&gt;
+ &lt;h3&gt;"તમારી ઘડિયાળ પાછળ છે" અથવા "તમારી ઘડિયાળ આગળ છે" અથવા "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;તમારું કમ્પ્યુટર અથવા મોબાઇલ ઉપકરણની તારીખ અને સમય અચોક્કસ હશે ત્યારે તમને આ ભૂલ આવશે.&lt;/p&gt;
+ &lt;p&gt;ભૂલને ઠીક કરવા માટે, તમારા ઉપકરણની ઘડિયાળ ખોલો. ખાતરી કરો કે સમય અને તારીખ સાચા છે.&lt;/p&gt;
+ &lt;h3&gt;"તમારા કમ્પ્યુટર પરનું કોઈ સૉફ્ટવેર Chromeને સુરક્ષિત રીતે વેબ સાથે કનેક્ટ થવાથી અટકાવી રહ્યું છે" (માત્ર Windows કમ્પ્યુટર)&lt;/h3&gt;
+ &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;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; પર ક્લિક કરો
+ &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="3615877443314183785">એક માન્ય સમાપ્તિ તારીખ દાખલ કરો</translation>
<translation id="36224234498066874">બ્રાઉઝિંગ ડેટા સાફ કરો...</translation>
<translation id="362276910939193118">પૂર્ણ ઇતિહાસ બતાવો</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">શું તમે આ કાર્ડને તમારા Google એકાઉન્ટ અને આ ઉપકરણ પર સાચવવા માગો છો?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> માં સમાપ્ત થાય છે</translation>
-<translation id="3800436529451849929"><ph name="SITE" />માંથી</translation>
<translation id="382518646247711829">જો તમે કોઈ પ્રોક્સી સર્વરનો ઉપયોગ કરો છો...</translation>
<translation id="3828924085048779000">ખાલી પાસફ્રેઝને અનુમતિ નથી. </translation>
<translation id="385051799172605136">પાછળ</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">ક્રેશ રિપોર્ટ ID <ph name="CRASH_ID" /> (સ્થાનિક ક્રેશ ID: <ph name="CRASH_LOCAL_ID" />) અપલોડ કર્યું</translation>
<translation id="3949571496842715403">આ સર્વર સાબિત કરી શક્યું નથી કે તે <ph name="DOMAIN" /> છે; તેનું સુરક્ષા પ્રમાણપત્ર વિષય વૈકલ્પિક નામનો ઉલ્લેખ કરતું નથી. આ કોઈ ખોટી ગોઠવણીને કારણે અથવા કોઈ હુમલાખોર તમારા કનેક્શનને અટકાવતો હોવાને કારણે બન્યું હોઈ શકે.</translation>
<translation id="3949601375789751990">તમારો બ્રાઉઝિંગ ઇતિહાસ અહીં દેખાય છે</translation>
+<translation id="3950820424414687140">સાઇન ઇન</translation>
<translation id="3963721102035795474">રીડર મોડ</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{કોઈ નહીં}=1{1 સાઇટમાંથી }one{# સાઇટમાંથી }other{# સાઇટમાંથી }}</translation>
<translation id="397105322502079400">ગણના કરી રહ્યું છે...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">ઉપકરણ અનુક્ર્માંક નંબર અમાન્ય છે</translation>
<translation id="410351446219883937">ઑટોપ્લે</translation>
<translation id="4103763322291513355">બ્લેકલિસ્ટ કરેલા URL ની સૂચિ અને તમારા સિસ્ટમ વ્યવસ્થાપક દ્વારા લાગુ અન્ય નીતિઓ જોવા માટે &lt;strong&gt;chrome://policy&lt;/strong&gt; ની મુલાકાત લો.</translation>
+<translation id="4110652170750985508">તમારી ચુકવણીને રિવ્યૂ કરો</translation>
<translation id="4116663294526079822">હંમેશા આ સાઇટ પર મંજૂરી આપો</translation>
<translation id="4117700440116928470">નીતિ મર્યાદા સમર્થિત નથી.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 અન્ય}one{# અન્ય}other{# અન્ય}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(કોઇ વપરાશકર્તાનામ નથી)</translation>
<translation id="4275830172053184480">તમારું ઉપકરણ પુનઃપ્રારંભ કરો</translation>
<translation id="4280429058323657511">, સમાપ્તિ તારીખ <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">લૉગ ઇન કરો</translation>
<translation id="4312866146174492540">અવરોધિત કરો (ડિફૉલ્ટ)</translation>
<translation id="4325863107915753736">લેખ શોધવામાં નિષ્ફળ થયાં</translation>
<translation id="4326324639298822553">તમારી સમાપ્તિ તારીખ તપાસો અને ફરી પ્રયાસ કરો</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">કાર્ડ અને સરનામા Chrome અને Google એકાઉન્ટ (<ph name="ACCOUNT_EMAIL" />)માંથી છે. તમે તેને <ph name="BEGIN_LINK" />સેટિંગ્સ<ph name="END_LINK" />માં જઈને સંચાલિત કરી શકો છો.</translation>
<translation id="4522570452068850558">વિગતો</translation>
<translation id="4552089082226364758">ફ્લેશ</translation>
-<translation id="4554702541363482291"><ph name="SITE" /> પરના શામેલ કરેલ પેજ પરથી</translation>
<translation id="4558551763791394412">તમારા એક્સ્ટેન્શન્સને અક્ષમ કરવાનો પ્રયાસ કરો.</translation>
<translation id="457875822857220463">વિતરણ</translation>
<translation id="4582800630050655161">તમે તમારા Google એકાઉન્ટનો ઍક્સેસ ગુમાવી શકો છો અથવા તમને ઓળખ ચોરીનો અનુભવ થઈ શકે છે. Chromium તમને હમણાં જ તમારો પાસવર્ડ બદલવાની ભલામણ કરે છે.</translation>
<translation id="4587425331216688090">Chrome માંથી સરનામું દૂર કરીએ?</translation>
<translation id="4592951414987517459">આધુનિક સાઇફર સ્યૂટનો ઉપયોગ કરીને <ph name="DOMAIN" /> સાથેનું તમારું કનેક્શન એન્ક્રિપ્ટ કરાયું છે.</translation>
<translation id="4594403342090139922">&amp;કાઢી નાખવું પૂર્વવત્‌ કરો</translation>
-<translation id="4611292653554630842">લૉગ ઇન કરો</translation>
<translation id="4619615317237390068">અન્ય ઉપકરણોમાંથી ટૅબ્સ</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">આ સર્વર સાબિત કરી શક્યું નથી કે તે <ph name="DOMAIN" /> છે; તેના સુરક્ષા પ્રમાણપત્રમાં ભૂલો છે. આ કોઈ ખોટી ગોઠવણીને કારણે થયું હશે અથવા કોઈ હુમલાખોર તમારા કનેક્શનને અટકાવી રહ્યો છે.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">તમારું કનેક્શન અવરોધાયું હતું</translation>
<translation id="471880041731876836">તમારી પાસે આ સાઇટની મુલાકાત લેવાની પરવાનગી નથી</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows નેટવર્ક ડાયગ્નોસ્ટિક્સ ચલાવી રહ્યાં છે<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">તમારી ચુકવણી</translation>
<translation id="4726672564094551039">નીતિઓ ફરીથી લોડ કરો</translation>
<translation id="4728558894243024398">પ્લેટફોર્મ</translation>
<translation id="4736825316280949806">Chromium ને પુનઃપ્રારંભ કરો</translation>
-<translation id="4737498291095696011">આ પેજ પરથી</translation>
<translation id="4744603770635761495">અમલ કરવાયોગ્ય પાથ</translation>
<translation id="4749685221585524849">છેલ્લે <ph name="LAST_USED_MONTH" /> ના રોજ ઉપયોગ કર્યો</translation>
<translation id="4750917950439032686">તમારી માહિતી (ઉદાહરણ તરીકે, પાસવર્ડ્સ અથવા ક્રેડિટ કાર્ડ નંબર્સ) ખાનગી હોય છે જ્યારે તે આ સાઇટ પર મોકલવામાં આવે.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">જુઓ</translation>
<translation id="4854362297993841467">વિતરણની આ પદ્ધતિ ઉપલબ્ધ નથી. કોઈ ભિન્ન પદ્ધતિ અજમાવો.</translation>
<translation id="4858792381671956233">તમે આ સાઇટની મુલાકાત લો છો તે ઠીક છે કે કેમ તેવું તમે તમારા માતાપિતાને પૂછ્યું</translation>
-<translation id="4871132632506079383"><ph name="SITE" /> પરના શામેલ કરેલ પેજ પરથી</translation>
<translation id="4880827082731008257">ઇતિહાસ શોધ</translation>
+<translation id="4881695831933465202">ખોલો</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">પ્રમાણીકરણ આવશ્યક છે</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{અને 1 વધુ વેબ પૃષ્ઠ}one{અને # વધુ વેબ પૃષ્ઠ}other{અને # વધુ વેબ પૃષ્ઠ}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947"><ph name="CREDIT_CARD" /> માટે CVC દાખલ કરો. તમે પુષ્ટિ કરી લો પછી, આ સાઇટ સાથે તમારા Google Payments એકાઉન્ટમાંથી કાર્ડની વિગતો શેર કરવામાં આવશે.</translation>
<translation id="4923417429809017348">આ પૃષ્ઠ કોઈ અજ્ઞાત ભાષામાંથી <ph name="LANGUAGE_LANGUAGE" /> માં અનુવાદિત કરવામાં આવ્યું છે</translation>
<translation id="4923459931733593730">ચુકવણી</translation>
<translation id="4926049483395192435">ઉલ્લેખિત હોવું આવશ્યક છે.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> કહે છે કે</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">ક્રિયાઓ</translation>
<translation id="4958444002117714549">સૂચિ વિસ્તૃત કરો</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">જો સક્ષમ કરેલું હોય, તો ઝડપથી ફોર્મ ભરવા માટે Chrome આ ઉપકરણ પર તમારા કાર્ડની એક કૉપિ સંગ્રહશે.</translation>
<translation id="5018422839182700155">આ પૃષ્ઠ ખોલી શકતાં નથી</translation>
<translation id="5019198164206649151">બેકઅપ સ્ટોર કરવું ખરાબ સ્થિતિમાં છે</translation>
-<translation id="5020990877659450221">આ પેજ પરથી</translation>
<translation id="5023310440958281426">તમારા વ્યવસ્થાપકની નીતિઓ તપાસો</translation>
<translation id="5029568752722684782">કૉપિ સાફ કરો</translation>
<translation id="503069730517007720">"<ph name="SOFTWARE_NAME" />" માટેનું રૂટ પ્રમાણપત્ર આવશ્યક છે પરંતુ તે ઇન્સ્ટૉલ કરેલું નથી. આ સમસ્યાના નિવારણ માટે તમારા IT વ્યવસ્થાપકે "<ph name="SOFTWARE_NAME" />" ની ગોઠવણી માટેની સૂચના જોવી જરૂરી છે. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">મશીન</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> માં નથી? આ ભૂલની જાણ કરો </translation>
<translation id="5190835502935405962">બુકમાર્ક્સ બાર</translation>
+<translation id="5201306358585911203">આ પેજ પરનું શામેલ કરેલ પેજ કહે છે કે</translation>
<translation id="5205222826937269299">નામ આવશ્યક છે</translation>
<translation id="5222812217790122047">ઇમેઇલ આવશ્યક છે</translation>
<translation id="522700295135997067">આ સાઇટે હમણાં જ તમારો પાસવર્ડ ચોર્યો હોઈ શકે છે</translation>
<translation id="5230733896359313003">વિતરણ માટેનું સરનામું</translation>
<translation id="5251803541071282808">મેઘ</translation>
-<translation id="5277279256032773186">કાર્ય પર Chrome નો ઉપયોગ કરી રહ્યાં છો? વ્યવસાયો તેમના કર્મચારીઓ માટે Chrome સેટિંગ્સને સંચાલિત કરી શકે છે. વધુ જાણો</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />સૉફ્ટવેરને અસ્થાયીરૂપે અક્ષમ કરવા માટે આ પગલાં અનુસરો જેથી તમે વેબ પર જઈ શકો. તમને વ્યવસ્થાપકના વિશેષાધિકારની જરૂર પડશે.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">કનેક્શન તપાસીને</translation>
<translation id="5610807607761827392">તમે <ph name="BEGIN_LINK" />સેટિંગ્સ<ph name="END_LINK" />માં કાર્ડ્સ અને સરનામાં સંચાલિત કરી શકો છો.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> એ તમને ઘણીબધી વખત રીડાયરેક્ટ કર્યું.</translation>
-<translation id="5622887735448669177">શું તમે આ સાઇટ છોડવા માંગો છો?</translation>
<translation id="5629630648637658800">નીતિ સેટિંગ્સ લોડ કરવામાં નિષ્ફળ થયાં</translation>
<translation id="5631439013527180824">અમાન્ય ઉપકરણ સંચાલન ટોકન</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">શું તમે તમારી કાર્ડ માહિતી ભરવા માગો છો?</translation>
<translation id="5803412860119678065">શું તમે તમારી <ph name="CARD_DETAIL" /> માહિતી ભરવા માગો છો?</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> સાથેના તમારા કનેક્શનને ઑબ્સોલિટ સાઇફર સ્યૂટનો ઉપયોગ કરીને એન્ક્રિપ્ટ કરાયું છે.</translation>
-<translation id="5810928923025889964">આ પેજ પરના શામેલ કરેલ પેજ પરથી</translation>
<translation id="5813119285467412249">&amp;ઉમેરવું ફરી કરો</translation>
<translation id="5838278095973806738">તમારે આ સાઇટ પર કોઈપણ સંવેદનશીલ માહિતી (ઉદાહરણ તરીકે, પાસવર્ડ્સ અથવા ક્રેડિટ કાર્ડ્સ) દાખલ કરવી જોઈએ નહીં, કારણ કે તે હુમલાખોર દ્વારા ચોરવામાં આવી શકે છે.</translation>
<translation id="5866257070973731571">ફોન નંબર ઉમેરો</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">વધુ માહિતી ઉમેરો</translation>
<translation id="6447842834002726250">કૂકીઝ</translation>
<translation id="6451458296329894277">ફોર્મનાં ફરી સબમિશનની પુષ્ટિ કરો</translation>
-<translation id="6456339708790392414">તમારી ચુકવણી</translation>
<translation id="647261751007945333">ઉપકરણ નીતિઓ</translation>
<translation id="6477321094435799029">Chrome ને આ પૃષ્ઠ પર અસામાન્ય કોડ મળ્યો અને તમારી વ્યક્તિગત માહિતી (ઉદાહરણ તરીકે, પાસવર્ડ્સ, ફોન નંબર્સ અને ક્રેડિટ કાર્ડ્સ)ની સુરક્ષા કરવા માટે તેને અવરોધિત કરેલ છે.</translation>
<translation id="6489534406876378309">ક્રેશ અપલોડ કરવાનું શરૂ કરો</translation>
<translation id="6507833130742554667">ક્રેડિટ અને ડેબિટ કાર્ડ સ્વીકારવામાં આવે છે.</translation>
<translation id="6508722015517270189">Chrome ને પુનઃપ્રારંભ કરો</translation>
-<translation id="6521373090216409766">શું તમે આ સાઇટ ફરીથી લોડ કરવા માગો છો?</translation>
<translation id="6529602333819889595">&amp;કાઢી નાખવું ફરી કરો</translation>
<translation id="6534179046333460208">વાસ્તવિક વેબ સૂચનો</translation>
<translation id="6550675742724504774">વિકલ્પો</translation>
-<translation id="6556239504065605927">સુરક્ષિત કનેક્શન</translation>
<translation id="6556915248009097796">સમાપ્તિ: <ph name="EXPIRATION_DATE_ABBR" />, છેલ્લે <ph name="LAST_USED_DATE_NO_DETAIL" /> ના રોજ ઉપયોગ કર્યો</translation>
<translation id="6563469144985748109">તમારા સંચાલકે હજી સુધી તેને મંજૂર કરેલ નથી</translation>
<translation id="6569060085658103619">તમે એક્સ્ટેન્શન પૃષ્ઠ જોઈ રહ્યાં છો</translation>
<translation id="6596325263575161958">એન્ક્રિપ્શન વિકલ્પો</translation>
+<translation id="6604181099783169992">મોશન અથવા લાઇટ સેન્સર</translation>
<translation id="6624427990725312378">સંપર્ક માહિતી</translation>
<translation id="6626291197371920147">માન્ય કાર્ડ નંબર ઉમેરો</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> શોધ</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">સંચાલિત બુકમાર્ક્સ</translation>
<translation id="7298195798382681320">ભલામણ કરેલ</translation>
<translation id="7309308571273880165">ક્રેશ રિપોર્ટ <ph name="CRASH_TIME" /> એ કૅપ્ચર કરવામાં આવી (વપરાશકર્તા દ્વારા અપલોડની વિનંતી કરવામાં આવી, હજી સુધી અપલોડ કરેલ નથી)</translation>
+<translation id="7320336641823683070">કનેક્શન સહાય</translation>
<translation id="7334320624316649418">&amp;પુનઃક્રમાંકિત કરવું ફરી કરો</translation>
<translation id="733923710415886693">પ્રમાણપત્ર પારદર્શિતા દ્વારા સર્વરનું પ્રમાણપત્ર જાહેર કરવામાં આવ્યું ન હતું.</translation>
<translation id="7353601530677266744">આદેશ પંક્તિ</translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">તમે ઉપયોગ કરી રહ્યાં છો તે Wi-Fi (<ph name="WIFI_NAME" />) ને તેના લોગિન પૃષ્ઠની મુલાકાત લેવાની જરૂર હોઈ શકે છે.</translation>
<translation id="785549533363645510">જો કે, તમે અદૃશ્ય નથી. છુપામાં જવું તમારા નિયોક્તા, તમારા ઇન્ટરનેટ સેવા પ્રદાતા અથવા તમે મુલાકાત લો છો તે વેબસાઇટ્સથી તમારા બ્રાઉઝિંગને છુપાવતું નથી.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">સાઇટ છોડવી છે?</translation>
<translation id="7878176543348854470">ડેબિટ અને પ્રીપેઇડ કાર્ડ સ્વીકારવામાં આવે છે.</translation>
<translation id="7878562273885520351">તમારા પાસવર્ડ સાથે ચેડાં થઈ શકે છે</translation>
<translation id="7887683347370398519">તમારું CVC તપાસો અને ફરીથી પ્રયાસ કરો</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">વૈશ્વિક ડિફોલ્ટનો ઉપયોગ કરો (કહો)</translation>
<translation id="8042918947222776840">પિકઅપ પદ્ધતિ પસંદ કરો</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />"ની ગોઠવણી યોગ્ય રીતે કરવામાં આવી નથી. સામાન્ય રીતે "<ph name="SOFTWARE_NAME" />"ને અનઇન્સ્ટૉલ કરવાથી સમસ્યા હલ થઈ જાય છે. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">સાઇટ ફરીથી લોડ કરીએ?</translation>
<translation id="8088680233425245692">લેખ જોવામાં નિષ્ફળ થયાં.</translation>
<translation id="8091372947890762290">સક્રિયતા સર્વર પર બાકી છે</translation>
<translation id="8094917007353911263">તમે ઉપયોગ કરી રહ્યાં છો તે નેટવર્કને <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> ની મુલાકાત લેવાની જરૂર પડી શકે છે.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">ID "<ph name="EXTENSION_ID" />" સાથેના એક્સટેન્શન માટે અમાન્ય અપડેટ URL.</translation>
<translation id="8202097416529803614">ઓર્ડરનો સારાંશ</translation>
<translation id="8205463626947051446">ખલેલ પાડતી જાહેરાતો બતાવવાનું વલણ ધરાવતી સાઇટ</translation>
+<translation id="8211406090763984747">કનેક્શન સુરક્ષિત છે</translation>
<translation id="8218327578424803826">સોંપાયેલ સ્થાન:</translation>
<translation id="8225771182978767009">આ કમ્પ્યુટરને સેટ કરનાર વ્યક્તિએ આ સાઇટને અવરોધિત કરવાનું પસંદ કર્યું છે.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">બધા સાચવેલા પાસવર્ડ બતાવો</translation>
<translation id="8261506727792406068">કાઢી નાખો</translation>
<translation id="8267698848189296333"><ph name="USERNAME" /> તરીકે સાઇન ઇન કરી રહ્યાં છે</translation>
+<translation id="8286036467436129157">સાઇન ઇન કરો</translation>
<translation id="8288807391153049143">પ્રમાણપત્ર બતાવો</translation>
<translation id="8289355894181816810">આ શું છે તે ખાતરીપૂર્વક જાણતા ન હો તો તમારા નેટવર્ક વ્યવસ્થાપકનો સંપર્ક કરો.</translation>
<translation id="8293206222192510085">બુકમાર્ક ઉમેરો</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">સ્વીકૃત ક્રેડિટ અને પ્રિપેઇડ કાર્ડ</translation>
<translation id="8759274551635299824">આ કાર્ડની સમયસીમા સમાપ્ત થઈ ગઈ છે</translation>
<translation id="8761567432415473239">Google Safe Browsing ને તાજેતરમાં <ph name="SITE" /> પર <ph name="BEGIN_LINK" />હાનિકારક પ્રોગ્રામ્સ મળ્યાં<ph name="END_LINK" />.</translation>
+<translation id="8763927697961133303">USB ઉપકરણ</translation>
<translation id="8790007591277257123">&amp;કાઢી નાખવું ફરી કરો</translation>
<translation id="8800988563907321413">તમારા નજીકના સૂચનો અહીં દેખાય છે</translation>
<translation id="8820817407110198400">બુકમાર્ક્સ</translation>
diff --git a/chromium/components/strings/components_strings_hi.xtb b/chromium/components/strings/components_strings_hi.xtb
index b86f34df334..fcb4b3e6d05 100644
--- a/chromium/components/strings/components_strings_hi.xtb
+++ b/chromium/components/strings/components_strings_hi.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;प्रिंट करें...</translation>
<translation id="1181037720776840403">निकालें</translation>
<translation id="1184214524891303587">Google को संभावित सुरक्षा घटनाओं के विवरण की <ph name="BEGIN_WHITEPAPER_LINK" />अपने आप रिपोर्ट करें<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">भुगतान पूरा नहीं हुआ</translation>
<translation id="1201402288615127009">अगला</translation>
<translation id="1201895884277373915">इस साइट की ओर से अधिक</translation>
<translation id="1206967143813997005">नाम के पहले अक्षर के गलत हस्ताक्षर</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">ख़राबी रिपोर्ट <ph name="CRASH_TIME" /> पर कैप्चर की गई (अभी तक अपलोड नहीं की गई या उसे अनदेखा किया गया)</translation>
<translation id="1270502636509132238">पिकअप का तरीका</translation>
<translation id="1285320974508926690">कभी भी इस साइट का अनुवाद न करें</translation>
+<translation id="1294154142200295408">कमांड लाइन की विविधताएं</translation>
<translation id="129553762522093515">हाल ही में बंद किए गए</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />अपनी कुकी साफ़ करके देखें<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">आपकी गतिविधि इन्हें <ph name="BEGIN_EMPHASIS" />अभी भी दिखाई दे सकती है<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">स्वीकृत क्रेडिट और डेबिट कार्ड</translation>
<translation id="1519264250979466059">बिल्ड दिनांक</translation>
<translation id="1527263332363067270">कनेक्‍शन के इंतज़ार में…</translation>
+<translation id="1532118530259321453">इस पेज का कहना है कि</translation>
<translation id="153384715582417236">अभी के लिए हो गया</translation>
<translation id="154408704832528245">डिलीवरी पता चुनें</translation>
<translation id="1549470594296187301">इस सुविधा का उपयोग करने के लिए JavaScript को सक्षम किया जाना चाहिए.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />प्रॉक्सी और फायरवॉल की जाँच करें<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">ज़िप कोड</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 सुझाव}one{# सुझाव}other{# सुझाव}}</translation>
-<translation id="2065985942032347596">प्रमाणीकरण आवश्यक</translation>
<translation id="2079545284768500474">वापस लाएं</translation>
<translation id="20817612488360358">सिस्‍टम प्रॉक्‍सी सेटिंग उपयोग किए जाने के लिए सेट हैं लेकिन कोई स्पष्‍ट प्रॉक्‍सी कॉन्फ़िगरेशन भी निर्दिष्ट है.</translation>
<translation id="2091887806945687916">ध्वनि</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">भुगतान न करें</translation>
<translation id="2147827593068025794">पृष्ठभूमि समन्वयन</translation>
<translation id="2148613324460538318">कार्ड जोड़ें</translation>
-<translation id="2149973817440762519">बुकमार्क संपादित करें</translation>
<translation id="2154054054215849342">आपके डोमेन के लिए सिंक करने की सुविधा उपलब्‍ध नहीं है</translation>
<translation id="2154484045852737596">कार्ड संपादित करें</translation>
<translation id="2166049586286450108">पूर्ण व्यवस्थापकीय एक्सेस</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">पिकअप का पता चुनें</translation>
<translation id="2740531572673183784">ठीक है</translation>
<translation id="2742870351467570537">चयनित आइटम निकालें</translation>
-<translation id="2744590937989388266">इस पेज पर एम्बेड किए गए पेज से</translation>
<translation id="277133753123645258">शिपिंग का तरीका</translation>
<translation id="277499241957683684">डिवाइस का रिकॉर्ड लापता है</translation>
<translation id="2784949926578158345">कनेक्‍शन रीसेट किया गया था.</translation>
<translation id="2788784517760473862">स्वीकृत क्रेडिट कार्ड</translation>
<translation id="2794233252405721443">साइट अवरोधित है</translation>
-<translation id="2795286477369100655">क्या आप इस साइट को छोड़ना चाहते हैं?</translation>
<translation id="2799020568854403057">आगे आने वाली साइट में नुकसान पहुंचाने वाले ऐप्लिकेशन हैं</translation>
<translation id="2803306138276472711">Google सुरक्षित ब्राउज़िंग को <ph name="SITE" /> पर हाल ही में <ph name="BEGIN_LINK" />मैलवेयर का पता चला<ph name="END_LINK" /> है. आमतौर पर सुरक्षित रहने वाली वेबसाइटें कभी-कभी मैलवेयर से संक्रमित हो जाती हैं.</translation>
<translation id="2824775600643448204">पता और खोज बार</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">सूची प्रविष्ट‍ि "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">ऑटोमैटिक रूप से ब्लॉक है</translation>
<translation id="3024663005179499861">गलत नीति प्रकार</translation>
-<translation id="3032412215588512954">क्या आप इस साइट को फिर से लोड करना चाहते हैं?</translation>
<translation id="3037605927509011580">हे भगवान!</translation>
<translation id="3039538478787849737">Google में कार्ड सेव करें?</translation>
<translation id="3041612393474885105">प्रमाणपत्र जानकारी</translation>
@@ -310,12 +306,13 @@
अपनी प्रॉक्सी सेटिंग जाँचें या अपने नेटवर्क व्यवस्थापक से संपर्क करें. यदि आपको विश्वास नहीं हो
कि आप किसी प्रॉक्सी सर्वर का उपयोग कर रहे हैं, तो:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="SERVER_NAME" /> पर <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">भुगतान रद्द करें</translation>
<translation id="3207960819495026254">बुकमार्क किया गया</translation>
<translation id="3209375525920864198">कृपया सत्र का मान्य नाम डालें.</translation>
<translation id="3211223744486044430">अगली बार तेज़ी से भुगतान करने के लिए, इस कार्ड को अपने Google खाते में और इस डिवाइस में सेव करें.</translation>
<translation id="3225919329040284222">सर्वर द्वारा कोई प्रमाणपत्र प्रस्‍तुत किया गया, जो बिल्‍ट-इन अपेक्षाओं से मिलान नहीं करता. इन अपेक्षाओं को आपकी सुरक्षा करने के लिए कुछ, उच्‍च-सुरक्षा वेबसाइटों के लिए शामिल किया गया है.</translation>
-<translation id="3226128629678568754">पेज को लोड करने के लिए आवश्यक डेटा पुन: सबमिट करने के लिए पुन: लोड करें बटन दबाएं.</translation>
+<translation id="3226128629678568754">पेज को लोड करने के लिए ज़रूरी डेटा फिर सबमिट करने के लिए फिर लोड करें बटन दबाएं.</translation>
<translation id="3227137524299004712">माइक्रोफ़ोन</translation>
<translation id="3228969707346345236">अनुवाद विफल हो गया क्योंकि पेज पहले से ही <ph name="LANGUAGE" /> में है.</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> का CVC डालें.</translation>
@@ -367,11 +364,58 @@
<translation id="3556433843310711081">आपका प्रबंधक इसे आपके लिए अनवरोधित कर सकता है</translation>
<translation id="3566021033012934673">आपका कनेक्शन निजी नहीं है</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" /> पर एम्बेड किए गए पेज का कहना है कि</translation>
<translation id="358285529439630156">क्रेडिट और प्रीपेड कार्ड स्वीकार किए जाते हैं.</translation>
<translation id="3582930987043644930">नाम जोड़ें</translation>
<translation id="3583757800736429874">&amp;ले जाना फिर से करें</translation>
<translation id="3586931643579894722">विवरण छुपाएं</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;कनेक्शन गड़बड़ियां ठीक करना&lt;/h1&gt;
+ &lt;p&gt;अगर किसी वेबसाइट पर जाने की कोशिश करते समय आपको गड़बड़ी का कोई मैसेज मिलता है, तो ये समाधान आज़माकर देखें.&lt;/p&gt;
+ &lt;h2&gt;कनेक्शन से जुड़ी ज़्यादातर गड़बड़ियां ठीक करना&lt;/h2&gt;
+ &lt;p&gt;अगर आप किसी वेबसाइट पर जाने की कोशिश करते हैं और वह नहीं खुलती है, तो पहले समस्‍या निवारण के इन चरणों से गड़बड़ी को ठीक करके देखें:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;देखें कि वेब पता लिखने में कोई गलती तो नहीं हुई है.&lt;/li&gt;
+ &lt;li&gt;पक्का करें कि आपका इंटरनेट कनेक्शन ठीक से काम कर रहा है.&lt;/li&gt;
+ &lt;li&gt;वेबसाइट के मालिक से संपर्क करें.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;गड़बड़ी के किसी खास मैसेज के संबंध में सहायता पाएं&lt;/h2&gt;
+ &lt;h3&gt;"आपका कनेक्शन निजी नहीं है" या "NET::ERR_CERT_AUTHORITY_INVALID" या "ERR_CERT_COMMON_NAME_INVALID" या "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" या "SSL प्रमाणपत्र की गड़बड़ी"&lt;/h3&gt;
+ &lt;h4&gt;चरण 1: पोर्टल में साइन इन करें&lt;/h4&gt;
+ &lt;p&gt;कैफ़े या हवाई अड्डों जैसी जगहों पर मौजूद वाई-फ़ाई नेटवर्क के लिए आपको साइन इन करना होगा. साइन-इन पेज देखने के लिए, किसी ऐसे पेज पर जाएं जो &lt;code&gt;http://&lt;/code&gt; का इस्तेमाल करता है.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;&lt;code&gt;http://&lt;/code&gt; से शुरू होने वाली किसी भी वेबसाइट, जैसे कि &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt; पर जाएं.&lt;/li&gt;
+ &lt;li&gt;इंटरनेट का इस्तेमाल करने के लिए, खुलने वाले साइन-इन पेज पर साइन इन करें.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;चरण 2: पेज को गुप्त मोड में खोलें (सिर्फ़ कंप्यूटर)&lt;/h4&gt;
+ &lt;p&gt;वह पेज खोलें, जिस पर आप गुप्त विंडो में आए थे.&lt;/p&gt;
+ &lt;p&gt;अगर पेज खुल जाता है, तो कोई Chrome एक्सटेंशन ठीक से काम नहीं कर रहा है. गड़बड़ी को ठीक करने के लिए, एक्सटेंशन बंद करें.&lt;/p&gt;
+ &lt;h4&gt;चरण 3: अपना ऑपरेटिंग सिस्टम अपडेट करें&lt;/h4&gt;
+ &lt;p&gt;पक्का करें कि आपका डिवाइस अप टू डेट है.&lt;/p&gt;
+ &lt;h4&gt;चरण 4: अपना एंटीवायरस कुछ देर के लिए बंद करें&lt;/h4&gt;
+ &lt;p&gt;अगर आपके पास ऐसा एंटीवायरस सॉफ़्टवेयर है जो "HTTPS सुरक्षा" या "HTTPS स्कैनिंग" उपलब्ध कराता है, तो आपको यह गड़बड़ी दिखाई देती है. एंटीवायरस, सुरक्षा उपलब्ध कराने से Chrome को रोक रहा है.&lt;/p&gt;
+ &lt;p&gt;समस्या को ठीक करने के लिए, अपना एंटीवायरस सॉफ़्टवेयर बंद करें. अगर सॉफ़्टवेयर बंद करने के बाद पेज काम करता है, तो सुरक्षित साइटों का इस्तेमाल करते समय इस सॉफ़्टवेयर को बंद कर दें.&lt;/p&gt;
+ &lt;p&gt;जब आपका काम हो जाए तो अपना एंटीवायरस प्रोग्राम वापस चालू करना न भूलें.&lt;/p&gt;
+ &lt;h4&gt;चरण 5: ज़्यादा सहायता पाएं&lt;/h4&gt;
+ &lt;p&gt;अगर आपको अभी भी गड़बड़ी दिखाई दे रही है, तो वेबसाइट के मालिक से संपर्क करें.&lt;/p&gt;
+ &lt;h3&gt;"नेटवर्क से कनेक्ट करें"&lt;/h3&gt;
+ &lt;p&gt;अगर आप ऐसे वाई-फ़ाई पोर्टल का इस्तेमाल कर रहे हैं जिसके लिए यह ज़रूरी है कि आप ऑनलाइन होने से पहले साइन इन करें, तो आपको यह गड़बड़ी दिखाई देगी.&lt;/p&gt;
+ &lt;p&gt;गड़बड़ी ठीक करने के लिए, जिस पेज को आप खोलने की कोशिश कर रहे हैं, उस पर &lt;strong&gt;कनेक्ट करें&lt;/strong&gt; पर क्लिक करें.&lt;/p&gt;
+ &lt;h3&gt;"आपकी घड़ी पीछे चल रही है" या "आपकी घड़ी आगे चल रही है" या "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;अगर आपके कंप्यूटर या मोबाइल डिवाइस की तारीख और समय गलत हैं, तो आपको यह गड़बड़ी दिखाई देगी.&lt;/p&gt;
+ &lt;p&gt;गड़बड़ी को ठीक करने के लिए, अपने डिवाइस की घड़ी खोलें. यह पक्का करें कि समय और तारीख सही हैं.&lt;/p&gt;
+ &lt;h3&gt;"आपके कंप्यूटर पर मौजूद सॉफ़्टवेयर Chrome को सुरक्षित रूप से वेब से कनेक्ट होने से रोक रहा है" (सिर्फ़ Windows कंप्यूटर)&lt;/h3&gt;
+ &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;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; पर क्लिक करें
+ &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="3615877443314183785">खत्म होने की मान्य तारीख डालें</translation>
<translation id="36224234498066874">ब्राउज़िंग डेटा साफ़ करें...</translation>
<translation id="362276910939193118">संपूर्ण इतिहास दिखाएं</translation>
@@ -404,7 +448,6 @@
<translation id="3778403066972421603">क्या आप इस कार्ड को अपने Google खाते में और इस डिवाइस पर सहेजना चाहते हैं?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> में खत्म होगा</translation>
-<translation id="3800436529451849929"><ph name="SITE" /> से</translation>
<translation id="382518646247711829">यदि आप प्रॉक्सी सर्वर का उपयोग करते हैं...</translation>
<translation id="3828924085048779000">खाली पासफ़्रेज़ की अनुमति नहीं है.</translation>
<translation id="385051799172605136">वापस</translation>
@@ -418,6 +461,7 @@
<translation id="3945915738023014686">अपलोड की गई ख़राबी रिपोर्ट आईडी <ph name="CRASH_ID" /> (स्थानीय क्रैश आईडी: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">यह सर्वर प्रमाणित नहीं कर सका कि यह <ph name="DOMAIN" /> है; इसके सुरक्षा प्रमाणपत्र में विषय के वैकल्पिक नाम नहीं बताए गए हैं. ऐसा गलत कॉन्फ़िगरेशन के कारण या किसी आक्रमणकर्ता की ओर से आपके कनेक्शन में अवरोध डालने के कारण हो सकता है.</translation>
<translation id="3949601375789751990">आपका ब्राउज़िंग इतिहास यहां दिखाई देता है</translation>
+<translation id="3950820424414687140">प्रवेश करें</translation>
<translation id="3963721102035795474">रीडर मोड</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{कुछ नहीं}=1{1 साइट से }one{# साइटों से }other{# साइटों से }}</translation>
<translation id="397105322502079400">गणना की जा रही है...</translation>
@@ -434,6 +478,7 @@
<translation id="4103249731201008433">डिवाइस की क्रम संख्या अमान्य है</translation>
<translation id="410351446219883937">स्वतः चलाएं</translation>
<translation id="4103763322291513355">काली सूची में डाले गए URL तथा आपके सिस्टम व्यवस्थापक द्वारा लागू की गई अन्य नीतियों को देखने के लिए &lt;strong&gt;chrome://policy&lt;/strong&gt; पर जाएं.</translation>
+<translation id="4110652170750985508">अपना भुगतान देखें</translation>
<translation id="4116663294526079822">इस साइट पर हमेशा अनुमति दें</translation>
<translation id="4117700440116928470">नीति क्षेत्र समर्थित नहीं है.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 अन्य}one{# अन्‍य}other{# अन्‍य}}</translation>
@@ -460,7 +505,6 @@
<translation id="4269787794583293679">(कोई उपयोगकर्ता नाम नहीं)</translation>
<translation id="4275830172053184480">अपना डिवाइस पुन: प्रारंभ करें</translation>
<translation id="4280429058323657511">, समाप्ति दिनांक <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">प्रवेश करें</translation>
<translation id="4312866146174492540">अवरुद्ध करें (डिफ़ॉल्ट)</translation>
<translation id="4325863107915753736">लेख ढूंढ़ने में विफल</translation>
<translation id="4326324639298822553">अपना समाप्ति दिनांक जाँचें और फिर से कोशिश करें</translation>
@@ -482,14 +526,12 @@
<translation id="4515275063822566619">कार्ड और पते Chrome और आपके Google खाते (<ph name="ACCOUNT_EMAIL" />) से मिलते हैं. आप उन्हें <ph name="BEGIN_LINK" />सेटिंग<ph name="END_LINK" /> में जाकर प्रबंधित कर सकते हैं.</translation>
<translation id="4522570452068850558">विवरण</translation>
<translation id="4552089082226364758">फ़्लैश</translation>
-<translation id="4554702541363482291"><ph name="SITE" /> पर एम्बेड किए गए पेज से</translation>
<translation id="4558551763791394412">अपने एक्सटेंशन अक्षम करके देखें.</translation>
<translation id="457875822857220463">वितरण</translation>
<translation id="4582800630050655161">आप अपने Google खाते का एक्सेस खो सकते हैं या आपकी पहचान चोरी हो सकती है. Chromium आपको इसी समय अपना पासवर्ड बदलने का सुझाव देता है.</translation>
<translation id="4587425331216688090">Chrome से पता निकालें?</translation>
<translation id="4592951414987517459"><ph name="DOMAIN" /> से आपके कनेक्शन को किसी आधुनिक सिफ़र सुइट का उपयोग करके एन्‍क्रिप्‍ट किया गया है.</translation>
<translation id="4594403342090139922">&amp;हटाना वापस लाएं</translation>
-<translation id="4611292653554630842">लॉग इन करें</translation>
<translation id="4619615317237390068">अन्य डिवाइस के टैब</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">यह सर्वर यह प्रमाणित नहीं कर सका कि यह <ph name="DOMAIN" /> है; इसके सुरक्षा प्रमाणपत्र में त्रुटियां हैं. ऐसा गलत कॉन्फ़िगरेशन के कारण या किसी आक्रमणकर्ता द्वारा आपके कनेक्शन में अवरोध डालने के कारण हो सकता है.</translation>
@@ -499,11 +541,9 @@
<translation id="4708268264240856090">आपका कनेक्शन बाधित था</translation>
<translation id="471880041731876836">आपको इस साइट पर जाने की अनुमति नहीं है</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows नेटवर्क निदान चलाकर देखें<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">आपका भुगतान</translation>
<translation id="4726672564094551039">नीतियां फिर से लोड करें</translation>
<translation id="4728558894243024398">प्लेटफ़ॉर्म</translation>
<translation id="4736825316280949806">क्रोमियम को फिर से शुरू करें</translation>
-<translation id="4737498291095696011">इस पेज से</translation>
<translation id="4744603770635761495">निष्पादन-योग्य पथ</translation>
<translation id="4749685221585524849">पिछली बार <ph name="LAST_USED_MONTH" /> को उपयोग किया गया</translation>
<translation id="4750917950439032686">आपकी जानकारी (उदाहरण के लिए, पासवर्ड या क्रेडिट कार्ड नंबर) जब इस साइट पर भेजी जाती है तब वह निजी होती है .</translation>
@@ -522,16 +562,16 @@
<translation id="4850886885716139402">देखें</translation>
<translation id="4854362297993841467">वितरण का यह तरीका उपलब्ध नहीं है. कोई दूसरा तरीका आज़माएं.</translation>
<translation id="4858792381671956233">आपने अपने अभिभावकों से पूछा था कि इस साइट पर जाना ठीक है या नहीं</translation>
-<translation id="4871132632506079383"><ph name="SITE" /> पर एम्बेड किए गए पेज से</translation>
<translation id="4880827082731008257">खोज इतिहास</translation>
+<translation id="4881695831933465202">खोलें</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">प्रमाणीकरण ज़रूरी है</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{1 और वेब पेज}one{# और वेब पेज}other{# और वेब पेज}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947"><ph name="CREDIT_CARD" /> का कार्ड वेरीफ़िकेशन कोड (सीवीसी) डालें. आपकी ओर से पुष्टि होने के बाद, आपके Google Payments खाते में मौजूद कार्ड के विवरण इस साइट से शेयर किए जाएंगे.</translation>
<translation id="4923417429809017348">इस पेज का एक अज्ञात भाषा से <ph name="LANGUAGE_LANGUAGE" /> में अनुवाद किया गया है</translation>
<translation id="4923459931733593730">भुगतान</translation>
<translation id="4926049483395192435">निर्दिष्ट किया जाना चाहिए.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> का कहना है कि</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">क्रियाएं</translation>
<translation id="4958444002117714549">सूची विस्तृत करें</translation>
@@ -540,7 +580,6 @@
<translation id="5002932099480077015">यदि सक्षम किया हुआ हो, तो Chrome फ़ॉर्म को तेज़ी से भरने के लिए इस डिवाइस पर आपके कार्ड की एक प्रति संग्रहित करेगा.</translation>
<translation id="5018422839182700155">यह पेज खुल नहीं पा रहा है</translation>
<translation id="5019198164206649151">बैकिंग संग्रह खराब स्थिति में है</translation>
-<translation id="5020990877659450221">इस पेज से</translation>
<translation id="5023310440958281426">अपने व्यवस्थापक की नीतियां देखें</translation>
<translation id="5029568752722684782">स्‍पष्‍ट कॉपी</translation>
<translation id="503069730517007720">"<ph name="SOFTWARE_NAME" />" के रूट प्रमाणपत्र की ज़रूरत है लेकिन वह इंस्टॉल नहीं है. यह समस्या ठीक करने के लिए आपके आईटी व्यवस्थापक को "<ph name="SOFTWARE_NAME" />" के कॉन्फ़िगरेशन से जुड़े निर्देशों पर नज़र डालनी चाहिए. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +605,12 @@
<translation id="5172758083709347301">मशीन</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> में नहीं है? इस गड़बड़ी की रिपोर्ट करें</translation>
<translation id="5190835502935405962">बुकमार्क बार</translation>
+<translation id="5201306358585911203">इस पेज पर एम्बेड किए गए पेज का कहना है कि</translation>
<translation id="5205222826937269299">नाम आवश्यक है</translation>
<translation id="5222812217790122047">ईमेल आवश्यक है</translation>
<translation id="522700295135997067">शायद इस साइट ने अभी-अभी आपका पासवर्ड चुरा लिया है</translation>
<translation id="5230733896359313003">शिपिंग पता</translation>
<translation id="5251803541071282808">क्लाउड</translation>
-<translation id="5277279256032773186">कार्यस्थल पर Chrome का उपयोग कर रहे हैं? कंपनियां अपने कर्मचारियों के लिए Chrome सेटिंग प्रबंधित कर सकती हैं. और जानें</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />इन चरणों का पालन करके सॉफ़्टवेयर को कुछ समय के लिए अक्षम करें ताकि आप वेब पर जा सकें. आपको व्यावस्थापकीय विशेषाधिकारों की ज़रूरत होगी.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -619,7 +658,7 @@
<translation id="5540224163453853">अनुरोध किया गया लेख नहीं ढूंढा जा सका.</translation>
<translation id="5541546772353173584">ईमेल जोड़ें</translation>
<translation id="5545756402275714221">आपके लिए लेख</translation>
-<translation id="5556459405103347317">पुन: लोड करें</translation>
+<translation id="5556459405103347317">फिर लोड करें</translation>
<translation id="5560088892362098740">समयसीमा समाप्ति दिनांक</translation>
<translation id="5565735124758917034">सक्रिय</translation>
<translation id="5571083550517324815">इस पते से पिक अप नहीं किया जा सकता. कोई दूसरा पता चुनें.</translation>
@@ -633,7 +672,6 @@
<translation id="5610142619324316209">कनेक्शन की जाँच करें</translation>
<translation id="5610807607761827392">आप <ph name="BEGIN_LINK" />सेटिंग<ph name="END_LINK" /> में कार्ड और पते प्रबंधित कर सकते हैं.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> ने आपको कई बार रीडायरेक्ट किया है.</translation>
-<translation id="5622887735448669177">क्या आप इस साइट को छोड़ना चाहते हैं?</translation>
<translation id="5629630648637658800">नीति सेटिंग लोड करने में विफल</translation>
<translation id="5631439013527180824">अमान्य डिवाइस प्रबंधन टोकन</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>
@@ -656,7 +694,6 @@
<translation id="5786044859038896871">क्या अपनी कार्ड जानकारी भरना चाहते हैं?</translation>
<translation id="5803412860119678065">क्या आप अपनी <ph name="CARD_DETAIL" /> भरना चाहते हैं?</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> से आपके कनेक्शन को किसी अप्रचलित सिफ़र सुइट का उपयोग करके एन्‍क्रिप्‍ट किया गया है.</translation>
-<translation id="5810928923025889964">इस पेज पर एम्बेड किए गए पेज से</translation>
<translation id="5813119285467412249">&amp;जोड़ना फिर से करें</translation>
<translation id="5838278095973806738">आपको इस साइट पर कोई भी संवेदनशील जानकारी (उदाहरण के लिए, पासवर्ड या क्रेडिट कार्ड) नहीं डालनी चाहिए, क्योंकि उसे हमलावर चुरा सकते हैं.</translation>
<translation id="5866257070973731571">फ़ोन नंबर जोड़ें</translation>
@@ -730,21 +767,19 @@
<translation id="6446608382365791566">और जानकारी जोड़ें</translation>
<translation id="6447842834002726250">कुकी</translation>
<translation id="6451458296329894277">फ़ार्म पुन: जमा करने की दुबारा पूछें</translation>
-<translation id="6456339708790392414">आपका भुगतान</translation>
<translation id="647261751007945333">डिवाइस नीतियां</translation>
<translation id="6477321094435799029">Chrome को इस पेज पर असामान्य कोड मिला था और उसने आपकी व्यक्तिगत जानकारी (उदाहरण के लिए, पासवर्ड, फ़ोन नंबर और क्रेडिट कार्ड) की सुरक्षा करने के लिए उसे अवरुद्ध कर दिया है.</translation>
<translation id="6489534406876378309">क्रैश अपलोड करना प्रारंभ करें</translation>
<translation id="6507833130742554667">क्रेडिट और डेबिट कार्ड स्वीकार किए जाते हैं.</translation>
<translation id="6508722015517270189">Chrome को फिर से शुरू करें</translation>
-<translation id="6521373090216409766">क्या आप इस साइट को फिर लोड करना चाहते हैं?</translation>
<translation id="6529602333819889595">&amp;हटाना फिर से करें</translation>
<translation id="6534179046333460208">जीता-जागता वेब के सुझाव</translation>
<translation id="6550675742724504774">विकल्प</translation>
-<translation id="6556239504065605927">सुरक्षित कनेक्शन</translation>
<translation id="6556915248009097796">खत्म होने की तारीख: <ph name="EXPIRATION_DATE_ABBR" />, पिछली बार <ph name="LAST_USED_DATE_NO_DETAIL" /> को उपयोग किया गया</translation>
<translation id="6563469144985748109">आपके प्रबंधक ने अभी तक इसकी स्वीकृति नहीं दी है</translation>
<translation id="6569060085658103619">आप एक एक्सटेंशन पेज देख रहे हैं</translation>
<translation id="6596325263575161958">सुरक्षित तरीका विकल्प</translation>
+<translation id="6604181099783169992">गति या लाइट सेंसर</translation>
<translation id="6624427990725312378">संपर्क जानकारी</translation>
<translation id="6626291197371920147">मान्य कार्ड नंबर जोड़ें</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> खोज</translation>
@@ -816,6 +851,7 @@
<translation id="7275334191706090484">प्रबंधित बुकमार्क</translation>
<translation id="7298195798382681320">सुझाए गए</translation>
<translation id="7309308571273880165">क्रैैश रिपोर्ट <ph name="CRASH_TIME" /> बजे कैप्चर की गई (उपयोगकर्ता द्वारा अपलोड करने का अनुरोध किया गया, अभी तक अपलोड नहीं किया गया)</translation>
+<translation id="7320336641823683070">कनेक्शन संबंधी सहायता</translation>
<translation id="7334320624316649418">&amp;पुन: क्रमित करना फिर से करें</translation>
<translation id="733923710415886693">प्रमाणपत्र पारदर्शिता के माध्यम से सर्वर के प्रमाणपत्र को प्रकट नहीं किया गया.</translation>
<translation id="7353601530677266744">आदेश पंक्ति</translation>
@@ -900,6 +936,7 @@
<translation id="782886543891417279">आप जिस वाई-फ़ाई का उपयोग कर रहे हैं (<ph name="WIFI_NAME" />) उसके लिए आपको प्रवेश पृष्‍ठ पर जाने की आवश्‍यकता हो सकती है.</translation>
<translation id="785549533363645510">हालांकि, आप अदृश्य नहीं हैं. गुप्त मोड में रहने से आपकी ब्राउज़िंग आपके नियोक्ता, आपके इंटरनेट सेवा प्रदाता या आपके द्वारा देखी जाने वाली वेबसाइट से छिपती नहीं है.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">साइट छोड़ें?</translation>
<translation id="7878176543348854470">डेबिट और प्रीपेड कार्ड स्वीकार किए जाते हैं.</translation>
<translation id="7878562273885520351">आपके पासवर्ड से छेड़छाड़ की जा सकती है</translation>
<translation id="7887683347370398519">अपना CVC जाँचें और पुन: प्रयास करें</translation>
@@ -922,6 +959,7 @@
<translation id="8041940743680923270">वैश्विक डिफ़ॉल्ट का उपयोग करें (पूछें)</translation>
<translation id="8042918947222776840">पिकअप का तरीका चुनें</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" सही तरीके से कॉन्फ़िगर नहीं किया गया है. आमतौर पर "<ph name="SOFTWARE_NAME" />" को अनइंस्टॉल करने से समस्या ठीक हो जाती है. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">साइट को फिर लोड करें?</translation>
<translation id="8088680233425245692">लेख देखने में विफल रहा.</translation>
<translation id="8091372947890762290">सर्वर पर सक्रियण लंबित है</translation>
<translation id="8094917007353911263">आप जिस नेटवर्क का उपयोग कर रहे हैं उसके लिए आपको <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> पर जाने की आवश्‍यकता हो सकती है.</translation>
@@ -937,6 +975,7 @@
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" आईडी वाले एक्‍सटेंशन का अमान्‍य अपडेट URL.</translation>
<translation id="8202097416529803614">आदेश सारांश</translation>
<translation id="8205463626947051446">साइट तंग करने वाले विज्ञापन दिखाने के लिए जानी जाती है</translation>
+<translation id="8211406090763984747">कनेक्शन सुरक्षित है</translation>
<translation id="8218327578424803826">सौंपा गया स्‍थान:</translation>
<translation id="8225771182978767009">जिस व्यक्ति ने इस कंप्यूटर को सेट किया है, उसने इस साइट को अवरुद्ध करना चुना है.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +987,7 @@
<translation id="825929999321470778">सेव किए गए सभी पासवर्ड दिखाएं</translation>
<translation id="8261506727792406068">हटाएं</translation>
<translation id="8267698848189296333"><ph name="USERNAME" /> के रूप में प्रवेश करना</translation>
+<translation id="8286036467436129157">प्रवेश करें</translation>
<translation id="8288807391153049143">प्रमाणपत्र दिखाएं</translation>
<translation id="8289355894181816810">यदि आप सुनिश्चित नहीं हैं कि इसका क्या मतलब है, तो अपने नेटवर्क व्यवस्थापक से संपर्क करें.</translation>
<translation id="8293206222192510085">बुकमार्क जोड़ें</translation>
@@ -973,7 +1013,7 @@
<translation id="8466379296835108687">{COUNT,plural, =1{1 क्रेडिट कार्ड}one{# क्रेडिट कार्ड}other{# क्रेडिट कार्ड}}</translation>
<translation id="8483780878231876732">कार्ड का उपयोग अपने Google खाते से करने के लिए, Chrome में प्रवेश करें</translation>
<translation id="8488350697529856933">इस पर लागू होती है</translation>
-<translation id="8498891568109133222"><ph name="HOST_NAME" /> ने प्रतिसाद देने में अत्यधिक समय लिया.</translation>
+<translation id="8498891568109133222"><ph name="HOST_NAME" /> को लोड होने में बहुत ज़्यादा समय लगा.</translation>
<translation id="8503559462189395349">Chrome पासवर्ड</translation>
<translation id="8503813439785031346">उपयोगकर्ता नाम</translation>
<translation id="8543181531796978784">आप <ph name="BEGIN_ERROR_LINK" />पहचान संबंधी समस्‍या की रिपोर्ट<ph name="END_ERROR_LINK" /> कर सकते हैं या यदि आप अपनी सुरक्षा से जुड़े जोखिमों को समझते हैं, तो <ph name="BEGIN_LINK" />इस असुरक्षित साइट पर जा<ph name="END_LINK" /> सकते हैं.</translation>
@@ -999,6 +1039,7 @@
<translation id="874846938927089722">स्वीकार किए जाने वाले क्रेडिट और प्रीपेड कार्ड</translation>
<translation id="8759274551635299824">इस कार्ड की अवधि खत्म हो चुकी है</translation>
<translation id="8761567432415473239">Google सुरक्षित ब्राउज़िंग को <ph name="SITE" /> पर हाल ही में <ph name="BEGIN_LINK" />हानिकारक प्रोग्राम मिले हैं<ph name="END_LINK" />.</translation>
+<translation id="8763927697961133303">USB डिवाइस</translation>
<translation id="8790007591277257123">&amp;हटाना फिर से करें</translation>
<translation id="8800988563907321413">आपके आस-पास के सुझाव यहां दिखाई देंगे</translation>
<translation id="8820817407110198400">बुकमार्क</translation>
diff --git a/chromium/components/strings/components_strings_hr.xtb b/chromium/components/strings/components_strings_hr.xtb
index 4c0fd6e5be9..a1635a1aed5 100644
--- a/chromium/components/strings/components_strings_hr.xtb
+++ b/chromium/components/strings/components_strings_hr.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Ispis...</translation>
<translation id="1181037720776840403">Ukloni</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Automatski prijavi<ph name="END_WHITEPAPER_LINK" /> Googleu pojedinosti o mogućim sigurnosnim incidentima. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Plaćanje nije dovršeno</translation>
<translation id="1201402288615127009">Sljedeće</translation>
<translation id="1201895884277373915">Više s ove web-lokacije</translation>
<translation id="1206967143813997005">Potpis inicijalima nije ispravan</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Izvješća o rušenju programa generirana <ph name="CRASH_TIME" /> (još nisu prenesena ili zanemarena)</translation>
<translation id="1270502636509132238">Način preuzimanja</translation>
<translation id="1285320974508926690">Nikad nemoj prevoditi ovu web-lokaciju</translation>
+<translation id="1294154142200295408">Varijacije naredbenog retka</translation>
<translation id="129553762522093515">Nedavno zatvoreno</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Izbrišite kolačiće<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Vaše aktivnosti <ph name="BEGIN_EMPHASIS" />i dalje mogu biti vidljive<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Prihvaćene kreditne i debitne kartice</translation>
<translation id="1519264250979466059">Datum međuverzije</translation>
<translation id="1527263332363067270">Čekanje na uspostavu veze…</translation>
+<translation id="1532118530259321453">Na ovoj se stranici navodi sljedeće</translation>
<translation id="153384715582417236">To je zasad sve</translation>
<translation id="154408704832528245">Odaberite adresu za isporuku</translation>
<translation id="1549470594296187301">Za upotrebu te značajke mora biti omogućen JavaScript.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />provjerite proxy i vatrozid<ph name="END_LINK" /></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="2065985942032347596">Potrebna autentikacija</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="2091887806945687916">Zvuk</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Otkaži plaćanje</translation>
<translation id="2147827593068025794">Sinkronizacija u pozadini</translation>
<translation id="2148613324460538318">Dodaj karticu</translation>
-<translation id="2149973817440762519">Uredi oznaku</translation>
<translation id="2154054054215849342">Sinkronizacija nije dostupna za vašu domenu</translation>
<translation id="2154484045852737596">Uredite karticu</translation>
<translation id="2166049586286450108">Potpuni administratorski pristup</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Odaberite adresu preuzimanja</translation>
<translation id="2740531572673183784">U redu</translation>
<translation id="2742870351467570537">Ukloni odabrane stavke</translation>
-<translation id="2744590937989388266">S ugrađene stranice na ovoj stranici</translation>
<translation id="277133753123645258">Način dostave</translation>
<translation id="277499241957683684">Zapis uređaja nije prisutan</translation>
<translation id="2784949926578158345">Veza je ponovo uspostavljena.</translation>
<translation id="2788784517760473862">Prihvaćene kreditne kartice</translation>
<translation id="2794233252405721443">Web-lokacija blokirana</translation>
-<translation id="2795286477369100655">Želite li zatvoriti tu web-lokaciju?</translation>
<translation id="2799020568854403057">Sljedeća web-lokacija sadrži štetne aplikacije</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="2824775600643448204">Adresna traka i traka za pretraživanje</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Unos popisa "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automatski blokirano</translation>
<translation id="3024663005179499861">Pogrešna vrsta pravila</translation>
-<translation id="3032412215588512954">Želite li ponovo učitati tu web-lokaciju?</translation>
<translation id="3037605927509011580">O, ne!</translation>
<translation id="3039538478787849737">Želite li spremiti karticu na Google?</translation>
<translation id="3041612393474885105">Podaci o certifikatu</translation>
@@ -310,6 +306,7 @@
biste provjerili je li proxy poslužitelj u funkciji. Ako mislite da ne
biste trebali upotrebljavati proxy poslužitelj:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> na poslužitelju <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Otkaži plaćanje</translation>
<translation id="3207960819495026254">Označeno</translation>
<translation id="3209375525920864198">Unesite važeći naziv sesije.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Voditelj je može deblokirati</translation>
<translation id="3566021033012934673">Vaša veza nije privatna</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Na ugrađenoj stranici na web-lokaciji <ph name="SITE" /> navodi se sljedeće</translation>
<translation id="358285529439630156">Prihvaćaju se kreditne i pretplatne kartice.</translation>
<translation id="3582930987043644930">Dodajte ime</translation>
<translation id="3583757800736429874">&amp;Ponovi premještanje</translation>
<translation id="3586931643579894722">Sakrij detalje</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Ispravljanje pogrešaka veze&lt;/h1&gt;
+ &lt;p&gt;Ako vam se pri pokušaju otvaranja web-lokacije prikaže poruka pogreške, pokušajte primijeniti ova rješenja.&lt;/p&gt;
+ &lt;h2&gt;Ispravljanje većine pogrešaka veze&lt;/h2&gt;
+ &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;
+ &lt;ol&gt;
+ &lt;li&gt;Provjerite je li web-adresa ispravno napisana.&lt;/li&gt;
+ &lt;li&gt;Provjerite jeste li povezani s internetom.&lt;/li&gt;
+ &lt;li&gt;Obratite se vlasniku web-lokacije.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Pomoć za konkretne poruke pogreške&lt;/h2&gt;
+ &lt;h3&gt;"Vaša veza nije privatna" ili "NET::ERR_CERT_AUTHORITY_INVALID" ili "ERR_CERT_COMMON_NAME_INVALID" ili "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" ili "Pogreška SSL certifikata"&lt;/h3&gt;
+ &lt;h4&gt;1. korak: prijavite se na portal&lt;/h4&gt;
+ &lt;p&gt;Na Wi-Fi mreže na mjestima kao što su kafići ili zračne luke trebate se prijaviti. Da biste vidjeli stranicu za prijavu, posjetite stranicu koja upotrebljava&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Otvorite bilo koju web-lokaciju koja započinje s &lt;code&gt;http://&lt;/code&gt;, na primjer &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Na stranici za prijavu koja će se otvoriti prijavite se da biste se povezali s internetom.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;2. korak: otvorite stranicu u anonimnom načinu (samo na računalima)&lt;/h4&gt;
+ &lt;p&gt;Otvorite stranicu koju ste posjetili u anonimnom prozoru.&lt;/p&gt;
+ &lt;p&gt;Ako se ta stranica otvori, Chromeovo proširenje ne funkcionira pravilno. Da biste ispravili tu pogrešku, isključite proširenje.&lt;/p&gt;
+ &lt;h4&gt;3. korak: ažurirajte operativni sustav&lt;/h4&gt;
+ &lt;p&gt;Ako uređaj nije ažuriran, ažurirajte ga.&lt;/p&gt;
+ &lt;h4&gt;4. korak: privremeno isključite antivirusni softver&lt;/h4&gt;
+ &lt;p&gt;Ta će se pogreška pojaviti ako imate antivirusni softver za "zaštitu HTTPS-a" ili "pretraživanje HTTPS-a". Taj softver onemogućuje Chromeu da pruža zaštitu.&lt;/p&gt;
+ &lt;p&gt;Da biste riješili taj problem, isključite antivirusni softver. Ako nakon isključivanja tog softvera stranica funkcionira, isključite taj softver kada upotrebljavate sigurne web-lokacije.&lt;/p&gt;
+ &lt;p&gt;Ne zaboravite ponovo uključiti antivirusni program kada završite.&lt;/p&gt;
+ &lt;h4&gt;5. korak: potražite dodatnu pomoć&lt;/h4&gt;
+ &lt;p&gt;Ako i dalje vidite pogrešku, obratite se vlasniku web-lokacije.&lt;/p&gt;
+ &lt;h3&gt;"Povežite se s mrežom"&lt;/h3&gt;
+ &lt;p&gt;Ta će se pogreška pojaviti ako upotrebljavate Wi-Fi portal na kojem se morate prijaviti da biste se mogli povezati s internetom.&lt;/p&gt;
+ &lt;p&gt;Da biste ispravili tu pogrešku, na stranici koju pokušavate otvoriti kliknite &lt;strong&gt;Poveži&lt;/strong&gt;.&lt;/p&gt;
+ &lt;h3&gt;"Sat kasni" ili "Sat ide unaprijed" ili "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Ta će se pogreška pojaviti ako datum i vrijeme vašeg računala ili mobilnog uređaja nisu točni.&lt;/p&gt;
+ &lt;p&gt;Da biste ispravili tu pogrešku, otvorite sat uređaja. Provjerite jesu li vrijeme i datum točni.&lt;/p&gt;
+ &lt;h3&gt;"Softver na vašem računalu sprječava sigurno povezivanje Chromea s webom" (samo na Windows računalima)&lt;/h3&gt;
+ &lt;p&gt;Ta će se pogreška pojaviti ako na Windows računalu imate softver Superfish.&lt;/p&gt;
+ &lt;p&gt;Privremeno onemogućite softver prema ovim uputama da biste se povezali s webom. Potrebne su vam administratorske povlastice.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Kliknite &lt;strong&gt;Start&lt;/strong&gt;, a zatim potražite i odaberite &lt;strong&gt;"Prikaz lokalnih servisa".&lt;/strong&gt;
+ &lt;li&gt;Odaberite &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;U odjeljku &lt;strong&gt;Vrsta pokretanja&lt;/strong&gt; odaberite &lt;strong&gt;Onemogućeno&lt;/strong&gt;
+ &lt;li&gt;U odjeljku &lt;strong&gt;Status servisa&lt;/strong&gt; kliknite &lt;strong&gt;Zaustavi&lt;/strong&gt;
+ &lt;li&gt;Kliknite &lt;strong&gt;Primijeni&lt;/strong&gt;, a zatim kliknite &lt;strong&gt;U redu&lt;/strong&gt;
+ &lt;li&gt;U &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chromeovu centru za pomoć&lt;/a&gt; možete saznati kako trajno ukloniti softver s računala
+ &lt;/ol&gt;</translation>
<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>
@@ -403,7 +446,6 @@
<translation id="3778403066972421603">Želite li spremiti ovu karticu na svoj Google račun i na ovaj uređaj?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Istječe <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">S web-lokacije <ph name="SITE" /></translation>
<translation id="382518646247711829">Ako upotrebljavate proxy poslužitelj...</translation>
<translation id="3828924085048779000">Prazne zaporke nisu dopuštene.</translation>
<translation id="385051799172605136">Natrag</translation>
@@ -417,6 +459,7 @@
<translation id="3945915738023014686">Preneseno je izvješće o rušenju programa s ID-om <ph name="CRASH_ID" /> (lokalni ID rušenja: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Poslužitelj nije mogao dokazati da je <ph name="DOMAIN" />; njegov sigurnosni certifikat ne navodi alternativne nazive predmeta. To može biti uzrokovano pogrešnom konfiguracijom ili napadom na vašu vezu.</translation>
<translation id="3949601375789751990">Ovdje se prikazuje vaša povijest pregledavanja</translation>
+<translation id="3950820424414687140">Prijava</translation>
<translation id="3963721102035795474">Način čitača</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Nijedna}=1{S 1 web-lokacije }one{S/sa # web-lokacije }few{S/sa # web-lokacije }other{S/sa # web-lokacija }}</translation>
<translation id="397105322502079400">Izračun u tijeku…</translation>
@@ -433,6 +476,7 @@
<translation id="4103249731201008433">Serijski broj uređaja nije važeći</translation>
<translation id="410351446219883937">Automatska reprodukcija</translation>
<translation id="4103763322291513355">Posjetite &lt;strong&gt;chrome://policy&lt;/strong&gt; da biste vidjeli popis nedopuštenih URL-ova i druga pravila koja je nametnuo vaš administrator sustava.</translation>
+<translation id="4110652170750985508">Pregledajte uplatu</translation>
<translation id="4116663294526079822">Uvijek dopusti na ovoj web-lokaciji</translation>
<translation id="4117700440116928470">Opseg pravila nije podržan.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 druga stavka}one{# druga stavka}few{# druge stavke}other{# drugih stavki}}</translation>
@@ -459,7 +503,6 @@
<translation id="4269787794583293679">(Nema korisničkog imena)</translation>
<translation id="4275830172053184480">Ponovo pokrenite svoj uređaj</translation>
<translation id="4280429058323657511">, istek <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Prijavi se</translation>
<translation id="4312866146174492540">Blokiraj (zadano)</translation>
<translation id="4325863107915753736">Članak nije pronađen</translation>
<translation id="4326324639298822553">Provjerite datum isteka, pa pokušajte ponovo</translation>
@@ -481,14 +524,12 @@
<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="4522570452068850558">Detalji</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">S ugrađene stranice na web-lokaciji <ph name="SITE" /></translation>
<translation id="4558551763791394412">Pokušajte onemogućiti proširenja.</translation>
<translation id="457875822857220463">Dostava</translation>
<translation id="4582800630050655161">Mogli biste izgubiti pristup svojem Google računu ili bi netko mogao ukrasti vaš identitet. Chromium preporučuje da odmah promijenite zaporku.</translation>
<translation id="4587425331216688090">Želite li s Chromea ukloniti adresu?</translation>
<translation id="4592951414987517459">Vaša veza s domenom <ph name="DOMAIN" /> kriptirana je modernim kriptografskim paketom.</translation>
<translation id="4594403342090139922">&amp;Poništi brisanje</translation>
-<translation id="4611292653554630842">Prijava</translation>
<translation id="4619615317237390068">Kartice s drugih uređaja</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Poslužitelj nije mogao dokazati da je <ph name="DOMAIN" />; njegov sigurnosni certifikat sadrži pogreške. To može biti uzrokovano pogrešnom konfiguracijom ili napadom na vašu vezu.</translation>
@@ -498,11 +539,9 @@
<translation id="4708268264240856090">Veza je prekinuta</translation>
<translation id="471880041731876836">Nemaš dopuštenje za posjet toj web-lokaciji</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />pokrenuti Mrežnu dijagnostiku sustava Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Vaše plaćanje</translation>
<translation id="4726672564094551039">Ponovo učitaj pravila</translation>
<translation id="4728558894243024398">Platforma</translation>
<translation id="4736825316280949806">Ponovo pokrenite Chromium</translation>
-<translation id="4737498291095696011">S ove stranice</translation>
<translation id="4744603770635761495">Izvršna putanja</translation>
<translation id="4749685221585524849">Posljednja upotreba <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Vaši podaci (na primjer, zaporke i brojevi kreditnih kartica) privatni su kada se šalju na tu web-lokaciju.</translation>
@@ -521,16 +560,16 @@
<translation id="4850886885716139402">Prikaz</translation>
<translation id="4854362297993841467">Taj način dostave nije dostupan. Pokušajte s nekim drugim načinom.</translation>
<translation id="4858792381671956233">Pitao si roditelje smiješ li otvoriti tu web-lokaciju</translation>
-<translation id="4871132632506079383">S ugrađene stranice na web-lokaciji <ph name="SITE" /></translation>
<translation id="4880827082731008257">Pretraži povijest</translation>
+<translation id="4881695831933465202">Otvori</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Potrebna je autentifikacija</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{i još 1 web-stranica}one{i još # web-stranica}few{i još # web-stranice}other{i još # web-stranica}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Unesite CVC za karticu <ph name="CREDIT_CARD" />. Nakon što ih potvrdite, podaci o kartici s vašeg računa na usluzi Google Payments podijelit će se s ovom web-lokacijom.</translation>
<translation id="4923417429809017348">Ova je stranica prevedena s nepoznatog jezika na <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Plaćanje</translation>
<translation id="4926049483395192435">Mora biti određeno.</translation>
+<translation id="4926159001844873046">Na web-lokaciji <ph name="SITE" /> navodi se sljedeće</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Radnje</translation>
<translation id="4958444002117714549">Proširi popis</translation>
@@ -539,7 +578,6 @@
<translation id="5002932099480077015">Ako je to omogućeno, Chrome će pohraniti kopiju vaše kartice na ovom uređaju radi bržeg ispunjavanja obrazaca.</translation>
<translation id="5018422839182700155">Stranica se ne može otvoriti</translation>
<translation id="5019198164206649151">Sigurnosno pohranjivanje u neispravnom je stanju</translation>
-<translation id="5020990877659450221">S ove stranice</translation>
<translation id="5023310440958281426">Provjerite pravila svojeg administratora</translation>
<translation id="5029568752722684782">Izbriši kopiju</translation>
<translation id="503069730517007720">Potreban je korijenski certifikat za "<ph name="SOFTWARE_NAME" />", ali nije instaliran. Vaš IT administrator trebao bi pogledati upute za konfiguraciju softvera "<ph name="SOFTWARE_NAME" />" kako bi riješio taj problem. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -565,12 +603,12 @@
<translation id="5172758083709347301">Strojno</translation>
<translation id="5179510805599951267">Nije <ph name="ORIGINAL_LANGUAGE" /> jezik? Prijavite tu pogrešku</translation>
<translation id="5190835502935405962">Traka oznaka</translation>
+<translation id="5201306358585911203">Na ugrađenoj stranici na ovoj stranici navodi se sljedeće</translation>
<translation id="5205222826937269299">Ime je obavezno</translation>
<translation id="5222812217790122047">E-pošta (obavezno)</translation>
<translation id="522700295135997067">Ova web-lokacija možda vam je upravo ukrala zaporku</translation>
<translation id="5230733896359313003">Adresa za dostavu</translation>
<translation id="5251803541071282808">Oblak</translation>
-<translation id="5277279256032773186">Upotrebljavate li Chrome na poslu? Tvrtke mogu upravljati Chromeovim postavkama za svoje zaposlenike. Saznajte više</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Privremeno onemogućite softver prema ovim uputama da biste se povezali s webom. Potrebne su vam administratorske povlastice.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -632,7 +670,6 @@
<translation id="5610142619324316209">provjerite vezu</translation>
<translation id="5610807607761827392">Karticama i adresama možete upravljati u <ph name="BEGIN_LINK" />Postavkama<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Host <ph name="HOST_NAME" /> preusmjerio vas je previše puta.</translation>
-<translation id="5622887735448669177">Želite li zatvoriti tu web-lokaciju?</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="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>
@@ -655,7 +692,6 @@
<translation id="5786044859038896871">Želite li ispuniti podatke o kartici?</translation>
<translation id="5803412860119678065">Želite li ispuniti podatke o kartici <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Vaša veza s domenom <ph name="DOMAIN" /> kriptirana je zastarjelim kriptografskim paketom.</translation>
-<translation id="5810928923025889964">S ugrađene stranice na ovoj stranici</translation>
<translation id="5813119285467412249">&amp;Ponovi dodavanje</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>
<translation id="5866257070973731571">Dodajte telefonski broj</translation>
@@ -729,21 +765,19 @@
<translation id="6446608382365791566">Dodajte još podataka</translation>
<translation id="6447842834002726250">Kolačići</translation>
<translation id="6451458296329894277">Potvrdi ponovno slanje obrasca</translation>
-<translation id="6456339708790392414">Vaše plaćanje</translation>
<translation id="647261751007945333">Pravila uređaja</translation>
<translation id="6477321094435799029">Chrome je otkrio neuobičajeni kôd na toj stranici i blokirao ju je radi zaštite vaših osobnih podataka (primjerice zaporki, telefonskih brojeva i kreditnih kartica).</translation>
<translation id="6489534406876378309">Pokreni prijenos rušenja</translation>
<translation id="6507833130742554667">Prihvaćaju se kreditne i debitne kartice.</translation>
<translation id="6508722015517270189">Ponovo pokrenite Chrome</translation>
-<translation id="6521373090216409766">Želite li ponovo učitati tu web-lokaciju?</translation>
<translation id="6529602333819889595">&amp;Ponovi brisanje</translation>
<translation id="6534179046333460208">Prijedlozi Fizičkog weba</translation>
<translation id="6550675742724504774">Opcije</translation>
-<translation id="6556239504065605927">Sigurna veza</translation>
<translation id="6556915248009097796">Istek: <ph name="EXPIRATION_DATE_ABBR" />, posljednja upotreba <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Voditelj je još nije odobrio</translation>
<translation id="6569060085658103619">Gledate stranicu proširenja</translation>
<translation id="6596325263575161958">Opcije šifriranja</translation>
+<translation id="6604181099783169992">Senzori pokreta ili osvjetljenja</translation>
<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>
@@ -815,6 +849,7 @@
<translation id="7275334191706090484">Upravljane oznake</translation>
<translation id="7298195798382681320">Preporučeno</translation>
<translation id="7309308571273880165">Izvješće o rušenju programa generirano <ph name="CRASH_TIME" /> (prijenos zatražio korisnik, još nije preneseno)</translation>
+<translation id="7320336641823683070">Pomoć za povezivanje</translation>
<translation id="7334320624316649418">&amp;Ponovi promjenu rasporeda</translation>
<translation id="733923710415886693">Certifikat poslužitelja nije otkriven putem Transparentnosti certifikata.</translation>
<translation id="7353601530677266744">Naredbeni redak</translation>
@@ -899,6 +934,7 @@
<translation id="782886543891417279">Za Wi-Fi koji upotrebljavate (<ph name="WIFI_NAME" />) možda ćete morati posjetiti stranicu za prijavu.</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="7862185352068345852">Želite li napustiti web-lokaciju?</translation>
<translation id="7878176543348854470">Prihvaćaju se debitne i pretplatne kartice.</translation>
<translation id="7878562273885520351">Vaša je zaporka možda ugrožena</translation>
<translation id="7887683347370398519">Provjerite CVC i pokušajte ponovo</translation>
@@ -921,6 +957,7 @@
<translation id="8041940743680923270">Upotrijebi globalnu zadanu vrijednost (pitaj)</translation>
<translation id="8042918947222776840">Odaberite način preuzimanja</translation>
<translation id="8057711352706143257">Softver "<ph name="SOFTWARE_NAME" />" nije ispravno konfiguriran. Taj se problem obično rješava deinstaliranjem softvera "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Želite li ponovo učitati web-lokaciju?</translation>
<translation id="8088680233425245692">Prikaz članka nije uspio.</translation>
<translation id="8091372947890762290">Aktivacija je na čekanju na poslužitelju</translation>
<translation id="8094917007353911263">Za mrežu koju upotrebljavate možda ćete morati posjetiti stranicu <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -936,6 +973,7 @@
<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>
<translation id="8205463626947051446">Web-lokacija često prikazuje ometajuće oglase</translation>
+<translation id="8211406090763984747">Veza je sigurna</translation>
<translation id="8218327578424803826">Dodijeljena lokacija:</translation>
<translation id="8225771182978767009">Osoba koja je postavila računalo blokirala je tu web-lokaciju.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -947,6 +985,7 @@
<translation id="825929999321470778">Prikaži sve spremljene zaporke</translation>
<translation id="8261506727792406068">Izbriši</translation>
<translation id="8267698848189296333">Prijavljujete se kao <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Prijava</translation>
<translation id="8288807391153049143">Prikaz certifikata</translation>
<translation id="8289355894181816810">Obratite se svojem mrežnom administratoru ako niste sigurni što to znači.</translation>
<translation id="8293206222192510085">Dodaj oznaku</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Prihvaćene kreditne i pretplatne kartice</translation>
<translation id="8759274551635299824">Ta je kartica istekla</translation>
<translation id="8761567432415473239">Googleovo Sigurno pregledavanje nedavno je <ph name="BEGIN_LINK" />pronašlo štetne programe<ph name="END_LINK" /> na web-lokaciji <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">USB uređaj</translation>
<translation id="8790007591277257123">&amp;Ponovi brisanje</translation>
<translation id="8800988563907321413">Ovdje se prikazuju prijedlozi u blizini za vas</translation>
<translation id="8820817407110198400">Knjižne oznake</translation>
diff --git a/chromium/components/strings/components_strings_hu.xtb b/chromium/components/strings/components_strings_hu.xtb
index dabf29b371a..e2c124a408b 100644
--- a/chromium/components/strings/components_strings_hu.xtb
+++ b/chromium/components/strings/components_strings_hu.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Nyomtatás...</translation>
<translation id="1181037720776840403">Eltávolítás</translation>
<translation id="1184214524891303587">A lehetséges biztonsági események adatainak <ph name="BEGIN_WHITEPAPER_LINK" />automatikus jelentése<ph name="END_WHITEPAPER_LINK" /> a Google-nak. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">A fizetés nem fejeződött be</translation>
<translation id="1201402288615127009">Következő</translation>
<translation id="1201895884277373915">Továbbiak erről a webhelyről</translation>
<translation id="1206967143813997005">Hibás alapértelmezett aláírás</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Hibajelentés készült: <ph name="CRASH_TIME" /> (még nincs feltöltve vagy mellőzték)</translation>
<translation id="1270502636509132238">Átvételi mód</translation>
<translation id="1285320974508926690">Ezt a webhelyet soha ne fordítsa le</translation>
+<translation id="1294154142200295408">Parancssorváltozatok</translation>
<translation id="129553762522093515">Mostanában bezárt</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Próbálkozzon a cookie-k törlésével<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Tevékenysége <ph name="BEGIN_EMPHASIS" />továbbra is látható maradhat<ph name="END_EMPHASIS" /> a következők számára:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Elfogadott hitel- és bankkártyák</translation>
<translation id="1519264250979466059">Build dátuma</translation>
<translation id="1527263332363067270">Várakozás a kapcsolódásra…</translation>
+<translation id="1532118530259321453">Az oldal közlendője</translation>
<translation id="153384715582417236">Egyelőre ennyi</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>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />A proxy és a tűzfal ellenőrzése<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Irányítószám</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 javaslat}other{# javaslat}}</translation>
-<translation id="2065985942032347596">Hitelesítés szükséges</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="2091887806945687916">Hang</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Fizetés visszavonása</translation>
<translation id="2147827593068025794">Szinkronizálás a háttérben</translation>
<translation id="2148613324460538318">Kártya hozzáadása</translation>
-<translation id="2149973817440762519">Könyvjelző szerkesztése</translation>
<translation id="2154054054215849342">A szinkronizálás az Ön domainjén nem áll rendelkezésre</translation>
<translation id="2154484045852737596">Kártya szerkesztése</translation>
<translation id="2166049586286450108">Teljes rendszergazdai hozzáférés</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Átvételi cím kiválasztása</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">A kijelölt elemek eltávolítása</translation>
-<translation id="2744590937989388266">Az oldal egyik beágyazott oldaláról</translation>
<translation id="277133753123645258">Szállítási mód</translation>
<translation id="277499241957683684">Hiányzó eszközrekord</translation>
<translation id="2784949926578158345">A kapcsolat alaphelyzetbe állt.</translation>
<translation id="2788784517760473862">Elfogadott hitelkártyák</translation>
<translation id="2794233252405721443">A webhely le van tiltva</translation>
-<translation id="2795286477369100655">Szeretné elhagyni ezt a webhelyet?</translation>
<translation id="2799020568854403057">A felkeresni kívánt webhely káros alkalmazásokat tartalmaz</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="2824775600643448204">Cím- és keresősáv</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">"<ph name="ENTRY_INDEX" />." listabejegyzés: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automatikusan letiltva</translation>
<translation id="3024663005179499861">Nem megfelelő irányelvtípus</translation>
-<translation id="3032412215588512954">Szeretné újratölteni a webhelyet?</translation>
<translation id="3037605927509011580">A manóba!</translation>
<translation id="3039538478787849737">Menti a kártyát a Google rendszerébe?</translation>
<translation id="3041612393474885105">Tanúsítvány adatai</translation>
@@ -308,6 +304,7 @@
<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:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> nyomtató a(z) <ph name="SERVER_NAME" /> nevű szerveren</translation>
<translation id="320323717674993345">Fizetés visszavonása</translation>
<translation id="3207960819495026254">Könyvjelzőzött</translation>
<translation id="3209375525920864198">Érvényes munkamenetnevet adjon meg.</translation>
@@ -365,11 +362,57 @@
<translation id="3556433843310711081">A letiltást a kezelő oldhatja fel</translation>
<translation id="3566021033012934673">Az Ön kapcsolata nem privát</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">A(z) <ph name="SITE" /> egyik beágyazott oldalának közlendője</translation>
<translation id="358285529439630156">Elfogadott hitel- és feltöltőkártyák.</translation>
<translation id="3582930987043644930">Név hozzáadása</translation>
<translation id="3583757800736429874">&amp;Áthelyezés újra</translation>
<translation id="3586931643579894722">Részletek elrejtése</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;A kapcsolódási problémák megoldása&lt;/h1&gt;
+ &lt;p&gt;Ha hibaüzenetet kap, amikor megpróbál megnyitni valamilyen webhelyet, akkor próbálkozzon az alábbi megoldásokkal.&lt;/p&gt;
+ &lt;h2&gt;A csatlakozási hibák többségének megoldása&lt;/h2&gt;
+ &lt;p&gt;Ha a felkeresni kívánt webhely nem nyílik meg, 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;
+ &lt;ol&gt;
+ &lt;li&gt;Keressen gépelési hibát az internetcímben.&lt;/li&gt;
+ &lt;li&gt;Győződjön meg arról, hogy internetkapcsolata megfelelően működik.&lt;/li&gt;
+ &lt;li&gt;Vegye fel a kapcsolatot a webhely tulajdonosával.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Segítségkérés konkrét hibaüzenettel kapcsolatban&lt;/h2&gt;
+ &lt;h3&gt;„Az Ön kapcsolata nem privát”, „NET::ERR_CERT_AUTHORITY_INVALID”, „ERR_CERT_COMMON_NAME_INVALID”, „NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM” vagy „SSL-tanúsítványhiba”&lt;/h3&gt;
+ &lt;h4&gt;1. lépés: Jelentkezzen be a portálra&lt;/h4&gt;
+ &lt;p&gt;Az olyan nyilvános helyek Wi-Fi-hálózatai esetében, mint a kávézók és a repterek, bejelentkezés szükséges. A bejelentkezési oldal megtekintéséhez keressen fel egy olyan oldalt, amely a &lt;code&gt;http://&lt;/code&gt; előtaggal kezdődik.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Keresse fel valamelyik tetszőleges, &lt;code&gt;http://&lt;/code&gt; karakterlánccal kezdődő webhelyet, amilyen például a következő: &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Az internet használatához jelentkezzen be a megnyíló bejelentkezési oldalon.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;2. lépés: Nyissa meg a weboldalt inkognitómódban (csak számítógépen)&lt;/h4&gt;
+ &lt;p&gt;Nyissa meg a felkeresett weboldalt inkognitómódban.&lt;/p&gt;
+ &lt;p&gt;Ha az oldal megnyílik, akkor a Chrome egyik bővítménye nem működik megfelelően. A hiba kijavításához kapcsolja ki a bővítményt.&lt;/p&gt;
+ &lt;h4&gt;3. lépés: Frissítse operációs rendszerét&lt;/h4&gt;
+ &lt;p&gt;Győződjön meg arról, hogy eszközének operációs rendszere naprakész.&lt;/p&gt;
+ &lt;h4&gt;4. lépés: Ideiglenesen kapcsolja ki a vírusirtó szoftvert&lt;/h4&gt;
+ &lt;p&gt;Akkor láthatja ezt a hibaüzenetet, ha vírusirtó szoftvere HTTPS-védelmi vagy HTTPS-vizsgálati funkciót tartalmaz. A vírusirtó megakadályozza, hogy a Chrome biztonságos kapcsolatot létesítsen.&lt;/p&gt;
+ &lt;p&gt;A probléma megoldásához kapcsolja ki vírusirtó szoftverét. Ha a weboldal a szoftver kikapcsolása után működik, minden alkalommal kapcsolja ki, ha biztonságos webhelyen jár.&lt;/p&gt;
+ &lt;p&gt;Ne felejtse el újra bekapcsolni a vírusirtót, ha végzett.&lt;/p&gt;
+ &lt;h4&gt;5. lépés: Vegyen igénybe külső segítséget&lt;/h4&gt;
+ &lt;p&gt;Ha a hiba továbbra is fennáll, lépjen kapcsolatba a webhely tulajdonosával.&lt;/p&gt;
+ &lt;h3&gt;„Csatlakozás hálózathoz”&lt;/h3&gt;
+ &lt;p&gt;Akkor láthatja ezt a hibaüzenetet, ha olyan Wi-Fi-portált használ, amelybe be kell jelentkezni, hogy használhassa az internetet.&lt;/p&gt;
+ &lt;p&gt;A probléma megoldásához kattintson a megnyitni kívánt oldalon lévő &lt;strong&gt;Connect&lt;/strong&gt; (Csatlakozás) gombra.&lt;/p&gt;
+ &lt;h3&gt;„Az óra késik” vagy „Az óra siet”, illetve „NET::ERR_CERT_DATE_INVALID”&lt;/h3&gt;
+ &lt;p&gt;Akkor láthatja ezt a hibaüzenetet, ha számítógépén vagy mobileszközén pontatlanul van beállítva a dátum és az idő.&lt;/p&gt;
+ &lt;p&gt;A probléma megoldásához nyissa meg az eszköz óráját. Gondoskodjon a dátum és az idő helyes beállításáról.&lt;/p&gt;
+ &lt;h3&gt;„A számítógépen található valamelyik szoftver megakadályozza a Chrome-ot abban, hogy biztonságosan csatlakozzon az internetre” (csak Windows rendszerű számítógépeken)&lt;/h3&gt;
+ &lt;p&gt;Akkor láthatja ezt a hibaüzenetet, ha a Superfish szoftver telepítve van windowsos számítógépén.&lt;/p&gt;
+ &lt;p&gt;Kövesse ezeket a lépéseket, ha szeretné átmenetileg letiltani a szoftvert, hogy hozzáférjen az internethez. Rendszergazdai jogosultságokra lesz szüksége.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Kattintson a &lt;strong&gt;Start&lt;/strong&gt; menüre, majd keresse meg, és válassza ki a &lt;strong&gt;„Helyi szolgáltatások megjelenítése”&lt;/strong&gt; lehetőséget.
+ &lt;li&gt;Válassza ki a &lt;strong&gt;VisualDiscovery&lt;/strong&gt; szolgáltatást.
+ &lt;li&gt;Az &lt;strong&gt;Indítás típusa&lt;/strong&gt; legördülő menüben válassza ki a &lt;strong&gt;Letiltva&lt;/strong&gt; lehetőséget.
+ &lt;li&gt;A &lt;strong&gt;Szolgáltatás állapota&lt;/strong&gt; részben kattintson a &lt;strong&gt;Leállítás&lt;/strong&gt; gombra.
+ &lt;li&gt;Kattintson előbb az &lt;strong&gt;Alkalmaz&lt;/strong&gt;, majd az &lt;strong&gt;OK&lt;/strong&gt; gombra.
+ &lt;li&gt;A &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome súgójában&lt;/a&gt; többet is megtudhat arról, hogyan távolíthatja el véglegesen a szoftvert a számítógépéről.
+ &lt;/ol&gt;</translation>
<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">Minden előzmény megjelenítése</translation>
@@ -402,7 +445,6 @@
<translation id="3778403066972421603">Szeretné menteni a kártyát Google-fiókjába és az eszközre?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Lejárat dátuma: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">A(z) <ph name="SITE" /> webhelyről</translation>
<translation id="382518646247711829">Ha proxyszervert használ...</translation>
<translation id="3828924085048779000">Az üres összetett jelszó nem engedélyezett.</translation>
<translation id="385051799172605136">Vissza</translation>
@@ -416,6 +458,7 @@
<translation id="3945915738023014686">Feltöltött hibajelentés azonosítója: <ph name="CRASH_ID" /> (helyi hibaazonosító: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">A szerver nem tudta bizonyítani, hogy valóban a(z) <ph name="DOMAIN" /> domainbe tartozik; biztonsági tanúsítványában nincs meghatározva a „Subject Alternative Names” mező. Ezt okozhatja konfigurációs hiba, vagy az, hogy egy támadó eltérítette az Ön kapcsolatát.</translation>
<translation id="3949601375789751990">A böngészési előzmények itt jelennek meg</translation>
+<translation id="3950820424414687140">Bejelentkezés</translation>
<translation id="3963721102035795474">Olvasási mód</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Nincs}=1{ 1 webhelytől }other{# webhelytől }}</translation>
<translation id="397105322502079400">Számítás…</translation>
@@ -432,6 +475,7 @@
<translation id="4103249731201008433">Az eszköz sorozatszáma érvénytelen</translation>
<translation id="410351446219883937">Automatikus lejátszás</translation>
<translation id="4103763322291513355">Látogasson el a &lt;strong&gt;chrome://policy&lt;/strong&gt; oldalra a feketelistán lévő URL-ek és egyéb, a rendszergazda által előírt szabályok megtekintéséhez.</translation>
+<translation id="4110652170750985508">Befizetés áttekintése</translation>
<translation id="4116663294526079822">Mindig engedélyezze ezen az oldalon</translation>
<translation id="4117700440116928470">Az irányelv hatásköre nem támogatott.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 egyéb}other{# egyéb}}</translation>
@@ -458,7 +502,6 @@
<translation id="4269787794583293679">(Nincs felhasználónév)</translation>
<translation id="4275830172053184480">Indítsa újra az eszközt</translation>
<translation id="4280429058323657511">, lejár: <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Bejelentkezés</translation>
<translation id="4312866146174492540">Letiltás (alapértelmezett)</translation>
<translation id="4325863107915753736">Nem sikerült megtalálni a cikket</translation>
<translation id="4326324639298822553">Ellenőrizze a lejárati dátumot, majd próbálja újra</translation>
@@ -480,14 +523,12 @@
<translation id="4515275063822566619">A kártyák és a címek a Chrome-ból és az Ön Google-fiókjából (<ph name="ACCOUNT_EMAIL" />) származnak. A <ph name="BEGIN_LINK" />Beállításokban<ph name="END_LINK" /> kezelheti őket.</translation>
<translation id="4522570452068850558">Részletek</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">A(z) <ph name="SITE" /> egyik beágyazott oldaláról</translation>
<translation id="4558551763791394412">Próbálkozzon a bővítmények letiltásával.</translation>
<translation id="457875822857220463">Szállítás</translation>
<translation id="4582800630050655161">Elveszítheti hozzáférést Google-fiókjához, vagy visszaélhetnek személyes adataival. A Chromium azt javasolja, hogy azonnal módosítsa jelszavát.</translation>
<translation id="4587425331216688090">Eltávolítja a címet a Chrome-ból?</translation>
<translation id="4592951414987517459">A(z) <ph name="DOMAIN" /> domainnel való kapcsolata modern kriptográfiával van titkosítva.</translation>
<translation id="4594403342090139922">&amp;Törlés visszavonása</translation>
-<translation id="4611292653554630842">Bejelentkezés</translation>
<translation id="4619615317237390068">Más eszközök lapjai</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">A szerver nem tudta bizonyítani, hogy valóban a(z) <ph name="DOMAIN" /> domainbe tartozik; biztonsági tanúsítványa hibákat tartalmaz. Ennek oka lehet konfigurációs hiba, vagy hogy egy támadó eltérítette az Ön kapcsolódását.</translation>
@@ -497,11 +538,9 @@
<translation id="4708268264240856090">Kapcsolata megszakadt</translation>
<translation id="471880041731876836">Nincs jogosultsága a webhely felkereséséhez</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />A Windows Hálózati diagnosztika futtatása<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Fizetés</translation>
<translation id="4726672564094551039">Házirendek újratöltése</translation>
<translation id="4728558894243024398">Platform</translation>
<translation id="4736825316280949806">Indítsa újra a Chromiumot</translation>
-<translation id="4737498291095696011">Erről az oldalról</translation>
<translation id="4744603770635761495">Végrehajtható fájl útvonala</translation>
<translation id="4749685221585524849">Utolsó használat: <ph name="LAST_USED_MONTH" /></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>
@@ -520,16 +559,16 @@
<translation id="4850886885716139402">Nézet</translation>
<translation id="4854362297993841467">Ez a kézbesítési mód nem áll rendelkezésre. Próbálkozzon másik móddal.</translation>
<translation id="4858792381671956233">Megkérdezted a szüleidet, hogy meg szabad-e látogatnod ezt a webhelyet</translation>
-<translation id="4871132632506079383">A(z) <ph name="SITE" /> egyik beágyazott oldaláról</translation>
<translation id="4880827082731008257">Keresés az előzmények között</translation>
+<translation id="4881695831933465202">Megnyitás</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" /> és <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Azonosítás szükséges</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{és egy további weboldal}other{és # további weboldal}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Adja meg a(z) <ph name="CREDIT_CARD" /> kártya CVC-kódját. A megerősítést követően a böngésző megosztja majd az Ön Google Payments-fiókjából származó kártyaadatokat ezzel a webhellyel.</translation>
<translation id="4923417429809017348">Ezt az oldalt lefordították egy ismeretlen nyelvről <ph name="LANGUAGE_LANGUAGE" /> nyelvre</translation>
<translation id="4923459931733593730">Fizetés</translation>
<translation id="4926049483395192435">Meg kell határozni.</translation>
+<translation id="4926159001844873046">A(z) <ph name="SITE" /> közlendője</translation>
<translation id="4926340098269537727"><ph name="TOTAL_MATCHCOUNT" />/<ph name="ACTIVE_MATCH" /></translation>
<translation id="495170559598752135">Műveletek</translation>
<translation id="4958444002117714549">Lista részletes nézete</translation>
@@ -538,7 +577,6 @@
<translation id="5002932099480077015">Ha engedélyezi, a Chrome megőrzi a kártya másolatát ezen az eszközön a gyorsabb űrlapkitöltés érdekében.</translation>
<translation id="5018422839182700155">Nem lehet megnyitni az oldalt</translation>
<translation id="5019198164206649151">A háttértároló állapota nem megfelelő</translation>
-<translation id="5020990877659450221">Erről az oldalról</translation>
<translation id="5023310440958281426">Ellenőrizze rendszergazdai házirendjeit</translation>
<translation id="5029568752722684782">Példány törlése</translation>
<translation id="503069730517007720">A(z) „<ph name="SOFTWARE_NAME" />” szoftverhez főtanúsítványra van szükség, amely azonban nincs telepítve. A rendszergazda a(z) „<ph name="SOFTWARE_NAME" />” beállítási útmutatójában találhat segítséget a probléma megoldásához. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -564,12 +602,12 @@
<translation id="5172758083709347301">Számítógép</translation>
<translation id="5179510805599951267">Nem <ph name="ORIGINAL_LANGUAGE" /> nyelven van? Hiba bejelentése</translation>
<translation id="5190835502935405962">Könyvjelzősáv</translation>
+<translation id="5201306358585911203">Az oldal egyik beágyazott oldalának közlendője</translation>
<translation id="5205222826937269299">A név megadása kötelező</translation>
<translation id="5222812217790122047">Az e-mail-cím megadása kötelező</translation>
<translation id="522700295135997067">Előfordulhat, hogy a webhely éppen most lopta el a jelszavát</translation>
<translation id="5230733896359313003">Szállítási cím</translation>
<translation id="5251803541071282808">Felhő</translation>
-<translation id="5277279256032773186">A munkahelyén használja a Chrome-ot? A cégek kezelhetik a Chrome-beállításokat alkalmazottaik számára. További információ.</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Kövesse ezeket a lépéseket, ha szeretné átmenetileg letiltani a szoftvert, hogy hozzáférhessen az internethez. Rendszergazdai jogosultságokra lesz szüksége.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -631,7 +669,6 @@
<translation id="5610142619324316209">A kapcsolat ellenőrzése</translation>
<translation id="5610807607761827392">A kártyákat és a címeket a <ph name="BEGIN_LINK" />Beállítások<ph name="END_LINK" /> menüpontban kezelheti.</translation>
<translation id="5617949217645503996">A(z) <ph name="HOST_NAME" /> túl sokszor irányította át.</translation>
-<translation id="5622887735448669177">Szeretné elhagyni ezt a webhelyet?</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="5633066919399395251">Előfordulhat, hogy a(z) <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> webhely támadói 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 hitelkártyaadatait). <ph name="BEGIN_LEARN_MORE_LINK" />További információ<ph name="END_LEARN_MORE_LINK" />.</translation>
@@ -654,7 +691,6 @@
<translation id="5786044859038896871">Ki szeretné tölteni a kártyaadatait?</translation>
<translation id="5803412860119678065">Ki szeretné tölteni <ph name="CARD_DETAIL" /> kártyájának adataival?</translation>
<translation id="5810442152076338065">A(z) <ph name="DOMAIN" /> domainnel való kapcsolata elavult kriptográfiával van titkosítva.</translation>
-<translation id="5810928923025889964">Az oldal egyik beágyazott oldaláról</translation>
<translation id="5813119285467412249">&amp;Hozzáadás újra</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>
<translation id="5866257070973731571">Telefonszám hozzáadása</translation>
@@ -728,21 +764,19 @@
<translation id="6446608382365791566">További adatok hozzáadása</translation>
<translation id="6447842834002726250">Cookie-k</translation>
<translation id="6451458296329894277">Képernyő újraküldésének megerősítése</translation>
-<translation id="6456339708790392414">Fizetés</translation>
<translation id="647261751007945333">Eszközházirendek</translation>
<translation id="6477321094435799029">A Chrome szokatlan kódot észlelt az oldalon, ezért letiltotta az Ön személyes adatainak (például jelszavak, telefonszámok és hitelkártyaszámok) védelme érdekében.</translation>
<translation id="6489534406876378309">Feltöltési összeomlások indítása</translation>
<translation id="6507833130742554667">Elfogadott hitel- és bankkártyák.</translation>
<translation id="6508722015517270189">Indítsa újra a Chrome-ot</translation>
-<translation id="6521373090216409766">Szeretné újratölteni a webhelyet?</translation>
<translation id="6529602333819889595">&amp;Törlés újra</translation>
<translation id="6534179046333460208">Fizikai web – javaslatok</translation>
<translation id="6550675742724504774">Beállítások</translation>
-<translation id="6556239504065605927">Biztonságos kapcsolat</translation>
<translation id="6556915248009097796">Lejárati dátum: <ph name="EXPIRATION_DATE_ABBR" />, utolsó használat: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">A kezelő még nem hagyta jóvá</translation>
<translation id="6569060085658103619">Jelenleg bővítményoldalt tekint meg</translation>
<translation id="6596325263575161958">Titkosítási lehetőségek</translation>
+<translation id="6604181099783169992">Mozgás- és fényérzékelők</translation>
<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>
@@ -814,6 +848,7 @@
<translation id="7275334191706090484">Kezelt könyvjelzők</translation>
<translation id="7298195798382681320">Ajánlott</translation>
<translation id="7309308571273880165">Hibajelentés készült: <ph name="CRASH_TIME" /> (a felhasználó által kért feltöltés – még nincs feltöltve)</translation>
+<translation id="7320336641823683070">Segítség a kapcsolódáshoz</translation>
<translation id="7334320624316649418">&amp;Átrendezés újra</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="7353601530677266744">Parancssor</translation>
@@ -898,6 +933,7 @@
<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="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="7862185352068345852">Elhagyja a webhelyet?</translation>
<translation id="7878176543348854470">Elfogadott bank- és feltöltőkártyák.</translation>
<translation id="7878562273885520351">Előfordultat, hogy jelszava már nem biztonságos</translation>
<translation id="7887683347370398519">Ellenőrizze a CVC-t, majd próbálja újra</translation>
@@ -920,6 +956,7 @@
<translation id="8041940743680923270">Globális alapértelmezés használata (Megkérdezés)</translation>
<translation id="8042918947222776840">Átvételi mód kiválasztása</translation>
<translation id="8057711352706143257">A(z) „<ph name="SOFTWARE_NAME" />” nincs megfelelően beállítva. A(z) „<ph name="SOFTWARE_NAME" />” eltávolítása általában megoldja a problémát. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Újratölti a webhelyet?</translation>
<translation id="8088680233425245692">Nem sikerült megtekinteni a cikket.</translation>
<translation id="8091372947890762290">Az aktiválás függőben van a szerveren</translation>
<translation id="8094917007353911263">Az Ön által használt hálózat megkövetelheti a(z) <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> felkeresését.</translation>
@@ -935,6 +972,7 @@
<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>
<translation id="8205463626947051446">A webhely jellemzően tolakodó hirdetéseket jelenít meg</translation>
+<translation id="8211406090763984747">A kapcsolat biztonságos</translation>
<translation id="8218327578424803826">Hozzárendelt helyszín:</translation>
<translation id="8225771182978767009">A számítógépet beállító személy a webhely letiltása mellett döntött.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" /> és <ph name="TYPE_2" /></translation>
@@ -946,6 +984,7 @@
<translation id="825929999321470778">Az összes mentett jelszó megjelenítése</translation>
<translation id="8261506727792406068">Törlés</translation>
<translation id="8267698848189296333">Bejelentkezés mint <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Bejelentkezés</translation>
<translation id="8288807391153049143">Tanúsítvány megjelenítése</translation>
<translation id="8289355894181816810">Forduljon a hálózati rendszergazdához, ha nem tudja, hogy ez mit jelent.</translation>
<translation id="8293206222192510085">Könyvjelző hozzáadása</translation>
@@ -997,6 +1036,7 @@
<translation id="874846938927089722">Elfogadott hitel- és feltöltőkártyák</translation>
<translation id="8759274551635299824">A kártya lejárt</translation>
<translation id="8761567432415473239">A Google Biztonságos Böngészés nemrég <ph name="BEGIN_LINK" />ártalmas programokat talált<ph name="END_LINK" /> a következő webhelyen: <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">USB-eszköz</translation>
<translation id="8790007591277257123">&amp;Törlés újra</translation>
<translation id="8800988563907321413">A közeli javaslatok helye</translation>
<translation id="8820817407110198400">Könyvjelzők</translation>
diff --git a/chromium/components/strings/components_strings_id.xtb b/chromium/components/strings/components_strings_id.xtb
index 0e1700f03fe..89dca7f9628 100644
--- a/chromium/components/strings/components_strings_id.xtb
+++ b/chromium/components/strings/components_strings_id.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Cetak...</translation>
<translation id="1181037720776840403">Hapus</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Otomatis laporkan<ph name="END_WHITEPAPER_LINK" /> detail kemungkinan insiden keamanan ke Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Pembayaran Belum Selesai</translation>
<translation id="1201402288615127009">Berikutnya</translation>
<translation id="1201895884277373915">Lainnya dari situs ini</translation>
<translation id="1206967143813997005">Tanda tangan awal tidak valid</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Laporan kerusakan diambil pada pukul <ph name="CRASH_TIME" /> (belum diupload atau diabaikan)</translation>
<translation id="1270502636509132238">Metode Pengambilan</translation>
<translation id="1285320974508926690">Jangan pernah terjemahkan situs ini</translation>
+<translation id="1294154142200295408">Variasi baris perintah</translation>
<translation id="129553762522093515">Barusan ditutup</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Coba hapus cookie Anda<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Aktivitas Anda <ph name="BEGIN_EMPHASIS" />mungkin tetap dapat dilihat<ph name="END_EMPHASIS" /> oleh:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Kartu kredit dan debit yang diterima</translation>
<translation id="1519264250979466059">Tanggal Dibuat</translation>
<translation id="1527263332363067270">Menunggu sambungan internet...</translation>
+<translation id="1532118530259321453">Halaman ini menyatakan</translation>
<translation id="153384715582417236">Itu saja untuk sekarang</translation>
<translation id="154408704832528245">Pilih Alamat Pengiriman</translation>
<translation id="1549470594296187301">JavaScript harus diaktifkan untuk menggunakan fitur ini.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Memeriksa proxy dan firewall<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Kode pos</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 saran}other{# saran}}</translation>
-<translation id="2065985942032347596">Diperlukan Otentikasi</translation>
<translation id="2079545284768500474">Urungkan</translation>
<translation id="20817612488360358">Setelan proxy sistem disetel untuk digunakan namun konfigurasi proxy eksplisit juga ditentukan.</translation>
<translation id="2091887806945687916">Suara</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Batalkan pembayaran</translation>
<translation id="2147827593068025794">Sinkronisasi Latar Belakang</translation>
<translation id="2148613324460538318">Tambahkan Kartu</translation>
-<translation id="2149973817440762519">Edit Bookmark</translation>
<translation id="2154054054215849342">Sinkronisasi tidak tersedia untuk domain Anda</translation>
<translation id="2154484045852737596">Edit kartu</translation>
<translation id="2166049586286450108">Akses Penuh Admin</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Pilih Alamat Pengambilan</translation>
<translation id="2740531572673183784">Oke</translation>
<translation id="2742870351467570537">Hapus item yang dipilih</translation>
-<translation id="2744590937989388266">Dari Halaman Tersemat di Halaman Ini</translation>
<translation id="277133753123645258">Metode pengiriman</translation>
<translation id="277499241957683684">Catatan perangkat hilang</translation>
<translation id="2784949926578158345">Sambungan disetel ulang.</translation>
<translation id="2788784517760473862">Kartu kredit yang diterima</translation>
<translation id="2794233252405721443">Situs diblokir</translation>
-<translation id="2795286477369100655">Ingin Keluar dari Situs Ini?</translation>
<translation id="2799020568854403057">Situs yang akan dibuka berisi aplikasi berbahaya</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="2824775600643448204">Bilah penelusuran dan alamat</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Entri daftar "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Diblokir secara otomatis</translation>
<translation id="3024663005179499861">Jenis kebijakan salah</translation>
-<translation id="3032412215588512954">Ingin memuat ulang situs ini?</translation>
<translation id="3037605927509011580">Yah!</translation>
<translation id="3039538478787849737">Simpan kartu ke Google?</translation>
<translation id="3041612393474885105">Informasi Sertifikat</translation>
@@ -310,6 +306,7 @@
memastikan bahwa server proxy bekerja. Jika Anda tidak yakin harus
menggunakan server proxy:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> di <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Batalkan Pembayaran</translation>
<translation id="3207960819495026254">Diberi bookmark</translation>
<translation id="3209375525920864198">Harap masukkan nama sesi yang valid.</translation>
@@ -367,11 +364,60 @@
<translation id="3556433843310711081">Pengelola dapat membuka blokirnya untuk Anda</translation>
<translation id="3566021033012934673">Koneksi Anda tidak pribadi</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Halaman tersemat di <ph name="SITE" /> menyatakan</translation>
<translation id="358285529439630156">Kartu kredit dan prabayar diterima.</translation>
<translation id="3582930987043644930">Tambahkan nama</translation>
<translation id="3583757800736429874">&amp;Ulangi Pemindahan</translation>
<translation id="3586931643579894722">Sembunyikan detail</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Memperbaiki error koneksi&lt;/h1&gt;
+ &lt;p&gt;Jika Anda mendapatkan pesan error saat mencoba membuka situs, coba lakukan perbaikan ini.&lt;/p&gt;
+ &lt;h2&gt;Memperbaiki sebagian besar error koneksi&lt;/h2&gt;
+ &lt;p&gt;Jika Anda mencoba membuka situs dan situs tersebut tidak terbuka, terlebih dahulu coba perbaiki error dengan langkah-langkah pemecahan masalah ini:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Periksa apakah ada kesalahan ketik alamat web.&lt;/li&gt;
+ &lt;li&gt;Pastikan sambungan internet berfungsi dengan normal.&lt;/li&gt;
+ &lt;li&gt;Hubungi pemilik situs.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Mendapatkan bantuan terkait pesan error tertentu&lt;/h2&gt;
+ &lt;h3&gt;"Koneksi tidak bersifat pribadi" atau "NET::ERR_CERT_AUTHORITY_INVALID" atau "ERR_CERT_COMMON_NAME_INVALID" atau "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" atau "SSL certificate error"&lt;/h3&gt;
+ &lt;h4&gt;Langkah 1: Login ke portal&lt;/h4&gt;
+ &lt;p&gt;Jaringan Wi-Fi di tempat seperti kafe atau bandara mengharuskan Anda
+untuk login. Untuk melihat halaman login, buka halaman yang menggunakan&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Buka situs apa pun yang diawali dengan &lt;code&gt;http://&lt;/code&gt;, seperti &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Loginlah di halaman login yang terbuka untuk menggunakan internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Langkah 2: Buka halaman dalam Mode penyamaran (khusus komputer)&lt;/h4&gt;
+ &lt;p&gt;Buka halaman yang Anda akses di Jendela samaran.&lt;/p&gt;
+ &lt;p&gt;Jika halaman terbuka, ekstensi Chrome tidak berfungsi dengan baik. Untuk memperbaiki error tersebut, nonaktifkan ekstensi.&lt;/p&gt;
+ &lt;h4&gt;Langkah 3: Update sistem operasi Anda&lt;/h4&gt;
+ &lt;p&gt;Pastikan perangkat sudah versi terbaru.&lt;/p&gt;
+ &lt;h4&gt;Langkah 4: Nonaktifkan antivirus untuk sementara&lt;/h4&gt;
+ &lt;p&gt;Anda akan melihat error ini jika terdapat software antivirus yang memberikan "perlindungan HTTPS" atau "pemindaian HTTPS". Antivirus tersebut mencegah Chrome memberikan perlindungan.&lt;/p&gt;
+ &lt;p&gt;Untuk memperbaiki masalah, nonaktifkan software antivirus. Jika halaman
+berfungsi setelah antivirus dinonaktifkan, nonaktifkan antivirus ini
+jika Anda menggunakan situs aman.&lt;/p&gt;
+ &lt;p&gt;Ingatlah untuk kembali mengaktifkan program antivirus jika telah selesai.&lt;/p&gt;
+ &lt;h4&gt;Langkah 5: Dapatkan bantuan tambahan&lt;/h4&gt;
+ &lt;p&gt;Jika Anda tetap melihat error, hubungi pemilik situs.&lt;/p&gt;
+ &lt;h3&gt;"Sambungkan ke jaringan"&lt;/h3&gt;
+ &lt;p&gt;Anda akan melihat error ini jika menggunakan portal Wi-Fi tempat Anda harus login sebelum terhubung online.&lt;/p&gt;
+ &lt;p&gt;Untuk memperbaiki error, klik &lt;strong&gt;Sambungkan&lt;/strong&gt; pada halaman yang ingin dibuka.&lt;/p&gt;
+ &lt;h3&gt;"Jam terlalu lambat" atau "Jam terlalu cepat" atau "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Anda akan melihat error ini jika komputer atau perangkat seluler memiliki tanggal dan waktu yang tidak akurat.&lt;/p&gt;
+ &lt;p&gt;Untuk memperbaiki error, buka jam pada perangkat. Pastikan waktu dan tanggal sudah tepat.&lt;/p&gt;
+ &lt;h3&gt;"Software di komputer mencegah Chrome terhubung dengan aman ke web" (khusus komputer Windows)&lt;/h3&gt;
+ &lt;p&gt;Anda akan melihat error ini jika Anda memiliki software Superfish di komputer Windows.&lt;/p&gt;
+ &lt;p&gt;Ikuti langkah-langkah ini untuk menonaktifkan software tersebut sementara waktu agar Anda dapat mengakses web. Anda memerlukan hak istimewa administrator.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Klik &lt;strong&gt;Mulai&lt;/strong&gt;, lalu telusuri dan pilih &lt;strong&gt;"Lihat layanan lokal"&lt;/strong&gt;
+ &lt;li&gt;Pilih &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Pada &lt;strong&gt;Jenis startup&lt;/strong&gt;, pilih &lt;strong&gt;Nonaktif&lt;/strong&gt;
+ &lt;li&gt;Pada &lt;strong&gt;Status layanan&lt;/strong&gt;, klik &lt;strong&gt;Stop&lt;/strong&gt;
+ &lt;li&gt;Klik &lt;strong&gt;Terapkan&lt;/strong&gt;, lalu klik &lt;strong&gt;Oke&lt;/strong&gt;
+ &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="3615877443314183785">Masukkan tanggal masa berlaku yang valid</translation>
<translation id="36224234498066874">Hapus Data Browsing...</translation>
<translation id="362276910939193118">Tampilkan Histori Lengkap</translation>
@@ -404,7 +450,6 @@
<translation id="3778403066972421603">Ingin menyimpan kartu ini di Akun Google dan perangkat ini?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Masa berlaku <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Dari <ph name="SITE" /></translation>
<translation id="382518646247711829">Jika Anda menggunakan server proxy...</translation>
<translation id="3828924085048779000">Frasa sandi kosong tidak dibolehkan.</translation>
<translation id="385051799172605136">Mundur</translation>
@@ -418,6 +463,7 @@
<translation id="3945915738023014686">ID Laporan Error yang Diupload <ph name="CRASH_ID" /> (ID Error Lokal: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Server ini tidak dapat membuktikan bahwa ini adalah <ph name="DOMAIN" />; sertifikat keamanannya tidak menyebutkan Nama Alternatif Subjek. Hal ini dapat disebabkan oleh kesalahan konfigurasi atau penyerang memotong sambungan Anda.</translation>
<translation id="3949601375789751990">Histori browsing Anda muncul di sini</translation>
+<translation id="3950820424414687140">Masuk</translation>
<translation id="3963721102035795474">Mode Pembaca</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Tidak ada}=1{Dari 1 situs }other{Dari # situs }}</translation>
<translation id="397105322502079400">Menghitung...</translation>
@@ -434,6 +480,7 @@
<translation id="4103249731201008433">Nomor seri perangkat tidak valid</translation>
<translation id="410351446219883937">Putar otomatis</translation>
<translation id="4103763322291513355">Kunjungi &lt;strong&gt;chrome://policy&lt;/strong&gt; untuk melihat daftar URL yang masuk daftar hitam dan kebijakan lain yang diterapkan oleh administrator sistem Anda.</translation>
+<translation id="4110652170750985508">Tinjau pembayaran</translation>
<translation id="4116663294526079822">Selalu izinkan di situs ini</translation>
<translation id="4117700440116928470">Lingkup kebijakan tidak didukung.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 lainnya}other{# lainnya}}</translation>
@@ -460,7 +507,6 @@
<translation id="4269787794583293679">(Tidak ada nama pengguna)</translation>
<translation id="4275830172053184480">Mulai ulang perangkat Anda</translation>
<translation id="4280429058323657511">, kedaluwarsa <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Log In</translation>
<translation id="4312866146174492540">Blokir (default)</translation>
<translation id="4325863107915753736">Gagal menemukan artikel</translation>
<translation id="4326324639298822553">Periksa tanggal kedaluwarsa dan coba lagi</translation>
@@ -482,14 +528,12 @@
<translation id="4515275063822566619">Kartu dan alamat berasal dari Chrome dan Akun Google (<ph name="ACCOUNT_EMAIL" />). Anda dapat mengelolanya di <ph name="BEGIN_LINK" />Setelan<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Detail</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Dari Halaman Tersemat di <ph name="SITE" /></translation>
<translation id="4558551763791394412">Coba nonaktifkan ekstensi.</translation>
<translation id="457875822857220463">Pengiriman</translation>
<translation id="4582800630050655161">Anda dapat kehilangan akses ke Akun Google atau mengalami pencurian identitas. Chromium merekomendasikan untuk mengubah sandi saat ini.</translation>
<translation id="4587425331216688090">Hapus alamat dari Chrome?</translation>
<translation id="4592951414987517459">Sambungan Anda ke <ph name="DOMAIN" /> dienkripsi menggunakan cipher suite modern.</translation>
<translation id="4594403342090139922">&amp;Urungkan Penghapusan</translation>
-<translation id="4611292653554630842">Login</translation>
<translation id="4619615317237390068">Tab dari perangkat lain</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Server ini tidak dapat membuktikan bahwa ini adalah <ph name="DOMAIN" />; sertifikat keamanannya berisi kesalahan. Hal ini dapat disebabkan oleh kesalahan konfigurasi atau penyerang memotong sambungan Anda.</translation>
@@ -499,11 +543,9 @@
<translation id="4708268264240856090">Sambungan Anda terganggu</translation>
<translation id="471880041731876836">Anda tidak memiliki izin untuk membuka situs ini</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Jalankan Diagnostik Jaringan Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Pembayaran Anda</translation>
<translation id="4726672564094551039">Muat ulang kebijakan</translation>
<translation id="4728558894243024398">Platform</translation>
<translation id="4736825316280949806">Buka Ulang Chromium</translation>
-<translation id="4737498291095696011">Dari Halaman Ini</translation>
<translation id="4744603770635761495">Jalur Yang Dapat Dijalankan</translation>
<translation id="4749685221585524849">Terakhir digunakan pada <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Informasi Anda (misalnya, sandi atau nomor kartu kredit) bersifat pribadi saat dikirimkan ke situs ini.</translation>
@@ -522,16 +564,16 @@
<translation id="4850886885716139402">Lihat</translation>
<translation id="4854362297993841467">Metode pengiriman tidak tersedia. Coba metode lain.</translation>
<translation id="4858792381671956233">Kamu telah meminta izin kepada orang tua untuk mengunjungi situs ini</translation>
-<translation id="4871132632506079383">Dari halaman tersemat di <ph name="SITE" /></translation>
<translation id="4880827082731008257">Telusuri histori</translation>
+<translation id="4881695831933465202">Buka</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Perlu autentikasi</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{dan 1 halaman web lainnya}other{dan # halaman web lainnya}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Masukkan CVC untuk <ph name="CREDIT_CARD" />. Setelah mengonfirmasi, detail kartu dari akun Pembayaran Google Anda akan dibagikan dengan situs ini.</translation>
<translation id="4923417429809017348">Halaman ini telah diterjemahkan dari bahasa yang tidak diketahui ke bahasa <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Pembayaran</translation>
<translation id="4926049483395192435">Harus ditentukan.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> menyatakan</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Tindakan</translation>
<translation id="4958444002117714549">Luaskan daftar</translation>
@@ -540,7 +582,6 @@
<translation id="5002932099480077015">Jika diaktifkan, Chrome akan menyimpan salinan kartu Anda di perangkat ini untuk pengisian formulir yang lebih cepat.</translation>
<translation id="5018422839182700155">Tidak dapat membuka halaman ini</translation>
<translation id="5019198164206649151">Penyimpanan cadangan dalam kondisi buruk</translation>
-<translation id="5020990877659450221">Dari halaman ini</translation>
<translation id="5023310440958281426">Periksa kebijakan administrator Anda</translation>
<translation id="5029568752722684782">Hapus salinan</translation>
<translation id="503069730517007720">Sertifikat root wajib untuk "<ph name="SOFTWARE_NAME" />" tidak diinstal. Administrator IT Anda harus melihat petunjuk konfigurasi untuk "<ph name="SOFTWARE_NAME" />" agar dapat menyelesaikan masalah ini. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +607,12 @@
<translation id="5172758083709347301">Mesin</translation>
<translation id="5179510805599951267">Bukan <ph name="ORIGINAL_LANGUAGE" />? Laporkan kesalahan deteksi ini</translation>
<translation id="5190835502935405962">Bilah Bookmark</translation>
+<translation id="5201306358585911203">Halaman tersemat di halaman ini menyatakan</translation>
<translation id="5205222826937269299">Nama wajib diisi</translation>
<translation id="5222812217790122047">Email wajib diisi</translation>
<translation id="522700295135997067">Situs ini mungkin telah mencuri sandi Anda</translation>
<translation id="5230733896359313003">Alamat Pengiriman</translation>
<translation id="5251803541071282808">Awan</translation>
-<translation id="5277279256032773186">Menggunakan Chrome di kantor? Perusahaan dapat mengelola setelan Chrome untuk karyawan mereka. Pelajari lebih lanjut</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Ikuti langkah-langkah berikut untuk menonaktifkan software sementara waktu, sehingga Anda dapat online. Anda memerlukan hak istimewa administrator.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +674,6 @@
<translation id="5610142619324316209">Periksa sambungan</translation>
<translation id="5610807607761827392">Anda dapat mengelola kartu dan alamat di <ph name="BEGIN_LINK" />Setelan<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> terlalu sering mengalihkan Anda.</translation>
-<translation id="5622887735448669177">Ingin keluar dari situs ini?</translation>
<translation id="5629630648637658800">Gagal memuat setelan kebijakan</translation>
<translation id="5631439013527180824">Token pengelolaan perangkat tidak valid</translation>
<translation id="5633066919399395251">Saat ini, penyerang di <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mungkin berusaha menginstal program berbahaya di komputer Anda yang dapat 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>
@@ -656,7 +696,6 @@
<translation id="5786044859038896871">Ingin mengisi informasi kartu?</translation>
<translation id="5803412860119678065">Ingin mengisi <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Sambungan Anda ke <ph name="DOMAIN" /> dienkripsi menggunakan cipher suite yang sudah usang.</translation>
-<translation id="5810928923025889964">Dari halaman tersemat di halaman ini</translation>
<translation id="5813119285467412249">&amp;Ulangi Penambahan</translation>
<translation id="5838278095973806738">Jangan masukkan informasi sensitif apa pun di situs ini (misalnya, sandi atau kartu kredit), karena penyerang dapat mencurinya.</translation>
<translation id="5866257070973731571">Tambahkan Nomor Telepon</translation>
@@ -730,21 +769,19 @@
<translation id="6446608382365791566">Tambahkan informasi lainnya</translation>
<translation id="6447842834002726250">Cookie</translation>
<translation id="6451458296329894277">Konfirmasikan Pengiriman Ulang Formulir</translation>
-<translation id="6456339708790392414">Pembayaran Anda</translation>
<translation id="647261751007945333">Kebijakan perangkat</translation>
<translation id="6477321094435799029">Chrome mendeteksi kode yang tidak biasa pada halaman ini dan memblokirnya untuk melindungi informasi pribadi Anda (misalnya, sandi, nomor telepon, dan kartu kredit).</translation>
<translation id="6489534406876378309">Mulai mengupload kerusakan</translation>
<translation id="6507833130742554667">Kartu kredit dan debit diterima.</translation>
<translation id="6508722015517270189">Buka Ulang Chrome</translation>
-<translation id="6521373090216409766">Ingin Memuat Ulang Situs Ini?</translation>
<translation id="6529602333819889595">&amp;Ulangi Penghapusan</translation>
<translation id="6534179046333460208">Saran Web Fisik</translation>
<translation id="6550675742724504774">Opsi</translation>
-<translation id="6556239504065605927">Sambungan aman</translation>
<translation id="6556915248009097796">Habis masa berlaku: <ph name="EXPIRATION_DATE_ABBR" />, terakhir digunakan pada <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Pengelola Anda belum menyetujuinya</translation>
<translation id="6569060085658103619">Anda melihat halaman ekstensi</translation>
<translation id="6596325263575161958">Opsi enkripsi</translation>
+<translation id="6604181099783169992">Sensor Gerakan atau Cahaya</translation>
<translation id="6624427990725312378">Info Kontak</translation>
<translation id="6626291197371920147">Tambahkan kartu yang valid</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Penelusuran</translation>
@@ -816,6 +853,7 @@
<translation id="7275334191706090484">Bookmark yang Terkelola</translation>
<translation id="7298195798382681320">Direkomendasikan</translation>
<translation id="7309308571273880165">Laporan kerusakan diambil pada <ph name="CRASH_TIME" /> (upload yang diminta pengguna, belum diupload)</translation>
+<translation id="7320336641823683070">Bantuan Koneksi</translation>
<translation id="7334320624316649418">&amp;Ulangi pengaturan ulang</translation>
<translation id="733923710415886693">Sertifikat server tidak diungkapkan melalui Transparansi Sertifikat.</translation>
<translation id="7353601530677266744">Baris Perintah</translation>
@@ -900,6 +938,7 @@
<translation id="782886543891417279">Wi-Fi yang digunakan (<ph name="WIFI_NAME" />) mungkin mewajibkan Anda mengunjungi halaman masuknya.</translation>
<translation id="785549533363645510">Namun, Anda masih dapat terlihat. Masuk ke mode penyamaran 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="7862185352068345852">Keluar dari situs?</translation>
<translation id="7878176543348854470">Kartu debit dan prabayar diterima.</translation>
<translation id="7878562273885520351">Sandi Anda mungkin disusupi</translation>
<translation id="7887683347370398519">Periksa CVC dan coba lagi</translation>
@@ -922,6 +961,7 @@
<translation id="8041940743680923270">Gunakan default global (Tanyakan)</translation>
<translation id="8042918947222776840">Pilih Metode Pengambilan</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" tidak dikonfigurasi dengan benar. Biasanya masalah akan terselesaikan dengan meng-uninstal "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Muat ulang situs?</translation>
<translation id="8088680233425245692">Gagal melihat artikel.</translation>
<translation id="8091372947890762290">Aktivasi ditunda di server</translation>
<translation id="8094917007353911263">Jaringan yang Anda gunakan mungkin mewajibkan Anda mengunjungi <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +977,7 @@
<translation id="8201077131113104583">URL pembaruan tidak valid untuk ekstensi dengan ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Ringkasan pesanan</translation>
<translation id="8205463626947051446">Situs cenderung menampilkan iklan mengganggu</translation>
+<translation id="8211406090763984747">Koneksi aman</translation>
<translation id="8218327578424803826">Lokasi yang Ditetapkan:</translation>
<translation id="8225771182978767009">Orang yang menyiapkan komputer ini telah memilih untuk memblokir situs ini.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +989,7 @@
<translation id="825929999321470778">Tampilkan Semua Sandi Tersimpan</translation>
<translation id="8261506727792406068">Hapus</translation>
<translation id="8267698848189296333">Masuk sebagai <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Masuk</translation>
<translation id="8288807391153049143">Tampilkan sertifikat</translation>
<translation id="8289355894181816810">Hubungi administrator jaringan Anda jika Anda tidak yakin apa maksudnya.</translation>
<translation id="8293206222192510085">Tambahkan Bookmark</translation>
@@ -998,6 +1040,7 @@
<translation id="874846938927089722">Kartu Kredit dan Prabayar yang Diterima</translation>
<translation id="8759274551635299824">Kartu sudah tidak aktif</translation>
<translation id="8761567432415473239">Google Safe Browsing baru-baru ini <ph name="BEGIN_LINK" />menemukan program berbahaya<ph name="END_LINK" /> di <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Perangkat USB</translation>
<translation id="8790007591277257123">&amp;Ulangi penghapusan</translation>
<translation id="8800988563907321413">Saran terdekat muncul di sini</translation>
<translation id="8820817407110198400">Bookmark</translation>
diff --git a/chromium/components/strings/components_strings_it.xtb b/chromium/components/strings/components_strings_it.xtb
index 1e1396e6e23..aa9550c7a59 100644
--- a/chromium/components/strings/components_strings_it.xtb
+++ b/chromium/components/strings/components_strings_it.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Stampa...</translation>
<translation id="1181037720776840403">Rimuovi</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Segnala automaticamente<ph name="END_WHITEPAPER_LINK" /> a Google i dettagli dei possibili problemi di sicurezza. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Pagamento non completato</translation>
<translation id="1201402288615127009">Avanti</translation>
<translation id="1201895884277373915">Altri dal sito</translation>
<translation id="1206967143813997005">Firma iniziale non valida</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Rapporto sugli arresti anomali generato il giorno <ph name="CRASH_TIME" /> (non ancora caricato o ignorato)</translation>
<translation id="1270502636509132238">Metodo di ritiro</translation>
<translation id="1285320974508926690">Non tradurre mai questo sito</translation>
+<translation id="1294154142200295408">Variazioni nella riga di comando</translation>
<translation id="129553762522093515">Chiuse di recente</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Prova a cancellare i cookie<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">La tua attività <ph name="BEGIN_EMPHASIS" />potrebbe comunque essere visibile<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Carte di credito e di debito accettate</translation>
<translation id="1519264250979466059">Data build</translation>
<translation id="1527263332363067270">In attesa di connessione…</translation>
+<translation id="1532118530259321453">Questa pagina dice</translation>
<translation id="153384715582417236">Per il momento è tutto</translation>
<translation id="154408704832528245">Scegli l'indirizzo di consegna</translation>
<translation id="1549470594296187301">JavaScript deve essere attivato per utilizzare questa funzione.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Controllare il proxy e firewall<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">ZIP</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggerimento}other{# suggerimenti}}</translation>
-<translation id="2065985942032347596">Autenticazione richiesta</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="2091887806945687916">Audio</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Annulla pagamento</translation>
<translation id="2147827593068025794">Sincronizzazione in background</translation>
<translation id="2148613324460538318">Aggiungi carta</translation>
-<translation id="2149973817440762519">Modifica Preferito</translation>
<translation id="2154054054215849342">Il servizio di sincronizzazione non è disponibile per il tuo dominio</translation>
<translation id="2154484045852737596">Modifica la carta</translation>
<translation id="2166049586286450108">Accesso amministrativo completo</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Scegli l'indirizzo di ritiro</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Rimuovi gli elementi selezionati</translation>
-<translation id="2744590937989388266">Da una pagina incorporata in questa pagina</translation>
<translation id="277133753123645258">Metodo di spedizione</translation>
<translation id="277499241957683684">Record del dispositivo mancante</translation>
<translation id="2784949926578158345">La connessione è stata reimpostata.</translation>
<translation id="2788784517760473862">Carte di credito accettate</translation>
<translation id="2794233252405721443">Sito bloccato</translation>
-<translation id="2795286477369100655">Vuoi uscire da questo sito?</translation>
<translation id="2799020568854403057">Il sito che stai per visitare contiene app dannose</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="2824775600643448204">Barra degli indirizzi e di ricerca</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Voce "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Bloccata automaticamente</translation>
<translation id="3024663005179499861">Tipo di criterio errato</translation>
-<translation id="3032412215588512954">Vuoi ricaricare questo sito?</translation>
<translation id="3037605927509011580">Uffa!</translation>
<translation id="3039538478787849737">Vuoi salvare la carta in Google?</translation>
<translation id="3041612393474885105">Informazioni certificato</translation>
@@ -307,6 +303,7 @@
<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>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> su <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Annulla pagamento</translation>
<translation id="3207960819495026254">Aggiunto ai Preferiti</translation>
<translation id="3209375525920864198">Inserisci un nome sessione valido</translation>
@@ -364,11 +361,57 @@
<translation id="3556433843310711081">Il tuo gestore può sbloccarlo per te</translation>
<translation id="3566021033012934673">La connessione non è privata</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Una pagina incorporata in <ph name="SITE" /> dice</translation>
<translation id="358285529439630156">Le carte di credito e prepagate sono accettate.</translation>
<translation id="3582930987043644930">Aggiungi nome</translation>
<translation id="3583757800736429874">&amp;Ripeti spostamento</translation>
<translation id="3586931643579894722">Nascondi dettagli</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Correggere gli errori di connessione&lt;/h1&gt;
+ &lt;p&gt;Se ricevi un messaggio di errore mentre tenti di visitare un sito web, prova le soluzioni descritte di seguito.&lt;/p&gt;
+ &lt;h2&gt;Correggere la maggior parte degli errori di connessione&lt;/h2&gt;
+ &lt;p&gt;Se il sito web che intendi visitare non si apre, prova innanzitutto a correggere l'errore con questi passaggi di risoluzione dei problemi:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Verifica che non siano presenti errori ortografici nell'indirizzo web.&lt;/li&gt;
+ &lt;li&gt;Verifica che la connessione a Internet funzioni correttamente.&lt;/li&gt;
+ &lt;li&gt;Contatta il proprietario del sito web.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Ricevere assistenza per uno specifico messaggio di errore&lt;/h2&gt;
+ &lt;h3&gt;"La connessione non è privata", "NET::ERR_CERT_AUTHORITY_INVALID", "ERR_CERT_COMMON_NAME_INVALID", "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" oppure "Errore certificato SSL"&lt;/h3&gt;
+ &lt;h4&gt;Passaggio 1: accedi al portale&lt;/h4&gt;
+ &lt;p&gt;Per le reti Wi-Fi di luoghi come gli aeroporti o le caffetterie, è necessario effettuare l'accesso. Per visualizzare la pagina di accesso, visita una pagina che inizia con &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Visita un qualunque sito web che inizi con &lt;code&gt;http://&lt;/code&gt;, ad esempio &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Nella pagina di accesso che si apre, accedi per utilizzare Internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Passaggio 2: apri la pagina in modalità di navigazione in incognito (solo da computer)&lt;/h4&gt;
+ &lt;p&gt;Apri la pagina che stavi visitando in una finestra di navigazione in incognito.&lt;/p&gt;
+ &lt;p&gt;Se riesci ad aprire la pagina, un'estensione di Chrome non funziona correttamente. Per correggere l'errore, disattiva l'estensione.&lt;/p&gt;
+ &lt;h4&gt;Passaggio 3: aggiorna il sistema operativo&lt;/h4&gt;
+ &lt;p&gt;Assicurati che il dispositivo sia aggiornato.&lt;/p&gt;
+ &lt;h4&gt;Passaggio 4: disattiva temporaneamente il software antivirus&lt;/h4&gt;
+ &lt;p&gt;Potresti vedere questo errore se hai un software antivirus che fornisce "protezione HTTPS" o "scansione HTTPS" e impedisce a Chrome di offrire sicurezza.&lt;/p&gt;
+ &lt;p&gt;Per risolvere il problema, disattiva il software antivirus. Se la pagina funziona dopo questo passaggio, disattiva l'antivirus quando visiti siti protetti.&lt;/p&gt;
+ &lt;p&gt;Terminata l'operazione, ricordati di riattivare il programma antivirus.&lt;/p&gt;
+ &lt;h4&gt;Passaggio 5: richiedi ulteriore assistenza&lt;/h4&gt;
+ &lt;p&gt;Se l'errore continua a essere mostrato, contatta il proprietario del sito web.&lt;/p&gt;
+ &lt;h3&gt;"Collegati alla rete"&lt;/h3&gt;
+ &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;
+ &lt;h3&gt;"L'orologio è indietro", "L'orologio è avanti" oppure "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Vedrai questo errore se la data e l'ora del dispositivo mobile o del computer non sono esatte.&lt;/p&gt;
+ &lt;p&gt;Per risolvere il problema, apri l'orologio del dispositivo e assicurati che la data e l'ora siano corrette.&lt;/p&gt;
+ &lt;h3&gt;"Il software installato sul computer sta impedendo a Chrome di connettersi in sicurezza a Internet" (solo su computer Windows)&lt;/h3&gt;
+ &lt;p&gt;Potresti vedere questo errore se sul tuo computer Windows è installato il software Superfish.&lt;/p&gt;
+ &lt;p&gt;Svolgi i seguenti passaggi per disattivare temporaneamente il software e accedere così al Web. Devi disporre di privilegi di amministratore.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Fai clic su &lt;strong&gt;Start&lt;/strong&gt;, quindi cerca e seleziona &lt;strong&gt;"Visualizza servizi locali"&lt;/strong&gt;
+ &lt;li&gt;Seleziona &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Nella sezione &lt;strong&gt;Tipo di avvio&lt;/strong&gt;, seleziona &lt;strong&gt;Disabilitato&lt;/strong&gt;
+ &lt;li&gt;Nella sezione &lt;strong&gt;Stato del servizio&lt;/strong&gt;, fai clic su &lt;strong&gt;Interrompi&lt;/strong&gt;
+ &lt;li&gt;Fai clic su &lt;strong&gt;Applica&lt;/strong&gt;, quindi su &lt;strong&gt;OK&lt;/strong&gt;
+ &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="3615877443314183785">Inserisci una data di scadenza valida</translation>
<translation id="36224234498066874">Cancella dati di navigazione...</translation>
<translation id="362276910939193118">Mostra cronologia completa</translation>
@@ -401,7 +444,6 @@
<translation id="3778403066972421603">Vuoi salvare questa carta nel tuo account Google e su questo dispositivo?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Data di scadenza: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Da <ph name="SITE" /></translation>
<translation id="382518646247711829">Se utilizzi un server proxy...</translation>
<translation id="3828924085048779000">Non è consentita una passphrase vuota.</translation>
<translation id="385051799172605136">Indietro</translation>
@@ -415,6 +457,7 @@
<translation id="3945915738023014686">ID rapporto sugli arresti anomali caricato <ph name="CRASH_ID" /> (ID arresto anomalo locale: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Questo server non è riuscito a dimostrare che si tratta di <ph name="DOMAIN" />; il relativo certificato di sicurezza non contiene nomi alternativi del soggetto. Il problema potrebbe essere dovuto a un'errata configurazione o a un malintenzionato che intercetta la connessione.</translation>
<translation id="3949601375789751990">La cronologia di navigazione viene mostrata qui</translation>
+<translation id="3950820424414687140">Accedi</translation>
<translation id="3963721102035795474">Modalità Reader</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Nessuno}=1{Di 1 sito }other{Di # siti }}</translation>
<translation id="397105322502079400">Calcolo in corso...</translation>
@@ -431,6 +474,7 @@
<translation id="4103249731201008433">Il numero di serie del dispositivo non è valido</translation>
<translation id="410351446219883937">Riproduzione automatica</translation>
<translation id="4103763322291513355">Visita &lt;strong&gt;chrome://policy&lt;/strong&gt; per visualizzare l'elenco di URL inseriti nella blacklist e altre norme applicate dall'amministratore di sistema.</translation>
+<translation id="4110652170750985508">Verifica il pagamento</translation>
<translation id="4116663294526079822">Consenti sempre su questo sito</translation>
<translation id="4117700440116928470">L'ambito della norma non è supportato.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 altro}other{# altri}}</translation>
@@ -457,7 +501,6 @@
<translation id="4269787794583293679">(Nessun nome utente)</translation>
<translation id="4275830172053184480">Riavvia il dispositivo</translation>
<translation id="4280429058323657511">, scad.: <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Accedi</translation>
<translation id="4312866146174492540">Blocca (predefinita)</translation>
<translation id="4325863107915753736">Impossibile trovare l'articolo</translation>
<translation id="4326324639298822553">Controlla la data di scadenza e riprova</translation>
@@ -479,14 +522,12 @@
<translation id="4515275063822566619">Carte di credito e indirizzi provengono da Chrome e dall'account Google (<ph name="ACCOUNT_EMAIL" />). Puoi gestirli in <ph name="BEGIN_LINK" />Impostazioni<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Dettagli</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Da una pagina incorporata all'indirizzo <ph name="SITE" /></translation>
<translation id="4558551763791394412">Prova a disattivare le estensioni.</translation>
<translation id="457875822857220463">Consegna</translation>
<translation id="4582800630050655161">Potresti non riuscire più ad accedere al tuo account Google o subire un furto d'identità. Chromium ti consiglia di cambiare subito la password.</translation>
<translation id="4587425331216688090">Rimuovere l'indirizzo da Chrome?</translation>
<translation id="4592951414987517459">La connessione a <ph name="DOMAIN" /> è criptata tramite un pacchetto di crittografia moderno.</translation>
<translation id="4594403342090139922">&amp;Annulla eliminazione</translation>
-<translation id="4611292653554630842">Accedi</translation>
<translation id="4619615317237390068">Schede di altri dispositivi</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Questo server non è riuscito a dimostrare che si tratta di <ph name="DOMAIN" />; il relativo certificato di sicurezza contiene errori. Il problema potrebbe essere dovuto a un'errata configurazione o a un malintenzionato che intercetta la connessione.</translation>
@@ -496,11 +537,9 @@
<translation id="4708268264240856090">La connessione è stata interrotta</translation>
<translation id="471880041731876836">Non sei autorizzato a visitare questo sito</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Eseguire lo strumento Diagnostica di rete Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Il tuo pagamento</translation>
<translation id="4726672564094551039">Ricarica criteri</translation>
<translation id="4728558894243024398">Piattaforma</translation>
<translation id="4736825316280949806">Riavvia Chromium</translation>
-<translation id="4737498291095696011">Da questa pagina</translation>
<translation id="4744603770635761495">Percorso eseguibile</translation>
<translation id="4749685221585524849">Ultimo utilizzo: <ph name="LAST_USED_MONTH" /></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>
@@ -519,16 +558,16 @@
<translation id="4850886885716139402">Visualizza</translation>
<translation id="4854362297993841467">Questo metodo di consegna non è disponibile. Prova un metodo diverso.</translation>
<translation id="4858792381671956233">Hai chiesto ai tuoi genitori se puoi visitare questo sito</translation>
-<translation id="4871132632506079383">Da una pagina incorporata all'indirizzo <ph name="SITE" /></translation>
<translation id="4880827082731008257">Cerca nella cronologia</translation>
+<translation id="4881695831933465202">Apri</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Autenticazione richiesta</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{e un'altra pagina web}other{e altre # pagine web}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Inserisci il codice CVC della carta <ph name="CREDIT_CARD" />. Dopo essere stati confermati, i dati della carta del tuo account Google Payments saranno condivisi con questo sito.</translation>
<translation id="4923417429809017348">Questa pagina è stata tradotta da una lingua sconosciuta in <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Pagamento</translation>
<translation id="4926049483395192435">Deve essere specificato.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> dice</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Azioni</translation>
<translation id="4958444002117714549">Espandi elenco</translation>
@@ -537,7 +576,6 @@
<translation id="5002932099480077015">Se questa opzione viene attivata, Chrome memorizza una copia della carta sul dispositivo per velocizzare la compilazione dei moduli.</translation>
<translation id="5018422839182700155">Impossibile aprire questa pagina</translation>
<translation id="5019198164206649151">Archivio di backup in stato non valido</translation>
-<translation id="5020990877659450221">Da questa pagina</translation>
<translation id="5023310440958281426">Consulta le norme dell'amministratore</translation>
<translation id="5029568752722684782">Cancella copia</translation>
<translation id="503069730517007720">Per "<ph name="SOFTWARE_NAME" />" è richiesto un certificato radice che non è installato. L'amministratore IT deve consultare le istruzioni di configurazione relative a "<ph name="SOFTWARE_NAME" />" per risolvere il problema. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -563,12 +601,12 @@
<translation id="5172758083709347301">Computer</translation>
<translation id="5179510805599951267">Non in <ph name="ORIGINAL_LANGUAGE" />? Segnala questo errore</translation>
<translation id="5190835502935405962">Barra dei Preferiti</translation>
+<translation id="5201306358585911203">Una pagina incorporata in questa pagina dice</translation>
<translation id="5205222826937269299">Nome obbligatorio</translation>
<translation id="5222812217790122047">Email obbligatoria</translation>
<translation id="522700295135997067">Questo sito potrebbe avere appena rubato la tua password</translation>
<translation id="5230733896359313003">Indirizzo di spedizione</translation>
<translation id="5251803541071282808">Cloud</translation>
-<translation id="5277279256032773186">Utilizzi Chrome al lavoro? Le aziende possono gestire le impostazioni di Chrome per conto dei propri dipendenti. Ulteriori informazioni</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Svolgi i seguenti passaggi per disattivare temporaneamente il software e accedere così al Web. Devi disporre di privilegi di amministratore.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -630,7 +668,6 @@
<translation id="5610142619324316209">Verificare la connessione</translation>
<translation id="5610807607761827392">Puoi gestire carte e indirizzi nelle <ph name="BEGIN_LINK" />Impostazioni<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> ti ha reindirizzato troppe volte.</translation>
-<translation id="5622887735448669177">Vuoi uscire da questo sito?</translation>
<translation id="5629630648637658800">Caricamento delle impostazioni criterio non riuscito</translation>
<translation id="5631439013527180824">Token di gestione del dispositivo non valido</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>
@@ -653,7 +690,6 @@
<translation id="5786044859038896871">Vuoi inserire automaticamente i dati della carta?</translation>
<translation id="5803412860119678065">Vuoi inserire automaticamente <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">La connessione a <ph name="DOMAIN" /> è criptata tramite un pacchetto di crittografia obsoleto.</translation>
-<translation id="5810928923025889964">Da una pagina incorporata in questa pagina</translation>
<translation id="5813119285467412249">&amp;Ripeti aggiunta</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>
<translation id="5866257070973731571">Aggiungi numero di telefono</translation>
@@ -726,21 +762,19 @@
<translation id="6446608382365791566">Aggiungi altre informazioni</translation>
<translation id="6447842834002726250">Cookie</translation>
<translation id="6451458296329894277">Conferma reinvio modulo</translation>
-<translation id="6456339708790392414">Il tuo pagamento</translation>
<translation id="647261751007945333">Norme dispositivo</translation>
<translation id="6477321094435799029">Chrome ha rilevato un codice insolito su questa pagina e l'ha bloccata per proteggere le tue informazioni personali (ad esempio password, numeri di telefono e carte di credito).</translation>
<translation id="6489534406876378309">Avvia caricamento arresti anomali</translation>
<translation id="6507833130742554667">Le carte di credito e di debito sono accettate.</translation>
<translation id="6508722015517270189">Riavvia Chrome</translation>
-<translation id="6521373090216409766">Vuoi ricaricare questo sito?</translation>
<translation id="6529602333819889595">&amp;Ripeti eliminazione</translation>
<translation id="6534179046333460208">Suggerimenti relativi al Physical Web</translation>
<translation id="6550675742724504774">Opzioni</translation>
-<translation id="6556239504065605927">Connessione protetta</translation>
<translation id="6556915248009097796">Scadenza: <ph name="EXPIRATION_DATE_ABBR" />, ultimo utilizzo: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Il tuo gestore non ha ancora approvato la richiesta</translation>
<translation id="6569060085658103619">È visualizzata la pagina di un'estensione</translation>
<translation id="6596325263575161958">Opzioni di crittografia</translation>
+<translation id="6604181099783169992">Sensori di movimento o della luce</translation>
<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>
@@ -812,6 +846,7 @@
<translation id="7275334191706090484">Preferiti gestiti</translation>
<translation id="7298195798382681320">Consigliate</translation>
<translation id="7309308571273880165">Rapporto sugli arresti anomali generato <ph name="CRASH_TIME" /> (caricamento richiesto dall'utente, ma non ancora eseguito)</translation>
+<translation id="7320336641823683070">Guida alla connessione</translation>
<translation id="7334320624316649418">&amp;Ripeti ridisposizione</translation>
<translation id="733923710415886693">Il certificato del server non è stato reso pubblico tramite Certificate Transparency.</translation>
<translation id="7353601530677266744">Riga di comando</translation>
@@ -896,6 +931,7 @@
<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="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="7862185352068345852">Vuoi uscire dal sito?</translation>
<translation id="7878176543348854470">Le carte di debito e prepagate sono accettate.</translation>
<translation id="7878562273885520351">La tua password potrebbe essere stata compromessa</translation>
<translation id="7887683347370398519">Controlla il tuo codice CVC e riprova</translation>
@@ -918,6 +954,7 @@
<translation id="8041940743680923270">Usa predefinita globale (Chiedi)</translation>
<translation id="8042918947222776840">Scegli il metodo di ritiro</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" non è configurato correttamente. La disinstallazione di "<ph name="SOFTWARE_NAME" />" solitamente risolve il problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Vuoi ricaricare il sito?</translation>
<translation id="8088680233425245692">Impossibile visualizzare l'articolo.</translation>
<translation id="8091372947890762290">Attivazione in attesa sul server</translation>
<translation id="8094917007353911263">La rete in uso potrebbe richiedere la visita della pagina <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -933,6 +970,7 @@
<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>
<translation id="8205463626947051446">Il sito tende a mostrare annunci invasivi</translation>
+<translation id="8211406090763984747">La connessione è protetta</translation>
<translation id="8218327578424803826">Posizione assegnata:</translation>
<translation id="8225771182978767009">La persona che ha configurato il computer ha deciso di bloccare questo sito.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -944,6 +982,7 @@
<translation id="825929999321470778">Mostra tutte le password salvate</translation>
<translation id="8261506727792406068">Elimina</translation>
<translation id="8267698848189296333">Accesso come <ph name="USERNAME" /> in corso</translation>
+<translation id="8286036467436129157">Accedi</translation>
<translation id="8288807391153049143">Mostra certificato</translation>
<translation id="8289355894181816810">Contatta l'amministratore di rete se non sei sicuro del significato.</translation>
<translation id="8293206222192510085">Aggiunta preferito</translation>
@@ -994,6 +1033,7 @@
<translation id="874846938927089722">Carte di credito e prepagate accettate</translation>
<translation id="8759274551635299824">La carta è scaduta</translation>
<translation id="8761567432415473239">La funzione Navigazione sicura di Google <ph name="BEGIN_LINK" />ha trovato di recente programmi dannosi<ph name="END_LINK" /> su <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Dispositivo USB</translation>
<translation id="8790007591277257123">&amp;Ripeti eliminazione</translation>
<translation id="8800988563907321413">I suggerimenti Qui vicino vengono visualizzati qui</translation>
<translation id="8820817407110198400">Preferiti</translation>
diff --git a/chromium/components/strings/components_strings_iw.xtb b/chromium/components/strings/components_strings_iw.xtb
index 84fa5a39387..b5155b22351 100644
--- a/chromium/components/strings/components_strings_iw.xtb
+++ b/chromium/components/strings/components_strings_iw.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">הדפס...</translation>
<translation id="1181037720776840403">הסר</translation>
<translation id="1184214524891303587">‏<ph name="BEGIN_WHITEPAPER_LINK" />שלח באופן אוטומטי<ph name="END_WHITEPAPER_LINK" /> אל Google דיווח על בעיות אבטחה אפשריות. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">התשלום לא הושלם</translation>
<translation id="1201402288615127009">הבא</translation>
<translation id="1201895884277373915">עוד מאתר זה</translation>
<translation id="1206967143813997005">חתימה ראשונית לא חוקית</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">דוח הקריסה תועד ב-<ph name="CRASH_TIME" /> (עדיין לא העלית אותו או בחרת להתעלם ממנו)</translation>
<translation id="1270502636509132238">שיטת איסוף</translation>
<translation id="1285320974508926690">לעולם אל תתרגם אתר זה</translation>
+<translation id="1294154142200295408">וריאציות של שורת פקודה</translation>
<translation id="129553762522093515">נסגרו לאחרונה</translation>
<translation id="129863573139666797">‏<ph name="BEGIN_LINK" />נסה לנקות את קובצי ה-Cookie<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">הפעילות שלך <ph name="BEGIN_EMPHASIS" />עדיין עשויה להיות מוצגת<ph name="END_EMPHASIS" /> בפני:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">כרטיסי אשראי וחיוב שהסוחר מקבל</translation>
<translation id="1519264250979466059">‏תאריך ה-Build</translation>
<translation id="1527263332363067270">ממתין לחיבור...</translation>
+<translation id="1532118530259321453">הדף הזה אומר</translation>
<translation id="153384715582417236">זה הכול בינתיים</translation>
<translation id="154408704832528245">בחירת כתובת למסירה</translation>
<translation id="1549470594296187301">‏JavaScript צריך להיות מופעל כדי להשתמש בתכונה זו.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086">‏<ph name="BEGIN_LINK" />לבדוק את שרת ה-Proxy ואת חומת האש<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">מספר / מיקוד</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{הצעה אחת}two{שתי הצעות}many{# הצעות}other{# הצעות}}</translation>
-<translation id="2065985942032347596">נדרש אימות</translation>
<translation id="2079545284768500474">בטל פעולה</translation>
<translation id="20817612488360358">‏נקבע שימוש בהגדרות שרת Proxy של מערכת אך בנוסף מצוינת גם תצורה מפורשת של שרת Proxy.</translation>
<translation id="2091887806945687916">צליל</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">ביטול תשלום</translation>
<translation id="2147827593068025794">סינכרון ברקע</translation>
<translation id="2148613324460538318">הוספת כרטיס</translation>
-<translation id="2149973817440762519">ערוך סימניות</translation>
<translation id="2154054054215849342">סנכרון אינו זמין בדומיין שלך</translation>
<translation id="2154484045852737596">עריכת כרטיס</translation>
<translation id="2166049586286450108">גישה מלאה של מנהל המערכת</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">בחירת כתובת לאיסוף</translation>
<translation id="2740531572673183784">אישור</translation>
<translation id="2742870351467570537">הסר פריטים שנבחרו</translation>
-<translation id="2744590937989388266">מדף מוטמע בדף הזה</translation>
<translation id="277133753123645258">שיטת משלוח</translation>
<translation id="277499241957683684">חסרה רשומת מכשיר</translation>
<translation id="2784949926578158345">החיבור עבר איפוס.</translation>
<translation id="2788784517760473862">כרטיסי אשראי שהסוחר מקבל</translation>
<translation id="2794233252405721443">אתר חסום</translation>
-<translation id="2795286477369100655">רוצה לעזוב את האתר?</translation>
<translation id="2799020568854403057">האתר שאתה עומד לעבור אליו מכיל יישומים מזיקים</translation>
<translation id="2803306138276472711">‏לאחרונה, 'גלישה בטוחה של Google‏' <ph name="BEGIN_LINK" />זיהתה תוכנה זדונית<ph name="END_LINK" /> באתר <ph name="SITE" />. אתרים שבדרך כלל נחשבים לבטוחים נדבקים לעתים בתוכנה זדונית.</translation>
<translation id="2824775600643448204">סרגל חיפוש וכתובות</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">רשומה ברשימה "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">נחסמה אוטומטית</translation>
<translation id="3024663005179499861">סוג המדיניות שגוי</translation>
-<translation id="3032412215588512954">האם ברצונך לטעון מחדש את האתר?</translation>
<translation id="3037605927509011580">אוי, לא!</translation>
<translation id="3039538478787849737">‏לשמור את הכרטיס ב-Google?</translation>
<translation id="3041612393474885105">פרטי אישור</translation>
@@ -310,6 +306,7 @@
כדי לוודא ששרת ה-proxy פועל. אם אינך סבור שעליך
להשתמש בשרת proxy:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> בשרת <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">בטל תשלום</translation>
<translation id="3207960819495026254">מסומן בסימניה</translation>
<translation id="3209375525920864198">יש להזין שם הפעלה חוקי.</translation>
@@ -367,11 +364,58 @@
<translation id="3556433843310711081">המנהל שלך יכול לבטל בשבילך את החסימה</translation>
<translation id="3566021033012934673">החיבור שלך אינו פרטי</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">דף מוטמע באתר <ph name="SITE" /> אומר</translation>
<translation id="358285529439630156">אפשר לשלם באמצעות כרטיסי אשראי וכרטיסים משולמים מראש.</translation>
<translation id="3582930987043644930">הוסף שם</translation>
<translation id="3583757800736429874">&amp;ביצוע מחדש של העברה</translation>
<translation id="3586931643579894722">הסתר פרטים</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">‏&lt;h1&gt;פתרון שגיאות חיבור&lt;/h1&gt;
+ &lt;p&gt;אם מופיעה הודעת שגיאה כשמנסים להיכנס לאתר כלשהו, אפשר לנסות את הפתרונות הבאים.&lt;/p&gt;
+ &lt;h2&gt;איך לפתור את רוב שגיאות החיבור&lt;/h2&gt;
+ &lt;p&gt;אם מנסים להיכנס לאתר והוא לא נפתח, קודם צריך לנסות את השלבים הבאים כדי לפתור את הבעיה:
+&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;בודקים אם יש שגיאות הקלדה בכתובת האתר.&lt;/li&gt;
+ &lt;li&gt;מוודאים שהחיבור לאינטרנט תקין.&lt;/li&gt;
+ &lt;li&gt;פונים אל הבעלים של האתר.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;עזרה לגבי הודעות שגיאה ספציפיות&lt;/h2&gt;
+ &lt;h3&gt;"החיבור שלך אינו פרטי" או "NET::ERR_CERT_AUTHORITY_INVALID" או "ERR_CERT_COMMON_NAME_INVALID" או "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" או "שגיאת אישור SSL"&lt;/h3&gt;
+ &lt;h4&gt;שלב ראשון: כניסה לפורטל&lt;/h4&gt;
+ &lt;p&gt;כדי להשתמש ברשתות Wi-Fi במקומות כמו בתי קפה ושדות תעופה צריך להיכנס לפורטל ייעודי. כדי לראות את דף הכניסה צריך להיכנס לדף שהכתובת שלו מתחילה ב-&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;עוברים לאתר כלשהו שהכתובת שלו מתחילה ב-&lt;code&gt;http://&lt;/code&gt;, כמו &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;בדף הכניסה שנפתח, מזינים את פרטי הכניסה כדי להשתמש באינטרנט.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;שלב שני: פתיחת הדף במצב גלישה בסתר (מחשבים בלבד)&lt;/h4&gt;
+ &lt;p&gt;פותחים את הדף שאליו רוצים להיכנס בחלון גלישה בסתר.&lt;/p&gt;
+ &lt;p&gt;אם הדף הנפתח, יש בעיה בתוסף של Chrome. כדי לפתור את השגיאה צריך להשבית את התוסף.&lt;/p&gt;
+ &lt;h4&gt;שלב שלישי: עדכון מערכת ההפעלה&lt;/h4&gt;
+ &lt;p&gt;מוודאים שמערכת ההפעלה במכשיר מעודכנת.&lt;/p&gt;
+ &lt;h4&gt;שלב רביעי: השבתה זמנית של האנטי-וירוס&lt;/h4&gt;
+ &lt;p&gt;השגיאה זו תוצג אם במחשב מותקנת תוכנת אנטי-וירוס שמספקת "הגנת HTTPS" או "סריקת HTTPS". תוכנת האנטי-וירוס מונעת מ-Chrome לספק אבטחה.&lt;/p&gt;
+ &lt;p&gt;כדי לפתור את הבעיה, יש לכבות את תוכנת האנטי-וירוס. אם הדף פועל לאחר כיבוי התוכנה, יש לכבות אותה בזמן השימוש באתרים מאובטחים.&lt;/p&gt;
+ &lt;p&gt;חשוב להפעיל שוב את האנטי-וירוס בסיום.&lt;/p&gt;
+ &lt;h4&gt;שלב חמישי: סיוע נוסף&lt;/h4&gt;
+ &lt;p&gt;אם השגיאה עדיין מופיעה, יש לפנות לבעלים של האתר.&lt;/p&gt;
+ &lt;h3&gt;"התחברות לרשת"&lt;/h3&gt;
+ &lt;p&gt;השגיאה הזו תוצג אם משתמשים בפורטל Wi-Fi שבו צריך להיכנס לחשבון לפני התחברות לרשת.&lt;/p&gt;
+ &lt;p&gt;כדי לפתור את השגיאה, צריך ללחוץ על &lt;strong&gt;התחברות&lt;/strong&gt; בדף שמנסים לפתוח.&lt;/p&gt;
+ &lt;h3&gt;"השעון מאחר" או "השעון ממהר" או "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;השגיאה הזו תוצג אם התאריך והשעה במחשב או בנייד אינם מדויקים.&lt;/p&gt;
+ &lt;p&gt;כדי לפתור את השגיאה צריך לפתוח את השעון של המכשיר ולוודא שהתאריך והשעה מדויקים.&lt;/p&gt;
+ &lt;h3&gt;"יש תוכנה במחשב שלך שמונעת מ-Chrome להתחבר באופן מאובטח אל האינטרנט" (רק מחשבי Windows)&lt;/h3&gt;
+ &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;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;
+ &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="3615877443314183785">עליך להזין תאריך תפוגה חוקי</translation>
<translation id="36224234498066874">נקה נתוני גלישה...</translation>
<translation id="362276910939193118">הצג את כל ההיסטוריה</translation>
@@ -404,7 +448,6 @@
<translation id="3778403066972421603">‏האם ברצונך לשמור את הכרטיס בחשבון Google שלך ובמכשיר הזה?</translation>
<translation id="3783418713923659662">מאסטרקארד</translation>
<translation id="3787705759683870569">תאריך תפוגה: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">מהאתר <ph name="SITE" /></translation>
<translation id="382518646247711829">‏אם אתה משתמש בשרת Proxy...</translation>
<translation id="3828924085048779000">אין אפשרות להשתמש במשפט-סיסמה ריק.</translation>
<translation id="385051799172605136">חזור</translation>
@@ -418,6 +461,7 @@
<translation id="3945915738023014686">מזהה דוח הקריסה שהועלה <ph name="CRASH_ID" /> (מזהה קריסה מקומי: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">‏השרת הזה לא הצליח להוכיח שהוא <ph name="DOMAIN" />; אישור האבטחה שלו לא מציין ערכי Subject Alternative Name. ייתכן שהסיבה לכך היא תצורה שגויה או תוקף המיירט את החיבור שלך.</translation>
<translation id="3949601375789751990">היסטוריית הגלישה שלך מופיעה כאן</translation>
+<translation id="3950820424414687140">כניסה</translation>
<translation id="3963721102035795474">מצב קורא</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{ללא}=1{מאתר אחד }two{משני אתרים }many{מ-# אתרים }other{מ-# אתרים }}</translation>
<translation id="397105322502079400">מחשב...</translation>
@@ -434,6 +478,7 @@
<translation id="4103249731201008433">המספר הסידורי של המכשיר אינו חוקי</translation>
<translation id="410351446219883937">הפעלה אוטומטית</translation>
<translation id="4103763322291513355">‏היכנס לכתובת &lt;strong&gt;chrome://policy&lt;/strong&gt; כדי לראות רשימה של כתובות אתרים שנמנעה אליהם הגישה, כמו גם תקנונים אחרים שנאכפו על ידי מנהל המערכת שלך.</translation>
+<translation id="4110652170750985508">בדיקת התשלום</translation>
<translation id="4116663294526079822">אפשר תמיד באתר זה</translation>
<translation id="4117700440116928470">היקף המדיניות אינו נתמך.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{אחד נוסף}two{שניים נוספים}many{# נוספים}other{# נוספים}}</translation>
@@ -460,7 +505,6 @@
<translation id="4269787794583293679">(אין שם משתמש)</translation>
<translation id="4275830172053184480">הפעלת המכשיר מחדש</translation>
<translation id="4280429058323657511">, בתוקף עד <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">היכנס</translation>
<translation id="4312866146174492540">חסום (ברירת מחדל)</translation>
<translation id="4325863107915753736">לא ניתן היה למצוא את הפריט</translation>
<translation id="4326324639298822553">בדוק את תאריך התפוגה ונסה שוב</translation>
@@ -482,14 +526,12 @@
<translation id="4515275063822566619">‏הכרטיסים והכתובות לקוחים מ-Chrome ומחשבון Google שלך (<ph name="ACCOUNT_EMAIL" />). אפשר לנהל אותם ב<ph name="BEGIN_LINK" />הגדרות<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">פרטים</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">מדף מוטמע באתר <ph name="SITE" /></translation>
<translation id="4558551763791394412">נסה להשבית את התוספים.</translation>
<translation id="457875822857220463">משלוח</translation>
<translation id="4582800630050655161">‏הגישה שלך לחשבון Google עלולה להישלל והזהות שלך עלולה להיגנב. לגלישה בטוחה ב-Chromium, מומלץ לשנות את הסיסמה עכשיו.</translation>
<translation id="4587425331216688090">‏האם להסיר את הכתובת מ-Chrome?</translation>
<translation id="4592951414987517459">החיבור שלך אל <ph name="DOMAIN" /> מוצפן באמצעות חבילת צופן מתקדמת.</translation>
<translation id="4594403342090139922">&amp;ביטול מחיקה</translation>
-<translation id="4611292653554630842">התחבר</translation>
<translation id="4619615317237390068">כרטיסיות ממכשירים אחרים</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">השרת הזה לא הצליח להוכיח שהוא <ph name="DOMAIN" />; אישור האבטחה שלו מכיל שגיאות. ייתכן שהסיבה לכך היא הגדרה שגויה או תוקף המיירט את החיבור שלך.</translation>
@@ -499,11 +541,9 @@
<translation id="4708268264240856090">החיבור נקטע</translation>
<translation id="471880041731876836">אין לך הרשאה להיכנס אל האתר הזה</translation>
<translation id="4722547256916164131">‏<ph name="BEGIN_LINK" />מפעיל את אבחון הרשת של Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">התשלום שלך</translation>
<translation id="4726672564094551039">טען מדיניות מחדש</translation>
<translation id="4728558894243024398">פלטפורמה</translation>
<translation id="4736825316280949806">‏אתחול ה-Chromium</translation>
-<translation id="4737498291095696011">מהדף הזה</translation>
<translation id="4744603770635761495">נתיב להפעלה</translation>
<translation id="4749685221585524849">שימוש אחרון: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">הפרטים שלך (כמו סיסמאות או מספרי כרטיסי אשראי) נשלחים לאתר הזה במצב פרטי.</translation>
@@ -526,16 +566,16 @@ Del</translation>
<translation id="4850886885716139402">הצג</translation>
<translation id="4854362297993841467">שיטת המסירה הזו אינה זמינה. עליך לבחור שיטה אחרת.</translation>
<translation id="4858792381671956233">שאלת את ההורים שלך אם אתה יכול לגשת לאתר הזה</translation>
-<translation id="4871132632506079383">מדף מוטמע באתר <ph name="SITE" /></translation>
<translation id="4880827082731008257">חפש בהיסטוריה</translation>
+<translation id="4881695831933465202">פתח</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">נדרש אימות</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{ועוד דף אינטרנט אחד}two{ועוד # דפי אינטרנט}many{ועוד # דפי אינטרנט}other{ועוד # דפי אינטרנט}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">‏צריך להזין את קוד האימות של <ph name="CREDIT_CARD" />. אחרי שנקבל ממך אישור, נשתף עם האתר הזה את פרטי הכרטיס מחשבון תשלומי Google.</translation>
<translation id="4923417429809017348">דף זה תורגם משפה לא ידועה ל<ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">תשלום</translation>
<translation id="4926049483395192435">יש לציין ערך זה.</translation>
+<translation id="4926159001844873046">האתר <ph name="SITE" /> אומר</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">פעולות</translation>
<translation id="4958444002117714549">הרחב רשימה</translation>
@@ -544,7 +584,6 @@ Del</translation>
<translation id="5002932099480077015">‏אם האפשרות הזו תופעל, Chrome יאחסן עותק של הכרטיס שלך במכשיר הזה למילוי מהיר יותר של טפסים.</translation>
<translation id="5018422839182700155">לא ניתן לפתוח את הדף</translation>
<translation id="5019198164206649151">האחסון המשמש כגיבוי אינו תקין</translation>
-<translation id="5020990877659450221">מהדף הזה</translation>
<translation id="5023310440958281426">בדוק את תקנון מנהל המערכת שלך</translation>
<translation id="5029568752722684782">נקה את העותק</translation>
<translation id="503069730517007720">‏יש צורך באישור שורש בשביל "<ph name="SOFTWARE_NAME" />", אבל לא מותקן אישור כזה. על מנהל ה-IT לבדוק את הוראות התצורה של "<ph name="SOFTWARE_NAME" />" כדי לפתור את הבעיה. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -568,14 +607,14 @@ Del</translation>
<translation id="5159010409087891077">‏פתח את הדף בחלון חדש של גלישה בסתר (‎⇧⌘N)</translation>
<translation id="5171045022955879922">חפש או הקלד כתובת אתר</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="5201306358585911203">דף מוטמע בדף הזה אומר</translation>
<translation id="5205222826937269299">שם (חובה)</translation>
<translation id="5222812217790122047">אימייל (חובה)</translation>
<translation id="522700295135997067">ייתכן שהאתר הזה גנב עכשיו את הזהות שלך</translation>
<translation id="5230733896359313003">כתובת למשלוח</translation>
<translation id="5251803541071282808">ענן</translation>
-<translation id="5277279256032773186">‏משתמש ב-Chrome בעבודה? עסקים יכולים לנהל את ההגדרות של Chrome עבור העובדים. למידע נוסף</translation>
<translation id="5281113152797308730">‏<ph name="BEGIN_PARAGRAPH" />בצע את השלבים הבאים על מנת להשבית את התוכנה באופן זמני, כדי שתוכל להתחבר לאינטרנט. יש צורך בהרשאות מנהל מערכת.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -638,7 +677,6 @@ Del</translation>
<translation id="5610142619324316209">לבדוק את החיבור</translation>
<translation id="5610807607761827392">ב<ph name="BEGIN_LINK" />הגדרות<ph name="END_LINK" /> תוכל לנהל את האפשרויות של כרטיסים וכתובות.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> הפנה אותך מחדש פעמים רבות מדי.</translation>
-<translation id="5622887735448669177">האם ברצונך לעזוב את האתר?</translation>
<translation id="5629630648637658800">טעינת הגדרות המדיניות נכשלה</translation>
<translation id="5631439013527180824">אסימון ניהול המכשיר אינו חוקי</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>
@@ -661,7 +699,6 @@ Del</translation>
<translation id="5786044859038896871">האם ברצונך למלא את פרטי הכרטיס שלך?</translation>
<translation id="5803412860119678065">האם ברצונך למלא את פרטי הכרטיס <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">החיבור שלך אל <ph name="DOMAIN" /> מוצפן באמצעות חבילת צופן מיושנת.</translation>
-<translation id="5810928923025889964">מדף מוטמע בדף הזה</translation>
<translation id="5813119285467412249">&amp;ביצוע מחדש של הוספה</translation>
<translation id="5838278095973806738">אין להזין מידע רגיש באתר הזה (כמו סיסמאות או מספרי כרטיסי אשראי), מאחר שתוקפים עלולים לקבל אליו גישה.</translation>
<translation id="5866257070973731571">הוספת מספר טלפון</translation>
@@ -735,21 +772,19 @@ Del</translation>
<translation id="6446608382365791566">הוסף מידע</translation>
<translation id="6447842834002726250">‏קובצי Cookie</translation>
<translation id="6451458296329894277">אשר שליחה-מחדש של הטופס</translation>
-<translation id="6456339708790392414">התשלום שלך</translation>
<translation id="647261751007945333">מדיניות המכשיר</translation>
<translation id="6477321094435799029">‏Chrome זיהה קוד חריג בדף הזה וחסם אותו כדי להגן על המידע הפרטי שלך (כגון סיסמאות, מספרי טלפון ומספרי כרטיסי אשראי).</translation>
<translation id="6489534406876378309">התחל להעלות קריסות</translation>
<translation id="6507833130742554667">אפשר לשלם באמצעות כרטיסי אשראי וחיוב.</translation>
<translation id="6508722015517270189">‏הפעלה מחדש של Chrome</translation>
-<translation id="6521373090216409766">רוצה לטעון מחדש את האתר?</translation>
<translation id="6529602333819889595">&amp;ביצוע מחדש של מחיקה</translation>
<translation id="6534179046333460208">הצעות לאינטרנט הווירטופיזי</translation>
<translation id="6550675742724504774">אפשרויות</translation>
-<translation id="6556239504065605927">חיבור מאובטח</translation>
<translation id="6556915248009097796">תאריך תפוגה: <ph name="EXPIRATION_DATE_ABBR" />, שימוש אחרון: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">המנהל שלך עדיין לא אישר זאת</translation>
<translation id="6569060085658103619">אתה מציג דף של תוסף</translation>
<translation id="6596325263575161958">אפשרויות הצפנה</translation>
+<translation id="6604181099783169992">חיישני תנועה או אור</translation>
<translation id="6624427990725312378">פרטי איש קשר</translation>
<translation id="6626291197371920147">הוסף מספר כרטיס חוקי</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> חיפוש</translation>
@@ -821,6 +856,7 @@ Del</translation>
<translation id="7275334191706090484">סימניות מנוהלות</translation>
<translation id="7298195798382681320">מומלצים</translation>
<translation id="7309308571273880165">דוח הקריסה תועד ב<ph name="CRASH_TIME" /> (המשתמש ביקש העלאה, הדוח עדיין לא הועלה)</translation>
+<translation id="7320336641823683070">עזרה בחיבור</translation>
<translation id="7334320624316649418">&amp;ביצוע מחדש של שינוי סדר</translation>
<translation id="733923710415886693">אישור השרת לא נחשף דרך 'שקיפות אישורים'.</translation>
<translation id="7353601530677266744">שורת פקודה </translation>
@@ -905,6 +941,7 @@ Del</translation>
<translation id="782886543891417279">‏ייתכן שתידרש להיכנס לדף ההתחברות של רשת ה-Wi-Fi שבה אתה משתמש (<ph name="WIFI_NAME" />).</translation>
<translation id="785549533363645510">עם זאת, אינך בלתי נראה. המעבר למצב גלישה בסתר לא מסתיר את הגלישה שלך מהמעסיק, מספק האינטרנט או מהאתרים שאליהם אתה נכנס.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">לצאת מהאתר?</translation>
<translation id="7878176543348854470">אפשר לשלם באמצעות כרטיסי חיוב וכרטיסים משולמים מראש.</translation>
<translation id="7878562273885520351">ייתכן שאבטחת הסיסמה שלך נפגעה</translation>
<translation id="7887683347370398519">‏בדוק את ה-CVC ונסה שוב</translation>
@@ -927,6 +964,7 @@ Del</translation>
<translation id="8041940743680923270">השתמש בברירת המחדל הכללית (שאל)</translation>
<translation id="8042918947222776840">בחירת שיטת איסוף</translation>
<translation id="8057711352706143257">יש בעיה בהגדרה של "<ph name="SOFTWARE_NAME" />". בדרך כלל, הסרת ההתקנה של "<ph name="SOFTWARE_NAME" />" פותרת את הבעיה. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">לטעון את האתר מחדש?</translation>
<translation id="8088680233425245692">הצגת הפריט נכשלה.</translation>
<translation id="8091372947890762290">ההפעלה ממתינה בשרת</translation>
<translation id="8094917007353911263">ייתכן שתידרש להיכנס ל-<ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> עבור הרשת שבה אתה משתמש.</translation>
@@ -942,6 +980,7 @@ Del</translation>
<translation id="8201077131113104583">כתובת אתר לא חוקית לעדכון עבור תוסף עם המזהה "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">סיכום הזמנה</translation>
<translation id="8205463626947051446">האתר נוטה להציג מודעות שמפריעות</translation>
+<translation id="8211406090763984747">החיבור מאובטח</translation>
<translation id="8218327578424803826">מיקום מוקצה:</translation>
<translation id="8225771182978767009">האדם שהגדיר את המחשב הזה בחר לחסום את האתר הזה.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -953,6 +992,7 @@ Del</translation>
<translation id="825929999321470778">הצגת כל הסיסמאות השמורות</translation>
<translation id="8261506727792406068">מחיקה</translation>
<translation id="8267698848189296333">נכנס כ-<ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">כניסה</translation>
<translation id="8288807391153049143">הצגת אישור</translation>
<translation id="8289355894181816810">פנה אל מנהל הרשת אם אינך יודע מה זה אומר.</translation>
<translation id="8293206222192510085">הוסף סימניה</translation>
@@ -1004,6 +1044,7 @@ Del</translation>
<translation id="874846938927089722">כרטיסי אשראי וכרטיסים משולמים מראש שהסוחר מקבל</translation>
<translation id="8759274551635299824">פג תוקפו של הכרטיס</translation>
<translation id="8761567432415473239">‏גלישה בטוחה של Google <ph name="BEGIN_LINK" />איתרה לאחרונה תוכניות מזיקות<ph name="END_LINK" /> באתר <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">‏התקן USB</translation>
<translation id="8790007591277257123">&amp;ביצוע מחדש של מחיקה</translation>
<translation id="8800988563907321413">כאן מופיעות הצעות עבורך למקומות קרובים</translation>
<translation id="8820817407110198400">סימניות</translation>
diff --git a/chromium/components/strings/components_strings_ja.xtb b/chromium/components/strings/components_strings_ja.xtb
index d6130b2f9ed..eb52cd7daa2 100644
--- a/chromium/components/strings/components_strings_ja.xtb
+++ b/chromium/components/strings/components_strings_ja.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">印刷(&amp;P)...</translation>
<translation id="1181037720776840403">削除</translation>
<translation id="1184214524891303587">セキュリティに関する事象についての詳細を Google に<ph name="BEGIN_WHITEPAPER_LINK" />自動送信<ph name="END_WHITEPAPER_LINK" />する。<ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">支払い処理を完了できませんでした</translation>
<translation id="1201402288615127009">次へ</translation>
<translation id="1201895884277373915">このサイトからの他の履歴</translation>
<translation id="1206967143813997005">最初の署名に問題があります</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575"><ph name="CRASH_TIME" /> にクラッシュ レポートが作成されました(まだアップロードされておらず、無視の指定もありません)</translation>
<translation id="1270502636509132238">集荷方法</translation>
<translation id="1285320974508926690">このサイトは翻訳しない</translation>
+<translation id="1294154142200295408">コマンドラインのバリエーション</translation>
<translation id="129553762522093515">最近閉じたタブ</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Cookie を消去してみてください<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">ただし、次の相手に<ph name="BEGIN_EMPHASIS" />あなたのアクティビティが知られる<ph name="END_EMPHASIS" />可能性はあります。
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">利用可能なクレジット カードとデビットカード</translation>
<translation id="1519264250979466059">ビルド日</translation>
<translation id="1527263332363067270">接続を待機しています…</translation>
+<translation id="1532118530259321453">このページの内容</translation>
<translation id="153384715582417236">現時点では他にありません</translation>
<translation id="154408704832528245">配達先住所を選択</translation>
<translation id="1549470594296187301">この機能を使用するには JavaScript を有効にする必要があります。</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />プロキシとファイアウォールを確認する<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">郵便番号</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 件の候補}other{# 件の候補}}</translation>
-<translation id="2065985942032347596">認証が必要</translation>
<translation id="2079545284768500474">元に戻す</translation>
<translation id="20817612488360358">システム プロキシ設定を使用するように設定されていますが、明示的なプロキシの設定も指定されています。</translation>
<translation id="2091887806945687916">音声</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">支払いをキャンセル</translation>
<translation id="2147827593068025794">バックグラウンド同期</translation>
<translation id="2148613324460538318">カードを追加</translation>
-<translation id="2149973817440762519">ブックマークを編集</translation>
<translation id="2154054054215849342">お使いのドメインでは同期機能をご利用いただけません</translation>
<translation id="2154484045852737596">カードを編集</translation>
<translation id="2166049586286450108">すべてのデータへの管理者アクセス</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">集荷先住所を選択</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">選択したアイテムを削除</translation>
-<translation id="2744590937989388266">このページに埋め込まれているページから</translation>
<translation id="277133753123645258">配送方法</translation>
<translation id="277499241957683684">デバイス レコードがありません</translation>
<translation id="2784949926578158345">接続がリセットされました。</translation>
<translation id="2788784517760473862">利用可能なクレジット カード</translation>
<translation id="2794233252405721443">サイトがブロックされています</translation>
-<translation id="2795286477369100655">このサイトを離れてもよろしいですか?</translation>
<translation id="2799020568854403057">アクセス先のサイトには有害なアプリがあります</translation>
<translation id="2803306138276472711"><ph name="SITE" /> では最近、Google セーフ ブラウジングにより、<ph name="BEGIN_LINK" />不正なソフトウェアが検出されました<ph name="END_LINK" />。通常は安全なウェブサイトであっても、不正なソフトウェアに感染している場合があります。</translation>
<translation id="2824775600643448204">アドレス検索バー</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">リスト エントリ「<ph name="ENTRY_INDEX" />」: <ph name="ERROR" /></translation>
<translation id="301521992641321250">自動ブロックされました</translation>
<translation id="3024663005179499861">ポリシー タイプが間違っています</translation>
-<translation id="3032412215588512954">このサイトを再読み込みしますか?</translation>
<translation id="3037605927509011580">エラー</translation>
<translation id="3039538478787849737">カードを Google に保存しますか?</translation>
<translation id="3041612393474885105">証明書情報</translation>
@@ -310,6 +306,7 @@
動作しているかどうかを確認してください。プロキシ サーバーを使用していない場合は
次の方法をお試しください。
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" />(<ph name="SERVER_NAME" /> 上)</translation>
<translation id="320323717674993345">支払いをキャンセル</translation>
<translation id="3207960819495026254">ブックマークしました</translation>
<translation id="3209375525920864198">有効なセッション名を入力してください。</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">ブロックの解除は管理者が行うことができます</translation>
<translation id="3566021033012934673">この接続ではプライバシーが保護されません</translation>
<translation id="3574305903863751447"><ph name="COUNTRY" /> <ph name="STATE" /> <ph name="CITY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" /> に埋め込まれているページの内容</translation>
<translation id="358285529439630156">クレジット カードとプリペイド カードをご利用いただけます。</translation>
<translation id="3582930987043644930">名前を追加</translation>
<translation id="3583757800736429874">移動のやり直し(&amp;R)</translation>
<translation id="3586931643579894722">詳細を非表示</translation>
<translation id="3600246354004376029"><ph name="TITLE" />、<ph name="DOMAIN" />、<ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;接続エラーを解決する&lt;/h1&gt;
+ &lt;p&gt;ウェブサイトにアクセスしようとするとエラー メッセージが表示される場合は、以下の解決方法をお試しください。&lt;/p&gt;
+ &lt;h2&gt;一般的な接続エラーを解決する&lt;/h2&gt;
+ &lt;p&gt;ウェブサイトにアクセスしようとしてもサイトが開かない場合は、まず次の解決方法を行って、エラーが解消されるかご確認ください。&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;ウェブアドレスに入力ミスがないか確認します。&lt;/li&gt;
+ &lt;li&gt;インターネット接続に問題がないことを確認します。&lt;/li&gt;
+ &lt;li&gt;ウェブサイトの所有者に問い合わせます。&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;特定のエラー メッセージに関する情報&lt;/h2&gt;
+ &lt;h3&gt;「この接続ではプライバシーが保護されません」、「NET::ERR_CERT_AUTHORITY_INVALID」、「ERR_CERT_COMMON_NAME_INVALID」、「NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM」、「SSL 証明書エラー」&lt;/h3&gt;
+ &lt;h4&gt;ステップ 1: ポータルにログインする&lt;/h4&gt;
+ &lt;p&gt;カフェや空港といった場所の Wi-Fi ネットワークを使用するには、ログインが必要です。ログインページを表示するには、&lt;code&gt;http://&lt;/code&gt; を使用しているページにアクセスします。&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;&lt;code&gt;http://&lt;/code&gt; で始まる任意のウェブサイトにアクセスします(例: &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;)。&lt;/li&gt;
+ &lt;li&gt;インターネットを使用するには、表示されたログインページでログインします。&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;ステップ 2: シークレット モードでページを開く(パソコンのみ)&lt;/h4&gt;
+ &lt;p&gt;アクセスしたページをシークレット ウィンドウで開きます。&lt;/p&gt;
+ &lt;p&gt;この方法でページが表示された場合は、Chrome の拡張機能に問題があります。エラーを解決するには、問題のある拡張機能を無効にしてください。&lt;/p&gt;
+ &lt;h4&gt;ステップ 3: オペレーティング システムを更新する&lt;/h4&gt;
+ &lt;p&gt;端末が最新の状態であることを確認します。&lt;/p&gt;
+ &lt;h4&gt;ステップ 4: ウィルス対策ソフトウェアを一時的に無効にする&lt;/h4&gt;
+ &lt;p&gt;このエラーは、「HTTPS 保護」や「HTTPS スキャン」などの機能を備えたウィルス対策ソフトウェアを使用している場合に表示されます。こうしたウィルス対策ソフトウェアにより、Chrome のセキュリティが適用されなくなっています。&lt;/p&gt;
+ &lt;p&gt;問題を解決するには、ウィルス対策ソフトウェアを無効にします。無効にするとページを利用できるようになる場合は、セキュリティで保護されたサイトにアクセスするときにこのソフトウェアを無効にしてください。&lt;/p&gt;
+ &lt;p&gt;サイトの利用が終わったら、ウィルス対策ソフトウェアを有効にします。&lt;/p&gt;
+ &lt;h4&gt;ステップ 5: サポートを依頼する&lt;/h4&gt;
+ &lt;p&gt;引き続きエラーが表示される場合は、ウェブサイトの所有者にお問い合わせください。&lt;/p&gt;
+ &lt;h3&gt;「ネットワークに接続してください」&lt;/h3&gt;
+ &lt;p&gt;インターネットに接続するために Wi-Fi ポータルへのログインが必要な場合は、このエラーが表示されます。&lt;/p&gt;
+ &lt;p&gt;エラーを解決するには、開こうとしているページで [&lt;strong&gt;接続&lt;/strong&gt;] をクリックします。&lt;/p&gt;
+ &lt;h3&gt;「時計が遅れています」、「時計が進んでいます」、「NET::ERR_CERT_DATE_INVALID」&lt;/h3&gt;
+ &lt;p&gt;このエラーは、パソコンまたはモバイル端末の日付と時刻が正確ではない場合に表示されます。&lt;/p&gt;
+ &lt;p&gt;エラーを解決するには、端末の時計を開き、日付と時刻が正しいことを確認します。&lt;/p&gt;
+ &lt;h3&gt;「パソコンにインストールされているソフトウェアが原因で、Chrome からインターネットに安全に接続することができません」(Windows パソコンのみ)&lt;/h3&gt;
+ &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;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;] をクリックします。
+ &lt;li&gt;[&lt;strong&gt;適用&lt;/strong&gt;] をクリックし、[&lt;strong&gt;OK&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="3615877443314183785">有効期限(日)を入力してください</translation>
<translation id="36224234498066874">閲覧履歴を消去...</translation>
<translation id="362276910939193118">全履歴を表示</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">このカードを Google アカウントとこの端末に保存しますか?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">有効期限: <ph name="EXPIRATION_MONTH" /> / <ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929"><ph name="SITE" /> から</translation>
<translation id="382518646247711829">プロキシ サーバーを使用している場合...</translation>
<translation id="3828924085048779000">パスフレーズは必ず指定してください。</translation>
<translation id="385051799172605136">戻る</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">クラッシュ レポート ID <ph name="CRASH_ID" /> がアップロードされました(ローカルのクラッシュ ID: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">このサーバーが <ph name="DOMAIN" /> であることを確認できませんでした。このサーバーのセキュリティ証明書で SAN(サブジェクトの別名)が指定されていません。設定が不適切であるか、悪意のあるユーザーによって接続が妨害されている可能性があります。</translation>
<translation id="3949601375789751990">閲覧履歴がここに表示されます</translation>
+<translation id="3950820424414687140">ログイン</translation>
<translation id="3963721102035795474">リーダーモード</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{なし}=1{1 件のサイトから}other{# 件のサイトから}}</translation>
<translation id="397105322502079400">計算しています...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">デバイスのシリアル番号が無効です</translation>
<translation id="410351446219883937">自動再生</translation>
<translation id="4103763322291513355">&lt;strong&gt;chrome://policy&lt;/strong&gt; にアクセスして、ブラックリストに登録されている URL とシステム管理者が設定した他のポリシーを確認できます。</translation>
+<translation id="4110652170750985508">お支払いの確認</translation>
<translation id="4116663294526079822">このサイトでは常に許可</translation>
<translation id="4117700440116928470">ポリシーの適用範囲がサポートされていません。</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{他 1 件}other{他 # 件}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(ユーザー名なし)</translation>
<translation id="4275830172053184480">デバイスの再起動</translation>
<translation id="4280429058323657511">、有効期限: <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">ログイン</translation>
<translation id="4312866146174492540">ブロック(デフォルト)</translation>
<translation id="4325863107915753736">記事が見つかりませんでした</translation>
<translation id="4326324639298822553">有効期限の「日」を確認してもう一度お試しください</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Chrome と Google アカウント(<ph name="ACCOUNT_EMAIL" />)に保存されているクレジット カードと住所です。[<ph name="BEGIN_LINK" />設定<ph name="END_LINK" />] で管理できます。</translation>
<translation id="4522570452068850558">詳細</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291"><ph name="SITE" /> に埋め込まれているページから</translation>
<translation id="4558551763791394412">拡張機能を無効にしてみてください。</translation>
<translation id="457875822857220463">配送</translation>
<translation id="4582800630050655161">Google アカウントにアクセスできなくなったり、個人情報が盗まれたりする可能性があります。Chromium で今すぐパスワードを変更することをおすすめします。</translation>
<translation id="4587425331216688090">Chrome からアドレスを削除してもよろしいですか?</translation>
<translation id="4592951414987517459"><ph name="DOMAIN" /> への接続は新しい暗号スイートにより暗号化されています。</translation>
<translation id="4594403342090139922">削除の取り消し(&amp;U)</translation>
-<translation id="4611292653554630842">ログイン</translation>
<translation id="4619615317237390068">他のデバイスからのタブ</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">このサーバーが <ph name="DOMAIN" /> であることを確認できませんでした。このサーバーのセキュリティ証明書にはエラーがあります。原因としては、不適切な設定や、悪意のあるユーザーによる接続妨害が考えられます。</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">接続が中断されました</translation>
<translation id="471880041731876836">このサイトへのアクセスが許可されていません</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows ネットワーク診断ツールを実行する<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">お支払い</translation>
<translation id="4726672564094551039">ポリシーを再読み込み</translation>
<translation id="4728558894243024398">プラットフォーム</translation>
<translation id="4736825316280949806">Chromium を再起動する</translation>
-<translation id="4737498291095696011">このページから</translation>
<translation id="4744603770635761495">実行ファイルのパス</translation>
<translation id="4749685221585524849">最終使用日: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">お客様がこのサイトに送信した情報(パスワード、クレジット カード番号など)が第三者に見られることはありません。</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">表示</translation>
<translation id="4854362297993841467">この配達方法はご利用いただけません。別の方法を選択してください。</translation>
<translation id="4858792381671956233">このサイトを開いてもよいかの問い合わせを保護者に送信しました</translation>
-<translation id="4871132632506079383"><ph name="SITE" /> に埋め込まれているページから</translation>
<translation id="4880827082731008257">履歴を検索</translation>
+<translation id="4881695831933465202">開く</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />、<ph name="TYPE_2" />、<ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">認証が必要です</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{他 1 件のウェブページ}other{他 # 件のウェブページ}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947"><ph name="CREDIT_CARD" /> の CVC を入力します。確認後、Google Payments アカウントのカード情報がこのサイトと共有されます。</translation>
<translation id="4923417429809017348">このページは、不明な言語から<ph name="LANGUAGE_LANGUAGE" />に翻訳されました。</translation>
<translation id="4923459931733593730">お支払い</translation>
<translation id="4926049483395192435">指定する必要があります。</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> の内容</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" /> / <ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">操作</translation>
<translation id="4958444002117714549">リストを展開する</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">有効にすると、Chrome ではこの端末にカードのコピーが保存されます。これにより、フォームにすばやく入力できるようになります。</translation>
<translation id="5018422839182700155">このページを開けません</translation>
<translation id="5019198164206649151">代替ストアの状態が不適切です</translation>
-<translation id="5020990877659450221">このページから</translation>
<translation id="5023310440958281426">管理者のポリシーを確認してください</translation>
<translation id="5029568752722684782">コピーを消去</translation>
<translation id="503069730517007720">「<ph name="SOFTWARE_NAME" />」のルート証明書が必要ですが、インストールされていません。IT 管理者に、「<ph name="SOFTWARE_NAME" />」の設定手順を確認したうえでこの問題を修正するよう依頼してください。<ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">マシン</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" />でない場合はこのエラーを報告する</translation>
<translation id="5190835502935405962">ブックマーク バー</translation>
+<translation id="5201306358585911203">このページに埋め込まれているページの内容</translation>
<translation id="5205222826937269299">名前は必須です</translation>
<translation id="5222812217790122047">メールアドレスは必須です</translation>
<translation id="522700295135997067">このサイトでパスワードを盗まれた可能性があります</translation>
<translation id="5230733896359313003">配送先住所</translation>
<translation id="5251803541071282808">クラウド</translation>
-<translation id="5277279256032773186">会社で Chrome を使用する場合は、従業員用に Chrome の設定を管理できます。詳細</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />このソフトウェアを一時的に無効にしてインターネットに接続できるようにするには、次の手順を行います。なお、この作業には管理者権限が必要です。<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">接続を確認する</translation>
<translation id="5610807607761827392">カードと住所は [<ph name="BEGIN_LINK" />設定<ph name="END_LINK" />] で管理できます。</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> でリダイレクトが繰り返し行われました。</translation>
-<translation id="5622887735448669177">このサイトを離れてもよろしいですか?</translation>
<translation id="5629630648637658800">ポリシー設定を読み込めませんでした</translation>
<translation id="5631439013527180824">無効なデバイス管理トークンです</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">カード情報を入力しますか?</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" /> を入力しますか?</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> への接続は古い暗号スイートにより暗号化されています。</translation>
-<translation id="5810928923025889964">このページに埋め込まれているページから</translation>
<translation id="5813119285467412249">追加のやり直し(&amp;R)</translation>
<translation id="5838278095973806738">このサイトでは機密情報(パスワード、クレジット カードなど)を入力しないでください。悪意のあるユーザーに情報が盗まれる恐れがあります。</translation>
<translation id="5866257070973731571">電話番号の追加</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">他の情報を追加</translation>
<translation id="6447842834002726250">Cookie</translation>
<translation id="6451458296329894277">フォーム再送信の確認</translation>
-<translation id="6456339708790392414">お支払い</translation>
<translation id="647261751007945333">デバイス ポリシー</translation>
<translation id="6477321094435799029">このページで通常と異なるコードを検出したため、個人情報(例: パスワード、電話番号、クレジット カード番号)を保護するために、ページをブロックしました。</translation>
<translation id="6489534406876378309">クラッシュのアップロードを開始</translation>
<translation id="6507833130742554667">クレジット カードとデビットカードをご利用いただけます。</translation>
<translation id="6508722015517270189">Chrome を再起動する</translation>
-<translation id="6521373090216409766">このサイトを再読み込みしてもよろしいですか?</translation>
<translation id="6529602333819889595">削除のやり直し(&amp;R)</translation>
<translation id="6534179046333460208">フィジカル ウェブからの URL</translation>
<translation id="6550675742724504774">オプション</translation>
-<translation id="6556239504065605927">保護された接続</translation>
<translation id="6556915248009097796">有効期限: <ph name="EXPIRATION_DATE_ABBR" />、最終使用日: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">管理者がまだサイトを開くことを許可していません</translation>
<translation id="6569060085658103619">拡張機能のページを表示しています</translation>
<translation id="6596325263575161958">暗号化オプション</translation>
+<translation id="6604181099783169992">モーション センサーまたは光センサー</translation>
<translation id="6624427990725312378">連絡先情報</translation>
<translation id="6626291197371920147">有効なカード番号を追加</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> 検索</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">管理対象のブックマーク</translation>
<translation id="7298195798382681320">推奨</translation>
<translation id="7309308571273880165"><ph name="CRASH_TIME" /> にクラッシュ レポートが作成されました(ユーザーからアップロードがリクエストされましたが、まだアップロードされていません)</translation>
+<translation id="7320336641823683070">接続に関するヘルプ</translation>
<translation id="7334320624316649418">順序変更のやり直し(&amp;R)</translation>
<translation id="733923710415886693">サーバーの証明書は、証明書の透明性ポリシーを介して公開されていません。</translation>
<translation id="7353601530677266744">コマンドライン</translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">ご利用の Wi-Fi(<ph name="WIFI_NAME" />)では、ログインページへのアクセスが必要な可能性があります。</translation>
<translation id="785549533363645510">あらゆる場所に記録が一切残らないわけではありません。シークレット モードを使っても、雇用主、インターネット サービス プロバイダ、訪問先のウェブサイトに閲覧内容が知られる可能性はあります。</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
+<translation id="7862185352068345852">このサイトを離れますか?</translation>
<translation id="7878176543348854470">デビットカードとプリペイド カードをご利用いただけます。</translation>
<translation id="7878562273885520351">パスワードが不正使用される可能性があります</translation>
<translation id="7887683347370398519">CVC を確認してからもう一度お試しください</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">グローバルのデフォルト値([確認])を使用</translation>
<translation id="8042918947222776840">集荷方法を選択</translation>
<translation id="8057711352706143257">「<ph name="SOFTWARE_NAME" />」が正しく設定されていません。通常、この問題は「<ph name="SOFTWARE_NAME" />」をアンインストールすることで解決します。<ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">このサイトを再読み込みしますか?</translation>
<translation id="8088680233425245692">記事を表示できませんでした。</translation>
<translation id="8091372947890762290">サーバーで有効化が保留になっています</translation>
<translation id="8094917007353911263">ご利用のネットワークでは、<ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> へのアクセスが必要な可能性があります。</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">ID「<ph name="EXTENSION_ID" />」の拡張機能に対する無効な更新 URL です。</translation>
<translation id="8202097416529803614">ご注文概要</translation>
<translation id="8205463626947051446">煩わしい広告がよく表示されるサイト</translation>
+<translation id="8211406090763984747">この接続は保護されています</translation>
<translation id="8218327578424803826">割り当てられた場所:</translation>
<translation id="8225771182978767009">このサイトは、このパソコンを設定したユーザーによってブロックされています。</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />、<ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">保存したパスワードをすべて表示</translation>
<translation id="8261506727792406068">削除</translation>
<translation id="8267698848189296333"><ph name="USERNAME" /> としてログイン</translation>
+<translation id="8286036467436129157">ログイン</translation>
<translation id="8288807391153049143">証明書を表示</translation>
<translation id="8289355894181816810">確認方法がわからない場合は、ネットワーク管理者までお問い合わせください。</translation>
<translation id="8293206222192510085">ブックマークの追加</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">利用可能なクレジット カードとプリペイド カード</translation>
<translation id="8759274551635299824">このカードは有効期限が切れています</translation>
<translation id="8761567432415473239"><ph name="SITE" /> では最近、Google セーフ ブラウジングにより<ph name="BEGIN_LINK" />有害なプログラムが検出<ph name="END_LINK" />されました。</translation>
+<translation id="8763927697961133303">USB デバイス</translation>
<translation id="8790007591277257123">削除のやり直し(&amp;R)</translation>
<translation id="8800988563907321413">周辺のおすすめの場所がここに表示されます</translation>
<translation id="8820817407110198400">ブックマーク</translation>
diff --git a/chromium/components/strings/components_strings_kn.xtb b/chromium/components/strings/components_strings_kn.xtb
index 2bbea86578c..817e8e9e529 100644
--- a/chromium/components/strings/components_strings_kn.xtb
+++ b/chromium/components/strings/components_strings_kn.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;ಮುದ್ರಿಸಿ...</translation>
<translation id="1181037720776840403">ತೆಗೆದುಹಾಕು</translation>
<translation id="1184214524891303587">ಸಂಭಾವ್ಯ ಸುರಕ್ಷತೆ ಸಂಬಂಧಿಸಿದ ಘಟನೆಗಳ ವಿವರಗಳನ್ನು Google ಗೆ <ph name="BEGIN_WHITEPAPER_LINK" />ಸ್ವಯಂಚಾಲಿತವಾಗಿ ವರದಿಮಾಡಿ<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">ಪಾವತಿ ಪೂರ್ಣಗೊಂಡಿಲ್ಲ</translation>
<translation id="1201402288615127009">ಮುಂದೆ</translation>
<translation id="1201895884277373915">ಈ ಸೈಟ್‌ನಿಂದ ಇನ್ನಷ್ಟು</translation>
<translation id="1206967143813997005">ತಪ್ಪು ಪ್ರಾರಂಭಿಕ ಸಹಿ</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575"><ph name="CRASH_TIME" /> ನಲ್ಲಿ ಕ್ರ್ಯಾಶ್ ವರದಿಯನ್ನು ಸೆರೆಹಿಡಿಯಲಾಗಿದೆ (ಇನ್ನೂ ಅಪ್‌ಲೋಡ್ ಮಾಡಲಾಗಿಲ್ಲ ಅಥವಾ ನಿರ್ಲಕ್ಷಿಸಲಾಗಿಲ್ಲ)</translation>
<translation id="1270502636509132238">ಪಿಕಪ್ ವಿಧಾನ</translation>
<translation id="1285320974508926690">ಈ ಸೈಟ್ ಅನ್ನು ಎಂದಿಗೂ ಭಾಷಾಂತರಿಸದಿರಿ</translation>
+<translation id="1294154142200295408">ಕಮಾಂಡ್-ಲೈನ್ ವ್ಯತ್ಯಾಸಗಳು</translation>
<translation id="129553762522093515">ಇತ್ತೀಚೆಗೆ ಮುಚ್ಚಲಾಗಿರುವುದು</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />ನಿಮ್ಮ ಕುಕೀಗಳನ್ನು ತೆರವುಗೊಳಿಸಲು ಪ್ರಯತ್ನಿಸಿ<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">ನಿಮ್ಮ ಚಟುವಟಿಕೆಗಳು <ph name="BEGIN_EMPHASIS" />ಇನ್ನೂ ಇವರಿಗೆ ಕಾಣಿಸಿಕೊಳ್ಳಬಹುದು<ph name="END_EMPHASIS" /> :
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">ಸಮ್ಮತಿಸಲಾದ ಕ್ರೆಡಿಟ್ ಮತ್ತು ಡೆಬಿಟ್ ಕಾರ್ಡ್‌ಗಳು</translation>
<translation id="1519264250979466059">ಬಿಲ್ಡ್ ಡೇಟಾ</translation>
<translation id="1527263332363067270">ಸಂಪರ್ಕಕ್ಕೆ ಕಾಯಲಾಗುತ್ತಿದೆ...</translation>
+<translation id="1532118530259321453">ಈ ಪುಟವು ಹೀಗೆ ಹೇಳುತ್ತದೆ</translation>
<translation id="153384715582417236">ಇದುವರೆಗೂ ಇಷ್ಟೇ</translation>
<translation id="154408704832528245">ವಿತರಣೆಯ ವಿಳಾಸಗಳನ್ನು ಆರಿಸಿ</translation>
<translation id="1549470594296187301">ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬಳಸಲು JavaScript ಸಕ್ರಿಯಗೊಳಿಸಬೇಕು.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />ಪ್ರಾಕ್ಸಿ ಮತ್ತು ಫೈರ್‌ವಾಲ್ ಅನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">ಪಿನ್ ಕೋಡ್</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 ಸಲಹೆ}one{# ಸಲಹೆಗಳು}other{# ಸಲಹೆಗಳು}}</translation>
-<translation id="2065985942032347596">ದೃಢೀಕರಣದ ಅವಶ್ಯಕತೆಯಿದೆ</translation>
<translation id="2079545284768500474">ರದ್ದುಮಾಡಿ</translation>
<translation id="20817612488360358">ಸಿಸ್ಟಂ ಪ್ರಾಕ್ಸಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬಳಸಲು ಹೊಂದಿಸಲಾಗಿದೆ ಆದರೆ ಬಹಿರಂಗವಾದ ಪ್ರಾಕ್ಸಿ ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ಸಹ ನಿರ್ದಿಷ್ಟಪಡಿಸಲಾಗಿದೆ.</translation>
<translation id="2091887806945687916">ಶಬ್ಧ</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">ಪಾವತಿಯನ್ನು ರದ್ದುಮಾಡಿ</translation>
<translation id="2147827593068025794">ಹಿನ್ನೆಲೆ ಸಿಂಕ್</translation>
<translation id="2148613324460538318">ಕಾರ್ಡ್ ಸೇರಿಸಿ</translation>
-<translation id="2149973817440762519">ಬುಕ್‌ಮಾರ್ಕ್ ಎಡಿಟ್ ಮಾಡಿ</translation>
<translation id="2154054054215849342">ಸಿಂಕ್ ಸೇವೆಯು ನಿಮ್ಮ ಡೊಮೇನ್‌ಗೆ ಲಭ್ಯವಿಲ್ಲ</translation>
<translation id="2154484045852737596">ಕಾರ್ಡ್ ಎಡಿಟ್ ಮಾಡಿ</translation>
<translation id="2166049586286450108">ಪೂರ್ಣ ನಿರ್ವಾಹಕ ಪ್ರವೇಶ</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">ಪಿಕಪ್ ವಿಳಾಸವನ್ನು ಆರಿಸಿ</translation>
<translation id="2740531572673183784">ಸರಿ</translation>
<translation id="2742870351467570537">ಆಯ್ಕೆಮಾಡಿದ ಐಟಂಗಳನ್ನು ತೆಗೆದುಹಾಕಿ</translation>
-<translation id="2744590937989388266">ಈ ಪುಟದಲ್ಲಿ ಎಂಬೆಡ್ ಮಾಡಲಾದ ಪುಟದಿಂದ</translation>
<translation id="277133753123645258">ಶಿಪ್ಪಿಂಗ್ ವಿಧಾನ</translation>
<translation id="277499241957683684">ಸಾಧನದ ರೆಕಾರ್ಡ್ ಕಾಣೆಯಾಗಿದೆ</translation>
<translation id="2784949926578158345">ಸಂಪರ್ಕವನ್ನು ರೀಸೆಟ್ ಮಾಡಲಾಗಿದೆ.</translation>
<translation id="2788784517760473862">ಸ್ವೀಕೃತ ಕ್ರೆಡಿಟ್‌ ಕಾರ್ಡ್‌ಗಳು</translation>
<translation id="2794233252405721443">ಸೈಟ್ ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ</translation>
-<translation id="2795286477369100655">ನೀವು ಈ ಸೈಟ್ ತೊರೆಯಲು ಬಯಸುತ್ತೀರಾ?</translation>
<translation id="2799020568854403057">ಮುಂದಿರುವ ಸೈಟ್‌ನಲ್ಲಿ ಹಾನಿಕಾರಕ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿವೆ</translation>
<translation id="2803306138276472711">Google ಸುರಕ್ಷಿತ ಬ್ರೌಸಿಂಗ್ ಇತ್ತೀಚೆಗೆ <ph name="SITE" /> ನಲ್ಲಿ <ph name="BEGIN_LINK" />ಮಾಲ್‌ವೇರ್ ಪತ್ತೆಹಚ್ಚಿದೆ<ph name="END_LINK" />. ವೆಬ್‌ಸೈಟ್‌ಗಳು ಸಾಮಾನ್ಯವಾಗಿ ಸುರಕ್ಷಿತವಾಗಿದ್ದರೂ, ಕೆಲವೊಮ್ಮೆ ಮಾಲ್‌ವೇರ್‌ಗೆ ತುತ್ತಾಗಿರುತ್ತವೆ.</translation>
<translation id="2824775600643448204">ವಿಳಾಸ ಹಾಗೂ ಹುಡುಕಾಟ ಪಟ್ಟಿ</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">ಪಟ್ಟಿ ನಮೂದು "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">ಸ್ವಯಂಚಾಲಿತವಾಗಿ ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ</translation>
<translation id="3024663005179499861">ತಪ್ಪಾದ ನೀತಿಯ ಪ್ರಕಾರ</translation>
-<translation id="3032412215588512954">ನೀವು ಈ ಸೈಟ್ ಮರುಲೋಡ್ ಮಾಡಲು ಬಯಸುವಿರಾ?</translation>
<translation id="3037605927509011580">ಓಹ್, ಹೋಯ್ತು!</translation>
<translation id="3039538478787849737">ಕಾರ್ಡ್‌ ಅನ್ನು Google ನಲ್ಲಿ ಉಳಿಸಬೇಕೆ?</translation>
<translation id="3041612393474885105">ಪ್ರಮಾಣಪತ್ರ ಮಾಹಿತಿ</translation>
@@ -308,6 +304,7 @@
<translation id="3174168572213147020">ದ್ವೀಪ</translation>
<translation id="3176929007561373547">ಪ್ರಾಕ್ಸಿ ಸರ್ವರ್ ಕಾರ್ಯವನಿರ್ವಹಿಸುತ್ತಿದೆಯೇ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು ನಿಮ್ಮ ಪ್ರಾಕ್ಸಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ ಮತ್ತು ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ. ನೀವು ಪ್ರಾಕ್ಸಿ ಸರ್ವರ್ ಅನ್ನು ಬಳಸುತ್ತಿಲ್ಲ ಎಂಬ ಅನುಮಾನ ನಿಮಗಿದ್ದರೆ:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="SERVER_NAME" /> ನಲ್ಲಿ <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">ಪಾವತಿಯನ್ನು ರದ್ದುಮಾಡಿ</translation>
<translation id="3207960819495026254">ಬುಕ್‌ಮಾರ್ಕ್‌ ಮಾಡಲಾಗಿದೆ</translation>
<translation id="3209375525920864198">ಮಾನ್ಯವಾದ ಸೆಶನ್ ಹೆಸರನ್ನು ನಮೂದಿಸಿ.</translation>
@@ -365,11 +362,57 @@
<translation id="3556433843310711081">ನಿಮ್ಮ ಮ್ಯಾನೇಜರ್ ನಿಮಗಾಗಿ ಅದನ್ನು ಅನಿರ್ಬಂಧಿಸಬಹುದಾಗಿದೆ</translation>
<translation id="3566021033012934673">ನಿಮ್ಮ ಸಂಪರ್ಕವು ಖಾಸಗಿಯಲ್ಲ</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" /> ನಲ್ಲಿ ಎಂಬೆಡ್ ಮಾಡಲಾದ ಪುಟವು ಹೀಗೆ ಹೇಳುತ್ತದೆ</translation>
<translation id="358285529439630156">ಡೆಬಿಟ್‌ ಮತ್ತು ಪ್ರೀಪೇಯ್ಡ್‌ ಕಾರ್ಡ್‌ಗಳನ್ನು ಸಮ್ಮತಿಸಲಾಗಿದೆ.</translation>
<translation id="3582930987043644930">ಹೆಸರು ಸೇರಿಸಿ</translation>
<translation id="3583757800736429874">&amp;ಸರಿಸುವುದನ್ನು ಮತ್ತೆಮಾಡು</translation>
<translation id="3586931643579894722">ವಿವರಗಳನ್ನು ಮರೆಮಾಡಿ</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;ಸಂಪರ್ಕ ದೋಷಗಳನ್ನು ಪರಿಹರಿಸಿ&lt;/h1&gt;
+ &lt;p&gt;ನೀವು ಒಂದು ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಪ್ರಯತ್ನಿಸುವಾಗ ದೋಷ ಸಂದೇಶ ಕಾಣಿಸಿದರೆ, ಈ ಪರಿಹಾರಗಳನ್ನು ಬಳಸಿ ನೋಡಿ.&lt;/p&gt;
+ &lt;h2&gt;ಹೆಚ್ಚಿನ ಸಂಪರ್ಕ ದೋಷಗಳನ್ನು ಪರಿಹರಿಸಿ&lt;/h2&gt;
+ &lt;p&gt;ನೀವು ಒಂದು ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಪ್ರಯತ್ನಿಸುವಾಗ ಅದು ತೆರೆಯದಿದ್ದರೆ, ಈ ಸಮಸ್ಯೆ ನಿವಾರಣೆ ಕ್ರಮಗಳ ಮೂಲಕ ದೋಷವನ್ನು ಪರಿಹರಿಸಲು ಪ್ರಯತ್ನಿಸಿ:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;ವೆಬ್ ವಿಳಾಸದಲ್ಲಿ ಟೈಪಿಂಗ್ ದೋಷಗಳಿವೆಯೇ ಎಂದು ನೋಡಿ.&lt;/li&gt;
+ &lt;li&gt;ನಿಮ್ಮ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕ ಸಾಮಾನ್ಯವಾಗಿ ಕೆಲಸ ಮಾಡುತ್ತಿದೆಯೇ ಎಂದು ನೋಡಿ.&lt;/li&gt;
+ &lt;li&gt;ವೆಬ್‌ಸೈಟ್‌ನ ಮಾಲೀಕರನ್ನು ಸಂಪರ್ಕಿಸಿ.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;ನಿರ್ದಿಷ್ಟ ದೋಷ ಸಂದೇಶಕ್ಕಾಗಿ ಸಹಾಯ ಪಡೆಯಿರಿ&lt;/h2&gt;
+ &lt;h3&gt;"ನಿಮ್ಮದು ಖಾಸಗಿ ಸಂಪರ್ಕವಲ್ಲ" ಅಥವಾ "NET::ERR_CERT_AUTHORITY_INVALID" ಅಥವಾ "ERR_CERT_COMMON_NAME_INVALID" ಅಥವಾ "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" ಅಥವಾ "SSL ಪ್ರಮಾಣ ಪತ್ರ ದೋಷ"&lt;/h3&gt;
+ &lt;h4&gt;ಹಂತ 1: ಪೋರ್ಟಲ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ&lt;/h4&gt;
+ &lt;p&gt;ಕೆಫೆಗಳು ಅಥವಾ ವಿಮಾನ ನಿಲ್ದಾಣಗಳಲ್ಲಿನ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗಳಿಗೆ ಸಂಪರ್ಕ ಪಡೆಯಲು ನೀವು ಸೈನ್ ಇನ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ. ಸೈನ್-ಇನ್ ಪುಟವನ್ನು ನೋಡಲು, &lt;code&gt;http://&lt;/code&gt; ಬಳಸುವ ಪುಟಕ್ಕೆ ಭೇಟಿ ನೀಡಿ.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;&lt;code&gt;http://&lt;/code&gt; ನಿಂದ ಪ್ರಾರಂಭವಾಗುವ ಯಾವುದೇ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಹೋಗಿ, ಉದಾಹರಣೆಗೆ &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;ಸೈನ್-ಇನ್ ಪುಟವು ತೆರೆದುಕೊಂಡಾಗ, ಇಂಟರ್ನೆಟ್ ಬಳಸಲು ಸೈನ್-ಇನ್ ಮಾಡಿ.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;ಹಂತ 2: ಪುಟವನ್ನು ಅಜ್ಞಾತ ಮೋಡನಲ್ಲಿ ತೆರೆಯಿರಿ (ಕಂಪ್ಯೂಟರ್‌ನಲ್ಲಿ ಮಾತ್ರ)&lt;/h4&gt;
+ &lt;p&gt;ನೀವು ಅಜ್ಞಾತ ವಿಂಡೋದಲ್ಲಿ ಭೇಟಿ ನೀಡಿದ ಪುಟವನ್ನು ತೆರೆಯಿರಿ.&lt;/p&gt;
+ &lt;p&gt;ಪುಟವು ತೆರೆದುಕೊಂಡರೆ, ಒಂದು Chrome ವಿಸ್ತರಣೆಯು ಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡುತ್ತಿಲ್ಲ ಎಂದು ಅರ್ಥ. ದೋಷವನ್ನು ಪರಿಹರಿಸಲು, ವಿಸ್ತರಣೆಯನ್ನು ಆಫ್ ಮಾಡಿ.&lt;/p&gt;
+ &lt;h4&gt;ಹಂತ 3: ನಿಮ್ಮ ಆಪರೇಟಿಂಗ್ ಸಿಸ್ಟಮ್ ಅನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡಿ&lt;/h4&gt;
+ &lt;p&gt;ನಿಮ್ಮ ಸಾಧನವು ಅಪ್‌ಡೇಟ್ ಆಗಿರುವುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ.&lt;/p&gt;
+ &lt;h4&gt;ಹಂತ 4: ನಿಮ್ಮ ಆ್ಯಂಟಿವೈರಸ್ ಅನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ಆಫ್ ಮಾಡಿ&lt;/h4&gt;
+ &lt;p&gt;"HTTPS ಸಂರಕ್ಷಣೆ" ಅಥವಾ "HTTPS ಸ್ಕ್ಯಾನಿಂಗ್" ಅನ್ನು ಒದಗಿಸುವ ಆ್ಯಂಟಿವೈರಸ್ ಸಾಫ್ಟ್‌ವೇರ್ ಅನ್ನು ನೀವು ಹೊಂದಿದ್ದರೆ ನೀವು ಈ ದೋಷವನ್ನು ನೋಡುವಿರಿ. Chrome ಸುರಕ್ಷತೆ ಒದಗಿಸದಂತೆ ಆ್ಯಂಟಿವೈರಸ್ ತಡೆಯುತ್ತಿದೆ.&lt;/p&gt;
+ &lt;p&gt;ಸಮಸ್ಯೆಯನ್ನು ಪರಿಹರಿಸಲು, ಆ್ಯಂಟಿವೈರಸ್ ಸಾಫ್ಟ್‌ವೇರ್ ಅನ್ನು ಆಫ್ ಮಾಡಿ. ಸಾಫ್ಟ್‌ವೇರ್ ಆಫ್ ಮಾಡಿದ ಬಳಿಕ ಪುಟವು ಕೆಲಸ ಮಾಡಿದರೆ, ನೀವು ಸುರಕ್ಷಿತ ಸೈಟ್‌ಗಳನ್ನು ಬಳಸುವಾಗ ಈ ಸಾಫ್ಟ್‌ವೇರ್ ಅನ್ನು ಆಫ್ ಮಾಡಿ.&lt;/p&gt;
+ &lt;p&gt;ನಿಮ್ಮ ಕೆಲಸ ಮುಗಿದ ನಂತರ, ನಿಮ್ಮ ಆ್ಯಂಟಿವೈರಸ್ ಪ್ರೋಗ್ರಾಂ ಅನ್ನು ಮರಳಿ ಆನ್ ಮಾಡಲು ಮರೆಯಬೇಡಿ.&lt;/p&gt;
+ &lt;h4&gt;ಹಂತ 5: ಹೆಚ್ಚುವರಿ ಸಹಾಯ ಪಡೆಯಿರಿ&lt;/h4&gt;
+ &lt;p&gt;ದೋಷವು ಇನ್ನೂ ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತಿದ್ದರೆ, ವೆಬ್‌ಸೈಟ್ ಮಾಲೀಕರನ್ನು ಸಂಪರ್ಕಿಸಿ.&lt;/p&gt;
+ &lt;h3&gt;"ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸಿ"&lt;/h3&gt;
+ &lt;p&gt;ನೀವು ಆನ್‌ಲೈನ್‌ಗೆ ಹೋಗಬೇಕಾದರೆ ಸೈನ್-ಇನ್ ಮಾಡಬೇಕಾದ ಅಗತ್ಯವಿರುವ ವೈ-ಫೈ ಪೋರ್ಟಲ್ ಅನ್ನು ನೀವು ಬಳಸುತ್ತಿದ್ದರೆ, ನಿಮಗೆ ಈ ದೋಷ ಕಾಣಿಸುತ್ತದೆ.&lt;/p&gt;
+ &lt;p&gt;ದೋಷವನ್ನು ಪರಿಹರಿಸಲು, ನೀವು ತೆರೆಯಲು ಪ್ರಯತ್ನಿಸುತ್ತಿರುವ ಪುಟದಲ್ಲಿ &lt;strong&gt;ಸಂಪರ್ಕಿಸಿ&lt;/strong&gt; ಎಂಬುದನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ.&lt;/p&gt;
+ &lt;h3&gt;"ನಿಮ್ಮ ಗಡಿಯಾರದ ಸಮಯ ಹಿಂದೆ ಇದೆ ಅಥವಾ ಮುಂದೆ ಇದೆ" ಅಥವಾ "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್ ಅಥವಾ ಮೊಬೈಲ್ ಸಾಧನದ ದಿನಾಂಕ ಮತ್ತು ಸಮಯ ನಿಖರವಾಗಿರದಿದ್ದರೆ, ನೀವು ಈ ದೋಷವನ್ನು ನೋಡುವಿರಿ.&lt;/p&gt;
+ &lt;p&gt;ದೋಷವನ್ನು ಪರಿಹರಿಸಲು, ನಿಮ್ಮ ಸಾಧನದ ಗಡಿಯಾರವನ್ನು ತೆರೆಯಿರಿ. ದಿನಾಂಕ ಮತ್ತು ಸಮಯ ಸರಿಯಾಗಿರುವುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ.&lt;/p&gt;
+ &lt;h3&gt;"Chrome ಸುರಕ್ಷಿತವಾಗಿ ವೆಬ್‌ಗೆ ಸಂಪರ್ಕ ಹೊಂದದಂತೆ ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್‌ನಲ್ಲಿರುವ ಸಾಫ್ಟ್‌ವೇರ್ ತಡೆಯುತ್ತಿದೆ" (Windows ಕಂಪ್ಯೂಟರ್‌ಗಳಲ್ಲಿ ಮಾತ್ರ)&lt;/h3&gt;
+ &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;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;ಅನ್ವಯಿಸಿ&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="3615877443314183785">ಮಾನ್ಯವಾದ ಅವಧಿ-ಮುಕ್ತಾಯ ದಿನಾಂಕವನ್ನು ನಮೂದಿಸಿ</translation>
<translation id="36224234498066874">ಬ್ರೌಸ್ ಆಗುತ್ತಿರುವ ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸಿ...</translation>
<translation id="362276910939193118">ಪೂರ್ಣ ಇತಿಹಾಸ ತೋರಿಸಿ</translation>
@@ -401,7 +444,6 @@
<translation id="3778403066972421603">ಈ ಕಾರ್ಡ್‌ ಅನ್ನು ನಿಮ್ಮ Google ಖಾತೆ ಮತ್ತು ಈ ಸಾಧನದಲ್ಲಿ ಉಳಿಸಲು ಬಯಸುವಿರಾ?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">ಅವಧಿ-ಮುಕ್ತಾಯ <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929"><ph name="SITE" /> ಸೈಟ್‌ನಿಂದ</translation>
<translation id="382518646247711829">ನೀವು ಪ್ರಾಕ್ಸಿ ಸರ್ವರ್ ಬಳಸಿದರೆ...</translation>
<translation id="3828924085048779000">ಖಾಲಿ ಪಾಸ್‌ಫ್ರೇಸ್ ಅನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ.</translation>
<translation id="385051799172605136">ಹಿಂದೆ</translation>
@@ -415,6 +457,7 @@
<translation id="3945915738023014686">ಕ್ರ್ಯಾಷ್ ವರದಿ ಐಡಿ <ph name="CRASH_ID" />(ಸ್ಥಳೀಯ ಕ್ರ್ಯಾಷ್ ಐಡಿ: <ph name="CRASH_LOCAL_ID" />) ಅನ್ನು ಅಪ್‌ಲೋಡ್ ಮಾಡಲಾಗಿದೆ</translation>
<translation id="3949571496842715403">ಈ ಸರ್ವರ್ <ph name="DOMAIN" /> ಆಗಿದೆ ಎಂಬುದನ್ನು ಸಾಬೀತುಪಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ; ಅದರ ಸುರಕ್ಷತಾ ಪ್ರಮಾಣ ಪತ್ರವು ವಿಷಯವಸ್ತು ಪರ್ಯಾಯ ಹೆಸರುಗಳನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಿಲ್ಲ. ಇದು ತಪ್ಪು ಕಾನ್ಫಿಗರೇಶನ್‌ನಿಂದ ಅಥವಾ ಆಕ್ರಮಣಕಾರರು ನಿಮ್ಮ ಸಂಪರ್ಕದಲ್ಲಿ ಒಳನುಸುಳಿರುವುದರಿಂದ ಆಗಿರಬಹುದು.</translation>
<translation id="3949601375789751990">ನಿಮ್ಮ ಬ್ರೌಸಿಂಗ್ ಇತಿಹಾಸ ಇಲ್ಲಿ ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತದೆ</translation>
+<translation id="3950820424414687140">ಸೈನ್ ಇನ್</translation>
<translation id="3963721102035795474">ರೀಡರ್‌ ಮೋಡ್‌</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{ಯಾವುದೂ ಇಲ್ಲ}=1{1 ಸೈಟ್‌ನಿಂದ }one{# ಸೈಟ್‌ಗಳಿಂದ }other{# ಸೈಟ್‌ಗಳಿಂದ }}</translation>
<translation id="397105322502079400">ಎಣಿಸಲಾಗುತ್ತಿದೆ...</translation>
@@ -431,6 +474,7 @@
<translation id="4103249731201008433">ಸಾಧನದ ಸರಣಿಯ ಸಂಖ್ಯೆ ಅಮಾನ್ಯವಾಗಿದೆ</translation>
<translation id="410351446219883937">ಆಟೋಪ್ಲೇ</translation>
<translation id="4103763322291513355">ನಿಮ್ಮ ಸಿಸ್ಟಂ ನಿರ್ವಾಹಕರು ವಿಧಿಸಿರುವ ಕಪ್ಪುಪಟ್ಟಿಯ URLಗಳು ಮತ್ತು ಇತರ ನೀತಿಗಳನ್ನು ವೀಕ್ಷಿಸಲು &lt;strong&gt;chrome://policy&lt;/strong&gt; ಗೆ ಭೇಟಿ ನೀಡಿ.</translation>
+<translation id="4110652170750985508">ನಿಮ್ಮ ಪಾವತಿಯನ್ನು ಪರಿಶೀಲಿಸಿ</translation>
<translation id="4116663294526079822">ಈ ಸೈಟ್‌ನಲ್ಲಿ ಯಾವಾಗಲೂ ಅನುಮತಿಸಿ</translation>
<translation id="4117700440116928470">ನೀತಿಯ ವ್ಯಾಪ್ತಿಯು ಬೆಂಬಲಿತವಾಗಿಲ್ಲ.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 ಇತರೆ}one{# ಇತರೆ}other{# ಇತರೆ}}</translation>
@@ -457,7 +501,6 @@
<translation id="4269787794583293679">(ಯಾವುದು ಬಳಕೆದಾರಹೆಸರಿಲ್ಲ)</translation>
<translation id="4275830172053184480">ನಿಮ್ಮ ಸಾಧನವನ್ನು ಮರುಪ್ರಾರಂಭಿಸಿ</translation>
<translation id="4280429058323657511">, ಅವಧಿ ಮುಕ್ತಾಯ <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">ಲಾಗ್ ಇನ್</translation>
<translation id="4312866146174492540">ನಿರ್ಬಂಧಿಸು (ಡಿಫಾಲ್ಟ್)</translation>
<translation id="4325863107915753736">ಲೇಖನ ಕಂಡುಬರಲಿಲ್ಲ</translation>
<translation id="4326324639298822553">ನಿಮ್ಮ ಮುಕ್ತಾಯ ದಿನಾಂಕವನ್ನು ಪರಿಶೀಲಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ</translation>
@@ -479,14 +522,12 @@
<translation id="4515275063822566619">ಕಾರ್ಡ್‌ಗಳು ಮತ್ತು ವಿಳಾಸಗಳನ್ನು ನಿಮ್ಮ Chrome ಮತ್ತು ನಿಮ್ಮ Google ಖಾತೆಯಿಂದ (<ph name="ACCOUNT_EMAIL" />) ಪಡೆಯಲಾಗಿದೆ. ನೀವು ಅವುಗಳನ್ನು <ph name="BEGIN_LINK" />ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ<ph name="END_LINK" /> ನಿರ್ವಹಿಸಬಹುದು.</translation>
<translation id="4522570452068850558">ವಿವರಗಳು</translation>
<translation id="4552089082226364758">ಫ್ಲ್ಯಾಶ್‌</translation>
-<translation id="4554702541363482291"><ph name="SITE" /> ನಲ್ಲಿ ಎಂಬೆಡ್‌ ಮಾಡಲಾದ ಪುಟದಿಂದ</translation>
<translation id="4558551763791394412">ನಿಮ್ಮ ವಿಸ್ತರಣೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಪ್ರಯತ್ನಿಸಿ.</translation>
<translation id="457875822857220463">ವಿತರಣೆ</translation>
<translation id="4582800630050655161">ನಿಮ್ಮ Google ಖಾತೆಗೆ ಪ್ರವೇಶವನ್ನು ಕಳೆದುಕೊಳ್ಳಬಹುದು ಅಥವಾ ಗುರುತು ಕಳ್ಳತನ ನಿಂದನೆ ಅನುಭವಿಸಬಹುದು. ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಇದೀಗ ಬದಲಾಯಿಸುವಂತೆ Chromium ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ.</translation>
<translation id="4587425331216688090">Chrome ನಿಂದ ವಿಳಾಸವನ್ನು ತೆಗೆದುಹಾಕುವುದೇ?</translation>
<translation id="4592951414987517459">ಆಧುನಿಕ ಸೈಫರ್ ಸೂಟ್ ಬಳಸುವ ಮೂಲಕ <ph name="DOMAIN" /> ಗೆ ನಿಮ್ಮ ಸಂಪರ್ಕವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗಿದೆ.</translation>
<translation id="4594403342090139922">&amp;ಅಳಿಸುವುದನ್ನು ರದ್ದುಗೊಳಿಸಿ</translation>
-<translation id="4611292653554630842">ಲಾಗ್ ಇನ್</translation>
<translation id="4619615317237390068">ಇತರ ಸಾಧನಗಳಿಂದ ಟ್ಯಾಬ್‌ಗಳು</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">ಈ ಸರ್ವರ್ <ph name="DOMAIN" /> ಆಗಿದೆ ಎಂಬುದನ್ನು ಸಾಬೀತುಪಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ; ಅದರ ಸುರಕ್ಷತಾ ಪ್ರಮಾಣಪತ್ರದಲ್ಲಿ ಸಾಕಷ್ಟು ದೋಷಗಳಿವೆ. ಇದು ತಪ್ಪು ಕಾನ್ಫಿಗರೇಶನ್‌ನಿಂದ ಅಥವಾ ಆಕ್ರಮಣಕಾರರು ನಿಮ್ಮ ಸಂಪರ್ಕದಲ್ಲಿ ಒಳನುಸುಳಿರುವುದರಿಂದ ಆಗಿರಬಹುದು.</translation>
@@ -496,11 +537,9 @@
<translation id="4708268264240856090">ನಿಮ್ಮ ಸಂಪರ್ಕಕ್ಕೆ ಅಡ್ಡಿಯಾಗಿದೆ</translation>
<translation id="471880041731876836">ಈ ಸೈಟ್‌ ಗೆ ಭೇಟಿ ನೀಡಲು ನೀವು ಅನುಮತಿ ಹೊಂದಿಲ್ಲ</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows ನೆಟ್‌ವರ್ಕ್ ಡಯಾಗ್ನಾಸ್ಟಿಕ್ಸ್ ರನ್ ಮಾಡಲಾಗುತ್ತಿದೆ<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">ನಿಮ್ಮ ಪಾವತಿ</translation>
<translation id="4726672564094551039">ನೀತಿಗಳನ್ನು ಮರುಲೋಡ್ ಮಾಡಿ</translation>
<translation id="4728558894243024398">ಪ್ಲಾಟ್‌ಫಾರ್ಮ್</translation>
<translation id="4736825316280949806">Chromium ಮರುಪ್ರಾರಂಭಿಸಿ</translation>
-<translation id="4737498291095696011">ಈ ಪುಟದಿಂದ</translation>
<translation id="4744603770635761495">ಪ್ರದರ್ಶನಗೊಳ್ಳುವಂತಹ ಹಾದಿ</translation>
<translation id="4749685221585524849"><ph name="LAST_USED_MONTH" /> ಅಂತಿಮವಾಗಿ ಬಳಸಲಾಗಿದೆ</translation>
<translation id="4750917950439032686">ಈ ಸೈಟ್‌ಗೆ ನಿಮ್ಮ ಮಾಹಿತಿಯನ್ನು ಕಳುಹಿಸಿದಾಗ ಅದು (ಉದಾಹರಣೆಗೆ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಅಥವಾ ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್ ಸಂಖ್ಯೆಗಳು) ಖಾಸಗಿಯಾಗಿರುತ್ತದೆ.</translation>
@@ -519,16 +558,16 @@
<translation id="4850886885716139402">ವೀಕ್ಷಣೆ</translation>
<translation id="4854362297993841467">ಈ ವಿತರಣೆಯ ವಿಧಾನ ಲಭ್ಯವಿಲ್ಲ. ಬೇರೊಂದು ವಿಧಾನವನ್ನು ಪ್ರಯತ್ನಿಸಿ.</translation>
<translation id="4858792381671956233">ಈ ಸೈಟ್ ಅನ್ನು ಭೇಟಿ ಮಾಡಬಹುದು ಎಂದು ನಿಮ್ಮ ಪೋಷಕರಿಗೆ ನೀವು ಕೇಳಿರುವಿರಿ.</translation>
-<translation id="4871132632506079383"><ph name="SITE" /> ನಲ್ಲಿ ಎಂಬೆಡ್‌ ಮಾಡಲಾದ ಪುಟದಿಂದ</translation>
<translation id="4880827082731008257">ಹುಡುಕಾಟ ಇತಿಹಾಸ</translation>
+<translation id="4881695831933465202">ತೆರೆ</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">ಪ್ರಮಾಣೀಕರಣದ ಅವಶ್ಯಕತೆಯಿದೆ</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{ಮತ್ತು 1 ಹೆಚ್ಚಿನ ವೆಬ್ ಪುಟ}one{ಮತ್ತು # ಹೆಚ್ಚಿನ ವೆಬ್ ಪುಟಗಳು}other{ಮತ್ತು # ಹೆಚ್ಚಿನ ವೆಬ್ ಪುಟಗಳು}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947"><ph name="CREDIT_CARD" /> ಗೆ CVC ಅನ್ನು ನಮೂದಿಸಿ. ನೀವು ಖಚಿತಪಡಿಸಿದ ನಂತರ, ನಿಮ್ಮ Google ಪಾವತಿಗಳ ಖಾತೆಯಿಂದ ಕಾರ್ಡ್ ವಿವರಗಳನ್ನು ಈ ಸೈಟ್ ಜೊತೆಗೆ ಹಂಚಿಕೊಳ್ಳಲಾಗುತ್ತದೆ.</translation>
<translation id="4923417429809017348">ಗೊತ್ತಿಲ್ಲದ ಭಾಷೆಯಿಂದ <ph name="LANGUAGE_LANGUAGE" /> ಗೆ ಈ ಪುಟವನ್ನು ಭಾಷಾಂತರಿಸಲಾಗಿದೆ</translation>
<translation id="4923459931733593730">ಪಾವತಿ</translation>
<translation id="4926049483395192435">ನಿರ್ದಿಷ್ಟಪಡಿಸಬೇಕಾಗಿದೆ.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> ಹೀಗೆ ಹೇಳುತ್ತದೆ</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">ಕ್ರಿಯೆಗಳು</translation>
<translation id="4958444002117714549">ಪಟ್ಟಿಯನ್ನು ವಿಸ್ತರಿಸಿ</translation>
@@ -537,7 +576,6 @@
<translation id="5002932099480077015">ಸಕ್ರಿಯವಾಗಿದ್ದರೆ, ವೇಗವಾಗಿ ಫಾರ್ಮ್ ಭರ್ತಿ ಮಾಡಲು Chrome ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಕಾರ್ಡ್‌ನ ಪ್ರತಿಯನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ.</translation>
<translation id="5018422839182700155">ಈ ಪುಟವನ್ನು ತೆರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ</translation>
<translation id="5019198164206649151">ಕಳಪೆ ಸ್ಥಿತಿಯಲ್ಲಿ ಸಂಗ್ರಹಣೆಯನ್ನು ಹಿಂತಿರುಗಿಸಲಾಗಿದೆ</translation>
-<translation id="5020990877659450221">ಈ ಪುಟದಿಂದ</translation>
<translation id="5023310440958281426">ನಿಮ್ಮ ನಿರ್ವಾಹಕ ನೀತಿಗಳನ್ನು ಪರಿಶೀಲಿಸಿ</translation>
<translation id="5029568752722684782">ನಕಲು ತೆರವುಗೊಳಿಸು</translation>
<translation id="503069730517007720">"<ph name="SOFTWARE_NAME" />" ಗೆ ರೂಟ್ ಪ್ರಮಾಣಪತ್ರದ ಅಗತ್ಯವಿದೆ ಆದರೆ ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲಾಗಿಲ್ಲ. ಈ ಸಮಸ್ಯೆಯನ್ನು ಪರಿಹರಿಸಲು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು "<ph name="SOFTWARE_NAME" />" ಗಾಗಿ ಕಾನ್ಫಿಗರೇಶನ್ ಸೂಚನೆಗಳ ಕಡೆ ಗಮನವಿಡಬೇಕು. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -563,12 +601,12 @@
<translation id="5172758083709347301">ಯಂತ್ರ</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> ರಲ್ಲಿ ಇಲ್ಲವೆ? ಈ ದೋಷವನ್ನು ವರದಿ ಮಾಡಿ</translation>
<translation id="5190835502935405962">ಬುಕ್‌ಮಾರ್ಕ್‌ಗಳ ಬಾರ್</translation>
+<translation id="5201306358585911203">ಈ ಪುಟದಲ್ಲಿ ಎಂಬೆಡ್ ಮಾಡಲಾದ ಪುಟವು ಹೀಗೆ ಹೇಳುತ್ತದೆ</translation>
<translation id="5205222826937269299">ಹೆಸರು ಅವಶ್ಯವಾಗಿದೆ</translation>
<translation id="5222812217790122047">ಇಮೇಲ್ ಅಗತ್ಯವಿದೆ</translation>
<translation id="522700295135997067">ಈ ಸೈಟ್‌ ಕಳವು ಮಾಡಿರುವ ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಹೊಂದಿರಬಹುದು</translation>
<translation id="5230733896359313003">ಶಿಪ್ಪಿಂಗ್ ವಿಳಾಸ</translation>
<translation id="5251803541071282808">ಮೇಘ</translation>
-<translation id="5277279256032773186">ಕೆಲಸದಲ್ಲಿ Chrome ಬಳಸುತ್ತಿರುವಿರಾ? ತಮ್ಮ ಉದ್ಯೋಗಿಗಳಿಗಾಗಿ ವ್ಯವಹಾರಗಳಲ್ಲಿ Chrome ಸೆಟ್ಟಿಂಗ್‌ಗಳು ನಿರ್ವಹಿಸಬಹುದು. ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />ಈ ಹಂತಗಳನ್ನು ಅನುಸರಿಸಿ ತಾತ್ಕಾಲಿಕವಾಗಿ ಸಾಫ್ಟ್‌ವೇರ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದರೆ ನೀವು ವೆಬ್‌ ಅನ್ನು ಪಡೆದುಕೊಳ್ಳಬಹುದಾಗಿದೆ. ನಿಮಗೆ ನಿರ್ವಾಹಕರ ಸವಲತ್ತುಗಳ ಅಗತ್ಯವಿದೆ.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
<ph name="LIST_ITEM" />ಕ್ಲಿಕ್ ಮಾಡಿ <ph name="BEGIN_BOLD" />ಪ್ರಾರಂಭಿಸಿ<ph name="END_BOLD" />, ನಂತರ ಹುಡುಕಿ ಮತ್ತು <ph name="BEGIN_BOLD" />"ಸ್ಥಳೀಯ ಸೇವೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ"<ph name="END_BOLD" /> ಆಯ್ಕೆಮಾಡಿ
@@ -629,7 +667,6 @@
<translation id="5610142619324316209">ಸಂಪರ್ಕವನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ</translation>
<translation id="5610807607761827392">ನೀವು ಕಾರ್ಡ್‌ಗಳು ಮತ್ತು ವಿಳಾಸಗಳನ್ನು <ph name="BEGIN_LINK" />ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ<ph name="END_LINK" /> ನಿರ್ವಹಿಸಬಹುದು.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> ನಿಮ್ಮನ್ನು ತೀರಾ ಹೆಚ್ಚು ಬಾರಿ ಮರುನಿರ್ದೇಶಿಸಿದೆ.</translation>
-<translation id="5622887735448669177">ನೀವು ಈ ಸೈಟ್ ತೊರೆಯಲು ಬಯಸುತ್ತೀರಾ?</translation>
<translation id="5629630648637658800">ನೀತಿಯ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಲೋಡ್ ಮಾಡುವಲ್ಲಿ ವಿಫಲವಾಗಿದೆ</translation>
<translation id="5631439013527180824">ಅಮಾನ್ಯವಾದ ಸಾಧನ ನಿರ್ವಹಣೆ ಟೋಕನ್</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>
@@ -652,7 +689,6 @@
<translation id="5786044859038896871">ನಿಮ್ಮ ಕಾರ್ಡ್ ಮಾಹಿತಿ ಭರ್ತಿ ಮಾಡಲು ನೀವು ಬಯಸುವಿರಾ?</translation>
<translation id="5803412860119678065">ನಿಮ್ಮ <ph name="CARD_DETAIL" /> ಭರ್ತಿ ಮಾಡಲು ನೀವು ಬಯಸುವಿರಾ?</translation>
<translation id="5810442152076338065">ಬಳಕೆಯಲ್ಲಿಲ್ಲದ ಸೈಫರ್ ಸೂಟ್ ಬಳಸುವ ಮೂಲಕ <ph name="DOMAIN" /> ಗೆ ನಿಮ್ಮ ಸಂಪರ್ಕವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗಿದೆ.</translation>
-<translation id="5810928923025889964">ಈ ಪುಟದಲ್ಲಿ ಎಂಬೆಡ್ ಮಾಡಲಾದ ಪುಟದಿಂದ</translation>
<translation id="5813119285467412249">&amp;ಸೇರಿಸುವುದನ್ನು ಮತ್ತೆಮಾಡು</translation>
<translation id="5838278095973806738">ಈ ಸೈಟ್‌ನಲ್ಲಿ ನೀವು ಯಾವುದೇ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯನ್ನು (ಉದಾಹರಣೆಗೆ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಅಥವಾ ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್‌ಗಳು) ನಮೂದಿಸಬಾರದು, ಏಕೆಂದರೆ ಅದು ದಾಳಿಕೋರರ ಮೂಲಕ ಕಳುವಾಗಬಹುದು.</translation>
<translation id="5866257070973731571">ಫೋನ್ ಸಂಖ್ಯೆಯನ್ನು ಸೇರಿಸಿ</translation>
@@ -725,21 +761,19 @@
<translation id="6446608382365791566">ಇನ್ನಷ್ಟು ಮಾಹಿತಿಯನ್ನು ಸೇರಿಸಿ</translation>
<translation id="6447842834002726250">ಕುಕೀಸ್</translation>
<translation id="6451458296329894277">ಮರುಸಲ್ಲಿಕೆ ಫಾರ್ಮ್ ಅನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ</translation>
-<translation id="6456339708790392414">ನಿಮ್ಮ ಪಾವತಿ</translation>
<translation id="647261751007945333">ಸಾಧನ ನೀತಿಗಳು</translation>
<translation id="6477321094435799029">ಈ ಪುಟದಲ್ಲಿ ಅಸಹಜ ಕೋಡ್ ಅನ್ನು Chrome ಪತ್ತೆಹಚ್ಚಿದೆ ಮತ್ತು ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು (ಉದಾಹರಣೆಗೆ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಫೋನ್‌ ಸಂಖ್ಯೆಗಳು ಮತ್ತು ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್‌ಗಳು) ರಕ್ಷಿಸಲು ಅದನ್ನು ನಿರ್ಬಂಧಿಸಿದೆ.</translation>
<translation id="6489534406876378309">ವಿಫಲತೆಗಳನ್ನು ಅಪ್‌ಲೋಡ್‌ ಮಾಡುವುದನ್ನು ಪ್ರಾರಂಭಿಸು</translation>
<translation id="6507833130742554667">ಕ್ರೆಡಿಟ್‌ ಮತ್ತು ಡೆಬಿಟ್ ಕಾರ್ಡ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲಾಗುತ್ತದೆ.</translation>
<translation id="6508722015517270189">Chrome ಮರುಪ್ರಾರಂಭಿಸಿ</translation>
-<translation id="6521373090216409766">ನೀವು ಈ ಸೈಟ್ ಮರುಲೋಡ್ ಮಾಡಲು ಬಯಸುವಿರಾ?</translation>
<translation id="6529602333819889595">&amp;ಅಳಿಸುವುದನ್ನು ಮತ್ತೆಮಾಡು</translation>
<translation id="6534179046333460208">ಭೌತಿಕ ವೆಬ್ ಸಲಹೆಗಳು</translation>
<translation id="6550675742724504774">ಆಯ್ಕೆಗಳು</translation>
-<translation id="6556239504065605927">ಸುರಕ್ಷಿತ ಸಂಪರ್ಕ</translation>
<translation id="6556915248009097796">ಅವಧಿ ಮೀರುವ ಸಮಯ: <ph name="EXPIRATION_DATE_ABBR" />, <ph name="LAST_USED_DATE_NO_DETAIL" /> ಅಂತಿಮವಾಗಿ ಬಳಸಲಾಗಿದೆ</translation>
<translation id="6563469144985748109">ನಿಮ್ಮ ಮ್ಯಾನೇಜರ್ ಇನ್ನೂ ಇದನ್ನು ಅಂಗೀಕರಿಸಿಲ್ಲ</translation>
<translation id="6569060085658103619">ನೀವು ವಿಸ್ತರಣೆ ಪುಟವನ್ನು ವೀಕ್ಷಿಸುತ್ತಿರುವಿರಿ</translation>
<translation id="6596325263575161958">ಎನ್‌ಕ್ರಿಫ್ಶನ್ ಆಯ್ಕೆಗಳು</translation>
+<translation id="6604181099783169992">ಚಲನೆ ಅಥವಾ ಬೆಳಕಿನ ಸೆನ್ಸರ್‌ಗಳು</translation>
<translation id="6624427990725312378">ಸಂಪರ್ಕ ಮಾಹಿತಿ</translation>
<translation id="6626291197371920147">ಮಾನ್ಯವಾದ ಕಾರ್ಡ್ ಸಂಖ್ಯೆಯನ್ನು ಸೇರಿಸಿ</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> ಹುಡುಕಾಟ</translation>
@@ -811,6 +845,7 @@
<translation id="7275334191706090484">ನಿರ್ವಹಿಸಿದ ಬುಕ್‌ಮಾರ್ಕ್‌ಗಳು</translation>
<translation id="7298195798382681320">ಶಿಫಾರಸು ಮಾಡಲಾಗಿದೆ</translation>
<translation id="7309308571273880165">ಕ್ರ್ಯಾಶ್ ವರದಿಯನ್ನು <ph name="CRASH_TIME" /> ರಲ್ಲಿ ಸೆರೆಹಿಡಿಯಲಾಗಿದೆ (ಬಳಕೆದಾರರ ಮೂಲಕ ವಿನಂತಿಸಲಾದ ಅಪ್‌ಲೋಡ್ ಅನ್ನು, ಇನ್ನೂ ಅಪ್‌ಲೋಡ್ ಮಾಡಿಲಾಗಿಲ್ಲ)</translation>
+<translation id="7320336641823683070">ಸಂಪರ್ಕ ಸಹಾಯ</translation>
<translation id="7334320624316649418">&amp;ಮರುಕ್ರಮಗೊಳಿಸುವುದನ್ನು ಮತ್ತೆಮಾಡು</translation>
<translation id="733923710415886693">ಪ್ರಮಾಣಪತ್ರ ಪಾರದರ್ಶಕತೆಯ ಮೂಲಕ ಸರ್ವರ್ ಪ್ರಮಾಣಪತ್ರವನ್ನು ಬಹಿರಂಗಪಡಿಸಲಾಗಿಲ್ಲ.</translation>
<translation id="7353601530677266744">ಆದೇಶ ಸಾಲು</translation>
@@ -895,6 +930,7 @@
<translation id="782886543891417279">ನೀವು ಬಳಸುತ್ತಿರುವ ವೈ-ಫೈ (<ph name="WIFI_NAME" />) ಅದರ ಲಾಗಿನ್ ಪುಟಕ್ಕೆ ನೀವು ಭೇಟಿ ನೀಡುವ ಅಗತ್ಯವಿದೆ.</translation>
<translation id="785549533363645510">ಆದರೆ, ನೀವು ಅದೃಶ್ಯರಾಗಿರುವುದಿಲ್ಲ. ಅಜ್ಞಾತವಾಗಿ ಹೋಗುವುದರಿಂದ ನಿಮ್ಮ ಉದ್ಯೋಗದಾತರು, ನಿಮ್ಮ ಇಂಟರ್ನೆಟ್ ಸೇವಾ ಪೂರೈಕೆದಾರರು ಇಲ್ಲವೇ ನೀವು ಭೇಟಿ ನೀಡುವ ವೆಬ್‌ಸೈಟ್‌ಗಳಿಂದ ನಿಮ್ಮ ಬ್ರೌಸಿಂಗ್ ಮರೆ ಮಾಡಲಾಗುವುದಿಲ್ಲ.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">ಸೈಟ್‌ ಅನ್ನು ತೊರೆಯುವುದೇ?</translation>
<translation id="7878176543348854470">ಡೆಬಿಟ್ ಮತ್ತು ಪ್ರೀಪೇಯ್ಡ್ ಕಾರ್ಡ್‌ಗಳನ್ನು ಸಮ್ಮತಿಸಲಾಗಿದೆ.</translation>
<translation id="7878562273885520351">ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಸುಲಭವಾಗಿ ಪತ್ತೆ ಮಾಡಬಹುದು</translation>
<translation id="7887683347370398519">ನಿಮ್ಮ CVC ಅನ್ನು ಪರಿಶೀಲಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ</translation>
@@ -917,6 +953,7 @@
<translation id="8041940743680923270">ಜಾಗತಿಕ ಡಿಫಾಲ್ಟ್ ಬಳಸಿ (ಕೇಳಿ)</translation>
<translation id="8042918947222776840">ಪಿಕಪ್ ವಿಧಾನವನ್ನು ಆರಿಸಿ</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" ಅನ್ನು ಸರಿಯಾಗಿ ಕಾನ್ಫಿಗರ್ ಮಾಡಲಾಗಿಲ್ಲ. ಸಾಮಾನ್ಯವಾಗಿ ಸಮಸ್ಯೆಯನ್ನು ಪರಿಹರಿಸಲು "<ph name="SOFTWARE_NAME" />" ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲಾಗುತ್ತಿದೆ. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">ಸೈಟ್ ಅನ್ನು ಪುನಃ ಲೋಡ್ ಮಾಡಬೇಕೇ?</translation>
<translation id="8088680233425245692">ಲೇಖನವನ್ನು ವೀಕ್ಷಿಸಲು ವಿಫಲವಾಗಿದೆ.</translation>
<translation id="8091372947890762290">ಸರ್ವರ್‌ನಲ್ಲಿ ಸಕ್ರಿಯತೆ ಬಾಕಿ ಉಳಿದಿದೆ</translation>
<translation id="8094917007353911263">ನೀವು ಬಳಸುತ್ತಿರುವ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ನೀವು <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> ಅನ್ನು ಭೇಟಿ ನೀಡುವ ಅಗತ್ಯವಿದೆ.</translation>
@@ -932,6 +969,7 @@
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" ID ಜೊತೆಗಿನ ವಿಸ್ತರಣೆಗೆ ಅಮಾನ್ಯವಾದ ಅಪ್‌ಡೇಟ್‌‌ URL.</translation>
<translation id="8202097416529803614">ಆರ್ಡರ್ ಸಾರಾಂಶ</translation>
<translation id="8205463626947051446">ಈ ಸೈಟ್ ಸಾಮಾನ್ಯವಾಗಿ ಅತಿಕ್ರಮಣಕಾರಿಯಾಗಿರುವ ಜಾಹೀರಾತುಗಳನ್ನು ತೋರಿಸುತ್ತದೆ</translation>
+<translation id="8211406090763984747">ಸಂಪರ್ಕ ಸುರಕ್ಷಿತವಾಗಿದೆ</translation>
<translation id="8218327578424803826">ನಿಯೋಜಿಸಲಾದ ಸ್ಥಳ:</translation>
<translation id="8225771182978767009">ಈ ಕಂಪ್ಯೂಟರ್ ಹೊಂದಿಸಿರುವ ವ್ಯಕ್ತಿಯು ಈ ಸೈಟ್ ನಿರ್ಬಂಧಿಸಲು ಆಯ್ಕೆಮಾಡಿದ್ದಾರೆ.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -943,6 +981,7 @@
<translation id="825929999321470778">ಉಳಿಸಿದ ಎಲ್ಲ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ತೋರಿಸಿ</translation>
<translation id="8261506727792406068">ಅಳಿಸಿ</translation>
<translation id="8267698848189296333"><ph name="USERNAME" /> ನಂತೆ ಸೈನ್ ಇನ್ ಮಾಡಲಾಗುತ್ತಿದೆ</translation>
+<translation id="8286036467436129157">ಸೈನ್ ಇನ್</translation>
<translation id="8288807391153049143">ಪ್ರಮಾಣಪತ್ರವನ್ನು ತೋರಿಸಿ</translation>
<translation id="8289355894181816810">ಇದರ ಅರ್ಥವೇನೆಂದು ನಿಮಗೆ ಖಚಿತವಾಗದಿದ್ದರೆ ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ.</translation>
<translation id="8293206222192510085">ಬುಕ್‌ಮಾರ್ಕ್ ಸೇರಿಸು</translation>
@@ -994,6 +1033,7 @@
<translation id="874846938927089722">ಸ್ವೀಕೃತ ಕ್ರೆಡಿಟ್ ಮತ್ತು ಪ್ರೀಪೇಯ್ಡ್ ಕಾರ್ಡ್‌ಗಳು</translation>
<translation id="8759274551635299824">ಈ ಕಾರ್ಡ್‌ನ ಅವಧಿ ಮುಕ್ತಾಯವಾಗಿದೆ</translation>
<translation id="8761567432415473239">Google ಸುರಕ್ಷಿತ ಬ್ರೌಸಿಂಗ್‌ ಇತ್ತೀಚಿಗೆ <ph name="SITE" /> ನಲ್ಲಿ <ph name="BEGIN_LINK" />ಹಾನಿಕಾರಕ ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ಕಂಡುಹಿಡಿದಿದೆ<ph name="END_LINK" />.</translation>
+<translation id="8763927697961133303">USB ಸಾಧನ</translation>
<translation id="8790007591277257123">&amp;ಅಳಿಸುವುದನ್ನು ಮತ್ತೆಮಾಡು</translation>
<translation id="8800988563907321413">ನಿಮ್ಮ ಸಮೀಪದ ವೆಬ್ ಪುಟದ ಸಲಹೆಗಳು ಇಲ್ಲಿ ಗೋಚರಿಸುತ್ತವೆ</translation>
<translation id="8820817407110198400">ಬುಕ್‌ಮಾರ್ಕ್‌ಗಳು</translation>
diff --git a/chromium/components/strings/components_strings_ko.xtb b/chromium/components/strings/components_strings_ko.xtb
index bf68c370dda..3045b3dd79a 100644
--- a/chromium/components/strings/components_strings_ko.xtb
+++ b/chromium/components/strings/components_strings_ko.xtb
@@ -21,7 +21,7 @@
<translation id="1113869188872983271">재정렬 실행 취소(&amp;U)</translation>
<translation id="1126551341858583091">로컬 저장소는 <ph name="CRASH_SIZE" />입니다.</translation>
<translation id="112840717907525620">정책 캐시 확인</translation>
-<translation id="1132774398110320017">Chrome 자동완성 설정...</translation>
+<translation id="1132774398110320017">Chrome 자동 완성 설정...</translation>
<translation id="1150979032973867961">이 서버가 <ph name="DOMAIN" />임을 입증할 수 없으며 컴퓨터의 운영체제에서 신뢰하는 보안 인증서가 아닙니다. 서버를 잘못 설정했거나 불법 사용자가 연결을 가로채고 있기 때문일 수 있습니다.</translation>
<translation id="1151972924205500581">비밀번호를 입력해야 합니다.</translation>
<translation id="1152921474424827756"><ph name="URL" />의 <ph name="BEGIN_LINK" />캐시된 사본<ph name="END_LINK" />에 액세스</translation>
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">인쇄(&amp;P)</translation>
<translation id="1181037720776840403">삭제</translation>
<translation id="1184214524891303587">발생 가능성이 있는 보안 문제의 세부정보를 Google에 <ph name="BEGIN_WHITEPAPER_LINK" />자동으로 보고<ph name="END_WHITEPAPER_LINK" />합니다. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">결제가 완료되지 않음</translation>
<translation id="1201402288615127009">다음</translation>
<translation id="1201895884277373915">이 사이트에서 더보기</translation>
<translation id="1206967143813997005">잘못된 초기 서명</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575"><ph name="CRASH_TIME" />에 캡처된 비정상 종료 보고서(아직 업로드 또는 무시되지 않음)</translation>
<translation id="1270502636509132238">픽업 방법</translation>
<translation id="1285320974508926690">이 사이트 번역 안함</translation>
+<translation id="1294154142200295408">명령줄 변형</translation>
<translation id="129553762522093515">최근에 닫은 탭</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />쿠키 삭제해 보기<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">다음의 관계자는 내 활동 내역을 <ph name="BEGIN_EMPHASIS" />확인할 수도 있습니다<ph name="END_EMPHASIS" />.
@@ -57,7 +57,7 @@
<ph name="END_LIST" /></translation>
<translation id="1339601241726513588">등록 도메인:</translation>
<translation id="1340482604681802745">수령 주소</translation>
-<translation id="1344588688991793829">Chromium 자동완성 설정...</translation>
+<translation id="1344588688991793829">Chromium 자동 완성 설정...</translation>
<translation id="1348198688976932919">방문하려는 사이트에 위험한 앱이 있습니다.</translation>
<translation id="1374468813861204354">제안사항</translation>
<translation id="1375198122581997741">버전 정보</translation>
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">사용 가능한 신용카드 및 직불카드</translation>
<translation id="1519264250979466059">생성 날짜</translation>
<translation id="1527263332363067270">연결 대기 중...</translation>
+<translation id="1532118530259321453">이 페이지 내용:</translation>
<translation id="153384715582417236">새 콘텐츠가 없습니다.</translation>
<translation id="154408704832528245">배달 주소 선택</translation>
<translation id="1549470594296187301">이 기능을 이용하려면 자바스크립트를 사용하도록 설정해야 합니다.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />프록시 및 방화벽 확인<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">우편번호</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{제안 1개}other{제안 #개}}</translation>
-<translation id="2065985942032347596">인증 필요</translation>
<translation id="2079545284768500474">실행취소</translation>
<translation id="20817612488360358">시스템 프록시 설정이 사용하도록 설정되었지만 명시적 프록시 설정도 지정되어 있습니다.</translation>
<translation id="2091887806945687916">소리</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">결제 취소</translation>
<translation id="2147827593068025794">백그라운드 동기화</translation>
<translation id="2148613324460538318">카드 추가</translation>
-<translation id="2149973817440762519">북마크 수정</translation>
<translation id="2154054054215849342">도메인에 대해 동기화를 사용할 수 없습니다.</translation>
<translation id="2154484045852737596">카드 수정</translation>
<translation id="2166049586286450108">전체 관리자 액세스</translation>
@@ -235,7 +234,7 @@
<translation id="2704283930420550640">값이 형식과 일치하지 않습니다.</translation>
<translation id="2704951214193499422">현재 Chromium에서 카드를 확인할 수 없습니다. 나중에 다시 시도해 주세요.</translation>
<translation id="2705137772291741111">사이트의 저장된(캐시된) 사본을 읽을 수 없습니다.</translation>
-<translation id="2709516037105925701">자동완성</translation>
+<translation id="2709516037105925701">자동 완성</translation>
<translation id="2710942282213947212">컴퓨터에 설치된 소프트웨어로 인해 Chromium이 안전하게 웹에 접속할 수 없음</translation>
<translation id="2712173769900027643">권한 요청</translation>
<translation id="2720342946869265578">근처</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">수령 주소 선택</translation>
<translation id="2740531572673183784">확인</translation>
<translation id="2742870351467570537">선택한 항목 삭제</translation>
-<translation id="2744590937989388266">출처: 이 페이지에 삽입된 페이지</translation>
<translation id="277133753123645258">배송 방법</translation>
<translation id="277499241957683684">기기 기록 없음</translation>
<translation id="2784949926578158345">연결이 재설정되었습니다.</translation>
<translation id="2788784517760473862">사용 가능한 신용카드</translation>
<translation id="2794233252405721443">차단된 사이트</translation>
-<translation id="2795286477369100655">이 사이트에서 나가시겠습니까?</translation>
<translation id="2799020568854403057">방문하려는 사이트에 유해한 앱이 있습니다.</translation>
<translation id="2803306138276472711">최근 Google 세이프 브라우징이 <ph name="SITE" />에서 <ph name="BEGIN_LINK" />멀웨어를 감지<ph name="END_LINK" />했습니다. 평소에 안전한 웹사이트도 멀웨어에 감염될 때가 있습니다.</translation>
<translation id="2824775600643448204">주소창 및 검색창</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">목록 항목 '<ph name="ENTRY_INDEX" />': <ph name="ERROR" /></translation>
<translation id="301521992641321250">자동으로 차단됨</translation>
<translation id="3024663005179499861">잘못된 정책 유형</translation>
-<translation id="3032412215588512954">이 사이트를 새로고침하시겠습니까?</translation>
<translation id="3037605927509011580">앗, 이런!</translation>
<translation id="3039538478787849737">카드를 Google에 저장하시겠어요?</translation>
<translation id="3041612393474885105">인증서 정보</translation>
@@ -310,6 +306,7 @@
프록시 서버가 작동하는지 확인하세요. 프록시 서버를 사용하지 않으려면
다음 단계를 따르세요.
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="SERVER_NAME" />의 <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">결제 취소</translation>
<translation id="3207960819495026254">북마크됨</translation>
<translation id="3209375525920864198">올바른 세션 이름을 입력하세요.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">관리자가 차단 해제할 수 있습니다.</translation>
<translation id="3566021033012934673">연결이 비공개로 설정되어 있지 않습니다.</translation>
<translation id="3574305903863751447"><ph name="COUNTRY" /> <ph name="STATE" />, <ph name="CITY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" />에 삽입된 페이지 내용:</translation>
<translation id="358285529439630156">신용카드 및 선불카드를 사용할 수 있습니다.</translation>
<translation id="3582930987043644930">이름 추가</translation>
<translation id="3583757800736429874">이동 다시 실행(&amp;R)</translation>
<translation id="3586931643579894722">세부정보 숨기기</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;연결 문제해결&lt;/h1&gt;
+ &lt;p&gt;웹사이트 방문 시 오류 메시지가 표시되면 다음 해결책을 사용해 보세요.&lt;/p&gt;
+ &lt;h2&gt;일반적인 연결 오류 해결 방법&lt;/h2&gt;
+ &lt;p&gt;웹사이트를 방문하려고 하는데 열리지 않으면 우선 이 문제해결 단계에 따라 오류를 해결해 보세요.&lt;p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;웹 주소에 오타가 없는지 확인합니다.&lt;/li&gt;
+ &lt;li&gt;인터넷 연결에 문제가 없는지 확인합니다.&lt;/li&gt;
+ &lt;li&gt;웹사이트 소유자에게 문의합니다.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;특정 오류 메시지에 관한 도움말 보기&lt;/h2&gt;
+ &lt;h3&gt;’연결이 비공개로 설정되어 있지 않습니다’, ‘NET::ERR_CERT_AUTHORITY_INVALID’, ‘ERR_CERT_COMMON_NAME_INVALID', ‘NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM’ 또는 ‘SSL 인증서 오류’&lt;/h3&gt;
+ &lt;h4&gt;1단계: 포털에 로그인하기&lt;/h4&gt;
+ &lt;p&gt;카페 또는 공항과 같은 장소에서 Wi-Fi 네트워크에 연결하려면 로그인해야 합니다. 로그인 페이지를 보려면 &lt;code&gt;http://&lt;/code&gt;를 사용하는 페이지로 이동하세요.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;&lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;과 같이 &lt;code&gt;http://&lt;/code&gt;로 시작하는 웹사이트로 이동합니다.&lt;/li&gt;
+ &lt;li&gt;로그인 페이지가 열리면 로그인하여 인터넷을 사용합니다.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;2단계: 시크릿 모드로 페이지 열기(컴퓨터만 해당)&lt;/h4&gt;
+ &lt;p&gt;시크릿 창에서 방문하려는 페이지를 엽니다.&lt;/p&gt;
+ &lt;p&gt;페이지가 열리면 Chrome 확장 프로그램이 제대로 작동하지 않고 있는 것입니다. 오류를 해결하려면 확장 프로그램을 사용 중지해야 합니다.&lt;/p&gt;
+ &lt;h4&gt;3단계: 운영체제 업데이트하기&lt;/h4&gt;
+ &lt;p&gt;기기가 최신 상태인지 확인합니다.&lt;/p&gt;
+ &lt;h4&gt;4단계: 바이러스 백신 프로그램을 일시적으로 사용 중지하기&lt;/h4&gt;
+ &lt;p&gt;’HTTPS 보호’ 또는 ‘HTTPS 검사’를 제공하는 바이러스 백신 소프트웨어를 사용 중이면 바이러스 백신이 Chrome 보안 기능을 방해하기 때문에 이 오류가 표시됩니다.&lt;/p&gt;
+ &lt;p&gt;문제를 해결하려면 바이러스 백신 소프트웨어를 사용 중지하세요. 소프트웨어를 사용 중지한 후 페이지가 작동하면 보안 사이트를 사용할 때는 이 소프트웨어를 사용 중지해야 합니다.&lt;/p&gt;
+ &lt;p&gt;작업을 완료한 후 다시 바이러스 백신 프로그램을 사용 설정하세요.&lt;/p&gt;
+ &lt;h4&gt;5단계: 추가 도움 받기&lt;/h4&gt;
+ &lt;p&gt;계속해서 오류가 표시되면 웹사이트 소유자에게 문의하세요.&lt;/p&gt;
+ &lt;h3&gt;’네트워크에 연결’&lt;/h3&gt;
+ &lt;p&gt;온라인에 접속하기 위해 로그인해야 하는 Wi-Fi 포털을 사용하면 이 오류가 표시됩니다.&lt;/p&gt;
+ &lt;p&gt;이 오류를 해결하려면 열고자 하는 페이지에서 &lt;strong&gt;연결&lt;/strong&gt;을 클릭합니다.&lt;/p&gt;
+ &lt;h3&gt;'시간이 너무 먼 과거로 설정되어 있습니다', '시간이 너무 먼 미래로 설정되어 있습니다' 또는 ‘NET::ERR_CERT_DATE_INVALID’&lt;/h3&gt;
+ &lt;p&gt;컴퓨터 또는 휴대기기의 날짜 및 시간이 잘못 설정되어 있으면 이 오류가 표시됩니다.&lt;/p&gt;
+ &lt;p&gt;이 오류를 해결하려면 기기에서 시계를 연 다음 시간과 날짜가 정확한지 확인하세요.&lt;/p&gt;
+ &lt;h3&gt;’컴퓨터의 소프트웨어로 인해 Chrome이 안전하게 웹에 접속할 수 없습니다.’(Windows 컴퓨터에만 해당)&lt;/h3&gt;
+ &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;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;를 클릭합니다.
+ &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="3615877443314183785">올바른 만료일을 입력하세요.</translation>
<translation id="36224234498066874">인터넷 사용 기록 삭제...</translation>
<translation id="362276910939193118">방문 기록 전체 보기</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">이 카드를 Google 계정과 이 기기에 저장하시겠습니까?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">만료: <ph name="EXPIRATION_YEAR" />년 <ph name="EXPIRATION_MONTH" />월</translation>
-<translation id="3800436529451849929">출처: <ph name="SITE" /></translation>
<translation id="382518646247711829">프록시 서버를 사용하는 경우</translation>
<translation id="3828924085048779000">암호를 빈 칸으로 두어서는 안 됩니다.</translation>
<translation id="385051799172605136">뒤로</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">비정상 종료 보고서 ID <ph name="CRASH_ID" /> 업로드됨(로컬 비정상 종료 ID: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">보안 인증서에 주체 대체 이름(SAN)이 지정되어 있지 않아 이 서버가 <ph name="DOMAIN" />임을 입증할 수 없습니다. 서버를 잘못 설정했거나 공격자가 연결을 가로채고 있기 때문일 수도 있습니다.</translation>
<translation id="3949601375789751990">인터넷 사용 기록이 여기에 표시됩니다.</translation>
+<translation id="3950820424414687140">로그인</translation>
<translation id="3963721102035795474">리더 모드</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{없음}=1{사이트 1개 }other{사이트 #개 }}</translation>
<translation id="397105322502079400">계산 중...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">기기 일련번호가 잘못됨</translation>
<translation id="410351446219883937">자동재생</translation>
<translation id="4103763322291513355">차단된 URL 및 시스템 관리자가 설정한 기타 정책 목록을 확인하려면 &lt;strong&gt;chrome://policy&lt;/strong&gt;를 방문하세요.</translation>
+<translation id="4110652170750985508">결제 검토</translation>
<translation id="4116663294526079822">이 사이트에서 항상 허용</translation>
<translation id="4117700440116928470">지원되지 않는 정책 범위입니다.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{외 1개}other{외 #개}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(사용자 이름 없음)</translation>
<translation id="4275830172053184480">기기 다시 시작</translation>
<translation id="4280429058323657511">, 만료일 <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">로그인</translation>
<translation id="4312866146174492540">차단(기본값)</translation>
<translation id="4325863107915753736">도움말을 찾지 못했습니다.</translation>
<translation id="4326324639298822553">만료일을 확인한 후 다시 시도해 주세요.</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">카드와 주소는 Chrome 및 Google 계정(<ph name="ACCOUNT_EMAIL" />)에서 가져왔습니다. 이 정보는 <ph name="BEGIN_LINK" />설정<ph name="END_LINK" />에서 관리할 수 있습니다.</translation>
<translation id="4522570452068850558">세부정보</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">출처: <ph name="SITE" />에 삽입된 페이지</translation>
<translation id="4558551763791394412">확장 프로그램 사용 중지해 보기</translation>
<translation id="457875822857220463">배송</translation>
<translation id="4582800630050655161">Google 계정에 액세스할 수 없게 되거나 신원 도용이 발생할 수도 있습니다. 따라서 지금 비밀번호를 변경하는 것이 좋습니다.</translation>
<translation id="4587425331216688090">Chrome에서 주소를 삭제하시겠습니까?</translation>
<translation id="4592951414987517459"><ph name="DOMAIN" />에 대한 연결은 최신 암호화 기술을 사용하여 암호화됩니다.</translation>
<translation id="4594403342090139922">삭제 실행 취소(&amp;U)</translation>
-<translation id="4611292653554630842">로그인</translation>
<translation id="4619615317237390068">다른 기기의 탭</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">이 서버가 <ph name="DOMAIN" />임을 입증할 수 없으며 서버의 보안 인증서에 오류가 있습니다. 서버를 잘못 설정했거나 불법 사용자가 연결을 가로채고 있기 때문일 수 있습니다.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">연결이 끊김</translation>
<translation id="471880041731876836">이 사이트에 방문할 수 있는 권한이 없습니다.</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows 네트워크 진단 프로그램 실행<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">내 결제</translation>
<translation id="4726672564094551039">정책 새로고침</translation>
<translation id="4728558894243024398">플랫폼</translation>
<translation id="4736825316280949806">Chromium 다시 시작</translation>
-<translation id="4737498291095696011">출처: 이 페이지</translation>
<translation id="4744603770635761495">실행 가능 경로</translation>
<translation id="4749685221585524849">마지막 사용일: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">비밀번호나 신용카드 번호 등의 정보는 비공개 상태로 이 사이트에 전송됩니다.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">보기</translation>
<translation id="4854362297993841467">사용할 수 없는 배달 방법입니다. 다른 방법을 선택하세요.</translation>
<translation id="4858792381671956233">이 사이트를 방문해도 괜찮은지 부모님께 문의했습니다.</translation>
-<translation id="4871132632506079383">출처: <ph name="SITE" />에 삽입된 페이지</translation>
<translation id="4880827082731008257">기록 검색</translation>
+<translation id="4881695831933465202">열기</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">인증 필요</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{외 웹페이지 1개}other{외 웹페이지 #개}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947"><ph name="CREDIT_CARD" /> 카드의 CVC를 입력하세요. 카드를 확인하면 Google Payments 계정의 카드 세부정보가 이 사이트와 공유됩니다.</translation>
<translation id="4923417429809017348">페이지가 알 수 없는 언어에서 <ph name="LANGUAGE_LANGUAGE" />(으)로 번역되었습니다.</translation>
<translation id="4923459931733593730">결제</translation>
<translation id="4926049483395192435">지정해야 합니다.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> 내용:</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">작업</translation>
<translation id="4958444002117714549">펼치기 목록</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">선택하면 Chrome에서 양식을 더 빠르게 작성할 수 있도록 이 기기에 카드 사본을 저장합니다.</translation>
<translation id="5018422839182700155">이 페이지를 열 수 없음</translation>
<translation id="5019198164206649151">보조 기억 장치 상태가 잘못됨</translation>
-<translation id="5020990877659450221">출처: 이 페이지</translation>
<translation id="5023310440958281426">관리자 정책을 확인하세요.</translation>
<translation id="5029568752722684782">사본 지우기</translation>
<translation id="503069730517007720">'<ph name="SOFTWARE_NAME" />'의 루트 인증서가 필요하지만 설치되어 있지 않습니다. IT 관리자가 '<ph name="SOFTWARE_NAME" />'의 설정 안내에 따라 이 문제를 해결해야 합니다. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">컴퓨터</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" />가 아닙니까? 오류 신고</translation>
<translation id="5190835502935405962">북마크바</translation>
+<translation id="5201306358585911203">이 페이지에 삽입된 페이지 내용:</translation>
<translation id="5205222826937269299">이름은 필수입니다.</translation>
<translation id="5222812217790122047">이메일은 필수입니다.</translation>
<translation id="522700295135997067">이 사이트에서 비밀번호를 도용했을 수 있음</translation>
<translation id="5230733896359313003">배송지 주소</translation>
<translation id="5251803541071282808">클라우드</translation>
-<translation id="5277279256032773186">직장에서 Chrome을 사용하시나요? 기업은 직원의 Chrome 설정을 관리할 수 있습니다. 자세히 알아보기</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />소프트웨어를 일시적으로 사용 중지하여 웹에 접속하려면 다음 단계를 따르세요. 관리자 권한이 필요합니다.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">연결 확인</translation>
<translation id="5610807607761827392"><ph name="BEGIN_LINK" />설정<ph name="END_LINK" />에서 카드와 주소를 관리할 수 있습니다.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" />에서 리디렉션한 횟수가 너무 많습니다.</translation>
-<translation id="5622887735448669177">이 사이트에서 나가시겠습니까?</translation>
<translation id="5629630648637658800">정책 설정 로드 실패</translation>
<translation id="5631439013527180824">잘못된 기기 관리 토큰</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">카드 정보를 입력하시겠습니까?</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" />을(를) 입력하시겠습니까?</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" />에 대한 연결이 더 이상 사용되지 않는 암호화 기술을 사용하여 암호화됩니다.</translation>
-<translation id="5810928923025889964">출처: 이 페이지에 삽입된 페이지</translation>
<translation id="5813119285467412249">추가 다시 실행(&amp;R)</translation>
<translation id="5838278095973806738">공격자에 의해 도난당할 수 있으므로 이 사이트에 비밀번호나 신용카드 등 민감한 정보를 입력해서는 안 됩니다.</translation>
<translation id="5866257070973731571">전화번호 추가</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">자세한 정보 추가</translation>
<translation id="6447842834002726250">쿠키</translation>
<translation id="6451458296329894277">양식 다시 제출 확인</translation>
-<translation id="6456339708790392414">결제</translation>
<translation id="647261751007945333">기기 정책</translation>
<translation id="6477321094435799029">Chrome이 이 페이지에서 비정상적인 코드를 감지했으며 개인정보(예: 비밀번호, 전화번호, 신용카드) 보호를 위해 차단했습니다.</translation>
<translation id="6489534406876378309">비정상 종료 업로드 시작하기</translation>
<translation id="6507833130742554667">신용카드 및 직불카드를 사용할 수 있습니다.</translation>
<translation id="6508722015517270189">Chrome 다시 시작하기</translation>
-<translation id="6521373090216409766">이 사이트를 새로고침하시겠습니까?</translation>
<translation id="6529602333819889595">삭제 다시 실행(&amp;R)</translation>
<translation id="6534179046333460208">피지컬 웹 제안</translation>
<translation id="6550675742724504774">옵션</translation>
-<translation id="6556239504065605927">보안 연결</translation>
<translation id="6556915248009097796">만료: <ph name="EXPIRATION_DATE_ABBR" />, 마지막 사용일: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">관리자가 아직 승인하지 않았습니다.</translation>
<translation id="6569060085658103619">확장 프로그램 페이지를 보는 중</translation>
<translation id="6596325263575161958">암호화 옵션</translation>
+<translation id="6604181099783169992">모션 또는 조도 센서</translation>
<translation id="6624427990725312378">연락처 정보</translation>
<translation id="6626291197371920147">유효한 카드 번호 추가</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> 검색</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">관리 북마크</translation>
<translation id="7298195798382681320">권장</translation>
<translation id="7309308571273880165"><ph name="CRASH_TIME" />에 캡처된 비정상 종료 보고서(사용자가 업로드를 요청했으나 아직 업로드되지 않음)</translation>
+<translation id="7320336641823683070">연결 도움말</translation>
<translation id="7334320624316649418">재정렬 다시 실행(&amp;R)</translation>
<translation id="733923710415886693">서버 인증서가 인증서 투명성 정책을 사용하여 공개되지 않았습니다.</translation>
<translation id="7353601530677266744">명령줄</translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">사용 중인 Wi-Fi(<ph name="WIFI_NAME" />)에서 로그인 페이지 방문을 요청할 수 있습니다.</translation>
<translation id="785549533363645510">하지만 흔적이 아예 남지 않는 것은 아닙니다. 시크릿 모드로 탐색해도 회사, 인터넷 서비스 제공업체 또는 방문한 웹사이트에 저장된 흔적까지 없앨 수는 없습니다.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">사이트에서 나가시겠습니까?</translation>
<translation id="7878176543348854470">직불카드 및 선불카드를 사용할 수 있습니다.</translation>
<translation id="7878562273885520351">비밀번호가 도용될 수도 있음</translation>
<translation id="7887683347370398519">CVC를 확인한 후 다시 시도하세요.</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">전체 기본값 사용(요청)</translation>
<translation id="8042918947222776840">수령 방법 선택</translation>
<translation id="8057711352706143257">'<ph name="SOFTWARE_NAME" />이(가) 올바르게 설정되지 않았습니다. 일반적으로 '<ph name="SOFTWARE_NAME" />'을(를) 제거하면 문제가 해결됩니다. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">사이트를 새로고침하시겠습니까?</translation>
<translation id="8088680233425245692">글을 조회하지 못했습니다.</translation>
<translation id="8091372947890762290">활성화 요청이 서버에서 대기 중</translation>
<translation id="8094917007353911263">사용 중인 네트워크에서 <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> 방문을 요청할 수 있습니다.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">ID가 '<ph name="EXTENSION_ID" />'인 확장 프로그램에 대한 잘못된 업데이트 URL</translation>
<translation id="8202097416529803614">주문 요약</translation>
<translation id="8205463626947051446">사이트에 방해가 되는 광고를 표시하는 경향이 있음</translation>
+<translation id="8211406090763984747">이 연결은 안전합니다.</translation>
<translation id="8218327578424803826">지정된 위치:</translation>
<translation id="8225771182978767009">컴퓨터를 설정한 사용자가 이 사이트를 차단했습니다.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">저장된 비밀번호 모두 표시</translation>
<translation id="8261506727792406068">삭제</translation>
<translation id="8267698848189296333"><ph name="USERNAME" />(으)로 로그인</translation>
+<translation id="8286036467436129157">로그인</translation>
<translation id="8288807391153049143">인증서 표시</translation>
<translation id="8289355894181816810">잘 모르는 경우 네트워크 관리자에게 문의하시기 바랍니다.</translation>
<translation id="8293206222192510085">북마크 추가</translation>
@@ -986,7 +1025,7 @@
<translation id="859285277496340001">인증서는 취소 여부를 확인하는 매커니즘을 지정하지 않습니다.</translation>
<translation id="8620436878122366504">부모님이 아직 승인하지 않았습니다.</translation>
<translation id="8625384913736129811">이 기기에 카드 저장</translation>
-<translation id="8639963783467694461">자동완성 설정</translation>
+<translation id="8639963783467694461">자동 완성 설정</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, 답변, <ph name="ANSWER" /></translation>
<translation id="8703575177326907206"><ph name="DOMAIN" />로의 연결은 암호화되지 않습니다.</translation>
<translation id="8718314106902482036">결제가 완료되지 않음</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">사용 가능한 신용카드 및 선불카드</translation>
<translation id="8759274551635299824">만료된 카드입니다.</translation>
<translation id="8761567432415473239">Google 세이프 브라우징 결과 <ph name="SITE" />에서 최근 <ph name="BEGIN_LINK" />악성 프로그램이 발견<ph name="END_LINK" />되었습니다.</translation>
+<translation id="8763927697961133303">USB 기기</translation>
<translation id="8790007591277257123">삭제 다시 실행(&amp;R)</translation>
<translation id="8800988563907321413">근처 추천 항목이 여기에 표시됩니다.</translation>
<translation id="8820817407110198400">북마크</translation>
diff --git a/chromium/components/strings/components_strings_lt.xtb b/chromium/components/strings/components_strings_lt.xtb
index caf305d6a78..e87a8a99e3e 100644
--- a/chromium/components/strings/components_strings_lt.xtb
+++ b/chromium/components/strings/components_strings_lt.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Spausdinti...</translation>
<translation id="1181037720776840403">Pašalinti</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Automatiškai pateikti<ph name="END_WHITEPAPER_LINK" /> išsamią informaciją apie galimas saugos problemas sistemoje „Google“. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Mokėjimas neatliktas</translation>
<translation id="1201402288615127009">Toliau</translation>
<translation id="1201895884277373915">Daugiau iš šios svetainės</translation>
<translation id="1206967143813997005">Netinkamas pirminis parašas</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575"><ph name="CRASH_TIME" /> užfiksuota strigčių ataskaita (dar neįkelta ar nepaisoma)</translation>
<translation id="1270502636509132238">Paėmimo metodas</translation>
<translation id="1285320974508926690">Niekada neversti šios svetainės</translation>
+<translation id="1294154142200295408">Komandos eilutės kintamieji</translation>
<translation id="129553762522093515">Neseniai uždarytas</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Pabandykite išvalyti slapukus<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Veiklą <ph name="BEGIN_EMPHASIS" />vis tiek gali peržiūrėti<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Tinkamos kredito ir debeto kortelės</translation>
<translation id="1519264250979466059">Sukūrimo data</translation>
<translation id="1527263332363067270">Laukiama ryšio…</translation>
+<translation id="1532118530259321453">Šiame puslapyje nurodyta:</translation>
<translation id="153384715582417236">Kol kas tiek</translation>
<translation id="154408704832528245">Pasirinkti pristatymo adresą</translation>
<translation id="1549470594296187301">Norint naudoti šią funkciją, reikia įgalinti „JavaScript“.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Patikrinti tarpinį serverį ir užkardą<ph name="END_LINK" /></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="2065985942032347596">Reikalingas tapatybės nustatymas</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="2091887806945687916">Garsas</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Atšaukti mokėjimą</translation>
<translation id="2147827593068025794">Fono sinchronizavimas</translation>
<translation id="2148613324460538318">Pridėti kortelę</translation>
-<translation id="2149973817440762519">Redaguoti žymes</translation>
<translation id="2154054054215849342">Sinchronizavimo paslauga nepasiekiama jūsų domenui</translation>
<translation id="2154484045852737596">Kortelės informacijos redagavimas</translation>
<translation id="2166049586286450108">Visateisė administratoriaus prieiga</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Pasirinkti paėmimo adresą</translation>
<translation id="2740531572673183784">Gerai</translation>
<translation id="2742870351467570537">Pašalinti pasirinktus elementus</translation>
-<translation id="2744590937989388266">Iš šiame puslapyje įterpto puslapio</translation>
<translation id="277133753123645258">Pristatymo metodas</translation>
<translation id="277499241957683684">Trūksta įrenginio įrašo</translation>
<translation id="2784949926578158345">Ryšys atkurtas.</translation>
<translation id="2788784517760473862">Tinkamos kredito kortelės</translation>
<translation id="2794233252405721443">Svetainė užblokuota</translation>
-<translation id="2795286477369100655">Ar norite išeiti iš šios svetainės?</translation>
<translation id="2799020568854403057">Pateiktoje svetainėje yra kenkėjiškų programų</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="2824775600643448204">Adreso ir paieškos juosta</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Sąrašo įrašas „<ph name="ENTRY_INDEX" />“: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automatiškai užblokuota</translation>
<translation id="3024663005179499861">Netinkamas politikos tipas</translation>
-<translation id="3032412215588512954">Ar norite iš naujo įkelti šią svetainę?</translation>
<translation id="3037605927509011580">Oi!</translation>
<translation id="3039538478787849737">Išsaugoti kortelę sistemoje „Google“?</translation>
<translation id="3041612393474885105">Sertifikato informacija</translation>
@@ -311,6 +307,7 @@
serveris veikia. Jei manote, kad tarpinio serverio
naudoti nereikia:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956">„<ph name="PRINTER_NAME" />“ serveryje „<ph name="SERVER_NAME" />“</translation>
<translation id="320323717674993345">Atšaukti mokėjimą</translation>
<translation id="3207960819495026254">Pažymėta</translation>
<translation id="3209375525920864198">Įveskite tinkamą sesijos pavadinimą.</translation>
@@ -368,11 +365,57 @@
<translation id="3556433843310711081">Jūsų valdytojas gali atblokuoti ją už jus</translation>
<translation id="3566021033012934673">Jūsų ryšys nėra privatus</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Svetainėje <ph name="SITE" /> įterptame puslapyje nurodyta:</translation>
<translation id="358285529439630156">Kredito ir išankstinio mokėjimo kortelės tinkamos.</translation>
<translation id="3582930987043644930">Pridėti vardą</translation>
<translation id="3583757800736429874">&amp;Perkelti dar kartą</translation>
<translation id="3586931643579894722">Slėpti išsamią informaciją</translation>
<translation id="3600246354004376029">„<ph name="TITLE" />“, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Ryšio klaidų taisymas&lt;/h1&gt;
+ &lt;p&gt;Jei bandant apsilankyti svetainėje pateikiamas klaidos pranešimas, išbandykite toliau nurodytus sprendimo būdus.&lt;/p&gt;
+ &lt;h2&gt;Daugumos ryšio klaidų taisymas&lt;/h2&gt;
+ &lt;p&gt;Jei bandote apsilankyti svetainėje, bet nepavyksta jos atidaryti, pirma pabandykite ištaisyti klaidą atlikdami nurodytus trikčių šalinimo veiksmus.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Patikrinkite, ar žiniatinklio adrese nėra rašybos klaidų.&lt;/li&gt;
+ &lt;li&gt;Įsitikinkite, kad interneto ryšys veikia tinkamai.&lt;/li&gt;
+ &lt;li&gt;Susisiekite su svetainės savininku.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Pagalbos dėl konkrečios klaidos pranešimo gavimas&lt;/h2&gt;
+ &lt;h3&gt;„Jūsų ryšys nėra privatus“, NET::ERR_CERT_AUTHORITY_INVALID, ERR_CERT_COMMON_NAME_INVALID, NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM arba „SSL sertifikato klaida“&lt;/h3&gt;
+ &lt;h4&gt;1 veiksmas: prisijunkite prie portalo&lt;/h4&gt;
+ &lt;p&gt;Norint naudotis „Wi-Fi“ tinklais tokiose vietose kaip kavinės ar oro uostai, reikia prisijungti. Jei norite pamatyti prisijungimo puslapį, apsilankykite puslapyje, kuriame naudojama &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Eikite į bet kokią svetainę, prasidedančią &lt;code&gt;http://&lt;/code&gt;, pvz., &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Atsidariusiame prisijungimo puslapyje prisijunkite, kad galėtumėte naudoti internetą.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;2 veiksmas: atidarykite puslapį inkognito režimu (skirta tik kompiuteriams)&lt;/h4&gt;
+ &lt;p&gt;Atidarykite puslapį, kuriame lankėtės, inkognito lange.&lt;/p&gt;
+ &lt;p&gt;Jei puslapis atidaromas, reiškia, kad „Chrome“ plėtinys veikia netinkamai. Kad ištaisytumėte klaidą, išjunkite plėtinį.&lt;/p&gt;
+ &lt;h4&gt;3 veiksmas: atnaujinkite operacinę sistemą&lt;/h4&gt;
+ &lt;p&gt;Įsitikinkite, kad jūsų įrenginys atnaujintas.&lt;/p&gt;
+ &lt;h4&gt;4 veiksmas: laikinai išjunkite antivirusinę programą&lt;/h4&gt;
+ &lt;p&gt;Ši klaida rodoma, jei turite antivirusinę programinę įrangą, teikiančią HTTPS apsaugą arba HTTPS nuskaitymą. Antivirusinė programa trukdo „Chrome“ užtikrinti saugą.&lt;/p&gt;
+ &lt;p&gt;Kad išspręstumėte problemą, išjunkite antivirusinę programinę įrangą. Jei puslapis veikia išjungus programinę įrangą, išjunkite ją, kai naudojate saugias svetaines.&lt;/p&gt;
+ &lt;p&gt;Baigę nepamirškite vėl įjungti antivirusinės programos.&lt;/p&gt;
+ &lt;h4&gt;5 veiksmas: gaukite papildomos pagalbos&lt;/h4&gt;
+ &lt;p&gt;Jei vis tiek rodoma klaida, susisiekite su svetainės savininku.&lt;/p&gt;
+ &lt;h3&gt;„Prisijunkite prie tinklo“&lt;/h3&gt;
+ &lt;p&gt;Ši klaida rodoma, jei naudojate „Wi-Fi“ portalą, kuriame 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;
+ &lt;h3&gt;„Jūsų laikrodis atsilieka“, „Jūsų laikrodis skuba“ arba NET::ERR_CERT_DATE_INVALID&lt;/h3&gt;
+ &lt;p&gt;Ši klaida rodoma, jei netikslūs kompiuterio arba mobiliojo įrenginio data ir laikas.&lt;/p&gt;
+ &lt;p&gt;Kad ištaisytumėte klaidą, atidarykite įrenginio laikrodį. Įsitikinkite, kad laikas ir data tinkami.&lt;/p&gt;
+ &lt;h3&gt;„Programinė įranga jūsų kompiuteryje neleidžia „Chrome“ saugiai prisijungti prie žiniatinklio“ (tik „Windows“ kompiuteriai)&lt;/h3&gt;
+ &lt;p&gt;Ši klaida rodoma, jei „Windows“ kompiuteryje veikia programinė įranga „Superfish“.&lt;/p&gt;
+ &lt;p&gt;Jei norite laikinai išjungti programinę įrangą, kad galėtumėte pasiekti žiniatinklį, atlikite nurodytus veiksmus. Jums reikės administratoriaus teisių.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Spustelėkite &lt;strong&gt;Start&lt;/strong&gt;, tada suraskite ir pasirinkite &lt;strong&gt;"View local services"&lt;/strong&gt;
+ &lt;li&gt;Pasirinkite &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Skiltyje &lt;strong&gt;Startup type&lt;/strong&gt; pasirinkite &lt;strong&gt;Disabled&lt;/strong&gt;
+ &lt;li&gt;Skiltyje &lt;strong&gt;Service status&lt;/strong&gt; spustelėkite &lt;strong&gt;Stop&lt;/strong&gt;
+ &lt;li&gt;Spustelėkite &lt;strong&gt;Apply&lt;/strong&gt;, tada – &lt;strong&gt;OK&lt;/strong&gt;
+ &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="3615877443314183785">Įveskite tinkamą galiojimo laiko pabaigos datą</translation>
<translation id="36224234498066874">Išvalyti naršymo duomenis...</translation>
<translation id="362276910939193118">Rodyti visą istoriją</translation>
@@ -405,7 +448,6 @@
<translation id="3778403066972421603">Ar norite išsaugoti šią kortelę „Google“ paskyroje ir šiame įrenginyje?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Galiojimo laikas baigiasi <ph name="EXPIRATION_MONTH" /> / <ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Iš svetainės <ph name="SITE" /></translation>
<translation id="382518646247711829">Jei naudojate tarpinį serverį…</translation>
<translation id="3828924085048779000">Neleidžiama naudoti tuščios slaptafrazės.</translation>
<translation id="385051799172605136">Grįžti</translation>
@@ -419,6 +461,7 @@
<translation id="3945915738023014686">Įkeltos strigties ataskaitos ID: <ph name="CRASH_ID" /> (vietinės strigties ID: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikate nenurodomi temos alternatyvūs pavadinimai. Tai gali būti dėl netinkamos konfigūracijos arba dėl ryšį pertraukusio užgrobėjo.</translation>
<translation id="3949601375789751990">Naršymo istorija rodoma čia</translation>
+<translation id="3950820424414687140">Prisijungti</translation>
<translation id="3963721102035795474">Skaitytojo režimas</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Nėra}=1{Iš 1 svetainės }one{Iš # svetainės }few{Iš # svetainių }many{Iš # svetainės }other{Iš # svetainių }}</translation>
<translation id="397105322502079400">Skaičiuojama...</translation>
@@ -435,6 +478,7 @@
<translation id="4103249731201008433">Netinkamas įrenginio serijos numeris</translation>
<translation id="410351446219883937">Automatinis paleidimas</translation>
<translation id="4103763322291513355">Apsilankykite &lt;strong&gt;chrome://policy&lt;/strong&gt;, kad peržiūrėtumėte į juodąjį sąrašą įtrauktų URL sąrašą ir kitą politiką, kurią priverstinai paleido sistemos administratorius.</translation>
+<translation id="4110652170750985508">Mokėjimo peržiūra</translation>
<translation id="4116663294526079822">Visada leisti šioje svetainėje</translation>
<translation id="4117700440116928470">Politikos aprėptis nepalaikoma.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{Dar 1}one{Dar #}few{Dar #}many{Dar #}other{Dar #}}</translation>
@@ -461,7 +505,6 @@
<translation id="4269787794583293679">(Nėra naudotojo vardo)</translation>
<translation id="4275830172053184480">Iš naujo paleisti įrenginį</translation>
<translation id="4280429058323657511">, gal. pab. <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Prisijungti</translation>
<translation id="4312866146174492540">Užblokuoti (numatytoji parinktis)</translation>
<translation id="4325863107915753736">Nepavyko rasti straipsnio</translation>
<translation id="4326324639298822553">Patikrinkite galiojimo pabaigos datą ir bandykite dar kartą</translation>
@@ -483,14 +526,12 @@
<translation id="4515275063822566619">Kortelės ir adresai naudojami iš „Chrome“ ir jūsų „Google“ paskyros (<ph name="ACCOUNT_EMAIL" />). Galite juos tvarkyti skiltyje <ph name="BEGIN_LINK" />Nustatymai<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Išsami informacija</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Svetainėje <ph name="SITE" /> įterptame puslapyje</translation>
<translation id="4558551763791394412">Pabandykite išjungti plėtinius.</translation>
<translation id="457875822857220463">Pristatymas</translation>
<translation id="4582800630050655161">Galite prarasti prieigą prie „Google“ paskyros arba susidurti su tapatybės vagyste. „Chromium“ rekomenduoja pakeisti slaptažodį dabar.</translation>
<translation id="4587425331216688090">Pašalinti adresą iš „Chrome“?</translation>
<translation id="4592951414987517459">Ryšys su <ph name="DOMAIN" /> užšifruotas naudojant modernų šifravimo paketą.</translation>
<translation id="4594403342090139922">&amp;Anuliuoti ištrynimą</translation>
-<translation id="4611292653554630842">Prisijungti</translation>
<translation id="4619615317237390068">Skirtukai iš kitų įrenginių</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikate yra klaidų. Taip gali nutikti dėl netinkamos konfigūracijos ar dėl ryšį pertraukusio užgrobėjo.</translation>
@@ -500,11 +541,9 @@
<translation id="4708268264240856090">Ryšys nutrauktas</translation>
<translation id="471880041731876836">Neturite leidimo, kad galėtumėte apsilankykite šioje svetainėje</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Paleistas įrankis „Windows Network Diagnostics“<ph name="END_LINK" />.</translation>
-<translation id="472349245089439925">Jūsų mokėjimas</translation>
<translation id="4726672564094551039">Iš naujo įkelti politiką</translation>
<translation id="4728558894243024398">Platforma</translation>
<translation id="4736825316280949806">Iš naujo paleiskite „Chromium“</translation>
-<translation id="4737498291095696011">Iš šio puslapio</translation>
<translation id="4744603770635761495">Vykdomasis kelias</translation>
<translation id="4749685221585524849">Paskutinį kartą naudota <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Į šią svetainę siunčiama informacija (pvz., slaptažodžiai arba kredito kortelių numeriai) yra privati.</translation>
@@ -523,16 +562,16 @@
<translation id="4850886885716139402">Žiūrėti</translation>
<translation id="4854362297993841467">Šis pristatymo metodas nepasiekiamas. Išbandykite kitą metodą.</translation>
<translation id="4858792381671956233">Paprašėte tėvų leidimo apsilankyti šiame puslapyje</translation>
-<translation id="4871132632506079383">Svetainėje <ph name="SITE" /> įterptame puslapyje</translation>
<translation id="4880827082731008257">Ieškoti istorijoje</translation>
+<translation id="4881695831933465202">Atidaryti</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Autentifikavimas yra būtinas</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{ir dar 1 tinklalapis}one{ir dar # tinklalapis}few{ir dar # tinklalapiai}many{ir dar # tinklalapio}other{ir dar # tinklalapių}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Įveskite „<ph name="CREDIT_CARD" />“ kortelės saugos kodą (CVC). Kai patvirtinsite, „Google“ mokamojoje paskyroje nurodyta išsami kortelės informacija bus bendrinama su šia svetaine.</translation>
<translation id="4923417429809017348">Šis puslapis išverstas iš nežinomos kalbos į <ph name="LANGUAGE_LANGUAGE" /> k.</translation>
<translation id="4923459931733593730">Mokėjimas</translation>
<translation id="4926049483395192435">Turi būti nurodyta.</translation>
+<translation id="4926159001844873046">Svetainėje <ph name="SITE" /> nurodyta:</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" /> / <ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Veiksmai</translation>
<translation id="4958444002117714549">Išskleisti sąrašą</translation>
@@ -541,7 +580,6 @@
<translation id="5002932099480077015">Jei šis nustatymas įgalintas, „Chrome“ saugos kortelės kopiją šiame įrenginyje, kad būtų galima greičiau užpildyti formas.</translation>
<translation id="5018422839182700155">Negalima atidaryti šio puslapio</translation>
<translation id="5019198164206649151">Bloga atsarginio atminties įrenginio būsena</translation>
-<translation id="5020990877659450221">Iš šio puslapio</translation>
<translation id="5023310440958281426">Patikrinkite savo administratoriaus politiką</translation>
<translation id="5029568752722684782">Išvalyti kopiją</translation>
<translation id="503069730517007720">Reikalingas „<ph name="SOFTWARE_NAME" />“ šakninis sertifikatas, bet jis nėra įdiegtas. Jūsų IT administratorius turėtų peržiūrėti „<ph name="SOFTWARE_NAME" />“ konfigūravimo instrukcijas, kad išspręstų šią problemą. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -567,12 +605,12 @@
<translation id="5172758083709347301">Įrenginys</translation>
<translation id="5179510805599951267">Ne <ph name="ORIGINAL_LANGUAGE" /> k.? Pranešti apie šią klaidą</translation>
<translation id="5190835502935405962">Žymių juosta</translation>
+<translation id="5201306358585911203">Šiame puslapyje įterptame puslapyje nurodyta:</translation>
<translation id="5205222826937269299">Būtina nurodyti pavadinimą</translation>
<translation id="5222812217790122047">Būtina nurodyti el. paštą</translation>
<translation id="522700295135997067">Gali būti, kad ši svetainė ką tik pavogė jūsų slaptažodį</translation>
<translation id="5230733896359313003">Pristatymo adresas</translation>
<translation id="5251803541071282808">Debesis</translation>
-<translation id="5277279256032773186">Naudojate „Chrome“ darbe? Įmonės gali tvarkyti darbuotojų „Chrome“ nustatymus. Sužinokite daugiau</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Jei norite laikinai išjungti programinę įrangą, kad galėtumėte pasiekti žiniatinklį, atlikite nurodytus veiksmus. Jums reikės administratoriaus teisių.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -634,7 +672,6 @@
<translation id="5610142619324316209">Patikrinti ryšį</translation>
<translation id="5610807607761827392">Korteles ir adresus galite tvarkyti skiltyje <ph name="BEGIN_LINK" />Nustatymai<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> buvote per daug kartų peradresuoti.</translation>
-<translation id="5622887735448669177">Ar norite išeiti iš šios svetainės?</translation>
<translation id="5629630648637658800">Įkeliant politikos nustatymus įvyko klaida</translation>
<translation id="5631439013527180824">Netinkamas įrenginio tvarkymo prieigos raktas</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>
@@ -657,7 +694,6 @@
<translation id="5786044859038896871">Ar norite, kad būtų įvesta jūsų kredito kortelės informacija?</translation>
<translation id="5803412860119678065">Ar norite, kad būtų įvesta <ph name="CARD_DETAIL" /> informacija?</translation>
<translation id="5810442152076338065">Ryšys su <ph name="DOMAIN" /> užšifruotas naudojant pasenusį šifravimo paketą.</translation>
-<translation id="5810928923025889964">Iš šiame puslapyje įterpto puslapio</translation>
<translation id="5813119285467412249">&amp;Pridėti dar kartą</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>
<translation id="5866257070973731571">Telefono numerio pridėjimas</translation>
@@ -731,21 +767,19 @@
<translation id="6446608382365791566">Daugiau informacijos pridėjimas</translation>
<translation id="6447842834002726250">Slapukai</translation>
<translation id="6451458296329894277">Patvirtinkite pakartotiną formos pateikimą</translation>
-<translation id="6456339708790392414">Jūsų mokėjimas</translation>
<translation id="647261751007945333">Įrenginio politika</translation>
<translation id="6477321094435799029">„Chrome“ šiame puslapyje aptiko neįprastą kodą ir jį užblokavo, kad apsaugotų asmens informaciją (pvz., slaptažodžius, telefonų numerius ir kredito korteles).</translation>
<translation id="6489534406876378309">Pradėti įkelti strigtis</translation>
<translation id="6507833130742554667">Kredito ir debeto kortelės tinkamos.</translation>
<translation id="6508722015517270189">Iš naujo paleiskite „Chrome“</translation>
-<translation id="6521373090216409766">Ar norite iš naujo įkelti šią svetainę?</translation>
<translation id="6529602333819889595">&amp;Ištrinti dar kartą</translation>
<translation id="6534179046333460208">Fizinio žiniatinklio pasiūlymai</translation>
<translation id="6550675742724504774">Parinktys</translation>
-<translation id="6556239504065605927">Saugus ryšys</translation>
<translation id="6556915248009097796">Galiojimo laiko pabaiga: <ph name="EXPIRATION_DATE_ABBR" />, paskutinį kartą naudota <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Jūsų valdytojas dar jos nepatvirtino</translation>
<translation id="6569060085658103619">Peržiūrite plėtinio puslapį</translation>
<translation id="6596325263575161958">Šifravimo parinktys</translation>
+<translation id="6604181099783169992">Judesio arba šviesos jutikliai</translation>
<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>
@@ -817,6 +851,7 @@
<translation id="7275334191706090484">Tvarkomos žymės</translation>
<translation id="7298195798382681320">Rekomenduojama</translation>
<translation id="7309308571273880165">Strigčių ataskaita užfiksuota <ph name="CRASH_TIME" /> (įkėlimo užklausą pateikė naudotojas, dar neįkelta)</translation>
+<translation id="7320336641823683070">Su ryšiu susijusi pagalba</translation>
<translation id="7334320624316649418">&amp;Pertvarkyti dar kartą</translation>
<translation id="733923710415886693">Serverio sertifikatas nebuvo atskleistas taikant sertifikato skaidrumą.</translation>
<translation id="7353601530677266744">Komandos eilutė</translation>
@@ -901,6 +936,7 @@
<translation id="782886543891417279">Naudojant šį „Wi-Fi“ tinklą („<ph name="WIFI_NAME" />“) gali būti prašoma apsilankyti prisijungimo puslapyje.</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="7862185352068345852">Išeiti iš svetainės?</translation>
<translation id="7878176543348854470">Debeto ir išankstinio mokėjimo kortelės tinkamos.</translation>
<translation id="7878562273885520351">Jūsų slaptažodis gali būti pažeistas</translation>
<translation id="7887683347370398519">Patikrinkite kortelės saugos kodą (CVC) ir bandykite dar kartą</translation>
@@ -923,6 +959,7 @@
<translation id="8041940743680923270">Naudoti visuotinį numatytąjį nustatymą (klausti)</translation>
<translation id="8042918947222776840">Pasirinkti paėmimo metodą</translation>
<translation id="8057711352706143257">„<ph name="SOFTWARE_NAME" />“ netinkamai sukonfigūruota. Pašalinus „<ph name="SOFTWARE_NAME" />“ paprastai pavyksta išspręsti šią problemą. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Iš naujo įkelti svetainę?</translation>
<translation id="8088680233425245692">Nepavyko peržiūrėti straipsnio.</translation>
<translation id="8091372947890762290">Laukiama aktyvinimo serveryje</translation>
<translation id="8094917007353911263">Naudojant šį tinklą gali būti prašoma apsilankyti <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -938,6 +975,7 @@
<translation id="8201077131113104583">Netinkamas plėtinio, kurio ID „<ph name="EXTENSION_ID" />“, atnaujinimo URL.</translation>
<translation id="8202097416529803614">Užsakymo suvestinė</translation>
<translation id="8205463626947051446">Svetainėje bandoma rodyti nepageidaujamus skelbimus</translation>
+<translation id="8211406090763984747">Ryšys saugus</translation>
<translation id="8218327578424803826">Priskirta vieta:</translation>
<translation id="8225771182978767009">Šį kompiuterį nustatęs asmuo pasirinko blokuoti šią svetainę.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -949,6 +987,7 @@
<translation id="825929999321470778">Rodyti visus išsaugotus slaptažodžius</translation>
<translation id="8261506727792406068">Ištrinti</translation>
<translation id="8267698848189296333">Prisijungiama kaip <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Prisijungti</translation>
<translation id="8288807391153049143">Rodyti sertifikatą</translation>
<translation id="8289355894181816810">Jei nesate tikri, ką tai reiškia, susisiekite su tinklo administratoriumi.</translation>
<translation id="8293206222192510085">Pridėti žymę</translation>
@@ -1000,6 +1039,7 @@
<translation id="874846938927089722">Tinkamos kredito ir išankstinio mokėjimo kortelės</translation>
<translation id="8759274551635299824">Ši kortelė nebegalioja</translation>
<translation id="8761567432415473239">„Google“ saugaus naršymo funkcija neseniai <ph name="BEGIN_LINK" />rado kenkėjiškų programų<ph name="END_LINK" /> <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">USB įrenginys</translation>
<translation id="8790007591277257123">&amp;Ištrinti dar kartą</translation>
<translation id="8800988563907321413">Netoliese esantys pasiūlymai jums rodomi čia</translation>
<translation id="8820817407110198400">Žymės</translation>
diff --git a/chromium/components/strings/components_strings_lv.xtb b/chromium/components/strings/components_strings_lv.xtb
index 5ef3ded8411..3ec5424dc50 100644
--- a/chromium/components/strings/components_strings_lv.xtb
+++ b/chromium/components/strings/components_strings_lv.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">Drukāt...</translation>
<translation id="1181037720776840403">Noņemt</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Automātiski nosūtīt<ph name="END_WHITEPAPER_LINK" /> Google serveriem informāciju par iespējamām drošības problēmām. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Maksājums nav pabeigts</translation>
<translation id="1201402288615127009">Nākamais</translation>
<translation id="1201895884277373915">Vairāk no šīs vietnes</translation>
<translation id="1206967143813997005">Sākotnējais paraksts nav derīgs</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575"><ph name="CRASH_TIME" /> notverts ziņojums par avāriju (vēl nav augšupielādēts vai ignorēts)</translation>
<translation id="1270502636509132238">Saņemšanas veids</translation>
<translation id="1285320974508926690">Nekad netulkot šo vietni</translation>
+<translation id="1294154142200295408">Komandrindu varianti</translation>
<translation id="129553762522093515">Nesen aizvērtas</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Dzēsiet sīkfailus<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Iespējams, jūsu darbības <ph name="BEGIN_EMPHASIS" />joprojām būs redzamas<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Atbalstītās kredītkartes un debetkartes</translation>
<translation id="1519264250979466059">Būvējuma datums</translation>
<translation id="1527263332363067270">Tiek gaidīta savienojuma izveide...</translation>
+<translation id="1532118530259321453">Šajā lapā ir rakstīts</translation>
<translation id="153384715582417236">Pagaidām tas arī viss!</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>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Pārbaudiet starpniekserveri un ugunsmūri<ph name="END_LINK" />.</translation>
<translation id="2053553514270667976">Pasta indekss</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 ieteikums}zero{# ieteikumi}one{# ieteikums}other{# ieteikumi}}</translation>
-<translation id="2065985942032347596">Nepieciešama autentiskuma noteikšana</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="2091887806945687916">Signāls</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Atcelt maksājumu</translation>
<translation id="2147827593068025794">Sinhronizācija fonā</translation>
<translation id="2148613324460538318">Pievienot karti</translation>
-<translation id="2149973817440762519">Rediģēt grāmatzīmes</translation>
<translation id="2154054054215849342">Sinhronizācija jūsu domēnam nav pieejama.</translation>
<translation id="2154484045852737596">Kartes informācijas rediģēšana</translation>
<translation id="2166049586286450108">Pilna administratora piekļuve</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Izvēlēties saņemšanas adresi</translation>
<translation id="2740531572673183784">Labi</translation>
<translation id="2742870351467570537">Noņemt atlasītos vienumus</translation>
-<translation id="2744590937989388266">No iegultas lapas šajā lapā</translation>
<translation id="277133753123645258">Nosūtīšanas veids</translation>
<translation id="277499241957683684">Trūkst ierīces ieraksta.</translation>
<translation id="2784949926578158345">Savienojums tika atiestatīts.</translation>
<translation id="2788784517760473862">Atbalstītās kredītkartes</translation>
<translation id="2794233252405721443">Vietne bloķēta</translation>
-<translation id="2795286477369100655">Vai vēlaties pamest šo vietni?</translation>
<translation id="2799020568854403057">Šajā vietnē, kas tiks atvērta, ir kaitīgas lietotnes</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="2824775600643448204">Adreses un meklēšanas josla</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Saraksta ieraksts “<ph name="ENTRY_INDEX" />”: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automātiski bloķēta</translation>
<translation id="3024663005179499861">Politikas tips nav pareizs.</translation>
-<translation id="3032412215588512954">Vai vēlaties atkārtoti ielādēt šo vietni?</translation>
<translation id="3037605927509011580">Cilnes avārija.</translation>
<translation id="3039538478787849737">Vai saglabāt kartes datus Google tīklā?</translation>
<translation id="3041612393474885105">Sertifikāta informācija</translation>
@@ -310,6 +306,7 @@
pārliecinātos, vai starpniekserveris darbojas. Ja uzskatāt, ka jums nav jāizmanto
starpniekserveris,
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> serverī <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Atcelt maksājumu</translation>
<translation id="3207960819495026254">Atzīmēts kā grāmatzīme</translation>
<translation id="3209375525920864198">Lūdzu, ievadiet derīgu sesijas nosaukumu.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Lai atbloķētu, vērsieties pie pārvaldnieka</translation>
<translation id="3566021033012934673">Jūsu savienojums nav privāts</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Vietnē <ph name="SITE" /> iegultā lapā ir rakstīts</translation>
<translation id="358285529439630156">Tiek pieņemtas kredītkartes un priekšapmaksas kartes.</translation>
<translation id="3582930987043644930">Pievienojiet vārdu.</translation>
<translation id="3583757800736429874">&amp;Pārvietošanas atsaukuma atcelšana</translation>
<translation id="3586931643579894722">Slēpt detaļas</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Savienojuma kļūdu novēršana&lt;/h1&gt;
+ &lt;p&gt;Ja, mēģinot apmeklēt vietni, tiek rādīts kļūdas ziņojums, izmēģiniet šos risinājumus.&lt;/p&gt;
+ &lt;h2&gt;Vairākuma savienojuma kļūdu novēršana&lt;/h2&gt;
+ &lt;p&gt;Ja, mēģinot apmeklēt vietni, tā netiek atvērta, vispirms izmēģiniet tālāk norādītās kļūdu novēršanas darbības.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Pārbaudiet, vai tīmekļa adrese ir pareizi uzrakstīta.&lt;/li&gt;
+ &lt;li&gt;Pārbaudiet, vai interneta savienojums darbojas pareizi.&lt;/li&gt;
+ &lt;li&gt;Sazinieties ar vietnes īpašnieku.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Palīdzība par konkrētu kļūdas ziņojumu&lt;/h2&gt;
+ &lt;h3&gt;“Jūsu savienojums nav privāts”, “NET::ERR_CERT_AUTHORITY_INVALID”, “ERR_CERT_COMMON_NAME_INVALID”, “NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM” vai “SSL sertifikāta kļūda”&lt;/h3&gt;
+ &lt;h4&gt;1. darbība. Pierakstīšanās portālā&lt;/h4&gt;
+ &lt;p&gt;Wi-Fi tīklos tādās vietās kā kafejnīcas un lidostas ir jāveic pierakstīšanās. Lai atvērtu pierakstīšanās lapu, apmeklējiet lapu, kurā tiek izmantots &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Pārejiet uz jebkuru vietni, kuras adrese sākas ar &lt;code&gt;http://&lt;/code&gt;, piemēram, &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Atvērtajā pierakstīšanās lapā pierakstieties, lai izmantotu internetu.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;2. darbība. Lapas atvēršana inkognito režīmā (tikai datorā)&lt;/h4&gt;
+ &lt;p&gt;Atveriet apmeklēto lapu inkognito režīma logā.&lt;/p&gt;
+ &lt;p&gt;Ja lapa tiek atvērta, kāds Chrome paplašinājums nedarbojas pareizi. Lai novērstu šo kļūdu, izslēdziet attiecīgo paplašinājumu.&lt;/p&gt;
+ &lt;h4&gt;3. darbība. Operētājsistēmas atjaunināšana&lt;/h4&gt;
+ &lt;p&gt;Ierīcē ir jābūt instalētai jaunākajai operētājsistēmai.&lt;/p&gt;
+ &lt;h4&gt;4. darbība. Pretvīrusu programmas īslaicīga izslēgšana&lt;/h4&gt;
+ &lt;p&gt;Šis kļūdas ziņojums tiek rādīts, ja ierīcē ir instalēta pretvīrusu programmatūra, kas ietver HTTPS aizsardzību vai HTTPS skenēšanu. Šī antivīrusa programmatūra novērš Chrome drošības funkciju darbību.&lt;/p&gt;
+ &lt;p&gt;Lai novērstu šo problēmu, izslēdziet pretvīrusu programmatūru. Ja pēc programmatūras izslēgšanas lapa darbojas, izslēdziet šo programmatūru, kad apmeklējat drošas vietnes.&lt;/p&gt;
+ &lt;p&gt;Pēc darba pabeigšanas noteikti atkal ieslēdziet pretvīrusu programmu.&lt;/p&gt;
+ &lt;h4&gt;5. darbība. Papildu palīdzības saņemšana&lt;/h4&gt;
+ &lt;p&gt;Ja kļūda joprojām tiek rādīta, sazinieties ar vietnes īpašnieku.&lt;/p&gt;
+ &lt;h3&gt;“Izveidojiet savienojumu ar tīklu”&lt;/h3&gt;
+ &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;
+ &lt;h3&gt;“Pulksteņa laiks ir pagātnē”, “Pulksteņa laiks ir nākotnē” vai “NET::ERR_CERT_DATE_INVALID”&lt;/h3&gt;
+ &lt;p&gt;Šis kļūdas ziņojums tiek rādīts, ja datora vai mobilās ierīces datums un laiks nav precīzs.&lt;/p&gt;
+ &lt;p&gt;Lai novērstu šo kļūdu, atveriet ierīces pulksteni. Ir jābūt iestatītam pareizam datumam un laikam.&lt;/p&gt;
+ &lt;h3&gt;“Programmatūra jūsu datorā, kuras dēļ pārlūkā Chrome nevar izveidot drošu tīmekļa savienojumu” (tikai Windows datoros)&lt;/h3&gt;
+ &lt;p&gt;Šis kļūdas ziņojums tiek rādīts, ja datorā ir instalēta programmatūra Superfish.&lt;/p&gt;
+ &lt;p&gt;Lai īslaicīgi atspējotu programmatūru un piekļūtu tīmeklim, veiciet tālāk norādītās darbības. Nepieciešamas administratora privilēģijas.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Noklikšķiniet uz &lt;strong&gt;Sākums&lt;/strong&gt; un pēc tam atrodiet un atlasiet vienumu &lt;strong&gt;Skatīt vietējos pakalpojumus&lt;/strong&gt;.
+ &lt;li&gt;Atlasiet vienumu &lt;strong&gt;VisualDiscovery&lt;/strong&gt;.
+ &lt;li&gt;Sadaļā &lt;strong&gt;Startēšanas veids&lt;/strong&gt; atlasiet vienumu &lt;strong&gt;Atspējots&lt;/strong&gt;.
+ &lt;li&gt;Sadaļā &lt;strong&gt;Pakalpojuma statuss&lt;/strong&gt; noklikšķiniet uz &lt;strong&gt;Apturēt&lt;/strong&gt;.
+ &lt;li&gt;Noklikšķiniet uz &lt;strong&gt;Lietot&lt;/strong&gt;, pēc tam noklikšķiniet uz &lt;strong&gt;Labi&lt;/strong&gt;.
+ &lt;li&gt;Lai uzzinātu, kā neatgriezeniski noņemt programmatūru no datora, apmeklējiet &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome palīdzības centru&lt;/a&gt;.
+ &lt;/ol&gt;</translation>
<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>
@@ -403,7 +446,6 @@
<translation id="3778403066972421603">Vai vēlaties saglabāt šo karti savā Google kontā un šajā ierīcē?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Derīguma termiņš: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">No vietnes <ph name="SITE" /></translation>
<translation id="382518646247711829">Ja izmantojat starpniekserveri...</translation>
<translation id="3828924085048779000">Tukša ieejas frāze nav atļauta.</translation>
<translation id="385051799172605136">Atpakaļ</translation>
@@ -417,6 +459,7 @@
<translation id="3945915738023014686">Augšupielādētā avārijas ziņojuma ID <ph name="CRASH_ID" /> (vietējais avārijas ID: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Šis serveris nevarēja pierādīt, ka šī ir vietne <ph name="DOMAIN" />; tā drošības sertifikātā nav norādīti temata citi nosaukumi. Iespējams, tas ir nepareizas konfigurācijas dēļ vai arī kāds ļaunprātīgi izmanto jūsu savienojumu.</translation>
<translation id="3949601375789751990">Šeit ir redzama jūsu pārlūkošanas vēsture.</translation>
+<translation id="3950820424414687140">Pierakstīties</translation>
<translation id="3963721102035795474">Lasītāja režīms</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Nav}=1{No 1 vietnes }zero{No # vietnēm }one{No # vietnes }other{No # vietnēm }}</translation>
<translation id="397105322502079400">Aprēķina...</translation>
@@ -433,6 +476,7 @@
<translation id="4103249731201008433">Ierīces sērijas numurs nav derīgs.</translation>
<translation id="410351446219883937">Automātiskā atskaņošana</translation>
<translation id="4103763322291513355">Apmeklējiet vietni &lt;strong&gt;chrome://policy&lt;/strong&gt;, lai skatītu melnajā sarakstā iekļautos vietrāžus URL, kā arī citas politikas, ko noteicis sistēmas administrators.</translation>
+<translation id="4110652170750985508">Maksājuma pārskatīšana</translation>
<translation id="4116663294526079822">Vienmēr atļaut šajā vietnē</translation>
<translation id="4117700440116928470">Politikas diapazons netiek atbalstīts.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{vēl 1}zero{vēl #}one{vēl #}other{vēl #}}</translation>
@@ -459,7 +503,6 @@
<translation id="4269787794583293679">(Nav lietotājvārda)</translation>
<translation id="4275830172053184480">Ierīces restartēšana</translation>
<translation id="4280429058323657511">, derīga līdz <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Pieteikšanās</translation>
<translation id="4312866146174492540">Bloķēt (pēc noklusējuma)</translation>
<translation id="4325863107915753736">Rakstu neizdevās atrast.</translation>
<translation id="4326324639298822553">Pārbaudiet derīguma termiņa datumu un mēģiniet vēlreiz.</translation>
@@ -481,14 +524,12 @@
<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="4522570452068850558">Informācija</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">No iegultas lapas vietnē <ph name="SITE" /></translation>
<translation id="4558551763791394412">Atspējojiet paplašinājumus.</translation>
<translation id="457875822857220463">Piegāde</translation>
<translation id="4582800630050655161">Varat zaudēt piekļuvi savam Google kontam, vai jūsu identitāte var tikt nozagta. Chromium iesaka nekavējoties nomainīt paroli.</translation>
<translation id="4587425331216688090">Vai noņemt adresi no pārlūka Chrome?</translation>
<translation id="4592951414987517459">Savienojums ar domēnu <ph name="DOMAIN" /> ir šifrēts, izmantojot mūsdienīgu šifra komplektu.</translation>
<translation id="4594403342090139922">&amp;Dzēšanas atsaukšana</translation>
-<translation id="4611292653554630842">Pieteikties</translation>
<translation id="4619615317237390068">Cilnes no citām ierīcēm</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Šis serveris nevarēja pierādīt, ka šī ir vietne <ph name="DOMAIN" />; tās drošības sertifikātā ir kļūdas. Iespējams, tas ir nepareizas konfigurācijas dēļ vai arī kāds ir ļaunprātīgi izmantojis jūsu savienojumu.</translation>
@@ -498,11 +539,9 @@
<translation id="4708268264240856090">Savienojums tika pārtraukts</translation>
<translation id="471880041731876836">Jums nav atļaujas apmeklēt šo vietni</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Palaist Windows tīkla diagnostiku<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Jūsu maksājums</translation>
<translation id="4726672564094551039">Atkārtoti ielādēt politikas</translation>
<translation id="4728558894243024398">Platforma</translation>
<translation id="4736825316280949806">Restartējiet pārlūku Chromium</translation>
-<translation id="4737498291095696011">No šīs lapas</translation>
<translation id="4744603770635761495">Izpildāms ceļš</translation>
<translation id="4749685221585524849">Pēdējoreiz izmantota: <ph name="LAST_USED_MONTH" /></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>
@@ -521,16 +560,16 @@
<translation id="4850886885716139402">Skatīt</translation>
<translation id="4854362297993841467">Šis piegādes veids nav pieejams. Izmēģiniet citu veidu.</translation>
<translation id="4858792381671956233">Jūs lūdzāt vecākiem atļauju apmeklēt šo lapu</translation>
-<translation id="4871132632506079383">No iegultas lapas vietnē <ph name="SITE" /></translation>
<translation id="4880827082731008257">Meklēšanas vēsture</translation>
+<translation id="4881695831933465202">Atvērt</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Nepieciešama autentifikācija</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{un vēl 1 tīmekļa lapa}zero{un vēl # tīmekļa lapas}one{un vēl # tīmekļa lapa}other{un vēl # tīmekļa lapas}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Ievadiet kredītkartes <ph name="CREDIT_CARD" /> CVC kodu. Pēc apstiprināšanas kartes informācija no Google maksājumu konta tiks kopīgota ar šo vietni.</translation>
<translation id="4923417429809017348">Šī lapa ir tulkota no nezināmas valodas valodā: <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Maksājums</translation>
<translation id="4926049483395192435">Jābūt norādītai.</translation>
+<translation id="4926159001844873046">Vietnē <ph name="SITE" /> ir rakstīts</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Darbības</translation>
<translation id="4958444002117714549">Izvērst sarakstu</translation>
@@ -539,7 +578,6 @@
<translation id="5002932099480077015">Iespējojot šo opciju, Chrome saglabās jūsu kartes informāciju šajā ierīcē, lai jūs varētu ātrāk aizpildīt veidlapas.</translation>
<translation id="5018422839182700155">Nevar atvērt šo lapu</translation>
<translation id="5019198164206649151">Dublējumu krātuve nav labā stāvoklī.</translation>
-<translation id="5020990877659450221">No šīs lapas</translation>
<translation id="5023310440958281426">Administratora politiku pārbaude</translation>
<translation id="5029568752722684782">Dzēst kopiju</translation>
<translation id="503069730517007720">Programmatūrai <ph name="SOFTWARE_NAME" /> ir nepieciešams saknes sertifikāts, taču tas nav instalēts. Lai novērstu šo problēmu, tīkla administratoram ir jāapskata <ph name="SOFTWARE_NAME" /> konfigurācijas norādījumi. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -565,12 +603,12 @@
<translation id="5172758083709347301">Ierīce</translation>
<translation id="5179510805599951267">Vai nav valodā: <ph name="ORIGINAL_LANGUAGE" />? Ziņot par šo kļūdu</translation>
<translation id="5190835502935405962">Grāmatzīmju josla</translation>
+<translation id="5201306358585911203">Šajā lapā iegultā lapā ir rakstīts</translation>
<translation id="5205222826937269299">Jānorāda vārds vai nosaukums.</translation>
<translation id="5222812217790122047">Jānorāda e-pasta adrese.</translation>
<translation id="522700295135997067">Iespējams, šajā vietnē tikko tika nozagta jūsu parole</translation>
<translation id="5230733896359313003">Piegādes adrese</translation>
<translation id="5251803541071282808">Mākonis</translation>
-<translation id="5277279256032773186">Vai izmantojat Chrome darbā? Uzņēmumi var pārvaldīt darbinieku Chrome iestatījumus. Uzziniet vairāk.</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Lai īslaicīgi atspējotu programmatūru un piekļūtu tīmeklim, veiciet tālāk norādītās darbības. Nepieciešamas administratora privilēģijas.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -632,7 +670,6 @@
<translation id="5610142619324316209">Pārbaudiet savienojumu.</translation>
<translation id="5610807607761827392">Varat pārvaldīt karšu un adrešu informāciju sadaļā <ph name="BEGIN_LINK" />Iestatījumi<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> novirzīja pārāk daudz reižu.</translation>
-<translation id="5622887735448669177">Vai vēlaties pamest šo vietni?</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="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>
@@ -655,7 +692,6 @@
<translation id="5786044859038896871">Vai vēlaties aizpildīt laukus ar kartes informāciju?</translation>
<translation id="5803412860119678065">Vai vēlaties aizpildīt lauku ar informāciju “<ph name="CARD_DETAIL" />”?</translation>
<translation id="5810442152076338065">Savienojums ar domēnu <ph name="DOMAIN" /> ir šifrēts, izmantojot novecojušu šifra komplektu.</translation>
-<translation id="5810928923025889964">No iegultas lapas šajā lapā</translation>
<translation id="5813119285467412249">&amp;Pievienošanas atsaukuma atcelšana</translation>
<translation id="5838278095973806738">Neievadiet šajā vietnē sensitīvu informāciju (piemēram, paroles vai kredītkartes), jo to var nozagt uzbrucēji.</translation>
<translation id="5866257070973731571">Tālruņa numura pievienošana</translation>
@@ -729,21 +765,19 @@
<translation id="6446608382365791566">Papildu informācijas pievienošana</translation>
<translation id="6447842834002726250">Sīkfaili</translation>
<translation id="6451458296329894277">Apstiprināt veidlapas atkārtotu iesniegšanu</translation>
-<translation id="6456339708790392414">Maksājums</translation>
<translation id="647261751007945333">Ierīces politikas</translation>
<translation id="6477321094435799029">Pārlūkā Chrome tika noteikts, ka šajā lapā ir neparasts kods. Lapa tika bloķēta, lai aizsargātu jūsu personas informāciju (piemēram, paroles, tālruņa numurus un kredītkaršu informāciju).</translation>
<translation id="6489534406876378309">Sākt avāriju datu augšupielādi</translation>
<translation id="6507833130742554667">Tiek pieņemtas kredītkartes un debetkartes.</translation>
<translation id="6508722015517270189">Restartējiet pārlūku Chrome</translation>
-<translation id="6521373090216409766">Vai vēlaties atkārtoti ielādēt šo vietni?</translation>
<translation id="6529602333819889595">&amp;Dzēšanas atsaukuma atcelšana</translation>
<translation id="6534179046333460208">Fiziskā tīmekļa ieteikumi</translation>
<translation id="6550675742724504774">Opcijas</translation>
-<translation id="6556239504065605927">Drošs savienojums</translation>
<translation id="6556915248009097796">Derīguma termiņš: <ph name="EXPIRATION_DATE_ABBR" />; pēdējoreiz izmantota: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Jūsu vadītājs vēl nav to apstiprinājis</translation>
<translation id="6569060085658103619">Jūs skatāt paplašinājumu lapu.</translation>
<translation id="6596325263575161958">Šifrēšanas opcijas</translation>
+<translation id="6604181099783169992">Kustību un gaismas sensori</translation>
<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>
@@ -815,6 +849,7 @@
<translation id="7275334191706090484">Pārvaldītās grāmatzīmes</translation>
<translation id="7298195798382681320">Ieteicams</translation>
<translation id="7309308571273880165">Avārijas pārskats notverts: <ph name="CRASH_TIME" /> (augšupielādi pieprasījis lietotājs; augšupielāde vēl nav veikta)</translation>
+<translation id="7320336641823683070">Savienojuma palīdzība</translation>
<translation id="7334320624316649418">&amp;Atcelt pārkārtošanas atsaukšanu</translation>
<translation id="733923710415886693">Servera sertifikāts netika atklāts, izmantojot Certificate Transparency.</translation>
<translation id="7353601530677266744">Komandrinda</translation>
@@ -899,6 +934,7 @@
<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="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="7862185352068345852">Vai aizvērt vietni?</translation>
<translation id="7878176543348854470">Tiek pieņemtas debetkartes un priekšapmaksas kartes.</translation>
<translation id="7878562273885520351">Iespējams, jūsu parole ir apdraudēta</translation>
<translation id="7887683347370398519">Pārbaudiet CVC kodu un mēģiniet vēlreiz.</translation>
@@ -921,6 +957,7 @@
<translation id="8041940743680923270">Izmantot globālo noklusējumu (Vaicāt)</translation>
<translation id="8042918947222776840">Izvēlēties saņemšanas veidu</translation>
<translation id="8057711352706143257">Programmatūra <ph name="SOFTWARE_NAME" /> nav pareizi konfigurēta. Atinstalējot programmatūru <ph name="SOFTWARE_NAME" />, parasti problēma tiek novērsta. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Vai atkārtoti ielādēt vietni?</translation>
<translation id="8088680233425245692">Rakstu neizdevās skatīt.</translation>
<translation id="8091372947890762290">Aktivizācija vēl nav apstiprināta serverī.</translation>
<translation id="8094917007353911263">Iespējams, izmantotajā tīklā tiks pieprasīts apmeklēt vietni <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -936,6 +973,7 @@
<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>
<translation id="8205463626947051446">Vietnē tiek rādītas traucējošas reklāmas.</translation>
+<translation id="8211406090763984747">Savienojums ir drošs</translation>
<translation id="8218327578424803826">Piešķirtā atrašanās vieta:</translation>
<translation id="8225771182978767009">Persona, kura iestatīja šo datoru, izvēlējās bloķēt šo vietni.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -947,6 +985,7 @@
<translation id="825929999321470778">Rādīt visas saglabātās paroles</translation>
<translation id="8261506727792406068">Dzēst</translation>
<translation id="8267698848189296333">Notiek pierakstīšanās lietotāja <ph name="USERNAME" /> kontā</translation>
+<translation id="8286036467436129157">Pierakstīties</translation>
<translation id="8288807391153049143">Rādīt sertifikātu</translation>
<translation id="8289355894181816810">Sazinieties ar tīkla administratoru, ja neesat pārliecināts, ko tas nozīmē.</translation>
<translation id="8293206222192510085">Pievienot grāmatzīmi</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Atbalstītās kredītkartes un priekšapmaksas kartes</translation>
<translation id="8759274551635299824">Kartes derīguma termiņš ir beidzies</translation>
<translation id="8761567432415473239">Google drošās pārlūkošanas tehnoloģija nesen vietnē <ph name="SITE" /> <ph name="BEGIN_LINK" />atklāja kaitīgas programmas<ph name="END_LINK" />.</translation>
+<translation id="8763927697961133303">USB ierīce</translation>
<translation id="8790007591277257123">&amp;Atcelt dzēšanas atsaukšanu</translation>
<translation id="8800988563907321413">Šeit tiks parādīti funkcijas Tuvumā ieteikumi</translation>
<translation id="8820817407110198400">Grāmatzīmes</translation>
diff --git a/chromium/components/strings/components_strings_ml.xtb b/chromium/components/strings/components_strings_ml.xtb
index fd749bec25a..cde62218127 100644
--- a/chromium/components/strings/components_strings_ml.xtb
+++ b/chromium/components/strings/components_strings_ml.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;അച്ചടിക്കൂ...</translation>
<translation id="1181037720776840403">നീക്കംചെയ്യൂ</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />സുരക്ഷയെ ബാധിക്കാൻ സാധ്യതയുള്ള കാര്യങ്ങളുടെ വിശദാംശങ്ങൾ<ph name="END_WHITEPAPER_LINK" /> സ്വയമേവ Google-ൽ റിപ്പോർട്ടുചെയ്യുന്നു. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">പേയ്‌മെന്റ് പൂർത്തിയായിട്ടില്ല</translation>
<translation id="1201402288615127009">അടുത്തത്</translation>
<translation id="1201895884277373915">ഈ സൈറ്റിൽ നിന്നും കൂടുതൽ</translation>
<translation id="1206967143813997005">പ്രാരംഭ സിഗ്നേച്ചർ ശരിയല്ല</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575"><ph name="CRASH_TIME" />-ന് ക്യാപ്‌ച്ചർ ചെയ്‌ത ക്രാഷ് റിപ്പോർട്ട് (ഇതുവരെ അപ്‌ലോഡുചെയ്‌തിട്ടോ അവഗണിച്ചിട്ടോ ഇല്ല)</translation>
<translation id="1270502636509132238">പിക്കപ്പ് രീതി</translation>
<translation id="1285320974508926690">ഈ സൈറ്റ് ഒരിക്കലും വിവര്‍‌ത്തനം ചെയ്യരുത്</translation>
+<translation id="1294154142200295408">കമാൻഡ്-ലൈൻ വ്യതിയാനങ്ങൾ</translation>
<translation id="129553762522093515">സമീപകാലത്ത് അടച്ചവ</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />നിങ്ങളുടെ കുക്കികൾ മായ്‌ക്കുന്നത് പരീക്ഷിക്കുക<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">നിങ്ങളുടെ ആക്‌റ്റിവിറ്റി ഇനിപ്പറയുന്നവയ്‌ക്ക് <ph name="BEGIN_EMPHASIS" />തുടർന്നും ദൃശ്യമായേക്കും<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">ക്രെഡിറ്റ് കാർഡുകളും ഡെബിറ്റ് കാർഡുകളും സ്വീകരിക്കുന്നു</translation>
<translation id="1519264250979466059">ബിൽഡ് തീയതി</translation>
<translation id="1527263332363067270">കണക്ഷനുവേണ്ടി കാക്കുന്നു…</translation>
+<translation id="1532118530259321453">ഈ പേജ് പറയുന്നത്:</translation>
<translation id="153384715582417236">ഇപ്പോൾ ഇത്രമാത്രമേ ലഭ്യമായിട്ടുള്ളൂ</translation>
<translation id="154408704832528245">ഡെലിവറി നൽകേണ്ട വിലാസം തിരഞ്ഞെടുക്കുക</translation>
<translation id="1549470594296187301">ഈ ഫീച്ചർ ഉപയോഗിക്കാൻ JavaScript പ്രവർത്തനക്ഷമമാക്കിയിരിക്കണം.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />പ്രോക്‌സിയും ഫയർവാളും പരിശോധിക്കുന്നു<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">തപാൽ കോഡ്</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{ഒരു നിർദ്ദേശം}other{# നിർദ്ദേശങ്ങൾ}}</translation>
-<translation id="2065985942032347596">ആധികാരികത ആവശ്യമാണ്</translation>
<translation id="2079545284768500474">പഴയപടിയാക്കുക</translation>
<translation id="20817612488360358">സിസ്റ്റം പ്രോക്‌സി ക്രമീകരണം ഉപയോഗിക്കുന്നതിനായി സജ്ജമാക്കി, പക്ഷെ ഒരു സ്‌പഷ്‌ടമായ പ്രോക്‌സി കോൺഫിഗറേഷനും അതോടൊപ്പം നിർദ്ദേശിച്ചിരിക്കുന്നു.</translation>
<translation id="2091887806945687916">ശബ്‌ദം</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">പേയ്‌മെന്‍റ് റദ്ദാക്കുക</translation>
<translation id="2147827593068025794">പശ്ചാത്തലം സമന്വയിപ്പിക്കൽ</translation>
<translation id="2148613324460538318">കാർഡ് ചേർക്കുക</translation>
-<translation id="2149973817440762519">ബുക്മാര്‍ക്ക് എഡിറ്റ് ചെയ്യുക</translation>
<translation id="2154054054215849342">നിങ്ങളുടെ ഡൊമെയ്‌നിന് വേണ്ടി സമന്വയം ലഭ്യമല്ല</translation>
<translation id="2154484045852737596">കാർഡ് എഡിറ്റുചെയ്യുക</translation>
<translation id="2166049586286450108">പൂർണ്ണമായ അഡ്‌മിൻ ആക്‌സസ്സ്</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">പിക്കപ്പ് വിലാസം തിരഞ്ഞെടുക്കുക</translation>
<translation id="2740531572673183784">ശരി</translation>
<translation id="2742870351467570537">തിരഞ്ഞെടുത്ത ഇനങ്ങള്‍‌ നീക്കംചെയ്യുക </translation>
-<translation id="2744590937989388266">ഈ പേജിൽ ഉൾച്ചേർത്തിട്ടുള്ള ഒരു പേജിൽ നിന്ന്</translation>
<translation id="277133753123645258">ഷിപ്പിംഗ് രീതി</translation>
<translation id="277499241957683684">ഉപകരണ റെക്കോർഡ് കാണുന്നില്ല</translation>
<translation id="2784949926578158345">കണക്ഷന്‍ പുനഃസജ്ജമാക്കിയതാണ്.</translation>
<translation id="2788784517760473862">ക്രെഡിറ്റ് കാർഡുകൾ സ്വീകരിക്കുന്നു</translation>
<translation id="2794233252405721443">സൈറ്റ് ബ്ലോക്കുചെയ്‌തു</translation>
-<translation id="2795286477369100655">ഈ സൈറ്റ് വിടണോ?</translation>
<translation id="2799020568854403057">നിങ്ങൾ പോകുന്ന സൈറ്റിൽ ദോഷകരമായ ആപ്പുകളുണ്ട്</translation>
<translation id="2803306138276472711"><ph name="SITE" /> എന്നതിൽ Google സുരക്ഷിത ബ്രൗസിംഗ് ഈയിടെ <ph name="BEGIN_LINK" />മാൽവെയർ കണ്ടെത്തി<ph name="END_LINK" />. സാധാരണ നിലയിൽ സുരക്ഷിതമായ വെബ്സൈറ്റുകളിൽ ചിലപ്പോൾ മാൽവെയർ ഉണ്ടായേക്കാം.</translation>
<translation id="2824775600643448204">വിലാസവും തിരയൽ ബാറും</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">ലിസ്റ്റ് എൻട്രി "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">സ്വയമേവ ബ്ലോക്കുചെയ്‌തു</translation>
<translation id="3024663005179499861">തെറ്റായ നയ തരം</translation>
-<translation id="3032412215588512954">ഈ സൈറ്റ് റീലോഡുചെയ്യണോ?</translation>
<translation id="3037605927509011580">കഷ്ടം!</translation>
<translation id="3039538478787849737">Google-ൽ കാർഡ് സംരക്ഷിക്കണോ?</translation>
<translation id="3041612393474885105">സര്‍‌ട്ടിഫിക്കറ്റ് വിവരങ്ങള്‍‌</translation>
@@ -309,6 +305,7 @@
<translation id="3176929007561373547">പ്രോക്‌സി സെർവർ പ്രവർത്തിക്കുന്നുവെന്ന് ഉറപ്പാക്കാൻ
നിങ്ങളുടെ പ്രോക്‌സി ക്രമീകരണം പരിശോധിക്കുകയോ നെറ്റ്‌വർക്ക് അഡ്‌മിനിസ്‌ട്രേറ്ററെ ബന്ധപ്പെടുകയോ ചെയ്യുക. നിങ്ങൾ ഉപയോഗിക്കുന്നത് ഒരു പ്രോക്‌സി സെർവറാണെന്ന് കരുതുന്നില്ലെങ്കിൽ:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="SERVER_NAME" /> എന്നതിലെ <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">പേയ്‌മെന്റ് റദ്ദാക്കുക</translation>
<translation id="3207960819495026254">ബുക്ക്‌മാർക്കുചെയ്‌തു</translation>
<translation id="3209375525920864198">സാധുതയുള്ളൊരു സെഷൻ പേര് നൽകുക.</translation>
@@ -366,11 +363,57 @@
<translation id="3556433843310711081">നിങ്ങൾക്ക് വേണ്ടി ഇത് അൺബ്ലോക്കുചെയ്യാൻ മാനേജർക്ക് കഴിയും</translation>
<translation id="3566021033012934673">നിങ്ങളുടെ കണക്ഷൻ സ്വകാര്യമല്ല</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" /> സൈറ്റിലെ ഉൾച്ചേർത്ത പേജ് പറയുന്നത്:</translation>
<translation id="358285529439630156">ക്രെഡിറ്റ് കാർഡുകളും പ്രീപെയ്ഡ് കാർഡുകളും സ്വീകരിക്കുന്നു.</translation>
<translation id="3582930987043644930">പേര് ചേർക്കുക</translation>
<translation id="3583757800736429874">&amp;നീക്കുന്നത് വീണ്ടും ചെയ്യുക</translation>
<translation id="3586931643579894722">വിശദാംശങ്ങൾ മറയ്‌ക്കുക‍‌</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;കണക്ഷൻ പ്രശ്നങ്ങൾ പരിഹരിക്കുക&lt;/h1&gt;
+ &lt;p&gt;നിങ്ങളൊരു വെബ്‌സൈറ്റ് സന്ദർശിക്കാൻ ശ്രമിക്കുമ്പോൾ നിങ്ങൾക്കൊരു പിശക് സന്ദേശം ലഭിക്കുന്നുവെങ്കിൽ, ഈ പരിഹാരമാർഗ്ഗങ്ങൾ ശ്രമിക്കുക.&lt;/p&gt;
+ &lt;h2&gt;മിക്ക കണക്ഷൻ പിശകുകളും പരിഹരിക്കുക&lt;/h2&gt;
+ &lt;p&gt;നിങ്ങളൊരു വെബ്‌സൈറ്റ് സന്ദർശിക്കാൻ ശ്രമിക്കുകയും അത് തുറക്കാതിരിക്കുകയുമാണെങ്കിൽ, ഇനിപ്പറയുന്ന ട്രബിള്‍ഷൂട്ടിംഗ് ഘട്ടങ്ങൾ ഉപയോഗിച്ച്, പ്രശ്നം പരിഹരിക്കാൻ ശ്രമിക്കുക:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;അക്ഷരത്തെറ്റ് വന്നിട്ടുണ്ടോ എന്നറിയാൻ വെബ് വിലാസം പരിശോധിക്കുക.&lt;/li&gt;
+ &lt;li&gt;ഇന്റർനെറ്റ് കണക്ഷൻ സാധാരണ ഗതിയിൽ പ്രവർത്തിക്കുന്നുവെന്ന് ഉറപ്പാക്കുക.&lt;/li&gt;
+ &lt;li&gt;വെബ്‌സറ്റിന്റെ ഉടമയെ ബന്ധപ്പെടുക.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;നിർദ്ദിഷ്ട പിശക് സന്ദേശവുമായി ബന്ധപ്പെട്ട് സഹായം സ്വീകരിക്കുക&lt;/h2&gt;
+ &lt;h3&gt;"നിങ്ങളുടെ കണക്ഷൻ സ്വകാര്യമല്ല" അല്ലെങ്കിൽ "NET::ERR_CERT_AUTHORITY_INVALID" അല്ലെങ്കിൽ "ERR_CERT_COMMON_NAME_INVALID" അല്ലെങ്കിൽ "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" അല്ലെങ്കിൽ "SSL സർട്ടിഫിക്കറ്റ് പിശക്"&lt;/h3&gt;
+ &lt;h4&gt;ഘട്ടം 1: പോർട്ടലിലേക്ക് സൈൻ ഇൻ ചെയ്യുക&lt;/h4&gt;
+ &lt;p&gt;കഫേകളിലോ വിമാനത്താവളങ്ങളിലോ ലഭ്യമാക്കിയിട്ടുള്ള വൈ‌ഫൈ നെറ്റ്‌വർക്കുകൾ ഉപയോഗിക്കാൻ നിങ്ങൾ സൈൻ ഇൻ ചെയ്യേണ്ടതുണ്ട്. സൈൻ-ഇൻ പേജ് കാണുന്നതിന്, &lt;code&gt;http://&lt;/code&gt; ഉപയോഗിക്കുന്ന ഒരു പേജ് കാണുക.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;&lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt; പോലെ, &lt;code&gt;http://&lt;/code&gt; ഉപയോഗിച്ച് തുടങ്ങുന്ന ഏതൊരു വെബ്‌സൈറ്റിലേക്കും പോവുക.&lt;/li&gt;
+ &lt;li&gt;തുറക്കുന്ന സൈൻ-ഇൻ പേജിൽ, ഇന്റർനെറ്റ് ഉപയോഗിക്കാൻ സൈൻ ഇൻ ചെയ്യുക.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;ഘട്ടം 2: അദൃശ്യ മോഡിൽ പേജ് തുറക്കുക (കമ്പ്യൂട്ടർ മാത്രം)&lt;/h4&gt;
+ &lt;p&gt;ഒരു അദൃശ്യ വിൻ-ഡോയിൽ നിങ്ങൾ സന്ദർശിക്കുകയായിരുന്ന പേജ് തുറക്കുക.&lt;/p&gt;
+ &lt;p&gt;പേജ് തുറക്കുന്നുവെങ്കിൽ, ഒരു Chrome വിപുലീകരണം ശരിയായി പ്രവർത്തിക്കുന്നില്ല. ഈ പിശക് പരിഹരിക്കാൻ, വിപുലീകരണം ഓഫാക്കുക.&lt;/p&gt;
+ &lt;h4&gt;ഘട്ടം 3: നിങ്ങളുടെ ഓപ്പറേറ്റിംഗ് സിസ്റ്റം അപ്‌ഡേറ്റ് ചെയ്യുക&lt;/h4&gt;
+ &lt;p&gt;നിങ്ങളുടെ ഉപകരണം അപ്-ടു-ഡേറ്റ് ആണെന്ന് ഉറപ്പാക്കുക.&lt;/p&gt;
+ &lt;h4&gt;ഘട്ടം 4: ആന്റീവൈറസ് താൽക്കാലികമായി ഓഫാക്കുക&lt;/h4&gt;
+ &lt;p&gt;നിങ്ങൾക്ക് "HTTPS പരിരക്ഷയോ" "HTTPS സ്‌കാനിംഗോ" നൽകുന്ന ആന്റീവൈറസ് സോഫ്റ്റ്‌വെയർ ഉണ്ടെങ്കിൽ, നിങ്ങൾ ഈ പിശക് കാണും. സുരക്ഷ നൽകുന്നതിൽ നിന്ന് Chrome-നെ ആന്റീവൈറസ് തടയുകയാണ്.&lt;/p&gt;
+ &lt;p&gt;ഈ പ്രശ്‌നം പരിഹരിക്കാൻ, നിങ്ങളുടെ ആന്റീവൈറസ് സോഫ്റ്റ്‌വെയർ ഓഫാക്കുക. സോഫ്റ്റ്‌വെയർ ഓഫാക്കിയതിന് ശേഷം പേജ് പ്രവർത്തിക്കുന്നുവെങ്കിൽ, നിങ്ങൾ സുരക്ഷിതമായ സൈറ്റുകൾ ഉപയോഗിക്കുമ്പോഴൊക്കെ ഈ സോഫ്റ്റ്‌വെയർ ഓഫാക്കുക.&lt;/p&gt;
+ &lt;p&gt;ചെയ്‌തുകഴിഞ്ഞാൽ, ആന്റീവൈറസ് പ്രോഗ്രാം വീണ്ടും ഓണാക്കാൻ മറക്കരുത്.&lt;/p&gt;
+ &lt;h4&gt;ഘട്ടം 5: അധിക സഹായം സ്വീകരിക്കുക&lt;/h4&gt;
+ &lt;p&gt;നിങ്ങൾ ഇപ്പോഴും പിശക് കാണുന്നുവെങ്കിൽ, വെബ്‌സൈറ്റിന്റെ ഉടമയെ ബന്ധപ്പെടുക.&lt;/p&gt;
+ &lt;h3&gt;"നെറ്റ്‌വർക്കിലേക്ക് കണക്‌റ്റ് ചെയ്യുക"&lt;/h3&gt;
+ &lt;p&gt;ഓൺലൈൻ ആകുന്നതിന് സൈൻ ചെയ്യേണ്ടതില്ലാത്ത ഒരു വൈഫൈ പോർട്ടലാണ് നിങ്ങൾ ഉപയോഗിക്കുന്നതെങ്കിൽ, നിങ്ങൾ ഈ പിശക് കാണും.&lt;/p&gt;
+ &lt;p&gt;പിശക് പരിഹരിക്കാൻ, നിങ്ങൾ തുറക്കാൻ ശ്രമിക്കുന്ന പേജിൽ &lt;strong&gt;കണക്‌റ്റ് ചെയ്യുക&lt;/strong&gt; ക്ലിക്ക് ചെയ്യുക.&lt;/p&gt;
+ &lt;h3&gt;"നിങ്ങളുടെ സമയം പിന്നിലാണ്" അല്ലെങ്കിൽ "നിങ്ങളുടെ സമയം മുന്നിലാണ്" അല്ലെങ്കിൽ "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;നിങ്ങളുടെ കമ്പ്യൂട്ടറിന്റെയോ മൊബൈൽ ഉപകരണത്തിന്റെയോ തീയതിയും സമയവും കൃത്യമല്ലെങ്കിൽ ഈ പിശക് കാണും.&lt;/p&gt;
+ &lt;p&gt;പിശക് പരിഹരിക്കാൻ, ഉപകരണത്തിന്റെ ക്ലോക്ക് തുറക്കുക. സമയവും തീയതിയും കൃത്യമാണെന്ന് ഉറപ്പാക്കുക.&lt;/p&gt;
+ &lt;h3&gt;"വെബിലേക്ക് സുരക്ഷിതമായി കണക്‌റ്റ് ചെയ്യുന്നതിൽ നിന്ന് Chrome-നെ നിങ്ങളുടെ കമ്പ്യൂട്ടറിലെ സോഫ്റ്റ്‌വെയർ തടയുന്നു" (Windows കമ്പ്യൂട്ടറുകളിൽ മാത്രം)&lt;/h3&gt;
+ &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;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; തിരഞ്ഞെടുക്കുക
+ &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="3615877443314183785">കാലഹരണപ്പെടുന്ന ശരിയായ തീയതി നല്‍കുക</translation>
<translation id="36224234498066874">ബ്രൌസിംഗ് ഡാറ്റ മായ്‌ക്കുക...</translation>
<translation id="362276910939193118">മുഴുവന്‍ ചരിത്രവും കാണിക്കുക</translation>
@@ -403,7 +446,6 @@
<translation id="3778403066972421603">ഈ കാർഡ് നിങ്ങളുടെ Google അക്കൗണ്ടിലും ഈ ഉപകരണത്തിലും സംരക്ഷിക്കണോ?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" />-ൽ അവസാനിക്കുന്നു</translation>
-<translation id="3800436529451849929"><ph name="SITE" /> എന്ന സൈറ്റിൽ നിന്ന്</translation>
<translation id="382518646247711829">നിങ്ങൾ ഒരു പ്രോക്‌സി സെർവർ ഉപയോഗിക്കുന്നെങ്കിൽ...</translation>
<translation id="3828924085048779000">ശൂന്യ പാസ്ഫ്രെയ്സ് അനുവദനീയമല്ല.</translation>
<translation id="385051799172605136">പിന്നോട്ട്</translation>
@@ -417,6 +459,7 @@
<translation id="3945915738023014686"><ph name="CRASH_ID" /> എന്ന ക്രാഷ് റിപ്പോർട്ട് ഐഡി അപ്‌ലോഡുചെയ്‌തു (ലോക്കൽ ക്രാഷ് ഐഡി: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">ഈ സെർവറിന് ഇത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; അതിന്റെ സുരക്ഷാ സർട്ടിഫിക്കറ്റ് വിഷയേതര നാമങ്ങൾ വ്യക്തമാക്കുന്നില്ല. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു അക്രമി നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്.</translation>
<translation id="3949601375789751990">നിങ്ങളുടെ ബ്രൗസിംഗ് ചരിത്രം ഇവിടെ ദൃശ്യമാകും</translation>
+<translation id="3950820424414687140">സൈൻ ഇൻ</translation>
<translation id="3963721102035795474">റീഡർ മോഡ്</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{ഒന്നുമില്ല}=1{ഒരു സൈറ്റിൽ നിന്ന് }other{# സൈറ്റുകളിൽ നിന്ന് }}</translation>
<translation id="397105322502079400">കണക്കാക്കുന്നു...</translation>
@@ -433,6 +476,7 @@
<translation id="4103249731201008433">ഉപകരണ സീരിയൽ നമ്പർ അസാധുവാണ്</translation>
<translation id="410351446219883937">സ്വയം പ്ലേചെയ്യൽ</translation>
<translation id="4103763322291513355">ബ്ലാക്ക്‌ലിസ്റ്റിൽപ്പെട്ട URL-കളുടെ ലിസ്റ്റും നിങ്ങളുടെ സിസ്റ്റം അഡ്‌മിനിസ്‌ട്രേറ്റർ നടപ്പിലാക്കിയ മറ്റ് നയങ്ങളും കാണുന്നതിന് &lt;strong&gt;chrome://policy&lt;/strong&gt; സന്ദർശിക്കുക.</translation>
+<translation id="4110652170750985508">നിങ്ങളുടെ പേയ്‌മെന്റ് അവലോകനം ചെയ്യുക</translation>
<translation id="4116663294526079822">ഈ സൈറ്റിൽ എല്ലായ്‌പ്പോഴും അനുവദിക്കുക</translation>
<translation id="4117700440116928470">നയ സ്‌കോപ്പ് പിന്തുണയ്ക്കുന്നില്ല.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{മറ്റൊരെണ്ണം}other{മറ്റ് # എണ്ണം}}</translation>
@@ -459,7 +503,6 @@
<translation id="4269787794583293679">(ഉപയോക്തൃനാമമില്ല)</translation>
<translation id="4275830172053184480">നിങ്ങളുടെ ഉപകരണം പുനരാരംഭിക്കുക</translation>
<translation id="4280429058323657511">, <ph name="EXPIRATION_DATE_ABBR" />-ന് കാലാവധി തീരുന്നു</translation>
-<translation id="4304224509867189079">ലോഗ് ഇന്‍ ചെയ്യുക</translation>
<translation id="4312866146174492540">ബ്ലോക്കുചെയ്യുക (ഡിഫോൾട്ട്)</translation>
<translation id="4325863107915753736">ലേഖനം കണ്ടെത്തുന്നത് പരാജയപ്പെട്ടു</translation>
<translation id="4326324639298822553">കാലാവധി തീരുന്ന തീയതി പരിശോധിച്ച് വീണ്ടും ശ്രമിച്ചുനോക്കൂ</translation>
@@ -481,14 +524,12 @@
<translation id="4515275063822566619">കാർഡുകളും വിലാസങ്ങളും Chrome-ൽ നിന്നും നിങ്ങളുടെ അ‌ക്കൗണ്ടിൽ (<ph name="ACCOUNT_EMAIL" />) നിന്നുമുള്ളതുമാണ്. നിങ്ങൾക്ക് ഇവ <ph name="BEGIN_LINK" />ക്രമീകരണത്തിൽ<ph name="END_LINK" /> മാനേജുചെയ്യാം.</translation>
<translation id="4522570452068850558">വിശദാംശങ്ങൾ‌</translation>
<translation id="4552089082226364758">ഫ്ലാഷ്</translation>
-<translation id="4554702541363482291"><ph name="SITE" /> എന്ന സൈറ്റിൽ ഉൾച്ചേർത്തിട്ടുള്ള ഒരു പേജിൽ നിന്ന്</translation>
<translation id="4558551763791394412">നിങ്ങളുടെ വിപുലീകരണങ്ങൾ പ്രവർത്തനരഹിതമാക്കുന്നത് പരീക്ഷിക്കുക.</translation>
<translation id="457875822857220463">ഡെലിവറി വിവരങ്ങൾ</translation>
<translation id="4582800630050655161">നിങ്ങളുടെ Google അക്കൗണ്ടിലേക്കുള്ള ആക്‌സസ് നഷ്‌ടമാകാനോ നിങ്ങളുടെ ഐഡന്‍റിറ്റി മോഷ്ടിക്കപ്പെടാനോ സാധ്യതയുണ്ട്. ഇപ്പോൾ തന്നെ പാസ്‍വേഡ് മാറ്റാൻ Chromium നിർദ്ദേശിക്കുന്നു.</translation>
<translation id="4587425331216688090">Chrome-ൽ നിന്ന് വിലാസം നീക്കംചെയ്യണോ?</translation>
<translation id="4592951414987517459"><ph name="DOMAIN" /> എന്നതിലേക്കുള്ള നിങ്ങളുടെ കണക്ഷനെ ആധുനിക സൈഫർ സ്യൂട്ട് ഉപയോഗിച്ച് എൻക്രിപ്റ്റുചെയ്‌തിരിക്കുന്നു.</translation>
<translation id="4594403342090139922">&amp;ഇല്ലാതാക്കുന്നത് പഴയപടിയാക്കുക</translation>
-<translation id="4611292653554630842">ലോഗ് ഇന്‍ ചെയ്യുക</translation>
<translation id="4619615317237390068">മറ്റ് ഉപകരണങ്ങളിൽ നിന്നുള്ള ടാബുകൾ</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">ഈ സെർവറിന് അത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; അതിന്റെ സുരക്ഷാ സർട്ടിഫിക്കറ്റിൽ പിശകുകൾ അടങ്ങിയിരിക്കുന്നു. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു അക്രമണകാരി നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്.</translation>
@@ -498,11 +539,9 @@
<translation id="4708268264240856090">നിങ്ങളുടെ കണക്ഷൻ തടസ്സപ്പെട്ടു</translation>
<translation id="471880041731876836">ഈ സൈറ്റ് സന്ദർശിക്കാൻ നിങ്ങൾക്ക് അനുമതി ആവശ്യമില്ല</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows നെറ്റ്‌വർക്ക് ഡയഗണോസ്‌റ്റിക്‌സ് റൺ ചെയ്യുന്നു<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">നിങ്ങളുടെ പേയ്മെന്റ്</translation>
<translation id="4726672564094551039">നയങ്ങൾ വീണ്ടും ലോഡുചെയ്യുക</translation>
<translation id="4728558894243024398">പ്ലാറ്റ്ഫോം</translation>
<translation id="4736825316280949806">Chromium റീസ്‌റ്റാർട്ടുചെയ്യുക</translation>
-<translation id="4737498291095696011">ഈ പേജിൽ നിന്ന്</translation>
<translation id="4744603770635761495">നിര്‍വ്വഹിക്കാവുന്ന പാത</translation>
<translation id="4749685221585524849"><ph name="LAST_USED_MONTH" />-ന് അവസാനമായി ഉപയോഗിച്ചു</translation>
<translation id="4750917950439032686">നിങ്ങളുടെ വിവരങ്ങൾ (ഉദാഹരണത്തിന്, പാസ്‌വേഡുകളോ ക്രെഡിറ്റ് കാർഡ് നമ്പറുകളോ) ഈ സൈറ്റിലേക്ക് അയച്ച് കഴിഞ്ഞാൽ പിന്നെയത് സ്വകാര്യമായിരിക്കും.</translation>
@@ -521,16 +560,16 @@
<translation id="4850886885716139402">കാണുക</translation>
<translation id="4854362297993841467">ഈ ഡെലിവറി രീതി ലഭ്യമല്ല. മറ്റൊരു രീതി പരീക്ഷിക്കുക.</translation>
<translation id="4858792381671956233">ഈ സൈറ്റ് സന്ദർശിക്കുന്നതിന് നിങ്ങൾ രക്ഷിതാക്കളോട് അനുമതി ആവശ്യപ്പെട്ടു</translation>
-<translation id="4871132632506079383"><ph name="SITE" /> എന്ന സൈറ്റിൽ ഉൾച്ചേർത്തിട്ടുള്ള ഒരു പേജിൽ നിന്ന്</translation>
<translation id="4880827082731008257">തിരയൽ ചരിത്രം</translation>
+<translation id="4881695831933465202">തുറക്കുക</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">പരിശോധിച്ചുറപ്പിക്കൽ ആവശ്യമുണ്ട്</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{ഒരു വെബ്‌പേജ് കൂടിയുണ്ട്}other{# വെബ്‌പേജുകൾ കൂടിയുണ്ട്}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947"><ph name="CREDIT_CARD" /> കാർഡിന്‍റെ CVC നൽകുക. സ്ഥിരീകരിച്ച് കഴിഞ്ഞാൽ, നിങ്ങളുടെ Google പേയ്‌മെന്‍റ് അക്കൗണ്ടിൽ നിന്നുള്ള കാർഡ് വിശദാംശങ്ങൾ ഈ സൈറ്റുമായി പങ്കിടും.</translation>
<translation id="4923417429809017348">ഈ പേജിനെ അറിയപ്പെടാത്ത ഒരു ഭാഷയില്‍‌ നിന്നും <ph name="LANGUAGE_LANGUAGE" /> എന്നതിലേക്ക് വിവര്‍‌ത്തനം ചെയ്തു</translation>
<translation id="4923459931733593730">പേയ്‌മെന്റ് രീതി</translation>
<translation id="4926049483395192435">വ്യക്തമാക്കേണ്ടതാണ്.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> പറയുന്നത്:</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">പ്രവര്‍ത്തനങ്ങള്‍</translation>
<translation id="4958444002117714549">ലിസ്റ്റ് വിപുലീകരിക്കുക</translation>
@@ -539,7 +578,6 @@
<translation id="5002932099480077015">പ്രവർത്തനക്ഷമമാക്കിയെങ്കിൽ, വേഗത്തിൽ ഫോം പൂരിപ്പിക്കാൻ Chrome ഈ ഉപകരണത്തിൽ നിങ്ങളുടെ കാർഡിന്റെ ഒരു പകർപ്പ് സൂക്ഷിക്കും.</translation>
<translation id="5018422839182700155">ഈ പേജ് തുറക്കാനായില്ല</translation>
<translation id="5019198164206649151">ബാക്കിംഗ് സംഭരണം മോശം അവസ്ഥയിലാണ്</translation>
-<translation id="5020990877659450221">ഈ പേജിൽ നിന്ന്</translation>
<translation id="5023310440958281426">നിങ്ങളുടെ അഡ്‌മിനിസ്ട്രേറ്ററുടെ നയങ്ങൾ പരിശോധിക്കുക</translation>
<translation id="5029568752722684782">പകർപ്പ് മായ്‌ക്കുക</translation>
<translation id="503069730517007720">"<ph name="SOFTWARE_NAME" />" സോഫ്റ്റ്‌വെയറിന് ഒരു റൂട്ട് സർട്ടിഫിക്കറ്റ് ആവശ്യമാണ്, എന്നാൽ അത് ഇൻസ്‌റ്റാൾ ചെയ്‌‌തിട്ടില്ല. ഈ പ്രശ്‌നം പരിഹരിക്കാൻ, "<ph name="SOFTWARE_NAME" />" സോഫ്റ്റ്‌വെയറിനുള്ള കോൺഫിഗറേഷൻ നിർദ്ദേശങ്ങൾ ഐടി അഡ്‌മിനിസ്‌ട്രേറ്റർ പരിശോധിക്കേണ്ടതുണ്ട്. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -565,12 +603,12 @@
<translation id="5172758083709347301">മെഷീൻ</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> എന്നതില്‍‌ ഇല്ലേ? ഈ പിശക് റിപ്പോര്‍‌ട്ടുചെയ്യുക</translation>
<translation id="5190835502935405962">ബുക്ക്‌മാര്‍‌ക്കുകള്‍‌ ബാര്‍‌</translation>
+<translation id="5201306358585911203">ഈ പേജിലെ ഉൾച്ചേർത്ത പേജ് പറയുന്നത്:</translation>
<translation id="5205222826937269299">പേര് ആവശ്യമാണ്</translation>
<translation id="5222812217790122047">ഇമെയിൽ ആവശ്യമാണ്</translation>
<translation id="522700295135997067">നിങ്ങളുടെ പാസ്‍വേഡ് ഈ സൈറ്റ് ഇപ്പോൾ മോഷ്‌ടിച്ചിരിക്കാം</translation>
<translation id="5230733896359313003">ഷിപ്പിംഗ് വിലാസം</translation>
<translation id="5251803541071282808">ക്ലൗഡ്</translation>
-<translation id="5277279256032773186">ജോലിസ്ഥലത്തുള്ള Chrome ഉപയോഗിക്കുകയാണോ? ബിസിനസ് സ്ഥാപനങ്ങൾക്ക് അവരുടെ ജീവനക്കാർക്ക് വേണ്ടി Chrome ക്രമീകരണം മാനേജുചെയ്യാനാകും. കൂടുതലറിയുക</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />നിങ്ങൾക്ക് വെബിൽ കണക്റ്റുചെയ്യാൻ കഴിയുന്ന തരത്തിൽ താൽക്കാലികമായി സോഫ്റ്റ്‌വെയർ പ്രവർത്തനരഹിതമാക്കുന്നതിന് ഈ ഘട്ടങ്ങൾ പിന്തുടരുക. നിങ്ങൾക്ക് അഡ്‌മിനിസ്ട്രേറ്ററുടെ സവിശേഷാധികാരങ്ങൾ ആവശ്യമായിവരും.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -632,7 +670,6 @@
<translation id="5610142619324316209">കണക്ഷൻ പരിശോധിക്കുന്നു</translation>
<translation id="5610807607761827392">നിങ്ങൾക്ക് <ph name="BEGIN_LINK" />ക്രമീകരണത്തിൽ<ph name="END_LINK" /> കാർഡുകളും വിലാസങ്ങളും മാനേജുചെയ്യാം.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" />, നിരവധി തവണ നിങ്ങളെ റീഡയറക്‌ടുചെയ്‌തു.</translation>
-<translation id="5622887735448669177">നിങ്ങൾക്ക് ഈ സൈറ്റ് വിടണോ?</translation>
<translation id="5629630648637658800">നയ ക്രമീകരണങ്ങൾ ലോഡുചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു</translation>
<translation id="5631439013527180824">ഉപകരണ മാനേജുമെന്റ് ടോക്കൺ അസാധുവാണ്</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>
@@ -655,7 +692,6 @@
<translation id="5786044859038896871">നിങ്ങളുടെ കാർഡ് വിവരം പൂരിപ്പിക്കണോ?</translation>
<translation id="5803412860119678065">നിങ്ങളുടെ <ph name="CARD_DETAIL" /> പൂരിപ്പിക്കണോ?</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> എന്നതിലേക്കുള്ള നിങ്ങളുടെ കണക്ഷൻ കാലഹരണപ്പെട്ട സൈഫർ സ്യൂട്ട് ഉപയോഗിച്ച് എൻക്രിപ്റ്റുചെയ്‌തിരിക്കുന്നു.</translation>
-<translation id="5810928923025889964">ഈ പേജിൽ ഉൾച്ചേർത്തിട്ടുള്ള ഒരു പേജിൽ നിന്ന്</translation>
<translation id="5813119285467412249">&amp;ചേർക്കുന്നത് വീണ്ടും ചെയ്യുക</translation>
<translation id="5838278095973806738">അക്രമകാരികൾ മോഷ്‌ടിക്കാൻ സാധ്യതയുള്ളതിനാൽ ഈ സൈറ്റിൽ നിങ്ങളുടെ രഹസ്യ വിവരങ്ങളൊന്നും (ഉദാഹരണത്തിന്, പാസ്‌വേഡുകളോ ക്രെഡിറ്റ് കാർഡുകളോ പോലുള്ളവ) നൽകരുത്.</translation>
<translation id="5866257070973731571">ഫോണ്‍ നമ്പര്‍ ചേര്‍ക്കുക</translation>
@@ -729,21 +765,19 @@
<translation id="6446608382365791566">കൂടുതൽ വിവരങ്ങൾ ചേർക്കുക</translation>
<translation id="6447842834002726250">കുക്കികള്‍</translation>
<translation id="6451458296329894277">വീണ്ടും സമര്‍പ്പിക്കല്‍ അപേക്ഷ ഉറപ്പാക്കുക</translation>
-<translation id="6456339708790392414">നിങ്ങളുടെ പേയ്മെന്റ്</translation>
<translation id="647261751007945333">ഉപകരണ നയങ്ങൾ</translation>
<translation id="6477321094435799029">Chrome, ഈ പേജിൽ അസാധാരണമായ കോഡ് കണ്ടെത്തിയതിനാൽ നിങ്ങളുടെ വ്യക്തിഗത വിവരങ്ങൾ (ഉദാഹരണത്തിന്, പാസ്‌വേഡുകളും ഫോൺ നമ്പറുകളും ക്രെഡിറ്റ് കാർഡുകളും പോലുള്ളവ) പരിരക്ഷിക്കുന്നതിന് അതിനെ ബ്ലോക്കുചെയ്‌തു.</translation>
<translation id="6489534406876378309">ക്രാഷുകൾ അപ്‌ലോഡുചെയ്യുന്നത് ആരംഭിക്കുക</translation>
<translation id="6507833130742554667">ക്രെഡിറ്റ് കാർഡുകളും ഡെബിറ്റ് കാർഡുകളും സ്വീകരിക്കുന്നു.</translation>
<translation id="6508722015517270189">Chrome റീസ്‌റ്റാർട്ടുചെയ്യുക</translation>
-<translation id="6521373090216409766">ഈ സൈറ്റ് റീലോഡ് ചെയ്യണോ?</translation>
<translation id="6529602333819889595">&amp;ഇല്ലാതാക്കുന്നത് വീണ്ടും ചെയ്യുക</translation>
<translation id="6534179046333460208">ഫിസിക്കൽ വെബ് നിർദ്ദേശങ്ങൾ</translation>
<translation id="6550675742724504774">ഓപ്ഷനുകൾ</translation>
-<translation id="6556239504065605927">കണക്ഷൻ സുരക്ഷിതമാണ്</translation>
<translation id="6556915248009097796">കാലഹരണപ്പെടുന്ന തീയതി: <ph name="EXPIRATION_DATE_ABBR" />, <ph name="LAST_USED_DATE_NO_DETAIL" />-ന് അവസാനമായി ഉപയോഗിച്ചു</translation>
<translation id="6563469144985748109">നിങ്ങളുടെ മാനേജർ ഇതുവരെ അംഗീകാരം നൽകിയിട്ടില്ല</translation>
<translation id="6569060085658103619">നിങ്ങൾ ഒരു വിപുലീകരണ പേജാണ് കാണുന്നത്</translation>
<translation id="6596325263575161958">എൻക്രിപ്‌ഷൻ ഓപ്‌ഷനുകൾ</translation>
+<translation id="6604181099783169992">ചലന അല്ലെങ്കിൽ വെളിച്ച സെൻസറുകൾ</translation>
<translation id="6624427990725312378">കോണ്‍ടാക്റ്റ് വിവരം</translation>
<translation id="6626291197371920147">ശരിയായ കാർഡ് നമ്പർ ചേർക്കുക</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> തിരയൽ</translation>
@@ -815,6 +849,7 @@
<translation id="7275334191706090484">നിയന്ത്രിത ബുക്ക്‌മാർക്കുകൾ</translation>
<translation id="7298195798382681320">ശുപാർശചെയ്യുന്നത്</translation>
<translation id="7309308571273880165"><ph name="CRASH_TIME" />-ന് ക്യാപ്‌ചർ ചെയ്‌ത ക്രാഷ് റിപ്പോർട്ടുകൾ (ഉപയോക്താവ് അഭ്യർത്ഥിച്ച അപ്‌ലോഡ്, ഇതുവരെ അപ്‌ലോഡുചെയ്‌തിട്ടില്ല)</translation>
+<translation id="7320336641823683070">കണക്ഷൻ സഹായം</translation>
<translation id="7334320624316649418">&amp;പുനഃക്രമീകരിക്കുന്നത് വീണ്ടും ചെയ്യുക</translation>
<translation id="733923710415886693">സർട്ടിഫിക്കറ്റ് സുതാര്യതയിലൂടെ സെർവറുടെ സർട്ടിഫിക്കറ്റ് വെളിപ്പെടുത്തിയിട്ടില്ല.</translation>
<translation id="7353601530677266744">കമാന്‍റ് ലൈന്‍‌</translation>
@@ -899,6 +934,7 @@
<translation id="782886543891417279">നിങ്ങൾ ഉപയോഗിക്കുന്ന Wi-Fi (<ph name="WIFI_NAME" />) അതിന്റെ ലോഗിൻ പേജ് സന്ദർശിക്കാൻ ആവശ്യപ്പെടാം..</translation>
<translation id="785549533363645510">എന്നിരുന്നാലും നിങ്ങൾ അദൃശ്യനല്ല. ആൾമാറാട്ടത്തിലേയ്‌ക്ക് പോകുന്നത്, നിങ്ങളുടെ തൊഴിൽ ദാതാവിൽ നിന്നോ ഇന്റർനെറ്റ് സേവന ദാതാവിൽ നിന്നോ നിങ്ങൾ സന്ദർശിക്കുന്ന വെബ്‌സൈറ്റുകളിൽ നിന്നോ ഉള്ള ബ്രൗസിംഗിനെ മറയ്‌ക്കില്ല.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">സൈറ്റ് വിടണോ?</translation>
<translation id="7878176543348854470">ഡെബിറ്റ് കാർഡുകളും പ്രീപെയ്ഡ് കാർഡുകളും സ്വീകരിക്കുന്നു.</translation>
<translation id="7878562273885520351">നിങ്ങളുടെ പാസ്‍വേഡ് അപഹരിക്കപ്പെട്ടേക്കാം</translation>
<translation id="7887683347370398519">നിങ്ങളുടെ CVC പരിശോധിച്ച് വീണ്ടും ശ്രമിക്കുക</translation>
@@ -921,6 +957,7 @@
<translation id="8041940743680923270">ഗ്ലോബൽ ഡിഫോൾട്ട് ഉപയോഗിക്കുക (ചോദിക്കുക)</translation>
<translation id="8042918947222776840">പിക്കപ്പ് രീതി തിരഞ്ഞെടുക്കുക</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" ശരിയായി കോൺഫിഗർ ചെയ്‌‌തിട്ടില്ല. സാധാരണഗതിയിൽ "<ph name="SOFTWARE_NAME" />" അൺഇൻസ്‌റ്റാൾ ചെയ്യുന്നതിലൂടെ ഈ പ്രശ്‌നം പരിഹരിക്കാം. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">സൈറ്റ് റീലോഡ് ചെയ്യണോ?</translation>
<translation id="8088680233425245692">ലേഖനം കാണുന്നത് പരാജയപ്പെട്ടു.</translation>
<translation id="8091372947890762290">സെർവറിൽ സജീവമാക്കൽ തീർപ്പാക്കിയിട്ടില്ല</translation>
<translation id="8094917007353911263">നിങ്ങൾക്ക് ഉപയോഗിക്കുന്ന നെറ്റ്‌വർക്ക് <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> സന്ദർശിക്കാൻ നിങ്ങളോട് ആവശ്യപ്പെടാം.</translation>
@@ -936,6 +973,7 @@
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" എന്ന ഐഡിയുള്ള വിപുലീകരണത്തിന്റെ അപ്‌ഡേറ്റ് URL അസാധുവാണ്.</translation>
<translation id="8202097416529803614">ഓർഡർ സംഗ്രഹം</translation>
<translation id="8205463626947051446">അനാവശ്യമായ പരസ്യങ്ങൾ സൈറ്റ് കാണിക്കാൻ സാധ്യതയുണ്ട്</translation>
+<translation id="8211406090763984747">കണക്ഷൻ സുരക്ഷിതമാണ്</translation>
<translation id="8218327578424803826">നൽകിയിരിക്കുന്ന ലൊക്കേഷൻ:</translation>
<translation id="8225771182978767009">ഈ കമ്പ്യൂട്ടർ സജ്ജമാക്കിയ വ്യക്തി, ഈ സൈറ്റ് ബ്ലോക്കുചെയ്യാൻ തീരുമാനിച്ചിരുന്നു.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -947,6 +985,7 @@
<translation id="825929999321470778">സംരക്ഷിച്ച എല്ലാ പാസ്‌വേഡുകളും കാണിക്കുക</translation>
<translation id="8261506727792406068">ഇല്ലാതാക്കുക</translation>
<translation id="8267698848189296333"><ph name="USERNAME" /> എന്നയാളായി സൈൻ ഇൻ ചെയ്യുന്നു</translation>
+<translation id="8286036467436129157">സൈൻ ഇൻ ചെയ്യുക</translation>
<translation id="8288807391153049143">സർട്ടിഫിക്കറ്റ് കാണിക്കുക</translation>
<translation id="8289355894181816810">ഇത് അർത്ഥമാക്കുന്നത് എന്താണെന്ന് നിങ്ങൾക്ക് ഉറപ്പില്ലെങ്കിൽ നെറ്റ്‌വർക്ക് അഡ്‌മിനിസ്‌ട്രേറ്ററെ ബന്ധപ്പെടുക.</translation>
<translation id="8293206222192510085">ബുക്ക്‌മാര്‍‌ക്ക് ചേര്‍‌ക്കുക</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">സ്വീകരിക്കുന്ന ക്രെഡിറ്റ് കാർഡുകളും പ്രീപെയ്ഡ് കാർഡുകളും</translation>
<translation id="8759274551635299824">ഈ കാർഡ് കാലഹരണപ്പെട്ടു</translation>
<translation id="8761567432415473239">Google സുരക്ഷിത ബ്രൗസിംഗ് <ph name="SITE" /> എന്നതിൽ ഈയിടെ <ph name="BEGIN_LINK" />ദോഷകരമായ പ്രോഗ്രാമുകൾ കണ്ടെത്തി<ph name="END_LINK" />.</translation>
+<translation id="8763927697961133303">USB ഉപകരണം</translation>
<translation id="8790007591277257123">&amp;ഇല്ലാതാക്കുന്നത് വീണ്ടും ചെയ്യുക</translation>
<translation id="8800988563907321413">നിങ്ങളുടെ സമീപത്തുള്ള നിർദ്ദേശങ്ങൾ ഇവിടെ ദൃശ്യമാകും</translation>
<translation id="8820817407110198400">ബുക്ക്‌മാര്‍ക്കുകള്‍</translation>
diff --git a/chromium/components/strings/components_strings_mr.xtb b/chromium/components/strings/components_strings_mr.xtb
index a3d66e20da7..d7d89bd7f93 100644
--- a/chromium/components/strings/components_strings_mr.xtb
+++ b/chromium/components/strings/components_strings_mr.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;मुद्रण...</translation>
<translation id="1181037720776840403">काढा</translation>
<translation id="1184214524891303587">Google कडे संभाव्य सुरक्षितता घटनांच्या तपशीलांचा <ph name="BEGIN_WHITEPAPER_LINK" />स्वयंचलितपणे अहवाल द्या.<ph name="END_WHITEPAPER_LINK" /> <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">पेमेंट पूर्ण झाले नाही</translation>
<translation id="1201402288615127009">पुढील</translation>
<translation id="1201895884277373915">या साइटकडून अधिक</translation>
<translation id="1206967143813997005">खराब प्रारंभिक स्वाक्षरी</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575"><ph name="CRASH_TIME" /> वाजता क्रॅश अहवाल कॅप्चर केला (अद्याप अपलोड केलेला नाही किंवा दुर्लक्ष केले)</translation>
<translation id="1270502636509132238">घेण्याची पद्धत</translation>
<translation id="1285320974508926690">या साइटचा कधीही भाषांतर करु नका</translation>
+<translation id="1294154142200295408">विविध कमांड-लाइन</translation>
<translation id="129553762522093515">अलीकडे बंद केलेले</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />आपल्या कुकीज साफ करून पहा<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">आपले पुढील क्रियाकलाप <ph name="BEGIN_EMPHASIS" />अद्याप दिसतील<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">स्वीकारली जाणारी क्रेडिट आणि डेबिट कार्डे</translation>
<translation id="1519264250979466059">बिल्ड तारीख</translation>
<translation id="1527263332363067270">कनेक्शनची वाट पाहत आहे...</translation>
+<translation id="1532118530259321453">या पेजचे म्हणणे हे आहे की</translation>
<translation id="153384715582417236">सध्या इतकेच</translation>
<translation id="154408704832528245">वितरणाचा पत्ता निवडा</translation>
<translation id="1549470594296187301">हे वैशिष्‍ट्य वापरण्‍यासाठी JavaScript सक्षम करणे आवश्‍यक आहे.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />प्रॉक्सी आणि फायरवॉल तपासणे<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">पिनकोड</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 सूचना}one{# सूचना}other{# सूचना}}</translation>
-<translation id="2065985942032347596">प्रमाणीकरण आवश्यक</translation>
<translation id="2079545284768500474">पूर्ववत करा</translation>
<translation id="20817612488360358">सिस्टम प्रॉक्सी सेटिंग्ज वापरण्‍यास सेट करण्‍यात आल्या परंतु एक सुस्पष्‍ट प्रॉक्सी कॉन्फिगरेशन देखील निर्दिष्‍ट करण्‍यात आले.</translation>
<translation id="2091887806945687916">ध्वनी</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">पेमेंट रद्द करा</translation>
<translation id="2147827593068025794">पार्श्वभूमी संकालन</translation>
<translation id="2148613324460538318">कार्ड जोडा</translation>
-<translation id="2149973817440762519">बुकमार्क संपादित करा</translation>
<translation id="2154054054215849342">आपल्या डोमेनसाठी संकालन उपलब्ध नाही</translation>
<translation id="2154484045852737596">कार्ड संपादित करा</translation>
<translation id="2166049586286450108">पूर्ण प्रशासन प्रवेश</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">पिकअप पत्ता निवडा</translation>
<translation id="2740531572673183784">ठीक आहे</translation>
<translation id="2742870351467570537">निवडलेले आयटम काढा</translation>
-<translation id="2744590937989388266">एम्बेड केलेल्‍या पेजवरून या पेजवर</translation>
<translation id="277133753123645258">शिपिंग पद्धत</translation>
<translation id="277499241957683684">डिव्हाइस रेकॉर्ड गहाळ</translation>
<translation id="2784949926578158345">कनेक्शन रीसेट केले.</translation>
<translation id="2788784517760473862">क्रेडिट कार्डे स्वीकारली जातात</translation>
<translation id="2794233252405721443">साइट अवरोधित केली</translation>
-<translation id="2795286477369100655">तुम्हाला ही साइट सोडायची आहे का?</translation>
<translation id="2799020568854403057">पुढील साइटमध्ये हानिकारक अॅप आहे</translation>
<translation id="2803306138276472711">Google सुरक्षित ब्राउझिंगला अलीकडे <ph name="SITE" /> वर <ph name="BEGIN_LINK" />मालवेअर आढळले आहे<ph name="END_LINK" />. सामान्यतः सुरक्षित असलेल्या वेबसाइट काहीवेळा मालवेअरमुळे संक्रमित झालेल्या असतात.</translation>
<translation id="2824775600643448204">पत्ता आणि शोध बार</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">सूची प्रविष्टी "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">आपोआप ब्लॉक केलेले</translation>
<translation id="3024663005179499861">चुकीचा धोरण प्रकार</translation>
-<translation id="3032412215588512954">आपण ही साइट पुन्हा रीलोड करू इच्छिता?</translation>
<translation id="3037605927509011580">च्चक!</translation>
<translation id="3039538478787849737">Google वर कार्ड सेव्ह करायचे?</translation>
<translation id="3041612393474885105">प्रमाणपत्र माहिती...</translation>
@@ -310,6 +306,7 @@
किंवा आपल्या नेटवर्क प्रशासकाशी संपर्क साधा. आपण प्रॉक्सी सर्व्हर वापरत
आहात यावर आपला विश्वास नसल्यास:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="SERVER_NAME" /> वर <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">पेमेंट रद्द करा</translation>
<translation id="3207960819495026254">बुकमार्क केलेली</translation>
<translation id="3209375525920864198">कृपया एक वैध सेशन नाव टाका.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">आपला व्यवस्थापक तुमच्यासाठी ती अनावरोधित करू शकतो</translation>
<translation id="3566021033012934673">आपले कनेक्शन खाजगी नाही</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" /> वरील एंबेड केलेल्‍या पेजचे म्हणणे हे आहे की</translation>
<translation id="358285529439630156">क्रेडिट आणि प्रीपेड कार्डे स्वीकारली जातात.</translation>
<translation id="3582930987043644930">नाव जोडा</translation>
<translation id="3583757800736429874">&amp;हलवा पुन्हा करा</translation>
<translation id="3586931643579894722">तपशील लपवा</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;कनेक्शन एरर दुरुस्त करा&lt;/h1&gt;
+ &lt;p&gt;एखाद्या वेबसाइटला भेट देण्याचा प्रयत्न करताना तुम्हाला एरर मेसेज मिळाल्यास, या दुरुस्त्या करून पहा.&lt;/p&gt;
+ &lt;h2&gt;बहुतांश कनेक्शन एरर दुरुस्त करा&lt;/h2&gt;
+ &lt;p&gt;तुम्ही एखाद्या वेबसाइटला भेट देण्याचा प्रयत्न करत असल्यास आणि ती उघडत नसल्यास, आधी या ट्रबलशूटिंग पायऱ्या वापरून एरर दुरुस्त करून पहा:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;वेब अॅड्रेसमध्ये टायपिंगच्या चुका आहेत का ते तपासा.&lt;/li&gt;
+ &lt;li&gt;तुमचे इंटरनेट कनेक्शन सुरळीत काम करत आहे याची खात्री करा.&lt;/li&gt;
+ &lt;li&gt;वेबसाइट मालकाशी संपर्क साधा.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;विशिष्ट एरर मेसेजबाबत मदत मिळवा&lt;/h2&gt;
+ &lt;h3&gt;"तुमचे कनेक्शन खाजगी नाही" किंवा "NET::ERR_CERT_AUTHORITY_INVALID" किंवा "ERR_CERT_COMMON_NAME_INVALID" किंवा "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" किंवा "SSL सर्टिफिकेट एरर"&lt;/h3&gt;
+ &lt;h4&gt;पायरी १: पोर्टलमध्ये साइन इन करा&lt;/h4&gt;
+ &lt;p&gt;कॅफे किंवा विमानतळ यांसारख्या जागी असलेल्या वाय-फाय नेटवर्कसाठी तुम्हाला साइन इन करावे लागते. साइन-इन पेज पाहण्यासाठी, &lt;code&gt;http://&lt;/code&gt; वापरणाऱ्या पेजला भेट द्या.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;&lt;code&gt;http://&lt;/code&gt; ने सुरू होणाऱ्या कोणत्याही वेबसाइटवर जा, जसे की &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;उघडलेल्या साइन-इन पेजवर, इंटरनेट वापरण्यासाठी साइन इन करा.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;पायरी २: पेज गुप्त मोडमध्ये उघडा (केवळ काँप्युटर)&lt;/h4&gt;
+ &lt;p&gt;तुम्ही ज्या पेजला भेट देत होता ते गुप्त विंडोमध्ये उघडा.&lt;/p&gt;
+ &lt;p&gt;पेज उघडल्यास, Chrome एक्स्टेंशन बरोबर काम करत नाही आहे. एरर दुरुस्त करण्यासाठी, एक्स्टेंशन बंद करा.&lt;/p&gt;
+ &lt;h4&gt;पायरी ३: तुमची अॉपरेटिंग सिस्टम अपडेट करा&lt;/h4&gt;
+ &lt;p&gt;तुमचे डिव्हाइस अद्ययावत आहे याची खात्री करा.&lt;/p&gt;
+ &lt;h4&gt;पायरी ४: तुमचे अँटिव्हायरस तात्पुरते बंद करा&lt;/h4&gt;
+ &lt;p&gt;तुमच्याकडे "HTTPS संरक्षण" किंवा "HTTPS स्कॅनिंग" पुरवणारे अँटिव्हायरस सॉफ्टवेअर असल्यास तुम्हाला ही एरर दिसेल. अँटिव्हायरस Chrome ला सुरक्षितता पुरवण्यापासून रोखत आहे.&lt;/p&gt;
+ &lt;p&gt;समस्या सोडवण्यासाठी, तुमचे अँटिव्हायरस सॉफ्टवेअर बंद करा. सॉफ्टवेअर बंद केल्यानंतर पेज काम करत असल्यास, तुम्ही सुरक्षित साइट वापरत असताना हे सॉफ्टवेअर बंद करा.&lt;/p&gt;
+ &lt;p&gt;तुमचे काम झाल्यावर तुमचा अँटिव्हयरस प्रोग्राम पुन्हा चालू करण्याचे लक्षात ठेवा.&lt;/p&gt;
+ &lt;h4&gt;पायरी ५: अतिरिक्त मदत मिळवा&lt;/h4&gt;
+ &lt;p&gt;तुम्हाला तरीही एरर दिसत असल्यास, वेबसाइट मालकाशी संपर्क साधा.&lt;/p&gt;
+ &lt;h3&gt;"नेटवर्कशी कनेक्ट करा"&lt;/h3&gt;
+ &lt;p&gt;जेथे ऑनलाइन जाण्याआधी तुम्हाला साइन इन करावे लागते असे वाय-फाय पोर्टल तुम्ही वापरत असल्यास तुम्हाला ही एरर दिसेल.&lt;/p&gt;
+ &lt;p&gt;एरर दुरुस्त करण्यासाठी, तुम्ही उघडण्याचा प्रयत्न करत असलेल्या पेजवर &lt;strong&gt;कनेक्ट करा&lt;/strong&gt; वर क्लिक करा.&lt;/p&gt;
+ &lt;h3&gt;"तुमचे घड्याळ मागे आहे" किंवा "तुमचे घड्याळ पुढे आहे" किंवा "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;तुमच्या काँप्युटरची किंवा मोबाइल डिव्हाइसची तारीख आणि वेळ चुकीची असल्यास तुम्हाला ही एरर दिसेल.&lt;/p&gt;
+ &lt;p&gt;एरर दुरुस्त करण्यासाठी, तुमच्या डिव्हाइसचे घड्याळ उघडा. तारीख आणि वेळ बरोबर आहे याची खात्री करा.&lt;/p&gt;
+ &lt;h3&gt;"तुमच्या काँप्युटरवरील सॉफ्टवेअर Chrome ला वेबशी सुरक्षितपणे कनेक्ट करण्यापासून थांबवत आहे" (केवळ Windows काँप्युटर)&lt;/h3&gt;
+ &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;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; वर क्लिक करा
+ &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="3615877443314183785">वैध समाप्ती दिनांक एंटर करा</translation>
<translation id="36224234498066874">ब्राउझिंग डेटा साफ करा...</translation>
<translation id="362276910939193118">पूर्ण इतिहास दर्शवा</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">तुम्हाला हे कार्ड तुमच्या Google खात्यामध्ये आणि या डिव्हाइसवर सेव्ह करायचे आहे का?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">समाप्त होते: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929"><ph name="SITE" /> साइटवरून</translation>
<translation id="382518646247711829">आपण प्रॉक्सी सर्व्हर वापरत असल्यास...</translation>
<translation id="3828924085048779000">रिक्त सांकेतिक वाक्यांशाची परवानगी नाही.</translation>
<translation id="385051799172605136">मागील</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">क्रॅश तक्रार आयडी अपलोड केला<ph name="CRASH_ID" /> (स्थानिक क्रॅश आयडी: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">हा सर्व्हर <ph name="DOMAIN" /> असल्याचे सिद्ध करू शकला नाही; त्याचे सुरक्षा प्रमाणपत्र विषय पर्यायी नावांचा उल्लेख करत नाही. हे कदाचित चुकीच्या कॉंफिगरेशनमुळे होत आहे किंवा आक्रमणकर्ता तुमच्या कनेक्शनमध्ये अडथळा आणत आहे.</translation>
<translation id="3949601375789751990">तुमचा ब्राउझिंग इतिहास येथे दिसतो</translation>
+<translation id="3950820424414687140">साइन इन करा</translation>
<translation id="3963721102035795474">वाचक मोड</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{काहीही नाही}=1{1 साइटकडून }one{# साइटकडून }other{# साइटकडून }}</translation>
<translation id="397105322502079400">गणना करत आहे...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">डिव्हाइस सिरीयल क्रमांक अवैध आहे</translation>
<translation id="410351446219883937">ऑटोप्ले</translation>
<translation id="4103763322291513355">आपल्या सिस्टम प्रशासकाद्वारे प्रवर्तित काळ्यासूचीतील URLs आणि अन्य धोरणांची सूची पाहण्यासाठी &lt;strong&gt;chrome://policy&lt;/strong&gt; ला भेट द्या.</translation>
+<translation id="4110652170750985508">तुमचे पेमेंट पुन्हा एकदा तपासा</translation>
<translation id="4116663294526079822">या साइटवर नेहमी अनुमती द्या</translation>
<translation id="4117700440116928470">धोरण कक्षा समर्थित नाही.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{अन्य 1}one{अन्य #}other{अन्य #}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(वापरकर्तानाव नाही)</translation>
<translation id="4275830172053184480">आपला डिव्हाइस रीस्टार्ट करा</translation>
<translation id="4280429058323657511">, कालबाह्यता <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">लॉग इन</translation>
<translation id="4312866146174492540">अवरोधित करा (डीफॉल्ट)</translation>
<translation id="4325863107915753736">लेख शोधण्यात अयशस्वी</translation>
<translation id="4326324639298822553">आपली कालबाह्यता तारीख तपासा आणि पुन्हा प्रयत्न करा</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">कार्ड आणि पत्ते Chrome आणि आपल्या Google खात्याकडील (<ph name="ACCOUNT_EMAIL" />) आहेत. आपण त्यांना <ph name="BEGIN_LINK" />सेटिंग्‍ज<ph name="END_LINK" /> मधून व्यवस्थापित करू शकता.</translation>
<translation id="4522570452068850558">तपशील</translation>
<translation id="4552089082226364758">फ्लॅश</translation>
-<translation id="4554702541363482291"><ph name="SITE" /> वर एम्बेड केलेल्‍या पेजवरून</translation>
<translation id="4558551763791394412">आपले विस्तार अक्षम करून पहा.</translation>
<translation id="457875822857220463">वितरण</translation>
<translation id="4582800630050655161">तुम्ही तुमच्या Google खात्याचा अॅक्सेस गमावू शकता किंवा तुमची संवेदनशील माहिती चोरीला जाऊ शकते. Chromium लगेच तुमचा पासवर्ड बदलण्याची शिफारस करत आहे.</translation>
<translation id="4587425331216688090">Chrome मधून पत्ता काढायचा?</translation>
<translation id="4592951414987517459">आपले <ph name="DOMAIN" /> वरील कनेक्शन आधुनिक सायफर सूट वापरून कूटबद्ध केलेले आहे.</translation>
<translation id="4594403342090139922">&amp;हटवा पूर्ववत करा</translation>
-<translation id="4611292653554630842">लॉग इन करा</translation>
<translation id="4619615317237390068">अन्य डिव्हाइसेसमधील टॅब</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">हा सर्व्हर हे <ph name="DOMAIN" /> असल्याचे सिद्ध करू शकला नाही; त्याच्या सुरक्षितता प्रमाणपत्रात एरर आहेत. हे कदाचित एका चुकीच्या कॉन्फिगरेशनमुळे किंवा आक्रमणकर्त्याने आपले कनेक्शन आंतरखंडित केल्यामुळे झाले असू शकते.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">आपल्या कनेक्शनमध्ये व्यत्यय आला</translation>
<translation id="471880041731876836">या साइटला भेट देण्याची तुम्हाला परवानगी नाही</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows नेटवर्क निदान चालविणे<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">आपले पेमेंट</translation>
<translation id="4726672564094551039">धोरणे रीलोड करा</translation>
<translation id="4728558894243024398">प्लॅटफॉर्म</translation>
<translation id="4736825316280949806">Chromium रीस्टार्ट करा</translation>
-<translation id="4737498291095696011">या पेजवरून</translation>
<translation id="4744603770635761495">कार्यवाहीयोग्य पथ</translation>
<translation id="4749685221585524849">अखेरचे वापरले: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">आपली माहिती (उदाहरणार्थ, पासवर्ड किंवा क्रेडिट कार्ड क्रमांक) या साइटवर पाठविली जाते तेव्हा ती खाजगी राहते.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">पहा</translation>
<translation id="4854362297993841467">ही वितरण पद्धत उपलब्ध नाही. वेगळी पद्धत वापरून पहा.</translation>
<translation id="4858792381671956233">या साइटला भेट देणे ठीक आहे का ते आपण आपल्‍या पालकांना विचारले</translation>
-<translation id="4871132632506079383"><ph name="SITE" /> येथे एम्बेड केलेल्‍या पेजवरून</translation>
<translation id="4880827082731008257">इतिहास शोध</translation>
+<translation id="4881695831933465202">उघडा</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">प्रमाणीकरण आवश्यक</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{आणि 1 आणखी वेब पृष्ठ}one{आणि # आणखी वेब पृष्‍ठ}other{आणि # आणखी वेब पृष्ठे}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947"><ph name="CREDIT_CARD" /> चा CVV टाका. तुम्ही निश्चित केल्यावर तुमच्या Google पेमेंट खात्यामधील कार्डाचे तपशील या साइटसोबत शेअर केले जातील.</translation>
<translation id="4923417429809017348">हे पृष्ठ अज्ञात भाषेतून <ph name="LANGUAGE_LANGUAGE" /> मध्ये अनुवादित करण्यात आले</translation>
<translation id="4923459931733593730">पेमेंट</translation>
<translation id="4926049483395192435">निर्दिष्‍ट केले जाणे आवश्‍यक आहे.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> चे म्हणणे हे आहे की</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">क्रिया</translation>
<translation id="4958444002117714549">सूची विस्तृत करा</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">सक्षम केल्‍यास, Chrome जलदपणे फॉर्म भरण्‍यासाठी आपल्‍या कार्डची एक प्रत या डिव्‍हाइसवर संग्रहित करेल.</translation>
<translation id="5018422839182700155">हे पृष्‍ठ उघडू शकत नाही</translation>
<translation id="5019198164206649151">समर्थन संचयन खराब स्थितीत</translation>
-<translation id="5020990877659450221">या पेजवरून</translation>
<translation id="5023310440958281426">आपल्या प्रशासकाची धोरणे तपासा</translation>
<translation id="5029568752722684782">कॉपी साफ करा</translation>
<translation id="503069730517007720">"<ph name="SOFTWARE_NAME" />" साठी मूळ सर्टिफिकेट आवश्यक आहे परंतु ते इंस्टॉल केलेले नाही. तुमच्या IT अ‍ॅडमिनिस्ट्रेटरने ही समस्या सोडण्यासाठी "<ph name="SOFTWARE_NAME" />" साठीच्या कॉन्फिगरेशन सूचना पहाव्यात. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">मशीन</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> मध्ये नाही? या त्रुटीचा अहवाल नोंदवा</translation>
<translation id="5190835502935405962">बुकमार्क बार</translation>
+<translation id="5201306358585911203">या पेजवरील एंबेड केलेल्‍या पेजचे म्हणणे हे आहे की</translation>
<translation id="5205222826937269299">नाव आवश्यक आहे</translation>
<translation id="5222812217790122047">ईमेल आवश्यक आहे</translation>
<translation id="522700295135997067">या साइटने कदाचित तुमचा पासवर्ड चोरला असेल</translation>
<translation id="5230733896359313003">पाठविण्याचा पत्ता</translation>
<translation id="5251803541071282808">क्लाउड</translation>
-<translation id="5277279256032773186">कार्यस्थानी Chrome वापरत आहात? व्यवसाय त्यांच्या कर्मचार्‍यांंसाठी Chrome सेटिंग्ज व्यवस्थापित करू शकतात. अधिक जाणनू घ्या</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />सॉफ्टवेअर तात्पुरते बंद करून ठेवण्यासाठी खालील पायर्‍यांचे फॉलो करा, ज्यामुळे तुम्ही वेबशी कनेक्ट होऊ शकाल. तुम्हाला प्रशासकीय हक्क असणे आवश्यक असेल.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">कनेक्शन तपासणे</translation>
<translation id="5610807607761827392">आपण कार्ड आणि पत्ते <ph name="BEGIN_LINK" />सेटिंग्ज<ph name="END_LINK" /> मध्ये व्यवस्थापित करू शकता.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> नी आपल्‍याला अनेक वेळा पुनर्निर्देशित केले.</translation>
-<translation id="5622887735448669177">आपण ही साइट सोडू इच्छिता?</translation>
<translation id="5629630648637658800">धोरण सेटिंग्ज लोड करण्यात अयशस्वी</translation>
<translation id="5631439013527180824">अवैध डिव्हाइस व्यवस्थापन टोकन</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">आपण आपली कार्ड माहिती भरू इच्छित आहात?</translation>
<translation id="5803412860119678065">आपण आपले <ph name="CARD_DETAIL" /> भरू इच्छित आहात?</translation>
<translation id="5810442152076338065">आपले <ph name="DOMAIN" /> वरील कनेक्शन अप्रचलित सायफर सूट वापरून कूटबद्ध केलेले आहे.</translation>
-<translation id="5810928923025889964">एम्बेड केलेल्‍या पेजवरून या पेजवर</translation>
<translation id="5813119285467412249">&amp;जोडा पुन्हा करा</translation>
<translation id="5838278095973806738">या साइटवर कोणतीही संवेदनशील माहिती (उदाहरणार्थ, पासवर्ड किंवा क्रेडिट कार्ड) एंटर करू नका, कारण आक्रमणकर्ते ती चोरू शकतात.</translation>
<translation id="5866257070973731571">फोन नंबर जोडा</translation>
@@ -731,21 +767,19 @@
<translation id="6446608382365791566">अधिक माहिती जोडा</translation>
<translation id="6447842834002726250">कुकीज</translation>
<translation id="6451458296329894277">फॉर्म रीसबमिशनची पुष्टी करा</translation>
-<translation id="6456339708790392414">आपले पेमेंट</translation>
<translation id="647261751007945333">डीव्हाइस धोरणे</translation>
<translation id="6477321094435799029">Chrome ला या पृष्‍ठावर असमान्य कोड सापडला आहे आणि आपली वैयक्तिक माहिती (उदा, पासवर्ड, फोन नंबर आणि क्रेडिट कार्ड) संरक्षित करण्‍यासाठी अवरोधित केला आहे.</translation>
<translation id="6489534406876378309">क्रॅश अपलोड करणे प्रारंभ करा</translation>
<translation id="6507833130742554667">क्रेडिट आणि डेबिट कार्डे स्वीकरली जातात.</translation>
<translation id="6508722015517270189">Chrome रीस्टार्ट करा</translation>
-<translation id="6521373090216409766">तुम्हाला ही साइट रीलोड करायची आहे का?</translation>
<translation id="6529602333819889595">&amp;पुन्हा करा हटवा</translation>
<translation id="6534179046333460208">वास्तविक वेब सूचना</translation>
<translation id="6550675742724504774">पर्याय</translation>
-<translation id="6556239504065605927">सुरक्षित कनेक्शन</translation>
<translation id="6556915248009097796">कालबाह्यता: <ph name="EXPIRATION_DATE_ABBR" />, अखेरचे वापरले: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">आपल्या व्यवस्थापकाने अद्याप ती मंजूर केली नाही</translation>
<translation id="6569060085658103619">आपण एक विस्तार पृष्ठ पाहत आहात</translation>
<translation id="6596325263575161958">कूटबद्धता पर्याय</translation>
+<translation id="6604181099783169992">गती किंवा प्रकाश सेन्सर</translation>
<translation id="6624427990725312378">संपर्क माहिती</translation>
<translation id="6626291197371920147">वैध कार्ड नंबर जोडा</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> शोध</translation>
@@ -817,6 +851,7 @@
<translation id="7275334191706090484">व्यवस्थापित केलेले बुकमार्क</translation>
<translation id="7298195798382681320">शिफारस केलेले</translation>
<translation id="7309308571273880165"><ph name="CRASH_TIME" /> वाजता क्रॅश अहवाल कॅप्चर केला (वापरकर्त्याने विनंती केलेले अपलोड, अद्याप अपलोड केलेले नाही)</translation>
+<translation id="7320336641823683070">कनेक्शन मदत</translation>
<translation id="7334320624316649418">&amp;पुनर्क्रमित करा पुन्हा करा</translation>
<translation id="733923710415886693">प्रमाणपत्र पारदर्शकतेद्वारे सर्व्हरचे प्रमाणपत्र उघड केले नाही.</translation>
<translation id="7353601530677266744">कमांड लाइन</translation>
@@ -901,6 +936,7 @@
<translation id="782886543891417279">आपण वापरत असलेल्या (<ph name="WIFI_NAME" />) Wi-Fi च्या लॉग इन पृष्ठास आपल्याला भेट देण्याची आवश्यकता असू शकते.</translation>
<translation id="785549533363645510">तथापि, आपण अदृश्य नाही. गुप्त झाल्याने आपले ब्राउझिंग आपला नियोक्ता, आपला इंटरनेट सेवा प्रदाता, किंवा आपण भेट देता त्या वेबसाइटपासून लपत नाही.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">साइट सोडायची?</translation>
<translation id="7878176543348854470">डेबिट आणि प्रीपेड कार्डे स्वीकरली जातात.</translation>
<translation id="7878562273885520351">तुमच्या पासवर्डशी तडजोड होत असल्याची शक्यता आहे</translation>
<translation id="7887683347370398519">आपले CVC तपासा आणि पुन्हा प्रयत्न करा</translation>
@@ -923,6 +959,7 @@
<translation id="8041940743680923270">सार्वत्रिक डीफॉल्‍ट वापरा (विचारा)</translation>
<translation id="8042918947222776840">पिकअप पद्धत निवडा</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" योग्य रीतीने कॉन्फिगर केलेले नाही. "<ph name="SOFTWARE_NAME" />" अनइंस्टॉल केल्याने सहसा समस्या सुटते. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">साइट रीलोड करायची?</translation>
<translation id="8088680233425245692">लेख पाहण्यात अयशस्वी.</translation>
<translation id="8091372947890762290">सक्रियकरण सर्व्हरवर प्रलंबित आहे</translation>
<translation id="8094917007353911263">आपण वापरत असलेल्या नेटवर्कला आपण <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> ला भेट देण्याची आवश्यकता आहे.</translation>
@@ -938,6 +975,7 @@
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" आयडी असलेल्या विस्तारासाठी अवैध अपडेट URL.</translation>
<translation id="8202097416529803614">ऑर्डर सारांश</translation>
<translation id="8205463626947051446">साइट अनाहूत जाहिराती दाखवणे चालू ठेवेल</translation>
+<translation id="8211406090763984747">कनेक्शन सुरक्षित आहे</translation>
<translation id="8218327578424803826">नियुक्त केलेले स्थान:</translation>
<translation id="8225771182978767009">ज्या व्यक्तीने हा कॉंप्युटर सेट केला त्या व्यक्तीने ही साइट अवरोधित करण्याचे निवडले आहे.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -949,6 +987,7 @@
<translation id="825929999321470778">सेव्ह केलेले सर्व पासवर्ड दाखवा</translation>
<translation id="8261506727792406068">हटवा</translation>
<translation id="8267698848189296333"><ph name="USERNAME" /> म्हणून साइन इन करीत आहे</translation>
+<translation id="8286036467436129157">साइन इन</translation>
<translation id="8288807391153049143">सर्टिफिकेट दाखवा</translation>
<translation id="8289355894181816810">याचा निश्चित अर्थ आपल्याला माहिती नसल्यास आपल्या नेटवर्क प्रशासकाशी संपर्क साधा.</translation>
<translation id="8293206222192510085">बुकमार्क जोडा</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">स्वीकारली जाणारी क्रेडिट आणि प्रीपेड कार्डे</translation>
<translation id="8759274551635299824">या कार्डची मुदत संपली आहे</translation>
<translation id="8761567432415473239">Google सुरक्षित ब्राउझिंग ला <ph name="SITE" /> वर अलीकडे <ph name="BEGIN_LINK" />हानिकारक प्रोग्राम आढळले आहेत<ph name="END_LINK" />.</translation>
+<translation id="8763927697961133303">USB डिव्हाइस</translation>
<translation id="8790007591277257123">&amp;पुन्हा करा हटवा</translation>
<translation id="8800988563907321413">आपल्या जवळपासच्या सूचना येथे दिसतात</translation>
<translation id="8820817407110198400">Bookmarks</translation>
@@ -1011,7 +1051,7 @@
<translation id="8874824191258364635">वैध कार्ड नंबर एंटर करा</translation>
<translation id="8876793034577346603">विश्लेषण करण्यात नेटवर्क कॉन्फिगरेशन अयशस्वी.</translation>
<translation id="8891727572606052622">अवैध प्रॉक्सी मोड.</translation>
-<translation id="8903921497873541725">झूम वाढवा</translation>
+<translation id="8903921497873541725">झूम इन करा</translation>
<translation id="8931333241327730545">आपण आपल्या Google खात्यात हे कार्ड जतन करू इच्छिता?</translation>
<translation id="8932102934695377596">आपले घड्याळ मागे आहे</translation>
<translation id="893332455753468063">नाव जोडा</translation>
diff --git a/chromium/components/strings/components_strings_ms.xtb b/chromium/components/strings/components_strings_ms.xtb
index acd9cfc0e33..00184cc05c3 100644
--- a/chromium/components/strings/components_strings_ms.xtb
+++ b/chromium/components/strings/components_strings_ms.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Cetak...</translation>
<translation id="1181037720776840403">Alih keluar</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Laporkan secara automatik<ph name="END_WHITEPAPER_LINK" /> tentang butiran kemungkinan insiden keselamatan kepada Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Bayaran Belum Diselesaikan</translation>
<translation id="1201402288615127009">Seterusnya</translation>
<translation id="1201895884277373915">Lagi dari tapak ini</translation>
<translation id="1206967143813997005">Tandatangan awal tidak sah</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Laporan ranap sistem dirakam pada <ph name="CRASH_TIME" /> (belum dimuat naik atau diabaikan)</translation>
<translation id="1270502636509132238">Kaedah Pengambilan</translation>
<translation id="1285320974508926690">Jangan sekali-kali menterjemahkan tapak ini</translation>
+<translation id="1294154142200295408">Variasi baris perintah</translation>
<translation id="129553762522093515">Ditutup baru-baru ini</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Cuba kosongkan kuki anda<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Aktiviti anda <ph name="BEGIN_EMPHASIS" />mungkin masih boleh dilihat<ph name="END_EMPHASIS" /> oleh:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Kad kredit dan debit yang diterima</translation>
<translation id="1519264250979466059">Tarikh Bina</translation>
<translation id="1527263332363067270">Menunggu sambungan...</translation>
+<translation id="1532118530259321453">Halaman ini menyatakan</translation>
<translation id="153384715582417236">Itu sahaja buat masa ini</translation>
<translation id="154408704832528245">Pilih Alamat Penghantaran</translation>
<translation id="1549470594296187301">Javascript mesti didayakan untuk menggunakan ciri ini.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Menyemak proksi dan tembok api<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Poskod</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 cadangan}other{# cadangan}}</translation>
-<translation id="2065985942032347596">Pengesahan Diperlukan</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="2091887806945687916">Bunyi</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Batalkan pembayaran</translation>
<translation id="2147827593068025794">Penyegerakan Latar Belakang</translation>
<translation id="2148613324460538318">Tambahkan Kad</translation>
-<translation id="2149973817440762519">Edit Penanda Halaman</translation>
<translation id="2154054054215849342">Penyegerakan tidak tersedia untuk domain anda</translation>
<translation id="2154484045852737596">Edit kad</translation>
<translation id="2166049586286450108">Akses Penuh Pentadbir</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Pilih Alamat Pengambilan</translation>
<translation id="2740531572673183784">Ok</translation>
<translation id="2742870351467570537">Buang item yang dipilih</translation>
-<translation id="2744590937989388266">Daripada Halaman Terbenam pada Halaman Ini</translation>
<translation id="277133753123645258">Kaedah penghantaran</translation>
<translation id="277499241957683684">Tiada rekod peranti</translation>
<translation id="2784949926578158345">Sambungan ditetapkan semula.</translation>
<translation id="2788784517760473862">Kad kredit yang diterima</translation>
<translation id="2794233252405721443">Tapak disekat</translation>
-<translation id="2795286477369100655">Adakah Anda Ingin Meninggalkan Tapak Ini?</translation>
<translation id="2799020568854403057">Tapak yang akan disemak imbas mengandungi apl yang memudaratkan</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="2824775600643448204">Bar alamat dan carian</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Masukan senarai "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Disekat secara automatik</translation>
<translation id="3024663005179499861">Jenis dasar salah</translation>
-<translation id="3032412215588512954">Adakah anda ingin memuat semula tapak ini?</translation>
<translation id="3037605927509011580">Oh, Tidak!</translation>
<translation id="3039538478787849737">Simpan kad ke Google?</translation>
<translation id="3041612393474885105">Maklumat Sijil</translation>
@@ -310,6 +306,7 @@
memastikan pelayan proksi berfungsi. Jika anda tidak percaya anda perlu
menggunakan pelayan proksi:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> pada <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Batal Pembayaran</translation>
<translation id="3207960819495026254">Ditandai halaman</translation>
<translation id="3209375525920864198">Sila masukkan nama sesi yang sah.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Pengurus anda boleh menyahsekatnya untuk anda</translation>
<translation id="3566021033012934673">Sambungan anda tidak diperibadikan</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Halaman terbenam di <ph name="SITE" /> menyatakan</translation>
<translation id="358285529439630156">Kad kredit dan prabayar diterima.</translation>
<translation id="3582930987043644930">Tambah nama</translation>
<translation id="3583757800736429874">&amp;Buat Semula Pindahkan</translation>
<translation id="3586931643579894722">Sembunyikan butiran</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Betulkan ralat sambungan&lt;/h1&gt;
+ &lt;p&gt;Jika anda menerima mesej ralat apabila anda cuba melawati tapak web, cuba pembetulan ini.&lt;/p&gt;
+ &lt;h2&gt;Betulkan kebanyakan ralat sambungan&lt;/h2&gt;
+ &lt;p&gt;Jika anda cuba melawati tapak web tetapi tapak tersebut tidak dapat dibuka, cuba betulkan ralat itu dengan langkah penyelesai masalah ini:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Semak alamat web untuk mengesan kesalahan menaip.&lt;/li&gt;
+ &lt;li&gt;Pastikan sambungan Internet anda berfungsi seperti biasa.&lt;/li&gt;
+ &lt;li&gt;Hubungi pemilik tapak web.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Dapatkan bantuan untuk mesej ralat tertentu&lt;/h2&gt;
+ &lt;h3&gt;"Sambungan anda tidak peribadi" atau "NET::ERR_CERT_AUTHORITY_INVALID" atau "ERR_CERT_COMMON_NAME_INVALID" atau "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" atau "Ralat sijil SSL"&lt;/h3&gt;
+ &lt;h4&gt;Langkah 1: Log masuk ke portal&lt;/h4&gt;
+ &lt;p&gt;Rangkaian Wi-Fi di tempat seperti kafe atau lapangan terbang menghendaki anda untuk log masuk. Untuk memaparkan halaman log masuk, lawati halaman yang menggunakan&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Pergi ke mana-mana tapak web yang bermula dengan &lt;code&gt;http://&lt;/code&gt;, seperti &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Pada halaman log masuk yang terbuka, log masuk untuk menggunakan Internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Langkah 2: Buka halaman dalam mod Inkognito (komputer sahaja)&lt;/h4&gt;
+ &lt;p&gt;Buka halaman yang anda lawati dalam tetingkap Inkognito.&lt;/p&gt;
+ &lt;p&gt;Jika halaman tersebut terbuka, terdapat sambungan Chrome yang tidak berfungsi dengan betul. Untuk membetulkan ralat ini, matikan sambungan tersebut.&lt;/p&gt;
+ &lt;h4&gt;Langkah 3: Kemas kini sistem pengendalian anda&lt;/h4&gt;
+ &lt;p&gt;Pastikan peranti anda dalam keadaan terkini.&lt;/p&gt;
+ &lt;h4&gt;Langkah 4: Matikan antivirus anda buat sementara waktu&lt;/h4&gt;
+ &lt;p&gt;Ralat ini akan kelihatan jika anda memasang antivirus yang menyediakan "perlindungan HTTPS" atau "pengimbasan HTTPS". Antivirus tersebut menghalang Chrome daripada menyediakan keselamatan.&lt;/p&gt;
+ &lt;p&gt;Untuk menyelesaikan masalah ini, matikan perisian antivirus anda. Jika halaman berfungsi selepas perisian dimatikan, matikan perisian ini apabila anda menggunakan tapak yang selamat.&lt;/p&gt;
+ &lt;p&gt;Jangan lupa untuk menghidupkan semula atur cara antivirus itu apabila anda sudah selesai.&lt;/p&gt;
+ &lt;h4&gt;Langkah 5: Dapatkan bantuan tambahan&lt;/h4&gt;
+ &lt;p&gt;Jika ralat masih kelihatan, hubungi pemilik tapak web.&lt;/p&gt;
+ &lt;h3&gt;"Sambung ke rangkaian"&lt;/h3&gt;
+ &lt;p&gt;Ralat ini akan dipaparkan jika anda menggunakan portal Wi-Fi yang menghendaki anda untuk log masuk sebelum anda dapat masuk ke dalam talian.&lt;/p&gt;
+ &lt;p&gt;Untuk membetulkan ralat ini, klik &lt;strong&gt;Sambung&lt;/strong&gt; pada halaman yang cuba dibuka.&lt;/p&gt;
+ &lt;h3&gt;"Jam anda lambat" atau "Jam anda cepat" atau "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Mesej ini akan dipaparkan jika tarikh dan masa komputer atau peranti mudah alih anda tidak tepat.&lt;/p&gt;
+ &lt;p&gt;Untuk membetulkan ralat ini, buka jam peranti anda. Pastikan tarikh dan masa adalah betul.&lt;/p&gt;
+ &lt;h3&gt;"Perisian pada komputer anda menghalang Chrome daripada menyambung ke web dengan selamat" (komputer Windows sahaja)&lt;/h3&gt;
+ &lt;p&gt;Ralat ini akan dipaparkan jika anda memasang perisian Superfish pada komputer Windows anda.&lt;/p&gt;
+ &lt;p&gt;Ikut langkah berikut untuk melumpuhkan perisian ini buat sementara waktu supaya anda dapat melayari web. Anda memerlukan keistimewaan pentadbir.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Klik &lt;strong&gt;Mula&lt;/strong&gt;, kemudian cari dan pilih &lt;strong&gt;"Lihat perkhidmatan setempat"&lt;/strong&gt;
+ &lt;li&gt;Pilih &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Di bahagian &lt;strong&gt;Jenis permulaan&lt;/strong&gt;, pilih &lt;strong&gt;Lumpuhkan&lt;/strong&gt;
+ &lt;li&gt;Di bahagian &lt;strong&gt;Status perkhidmatan&lt;/strong&gt;, klik &lt;strong&gt;Hentikan&lt;/strong&gt;
+ &lt;li&gt;Klik &lt;strong&gt;Gunakan&lt;/strong&gt;, kemudian klik &lt;strong&gt;OK&lt;/strong&gt;
+ &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 tersebut secara kekal daripada komputer anda
+ &lt;/ol&gt;</translation>
<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>
@@ -405,7 +448,6 @@
<translation id="3778403066972421603">Adakah anda ingin menyimpan maklumat kad ini ke Akaun Google anda dan pada peranti ini?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Tamat tempoh pada <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Daripada <ph name="SITE" /></translation>
<translation id="382518646247711829">Jika anda menggunakan pelayan proksi...</translation>
<translation id="3828924085048779000">Kosongkan frasa laluan adalah tidak dibenarkan.</translation>
<translation id="385051799172605136">Kembali</translation>
@@ -419,6 +461,7 @@
<translation id="3945915738023014686">ID Laporan Ranap Yang Dimuat Naik <ph name="CRASH_ID" /> (ID Ranap Setempat: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Pelayan ini tidak dapat membuktikan bahawa domainnya ialah <ph name="DOMAIN" />; sijil keselamatannya tidak menyatakan Nama Alternatif Subjek. Ini mungkin disebabkan oleh kesilapan konfigurasi atau penyerang memintasi sambungan anda.</translation>
<translation id="3949601375789751990">Sejarah penyemakan imbas anda dipaparkan di sini</translation>
+<translation id="3950820424414687140">Log masuk</translation>
<translation id="3963721102035795474">Mod Pembaca</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Tiada}=1{Daripada 1 tapak }other{Daripada # tapak }}</translation>
<translation id="397105322502079400">Mengira...</translation>
@@ -435,6 +478,7 @@
<translation id="4103249731201008433">Nombor siri peranti tidak sah</translation>
<translation id="410351446219883937">Automain</translation>
<translation id="4103763322291513355">Lawati &lt;strong&gt;chrome://policy&lt;/strong&gt; untuk melihat senarai URL yang disenarai hitam dan dasar lain yang dikuatkuasakan oleh pentadbir sistem anda.</translation>
+<translation id="4110652170750985508">Semak pembayaran anda</translation>
<translation id="4116663294526079822">Sentiasa benarkan di tapak ini</translation>
<translation id="4117700440116928470">Skop dasar tidak disokong.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 yang lain}other{# yang lain}}</translation>
@@ -461,7 +505,6 @@
<translation id="4269787794583293679">(Tiada nama pengguna)</translation>
<translation id="4275830172053184480">Mulakan semula peranti anda</translation>
<translation id="4280429058323657511">, tamat tempoh <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Log Masuk</translation>
<translation id="4312866146174492540">Sekat (lalai)</translation>
<translation id="4325863107915753736">Gagal menemui artikel</translation>
<translation id="4326324639298822553">Semak tarikh tamat tempoh anda dan cuba lagi</translation>
@@ -483,14 +526,12 @@
<translation id="4515275063822566619">Kad dan alamat adalah daripada Chrome dan Akaun Google anda (<ph name="ACCOUNT_EMAIL" />). Anda boleh mengurus kad dan alamat ini dalam <ph name="BEGIN_LINK" />Tetapan<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Butiran</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Daripada Halaman Terbenam di <ph name="SITE" /></translation>
<translation id="4558551763791394412">Cuba lumpuhkan sambungan anda.</translation>
<translation id="457875822857220463">Penghantaran</translation>
<translation id="4582800630050655161">Anda boleh kehilangan akses kepada Akaun Google anda atau mengalami kecurian identiti. Chromium mengesyorkan supaya kata laluan anda ditukar sekarang.</translation>
<translation id="4587425331216688090">Alih keluar alamat daripada Chrome?</translation>
<translation id="4592951414987517459">Sambungan anda ke <ph name="DOMAIN" /> disulitkan menggunakan suit sifer moden.</translation>
<translation id="4594403342090139922">&amp;Buat asal Pemadaman</translation>
-<translation id="4611292653554630842">Log masuk</translation>
<translation id="4619615317237390068">Tab daripada peranti lain</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Pelayan ini tidak dapat membuktikan bahawa domainnya ialah <ph name="DOMAIN" />; sijil keselamatannya mengandungi ralat. Ini mungkin disebabkan oleh kesilapan konfigurasi atau penyerang yang memintas sambungan anda.</translation>
@@ -500,11 +541,9 @@
<translation id="4708268264240856090">Sambungan anda tergendala</translation>
<translation id="471880041731876836">Anda tiada kebenaran untuk melawat tapak ini</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Jalankan Diagnostik Rangkaian Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Pembayaran anda</translation>
<translation id="4726672564094551039">Muat semula dasar</translation>
<translation id="4728558894243024398">Platform</translation>
<translation id="4736825316280949806">Mulakan semula Chromium</translation>
-<translation id="4737498291095696011">Daripada Halaman Ini</translation>
<translation id="4744603770635761495">Laluan Boleh Laku</translation>
<translation id="4749685221585524849">Kali terakhir digunakan <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Maklumat anda (contohnya, kata laluan atau nombor kad kredit) adalah berciri peribadi apabila dihantar ke tapak ini.</translation>
@@ -523,16 +562,16 @@
<translation id="4850886885716139402">Lihat</translation>
<translation id="4854362297993841467">Kaedah penghantaran ini tidak tersedia. Cuba kaedah lain.</translation>
<translation id="4858792381671956233">Anda telah bertanya kepada ibu bapa anda sama ada OK untuk melawat tapak ini</translation>
-<translation id="4871132632506079383">Daripada halaman terbenam di <ph name="SITE" /></translation>
<translation id="4880827082731008257">Sejarah carian</translation>
+<translation id="4881695831933465202">Buka</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Pengesahan diperlukan</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{dan 1 lagi halaman web}other{dan # lagi halaman web}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Masukkan CVC untuk <ph name="CREDIT_CARD" />. Setelah anda mengesahkan, butiran kad daripada akaun Google Payments anda akan dikongsi dengan tapak ini.</translation>
<translation id="4923417429809017348">Halaman ini diterjemahkan dari bahasa yang tidak diketahui ke <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Pembayaran</translation>
<translation id="4926049483395192435">Mesti ditentukan.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> menyatakan</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Tindakan</translation>
<translation id="4958444002117714549">Kembangkan senarai</translation>
@@ -541,7 +580,6 @@
<translation id="5002932099480077015">Jika didayakan, Chrome akan menyimpan salinan kad anda pada peranti ini untuk pengisian borang yang lebih cepat.</translation>
<translation id="5018422839182700155">Tidak dapat membuka halaman ini</translation>
<translation id="5019198164206649151">Simpanan penyandaran dalam keadaan buruk</translation>
-<translation id="5020990877659450221">Daripada halaman ini</translation>
<translation id="5023310440958281426">Semak dasar pentadbir anda</translation>
<translation id="5029568752722684782">Hapuskan salinan</translation>
<translation id="503069730517007720">Sijil akar bagi "<ph name="SOFTWARE_NAME" />" diperlukan tetapi tidak dipasang. Pentadbir IT anda harus melihat arahan konfigurasi "<ph name="SOFTWARE_NAME" />" untuk menyelesaikan masalah ini. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -567,12 +605,12 @@
<translation id="5172758083709347301">Mesin</translation>
<translation id="5179510805599951267">Bukan dalam <ph name="ORIGINAL_LANGUAGE" />? Laporkan ralat ini</translation>
<translation id="5190835502935405962">Bar Penanda Halaman</translation>
+<translation id="5201306358585911203">Halaman terbenam pada halaman ini menyatakan</translation>
<translation id="5205222826937269299">Nama diperlukan</translation>
<translation id="5222812217790122047">E-mel diperlukan</translation>
<translation id="522700295135997067">Tapak ini mungkin baru sahaja mencuri kata laluan anda</translation>
<translation id="5230733896359313003">Alamat Penghantaran</translation>
<translation id="5251803541071282808">Awan</translation>
-<translation id="5277279256032773186">Menggunakan Chrome di tempat kerja? Perniagaan boleh mengurus tetapan Chrome untuk pekerja mereka. Ketahui lebih lanjut</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Ikut langkah ini untuk melumpuhkan perisian buat sementara waktu supaya anda boleh memasuki web. Anda memerlukan keistimewaan pentadbir.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -634,7 +672,6 @@
<translation id="5610142619324316209">Menyemak sambungan</translation>
<translation id="5610807607761827392">Anda boleh mengurus kad dan alamat dalam <ph name="BEGIN_LINK" />Tetapan<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> telah terlalu kerap mengubah hala anda.</translation>
-<translation id="5622887735448669177">Adakah anda ingin meninggalkan tapak ini?</translation>
<translation id="5629630648637658800">Gagal memuatkan tetapan dasar</translation>
<translation id="5631439013527180824">Token pengurusan peranti tidak sah</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>
@@ -657,7 +694,6 @@
<translation id="5786044859038896871">Adakah anda ingin mengisi maklumat kad anda?</translation>
<translation id="5803412860119678065">Adakah anda ingin mengisi <ph name="CARD_DETAIL" /> anda?</translation>
<translation id="5810442152076338065">Sambungan anda ke <ph name="DOMAIN" /> disulitkan menggunakan suit sifer yang sudah usang.</translation>
-<translation id="5810928923025889964">Daripada halaman terbenam pada halaman ini</translation>
<translation id="5813119285467412249">&amp;Buat Semula Tambahkan</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>
<translation id="5866257070973731571">Tambahkan Nombor Telefon</translation>
@@ -731,21 +767,19 @@
<translation id="6446608382365791566">Tambahkan maklumat lanjut</translation>
<translation id="6447842834002726250">Kuki</translation>
<translation id="6451458296329894277">Sahkan Penyerahan Semula Borang</translation>
-<translation id="6456339708790392414">Pembayaran Anda</translation>
<translation id="647261751007945333">Dasar peranti</translation>
<translation id="6477321094435799029">Chrome mengesan kod luar biasa pada halaman ini dan menyekatnya untuk melindungi maklumat peribadi anda (contohnya, kata laluan, nombor telefon dan maklumat kad kredit).</translation>
<translation id="6489534406876378309">Mulakan muat naik ranap sistem</translation>
<translation id="6507833130742554667">Kad kredit dan debit diterima.</translation>
<translation id="6508722015517270189">Mulakan semula Chrome</translation>
-<translation id="6521373090216409766">Adakah Anda Ingin Memuat Semula Tapak Ini?</translation>
<translation id="6529602333819889595">&amp;Buat Semula Pemadaman</translation>
<translation id="6534179046333460208">Cadangan Web Fizikal</translation>
<translation id="6550675742724504774">Pilihan</translation>
-<translation id="6556239504065605927">Sambungan selamat</translation>
<translation id="6556915248009097796">Tamat: <ph name="EXPIRATION_DATE_ABBR" />, kali terakhir digunakan <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Pengurus anda belum meluluskannya</translation>
<translation id="6569060085658103619">Anda sedang melihat halaman sambungan</translation>
<translation id="6596325263575161958">Pilihan penyulitan</translation>
+<translation id="6604181099783169992">Penderia Gerakan atau Cahaya</translation>
<translation id="6624427990725312378">Maklumat Hubungan</translation>
<translation id="6626291197371920147">Tambahkan nombor kad yang sah</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Carian</translation>
@@ -817,6 +851,7 @@
<translation id="7275334191706090484">Penanda Halaman Terurus</translation>
<translation id="7298195798382681320">Disyorkan</translation>
<translation id="7309308571273880165">Laporan ranap sistem dirakam pada <ph name="CRASH_TIME" /> (muat naik diminta oleh pengguna, belum dimuat naik lagi)</translation>
+<translation id="7320336641823683070">Bantuan Sambungan</translation>
<translation id="7334320624316649418">&amp;Buat semula susun semula</translation>
<translation id="733923710415886693">Sijil pelayan tidak didedahkan melalui Ketelusan Sijil.</translation>
<translation id="7353601530677266744">Baris Perintah</translation>
@@ -901,6 +936,7 @@
<translation id="782886543891417279">Wi-Fi yang anda gunakan (<ph name="WIFI_NAME" />) mungkin memerlukan anda melawat halaman log masuknya.</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="7862185352068345852">Tinggalkan tapak?</translation>
<translation id="7878176543348854470">Kad debit dan prabayar diterima.</translation>
<translation id="7878562273885520351">Kata laluan anda mungkin terjejas</translation>
<translation id="7887683347370398519">Semak CVC anda dan cuba lagi</translation>
@@ -923,6 +959,7 @@
<translation id="8041940743680923270">Gunakan lalai global (Tanya)</translation>
<translation id="8042918947222776840">Pilih Kaedah Pengambilan</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" tidak dikonfigurasi dengan betul. Tindakan menyahpasang "<ph name="SOFTWARE_NAME" />" biasanya dapat menyelesaikan masalah ini. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Muatkan semula tapak?</translation>
<translation id="8088680233425245692">Gagal melihat artikel.</translation>
<translation id="8091372947890762290">Pengaktifan belum selesai pada pelayan</translation>
<translation id="8094917007353911263">Rangkaian yang anda gunakan mungkin memerlukan anda melawat <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -938,6 +975,7 @@
<translation id="8201077131113104583">URL kemas kini tidak sah untuk sambungan dengan ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Ringkasan pesanan</translation>
<translation id="8205463626947051446">Tapak cenderung menyiarkan iklan yang mengganggu</translation>
+<translation id="8211406090763984747">Sambungan selamat</translation>
<translation id="8218327578424803826">Lokasi yang Ditentukan:</translation>
<translation id="8225771182978767009">Orang yang menyediakan komputer ini telah memilih untuk menyekat tapak ini.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -949,6 +987,7 @@
<translation id="825929999321470778">Tunjukkan Semua Kata Laluan yang Disimpan</translation>
<translation id="8261506727792406068">Padam</translation>
<translation id="8267698848189296333">Log masuk sebagai <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Log Masuk</translation>
<translation id="8288807391153049143">Tunjukkan sijil</translation>
<translation id="8289355894181816810">Hubungi pentadbir rangkaian anda jika anda tidak pasti apa yang dimaksudkan ini.</translation>
<translation id="8293206222192510085">Tambah Penanda Halaman</translation>
@@ -1000,6 +1039,7 @@
<translation id="874846938927089722">Kad Kredit dan Prabayar yang Diterima</translation>
<translation id="8759274551635299824">Kad ini telah tamat tempoh</translation>
<translation id="8761567432415473239">Penyemakan Imbas Selamat Google baru-baru ini <ph name="BEGIN_LINK" />menemui atur cara berbahaya<ph name="END_LINK" /> pada <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Peranti USB</translation>
<translation id="8790007591277257123">&amp;Buat semula pemadaman</translation>
<translation id="8800988563907321413">Cadangan berdekatan anda dipaparkan di sini</translation>
<translation id="8820817407110198400">Penanda buku</translation>
diff --git a/chromium/components/strings/components_strings_nl.xtb b/chromium/components/strings/components_strings_nl.xtb
index 914509e8310..dd0fa983aa8 100644
--- a/chromium/components/strings/components_strings_nl.xtb
+++ b/chromium/components/strings/components_strings_nl.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Afdrukken...</translation>
<translation id="1181037720776840403">Verwijderen</translation>
<translation id="1184214524891303587">Informatie over mogelijke beveiligingsincidenten <ph name="BEGIN_WHITEPAPER_LINK" />automatisch melden<ph name="END_WHITEPAPER_LINK" /> aan Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Betaling niet voltooid</translation>
<translation id="1201402288615127009">Volgende</translation>
<translation id="1201895884277373915">Meer van deze site</translation>
<translation id="1206967143813997005">Onjuiste eerste handtekening</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Crashrapport vastgelegd op <ph name="CRASH_TIME" /> (nog niet geüpload of genegeerd)</translation>
<translation id="1270502636509132238">Ophaalmethode</translation>
<translation id="1285320974508926690">Deze site nooit vertalen</translation>
+<translation id="1294154142200295408">Opdrachtregelvarianten</translation>
<translation id="129553762522093515">Recent gesloten</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Probeer je cookies te wissen<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Je activiteit is mogelijk <ph name="BEGIN_EMPHASIS" />nog wel zichtbaar<ph name="END_EMPHASIS" /> voor:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Geaccepteerde creditcards en betaalpassen</translation>
<translation id="1519264250979466059">Datum van build</translation>
<translation id="1527263332363067270">Wachten op verbinding...</translation>
+<translation id="1532118530259321453">Deze pagina meldt het volgende</translation>
<translation id="153384715582417236">Dat is voorlopig alles</translation>
<translation id="154408704832528245">Afleveradres kiezen</translation>
<translation id="1549470594296187301">JavaScript moet zijn ingeschakeld om deze functie te kunnen gebruiken.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Controleer de proxy en firewall<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Postcode</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggestie}other{# suggesties}}</translation>
-<translation id="2065985942032347596">Verificatie vereist</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="2091887806945687916">Geluid</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Betaling annuleren</translation>
<translation id="2147827593068025794">Synchronisatie op de achtergrond</translation>
<translation id="2148613324460538318">Kaart toevoegen</translation>
-<translation id="2149973817440762519">Bladwijzer bewerken</translation>
<translation id="2154054054215849342">De synchronisatieservice is niet beschikbaar voor je domein</translation>
<translation id="2154484045852737596">Kaart bewerken</translation>
<translation id="2166049586286450108">Volledige beheerderstoegang</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Ophaaladres kiezen</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Geselecteerde items verwijderen</translation>
-<translation id="2744590937989388266">Van een ingesloten pagina op deze pagina</translation>
<translation id="277133753123645258">Verzendmethode</translation>
<translation id="277499241957683684">Apparaatrecord ontbreekt</translation>
<translation id="2784949926578158345">De verbinding is opnieuw ingesteld.</translation>
<translation id="2788784517760473862">Geaccepteerde creditcards</translation>
<translation id="2794233252405721443">Site geblokkeerd</translation>
-<translation id="2795286477369100655">Wil je deze site verlaten?</translation>
<translation id="2799020568854403057">De volgende site bevat schadelijke apps</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="2824775600643448204">Adres- en zoekbalk</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Lijstitem '<ph name="ENTRY_INDEX" />': <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automatisch geblokkeerd</translation>
<translation id="3024663005179499861">Onjuist beleidstype</translation>
-<translation id="3032412215588512954">Wil je deze site opnieuw laden?</translation>
<translation id="3037605927509011580">Helaas.</translation>
<translation id="3039538478787849737">Kaart opslaan op Google?</translation>
<translation id="3041612393474885105">Certificaatgegevens</translation>
@@ -307,6 +303,7 @@
<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>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> op <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Betaling annuleren</translation>
<translation id="3207960819495026254">Toegevoegd aan 'Bladwijzers'</translation>
<translation id="3209375525920864198">Geef een geldige sessienaam op.</translation>
@@ -364,11 +361,57 @@
<translation id="3556433843310711081">Je beheerder kan de blokkering van de site opheffen</translation>
<translation id="3566021033012934673">Je verbinding is niet privé</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Een ingesloten pagina op <ph name="SITE" /> meldt het volgende</translation>
<translation id="358285529439630156">Creditcards en prepaidkaarten worden geaccepteerd.</translation>
<translation id="3582930987043644930">Voeg naam toe</translation>
<translation id="3583757800736429874">&amp;Opnieuw verplaatsen</translation>
<translation id="3586931643579894722">Details verbergen</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Verbindingsfouten oplossen&lt;/h1&gt;
+ &lt;p&gt;Als je een foutmelding ontvangt wanneer je een website probeert te bezoeken, kun je het volgende proberen om het probleem op te lossen.&lt;/p&gt;
+ &lt;h2&gt;De meeste verbindingsfouten oplossen&lt;/h2&gt;
+ &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;
+ &lt;ol&gt;
+ &lt;li&gt;Controleer het webadres op typfouten.&lt;/li&gt;
+ &lt;li&gt;Controleer of je internetverbinding normaal werkt.&lt;/li&gt;
+ &lt;li&gt;Neem contact op met de eigenaar van deze website.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Hulp bij een specifieke foutmelding&lt;/h2&gt;
+ &lt;h3&gt;'Je verbinding is niet privé' of 'NET::ERR_CERT_AUTHORITY_INVALID' of 'ERR_CERT_COMMON_NAME_INVALID' of 'NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM' of 'SSL certificate error'&lt;/h3&gt;
+ &lt;h4&gt;Stap 1: Log in bij de portal&lt;/h4&gt;
+ &lt;p&gt;Wifi-netwerken op openbare plekken zoals cafés en luchthavens vereisen dat je inlogt. Ga naar een pagina die &lt;code&gt;http://&lt;/code&gt; gebruikt om de inlogpagina weer te geven.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Ga naar een willekeurige website die begint met &lt;code&gt;http://&lt;/code&gt;, zoals &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Log in op de inlogpagina die wordt geopend om internet te gebruiken.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Stap 2: Open de pagina in de incognitomodus (alleen computer)&lt;/h4&gt;
+ &lt;p&gt;Open de webpagina die je bezocht in een incognitovenster.&lt;/p&gt;
+ &lt;p&gt;Als de pagina wordt geopend, is er een probleem met een Chrome-extensie. Schakel de extensie uit om de fout op te lossen.&lt;/p&gt;
+ &lt;h4&gt;Stap 3: Update je besturingssysteem&lt;/h4&gt;
+ &lt;p&gt;Controleer of je apparaat up-to-date is.&lt;/p&gt;
+ &lt;h4&gt;Stap 4: Schakel je antivirusprogramma tijdelijk uit&lt;/h4&gt;
+ &lt;p&gt;Deze foutmelding wordt weergegeven wanneer je antivirussoftware gebruikt met HTTPS-bescherming of HTTPS-scannen. Deze software verhindert dat Chrome beveiliging biedt.&lt;/p&gt;
+ &lt;p&gt;Schakel je antivirussoftware uit om het probleem op te lossen. Als de pagina werkt nadat je de software hebt uitgeschakeld, kun je de software uitschakelen wanneer je beveiligde sites bezoekt.&lt;/p&gt;
+ &lt;p&gt;Vergeet niet je antivirussoftware weer in te schakelen zodra je klaar bent.&lt;/p&gt;
+ &lt;h4&gt;Stap 5: Krijg extra ondersteuning&lt;/h4&gt;
+ &lt;p&gt;Als de fout nog steeds wordt weergegeven, neem je contact op met de eigenaar van de website.&lt;/p&gt;
+ &lt;h3&gt;'Verbinding maken met netwerk'&lt;/h3&gt;
+ &lt;p&gt;Deze fout wordt weergegeven wanneer je een wifi-portal gebruikt waarbij je moet inloggen voordat je online kunt gaan.&lt;/p&gt;
+ &lt;p&gt;Klik op de pagina die je wilt openen op &lt;strong&gt;Verbinden&lt;/strong&gt; om het probleem op te lossen.&lt;/p&gt;
+ &lt;h3&gt;'Je klok loopt achter' of 'Je klok loopt voor' of 'NET::ERR_CERT_DATE_INVALID'&lt;/h3&gt;
+ &lt;p&gt;Deze foutmelding wordt weergegeven wanneer de datum en tijd van je computer of mobiele apparaat niet juist is.&lt;/p&gt;
+ &lt;p&gt;Open de klok van je apparaat en update de datum en tijd om dit probleem op te lossen.&lt;/p&gt;
+ &lt;h3&gt;'Software op je computer voorkomt dat Chrome veilig verbinding kan maken met internet' (alleen Windows-computers)&lt;/h3&gt;
+ &lt;p&gt;Deze foutmelding wordt weergegeven wanneer je op je Windows-computer Superfish-software hebt geïnstalleerd.&lt;/p&gt;
+ &lt;p&gt;Volg deze stappen om de software tijdelijk uit te schakelen zodat je verbinding met internet kunt maken. Je hebt beheerdersrechten nodig.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Klik op &lt;strong&gt;Start&lt;/strong&gt; en selecteer &lt;strong&gt;'Lokale services weergeven'&lt;/strong&gt;
+ &lt;li&gt;Selecteer &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Ga naar &lt;strong&gt;Opstarttype&lt;/strong&gt; en selecteer &lt;strong&gt;Uitgeschakeld&lt;/strong&gt;
+ &lt;li&gt;Ga naar &lt;strong&gt;Servicestatus&lt;/strong&gt; en klik op &lt;strong&gt;Stoppen&lt;/strong&gt;
+ &lt;li&gt;Klik op &lt;strong&gt;Toepassen&lt;/strong&gt; en vervolgens op &lt;strong&gt;OK&lt;/strong&gt;
+ &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="3615877443314183785">Geef een geldige vervaldatum op</translation>
<translation id="36224234498066874">Browsegegevens wissen...</translation>
<translation id="362276910939193118">Volledige geschiedenis weergeven</translation>
@@ -400,7 +443,6 @@
<translation id="3778403066972421603">Wil je deze kaart opslaan in je Google-account en op dit apparaat?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Verloopt: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Van <ph name="SITE" /></translation>
<translation id="382518646247711829">Als je een proxyserver gebruikt...</translation>
<translation id="3828924085048779000">Een lege wachtwoordzin is niet toegestaan.</translation>
<translation id="385051799172605136">Vorige</translation>
@@ -414,6 +456,7 @@
<translation id="3945915738023014686">Crashrapport-ID <ph name="CRASH_ID" /> (lokale crash-ID: <ph name="CRASH_LOCAL_ID" />) geüpload</translation>
<translation id="3949571496842715403">Deze server kan niet bewijzen dat dit <ph name="DOMAIN" /> is. In het bijbehorende beveiligingscertificaat worden geen 'Subject Alternative Names' gespecificeerd. Dit kan worden veroorzaakt door een verkeerde configuratie of door een aanvaller die je verbinding heeft onderschept.</translation>
<translation id="3949601375789751990">Je browsegeschiedenis wordt hier weergegeven</translation>
+<translation id="3950820424414687140">Inloggen</translation>
<translation id="3963721102035795474">Lezermodus</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Geen}=1{Van één site }other{Van # sites }}</translation>
<translation id="397105322502079400">Berekenen...</translation>
@@ -430,6 +473,7 @@
<translation id="4103249731201008433">Serienummer van apparaat is ongeldig</translation>
<translation id="410351446219883937">Automatisch afspelen</translation>
<translation id="4103763322291513355">Ga naar &lt;strong&gt;chrome://policy&lt;/strong&gt; om de lijst met URL's op de zwarte lijst en andere beleidsregels te bekijken die worden afgedwongen door je systeembeheerder.</translation>
+<translation id="4110652170750985508">Je betaling controleren</translation>
<translation id="4116663294526079822">Altijd toestaan op deze site</translation>
<translation id="4117700440116928470">Beleidsbereik wordt niet ondersteund.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 andere persoon}other{# andere mensen}}</translation>
@@ -456,7 +500,6 @@
<translation id="4269787794583293679">(Geen gebruikersnaam)</translation>
<translation id="4275830172053184480">Je apparaat opnieuw opstarten</translation>
<translation id="4280429058323657511">, vervalt <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Inloggen</translation>
<translation id="4312866146174492540">Blokkeren (standaard)</translation>
<translation id="4325863107915753736">Kan artikel niet vinden</translation>
<translation id="4326324639298822553">Controleer de vervaldatum en probeer het opnieuw</translation>
@@ -478,14 +521,12 @@
<translation id="4515275063822566619">Kaarten en adressen zijn afkomstig uit Chrome en je Google-account (<ph name="ACCOUNT_EMAIL" />). Je kunt ze beheren in <ph name="BEGIN_LINK" />Instellingen<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Details</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Van een ingesloten pagina op <ph name="SITE" /></translation>
<translation id="4558551763791394412">Probeer je extensies uit te schakelen.</translation>
<translation id="457875822857220463">Bezorging</translation>
<translation id="4582800630050655161">Je kunt de toegang tot je Google-account kwijtraken of slachtoffer worden van identiteitsdiefstal. Chromium raadt je aan je wachtwoord nu te wijzigen.</translation>
<translation id="4587425331216688090">Adres verwijderen uit Chrome?</translation>
<translation id="4592951414987517459">Je verbinding met <ph name="DOMAIN" /> is versleuteld via een moderne Cipher Suite.</translation>
<translation id="4594403342090139922">&amp;Verwijderen ongedaan maken</translation>
-<translation id="4611292653554630842">Inloggen</translation>
<translation id="4619615317237390068">Tabbladen van andere apparaten</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">De server kan niet bewijzen dat dit <ph name="DOMAIN" /> is. Het beveiligingscertificaat van de server bevat fouten. Dit kan worden veroorzaakt door een verkeerde configuratie of een aanvaller die je verbinding onderschept.</translation>
@@ -495,11 +536,9 @@
<translation id="4708268264240856090">Je verbinding is onderbroken</translation>
<translation id="471880041731876836">Je hebt geen toestemming om deze site te bezoeken</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows Netwerkcontrole uitvoeren<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Je betaling</translation>
<translation id="4726672564094551039">Beleid opnieuw laden</translation>
<translation id="4728558894243024398">Platform</translation>
<translation id="4736825316280949806">Chromium opnieuw starten</translation>
-<translation id="4737498291095696011">Van deze pagina</translation>
<translation id="4744603770635761495">Uitvoerbaar pad</translation>
<translation id="4749685221585524849">Laatst gebruikt: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Je gegevens (zoals wachtwoorden of creditcardnummers) zijn privé wanneer ze worden verzonden naar deze site.</translation>
@@ -518,16 +557,16 @@
<translation id="4850886885716139402">Weergave</translation>
<translation id="4854362297993841467">Deze bezorgingsmethode is niet beschikbaar. Kies een andere methode.</translation>
<translation id="4858792381671956233">Je hebt je ouders gevraagd of je deze site mag bezoeken</translation>
-<translation id="4871132632506079383">Van een ingesloten pagina op <ph name="SITE" /></translation>
<translation id="4880827082731008257">Geschiedenis doorzoeken</translation>
+<translation id="4881695831933465202">Openen</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Verificatie vereist</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{en nog 1 webpagina}other{en nog # webpagina's}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Geef de CVC-code voor <ph name="CREDIT_CARD" /> op. Nadat je hebt bevestigd, worden je kaartgegevens gedeeld met deze site.</translation>
<translation id="4923417429809017348">Deze pagina is vertaald uit een onbekende taal naar het <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Betaling</translation>
<translation id="4926049483395192435">Moet worden opgegeven.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> meldt het volgende</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Acties</translation>
<translation id="4958444002117714549">Lijst uitvouwen</translation>
@@ -536,7 +575,6 @@
<translation id="5002932099480077015">Indien ingeschakeld, slaat Chrome een kopie van je kaart op dit apparaat op zodat formulieren sneller kunnen worden ingevuld.</translation>
<translation id="5018422839182700155">Kan deze pagina niet openen</translation>
<translation id="5019198164206649151">Backend-opslag in slechte staat</translation>
-<translation id="5020990877659450221">Van deze pagina</translation>
<translation id="5023310440958281426">Neem het beleid van je beheerder door</translation>
<translation id="5029568752722684782">Kopie wissen</translation>
<translation id="503069730517007720">Er is een rootcertificaat voor '<ph name="SOFTWARE_NAME" />' vereist, maar niet geïnstalleerd. Je IT-beheerder moet de configuratie-instructies voor '<ph name="SOFTWARE_NAME" />' raadplegen om dit probleem op te lossen. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -562,12 +600,12 @@
<translation id="5172758083709347301">Computer</translation>
<translation id="5179510805599951267">Niet in het <ph name="ORIGINAL_LANGUAGE" />? Deze fout melden</translation>
<translation id="5190835502935405962">Bladwijzerbalk</translation>
+<translation id="5201306358585911203">Een ingesloten pagina op deze pagina meldt het volgende</translation>
<translation id="5205222826937269299">Naam vereist</translation>
<translation id="5222812217790122047">E-mailadres vereist</translation>
<translation id="522700295135997067">Deze site heeft mogelijk zojuist je wachtwoord gestolen</translation>
<translation id="5230733896359313003">Verzendadres</translation>
<translation id="5251803541071282808">Cloud</translation>
-<translation id="5277279256032773186">Gebruik je Chrome op het werk? Bedrijven kunnen Chrome-instellingen beheren voor hun werknemers. Meer informatie</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Volg deze stappen om de software tijdelijk uit te schakelen zodat je verbinding met internet kunt maken. Je hebt beheerdersrechten nodig.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -629,7 +667,6 @@
<translation id="5610142619324316209">Controleer de verbinding</translation>
<translation id="5610807607761827392">Je kunt kaarten en adressen beheren in <ph name="BEGIN_LINK" />Instellingen<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> heeft je te vaak omgeleid.</translation>
-<translation id="5622887735448669177">Wil je deze site verlaten?</translation>
<translation id="5629630648637658800">Laden van beleidsinstellingen is mislukt</translation>
<translation id="5631439013527180824">Ongeldige token voor apparaatbeheer</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>
@@ -652,7 +689,6 @@
<translation id="5786044859038896871">Wil je de gegevens van je creditcard laten invullen?</translation>
<translation id="5803412860119678065">Wil je de gegevens van je <ph name="CARD_DETAIL" /> laten invullen?</translation>
<translation id="5810442152076338065">Je verbinding met <ph name="DOMAIN" /> is versleuteld via een verouderde Cipher Suite.</translation>
-<translation id="5810928923025889964">Van een ingesloten pagina op deze pagina</translation>
<translation id="5813119285467412249">&amp;Opnieuw toevoegen</translation>
<translation id="5838278095973806738">Je moet geen gevoelige gegevens (zoals wachtwoorden of creditcards) opgeven op deze site omdat ze kunnen worden gestolen door aanvallers.</translation>
<translation id="5866257070973731571">Telefoonnummer toevoegen</translation>
@@ -725,21 +761,19 @@
<translation id="6446608382365791566">Meer informatie toevoegen</translation>
<translation id="6447842834002726250">Cookies</translation>
<translation id="6451458296329894277">Opnieuw indienen bevestigen</translation>
-<translation id="6456339708790392414">Je betaling</translation>
<translation id="647261751007945333">Apparaatbeleid</translation>
<translation id="6477321094435799029">Chrome heeft ongebruikelijke code op deze pagina gedetecteerd en heeft de code geblokkeerd om je persoonlijke gegevens (zoals wachtwoorden, telefoonnummers en creditcards) te beschermen.</translation>
<translation id="6489534406876378309">Uploaden van crashes starten</translation>
<translation id="6507833130742554667">Creditcards en betaalpassen worden geaccepteerd.</translation>
<translation id="6508722015517270189">Chrome opnieuw starten</translation>
-<translation id="6521373090216409766">Wil je deze site opnieuw laden?</translation>
<translation id="6529602333819889595">&amp;Opnieuw verwijderen</translation>
<translation id="6534179046333460208">Fysieke web-suggesties</translation>
<translation id="6550675742724504774">Opties</translation>
-<translation id="6556239504065605927">Beveiligde verbinding</translation>
<translation id="6556915248009097796">Vervaldatum: <ph name="EXPIRATION_DATE_ABBR" />, laatst gebruikt: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Je beheerder heeft dit nog niet goedgekeurd</translation>
<translation id="6569060085658103619">Je bekijkt een extensiepagina</translation>
<translation id="6596325263575161958">Opties voor encryptie</translation>
+<translation id="6604181099783169992">Bewegings- of lichtsensoren</translation>
<translation id="6624427990725312378">Contactgegevens</translation>
<translation id="6626291197371920147">Een geldig kaartnummer toevoegen</translation>
<translation id="6628463337424475685">Zoeken via <ph name="ENGINE" /></translation>
@@ -811,6 +845,7 @@
<translation id="7275334191706090484">Beheerde bladwijzers</translation>
<translation id="7298195798382681320">Aanbevolen</translation>
<translation id="7309308571273880165">Crashrapport vastgelegd op <ph name="CRASH_TIME" /> (upload aangevraagd door gebruiker, nog niet geüpload)</translation>
+<translation id="7320336641823683070">Hulp bij verbinding maken</translation>
<translation id="7334320624316649418">&amp;Opnieuw volgorde wijzigen</translation>
<translation id="733923710415886693">Het certificaat van de server is niet bekendgemaakt via Certificaattransparantie.</translation>
<translation id="7353601530677266744">Opdrachtregel</translation>
@@ -895,6 +930,7 @@
<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="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="7862185352068345852">Site verlaten?</translation>
<translation id="7878176543348854470">Betaalpassen en prepaidkaarten worden geaccepteerd.</translation>
<translation id="7878562273885520351">Je wachtwoord is mogelijk gehackt</translation>
<translation id="7887683347370398519">Controleer je CVC-code en probeer het opnieuw</translation>
@@ -917,6 +953,7 @@
<translation id="8041940743680923270">Algemene standaardinstelling gebruiken (Vragen)</translation>
<translation id="8042918947222776840">Ophaalmethode kiezen</translation>
<translation id="8057711352706143257">'<ph name="SOFTWARE_NAME" />' is niet correct geconfigureerd. Als je '<ph name="SOFTWARE_NAME" />' verwijdert, wordt het probleem meestal opgelost. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Site opnieuw laden?</translation>
<translation id="8088680233425245692">Kan artikel niet bekijken.</translation>
<translation id="8091372947890762290">Activering is in behandeling op de server</translation>
<translation id="8094917007353911263">Het is mogelijk dat je <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> moet bezoeken van het netwerk dat je gebruikt.</translation>
@@ -932,6 +969,7 @@
<translation id="8201077131113104583">Ongeldige update-URL voor de extensie met de ID '<ph name="EXTENSION_ID" />'.</translation>
<translation id="8202097416529803614">Besteloverzicht</translation>
<translation id="8205463626947051446">Site geeft opdringerige advertenties weer</translation>
+<translation id="8211406090763984747">Verbinding is veilig</translation>
<translation id="8218327578424803826">Toegewezen locatie:</translation>
<translation id="8225771182978767009">De persoon die deze computer heeft geconfigureerd, heeft deze site geblokkeerd.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -943,6 +981,7 @@
<translation id="825929999321470778">Alle opgeslagen wachtwoorden weergeven</translation>
<translation id="8261506727792406068">Verwijderen</translation>
<translation id="8267698848189296333">Inloggen als <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Inloggen</translation>
<translation id="8288807391153049143">Certificaat weergeven</translation>
<translation id="8289355894181816810">Neem contact op met je netwerkbeheerder als je niet zeker weet wat dit betekent.</translation>
<translation id="8293206222192510085">Bladwijzer toevoegen</translation>
@@ -993,6 +1032,7 @@
<translation id="874846938927089722">Geaccepteerde creditcards en prepaidkaarten</translation>
<translation id="8759274551635299824">Deze kaart is verlopen</translation>
<translation id="8761567432415473239">Google Safe Browsing heeft onlangs <ph name="BEGIN_LINK" />schadelijke programma's gevonden<ph name="END_LINK" /> op <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">USB-apparaat</translation>
<translation id="8790007591277257123">&amp;Opnieuw verwijderen</translation>
<translation id="8800988563907321413">Je suggesties voor in de buurt worden hier weergegeven</translation>
<translation id="8820817407110198400">Bladwijzers</translation>
diff --git a/chromium/components/strings/components_strings_no.xtb b/chromium/components/strings/components_strings_no.xtb
index df9d93ba04b..f4d4476242d 100644
--- a/chromium/components/strings/components_strings_no.xtb
+++ b/chromium/components/strings/components_strings_no.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Skriv ut...</translation>
<translation id="1181037720776840403">Fjern</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Rapportér<ph name="END_WHITEPAPER_LINK" /> automatisk detaljer om mulige sikkerhetsbrudd til Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Betalingen er ikke fullført</translation>
<translation id="1201402288615127009">Neste</translation>
<translation id="1201895884277373915">Mer fra dette nettstedet</translation>
<translation id="1206967143813997005">Ugyldig start på signaturen</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Programstopprapport fra <ph name="CRASH_TIME" /> (ignorert eller ikke lastet opp ennå)</translation>
<translation id="1270502636509132238">Hentemåte</translation>
<translation id="1285320974508926690">Oversett aldri dette nettstedet</translation>
+<translation id="1294154142200295408">Variasjoner i kommandolinjen</translation>
<translation id="129553762522093515">Nylig lukket</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Prøv å slette informasjonskapslene dine<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Aktiviteten din <ph name="BEGIN_EMPHASIS" />kan fortsatt være synlig<ph name="END_EMPHASIS" /> for
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Godkjente kreditt- og debetkort</translation>
<translation id="1519264250979466059">Versjonsdato</translation>
<translation id="1527263332363067270">Venter på tilkobling …</translation>
+<translation id="1532118530259321453">På denne siden står det</translation>
<translation id="153384715582417236">Det var alt for denne gangen</translation>
<translation id="154408704832528245">Velg leveringsadresse</translation>
<translation id="1549470594296187301">Denne funksjonen kan ikke brukes når JavaScript er slått av.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Sjekk proxy-tjeneren og brannmuren<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Postnummer</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 forslag}other{# forslag}}</translation>
-<translation id="2065985942032347596">Godkjenning kreves</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="2091887806945687916">Lyd</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Avbryt betalingen</translation>
<translation id="2147827593068025794">Bakgrunnssynkronisering</translation>
<translation id="2148613324460538318">Legg til et kort</translation>
-<translation id="2149973817440762519">Rediger bokmerke</translation>
<translation id="2154054054215849342">Synkronisering er ikke tilgjengelig for domenet ditt</translation>
<translation id="2154484045852737596">Endre kortet</translation>
<translation id="2166049586286450108">Full administratortilgang</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Velg henteadresse</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Fjern valgte elementer</translation>
-<translation id="2744590937989388266">Fra en innebygd side på denne siden</translation>
<translation id="277133753123645258">Leveringsmetode</translation>
<translation id="277499241957683684">Manglende enhetsoppføring</translation>
<translation id="2784949926578158345">Tilkoblingen ble tilbakestilt.</translation>
<translation id="2788784517760473862">Godkjente kredittkort</translation>
<translation id="2794233252405721443">Nettstedet er blokkert</translation>
-<translation id="2795286477369100655">Vil du forlate dette nettstedet?</translation>
<translation id="2799020568854403057">Nettstedet du er på vei til, inneholder skadelige apper</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="2824775600643448204">Adresse- og søkefelt</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Listeoppføring «<ph name="ENTRY_INDEX" />»: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automatisk blokkert</translation>
<translation id="3024663005179499861">Feil type enhetsinnstillinger</translation>
-<translation id="3032412215588512954">Vil du laste inn dette nettstedet på nytt?</translation>
<translation id="3037605927509011580">Æsj!</translation>
<translation id="3039538478787849737">Vil du lagre kortet i Google?</translation>
<translation id="3041612393474885105">Sertifikatinformasjon</translation>
@@ -310,6 +306,7 @@
for å forsikre deg om at den fungerer. Følg disse instruksjonene hvis du
ikke tror du trenger å bruke noen proxy-tjener:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> på <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Avbryt betalingen</translation>
<translation id="3207960819495026254">Bokmerket</translation>
<translation id="3209375525920864198">Skriv inn et gyldig øktnavn.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Administratoren din kan oppheve blokkeringen for deg</translation>
<translation id="3566021033012934673">Tilkoblingen din er ikke privat</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" />, <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">På en innebygd side på <ph name="SITE" /> står det</translation>
<translation id="358285529439630156">Kredittkort og forhåndsbetalte kort godtas.</translation>
<translation id="3582930987043644930">Legg til navn</translation>
<translation id="3583757800736429874">&amp;Flytt likevel</translation>
<translation id="3586931643579894722">Skjul detaljer</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Fiks tilkoblingsfeil&lt;/h1&gt;
+ &lt;p&gt;Hvis du får en feilmelding når du prøver å besøke et nettsted, kan du prøve disse løsningene.&lt;/p&gt;
+ &lt;h2&gt;Fiks de fleste tilkoblingsfeil&lt;/h2&gt;
+ &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;
+ &lt;ol&gt;
+ &lt;li&gt;Sjekk at nettadressen er skrevet riktig.&lt;/li&gt;
+ &lt;li&gt;Sjekk at Internett-tilkoblingen din fungerer som den skal.&lt;/li&gt;
+ &lt;li&gt;Kontakt eieren av nettstedet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Få hjelp med spesifikke feilmeldinger&lt;/h2&gt;
+ &lt;h3&gt;«Tilkoblingen din er ikke privat», «NET::ERR_CERT_AUTHORITY_INVALID», «ERR_CERT_COMMON_NAME_INVALID», «NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM» eller «Feil i SSL-sertifikatet»&lt;/h3&gt;
+ &lt;h4&gt;Trinn 1: Logg på portalen&lt;/h4&gt;
+ &lt;p&gt;Wi-Fi-nettverk på steder som kaféer eller flyplasser krever at du logger på. For å se påloggingssiden, åpne en side som bruker &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Gå til et nettsted som begynner på &lt;code&gt;http://&lt;/code&gt; – for eksempel &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Logg på via påloggingssiden som åpnes, for å bruke Internett.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Trinn 2: Åpne siden i inkognitomodus (bare på datamaskiner)&lt;/h4&gt;
+ &lt;p&gt;Åpne siden du besøkte, i et inkognitovindu.&lt;/p&gt;
+ &lt;p&gt;Hvis siden åpnes, har du en Chrome-utvidelse som ikke fungerer som den skal. Du kan fikse feilen ved å slå av utvidelsen.&lt;/p&gt;
+ &lt;h4&gt;Trinn 3: Oppdater operativsystemet&lt;/h4&gt;
+ &lt;p&gt;Sørg for at enheten din er oppdatert.&lt;/p&gt;
+ &lt;h4&gt;Trinn 4: Slå av antivirusprogramvaren midlertidig&lt;/h4&gt;
+ &lt;p&gt;Du ser denne feilmeldingen hvis du har antivirusprogramvare som tilbyr «HTTPS-beskyttelse» eller «HTTPS-skanning», noe som gjør at sikkerhetsfunksjonene i Chrome ikke fungerer.&lt;/p&gt;
+ &lt;p&gt;For å fikse dette problemet, slå av antivirusprogramvaren. Hvis siden fungerer når du har slått av programvaren, bør du slå den av når du bruker sikre nettsteder.&lt;/p&gt;
+ &lt;p&gt;Husk å slå på antivirusprogramvaren igjen når du er ferdig.&lt;/p&gt;
+ &lt;h4&gt;Trinn 5: Få mer hjelp&lt;/h4&gt;
+ &lt;p&gt;Hvis du fortsatt får feilmeldingen, bør du kontakte eieren av nettstedet.&lt;/p&gt;
+ &lt;h3&gt;«Koble til nettverket»&lt;/h3&gt;
+ &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;
+ &lt;h3&gt;«Klokken går for sent», «Klokken går for fort» eller «NET::ERR_CERT_DATE_INVALID»&lt;/h3&gt;
+ &lt;p&gt;Du ser denne feilmeldingen hvis datoen og klokkeslettet på datamaskinen eller mobilenheten din er unøyaktig.&lt;/p&gt;
+ &lt;p&gt;For å fikse feilen, åpne klokken på enheten, og sørg for at klokkeslettet og datoen er riktig.&lt;/p&gt;
+ &lt;h3&gt;«Det er programvare på datamaskinen din som hindrer Chrome i å koble trygt til Internett» (bare på Windows-datamaskiner)&lt;/h3&gt;
+ &lt;p&gt;Du ser denne feilen hvis du har Superfish-programvare på Windows-datamaskinen din.&lt;/p&gt;
+ &lt;p&gt;Følg disse trinnene for å deaktivere programvaren midlertidig, sånn at du kan komme deg på nettet. Du må ha administratorrettigheter.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Klikk på &lt;strong&gt;Start&lt;/strong&gt;, og søk etter og velg &lt;strong&gt;«Vis lokale tjenester»&lt;/strong&gt;
+ &lt;li&gt;Velg &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Gå til &lt;strong&gt;Oppstartstype&lt;/strong&gt;, og velg &lt;strong&gt;Deaktivert&lt;/strong&gt;
+ &lt;li&gt;Gå til &lt;strong&gt;Tjenestestatus&lt;/strong&gt;, og klikk på &lt;strong&gt;Stopp&lt;/strong&gt;
+ &lt;li&gt;Klikk på &lt;strong&gt;Bruk&lt;/strong&gt; og deretter på &lt;strong&gt;OK&lt;/strong&gt;
+ &lt;li&gt;Gå til &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;brukerstøtten for Google Chrome&lt;/a&gt; for å finne ut hvordan du fjerner programvaren fra datamaskinen permanent
+ &lt;/ol&gt;</translation>
<translation id="3615877443314183785">Angi en gyldig utløpsdato</translation>
<translation id="36224234498066874">Slett nettlesingsdata...</translation>
<translation id="362276910939193118">Vis fullstendig logg</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Vil du lagre dette kortet i Google-kontoen din og på denne enheten?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Utløper <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Fra <ph name="SITE" /></translation>
<translation id="382518646247711829">Hvis du bruker en mellomtjener...</translation>
<translation id="3828924085048779000">Tom passordfrase er ikke tillatt.</translation>
<translation id="385051799172605136">Tilbake</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">ID-en for den opplastede programstopprapporten: <ph name="CRASH_ID" /> (lokal kræsj-ID: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Denne tjeneren kunne ikke bevise at den er <ph name="DOMAIN" />. Det er ikke angitt noen alternative emnenavn i tjenerens sikkerhetssertifikat. Dette kan være forårsaket av en feilkonfigurering eller en angriper som avskjærer tilkoblingen din.</translation>
<translation id="3949601375789751990">Nettleserloggen din vises her</translation>
+<translation id="3950820424414687140">Logg på</translation>
<translation id="3963721102035795474">Lesermodus</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Ingen}=1{Fra 1 nettsted }other{Fra # nettsteder }}</translation>
<translation id="397105322502079400">Beregner …</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Enhetens serienummer er ugyldig</translation>
<translation id="410351446219883937">Autoavspilling</translation>
<translation id="4103763322291513355">Gå til &lt;strong&gt;chrome://policy&lt;/strong&gt; for å se listen over sperrede nettadresser og andre innstillinger aktivert av systemadministratoren din.</translation>
+<translation id="4110652170750985508">Gjennomgå betalingen</translation>
<translation id="4116663294526079822">Tillat alltid på dette nettstedet</translation>
<translation id="4117700440116928470">Omfanget for innstillingen støttes ikke.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 til}other{# til}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Uten brukernavn)</translation>
<translation id="4275830172053184480">Start enheten din på nytt</translation>
<translation id="4280429058323657511">, utløper <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Logg på</translation>
<translation id="4312866146174492540">Blokkér (standard)</translation>
<translation id="4325863107915753736">Artikkelen ble ikke funnet</translation>
<translation id="4326324639298822553">Kontrollér utløpsdatoen, og prøv igjen</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Kortene og adressene er fra Chrome og Google-kontoen din (<ph name="ACCOUNT_EMAIL" />). Du kan administrere dem i <ph name="BEGIN_LINK" />Innstillinger<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Detaljer</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Fra en innebygd side på <ph name="SITE" /></translation>
<translation id="4558551763791394412">Prøv å slå av utvidelsene dine.</translation>
<translation id="457875822857220463">Levering</translation>
<translation id="4582800630050655161">Du kan miste tilgangen til Google-kontoen din eller bli utsatt for identitetstyveri. Chromium anbefaler at du endrer passordet ditt nå.</translation>
<translation id="4587425331216688090">Vil du fjerne adressen fra Chrome?</translation>
<translation id="4592951414987517459">Tilkoblingen til <ph name="DOMAIN" /> er kryptert med en moderne chifferserie.</translation>
<translation id="4594403342090139922">&amp;Angre slettingen</translation>
-<translation id="4611292653554630842">Logg på</translation>
<translation id="4619615317237390068">Faner fra andre enheter</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Denne tjeneren kunne ikke bevise at den er <ph name="DOMAIN" />. Sikkerhetssertifikatet til tjeneren inneholder feil. Dette kan være forårsaket av en feilkonfigurering eller en angriper som avskjærer tilkoblingen din.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Tilkoblingen ble avbrutt</translation>
<translation id="471880041731876836">Du har ikke tillatelse til å besøke dette nettstedet</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Kjør Windows Nettverksdiagnose<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Betalingen din</translation>
<translation id="4726672564094551039">Last inn retningslinjer på nytt</translation>
<translation id="4728558894243024398">Plattform</translation>
<translation id="4736825316280949806">Start Chromium på nytt</translation>
-<translation id="4737498291095696011">Fra denne siden</translation>
<translation id="4744603770635761495">Kjørbar sti</translation>
<translation id="4749685221585524849">Sist brukt: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Informasjonen din (for eksempel passord eller kredittkortnumre) er privat når den sendes til dette nettstedet.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Visning</translation>
<translation id="4854362297993841467">Denne leveringsmetoden er ikke tilgjengelig. Prøv en annen metode.</translation>
<translation id="4858792381671956233">Du har spurt foreldrene dine om det er greit å besøke dette nettstedet</translation>
-<translation id="4871132632506079383">Fra en innebygd side på <ph name="SITE" /></translation>
<translation id="4880827082731008257">Søk i loggen</translation>
+<translation id="4881695831933465202">Åpne</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Autentisering kreves</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{og 1 nettside til}other{og # nettsider til}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Skriv inn CVC-koden for <ph name="CREDIT_CARD" />. Etter at du har bekreftet, deles kortopplysningene fra Google Payments-kontoen med dette nettstedet.</translation>
<translation id="4923417429809017348">Denne siden er oversatt til <ph name="LANGUAGE_LANGUAGE" /> fra et ukjent språk</translation>
<translation id="4923459931733593730">Betaling</translation>
<translation id="4926049483395192435">Må angis.</translation>
+<translation id="4926159001844873046">På <ph name="SITE" /> står det</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Handlinger</translation>
<translation id="4958444002117714549">Utvid liste</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Hvis du slår på dette alternativet, lagrer Chrome en kopi av kortet ditt på denne enheten, slik at det blir raskere å fylle ut skjemaer i fremtiden.</translation>
<translation id="5018422839182700155">Kan ikke åpne denne siden</translation>
<translation id="5019198164206649151">Ugyldig funksjonalitet for sikkerhetskopiering</translation>
-<translation id="5020990877659450221">Fra denne siden</translation>
<translation id="5023310440958281426">Kontrollér retningslinjene til administratoren din</translation>
<translation id="5029568752722684782">Slett kopi</translation>
<translation id="503069730517007720">Et rotsertifikat for «<ph name="SOFTWARE_NAME" />» kreves, men er ikke installert. IT-administratoren din bør se på konfigurasjonsveiledningen for «<ph name="SOFTWARE_NAME" />» for å løse dette problemet. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Datamaskin</translation>
<translation id="5179510805599951267">Er ikke dette <ph name="ORIGINAL_LANGUAGE" />? Rapportér denne feilen</translation>
<translation id="5190835502935405962">Bokmerkerad</translation>
+<translation id="5201306358585911203">På en innebygd side på denne siden står det</translation>
<translation id="5205222826937269299">Navn er obligatorisk</translation>
<translation id="5222812217790122047">E-post er obligatorisk</translation>
<translation id="522700295135997067">Dette nettstedet stjal muligens nettopp passordet ditt</translation>
<translation id="5230733896359313003">Leveringsadresse</translation>
<translation id="5251803541071282808">Nettsky</translation>
-<translation id="5277279256032773186">Bruker du Chrome på jobben? Bedrifter kan administrere Chrome-innstillingene for de ansatte. Finn ut mer</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Følg disse trinnene for å deaktivere programvaren midlertidig, sånn at du kan komme deg på nettet. Du må ha administratorrettigheter.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Sjekk tilkoblingen</translation>
<translation id="5610807607761827392">Du kan administrere kort og adresser i <ph name="BEGIN_LINK" />Innstillinger<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> viderekoblet deg for mange ganger.</translation>
-<translation id="5622887735448669177">Vil du forlate dette nettstedet?</translation>
<translation id="5629630648637658800">Kunne ikke laste in angivelsen for enhetsinnstillinger</translation>
<translation id="5631439013527180824">Ugyldig token for enhetsadministrering</translation>
<translation id="5633066919399395251">Angripere som for øyeblikket 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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Vil du fylle ut kortinformasjonen?</translation>
<translation id="5803412860119678065">Vil du fylle ut informasjonen knyttet til <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Tilkoblingen til <ph name="DOMAIN" /> er kryptert med en foreldet chifferserie.</translation>
-<translation id="5810928923025889964">Fra en innebygd side på denne siden</translation>
<translation id="5813119285467412249">&amp;Legg til likevel</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>
<translation id="5866257070973731571">Legg til telefonnummer</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Legg til mer informasjon</translation>
<translation id="6447842834002726250">Informasjonskapsler</translation>
<translation id="6451458296329894277">Bekreft ny innsending av skjema</translation>
-<translation id="6456339708790392414">Betalingen din</translation>
<translation id="647261751007945333">Enhetsinnstillinger</translation>
<translation id="6477321094435799029">Chrome har oppdaget uvanlig kode på denne siden og blokkert den for å beskytte personopplysningene dine (for eksempel passord, telefonnumre og kredittkortinformasjon).</translation>
<translation id="6489534406876378309">Start opplastingen av krasj</translation>
<translation id="6507833130742554667">Kreditt- og debetkort godtas.</translation>
<translation id="6508722015517270189">Start Chrome på nytt</translation>
-<translation id="6521373090216409766">Vil du laste inn dette nettstedet på nytt?</translation>
<translation id="6529602333819889595">&amp;Slett likevel</translation>
<translation id="6534179046333460208">Fysisk nett-forslag</translation>
<translation id="6550675742724504774">Alternativer</translation>
-<translation id="6556239504065605927">Sikker tilkobling</translation>
<translation id="6556915248009097796">Utløper: <ph name="EXPIRATION_DATE_ABBR" />. Sist brukt: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Administratoren din har ikke godkjent det ennå</translation>
<translation id="6569060085658103619">Du ser på en utvidelsesside</translation>
<translation id="6596325263575161958">Krypteringsalternativer</translation>
+<translation id="6604181099783169992">Bevegelses- eller lyssensorer</translation>
<translation id="6624427990725312378">Kontaktinformasjon</translation>
<translation id="6626291197371920147">Legg til et gyldig kortnummer</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Søk</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Administrerte bokmerker</translation>
<translation id="7298195798382681320">Anbefalt</translation>
<translation id="7309308571273880165">Programstopprapport opprettet <ph name="CRASH_TIME" /> (opplasting er forespurt av brukeren, men den har ikke blitt utført ennå)</translation>
+<translation id="7320336641823683070">Tilkoblingshjelp</translation>
<translation id="7334320624316649418">&amp;Omorganiser likevel</translation>
<translation id="733923710415886693">Tjenerens sertifikat er ikke vist i henhold til regelen for sertifikatåpenhet.</translation>
<translation id="7353601530677266744">Kommandolinje </translation>
@@ -900,6 +935,7 @@
<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="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="7862185352068345852">Vil du forlate nettstedet?</translation>
<translation id="7878176543348854470">Debetkort og forhåndsbetalte kort godtas.</translation>
<translation id="7878562273885520351">Passordet ditt kan være kompromittert</translation>
<translation id="7887683347370398519">Kontrollér CVC-koden din, og prøv igjen.</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Bruk global standardinnstilling (Spør)</translation>
<translation id="8042918947222776840">Velg hentemåte</translation>
<translation id="8057711352706143257">«<ph name="SOFTWARE_NAME" />» er ikke riktig konfigurert. Avinstallering av «<ph name="SOFTWARE_NAME" />» løser vanligvis problemet. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Vil du laste inn nettstedet på nytt?</translation>
<translation id="8088680233425245692">Kunne ikke åpne artikkelen.</translation>
<translation id="8091372947890762290">Aktivering venter på tjeneren</translation>
<translation id="8094917007353911263">Det kan hende at nettverket du bruker, krever at du besøker <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">Ugyldig oppdaterings-URL for utvidelse med ID «<ph name="EXTENSION_ID" />».</translation>
<translation id="8202097416529803614">Bestillingssammendrag</translation>
<translation id="8205463626947051446">Nettstedet viser ofte forstyrrende annonser</translation>
+<translation id="8211406090763984747">Tilkoblingen er sikker</translation>
<translation id="8218327578424803826">Tilordnet posisjon:</translation>
<translation id="8225771182978767009">Personen som konfigurerte denne datamaskinen, har valgt å blokkere dette nettstedet.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Vis alle lagrede passord</translation>
<translation id="8261506727792406068">Slett</translation>
<translation id="8267698848189296333">Logger på som <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Logg på</translation>
<translation id="8288807391153049143">Vis sertifikat</translation>
<translation id="8289355894181816810">Kontakt nettverksadministratoren hvis du ikke er sikker på hva dette betyr.</translation>
<translation id="8293206222192510085">Legg til bokmerke</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Godkjente kredittkort og forhåndsbetalte kort</translation>
<translation id="8759274551635299824">Dette kortet er utløpt</translation>
<translation id="8761567432415473239">Google Safe Browsing oppdaget nylig <ph name="BEGIN_LINK" />skadelige programmer<ph name="END_LINK" /> på <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">USB-enhet</translation>
<translation id="8790007591277257123">&amp;Slett likevel</translation>
<translation id="8800988563907321413">Forslagene dine om ting like ved vises her</translation>
<translation id="8820817407110198400">Bokmerker</translation>
diff --git a/chromium/components/strings/components_strings_pl.xtb b/chromium/components/strings/components_strings_pl.xtb
index 385d6e76f0e..af3113dd971 100644
--- a/chromium/components/strings/components_strings_pl.xtb
+++ b/chromium/components/strings/components_strings_pl.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Drukuj...</translation>
<translation id="1181037720776840403">Usuń</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Automatycznie przesyłaj<ph name="END_WHITEPAPER_LINK" /> do Google szczegółowe informacje o możliwych zagrożeniach. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Płatność nie została zrealizowana</translation>
<translation id="1201402288615127009">Dalej</translation>
<translation id="1201895884277373915">Więcej z tej witryny</translation>
<translation id="1206967143813997005">Nieprawidłowy podpis wstępny</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Utworzono raport o awarii w dniu: <ph name="CRASH_TIME" /> (nie został jeszcze przesłany ani zignorowany)</translation>
<translation id="1270502636509132238">Metoda odbioru</translation>
<translation id="1285320974508926690">Nigdy nie tłumacz tej witryny</translation>
+<translation id="1294154142200295408">Odmiany w wierszu poleceń</translation>
<translation id="129553762522093515">Ostatnio zamknięte</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Usuń pliki cookie<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Twoja aktywność <ph name="BEGIN_EMPHASIS" />może być nadal widoczna<ph name="END_EMPHASIS" /> dla:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Akceptowane karty kredytowe i debetowe</translation>
<translation id="1519264250979466059">Data kompilacji</translation>
<translation id="1527263332363067270">Czekam na połączenie…</translation>
+<translation id="1532118530259321453">Komunikat z bieżącej strony</translation>
<translation id="153384715582417236">Na razie to wszystko</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>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Sprawdź serwer proxy i zaporę sieciową<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Kod pocztowy</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 podpowiedź}few{# podpowiedzi}many{# podpowiedzi}other{# podpowiedzi}}</translation>
-<translation id="2065985942032347596">Wymagane uwierzytelnienie</translation>
<translation id="2079545284768500474">Cofnij</translation>
<translation id="20817612488360358">Skonfigurowano używanie systemowych ustawień proxy, ale podano też jawną konfigurację proxy.</translation>
<translation id="2091887806945687916">Dźwięk</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Anuluj płatność</translation>
<translation id="2147827593068025794">Synchronizacja w tle</translation>
<translation id="2148613324460538318">Dodaj kartę</translation>
-<translation id="2149973817440762519">Edytuj zakładkę</translation>
<translation id="2154054054215849342">Synchronizacja nie jest dostępna w Twojej domenie.</translation>
<translation id="2154484045852737596">Edytowanie karty</translation>
<translation id="2166049586286450108">Pełny dostęp administratora</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Wybierz adres odbioru</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Usuń wybrane elementy</translation>
-<translation id="2744590937989388266">Z elementu umieszczonego na bieżącej stronie</translation>
<translation id="277133753123645258">Metoda wysyłki</translation>
<translation id="277499241957683684">Brak rekordu urządzenia</translation>
<translation id="2784949926578158345">Połączenie zostało zresetowane.</translation>
<translation id="2788784517760473862">Akceptowane karty kredytowe</translation>
<translation id="2794233252405721443">Strona zablokowana</translation>
-<translation id="2795286477369100655">Chcesz opuścić tę stronę?</translation>
<translation id="2799020568854403057">Strona, którą chcesz otworzyć, zawiera szkodliwe aplikacje</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="2824775600643448204">Pasek adresu i wyszukiwania</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Pozycja listy „<ph name="ENTRY_INDEX" />”: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automatycznie zablokowane</translation>
<translation id="3024663005179499861">Nieprawidłowy typ zasady</translation>
-<translation id="3032412215588512954">Chcesz ponownie załadować tę stronę?</translation>
<translation id="3037605927509011580">Kurza twarz!</translation>
<translation id="3039538478787849737">Zapisać kartę w Google?</translation>
<translation id="3041612393474885105">Informacje o certyfikacie</translation>
@@ -310,6 +306,7 @@
by upewnić się, że serwer proxy działa. Jeśli uważasz, że
nie powinien być on używany:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> na serwerze <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Anuluj płatność</translation>
<translation id="3207960819495026254">Dodano do zakładek</translation>
<translation id="3209375525920864198">Wpisz prawidłową nazwę sesji.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Twój menedżer może ją dla Ciebie odblokować</translation>
<translation id="3566021033012934673">Połączenie nie jest prywatne</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Komunikat z elementu umieszczonego na stronie <ph name="SITE" /></translation>
<translation id="358285529439630156">Karty kredytowe i przedpłacone są akceptowane.</translation>
<translation id="3582930987043644930">Dodaj nazwę</translation>
<translation id="3583757800736429874">&amp;Ponów przeniesienie</translation>
<translation id="3586931643579894722">Ukryj szczegóły</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Naprawianie błędów połączenia&lt;/h1&gt;
+ &lt;p&gt;Jeśli podczas próby wejścia na stronę pojawia się komunikat o błędzie, wypróbuj te rozwiązania.&lt;/p&gt;
+ &lt;h2&gt;Naprawianie większości błędów połączenia&lt;/h2&gt;
+ &lt;p&gt;Jeśli nie udaje się otworzyć strony, spróbuj rozwiązać problem, wykonując najpierw te czynności:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Sprawdź, czy w adresie internetowym nie ma błędów.&lt;/li&gt;
+ &lt;li&gt;Upewnij się, że połączenie internetowe działa prawidłowo.&lt;/li&gt;
+ &lt;li&gt;Skontaktuj się z właścicielem strony.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Uzyskiwanie pomocy w przypadku konkretnego komunikatu o błędzie&lt;/h2&gt;
+ &lt;h3&gt;„Połączenie nie jest prywatne” lub „NET::ERR_CERT_AUTHORITY_INVALID” lub „ERR_CERT_COMMON_NAME_INVALID” lub „NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM” lub „Błąd certyfikatu SSL”&lt;/h3&gt;
+ &lt;h4&gt;Krok 1. Zaloguj się w portalu&lt;/h4&gt;
+ &lt;p&gt;Aby w miejscach takich jak kawiarnie czy lotniska korzystać z sieci Wi-Fi, trzeba się w nich zalogować. Aby pojawiła się strona logowania, otwórz stronę rozpoczynającą się od &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Spróbuj wejść na dowolną stronę, której adres zaczyna się od &lt;code&gt;http://&lt;/code&gt;, np. &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Na stronie logowania, która się otworzy, zaloguj się, by korzystać z internetu.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Krok 2. Otwórz stronę w trybie incognito (tylko na komputerze)&lt;/h4&gt;
+ &lt;p&gt;Otwórz stronę w oknie incognito.&lt;/p&gt;
+ &lt;p&gt;Jeśli strona otwiera się, problem powoduje nieprawidłowo działające rozszerzenie Chrome. Aby to naprawić, wyłącz rozszerzenie.&lt;/p&gt;
+ &lt;h4&gt;Krok 3. Zaktualizuj system operacyjny&lt;/h4&gt;
+ &lt;p&gt;Upewnij się, że na urządzeniu masz zainstalowaną aktualną wersję systemu operacyjnego.&lt;/p&gt;
+ &lt;h4&gt;Krok 4. Tymczasowo wyłącz oprogramowanie antywirusowe&lt;/h4&gt;
+ &lt;p&gt;Ten błąd występuje, jeśli używasz oprogramowania antywirusowego z „ochroną HTTPS” lub „skanowaniem HTTPS”, które nie pozwala Chrome na nawiązanie bezpiecznego połączenia.&lt;/p&gt;
+ &lt;p&gt;Aby rozwiązać problem, wyłącz oprogramowanie antywirusowe. Jeśli strona się otworzy, na czas odwiedzania bezpiecznych witryn wyłączaj to oprogramowanie.&lt;/p&gt;
+ &lt;p&gt;Pamiętaj, by ponownie włączyć oprogramowanie antywirusowe, gdy skończysz.&lt;/p&gt;
+ &lt;h4&gt;Krok 5. Uzyskaj dodatkową pomoc&lt;/h4&gt;
+ &lt;p&gt;Jeśli nadal pojawia się błąd, skontaktuj się z właścicielem strony.&lt;/p&gt;
+ &lt;h3&gt;„Połącz z siecią”&lt;/h3&gt;
+ &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;
+ &lt;h3&gt;„Twój zegar się spóźnia”, „Twój zegar się śpieszy” lub „NET::ERR_CERT_DATE_INVALID”&lt;/h3&gt;
+ &lt;p&gt;Ten błąd występuje, jeśli data i godzina na komputerze lub urządzeniu mobilnym są niedokładne.&lt;/p&gt;
+ &lt;p&gt;Aby naprawić błąd, otwórz ustawienia zegara na urządzeniu. Zmień datę i godzinę na prawidłowe.&lt;/p&gt;
+ &lt;h3&gt;„Oprogramowanie na Twoim komputerze uniemożliwia Chrome bezpieczne połączenie się z internetem” (tylko na komputerach z systemem Windows)&lt;/h3&gt;
+ &lt;p&gt;Ten błąd występuje, jeśli na komputerze z Windows masz zainstalowane oprogramowanie Superfish.&lt;/p&gt;
+ &lt;p&gt;Wykonaj te czynności, by tymczasowo wyłączyć to oprogramowanie i otworzyć stronę internetową. Musisz mieć uprawnienia administratora.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Kliknij &lt;strong&gt;Start&lt;/strong&gt;, a następnie wyszukaj i wybierz opcję &lt;strong&gt;„Wyświetl usługi lokalne”&lt;/strong&gt;.
+ &lt;li&gt;Wybierz &lt;strong&gt;VisualDiscovery&lt;/strong&gt;.
+ &lt;li&gt;W obszarze &lt;strong&gt;Typ uruchomienia&lt;/strong&gt; wybierz &lt;strong&gt;Wyłączony&lt;/strong&gt;.
+ &lt;li&gt;W obszarze &lt;strong&gt;Stan usługi&lt;/strong&gt; kliknij &lt;strong&gt;Zatrzymaj&lt;/strong&gt;.
+ &lt;li&gt;Kliknij &lt;strong&gt;Zastosuj&lt;/strong&gt;, a następnie &lt;strong&gt;OK&lt;/strong&gt;.
+ &lt;li&gt;Odwiedź &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centrum pomocy Chrome&lt;/a&gt;, by dowiedzieć się, jak trwale usunąć to oprogramowanie ze swojego komputera.
+ &lt;/ol&gt;</translation>
<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>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Czy chcesz zapisać tę kartę na swoim koncie Google i na tym urządzeniu?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Wygasa: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Ze strony <ph name="SITE" /></translation>
<translation id="382518646247711829">Jeśli używasz serwera proxy...</translation>
<translation id="3828924085048779000">Puste hasło jest niedozwolone.</translation>
<translation id="385051799172605136">Wstecz</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">Przesłano raport o awarii – identyfikator: <ph name="CRASH_ID" /> (lokalny identyfikator awarii: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Serwer nie mógł udowodnić, że należy do <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa nie określa alternatywnych nazw podmiotu. Może to być spowodowane błędną konfiguracją lub przechwyceniem połączenia przez atakującego.</translation>
<translation id="3949601375789751990">Tutaj wyświetla się Twoja historia przeglądania</translation>
+<translation id="3950820424414687140">Zaloguj się</translation>
<translation id="3963721102035795474">Tryb czytnika</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Brak}=1{Z 1 witryny }few{Z # witryn }many{Z # witryn }other{Z # witryny }}</translation>
<translation id="397105322502079400">Obliczanie...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Numer seryjny urządzenia jest nieprawidłowy</translation>
<translation id="410351446219883937">Autoodtwarzanie</translation>
<translation id="4103763322291513355">Wejdź na stronę &lt;strong&gt;chrome://policy&lt;/strong&gt;, aby wyświetlić czarną listę URL-i oraz inne zasady egzekwowane przez administratora systemu.</translation>
+<translation id="4110652170750985508">Sprawdź szczegóły płatności</translation>
<translation id="4116663294526079822">Zawsze zezwalaj w tej witrynie</translation>
<translation id="4117700440116928470">Ten zakres zasad nie jest obsługiwany.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 inny wpis}few{# inne wpisy}many{# innych wpisów}other{# innego wpisu}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Brak nazwy użytkownika)</translation>
<translation id="4275830172053184480">Zrestartuj urządzenie</translation>
<translation id="4280429058323657511">, ważna do: <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Zaloguj się</translation>
<translation id="4312866146174492540">Blokuj (domyślnie)</translation>
<translation id="4325863107915753736">Nie udało się znaleźć artykułu</translation>
<translation id="4326324639298822553">Sprawdź datę ważności i spróbuj ponownie</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Karty i adresy pochodzą z Chrome i Twojego konta Google (<ph name="ACCOUNT_EMAIL" />). Możesz nimi zarządzać w <ph name="BEGIN_LINK" />Ustawieniach<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Szczegóły</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Z elementu umieszczonego na stronie <ph name="SITE" /></translation>
<translation id="4558551763791394412">Spróbuj wyłączyć rozszerzenia.</translation>
<translation id="457875822857220463">Dostawa</translation>
<translation id="4582800630050655161">Możesz stracić dostęp do swojego konta Google lub paść ofiarą kradzieży tożsamości. Chromium zaleca natychmiastową zmianę hasła.</translation>
<translation id="4587425331216688090">Usunąć ten adres z Chrome?</translation>
<translation id="4592951414987517459">Połączenie z <ph name="DOMAIN" /> jest szyfrowane przy użyciu nowoczesnego zestawu szyfrów.</translation>
<translation id="4594403342090139922">&amp;Cofnij usunięcie</translation>
-<translation id="4611292653554630842">Zaloguj się</translation>
<translation id="4619615317237390068">Karty z innych urządzeń</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Ten serwer nie mógł udowodnić, że należy do <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa ma błędy. Może to być spowodowane błędną konfiguracją lub przechwyceniem połączenia przez atakującego.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Połączenie zostało przerwane</translation>
<translation id="471880041731876836">Nie masz pozwolenia, by wejść na tę stronę</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Uruchom Diagnostykę sieci systemu Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Twoja płatność</translation>
<translation id="4726672564094551039">Odśwież zasady</translation>
<translation id="4728558894243024398">Platforma</translation>
<translation id="4736825316280949806">Uruchom ponownie Chromium</translation>
-<translation id="4737498291095696011">Z tej strony</translation>
<translation id="4744603770635761495">Ścieżka pliku wykonywalnego</translation>
<translation id="4749685221585524849">Ostatnio używana: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Informacje, które wysyłasz tej witrynie (na przykład hasła lub numery kart kredytowych), pozostają prywatne.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Widok</translation>
<translation id="4854362297993841467">Ta metoda dostawy jest niedostępna. Wybierz inną.</translation>
<translation id="4858792381671956233">Zapytałeś rodziców, czy możesz wejść na tę stronę</translation>
-<translation id="4871132632506079383">Z elementu umieszczonego na stronie <ph name="SITE" /></translation>
<translation id="4880827082731008257">Przeszukaj historię</translation>
+<translation id="4881695831933465202">Otwórz</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Wymagane uwierzytelnienie</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{i jeszcze 1 strona}few{i jeszcze # strony}many{i jeszcze # stron}other{i jeszcze # strony}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Wpisz kod CVC karty <ph name="CREDIT_CARD" />. Po potwierdzeniu szczegółowe dane karty z Twojego konta Google Payments zostaną udostępnione tej stronie.</translation>
<translation id="4923417429809017348">Ta strona została przetłumaczona z nieznanego języka na język <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Płatność</translation>
<translation id="4926049483395192435">Musi być określona.</translation>
+<translation id="4926159001844873046">Komunikat ze strony <ph name="SITE" /></translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Czynności</translation>
<translation id="4958444002117714549">Rozwiń listę</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Jeśli włączysz tę opcję, Chrome zapisze kopię Twojej karty na tym urządzeniu, by umożliwić Ci szybsze wypełnianie formularzy.</translation>
<translation id="5018422839182700155">Nie można otworzyć tej strony</translation>
<translation id="5019198164206649151">Nieprawidłowy stan magazynu wspomagającego</translation>
-<translation id="5020990877659450221">Z tej strony</translation>
<translation id="5023310440958281426">Sprawdź zasady administratora</translation>
<translation id="5029568752722684782">Usuń kopię</translation>
<translation id="503069730517007720">Certyfikat główny oprogramowania „<ph name="SOFTWARE_NAME" />” jest wymagany, ale nie został zainstalowany. Aby rozwiązać ten problem, administrator powinien przeczytać instrukcje dotyczące konfiguracji oprogramowania „<ph name="SOFTWARE_NAME" />”. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Komputer</translation>
<translation id="5179510805599951267">Jeśli to nie jest język <ph name="ORIGINAL_LANGUAGE" />, zgłoś błąd</translation>
<translation id="5190835502935405962">Pasek zakładek</translation>
+<translation id="5201306358585911203">Komunikat z elementu umieszczonego na bieżącej stronie</translation>
<translation id="5205222826937269299">Nazwa jest wymagana</translation>
<translation id="5222812217790122047">E-mail jest wymagany</translation>
<translation id="522700295135997067">Możliwe, że ta strona właśnie wykradła Twoje hasło</translation>
<translation id="5230733896359313003">Adres wysyłki</translation>
<translation id="5251803541071282808">Chmura</translation>
-<translation id="5277279256032773186">Korzystasz z Chrome w pracy? Firmy mogą zarządzać ustawieniami Chrome swoich pracowników. Więcej informacji</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Wykonaj te czynności, by tymczasowo wyłączyć to oprogramowanie i połączyć się z internetem. Będziesz potrzebować uprawnień administratora.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Sprawdź połączenie</translation>
<translation id="5610807607761827392">Możesz zarządzać kartami i adresami w <ph name="BEGIN_LINK" />Ustawieniach<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Strona <ph name="HOST_NAME" /> spowodowała zbyt wiele przekierowań.</translation>
-<translation id="5622887735448669177">Chcesz opuścić tę stronę?</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="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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Chcesz wpisać dane swojej karty?</translation>
<translation id="5803412860119678065">Chcesz wpisać dane swojej karty (<ph name="CARD_DETAIL" />)?</translation>
<translation id="5810442152076338065">Połączenie z <ph name="DOMAIN" /> jest szyfrowane przy użyciu przestarzałego zestawu szyfrów.</translation>
-<translation id="5810928923025889964">Z elementu umieszczonego na bieżącej stronie</translation>
<translation id="5813119285467412249">&amp;Ponów dodanie</translation>
<translation id="5838278095973806738">Nie podawaj żadnych informacji poufnych (takich jak hasła czy karty kredytowe) w tej witrynie, bo osoby atakujące będą mogły je wykraść.</translation>
<translation id="5866257070973731571">Dodaj numer telefonu</translation>
@@ -704,7 +740,7 @@
<translation id="625755898061068298">Wyłączyłeś ostrzeżenia dotyczące bezpieczeństwa tej witryny.</translation>
<translation id="6259156558325130047">&amp;Ponów zmianę kolejności</translation>
<translation id="6263376278284652872">Zakładki <ph name="DOMAIN" /></translation>
-<translation id="6264485186158353794">Powrót do bezpieczeństwa</translation>
+<translation id="6264485186158353794">Wróć do bezpieczeństwa</translation>
<translation id="6276112860590028508">Tu pojawią się strony z Twojej listy Do przeczytania</translation>
<translation id="6280223929691119688">Nie można dostarczyć pod ten adres. Wybierz inny.</translation>
<translation id="6282194474023008486">Kod pocztowy</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Dodaj więcej informacji</translation>
<translation id="6447842834002726250">Pliki cookie</translation>
<translation id="6451458296329894277">Potwierdź ponowne przesłanie formularza</translation>
-<translation id="6456339708790392414">Twoja płatność</translation>
<translation id="647261751007945333">Zasady dotyczące urządzeń</translation>
<translation id="6477321094435799029">Chrome wykrył nietypowy kod na tej stronie i zablokował ją, by chronić Twoje dane osobowe (np. hasła, numery telefonu czy dane kart kredytowych).</translation>
<translation id="6489534406876378309">Rozpocznij przesyłanie informacji o awariach</translation>
<translation id="6507833130742554667">Karty kredytowe i debetowe są akceptowane.</translation>
<translation id="6508722015517270189">Uruchom ponownie Chrome</translation>
-<translation id="6521373090216409766">Chcesz ponownie załadować tę stronę?</translation>
<translation id="6529602333819889595">&amp;Ponów usunięcie</translation>
<translation id="6534179046333460208">Sugestie dotyczące internetu rzeczy</translation>
<translation id="6550675742724504774">Opcje</translation>
-<translation id="6556239504065605927">Bezpieczne połączenie</translation>
<translation id="6556915248009097796">Data ważności: <ph name="EXPIRATION_DATE_ABBR" />, ostatnio używana: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Twój menedżer jeszcze na to nie zezwolił</translation>
<translation id="6569060085658103619">Przeglądasz stronę rozszerzenia</translation>
<translation id="6596325263575161958">Opcje szyfrowania</translation>
+<translation id="6604181099783169992">Czujniki ruchu lub światła</translation>
<translation id="6624427990725312378">Dane kontaktowe</translation>
<translation id="6626291197371920147">Dodaj prawidłowy numer karty</translation>
<translation id="6628463337424475685">Wyszukiwarka <ph name="ENGINE" /></translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Zakładki zarządzane</translation>
<translation id="7298195798382681320">Zalecane</translation>
<translation id="7309308571273880165">Raport o awarii utworzony w dniu: <ph name="CRASH_TIME" /> (użytkownik zażądał przesłania raportu, ale nie został on jeszcze przesłany)</translation>
+<translation id="7320336641823683070">Pomoc dotycząca połączeń</translation>
<translation id="7334320624316649418">&amp;Ponów zmianę kolejności</translation>
<translation id="733923710415886693">Certyfikat serwera nie został ujawniony przez protokół Certificate Transparency.</translation>
<translation id="7353601530677266744">Wiersz poleceń</translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">Sieć Wi-Fi (<ph name="WIFI_NAME" />), której używasz, może wymagać otwarcia strony logowania.</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="7862185352068345852">Opuścić stronę?</translation>
<translation id="7878176543348854470">Karty debetowe i przedpłacone są akceptowane.</translation>
<translation id="7878562273885520351">Ktoś mógł poznać Twoje hasło</translation>
<translation id="7887683347370398519">Sprawdź kod CVC i spróbuj ponownie</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Użyj globalnej wartości domyślnej (Pytaj)</translation>
<translation id="8042918947222776840">Wybierz metodę odbioru</translation>
<translation id="8057711352706143257">Oprogramowanie „<ph name="SOFTWARE_NAME" />” nie jest prawidłowo skonfigurowane. Odinstalowanie oprogramowania „<ph name="SOFTWARE_NAME" />” zwykle rozwiązuje problem. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Załadować ponownie stronę?</translation>
<translation id="8088680233425245692">Nie udało się wyświetlić artykułu.</translation>
<translation id="8091372947890762290">Aktywacja oczekuje na serwerze</translation>
<translation id="8094917007353911263">Sieć, której używasz, może wymagać otwarcia strony <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">Nieprawidłowy URL aktualizowania dla rozszerzenia o identyfikatorze „<ph name="EXTENSION_ID" />”.</translation>
<translation id="8202097416529803614">Podsumowanie zamówienia</translation>
<translation id="8205463626947051446">Na stronie wyświetlają się uciążliwe reklamy</translation>
+<translation id="8211406090763984747">Połączenie jest bezpieczne</translation>
<translation id="8218327578424803826">Przypisana lokalizacja:</translation>
<translation id="8225771182978767009">Administrator tego komputera zablokował tę witrynę.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Pokaż wszystkie zapisane hasła</translation>
<translation id="8261506727792406068">Usuń</translation>
<translation id="8267698848189296333">Logujesz się jako <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Zaloguj się</translation>
<translation id="8288807391153049143">Pokaż certyfikat</translation>
<translation id="8289355894181816810">Jeśli nie masz pewności, co to oznacza, skontaktuj się z administratorem sieci.</translation>
<translation id="8293206222192510085">Dodaj zakładkę</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Akceptowane karty kredytowe i przedpłacone</translation>
<translation id="8759274551635299824">Ta karta straciła ważność</translation>
<translation id="8761567432415473239">Funkcja Bezpieczne przeglądanie Google ostatnio <ph name="BEGIN_LINK" />znalazła szkodliwe<ph name="END_LINK" /> programy na <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Urządzenie USB</translation>
<translation id="8790007591277257123">&amp;Ponów usunięcie</translation>
<translation id="8800988563907321413">Tutaj wyświetlają się sugestie witryn w pobliżu</translation>
<translation id="8820817407110198400">Zakładki</translation>
diff --git a/chromium/components/strings/components_strings_pt-BR.xtb b/chromium/components/strings/components_strings_pt-BR.xtb
index 205e94fd400..f327a59f39b 100644
--- a/chromium/components/strings/components_strings_pt-BR.xtb
+++ b/chromium/components/strings/components_strings_pt-BR.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Imprimir...</translation>
<translation id="1181037720776840403">Remover</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Informar automaticamente<ph name="END_WHITEPAPER_LINK" /> ao Google detalhes de possíveis incidentes de segurança. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Pagamento não concluído</translation>
<translation id="1201402288615127009">Próxima</translation>
<translation id="1201895884277373915">Mais deste site</translation>
<translation id="1206967143813997005">Assinatura inicial inválida</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Relatório de erros registrado em <ph name="CRASH_TIME" /> (ainda não enviado ou ignorado)</translation>
<translation id="1270502636509132238">Método de Retirada</translation>
<translation id="1285320974508926690">Nunca traduzir este site</translation>
+<translation id="1294154142200295408">Variações de linha de comando</translation>
<translation id="129553762522093515">Recentemente fechadas</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Tente limpar os cookies<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">É possível que sua atividade <ph name="BEGIN_EMPHASIS" />ainda esteja visível<ph name="END_EMPHASIS" /> para:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Cartões de crédito e débito aceitos</translation>
<translation id="1519264250979466059">Data da versão</translation>
<translation id="1527263332363067270">Aguardando conexão...</translation>
+<translation id="1532118530259321453">Essa página diz</translation>
<translation id="153384715582417236">Isso é tudo por enquanto</translation>
<translation id="154408704832528245">Escolher endereço de entrega</translation>
<translation id="1549470594296187301">O JavaScript deve ser ativado para usar este recurso.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Verificar o proxy e o firewall<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">CEP</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugestão}one{# sugestão}other{# sugestões}}</translation>
-<translation id="2065985942032347596">Autenticação obrigatória</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="2091887806945687916">Som</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Cancelar pagamento</translation>
<translation id="2147827593068025794">Sincronização em segundo plano</translation>
<translation id="2148613324460538318">Adicionar Cartão</translation>
-<translation id="2149973817440762519">Editar favoritos</translation>
<translation id="2154054054215849342">O serviço de sincronização não está disponível para seu domínio</translation>
<translation id="2154484045852737596">Editar cartão</translation>
<translation id="2166049586286450108">Acesso completo de administrador</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Escolher endereço de retirada</translation>
<translation id="2740531572673183784">Ok</translation>
<translation id="2742870351467570537">Remover itens selecionados</translation>
-<translation id="2744590937989388266">A partir de uma página incorporada nesta</translation>
<translation id="277133753123645258">Método de envio</translation>
<translation id="277499241957683684">Registro de dispositivo não encontrado</translation>
<translation id="2784949926578158345">A conexão foi redefinida.</translation>
<translation id="2788784517760473862">Cartões de crédito aceitos</translation>
<translation id="2794233252405721443">Site bloqueado</translation>
-<translation id="2795286477369100655">Gostaria de sair deste site?</translation>
<translation id="2799020568854403057">O site a seguir contém apps prejudiciais</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="2824775600643448204">Barra de endereço e de pesquisa</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Entrada de lista "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Bloqueada automaticamente</translation>
<translation id="3024663005179499861">Tipo de política incorreto</translation>
-<translation id="3032412215588512954">Quer atualizar este site?</translation>
<translation id="3037605927509011580">Ah, não!</translation>
<translation id="3039538478787849737">Salvar cartão no Google?</translation>
<translation id="3041612393474885105">Informações do certificado</translation>
@@ -310,6 +306,7 @@
verificar se o servidor proxy está funcionando. Se você acredita que não deve
usar um servidor proxy:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> em <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Cancelar pagamento</translation>
<translation id="3207960819495026254">Adicionada aos favoritos</translation>
<translation id="3209375525920864198">Digite um nome de sessão válido.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Seu administrador pode desbloqueá-lo para você</translation>
<translation id="3566021033012934673">Sua conexão não é particular</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Uma página incorporada em <ph name="SITE" /> diz</translation>
<translation id="358285529439630156">Cartões de crédito e pré-pagos são aceitos.</translation>
<translation id="3582930987043644930">Adicionar nome</translation>
<translation id="3583757800736429874">&amp;Refazer mover</translation>
<translation id="3586931643579894722">Ocultar detalhes</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Corrigir erros de conexão&lt;/h1&gt;
+ &lt;p&gt;Se você receber uma mensagem de erro ao tentar visitar um site, tente estas correções.&lt;/p&gt;
+ &lt;h2&gt;Corrigir a maioria dos erros de conexão&lt;/h2&gt;
+ &lt;p&gt;Se você tentar visitar um site e ele não abrir, tente primeiro corrigir o erro com estas etapas de solução de problemas:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Verifique se o endereço da Web foi digitado corretamente.&lt;/li&gt;
+ &lt;li&gt;Certifique-se de que a conexão com a Internet esteja funcionando normalmente.&lt;/li&gt;
+ &lt;li&gt;Entre em contato com o proprietário do site.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Receber ajuda com uma mensagem de erro específica&lt;/h2&gt;
+ &lt;h3&gt;"Sua conexão não é particular", "NET::ERR_CERT_AUTHORITY_INVALID", "ERR_CERT_COMMON_NAME_INVALID", "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" ou "Erro de certificado SSL"&lt;/h3&gt;
+ &lt;h4&gt;Etapa 1: fazer login no portal&lt;/h4&gt;
+ &lt;p&gt;As redes Wi-Fi em locais como cafés ou aeroportos exigem que você faça login. Para ver a página de login, visite uma página que use &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Acesse qualquer site que comece com &lt;code&gt;http://&lt;/code&gt;, como &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Na página de login que é aberta, faça login para usar a Internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Etapa 2: abrir a página no modo de navegação anônima (somente no computador)&lt;/h4&gt;
+ &lt;p&gt;Abra a página que você estava visitando em uma janela de navegação anônima.&lt;/p&gt;
+ &lt;p&gt;Se a página abrir, isso significa que uma extensão do Chrome não está funcionando corretamente. Para corrigir o erro, desative a extensão.&lt;/p&gt;
+ &lt;h4&gt;Etapa 3: atualizar o sistema operacional&lt;/h4&gt;
+ &lt;p&gt;Certifique-se de que seu dispositivo esteja atualizado.&lt;/p&gt;
+ &lt;h4&gt;Etapa 4: desativar o antivírus temporariamente&lt;/h4&gt;
+ &lt;p&gt;Você verá este erro se tiver um software antivírus que fornece "proteção de HTTPS" ou "verificação de HTTPS". O antivírus está impedindo que o Chrome forneça segurança.&lt;/p&gt;
+ &lt;p&gt;Para corrigir o problema, desative o software antivírus. Se a página funcionar após a desativação do software, desative-o quando usar sites seguros.&lt;/p&gt;
+ &lt;p&gt;Lembre-se de ativar seu programa de antivírus novamente quando terminar.&lt;/p&gt;
+ &lt;h4&gt;Etapa 5: receber ajuda extra&lt;/h4&gt;
+ &lt;p&gt;Se ainda encontrar o erro, entre em contato com o proprietário do site.&lt;/p&gt;
+ &lt;h3&gt;"Conectar-se à rede"&lt;/h3&gt;
+ &lt;p&gt;Você verá esse erro se estiver usando um portal de Wi-Fi em que precisa fazer login para poder ficar on-line.&lt;/p&gt;
+ &lt;p&gt;Para corrigir esse erro, clique em &lt;strong&gt;Conectar&lt;/strong&gt; na página que você está tentando abrir.&lt;/p&gt;
+ &lt;h3&gt;"Seu relógio está atrasado", "Seu relógio está adiantado" ou "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Você verá esse erro se a data e a hora do seu computador ou dispositivo móvel estiverem incorretas.&lt;/p&gt;
+ &lt;p&gt;Para corrigir esse erro, abra o relógio do dispositivo. Certifique-se de que a data e a hora estejam corretas.&lt;/p&gt;
+ &lt;h3&gt;"Um software no computador está impedindo que o Chrome se conecte à Web com segurança" (somente em computadores Windows)&lt;/h3&gt;
+ &lt;p&gt;Você verá esse erro se tiver o software Superfish no computador Windows.&lt;/p&gt;
+ &lt;p&gt;Siga estas etapas para desativar o software temporariamente para que você possa entrar na Web. Você precisará de privilégios de administrador.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Clique em &lt;strong&gt;Iniciar&lt;/strong&gt;, procure e selecione &lt;strong&gt;Ver serviços locais&lt;/strong&gt;
+ &lt;li&gt;Selecione &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Em &lt;strong&gt;Tipo de inicialização&lt;/strong&gt;, selecione &lt;strong&gt;Desabilitada&lt;/strong&gt;
+ &lt;li&gt;Em &lt;strong&gt;Status do serviço&lt;/strong&gt;, clique em &lt;strong&gt;Parar&lt;/strong&gt;
+ &lt;li&gt;Clique em &lt;strong&gt;Aplicar&lt;/strong&gt; e depois em &lt;strong&gt;OK&lt;/strong&gt;
+ &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 computador
+ &lt;/ol&gt;</translation>
<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>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Quer salvar este cartão na sua Conta do Google e neste dispositivo?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Validade: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">A partir de <ph name="SITE" /></translation>
<translation id="382518646247711829">Se você usa um servidor proxy...</translation>
<translation id="3828924085048779000">Uma senha vazia não é permitida.</translation>
<translation id="385051799172605136">Voltar</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">Código do relatório de falha enviado: <ph name="CRASH_ID" /> (código de falha local: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O certificado de segurança dele não especifica a extensão Nomes alternativos do requerente. Isso pode ser causado por uma configuração incorreta ou pela interceptação da sua conexão por um invasor.</translation>
<translation id="3949601375789751990">Seu histórico de navegação aparece aqui</translation>
+<translation id="3950820424414687140">Fazer login</translation>
<translation id="3963721102035795474">Modo leitor</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Nenhum}=1{1 site }one{# site }other{# sites }}</translation>
<translation id="397105322502079400">Calculando...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">O número de série do dispositivo é inválido</translation>
<translation id="410351446219883937">Reprodução automática</translation>
<translation id="4103763322291513355">Visite &lt;strong&gt;chrome://policy&lt;/strong&gt; para ver a lista de URLs adicionados à lista negra e outras políticas aplicadas pelo administrador do seu sistema.</translation>
+<translation id="4110652170750985508">Analisar seu pagamento</translation>
<translation id="4116663294526079822">Sempre permitir neste site</translation>
<translation id="4117700440116928470">O escopo da política não é suportado.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{mais 1}one{mais #}other{mais #}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">Sem nome de usuário</translation>
<translation id="4275830172053184480">Reiniciar seu dispositivo</translation>
<translation id="4280429058323657511">, validade <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Fazer login</translation>
<translation id="4312866146174492540">Bloquear (padrão)</translation>
<translation id="4325863107915753736">Falha ao encontrar artigo</translation>
<translation id="4326324639298822553">Verifique a data de validade e tente novamente</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Os cartões e os endereços vieram do Chrome e da sua Conta do Google (<ph name="ACCOUNT_EMAIL" />). É possível gerenciar essas opções em <ph name="BEGIN_LINK" />Configurações<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Detalhes</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">A partir de uma página incorporada em <ph name="SITE" /></translation>
<translation id="4558551763791394412">Tente desativar suas extensões.</translation>
<translation id="457875822857220463">Entrega</translation>
<translation id="4582800630050655161">Você pode perder o acesso à sua Conta do Google ou ter sua identidade roubada. O Chromium recomenda a alteração da sua senha agora.</translation>
<translation id="4587425331216688090">Remover endereço do Chrome?</translation>
<translation id="4592951414987517459">Sua conexão com <ph name="DOMAIN" /> foi criptografada usando um pacote de criptografia moderno.</translation>
<translation id="4594403342090139922">&amp;Desfazer exclusão</translation>
-<translation id="4611292653554630842">Fazer login</translation>
<translation id="4619615317237390068">Guias de outros dispositivos</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O certificado de segurança contém erros. Isso pode ser causado por uma configuração incorreta ou pela interceptação da sua conexão por um invasor.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">A conexão foi interrompida</translation>
<translation id="471880041731876836">Você não tem permissão para visitar este site</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Executar o Diagnóstico de Rede do Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Seu pagamento</translation>
<translation id="4726672564094551039">Atualizar políticas</translation>
<translation id="4728558894243024398">Plataforma</translation>
<translation id="4736825316280949806">Reiniciar o Chromium</translation>
-<translation id="4737498291095696011">A partir desta página</translation>
<translation id="4744603770635761495">Caminho do executável</translation>
<translation id="4749685221585524849">Usado pela última vez em: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Suas informações (por exemplo, senhas ou números de cartão de crédito) permanecem particulares quando são enviadas para esse site.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Visualizar</translation>
<translation id="4854362297993841467">Esse método de entrega não está disponível. Tente um método diferente.</translation>
<translation id="4858792381671956233">Você perguntou aos seus responsáveis se pode visitar este site</translation>
-<translation id="4871132632506079383">A partir de uma página incorporada em <ph name="SITE" /></translation>
<translation id="4880827082731008257">Histórico de pesquisa</translation>
+<translation id="4881695831933465202">Abrir</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Autenticação necessária</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{e mais 1 página da Web}one{e mais # página da Web}other{e mais # páginas da Web}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Informe o CVC do <ph name="CREDIT_CARD" />. Depois da confirmação, os detalhes do cartão da sua conta do Google Payments serão compartilhados com esse site.</translation>
<translation id="4923417429809017348">Esta página foi traduzida de um idioma desconhecido para o <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Pagamento</translation>
<translation id="4926049483395192435">Deve ser especificado.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> diz</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Ações</translation>
<translation id="4958444002117714549">Expandir lista</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Se ativado, o Chrome armazenará uma cópia do seu cartão neste dispositivo para preencher formulários mais rapidamente.</translation>
<translation id="5018422839182700155">Não é possível abrir essa página</translation>
<translation id="5019198164206649151">Armazenamento de backup em estado inválido</translation>
-<translation id="5020990877659450221">A partir desta página</translation>
<translation id="5023310440958281426">Verifique as políticas do administrador</translation>
<translation id="5029568752722684782">Limpar cópia</translation>
<translation id="503069730517007720">Um certificado raiz para "<ph name="SOFTWARE_NAME" />" é necessário, mas não está instalado. O administrador de TI deve revisar as instruções de configuração do "<ph name="SOFTWARE_NAME" />" para corrigir esse problema. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Máquina</translation>
<translation id="5179510805599951267">Não está em <ph name="ORIGINAL_LANGUAGE" />? Informe este erro</translation>
<translation id="5190835502935405962">Barra de favoritos</translation>
+<translation id="5201306358585911203">Uma página incorporada nesta página diz</translation>
<translation id="5205222826937269299">Nome obrigatório</translation>
<translation id="5222812217790122047">E-mail obrigatório</translation>
<translation id="522700295135997067">Este site pode ter acabado de roubar sua senha</translation>
<translation id="5230733896359313003">Endereço para envio</translation>
<translation id="5251803541071282808">Nuvem</translation>
-<translation id="5277279256032773186">Você usa o Chrome no trabalho? As empresas podem gerenciar as configurações do Chrome para seus funcionários. Saiba mais</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Siga estas etapas para desativar temporariamente o software e entrar na Web. Para isso, você precisará de privilégios de administrador.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Verificar a conexão</translation>
<translation id="5610807607761827392">É possível gerenciar cartões e endereços em <ph name="BEGIN_LINK" />Configurações<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Redirecionamento em excesso por <ph name="HOST_NAME" /></translation>
-<translation id="5622887735448669177">Quer sair deste site?</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="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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Quer preencher as informações do cartão?</translation>
<translation id="5803412860119678065">Quer preencher as informações do seu cartão <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Sua conexão com <ph name="DOMAIN" /> está criptografada com um pacote de criptografia obsoleto.</translation>
-<translation id="5810928923025889964">A partir de uma página incorporada nesta</translation>
<translation id="5813119285467412249">&amp;Refazer adicionar</translation>
<translation id="5838278095973806738">Você não deve fornecer nenhuma informação confidencial nesse site (por exemplo, senhas ou cartões de crédito), porque elas podem ser roubadas por invasores.</translation>
<translation id="5866257070973731571">Adicione um Número de Telefone</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Adicionar mais informações</translation>
<translation id="6447842834002726250">Cookies</translation>
<translation id="6451458296329894277">Confirmar reenvio do formulário</translation>
-<translation id="6456339708790392414">Seu pagamento</translation>
<translation id="647261751007945333">Políticas de dispositivos</translation>
<translation id="6477321094435799029">O Chrome detectou um código incomum nesta página e a bloqueou para proteger suas informações pessoais (por exemplo, senhas, números de telefone e cartões de crédito).</translation>
<translation id="6489534406876378309">Iniciar upload de falhas</translation>
<translation id="6507833130742554667">Cartões de crédito e débito são aceitos.</translation>
<translation id="6508722015517270189">Reiniciar o Chrome</translation>
-<translation id="6521373090216409766">Gostaria de atualizar este site?</translation>
<translation id="6529602333819889595">&amp;Refazer excluir</translation>
<translation id="6534179046333460208">Sugestões da Web física</translation>
<translation id="6550675742724504774">Opções</translation>
-<translation id="6556239504065605927">Conexão segura</translation>
<translation id="6556915248009097796">Validade: <ph name="EXPIRATION_DATE_ABBR" />, usado pela última vez em: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Seu administrador ainda não o aprovou</translation>
<translation id="6569060085658103619">Você está vendo uma página de extensões</translation>
<translation id="6596325263575161958">Opções de criptografia</translation>
+<translation id="6604181099783169992">Sensores de luz ou movimento</translation>
<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>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Favoritos gerenciados</translation>
<translation id="7298195798382681320">Recomendada</translation>
<translation id="7309308571273880165">Relatório de erros capturado em <ph name="CRASH_TIME" /> (upload solicitado pelo usuário, upload ainda não realizado)</translation>
+<translation id="7320336641823683070">Ajuda de conexão</translation>
<translation id="7334320624316649418">&amp;Refazer reordenar</translation>
<translation id="733923710415886693">O certificado do servidor não foi divulgado por meio da Transparência dos certificados.</translation>
<translation id="7353601530677266744">Linha de comando</translation>
@@ -900,6 +935,7 @@
<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="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="7862185352068345852">Sair do site?</translation>
<translation id="7878176543348854470">Cartões de débito e pré-pagos são aceitos.</translation>
<translation id="7878562273885520351">Sua senha pode estar comprometida</translation>
<translation id="7887683347370398519">Verifique seu CVC e tente novamente</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Usar padrão global (Perguntar)</translation>
<translation id="8042918947222776840">Escolher método de retirada</translation>
<translation id="8057711352706143257">O software "<ph name="SOFTWARE_NAME" />" não foi configurado corretamente. A desinstalação do "<ph name="SOFTWARE_NAME" />" costuma resolver o problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Atualizar o site?</translation>
<translation id="8088680233425245692">Falha ao exibir artigo.</translation>
<translation id="8091372947890762290">A ativação está pendente no servidor</translation>
<translation id="8094917007353911263">A rede que você está usando pode exigir uma visita a <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<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>
<translation id="8205463626947051446">O site costuma mostrar anúncios invasivos</translation>
+<translation id="8211406090763984747">A conexão é segura</translation>
<translation id="8218327578424803826">Local designado:</translation>
<translation id="8225771182978767009">A pessoa que configurou este computador optou por bloquear esse site.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Mostrar todas as senhas salvas</translation>
<translation id="8261506727792406068">Excluir</translation>
<translation id="8267698848189296333">Fazendo login como <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Fazer login</translation>
<translation id="8288807391153049143">Mostrar certificado</translation>
<translation id="8289355894181816810">Entre em contato com seu administrador de rede se não souber o que isso significa.</translation>
<translation id="8293206222192510085">Adicionar favorito</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">Cartões de crédito e pré-pagos aceitos</translation>
<translation id="8759274551635299824">Este cartão expirou</translation>
<translation id="8761567432415473239">Recentemente, a Navegação Segura do Google <ph name="BEGIN_LINK" />encontrou programas nocivos<ph name="END_LINK" /> no site <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Dispositivo USB</translation>
<translation id="8790007591277257123">&amp;Refazer excluir</translation>
<translation id="8800988563907321413">As sugestões de itens nas proximidades são exibidas aqui</translation>
<translation id="8820817407110198400">Favoritos</translation>
diff --git a/chromium/components/strings/components_strings_pt-PT.xtb b/chromium/components/strings/components_strings_pt-PT.xtb
index ef291c8f582..65c702dda0a 100644
--- a/chromium/components/strings/components_strings_pt-PT.xtb
+++ b/chromium/components/strings/components_strings_pt-PT.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">Im&amp;primir...</translation>
<translation id="1181037720776840403">Remover</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Comunicar automaticamente<ph name="END_WHITEPAPER_LINK" /> os detalhes de possíveis incidentes de segurança à Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Pagamento não concluído</translation>
<translation id="1201402288615127009">Seguinte</translation>
<translation id="1201895884277373915">Mais a partir deste Web site</translation>
<translation id="1206967143813997005">Assinatura com inicial incorreta</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Relatório de falhas capturado <ph name="CRASH_TIME" /> (ainda não carregado ou ignorado)</translation>
<translation id="1270502636509132238">Método de recolha</translation>
<translation id="1285320974508926690">Nunca traduzir este site</translation>
+<translation id="1294154142200295408">Variações da linha de comandos</translation>
<translation id="129553762522093515">Fechados recentemente</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Experimente limpar os cookies<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">A sua atividade <ph name="BEGIN_EMPHASIS" />poderá continuar visível<ph name="END_EMPHASIS" /> para:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Cartões de crédito e de débito admitidos</translation>
<translation id="1519264250979466059">Data da Compilação</translation>
<translation id="1527263332363067270">A aguardar ligação…</translation>
+<translation id="1532118530259321453">Esta página diz</translation>
<translation id="153384715582417236">É tudo por agora</translation>
<translation id="154408704832528245">Escolher endereço de entrega</translation>
<translation id="1549470594296187301">É necessário ativar o JavaScript para utilizar esta funcionalidade.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Verificar o proxy e a firewall<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Código postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugestão}other{# sugestões}}</translation>
-<translation id="2065985942032347596">Autenticação necessária</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="2091887806945687916">Som</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Cancelar pagamento</translation>
<translation id="2147827593068025794">Sincronização em segundo plano</translation>
<translation id="2148613324460538318">Adicionar cartão</translation>
-<translation id="2149973817440762519">Editar marcador</translation>
<translation id="2154054054215849342">A sincronização não está disponível para o domínio</translation>
<translation id="2154484045852737596">Editar cartão</translation>
<translation id="2166049586286450108">Acesso de gestor total</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Escolher endereço de levantamento</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Remover itens seleccionados</translation>
-<translation id="2744590937989388266">A partir de uma página incorporada nesta página</translation>
<translation id="277133753123645258">Método de envio</translation>
<translation id="277499241957683684">Registo do dispositivo em falta</translation>
<translation id="2784949926578158345">A ligação foi reposta.</translation>
<translation id="2788784517760473862">Cartões de crédito admitidos</translation>
<translation id="2794233252405721443">Site bloqueado</translation>
-<translation id="2795286477369100655">Pretende sair deste site?</translation>
<translation id="2799020568854403057">O site que pretende visitar contém aplicações prejudiciais</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="2824775600643448204">Barra de pesquisa e endereço</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Entrada da lista "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Bloqueada automaticamente</translation>
<translation id="3024663005179499861">Tipo de política incorreto</translation>
-<translation id="3032412215588512954">Pretende atualizar este site?</translation>
<translation id="3037605927509011580">Ah, bolas!!</translation>
<translation id="3039538478787849737">Pretende guardar o cartão na Conta Google?</translation>
<translation id="3041612393474885105">Informações do certificado</translation>
@@ -310,6 +306,7 @@
se certificar de que o servidor proxy está a funcionar. Se achar que não deve
utilizar um servidor proxy:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> no servidor <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Cancelar pagamento</translation>
<translation id="3207960819495026254">Adicionado aos marcadores</translation>
<translation id="3209375525920864198">Introduza um nome de sessão válido.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">O seu gestor pode desbloqueá-lo</translation>
<translation id="3566021033012934673">A sua ligação não é privada</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Uma página incorporada em <ph name="SITE" /> diz</translation>
<translation id="358285529439630156">Os cartões de crédito e pré-pagos são admitidos.</translation>
<translation id="3582930987043644930">Adicionar nome</translation>
<translation id="3583757800736429874">&amp;Refazer movimentação</translation>
<translation id="3586931643579894722">Ocultar detalhes</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Corrigir erros de ligação&lt;/h1&gt;
+ &lt;p&gt;Se receber uma mensagem de erro ao tentar aceder a um Website, experimente estas correções.&lt;/p&gt;
+ &lt;h2&gt;Corrigir a maioria dos erros de ligação&lt;/h2&gt;
+ &lt;p&gt;Se tentar aceder a um Website e este não abrir, experimente primeiro corrigir o erro com estes passos de resolução de problemas:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Verifique se existem gralhas no endereço Web.&lt;/li&gt;
+ &lt;li&gt;Certifique-se de que a ligação à Internet está a funcionar normalmente.&lt;/li&gt;
+ &lt;li&gt;Contacte o proprietário do Website.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Obter ajuda relativamente a uma mensagem de erro específica&lt;/h2&gt;
+ &lt;h3&gt;"A sua ligação não é privada" ou "NET::ERR_CERT_AUTHORITY_INVALID" ou "ERR_CERT_COMMON_NAME_INVALID" ou "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" ou "Erro de certificado SSL"&lt;/h3&gt;
+ &lt;h4&gt;Passo 1: inicie sessão no portal&lt;/h4&gt;
+ &lt;p&gt;As redes Wi-Fi em locais como cafés ou aeroportos necessitam que inicie sessão. Para ver a página de início de sessão, aceda a uma página cujo endereço contenha o código &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Aceda a qualquer Website que comece por &lt;code&gt;http://&lt;/code&gt;, como &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Na página de início de sessão apresentada, inicie sessão para utilizar a Internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Passo 2: abra a página no modo de navegação anónima (apenas no computador)&lt;/h4&gt;
+ &lt;p&gt;Abra a página que estava a visitar numa janela de navegação anónima.&lt;/p&gt;
+ &lt;p&gt;Se conseguir abrir a página, significa que uma extensão do Chrome não está a funcionar corretamente. Para corrigir o erro, desative a extensão.&lt;/p&gt;
+ &lt;h4&gt;Passo 3: atualize o sistema operativo&lt;/h4&gt;
+ &lt;p&gt;Certifique-se de que o seu dispositivo está atualizado.&lt;/p&gt;
+ &lt;h4&gt;Passo 4: desative temporariamente o antivírus&lt;/h4&gt;
+ &lt;p&gt;Este erro é apresentado se tiver um software antivírus que forneça "Proteção HTTPS" ou "Análise de HTTPS". O antivírus impede o Chrome de fornecer segurança.&lt;/p&gt;
+ &lt;p&gt;Para resolver o problema, desative o software antivírus. Se a página funcionar depois de desativar o software, desative-o sempre que utilizar sites seguros.&lt;/p&gt;
+ &lt;p&gt;Lembre-se de ativar novamente o programa antivírus quando terminar.&lt;/p&gt;
+ &lt;h4&gt;Passo 5: obtenha ajuda adicional&lt;/h4&gt;
+ &lt;p&gt;Se o erro persistir, contacte o proprietário do Website.&lt;/p&gt;
+ &lt;h3&gt;"Ligue-se à rede"&lt;/h3&gt;
+ &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;
+ &lt;h3&gt;"O seu relógio está atrasado", "O seu relógio está adiantado" ou "Net::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Este erro é apresentado se a data e a hora do computador ou do dispositivo móvel estiverem erradas.&lt;/p&gt;
+ &lt;p&gt;Para corrigir o erro, aceda ao relógio do dispositivo. Certifique-se de que a data e a hora estão corretas.&lt;/p&gt;
+ &lt;h3&gt;"Existe software no computador que está a impedir que o Chrome se ligue à Web em segurança" (apenas para computadores com Windows)&lt;/h3&gt;
+ &lt;p&gt;Este erro é apresentado se tiver software da Superfish no seu computador Windows.&lt;/p&gt;
+ &lt;p&gt;Siga estes passos para desativar temporariamente o software para que possa aceder à Web. Precisa de privilégios de administrador.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Clique em &lt;strong&gt;Iniciar&lt;/strong&gt; e, de seguida, pesquise e selecione &lt;strong&gt;"Ver serviços locais"&lt;/strong&gt;
+ &lt;li&gt;Selecione &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Em &lt;strong&gt;Tipo de arranque&lt;/strong&gt;, selecione &lt;strong&gt;Desativado&lt;/strong&gt;
+ &lt;li&gt;Em &lt;strong&gt;Estado do serviço&lt;/strong&gt;, clique em &lt;strong&gt;Parar&lt;/strong&gt;
+ &lt;li&gt;Clique em &lt;strong&gt;Aplicar&lt;/strong&gt;e, de seguida, clique 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="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>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Pretende guardar este cartão na sua Conta Google e neste dispositivo?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Expira a <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">A partir de <ph name="SITE" /></translation>
<translation id="382518646247711829">Se utilizar um servidor de proxy...</translation>
<translation id="3828924085048779000">Não é permitida uma frase de acesso vazia.</translation>
<translation id="385051799172605136">Anterior</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">ID do relatório de falhas carregado <ph name="CRASH_ID" /> (ID de falha de sistema local: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O respetivo certificado de segurança não especifica Nomes alternativos do requerente. Isto pode ser o resultado de uma configuração incorreta ou de um utilizador mal-intencionado que intercetou a sua ligação.</translation>
<translation id="3949601375789751990">O histórico de navegação é apresentado aqui</translation>
+<translation id="3950820424414687140">Iniciar sessão</translation>
<translation id="3963721102035795474">Modo de leitor</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Nenhum}=1{De 1 site }other{De # sites }}</translation>
<translation id="397105322502079400">A calcular...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Número de série do dispositivo é inválido</translation>
<translation id="410351446219883937">Reprodução automática</translation>
<translation id="4103763322291513355">Visite &lt;strong&gt;chrome://policy&lt;/strong&gt; para ver os URLs que foram colocados na lista negra e outras políticas aplicadas pelo gestor do sistema.</translation>
+<translation id="4110652170750985508">Rever o seu pagamento</translation>
<translation id="4116663294526079822">Permitir sempre neste Website</translation>
<translation id="4117700440116928470">O âmbito da política não é suportado.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 outro}other{# outros}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Sem nome de utilizador)</translation>
<translation id="4275830172053184480">Reiniciar o dispositivo</translation>
<translation id="4280429058323657511">, exp. <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Iniciar sessão</translation>
<translation id="4312866146174492540">Bloquear (predefinição)</translation>
<translation id="4325863107915753736">Falha ao encontrar o artigo</translation>
<translation id="4326324639298822553">Verifique a data de validade e tente novamente</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Os cartões e os endereços são provenientes do Chrome e da sua Conta Google (<ph name="ACCOUNT_EMAIL" />). Pode geri-los nas <ph name="BEGIN_LINK" />Definições<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Detalhes</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">A partir de uma página incorporada em <ph name="SITE" /></translation>
<translation id="4558551763791394412">Experimente desativar as extensões.</translation>
<translation id="457875822857220463">Entrega</translation>
<translation id="4582800630050655161">Pode perder o acesso à sua Conta Google ou ser vítima de roubo de identidade. O Chromium recomenda a alteração da palavra-passe agora.</translation>
<translation id="4587425331216688090">Pretende remover o endereço do Chrome?</translation>
<translation id="4592951414987517459">A sua ligação a <ph name="DOMAIN" /> está encriptada através de um conjunto de cifras moderno.</translation>
<translation id="4594403342090139922">&amp;Anular eliminação</translation>
-<translation id="4611292653554630842">Iniciar sessão</translation>
<translation id="4619615317237390068">Separadores de outros dispositivos</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Este servidor não conseguiu provar que é o domínio <ph name="DOMAIN" />; o respetivo certificado de segurança contém erros. Isto pode ser o resultado de uma configuração incorreta ou de um invasor a intercetar a sua ligação.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">A ligação foi interrompida</translation>
<translation id="471880041731876836">Não tem autorização para aceder a este site</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Executar o Diagnóstico de rede do Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">O seu pagamento</translation>
<translation id="4726672564094551039">Recarregar políticas</translation>
<translation id="4728558894243024398">Plataforma</translation>
<translation id="4736825316280949806">Reiniciar o Chromium</translation>
-<translation id="4737498291095696011">A partir desta página</translation>
<translation id="4744603770635761495">Caminho do Executável</translation>
<translation id="4749685221585524849">Última utilização a <ph name="LAST_USED_MONTH" /></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>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Ver</translation>
<translation id="4854362297993841467">Este método de fornecimento não está disponível. Experimente um método diferente.</translation>
<translation id="4858792381671956233">Perguntaste aos teus pais se podes aceder a este site.</translation>
-<translation id="4871132632506079383">A partir de uma página incorporada em <ph name="SITE" /></translation>
<translation id="4880827082731008257">Pesquisar histórico</translation>
+<translation id="4881695831933465202">Abrir</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">É necessária autenticação</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{e mais 1 página Web}other{e mais # páginas Web}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Introduza o Código de Segurança/CVC de <ph name="CREDIT_CARD" />. Depois de confirmar, os detalhes do cartão da conta do Google Payments são partilhados com este site.</translation>
<translation id="4923417429809017348">Esta página foi traduzida de um idioma desconhecido para <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Pagamento</translation>
<translation id="4926049483395192435">Tem de ser especificado.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> diz</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Ações</translation>
<translation id="4958444002117714549">Expandir lista</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Quando esta opção está ativada, o Chrome armazena uma cópia do seu cartão neste dispositivo para preencher formulários mais rapidamente.</translation>
<translation id="5018422839182700155">Não é possível abrir esta página</translation>
<translation id="5019198164206649151">Armazenamento de segurança em mau estado</translation>
-<translation id="5020990877659450221">A partir desta página</translation>
<translation id="5023310440958281426">Verificar as políticas do gestor</translation>
<translation id="5029568752722684782">Limpar cópia</translation>
<translation id="503069730517007720">É necessário um certificado de raiz para o "<ph name="SOFTWARE_NAME" />", que não está instalado. O gestor de TI deve consultar as instruções de configuração do "<ph name="SOFTWARE_NAME" />" para corrigir este problema. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Equipamento</translation>
<translation id="5179510805599951267">Não está em <ph name="ORIGINAL_LANGUAGE" />? Comunicar este erro</translation>
<translation id="5190835502935405962">Barra de marcadores</translation>
+<translation id="5201306358585911203">Uma página incorporada nesta página diz</translation>
<translation id="5205222826937269299">Nome obrigatório</translation>
<translation id="5222812217790122047">Email obrigatório</translation>
<translation id="522700295135997067">Este site pode ter roubado a sua palavra-passe</translation>
<translation id="5230733896359313003">Endereço de envio</translation>
<translation id="5251803541071282808">Nuvem</translation>
-<translation id="5277279256032773186">Utiliza o Chrome no trabalho? As empresas podem gerir as definições do Chrome para os seus funcionários. Saiba mais</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Siga estes passos para desativar temporariamente o software para que possa aceder à Web. Precisa de privilégios de gestor.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Verificar a ligação</translation>
<translation id="5610807607761827392">Pode gerir cartões e endereços nas <ph name="BEGIN_LINK" />Definições<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> redirecionou-o demasiadas vezes.</translation>
-<translation id="5622887735448669177">Pretende sair deste site?</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="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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Pretende preencher as informações do cartão?</translation>
<translation id="5803412860119678065">Pretende preencher o seu cartão <ph name="CARD_DETAIL" />?</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="5810928923025889964">A partir de uma página incorporada nesta página</translation>
<translation id="5813119285467412249">&amp;Refazer adição</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>
<translation id="5866257070973731571">Adicionar número de telefone</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Adicionar mais informações</translation>
<translation id="6447842834002726250">Cookies</translation>
<translation id="6451458296329894277">Confirmar nova submissão de formulário</translation>
-<translation id="6456339708790392414">O seu pagamento</translation>
<translation id="647261751007945333">Políticas do dispositivo</translation>
<translation id="6477321094435799029">O Chrome detetou código estranho nesta página e bloqueou-a para proteger as suas informações pessoais (por exemplo, palavras-passe, números de telefone e números de cartões de crédito).</translation>
<translation id="6489534406876378309">Começar a carregar falhas</translation>
<translation id="6507833130742554667">Os cartões de crédito e de débito são admitidos.</translation>
<translation id="6508722015517270189">Reiniciar o Chrome</translation>
-<translation id="6521373090216409766">Pretende atualizar este site?</translation>
<translation id="6529602333819889595">&amp;Refazer eliminação</translation>
<translation id="6534179046333460208">Sugestões da Web física</translation>
<translation id="6550675742724504774">Opções</translation>
-<translation id="6556239504065605927">Ligação segura</translation>
<translation id="6556915248009097796">Exp.: <ph name="EXPIRATION_DATE_ABBR" />, última utilização a <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">O seu gestor ainda não o aprovou</translation>
<translation id="6569060085658103619">Está a ver a página de uma extensão</translation>
<translation id="6596325263575161958">Opções de encriptação</translation>
+<translation id="6604181099783169992">Sensores de movimento ou de luz</translation>
<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>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Marcadores Geridos</translation>
<translation id="7298195798382681320">Recomendado</translation>
<translation id="7309308571273880165">Relatório de falhas capturado no(a) <ph name="CRASH_TIME" /> (carregamento pedido pelo utilizador, ainda não carregado)</translation>
+<translation id="7320336641823683070">Ajuda para estabelecer ligação</translation>
<translation id="7334320624316649418">&amp;Refazer reordenação</translation>
<translation id="733923710415886693">O certificado do servidor não foi divulgado através da Transparência de certificados.</translation>
<translation id="7353601530677266744">Linha de comandos</translation>
@@ -900,6 +935,7 @@
<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="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="7862185352068345852">Pretende sair do site?</translation>
<translation id="7878176543348854470">Os cartões de débito e pré-pagos são admitidos.</translation>
<translation id="7878562273885520351">A palavra-passe pode estar comprometida</translation>
<translation id="7887683347370398519">Verifique o Código de Segurança/CVC e tente novamente</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Utilizar predefinição global (Perguntar)</translation>
<translation id="8042918947222776840">Escolher método de levantamento</translation>
<translation id="8057711352706143257">O "<ph name="SOFTWARE_NAME" />" não está configurado corretamente. Normalmente, a desinstalação do "<ph name="SOFTWARE_NAME" />" resolve o problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Pretende atualizar o site?</translation>
<translation id="8088680233425245692">Falha ao ver o artigo.</translation>
<translation id="8091372947890762290">Ativação pendente no servidor</translation>
<translation id="8094917007353911263">A rede que está a utilizar pode exigir que visite <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<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>
<translation id="8205463626947051446">O site tem tendência para mostrar anúncios intrusivos</translation>
+<translation id="8211406090763984747">A ligação é segura</translation>
<translation id="8218327578424803826">Localização atribuída:</translation>
<translation id="8225771182978767009">A pessoa que configurou este computador optou por bloquear este site.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Mostrar todas as palavras-passe guardadas</translation>
<translation id="8261506727792406068">Eliminar</translation>
<translation id="8267698848189296333">A iniciar sessão como <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Iniciar Sessão</translation>
<translation id="8288807391153049143">Mostrar certificado</translation>
<translation id="8289355894181816810">Se não tiver a certeza do que isto significa, contacte o gestor de rede.</translation>
<translation id="8293206222192510085">Adicionar marcador</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">Cartões de crédito e pré-pagos aceites</translation>
<translation id="8759274551635299824">Este cartão expirou</translation>
<translation id="8761567432415473239">A Navegação Segura do Google <ph name="BEGIN_LINK" />encontrou programas prejudiciais<ph name="END_LINK" /> recentemente em <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Dispositivo USB</translation>
<translation id="8790007591277257123">&amp;Refazer eliminação</translation>
<translation id="8800988563907321413">As sugestões próximas aparecem aqui</translation>
<translation id="8820817407110198400">Marcadores</translation>
diff --git a/chromium/components/strings/components_strings_ro.xtb b/chromium/components/strings/components_strings_ro.xtb
index 9de7e205072..f15c0c6cf8b 100644
--- a/chromium/components/strings/components_strings_ro.xtb
+++ b/chromium/components/strings/components_strings_ro.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Printează...</translation>
<translation id="1181037720776840403">Elimină</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Raportează automat<ph name="END_WHITEPAPER_LINK" /> la Google detaliile eventualelor incidente privind securitatea. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Plata nu a fost finalizată</translation>
<translation id="1201402288615127009">Înainte</translation>
<translation id="1201895884277373915">Mai multe de la acest site</translation>
<translation id="1206967143813997005">Semnătură inițială nevalidă</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Raport de blocare creat <ph name="CRASH_TIME" /> (nu a fost încă încărcat sau ignorat)</translation>
<translation id="1270502636509132238">Metodă de preluare</translation>
<translation id="1285320974508926690">Nu traduce niciodată acest site</translation>
+<translation id="1294154142200295408">Variații ale liniilor de comandă</translation>
<translation id="129553762522093515">Închise recent</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Șterge cookie-urile<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Este posibil ca activitatea ta <ph name="BEGIN_EMPHASIS" />să fie în continuare vizibilă<ph name="END_EMPHASIS" /> pentru:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Carduri de credit și de debit acceptate</translation>
<translation id="1519264250979466059">Dată versiune:</translation>
<translation id="1527263332363067270">Se așteaptă conectarea…</translation>
+<translation id="1532118530259321453">Această pagină afișează mesajul</translation>
<translation id="153384715582417236">Asta este tot</translation>
<translation id="154408704832528245">Alege adresa de livrare</translation>
<translation id="1549470594296187301">Trebuie să activezi JavaScript pentru a folosi această funcție.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />să verifici proxy-ul și firewallul;<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Cod zip</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugestie}few{# sugestii}other{# de sugestii}}</translation>
-<translation id="2065985942032347596">Autentificare obligatorie</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="2091887806945687916">Sunet</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Anulează plata</translation>
<translation id="2147827593068025794">Sincronizare în fundal</translation>
<translation id="2148613324460538318">Adaugă un card</translation>
-<translation id="2149973817440762519">Editați marcajul</translation>
<translation id="2154054054215849342">Sincronizarea nu este disponibilă pentru domeniul tău</translation>
<translation id="2154484045852737596">Editează cardul</translation>
<translation id="2166049586286450108">Acces complet de administrare</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Alege adresa de preluare</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Elimină elementele selectate</translation>
-<translation id="2744590937989388266">Dintr-o pagină încorporată în această pagină</translation>
<translation id="277133753123645258">Metodă de expediere</translation>
<translation id="277499241957683684">Lipsește o înregistrare pentru gadget</translation>
<translation id="2784949926578158345">Conexiunea a fost resetată.</translation>
<translation id="2788784517760473862">Carduri de credit acceptate</translation>
<translation id="2794233252405721443">Site blocat</translation>
-<translation id="2795286477369100655">Dorești să părăsești acest site?</translation>
<translation id="2799020568854403057">Site-ul pe care urmează să îl accesezi conține aplicații dăunătoare</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="2824775600643448204">Bara de adrese și de căutare</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Intrarea din listă „<ph name="ENTRY_INDEX" />”: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Blocată automat</translation>
<translation id="3024663005179499861">Tip de politică greșit</translation>
-<translation id="3032412215588512954">Dorești să reîncarci acest site?</translation>
<translation id="3037605927509011580">Of, nu mai merge!</translation>
<translation id="3039538478787849737">Salvezi cardul pe Google?</translation>
<translation id="3041612393474885105">Informații despre certificat</translation>
@@ -310,6 +306,7 @@
pentru a te asigura că serverul proxy funcționează. Dacă nu consideri că ar trebui
să folosești un server proxy:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> pe <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Anulează plata</translation>
<translation id="3207960819495026254">Marcată</translation>
<translation id="3209375525920864198">Introdu un nume de sesiune valid.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Administratorul îl poate debloca pentru tine</translation>
<translation id="3566021033012934673">Conexiunea nu este privată</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">O pagină încorporată de pe <ph name="SITE" /> afișează mesajul</translation>
<translation id="358285529439630156">Se acceptă carduri de credit și preplătite.</translation>
<translation id="3582930987043644930">Adăugați un nume</translation>
<translation id="3583757800736429874">&amp;Repetați mutarea</translation>
<translation id="3586931643579894722">Ascunde detaliile</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Remediază erorile de conectare&lt;/h1&gt;
+ &lt;p&gt;Dacă primești un mesaj de eroare când încerci să accesezi un site, încearcă aceste soluții.&lt;/p&gt;
+ &lt;h2&gt;Remediază majoritatea erorilor de conectare&lt;/h2&gt;
+ &lt;p&gt;Dacă încerci să accesezi un site, iar acesta nu se deschide, mai întâi încearcă să remediezi eroarea urmând acești pași:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;verifică dacă adresa web este scrisă corect;&lt;/li&gt;
+ &lt;li&gt;asigură-te de funcționarea normală a conexiunii la internet;&lt;/li&gt;
+ &lt;li&gt;contactează proprietarul site-ului.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Obține ajutor în privința unui anumit mesaj de eroare&lt;/h2&gt;
+ &lt;h3&gt;„Conexiunea nu este privată” sau „NET::ERR_CERT_AUTHORITY_INVALID” sau „ERR_CERT_COMMON_NAME_INVALID” sau „NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM” sau „Eroare privind certificatul SSL”&lt;/h3&gt;
+ &lt;h4&gt;Pasul 1: conectează-te la portal&lt;/h4&gt;
+ &lt;p&gt;Pentru rețelele Wi-Fi din locuri precum cafenele sau aeroporturi este necesar să te conectezi. Pentru a vedea pagina de conectare, accesează o pagină care folosește&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Accesează orice site care începe cu &lt;code&gt;http://&lt;/code&gt;, cum ar fi &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Pe pagina de conectare care se deschide, conectează-te pentru a avea acces la internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Pasul 2: deschide pagina în modul incognito (numai pe computer)&lt;/h4&gt;
+ &lt;p&gt;Deschide pagina accesată într-o fereastră incognito.&lt;/p&gt;
+ &lt;p&gt;Dacă pagina se deschide, o extensie Chrome nu funcționează corect. Pentru a remedia eroarea, dezactivează extensia.&lt;/p&gt;
+ &lt;h4&gt;Pasul 3: actualizează-ți sistemul de operare&lt;/h4&gt;
+ &lt;p&gt;Asigură-te că dispozitivul este actualizat.&lt;/p&gt;
+ &lt;h4&gt;Pasul 4: dezactivează temporar software-ul antivirus&lt;/h4&gt;
+ &lt;p&gt;Această eroare se va afișa dacă ai un software antivirus care oferă „protecție HTTPS” sau „scanare HTTPS” care împiedică browserul Chrome să ofere securitate.&lt;/p&gt;
+ &lt;p&gt;Pentru a remedia problema, dezactivează software-ul antivirus. Dacă pagina funcționează după ce dezactivezi software-ul, dezactivează software-ul respectiv când folosești site-uri securizate.&lt;/p&gt;
+ &lt;p&gt;Nu uita să reactivezi programul antivirus după ce ai terminat.&lt;/p&gt;
+ &lt;h4&gt;Pasul 5: primește ajutor suplimentar&lt;/h4&gt;
+ &lt;p&gt;Dacă eroarea apare în continuare, contactează proprietarul site-ului.&lt;/p&gt;
+ &lt;h3&gt;„Conectează-te la rețea”&lt;/h3&gt;
+ &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;
+ &lt;h3&gt;„Ora este setată în trecut” sau „Ora este setată în viitor” sau „NET::ERR_CERT_DATE_INVALID”&lt;/h3&gt;
+ &lt;p&gt;Această eroare se va afișa dacă data și ora de pe computer sau de pe dispozitivul mobil sunt inexacte.&lt;/p&gt;
+ &lt;p&gt;Pentru a remedia eroarea, deschide ceasul dispozitivului. Asigură-te că data și ora sunt corecte.&lt;/p&gt;
+ &lt;h3&gt;„Pe computer există software care împiedică browserul Chrome să se conecteze în siguranță la internet” (doar pentru computerele Windows)&lt;/h3&gt;
+ &lt;p&gt;Această eroare se va afișa dacă ai un software Superfish pe computerul Windows.&lt;/p&gt;
+ &lt;p&gt;Urmează acești pași ca să dezactivezi temporar software-ul, astfel încât să poți accesa internetul. Ai nevoie de privilegii de administrator.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Dă clic pe &lt;strong&gt;Start&lt;/strong&gt;, apoi caută și selectează &lt;strong&gt;„View local services”&lt;/strong&gt; (Vezi serviciile locale)
+ &lt;li&gt;Selectează &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Sub &lt;strong&gt;Startup type&lt;/strong&gt; (Tip de pornire), selectează &lt;strong&gt;Disabled&lt;/strong&gt; (Dezactivat)
+ &lt;li&gt;Sub &lt;strong&gt;Service status&lt;/strong&gt; (Starea serviciului), dă clic pe &lt;strong&gt;Stop&lt;/strong&gt; (Oprește)
+ &lt;li&gt;Dă clic pe &lt;strong&gt;Apply&lt;/strong&gt; (Aplică), apoi pe &lt;strong&gt;OK&lt;/strong&gt;
+ &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="3615877443314183785">Introdu o dată de expirare validă</translation>
<translation id="36224234498066874">Șterge datele de navigare...</translation>
<translation id="362276910939193118">Afișează întregul istoric</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Dorești să salvezi acest card în Contul Google și pe acest dispozitiv?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Expiră în <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">De pe <ph name="SITE" /></translation>
<translation id="382518646247711829">Dacă utilizați un server proxy...</translation>
<translation id="3828924085048779000">Trebuie să fie introdusă expresia de acces.</translation>
<translation id="385051799172605136">Înapoi</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">S-a încărcat Raportul de blocare cu ID-ul <ph name="CRASH_ID" /> (ID blocare locală: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Acest server nu a putut dovedi că este <ph name="DOMAIN" />; în certificatul său de securitate nu este specificat câmpul Nume alternative subiect. Cauza poate fi o eroare de configurare sau interceptarea conexiunii de către un atacator.</translation>
<translation id="3949601375789751990">Istoricul de navigare apare aici</translation>
+<translation id="3950820424414687140">Conectează-te</translation>
<translation id="3963721102035795474">Modul Cititor</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Niciunul}=1{De la 1 site }few{De la # site-uri }other{De la # de site-uri }}</translation>
<translation id="397105322502079400">Se calculează...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Numărul de serie al gadgetului este nevalid</translation>
<translation id="410351446219883937">Redare automată</translation>
<translation id="4103763322291513355">Accesați &lt;strong&gt;chrome://policy&lt;/strong&gt; pentru a vedea adresele URL introduse pe lista neagră și alte politici impuse de către administratorul de sistem.</translation>
+<translation id="4110652170750985508">Examinează plata</translation>
<translation id="4116663294526079822">Permiteți întotdeauna pe acest site</translation>
<translation id="4117700440116928470">Domeniul politicii nu este acceptat.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{încă 1}few{încă #}other{încă #}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Niciun nume de utilizator)</translation>
<translation id="4275830172053184480">Reporniți gadgetul</translation>
<translation id="4280429058323657511">data expirării: <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Conectează-te</translation>
<translation id="4312866146174492540">Blochează (în mod prestabilit)</translation>
<translation id="4325863107915753736">Articolul nu a fost găsit</translation>
<translation id="4326324639298822553">Verifică data de expirare și încearcă din nou</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Cardurile și adresele sunt din Chrome și din Contul Google (<ph name="ACCOUNT_EMAIL" />). Poți să le gestionezi în <ph name="BEGIN_LINK" />Setări<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Detalii</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Dintr-o pagină încorporată pe <ph name="SITE" /></translation>
<translation id="4558551763791394412">Dezactivează extensiile.</translation>
<translation id="457875822857220463">Livrare</translation>
<translation id="4582800630050655161">Este posibil să pierzi accesul la Contul Google sau să fii victima unui furt de identitate. Chromium îți recomandă să îți schimbi acum parola.</translation>
<translation id="4587425331216688090">Elimini adresa din Chrome?</translation>
<translation id="4592951414987517459">Conexiunea la <ph name="DOMAIN" /> este criptată folosind o suită de codificare modernă.</translation>
<translation id="4594403342090139922">&amp;Anulați ștergerea</translation>
-<translation id="4611292653554630842">Conectează-te</translation>
<translation id="4619615317237390068">File de pe alte dispozitive</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Acest server nu a putut dovedi că este <ph name="DOMAIN" />; certificatul său de securitate conține erori. Cauza poate fi o configurare greșită sau interceptarea conexiunii de către un atacator.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Conexiunea a fost întreruptă</translation>
<translation id="471880041731876836">Nu ai permisiunea să accesezi acest site</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />să rulezi Diagnostice rețea Windows<ph name="END_LINK" />;</translation>
-<translation id="472349245089439925">Plata</translation>
<translation id="4726672564094551039">Reîncărcați politicile</translation>
<translation id="4728558894243024398">Platformă</translation>
<translation id="4736825316280949806">repornește Chromium;</translation>
-<translation id="4737498291095696011">Din această pagină</translation>
<translation id="4744603770635761495">Cale executabilă</translation>
<translation id="4749685221585524849">Folosit ultima dată pe <ph name="LAST_USED_MONTH" /></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>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Afișează</translation>
<translation id="4854362297993841467">Această metodă de livrare nu este disponibilă. Încearcă altă metodă.</translation>
<translation id="4858792381671956233">Ți-ai întrebat părinții dacă poți accesa acest site</translation>
-<translation id="4871132632506079383">Dintr-o pagină încorporată pe <ph name="SITE" /></translation>
<translation id="4880827082731008257">Caută în istoric</translation>
+<translation id="4881695831933465202">Deschide</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Autentificare obligatorie</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{și încă 1 pagină web}few{și încă # pagini web}other{și încă # de pagini web}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Introdu codul CVC pentru <ph name="CREDIT_CARD" />. După ce confirmi, acest site va avea acces la detaliile cardului tău din contul Google Payments.</translation>
<translation id="4923417429809017348">Această pagină a fost tradusă dintr-o limbă necunoscută în <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Plată</translation>
<translation id="4926049483395192435">Valoarea trebuie specificată.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> afișează mesajul</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Acțiuni</translation>
<translation id="4958444002117714549">Extindeți lista</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Dacă este activată, Chrome va stoca o copie a cardului pe acest dispozitiv, pentru completarea mai rapidă a formularelor.</translation>
<translation id="5018422839182700155">Pagina nu poate fi deschisă</translation>
<translation id="5019198164206649151">Depozit de fundal în stare nevalidă</translation>
-<translation id="5020990877659450221">Din această pagină</translation>
<translation id="5023310440958281426">Consultați politicile administratorului</translation>
<translation id="5029568752722684782">Șterge copia</translation>
<translation id="503069730517007720">Un certificat rădăcină pentru „<ph name="SOFTWARE_NAME" />” este necesar, dar nu este instalat. Administratorul IT trebuie să verifice instrucțiunile de configurare pentru „<ph name="SOFTWARE_NAME" />” ca să remedieze problema. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Computer</translation>
<translation id="5179510805599951267">Nu este în <ph name="ORIGINAL_LANGUAGE" />? Semnalează această eroare.</translation>
<translation id="5190835502935405962">Bară de marcaje</translation>
+<translation id="5201306358585911203">O pagină încorporată de pe această pagină afișează mesajul</translation>
<translation id="5205222826937269299">Numele este obligatoriu</translation>
<translation id="5222812217790122047">Adresa de e-mail este obligatorie</translation>
<translation id="522700295135997067">Este posibil ca acest site să îți fi furat chiar acum parola</translation>
<translation id="5230733896359313003">Adresă de expediere</translation>
<translation id="5251803541071282808">Cloud</translation>
-<translation id="5277279256032773186">Folosești Chrome la serviciu? Companiile pot gestiona setările Chrome pentru angajații lor. Află mai multe</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Urmează acești pași ca să dezactivezi temporar software-ul, astfel încât să poți accesa internetul. Vei avea nevoie de privilegii de administrator.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">să verifici conexiunea;</translation>
<translation id="5610807607761827392">Poți să gestionezi cardurile și adresele în <ph name="BEGIN_LINK" />Setări<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> te-a redirecționat de prea multe ori.</translation>
-<translation id="5622887735448669177">Dorești să părăsești acest site?</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="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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Dorești să completezi datele cardului de credit?</translation>
<translation id="5803412860119678065">Dorești să completezi datele <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Conexiunea la <ph name="DOMAIN" /> este criptată folosind o suită de codificare învechită.</translation>
-<translation id="5810928923025889964">Dintr-o pagină încorporată în această pagină</translation>
<translation id="5813119285467412249">&amp;Repetați adăugarea</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>
<translation id="5866257070973731571">Adaugă un număr de telefon</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Adaugă mai multe informații</translation>
<translation id="6447842834002726250">Cookie-uri</translation>
<translation id="6451458296329894277">Confirmă retrimiterea formularului</translation>
-<translation id="6456339708790392414">Plata</translation>
<translation id="647261751007945333">Politici privind dispozitivele</translation>
<translation id="6477321094435799029">Chrome a detectat un cod neobișnuit pe această pagină și l-a blocat pentru a-ți proteja informațiile cu caracter personal (de exemplu, parole, numere de telefon sau carduri de credit).</translation>
<translation id="6489534406876378309">Începeți încărcarea rapoartelor de blocare</translation>
<translation id="6507833130742554667">Se acceptă carduri de credit și de debit.</translation>
<translation id="6508722015517270189">repornește Chrome;</translation>
-<translation id="6521373090216409766">Dorești să reîncarci acest site?</translation>
<translation id="6529602333819889595">&amp;Repetați ștergerea</translation>
<translation id="6534179046333460208">Sugestii pentru Webul material</translation>
<translation id="6550675742724504774">Opțiuni</translation>
-<translation id="6556239504065605927">Conexiune securizată</translation>
<translation id="6556915248009097796">Expirat în <ph name="EXPIRATION_DATE_ABBR" />, folosit ultima dată pe <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Administratorul nu l-a aprobat încă</translation>
<translation id="6569060085658103619">Se afișează pagina unei extensii</translation>
<translation id="6596325263575161958">Opțiuni de criptare</translation>
+<translation id="6604181099783169992">Senzori de mișcare sau de lumină</translation>
<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>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Marcaje gestionate</translation>
<translation id="7298195798382681320">Recomandate</translation>
<translation id="7309308571273880165">Raportul de blocare creat <ph name="CRASH_TIME" /> (utilizatorul a solicitat încărcarea, dar nu a fost încărcat încă)</translation>
+<translation id="7320336641823683070">Ajutor pentru conectare</translation>
<translation id="7334320624316649418">&amp;Repetați reordonarea</translation>
<translation id="733923710415886693">Certificatul serverului nu a fost dezvăluit folosind Transparența certificatului.</translation>
<translation id="7353601530677266744">Linie de comandă</translation>
@@ -900,6 +935,7 @@
<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="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="7862185352068345852">Ieși de pe site?</translation>
<translation id="7878176543348854470">Se acceptă carduri de debit și preplătite.</translation>
<translation id="7878562273885520351">Este posibil ca parola să fie compromisă</translation>
<translation id="7887683347370398519">Verifică codul CVC și încearcă din nou</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Utilizați setarea prestabilită la nivel global (Întrebați)</translation>
<translation id="8042918947222776840">Alege metoda de preluare</translation>
<translation id="8057711352706143257">„<ph name="SOFTWARE_NAME" />” nu este configurat corect. De obicei, problema se remediază dezinstalând „<ph name="SOFTWARE_NAME" />” <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Reîncarci site-ul?</translation>
<translation id="8088680233425245692">Articolul nu a fost vizualizat.</translation>
<translation id="8091372947890762290">Se așteaptă activarea pe server</translation>
<translation id="8094917007353911263">Rețeaua pe care o folosești poate solicita accesarea adresei <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<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>
<translation id="8205463626947051446">Site-ul tinde să afișeze anunțuri deranjante</translation>
+<translation id="8211406090763984747">Conexiunea este securizată</translation>
<translation id="8218327578424803826">Locație atribuită:</translation>
<translation id="8225771182978767009">Persoana care a configurat computerul a ales să blocheze acest site.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Afișează toate parolele salvate</translation>
<translation id="8261506727792406068">Șterge</translation>
<translation id="8267698848189296333">Te conectezi ca <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Conectați-vă</translation>
<translation id="8288807391153049143">Afișează certificatul</translation>
<translation id="8289355894181816810">Dacă nu știți sigur ce înseamnă aceasta, contactați administratorul de rețea.</translation>
<translation id="8293206222192510085">Adăugați marcaj</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">Carduri de credit și preplătite acceptate</translation>
<translation id="8759274551635299824">Acest card este expirat</translation>
<translation id="8761567432415473239">Recent, Navigarea sigură Google a <ph name="BEGIN_LINK" />descoperit programe dăunătoare<ph name="END_LINK" /> pe <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Dispozitiv USB</translation>
<translation id="8790007591277257123">&amp;Repetați ștergerea</translation>
<translation id="8800988563907321413">Sugestiile pentru În apropiere sunt afișate aici</translation>
<translation id="8820817407110198400">Marcaje</translation>
diff --git a/chromium/components/strings/components_strings_ru.xtb b/chromium/components/strings/components_strings_ru.xtb
index ca87f1f786b..e978ec9636f 100644
--- a/chromium/components/strings/components_strings_ru.xtb
+++ b/chromium/components/strings/components_strings_ru.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Печать...</translation>
<translation id="1181037720776840403">Удалить</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Автоматически отправлять в Google<ph name="END_WHITEPAPER_LINK" /> информацию о возможных проблемах безопасности. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Не удалось обработать платеж</translation>
<translation id="1201402288615127009">Далее</translation>
<translation id="1201895884277373915">Другие записи по этому сайту</translation>
<translation id="1206967143813997005">Начальная подпись недействительна</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575"><ph name="CRASH_TIME" />: получен отчет о сбое (ещё не загружен или не отклонен)</translation>
<translation id="1270502636509132238">Способ получения</translation>
<translation id="1285320974508926690">Никогда не переводить этот сайт</translation>
+<translation id="1294154142200295408">Модификации для командной строки</translation>
<translation id="129553762522093515">Недавно закрытые</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Удалите файлы cookie<ph name="END_LINK" />.</translation>
<translation id="1333989956347591814">Ваши действия <ph name="BEGIN_EMPHASIS" />будут видны<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Дебетовые и кредитные карты, которые принимаются к оплате</translation>
<translation id="1519264250979466059">Дата сборки</translation>
<translation id="1527263332363067270">Ожидание подключения…</translation>
+<translation id="1532118530259321453">Подтвердите действие</translation>
<translation id="153384715582417236">Пока это всё</translation>
<translation id="154408704832528245">Выбрать адрес доставки</translation>
<translation id="1549470594296187301">Для использования этой функции необходимо включить JavaScript.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Проверьте настройки прокси-сервера и брандмауэра<ph name="END_LINK" />.</translation>
<translation id="2053553514270667976">Почтовый индекс</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 вариант}one{# вариант}few{# варианта}many{# вариантов}other{# варианта}}</translation>
-<translation id="2065985942032347596">Необходима авторизация</translation>
<translation id="2079545284768500474">Отмена</translation>
<translation id="20817612488360358">Включены системные настройки прокси-сервера, но при этом его конфигурация задана явным образом.</translation>
<translation id="2091887806945687916">Звук</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Отменить оплату</translation>
<translation id="2147827593068025794">Фоновая синхронизация</translation>
<translation id="2148613324460538318">Добавить карту</translation>
-<translation id="2149973817440762519">Закладка</translation>
<translation id="2154054054215849342">В вашем домене синхронизация недоступна</translation>
<translation id="2154484045852737596">Изменение данных карты</translation>
<translation id="2166049586286450108">Доступ администратора ко всем данным</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Выбрать адрес получения</translation>
<translation id="2740531572673183784">ОК</translation>
<translation id="2742870351467570537">Удалить выбранные элементы</translation>
-<translation id="2744590937989388266">Подтвердите действие</translation>
<translation id="277133753123645258">Способ доставки</translation>
<translation id="277499241957683684">Устройство не зарегистрировано</translation>
<translation id="2784949926578158345">Соединение сброшено.</translation>
<translation id="2788784517760473862">Кредитные карты, которые принимаются к оплате</translation>
<translation id="2794233252405721443">Сайт заблокирован</translation>
-<translation id="2795286477369100655">Покинуть эту страницу?</translation>
<translation id="2799020568854403057">Сайт содержит вредоносные приложения</translation>
<translation id="2803306138276472711">Система Google по проверке безопасности сайтов недавно обнаружила на <ph name="SITE" /> <ph name="BEGIN_LINK" />вредоносное ПО<ph name="END_LINK" />. Будьте внимательны, иногда даже на безопасных сайтах появляются вирусы.</translation>
<translation id="2824775600643448204">Адресная строка и строка поиска</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Элемент списка "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Заблокировано автоматически</translation>
<translation id="3024663005179499861">Неверный тип политики</translation>
-<translation id="3032412215588512954">Обновить эту страницу?</translation>
<translation id="3037605927509011580">Опаньки...</translation>
<translation id="3039538478787849737">Сохранить карту в Google?</translation>
<translation id="3041612393474885105">Данные сертификата</translation>
@@ -309,6 +305,7 @@
<translation id="3176929007561373547">Проверьте настройки прокси-сервера или попросите администратора
задать верные параметры. В противном случае^
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> на <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Отменить оплату</translation>
<translation id="3207960819495026254">Добавлено в закладки</translation>
<translation id="3209375525920864198">Недопустимое название сеанса.</translation>
@@ -366,11 +363,57 @@
<translation id="3556433843310711081">Для разблокировки обратитесь к администратору.</translation>
<translation id="3566021033012934673">Подключение не защищено</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Подтвердите действие на странице <ph name="SITE" /></translation>
<translation id="358285529439630156">Принимаются кредитные карты и карты предоплаты.</translation>
<translation id="3582930987043644930">Добавьте имя</translation>
<translation id="3583757800736429874">&amp;Повторить перемещение</translation>
<translation id="3586931643579894722">Скрыть подробности</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Как устранить ошибки при подключении к Интернету&lt;/h1&gt;
+ &lt;p&gt;Если при попытке открыть сайт появляется сообщение об ошибке, следуйте инструкциям ниже.&lt;/p&gt;
+ &lt;h2&gt;Как устранить большинство ошибок&lt;/h2&gt;
+ &lt;p&gt;Если вам не удается открыть страницу, выполните следующие действия:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Убедитесь, что вы правильно ввели веб-адрес.&lt;/li&gt;
+ &lt;li&gt;Проверьте подключение к Интернету.&lt;/li&gt;
+ &lt;li&gt;Обратитесь к владельцу сайта.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Как устранить определенные виды ошибок&lt;/h2&gt;
+ &lt;h3&gt;"Подключение не защищено", NET::ERR_CERT_AUTHORITY_INVALID, ERR_CERT_COMMON_NAME_INVALID, NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM или "Ошибка сертификата SSL"&lt;/h3&gt;
+ &lt;h4&gt;Шаг 1. Войдите на портал&lt;/h4&gt;
+ &lt;p&gt;Чтобы воспользоваться общедоступной сетью Wi-Fi (например, в кафе или аэропорту), сначала подключитесь к ней. Для этого откройте любую веб-страницу с префиксом &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Перейдите на сайт, адрес которого начинается с &lt;code&gt;http://&lt;/code&gt;, например &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Подключитесь к Интернету, следуя инструкциям на открывшейся странице.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Шаг 2. Откройте сайт в режиме инкогнито (только на компьютере)&lt;/h4&gt;
+ &lt;p&gt;Откройте нужную страницу в новом окне в режиме инкогнито.&lt;/p&gt;
+ &lt;p&gt;Если в этом случае все работает, проблема связана с одним из расширений Chrome. Отключите его.&lt;/p&gt;
+ &lt;h4&gt;Шаг 3. Обновите операционную систему&lt;/h4&gt;
+ &lt;p&gt;Убедитесь, что на устройстве установлена последняя версия операционной системы.&lt;/p&gt;
+ &lt;h4&gt;Шаг 4. Временно отключите антивирусную программу&lt;/h4&gt;
+ &lt;p&gt;Если вы используете антивирусную программу с функцией защиты или сканирования HTTPS, возможно, она мешает системе защиты браузера Chrome.&lt;/p&gt;
+ &lt;p&gt;Отключите антивирусную программу. Если после этого страница загрузится, отключайте ее, когда работаете с безопасными сайтами.&lt;/p&gt;
+ &lt;p&gt;Не забудьте включить ее снова, когда закончите работу.&lt;/p&gt;
+ &lt;h4&gt;Шаг 5. Обратитесь за помощью&lt;/h4&gt;
+ &lt;p&gt;Если проблему решить не удалось, обратитесь к владельцу сайта.&lt;/p&gt;
+ &lt;h3&gt;"Подключитесь к сети"&lt;/h3&gt;
+ &lt;p&gt;Эта ошибка возникает, если вы используете подключение Wi-Fi, для которого требуется вход на портал.&lt;/p&gt;
+ &lt;p&gt;Нажмите &lt;strong&gt;Подключиться&lt;/strong&gt; на странице.&lt;/p&gt;
+ &lt;h3&gt;"Часы отстают", "Часы спешат" или NET::ERR_CERT_DATE_INVALID&lt;/h3&gt;
+ &lt;p&gt;Эта проблема возникает, если на вашем компьютере или мобильном устройстве неправильно установлены дата и время.&lt;/p&gt;
+ &lt;p&gt;Откройте на устройстве часы и установите правильное время.&lt;/p&gt;
+ &lt;h3&gt;"ПО, установленное на компьютере, не позволяет Chrome безопасно подключиться к Интернету" (только для Windows)&lt;/h3&gt;
+ &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;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;.
+ &lt;li&gt;Нажмите &lt;strong&gt;Применить&lt;/strong&gt;, затем &lt;strong&gt;OK&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="3615877443314183785">Укажите правильный срок действия.</translation>
<translation id="36224234498066874">Очистить историю...</translation>
<translation id="362276910939193118">Показать всю историю</translation>
@@ -403,7 +446,6 @@
<translation id="3778403066972421603">Хотите сохранить карту в аккаунте Google и на этом устройстве?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Срок действия: до <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Подтвердите действие на <ph name="SITE" /></translation>
<translation id="382518646247711829">Если вы используете прокси-сервер...</translation>
<translation id="3828924085048779000">Пустые кодовые фразы запрещены.</translation>
<translation id="385051799172605136">Назад</translation>
@@ -417,6 +459,7 @@
<translation id="3945915738023014686">Идентификатор загруженного отчета о сбоях: <ph name="CRASH_ID" />. Локальный идентификатор сбоя: <ph name="CRASH_LOCAL_ID" />.</translation>
<translation id="3949571496842715403">Сервер не может подтвердить связь с доменом <ph name="DOMAIN" />. В его сертификате безопасности не указаны альтернативные варианты имен. Возможно, сервер настроен неправильно или кто-то пытается перехватить ваши данные.</translation>
<translation id="3949601375789751990">История просмотров появится здесь</translation>
+<translation id="3950820424414687140">Вход</translation>
<translation id="3963721102035795474">Режим чтения</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Нет}=1{С 1 сайта }one{С # сайта }few{С # сайтов }many{С # сайтов }other{С # сайта }}</translation>
<translation id="397105322502079400">Вычисление…</translation>
@@ -433,6 +476,7 @@
<translation id="4103249731201008433">Серийный номер устройства недействителен</translation>
<translation id="410351446219883937">Автовоспроизведение</translation>
<translation id="4103763322291513355">Чтобы просмотреть URL, внесенные в черный список, и другие правила, заданные системным администратором, перейдите по адресу: &lt;strong&gt;chrome://policy&lt;/strong&gt;.</translation>
+<translation id="4110652170750985508">Просмотр платежа</translation>
<translation id="4116663294526079822">Всегда разрешать на этом сайте</translation>
<translation id="4117700440116928470">Область действия правил не поддерживается.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{ещё 1 вариант}one{ещё # вариант}few{ещё # варианта}many{ещё # вариантов}other{ещё # варианта}}</translation>
@@ -459,7 +503,6 @@
<translation id="4269787794583293679">(Не указано)</translation>
<translation id="4275830172053184480">Перезапуск устройства</translation>
<translation id="4280429058323657511">, действует до <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Вход</translation>
<translation id="4312866146174492540">Блокировать (по умолчанию)</translation>
<translation id="4325863107915753736">Не удалось найти статью</translation>
<translation id="4326324639298822553">Проверьте срок действия и повторите попытку</translation>
@@ -481,14 +524,12 @@
<translation id="4515275063822566619">Карты и адреса, указанные в Chrome и в вашем аккаунте Google (<ph name="ACCOUNT_EMAIL" />). Вы можете изменить их на странице <ph name="BEGIN_LINK" />Настройки<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Подробнее</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Подтвердите действие на <ph name="SITE" /></translation>
<translation id="4558551763791394412">Отключите расширения.</translation>
<translation id="457875822857220463">Доставка</translation>
<translation id="4582800630050655161">Кто-то посторонний мог получить доступ к вашим личным данным или аккаунту Google. Рекомендуем немедленно сменить пароль.</translation>
<translation id="4587425331216688090">Удалить адрес из Chrome?</translation>
<translation id="4592951414987517459">Соединение с <ph name="DOMAIN" /> зашифровано с помощью современных наборов шифров.</translation>
<translation id="4594403342090139922">&amp;Отменить удаление</translation>
-<translation id="4611292653554630842">Войти</translation>
<translation id="4619615317237390068">Вкладки с других устройств</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Не удалось подтвердить, что это сервер <ph name="DOMAIN" />. Его сертификат безопасности содержит ошибки. Возможно, сервер настроен неправильно или кто-то пытается перехватить ваши данные.</translation>
@@ -498,11 +539,9 @@
<translation id="4708268264240856090">Соединение прервано</translation>
<translation id="471880041731876836">Доступ запрещен</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Выполните диагностику сети в Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Ваш платеж</translation>
<translation id="4726672564094551039">Повторно загрузить политики</translation>
<translation id="4728558894243024398">Платформа</translation>
<translation id="4736825316280949806">Перезапустите Chromium.</translation>
-<translation id="4737498291095696011">Подтвердите действие</translation>
<translation id="4744603770635761495">Путь к исполняемому файлу</translation>
<translation id="4749685221585524849">Последний раз использовалась <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Информация, которую вы сообщаете этому сайту (например, пароли и номера банковских карт), защищена.</translation>
@@ -521,16 +560,16 @@
<translation id="4850886885716139402">Посмотреть</translation>
<translation id="4854362297993841467">Этот способ доставки недоступен. Выберите другой.</translation>
<translation id="4858792381671956233">Запрос на просмотр сайта отправлен вашим родителям</translation>
-<translation id="4871132632506079383">Подтвердите действие на <ph name="SITE" /></translation>
<translation id="4880827082731008257">Искать в истории</translation>
+<translation id="4881695831933465202">Открыть</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" /> и <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Требуется аутентификация</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{и ещё 1 веб-страница}one{и ещё # веб-страница}few{и ещё # веб-страницы}many{и ещё # веб-страниц}other{и ещё # веб-страницы}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Введите CVC-код карты <ph name="CREDIT_CARD" />. После этого ее реквизиты из платежного аккаунта Google будут переданы сайту.</translation>
<translation id="4923417429809017348">Эта страница была автоматически переведена с неизвестного языка на <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Платеж</translation>
<translation id="4926049483395192435">Укажите значение.</translation>
+<translation id="4926159001844873046">Подтвердите действие на странице <ph name="SITE" /></translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Действия</translation>
<translation id="4958444002117714549">Развернуть список</translation>
@@ -539,7 +578,6 @@
<translation id="5002932099480077015">Chrome будет хранить на этом устройстве данные карты для быстрого заполнения форм.</translation>
<translation id="5018422839182700155">Не удалось открыть страницу</translation>
<translation id="5019198164206649151">Данные в хранилище повреждены</translation>
-<translation id="5020990877659450221">Подтвердите действие</translation>
<translation id="5023310440958281426">Проверьте правила, установленные администратором</translation>
<translation id="5029568752722684782">Удалить данные</translation>
<translation id="503069730517007720">Необходимый корневой сертификат для программы "<ph name="SOFTWARE_NAME" />" не установлен. Чтобы устранить проблему, попросите системного администратора ознакомиться с инструкциями по настройке программы "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
@@ -565,12 +603,12 @@
<translation id="5172758083709347301">Локальный компьютер</translation>
<translation id="5179510805599951267">Это не <ph name="ORIGINAL_LANGUAGE" />? Сообщите об ошибке</translation>
<translation id="5190835502935405962">Панель закладок</translation>
+<translation id="5201306358585911203">Подтвердите действие</translation>
<translation id="5205222826937269299">Введите имя или название</translation>
<translation id="5222812217790122047">Введите адрес электронной почты</translation>
<translation id="522700295135997067">Через этот сайт могли похитить ваш пароль</translation>
<translation id="5230733896359313003">Адрес доставки</translation>
<translation id="5251803541071282808">Облако</translation>
-<translation id="5277279256032773186">Используете Chrome на работе? Узнайте, как компании могут управлять настройками Chrome на корпоративных устройствах.</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Чтобы временно отключить ПО и установить соединение с Интернетом, следуйте инструкциям ниже. Вам потребуются права администратора.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -632,7 +670,6 @@
<translation id="5610142619324316209">Проверьте подключение к Интернету.</translation>
<translation id="5610807607761827392">Сведения о картах и адресах можно изменить в <ph name="BEGIN_LINK" />настройках<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Сайт <ph name="HOST_NAME" /> выполнил переадресацию слишком много раз.</translation>
-<translation id="5622887735448669177">Покинуть эту страницу?</translation>
<translation id="5629630648637658800">Не удалось применить настройки политики</translation>
<translation id="5631439013527180824">Токен устройства недействителен</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>
@@ -655,7 +692,6 @@
<translation id="5786044859038896871">Заполнить данные банковской карты?</translation>
<translation id="5803412860119678065">Заполнить данные банковской карты <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Соединение с <ph name="DOMAIN" /> зашифровано с помощью устаревшего набора шифров.</translation>
-<translation id="5810928923025889964">Подтвердите действие</translation>
<translation id="5813119285467412249">&amp;Повторить добавление</translation>
<translation id="5838278095973806738">Не сообщайте этому сайту конфиденциальную информацию (например, пароли и номера банковских карт). К ней могут получить доступ злоумышленники.</translation>
<translation id="5866257070973731571">Добавьте номер телефона</translation>
@@ -729,21 +765,19 @@
<translation id="6446608382365791566">Укажите дополнительную информацию</translation>
<translation id="6447842834002726250">Файлы сookie</translation>
<translation id="6451458296329894277">Подтвердите повторную отправку формы</translation>
-<translation id="6456339708790392414">Оплата</translation>
<translation id="647261751007945333">Правила устройства</translation>
<translation id="6477321094435799029">Браузер Chrome обнаружил на этой странице необычный код и заблокировал его, чтобы защитить ваши данные (например, пароли, а также номера телефонов и банковских карт).</translation>
<translation id="6489534406876378309">Начать загрузку сведений об ошибках</translation>
<translation id="6507833130742554667">Принимаются кредитные и дебетовые карты.</translation>
<translation id="6508722015517270189">Перезапустите Google Chrome.</translation>
-<translation id="6521373090216409766">Обновить эту страницу?</translation>
<translation id="6529602333819889595">&amp;Повторить удаление</translation>
<translation id="6534179046333460208">Интернет вокруг нас: рекомендации</translation>
<translation id="6550675742724504774">Параметры</translation>
-<translation id="6556239504065605927">Защищенное соединение</translation>
<translation id="6556915248009097796">Срок действия: <ph name="EXPIRATION_DATE_ABBR" />, последний раз использовалась <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Ещё не одобрено администратором</translation>
<translation id="6569060085658103619">Вы просматриваете страницу расширения</translation>
<translation id="6596325263575161958">Параметры шифрования</translation>
+<translation id="6604181099783169992">Датчики движения и освещенности</translation>
<translation id="6624427990725312378">Контактная информация</translation>
<translation id="6626291197371920147">Введите номер действующей карты</translation>
<translation id="6628463337424475685">Поиск <ph name="ENGINE" /></translation>
@@ -815,6 +849,7 @@
<translation id="7275334191706090484">Управляемые закладки</translation>
<translation id="7298195798382681320">Рекомендованные</translation>
<translation id="7309308571273880165"><ph name="CRASH_TIME" />: отчет о сбое сохранен, но ещё не загружен (пользователь запросил загрузку)</translation>
+<translation id="7320336641823683070">Устранение ошибок при подключении к Интернету</translation>
<translation id="7334320624316649418">&amp;Повторить изменение порядка</translation>
<translation id="733923710415886693">Сертификат сервера не проходил проверку.</translation>
<translation id="7353601530677266744">Командная строка</translation>
@@ -899,6 +934,7 @@
<translation id="782886543891417279">Возможно, вам нужно перейти на страницу входа сети Wi-Fi (<ph name="WIFI_NAME" />).</translation>
<translation id="785549533363645510">Тем не менее ваши действия будут видны системному администратору и интернет-провайдеру, а также доступны веб-сайтам, которые вы посещаете.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
+<translation id="7862185352068345852">Закрыть сайт?</translation>
<translation id="7878176543348854470">Принимаются дебетовые карты и карты предоплаты.</translation>
<translation id="7878562273885520351">Злоумышленники могли узнать ваш пароль</translation>
<translation id="7887683347370398519">Проверьте CVC-код и повторите попытку</translation>
@@ -921,6 +957,7 @@
<translation id="8041940743680923270">Использовать глобальный параметр по умолчанию (спрашивать)</translation>
<translation id="8042918947222776840">Выбрать способ получения</translation>
<translation id="8057711352706143257">Программа "<ph name="SOFTWARE_NAME" />" настроена неправильно. Чтобы устранить проблему, удалите программу "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Перезагрузить сайт?</translation>
<translation id="8088680233425245692">Не удалось показать статью</translation>
<translation id="8091372947890762290">Активация управления устройствами не завершена</translation>
<translation id="8094917007353911263">Возможно, вам нужно перейти на страницу <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> используемой сети.</translation>
@@ -936,6 +973,7 @@
<translation id="8201077131113104583">Недействительный URL для обновления расширения с идентификатором <ph name="EXTENSION_ID" />.</translation>
<translation id="8202097416529803614">Информация о заказе</translation>
<translation id="8205463626947051446">На сайте может быть много навязчивой рекламы</translation>
+<translation id="8211406090763984747">Безопасное подключение</translation>
<translation id="8218327578424803826">Назначенное местоположение:</translation>
<translation id="8225771182978767009">Тот, кто настраивал компьютер, заблокировал этот сайт.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" /> и <ph name="TYPE_2" /></translation>
@@ -947,6 +985,7 @@
<translation id="825929999321470778">Показать все сохраненные пароли</translation>
<translation id="8261506727792406068">Удалить</translation>
<translation id="8267698848189296333">Вход в аккаунт <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Вход</translation>
<translation id="8288807391153049143">Показать сертификат</translation>
<translation id="8289355894181816810">Уточните информацию у администратора сети.</translation>
<translation id="8293206222192510085">Добавление закладки</translation>
@@ -997,6 +1036,7 @@
<translation id="874846938927089722">Кредитные карты и карты предоплаты, которые принимаются к оплате</translation>
<translation id="8759274551635299824">Срок действия карты истек.</translation>
<translation id="8761567432415473239">Система Google по проверке безопасности сайтов недавно обнаружила на <ph name="SITE" /> <ph name="BEGIN_LINK" />вредоносное ПО<ph name="END_LINK" />.</translation>
+<translation id="8763927697961133303">USB-устройство</translation>
<translation id="8790007591277257123">&amp;Повторить удаление</translation>
<translation id="8800988563907321413">Здесь появятся рекомендации.</translation>
<translation id="8820817407110198400">Закладки</translation>
@@ -1041,7 +1081,7 @@
<translation id="9103872766612412690">На сайте <ph name="SITE" /> для защиты ваших данных обычно используется шифрование. Однако учетные данные, которые мы получили от сайта <ph name="SITE" /> сейчас, отличаются от тех, которые он отправляет обычно. Вероятно, вредоносный сайт пытается выдать себя за <ph name="SITE" />, либо страница подключения к сети Wi-Fi прервала соединение. Ваша информация по-прежнему в безопасности, так как браузер Chromium разорвал соединение до того, как произошел обмен данными.</translation>
<translation id="9106062320799175032">Добавьте платежный адрес</translation>
<translation id="910908805481542201">Получить помощь</translation>
-<translation id="9128870381267983090">Подключиться к сети</translation>
+<translation id="9128870381267983090">Подключитесь к сети</translation>
<translation id="9137013805542155359">Показать оригинал</translation>
<translation id="9137248913990643158">Войдите в Chrome, прежде чем использовать это приложение.</translation>
<translation id="9148088599418889305">Выбрать способ доставки посылок</translation>
diff --git a/chromium/components/strings/components_strings_sk.xtb b/chromium/components/strings/components_strings_sk.xtb
index 72c688e671b..2a57750c7e3 100644
--- a/chromium/components/strings/components_strings_sk.xtb
+++ b/chromium/components/strings/components_strings_sk.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Tlačiť...</translation>
<translation id="1181037720776840403">Odstrániť</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Automaticky nahlasovať<ph name="END_WHITEPAPER_LINK" /> Googlu podrobnosti o možných problémoch so zabezpečením. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Platba nebola dokončená</translation>
<translation id="1201402288615127009">Ďalej</translation>
<translation id="1201895884277373915">Viac z týchto stránok</translation>
<translation id="1206967143813997005">Chybný úvodný podpis</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Správa o zlyhaní bola zaznamenaná v čase <ph name="CRASH_TIME" /> (ešte nebola nahraná ani ignorovaná)</translation>
<translation id="1270502636509132238">Spôsob vyzdvihnutia</translation>
<translation id="1285320974508926690">Nikdy neprekladať tieto webové stránky</translation>
+<translation id="1294154142200295408">Variácie v príkazovom riadku</translation>
<translation id="129553762522093515">Naposledy zatvorené</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Skúste vymazať súbory cookie<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Vašu aktivitu <ph name="BEGIN_EMPHASIS" />stále môžu vidieť<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Akceptované kreditné a debetné karty</translation>
<translation id="1519264250979466059">Dátum zostavenia</translation>
<translation id="1527263332363067270">Čaká sa na pripojenie...</translation>
+<translation id="1532118530259321453">Táto stránka hovorí</translation>
<translation id="153384715582417236">To je zatiaľ všetko</translation>
<translation id="154408704832528245">Zvoliť adresu doručenia</translation>
<translation id="1549470594296187301">Ak chcete použiť túto funkciu, musíte povoliť JavaScript.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Skontrolovať proxy server a bránu firewall<ph name="END_LINK" /></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="2065985942032347596">Vyžaduje sa autentifikácia</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="2091887806945687916">Zvuk</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Zrušiť platbu</translation>
<translation id="2147827593068025794">Synchronizácia na pozadí</translation>
<translation id="2148613324460538318">Pridať kartu</translation>
-<translation id="2149973817440762519">Upraviť záložku</translation>
<translation id="2154054054215849342">Synchronizácia nie je pre vašu doménu k dispozícii</translation>
<translation id="2154484045852737596">Úprava karty</translation>
<translation id="2166049586286450108">Úplný prístup správcu</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Zvoliť adresu vyzdvihnutia</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Odstrániť vybraté položky</translation>
-<translation id="2744590937989388266">Z vloženej stránky na tejto stránke</translation>
<translation id="277133753123645258">Spôsob dodania</translation>
<translation id="277499241957683684">Chýbajúci záznam zariadenia</translation>
<translation id="2784949926578158345">Spojenie bolo resetované.</translation>
<translation id="2788784517760473862">Akceptované kreditné karty</translation>
<translation id="2794233252405721443">Web je blokovaný</translation>
-<translation id="2795286477369100655">Chcete tento web opustiť?</translation>
<translation id="2799020568854403057">Web, ktorý chcete otvoriť, obsahuje škodlivé aplikácie</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="2824775600643448204">Panel s adresou a vyhľadávací panel</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Položka zoznamu „<ph name="ENTRY_INDEX" />“: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Automaticky blokované</translation>
<translation id="3024663005179499861">Chybný typ pravidla</translation>
-<translation id="3032412215588512954">Chcete tento web načítať znova?</translation>
<translation id="3037605927509011580">Aj, chyba!</translation>
<translation id="3039538478787849737">Uložiť kartu do Googlu?</translation>
<translation id="3041612393474885105">Informácie o certifikáte</translation>
@@ -307,6 +303,7 @@
<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>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> na serveri <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Zrušiť platbu</translation>
<translation id="3207960819495026254">Pridané medzi záložky</translation>
<translation id="3209375525920864198">Zadajte platný názov relácie.</translation>
@@ -364,11 +361,57 @@
<translation id="3556433843310711081">Váš správca ho môže pre vás odblokovať</translation>
<translation id="3566021033012934673">Vaše pripojenie nie je súkromné</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Vložená stránka na webe <ph name="SITE" /> hovorí</translation>
<translation id="358285529439630156">Kreditné a predplatené karty sú akceptované.</translation>
<translation id="3582930987043644930">Pridajte meno</translation>
<translation id="3583757800736429874">&amp;Znova presunúť</translation>
<translation id="3586931643579894722">Skryť podrobnosti</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Oprava chýb s pripojením&lt;/h1&gt;
+ &lt;p&gt;Ak chcete navštíviť určitý web a zobrazí sa chybové hlásenie, vyskúšajte tieto riešenia.&lt;/p&gt;
+ &lt;h2&gt;Oprava najčastejších chýb s pripojením&lt;/h2&gt;
+ &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;
+ &lt;ol&gt;
+ &lt;li&gt;Skontrolujte, či bola webová adresa zadaná správne.&lt;/li&gt;
+ &lt;li&gt;Skontrolujte, či internetové pripojenie funguje normálne.&lt;/li&gt;
+ &lt;li&gt;Kontaktujte vlastníka príslušného webu.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Pomoc s konkrétnym chybovým hlásením&lt;/h2&gt;
+ &lt;h3&gt;„Vaše pripojenie nie je súkromné“, „NET::ERR_CERT_AUTHORITY_INVALID“, „ERR_CERT_COMMON_NAME_INVALID“ alebo „NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM“ alebo „Chyba certifikátu SSL“&lt;/h3&gt;
+ &lt;h4&gt;1. krok: Prihláste sa do portálu&lt;/h4&gt;
+ &lt;p&gt;Siete Wi-Fi na miestach, ako sú kaviarne a letiská, vyžadujú prihlásenie. Ak chcete zobraziť prihlasovaciu stránku, prejdite na stránku, ktorá používa protokol &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Prejdite na ľubovoľný web začínajúci sa predponou &lt;code&gt;http://&lt;/code&gt; (napr. &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;).&lt;/li&gt;
+ &lt;li&gt;Na prihlasovacej stránke portálu, ktorá sa otvorí, sa prihláste, aby ste mohli používať internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;2. krok: Otvorte webovú stránku v režime inkognito (iba v počítači)&lt;/h4&gt;
+ &lt;p&gt;Otvorte stránku, na ktorú chcete prejsť, v okne inkognito.&lt;/p&gt;
+ &lt;p&gt;Ak sa otvorí, chybu spôsobuje rozšírenie pre Chrome. Ak chcete túto chybu odstrániť, vypnite dané rozšírenie.&lt;/p&gt;
+ &lt;h4&gt;3. krok: Aktualizujte operačný systém&lt;/h4&gt;
+ &lt;p&gt;Uistite sa, že je zariadenie aktualizované.&lt;/p&gt;
+ &lt;h4&gt;4. krok: Dočasne vypnite antivírusový program&lt;/h4&gt;
+ &lt;p&gt;Táto chyba sa zobrazí, keď máte antivírusový softvér poskytujúci ochranu protokolu HTTPS alebo skenovanie protokolu HTTPS. Tento antivírusový softvér bráni Chromu poskytovať zabezpečenie.&lt;/p&gt;
+ &lt;p&gt;Problém vyriešite vypnutím antivírusového softvéru. Ak stránka po vypnutí softvéru funguje, pri používaní zabezpečených webov tento softvér vypínajte.&lt;/p&gt;
+ &lt;p&gt;Po dokončení nezabudnite antivírusový program znova zapnúť.&lt;/p&gt;
+ &lt;h4&gt;5. krok: Získajte ďalšiu pomoc&lt;/h4&gt;
+ &lt;p&gt;Ak sa chyba zobrazuje aj naďalej, kontaktujte vlastníka príslušného webu.&lt;/p&gt;
+ &lt;h3&gt;„Pripojte sa k sieti“&lt;/h3&gt;
+ &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;
+ &lt;h3&gt;„Vaše hodiny idú pozadu“, „Vaše hodiny idú dopredu“ alebo „NET::ERR_CERT_DATE_INVALID“&lt;/h3&gt;
+ &lt;p&gt;Táto chyba sa zobrazí, keď máte v počítači alebo mobilnom zariadení nesprávny dátum a čas.&lt;/p&gt;
+ &lt;p&gt;Ak chcete túto chybu odstrániť, otvorte v zariadení aplikáciu hodín. Uistite sa, že uvádza správny dátum a čas.&lt;/p&gt;
+ &lt;h3&gt;„Softvér vo vašom počítači bráni Chromu bezpečne sa pripojiť k webu“ (iba počítače so systémom Windows)&lt;/h3&gt;
+ &lt;p&gt;Táto chyba sa zobrazí, keď máte v počítači so systémom Windows softvér Superfish.&lt;/p&gt;
+ &lt;p&gt;Postupujte podľa týchto krokov a softvér dočasne zakážte, aby ste mohli prejsť na daný web. Budete potrebovať oprávnenia správcu.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Kliknite na položku &lt;strong&gt;Štart&lt;/strong&gt;, potom vyhľadajte a vyberte položku &lt;strong&gt;Zobraziť lokálne služby&lt;/strong&gt;.
+ &lt;li&gt;Vyberte položku &lt;strong&gt;VisualDiscovery&lt;/strong&gt;.
+ &lt;li&gt;V časti &lt;strong&gt;Typ spúšťania&lt;/strong&gt; vyberte možnosť &lt;strong&gt;Vypnuté&lt;/strong&gt;.
+ &lt;li&gt;V časti &lt;strong&gt;Stav služby&lt;/strong&gt; kliknite na položku &lt;strong&gt;Zastaviť&lt;/strong&gt;.
+ &lt;li&gt;Kliknite na položku &lt;strong&gt;Použiť&lt;/strong&gt; a následne na položku &lt;strong&gt;OK&lt;/strong&gt;.
+ &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="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>
@@ -400,7 +443,6 @@
<translation id="3778403066972421603">Chcete uložiť túto kartu do svojho účtu Google a tohto zariadenia?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Platnosť vyprší <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Z webu <ph name="SITE" /></translation>
<translation id="382518646247711829">Ak používate server proxy...</translation>
<translation id="3828924085048779000">Prístupová fráza nemôže byť prázdna.</translation>
<translation id="385051799172605136">Naspäť</translation>
@@ -414,6 +456,7 @@
<translation id="3945915738023014686">Identifikátor nahranej správy o zlyhaní: <ph name="CRASH_ID" /> (ID miestneho zlyhania: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Tento server nedokázal potvrdiť, či ide o doménu <ph name="DOMAIN" /> – príslušný bezpečnostný certifikát neuvádza alternatívne názvy predmetu. Môže to byť spôsobené nesprávnou konfiguráciou alebo tým, že vaše pripojenie napadol útočník.</translation>
<translation id="3949601375789751990">Tu sa zobrazí vaša história prehliadania</translation>
+<translation id="3950820424414687140">Prihlásiť sa</translation>
<translation id="3963721102035795474">Režim čítačky</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Žiadne}=1{Z 1 webu }few{Z # webov }many{Z # webu }other{Z # webov }}</translation>
<translation id="397105322502079400">Prebieha výpočet...</translation>
@@ -430,6 +473,7 @@
<translation id="4103249731201008433">Sériové číslo zariadenia je neplatné</translation>
<translation id="410351446219883937">Automatické prehrávanie</translation>
<translation id="4103763322291513355">Na stránke &lt;strong&gt;chrome://policy&lt;/strong&gt; nájdete zoznam zakázaných webových adries a ďalšie pravidlá vynútené vaším správcom systému.</translation>
+<translation id="4110652170750985508">Kontrola platby</translation>
<translation id="4116663294526079822">Vždy povoliť na tomto webe</translation>
<translation id="4117700440116928470">Rozsah pravidla nie je podporovaný.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 ďalšia}few{# ďalšie}many{# ďalšej}other{# ďalších}}</translation>
@@ -456,7 +500,6 @@
<translation id="4269787794583293679">(Žiadne používateľské meno)</translation>
<translation id="4275830172053184480">Reštart zariadenia</translation>
<translation id="4280429058323657511">, dátum vypršania platnosti: <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Prihlásiť</translation>
<translation id="4312866146174492540">Blokovať (predvolené)</translation>
<translation id="4325863107915753736">Článok sa nepodarilo nájsť</translation>
<translation id="4326324639298822553">Skontrolujte dátum vypršania platnosti a skúste to znova</translation>
@@ -478,14 +521,12 @@
<translation id="4515275063822566619">Karty a adresy pochádzajú z Chromu a účtu Google (<ph name="ACCOUNT_EMAIL" />). Môžete ich spravovať v <ph name="BEGIN_LINK" />Nastaveniach<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Podrobnosti</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Z vloženej stránke na webe <ph name="SITE" /></translation>
<translation id="4558551763791394412">Skúste deaktivovať rozšírenia.</translation>
<translation id="457875822857220463">Doručenie</translation>
<translation id="4582800630050655161">Môžete stratiť prístup do účtu Google alebo vám môže ukradnúť identitu. Chromium odporúča, aby ste si ihneď zmenili heslo.</translation>
<translation id="4587425331216688090">Chcete adresu odstrániť z prehliadača Chrome?</translation>
<translation id="4592951414987517459">Vaše pripojenie k doméne <ph name="DOMAIN" /> je šifrované pomocou modernej šifrovacej súpravy.</translation>
<translation id="4594403342090139922">&amp;Vrátiť späť odstránenie</translation>
-<translation id="4611292653554630842">Prihlásiť sa</translation>
<translation id="4619615317237390068">Karty z iných zariadení</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Server nedokáže overiť, či ide o doménu <ph name="DOMAIN" />, jej bezpečnostný certifikát obsahuje chyby. Môže to byť spôsobené nesprávnou konfiguráciou alebo tým, že vaše pripojenie zachytil útočník.</translation>
@@ -495,11 +536,9 @@
<translation id="4708268264240856090">Pripojenie bolo prerušené</translation>
<translation id="471880041731876836">Nemáte povolenie na návštevu tohto webu</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Spustiť nástroj Diagnostika siete systému Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Vaša platba</translation>
<translation id="4726672564094551039">Znova načítať pravidlá</translation>
<translation id="4728558894243024398">Platforma</translation>
<translation id="4736825316280949806">Reštartujte Chromium</translation>
-<translation id="4737498291095696011">Z tejto stránky</translation>
<translation id="4744603770635761495">Spustiteľná cesta</translation>
<translation id="4749685221585524849">Naposledy použité <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Vaše informácie (napríklad heslá a čísla kreditných kariet) zostanú po odoslaní na tento web súkromné.</translation>
@@ -518,16 +557,16 @@
<translation id="4850886885716139402">Zobraziť</translation>
<translation id="4854362297993841467">Tento spôsob doručenia nie je k dispozícii. Skúste inú adresu.</translation>
<translation id="4858792381671956233">Požiadali ste rodičov o povolenie návštevy tohto webu.</translation>
-<translation id="4871132632506079383">Z vloženej stránke na webe <ph name="SITE" /></translation>
<translation id="4880827082731008257">Hľadať v histórii</translation>
+<translation id="4881695831933465202">Otvoriť</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Vyžaduje sa overenie totožnosti</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{a 1 ďalšia webová stránka}few{a # ďalšie webové stránky}many{a # ďalšej webovej stránky}other{a # ďalších webových stránok}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Zadajte kód CVC karty <ph name="CREDIT_CARD" />. Po potvrdení sa budú podrobnosti z účtu Google Payments zdieľať s týmto webom.</translation>
<translation id="4923417429809017348">Táto stránka bola preložená z neznámeho jazyka do jazyka <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Platba</translation>
<translation id="4926049483395192435">Musí byť určená.</translation>
+<translation id="4926159001844873046">Web <ph name="SITE" /> hovorí</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Akcie</translation>
<translation id="4958444002117714549">Rozbaliť zoznam</translation>
@@ -536,7 +575,6 @@
<translation id="5002932099480077015">Ak túto možnosť povolíte, Chrome bude uchovávať kópiu vašej karty na tomto zariadení na účely rýchlejšieho dopĺňania formulárov.</translation>
<translation id="5018422839182700155">Táto stránka sa nedá otvoriť</translation>
<translation id="5019198164206649151">Zlý stav záložného ukladacieho priestoru</translation>
-<translation id="5020990877659450221">Z tejto stránky</translation>
<translation id="5023310440958281426">Skontrolujte pravidlá správcu</translation>
<translation id="5029568752722684782">Vymazať kópiu</translation>
<translation id="503069730517007720">Vyžaduje sa koreňový certifikát softvéru <ph name="SOFTWARE_NAME" />, ale nie je nainštalovaný. Váš správca IT by si mal prezrieť pokyny na konfiguráciu softvéru <ph name="SOFTWARE_NAME" /> a tento problém vyriešiť. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -562,12 +600,12 @@
<translation id="5172758083709347301">Počítač</translation>
<translation id="5179510805599951267">Text sa nezobrazil v jazyku <ph name="ORIGINAL_LANGUAGE" />? Nahláste túto chybu</translation>
<translation id="5190835502935405962">Panel so záložkami</translation>
+<translation id="5201306358585911203">Vložená stránka na tejto stránke hovorí</translation>
<translation id="5205222826937269299">Meno je povinný údaj</translation>
<translation id="5222812217790122047">E-mailová adresa je povinný údaj</translation>
<translation id="522700295135997067">Tento web možno práve ukradol vaše heslo</translation>
<translation id="5230733896359313003">Dodacia adresa</translation>
<translation id="5251803541071282808">Cloud</translation>
-<translation id="5277279256032773186">Používate Chrome v práci? Firmy môžu spravovať nastavenia prehliadača Chrome pre svojich zamestnancov. Ďalšie informácie</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Postupujte podľa týchto krokov a softvér dočasne zakážte, aby ste mohli prejsť na daný web. Budete potrebovať oprávnenia správcu.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -629,7 +667,6 @@
<translation id="5610142619324316209">Skontrolovať pripojenie</translation>
<translation id="5610807607761827392">Karty a adresy môžete spravovať v časti <ph name="BEGIN_LINK" />Nastavenia<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Web <ph name="HOST_NAME" /> vás presmeroval príliš veľakrát.</translation>
-<translation id="5622887735448669177">Chcete tento web opustiť?</translation>
<translation id="5629630648637658800">Nastavenia pravidla sa nepodarilo načítať</translation>
<translation id="5631439013527180824">Neplatný token správy zariadenia</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>
@@ -652,7 +689,6 @@
<translation id="5786044859038896871">Chcete vyplniť informácie o karte?</translation>
<translation id="5803412860119678065">Chcete vyplniť informácie o karte <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Vaše pripojenie k doméne <ph name="DOMAIN" /> je šifrované pomocou zastaranej šifrovacej súpravy.</translation>
-<translation id="5810928923025889964">Z vloženej stránky na tejto stránke</translation>
<translation id="5813119285467412249">&amp;Znova pridať</translation>
<translation id="5838278095973806738">Na tomto webe by ste nemali zadávať citlivé informácie (napríklad heslá alebo kreditné karty), pretože by ich mohli ukradnúť útočníci.</translation>
<translation id="5866257070973731571">Pridanie telefónneho čísla</translation>
@@ -725,21 +761,19 @@
<translation id="6446608382365791566">Pridanie ďalších informácií</translation>
<translation id="6447842834002726250">Súbory cookie</translation>
<translation id="6451458296329894277">Potvrdiť opakované odoslanie formulára</translation>
-<translation id="6456339708790392414">Vaša platba</translation>
<translation id="647261751007945333">Pravidlá zariadenia</translation>
<translation id="6477321094435799029">Chrome na tejto stránke zaznamenal nezvyčajný kód a v záujme ochrany vašich osobných informácií (napr. hesiel, telefónnych čísel a kreditných kariet) ho zablokoval.</translation>
<translation id="6489534406876378309">Spustiť nahrávanie správ o zlyhaní</translation>
<translation id="6507833130742554667">Kreditné a debetné karty sú akceptované.</translation>
<translation id="6508722015517270189">Reštartujte Chrome</translation>
-<translation id="6521373090216409766">Chcete tento web znova načítať?</translation>
<translation id="6529602333819889595">&amp;Znova odstrániť</translation>
<translation id="6534179046333460208">Návrhy Fyzického webu</translation>
<translation id="6550675742724504774">Možnosti</translation>
-<translation id="6556239504065605927">Zabezpečené pripojenie</translation>
<translation id="6556915248009097796">Platnosť do <ph name="EXPIRATION_DATE_ABBR" />, naposledy použité <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Váš správca to zatiaľ neschválil</translation>
<translation id="6569060085658103619">Prezeráte si stránku s rozšíreniami</translation>
<translation id="6596325263575161958">Možnosti šifrovania</translation>
+<translation id="6604181099783169992">Senzory pohybu alebo svetla</translation>
<translation id="6624427990725312378">Kontaktné informácie</translation>
<translation id="6626291197371920147">Pridanie platného čísla karty</translation>
<translation id="6628463337424475685">Vyhľadávanie <ph name="ENGINE" /></translation>
@@ -811,6 +845,7 @@
<translation id="7275334191706090484">Spravované záložky</translation>
<translation id="7298195798382681320">Odporúčané</translation>
<translation id="7309308571273880165">Správa o zlyhaní zaznamenaná v čase <ph name="CRASH_TIME" /> (nahranie vyžiadané používateľom, zatiaľ nebola nahraná)</translation>
+<translation id="7320336641823683070">Pomocník s pripojením</translation>
<translation id="7334320624316649418">&amp;Znova zmeniť poradie</translation>
<translation id="733923710415886693">Certifikát servera nebol zverejnený prostredníctvom pravidla transparentnosti certifikátov.</translation>
<translation id="7353601530677266744">Príkazový riadok</translation>
@@ -895,6 +930,7 @@
<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="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="7862185352068345852">Opustiť web?</translation>
<translation id="7878176543348854470">Debetné a predplatené karty sú akceptované.</translation>
<translation id="7878562273885520351">Vaše heslo mohlo byť napadnuté</translation>
<translation id="7887683347370398519">Skontrolujte svoj kód CVC a skúste to znova</translation>
@@ -917,6 +953,7 @@
<translation id="8041940743680923270">Použiť predvolené všeobecné nastavenie (Opýtať sa)</translation>
<translation id="8042918947222776840">Zvoliť spôsob vyzdvihnutia</translation>
<translation id="8057711352706143257">Softvér <ph name="SOFTWARE_NAME" /> nie je správne nakonfigurovaný. Tento problém sa zvyčajne odstráni odinštalovaním softvéru <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Znova načítať web?</translation>
<translation id="8088680233425245692">Článok sa nepodarilo zobraziť.</translation>
<translation id="8091372947890762290">Aktivácia čaká na server</translation>
<translation id="8094917007353911263">Sieť, ktorú používate, môže vyžadovať, aby ste navštívili stránku <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /></translation>
@@ -932,6 +969,7 @@
<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>
<translation id="8205463626947051446">Web zvykne zobrazovať obťažujúce reklamy</translation>
+<translation id="8211406090763984747">Pripojenie je bezpečné</translation>
<translation id="8218327578424803826">Pridelená poloha:</translation>
<translation id="8225771182978767009">Osoba, ktorá nastavila tento počítač, sa rozhodla daný web blokovať.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -943,6 +981,7 @@
<translation id="825929999321470778">Zobraziť všetky uložené heslá</translation>
<translation id="8261506727792406068">Odstrániť</translation>
<translation id="8267698848189296333">Prihlasovanie pomocou účtu <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Prihlásenie</translation>
<translation id="8288807391153049143">Zobraziť certifikát</translation>
<translation id="8289355894181816810">Ak neviete, čo to znamená, kontaktujte správcu siete.</translation>
<translation id="8293206222192510085">Pridať záložku</translation>
@@ -994,6 +1033,7 @@
<translation id="874846938927089722">Akceptované kreditné a predplatené karty</translation>
<translation id="8759274551635299824">Platnosť tejto karty vypršala</translation>
<translation id="8761567432415473239">Bezpečné prehliadanie Google nedávno <ph name="BEGIN_LINK" />zistilo škodlivé programy<ph name="END_LINK" /> na webe <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Zariadenie USB</translation>
<translation id="8790007591277257123">&amp;Znova vymazať</translation>
<translation id="8800988563907321413">Tu sa zobrazia návrhy funkcie Nablízku</translation>
<translation id="8820817407110198400">Záložky</translation>
diff --git a/chromium/components/strings/components_strings_sl.xtb b/chromium/components/strings/components_strings_sl.xtb
index a5f45c56d0d..1dab337dedd 100644
--- a/chromium/components/strings/components_strings_sl.xtb
+++ b/chromium/components/strings/components_strings_sl.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Natisni ...</translation>
<translation id="1181037720776840403">Odstrani</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Samodejno poročanje<ph name="END_WHITEPAPER_LINK" /> podrobnosti morebitnih varnostnih dogodkov Googlu. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Plačilo ni dokončano</translation>
<translation id="1201402288615127009">Naprej</translation>
<translation id="1201895884277373915">Več s tega mesta</translation>
<translation id="1206967143813997005">Neveljaven prvotni podpis</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Poročilo o zrušitvi je bilo zajeto takrat: <ph name="CRASH_TIME" /> (ni še naloženo ali je prezrto)</translation>
<translation id="1270502636509132238">Način prevzema</translation>
<translation id="1285320974508926690">Nikoli ne prevedi tega spletnega mesta</translation>
+<translation id="1294154142200295408">Različice ukazne vrstice</translation>
<translation id="129553762522093515">Nedavno zaprto</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Poskusite izbrisati piškotke<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Vaša dejavnost <ph name="BEGIN_EMPHASIS" />je morda še vedno vidna<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Sprejete kreditne in debetne kartice</translation>
<translation id="1519264250979466059">Datum gradnje</translation>
<translation id="1527263332363067270">Čakanje na povezavo ...</translation>
+<translation id="1532118530259321453">Ta stran sporoča:</translation>
<translation id="153384715582417236">To je vse za zdaj</translation>
<translation id="154408704832528245">Izbira naslova za dostavo</translation>
<translation id="1549470594296187301">Če želite uporabljati to funkcijo, mora biti omogočen JavaScript.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />preveriti strežnik proxy in požarni zid<ph name="END_LINK" /></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="2065985942032347596">Zahtevano je preverjanje pristnosti</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="2091887806945687916">Zvok</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Prekliči plačilo</translation>
<translation id="2147827593068025794">Sinhroniziranje v ozadju</translation>
<translation id="2148613324460538318">Dodaj kartico</translation>
-<translation id="2149973817440762519">Uredi zaznamek</translation>
<translation id="2154054054215849342">Sinhronizacija ni na voljo za vašo domeno</translation>
<translation id="2154484045852737596">Urejanje kartice</translation>
<translation id="2166049586286450108">Polni skrbniški dostop</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Izbira naslova za prevzem</translation>
<translation id="2740531572673183784">V redu</translation>
<translation id="2742870351467570537">Odstrani izbrane elemente</translation>
-<translation id="2744590937989388266">Z vdelane strani na tej spletni strani</translation>
<translation id="277133753123645258">Način pošiljanja</translation>
<translation id="277499241957683684">Manjka zapis o napravi</translation>
<translation id="2784949926578158345">Povezava je bila obnovljena.</translation>
<translation id="2788784517760473862">Sprejete kreditne kartice</translation>
<translation id="2794233252405721443">Spletno mesto blokirano</translation>
-<translation id="2795286477369100655">Ali želite zapustiti to spletno mesto?</translation>
<translation id="2799020568854403057">Spletno mesto vsebuje škodljive aplikacije</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="2824775600643448204">Naslovna in iskalna vrstica</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Vnos na sznamu »<ph name="ENTRY_INDEX" />«: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Samodejno blokirano</translation>
<translation id="3024663005179499861">Napačna vrsta pravilnika</translation>
-<translation id="3032412215588512954">Ali želite znova naložiti to spletno mesto?</translation>
<translation id="3037605927509011580">Ti šment!</translation>
<translation id="3039538478787849737">Želite shraniti kartico v Googlu?</translation>
<translation id="3041612393474885105">Informacije o potrdilu</translation>
@@ -310,6 +306,7 @@
poskrbite za delovanje strežnika proxy. Če menite, da vam strežnika proxy
ni treba uporabljati:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> v strežniku <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Prekliči plačilo</translation>
<translation id="3207960819495026254">Zaznamovano</translation>
<translation id="3209375525920864198">Vnesite veljavno ime seje.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Skrbnik ga lahko odblokira</translation>
<translation id="3566021033012934673">Vaša povezava ni zasebna</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Vdelana stran na spletnem mestu <ph name="SITE" /> sporoča:</translation>
<translation id="358285529439630156">Sprejema kreditne in predplačniške kartice.</translation>
<translation id="3582930987043644930">Dodajte ime</translation>
<translation id="3583757800736429874">&amp;Uveljavi premik</translation>
<translation id="3586931643579894722">Skrij podrobnosti</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Odpravljanje napak s povezavami&lt;/h1&gt;
+ &lt;p&gt;Če prejmete sporočilo o napaki, ko poskusite obiskati spletno mesto, poskusite te postopke za odpravljanje težav.&lt;/p&gt;
+ &lt;h2&gt;Odpravljanje večine napak s povezavami&lt;/h2&gt;
+ &lt;p&gt;Če poskusite obiskati spletno mesto in se ne odpre, najprej poskusite odpraviti napako s temi postopki za odpravljanje težav:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Preverite, ali je spletni naslov napačno zapisan.&lt;/li&gt;
+ &lt;li&gt;Preverite, ali internetna povezava normalno deluje.&lt;/li&gt;
+ &lt;li&gt;Obrnite se na lastnika spletnega mesta.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Pomoč pri določenem sporočilu o napaki&lt;/h2&gt;
+ &lt;h3&gt;»Vaša povezava ni zasebna« ali »NET::ERR_CERT_AUTHORITY_INVALID« ali »ERR_CERT_COMMON_NAME_INVALID« ali »NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM« ali »SSL certificate error«&lt;/h3&gt;
+ &lt;h4&gt;1. korak: prijavite se v portal&lt;/h4&gt;
+ &lt;p&gt;Omrežja Wi-Fi na mestih, kot so kavarne ali letališča, zahtevajo, da se prijavite. Če želite prikazati stran za prijavo, obiščite stran, ki uporablja&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Odprite poljubno spletno mesto, ki se začne s &lt;code&gt;http://&lt;/code&gt;, na primer &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Na strani za prijavo, ki se odpre, se prijavite, če želite uporabljati internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;2. korak: odprite stran v načinu brez beleženja zgodovine (samo računalnik)&lt;/h4&gt;
+ &lt;p&gt;Odprite stran, ki ste jo obiskali v oknu brez beleženja zgodovine.&lt;/p&gt;
+ &lt;p&gt;Če se stran odpre, imate razširitev za Chrome, ki ne deluje pravilno. Če želite odpraviti napako, izklopite razširitev.&lt;/p&gt;
+ &lt;h4&gt;3. korak: posodobite operacijski sistem&lt;/h4&gt;
+ &lt;p&gt;Poskrbite, da je naprava posodobljena.&lt;/p&gt;
+ &lt;h4&gt;4. korak: začasno izklopite protivirusno programsko opremo&lt;/h4&gt;
+ &lt;p&gt;Ta napaka bo prikazana, če imate protivirusno programsko opremo, ki ponuja »zaščito HTTPS« ali »pregledovanje HTTPS«. Protivirusna programska oprema Chromu preprečuje zagotavljanje varnosti.&lt;/p&gt;
+ &lt;p&gt;Če želite odpraviti težavo, izklopite protivirusno programsko opremo. Če stran deluje, ko programsko opremo izklopite, izklopite to programsko opremo, ko uporablja varna spletna mesta.&lt;/p&gt;
+ &lt;p&gt;Ne pozabite spet vklopiti protivirusne programske opreme, ko končate.&lt;/p&gt;
+ &lt;h4&gt;5. korak: poiščite dodatno pomoč&lt;/h4&gt;
+ &lt;p&gt;Če je napaka še vedno prikazana, se obrnite na lastnika spletnega mesta.&lt;/p&gt;
+ &lt;h3&gt;»Vzpostavite povezavo z omrežjem«&lt;/h3&gt;
+ &lt;p&gt;Ta napaka bo prikazana, če uporabljate portal Wi-Fi, ki zahteva prijavo, preden lahko vzpostavite povezavo z internetom.&lt;/p&gt;
+ &lt;p&gt;Če želite odpraviti to napako, kliknite &lt;strong&gt;Poveži&lt;/strong&gt; na strani, ki jo poskušate odpreti.&lt;/p&gt;
+ &lt;h3&gt;»Ura zaostaja« ali »Ura prehiteva« ali »NET::ERR_CERT_DATE_INVALID«&lt;/h3&gt;
+ &lt;p&gt;Ta napaka bo prikazana, če datum in ura v računalniku ali mobilni napravi nista točna.&lt;/p&gt;
+ &lt;p&gt;Če želite odpraviti napako, odprite uro v napravi, in poskrbite, da sta datum in ura točna.&lt;/p&gt;
+ &lt;h3&gt;»Programska oprema v računalniku Chromu preprečuje vzpostavitev varne povezave s spletom« (samo računalniki s sistemom Windows)&lt;/h3&gt;
+ &lt;p&gt;Ta napaka se prikaže, če imate v računalniku s sistemom Windows programsko opremo Superfish.&lt;/p&gt;
+ &lt;p&gt;Upoštevajte ta navodila, če želite začasno onemogočiti programsko opremo, da se boste lahko povezali v splet. Potrebujete skrbniške pravice.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Kliknite &lt;strong&gt;Start&lt;/strong&gt;, nato poiščite in izberite &lt;strong&gt;»Ogled lokalnih storitev«&lt;/strong&gt;
+ &lt;li&gt;Izberite &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Pri &lt;strong&gt;Vrsta zagona&lt;/strong&gt; izberite &lt;strong&gt;Onemogočeno&lt;/strong&gt;
+ &lt;li&gt;Pri &lt;strong&gt;Stanje storitve&lt;/strong&gt; kliknite &lt;strong&gt;Ustavi&lt;/strong&gt;
+ &lt;li&gt;Kliknite &lt;strong&gt;Uporabi&lt;/strong&gt;, nato kliknite &lt;strong&gt;V redu&lt;/strong&gt;
+ &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 trajno odstranite programsko opremo iz računalnika.
+ &lt;/ol&gt;</translation>
<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>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Ali želite shraniti to kartico v Google Račun in v tej napravi?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Poteče: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">S spletnega mesta <ph name="SITE" /></translation>
<translation id="382518646247711829">Če uporabite namestniški strežnik ...</translation>
<translation id="3828924085048779000">Prazno geslo ni dovoljeno.</translation>
<translation id="385051799172605136">Nazaj</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">ID naloženega poročila o zrušitvah <ph name="CRASH_ID" /> (ID lokalne zrušitve: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Strežniku ni uspelo dokazati, da je <ph name="DOMAIN" />; njegovo varnostno potrdilo ne določa nadomestnih imen SAN (Subject Alternative Name). Razlog za to je morda napačna konfiguracija ali napadalčevo prestrezanje povezave.</translation>
<translation id="3949601375789751990">Tu je prikazana zgodovina brskanja</translation>
+<translation id="3950820424414687140">Prijava</translation>
<translation id="3963721102035795474">Način bralnika</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Brez}=1{1 spletno mesto }one{# spletno mesto }two{# spletni mesti }few{# spletna mesta }other{# spletnih mest }}</translation>
<translation id="397105322502079400">Izračunavanje …</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Neveljavna serijska številka naprave</translation>
<translation id="410351446219883937">Samodejno predvajanje</translation>
<translation id="4103763322291513355">Na &lt;strong&gt;chrome://policy&lt;/strong&gt; si lahko ogledate seznam blokiranih URL-jev in drugih pravilnikov, ki jih uveljavlja skrbnik sistema.</translation>
+<translation id="4110652170750985508">Pregled plačila</translation>
<translation id="4116663294526079822">Vedno dovoli na tem spletnem mestu</translation>
<translation id="4117700440116928470">Obseg pravilnika ni podprt.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{in še 1 drug}one{in še # drug}two{in še # druga}few{in še # drugi}other{in še # drugih}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Ni uporabniškega imena)</translation>
<translation id="4275830172053184480">Znova zaženite napravo.</translation>
<translation id="4280429058323657511">, datum poteka veljavnosti: <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Prijava</translation>
<translation id="4312866146174492540">Blokira (privzeto)</translation>
<translation id="4325863107915753736">Članka ni bilo mogoče najti</translation>
<translation id="4326324639298822553">Preverite datum poteka veljavnosti in poskusite znova.</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Kartice in naslovi so iz Chroma in Google Računa (<ph name="ACCOUNT_EMAIL" />). Upravljate jih lahko v <ph name="BEGIN_LINK" />nastavitvah<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Podrobnosti</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Z vdelane strani na spletnem mestu <ph name="SITE" /></translation>
<translation id="4558551763791394412">Poskusite onemogočiti razširitve.</translation>
<translation id="457875822857220463">Dostava</translation>
<translation id="4582800630050655161">Izgubite lahko dostop do Google Računa ali postanete žrtev kraje identitete. Chromium priporoča, da spremenite geslo.</translation>
<translation id="4587425331216688090">Želite odstraniti naslov iz Chroma?</translation>
<translation id="4592951414987517459">Povezava z domeno <ph name="DOMAIN" /> je šifrirana s sodobno šifrirno zbirko.</translation>
<translation id="4594403342090139922">&amp;Razveljavi izbris</translation>
-<translation id="4611292653554630842">Prijava</translation>
<translation id="4619615317237390068">Zavihki iz drugih naprav</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Strežniku ni uspelo dokazati, da je <ph name="DOMAIN" />; njegovo varnostno potrdilo vsebuje napake. Razlog za to je lahko napačna konfiguracija ali napadalčevo prestrezanje povezave.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Povezava je bila prekinjena</translation>
<translation id="471880041731876836">Nimate dovoljenja za obisk tega spletnega mesta</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Izvajanje orodja Omrežna diagnostika Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Plačilo</translation>
<translation id="4726672564094551039">Znova naloži pravilnike</translation>
<translation id="4728558894243024398">Okolje</translation>
<translation id="4736825316280949806">Znova zaženite Chromium</translation>
-<translation id="4737498291095696011">S te spletne strani</translation>
<translation id="4744603770635761495">Pot do izvedljive datoteke</translation>
<translation id="4749685221585524849">Zadnja uporaba: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Vaši podatki (npr. gesla ali številke kreditnih kartic) so zasebni, kadar so poslani temu spletnemu mestu.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Pogled</translation>
<translation id="4854362297993841467">Ta način pošiljanja ni na voljo. Poskusite uporabiti drugega.</translation>
<translation id="4858792381671956233">Starše si vprašal(-a), ali smeš obiskati to spletno mesto</translation>
-<translation id="4871132632506079383">Z vdelane strani na spletnem mestu <ph name="SITE" /></translation>
<translation id="4880827082731008257">Zgodovina iskanja</translation>
+<translation id="4881695831933465202">Odpri</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Zahtevano je preverjanje pristnosti</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{in še 1 spletna stran}one{in še # spletna stran}two{in še # spletni strani}few{in še # spletne strani}other{in še # spletnih strani}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Vnesite CVC za <ph name="CREDIT_CARD" />. Ko potrdite, bodo temu spletnemu mestu razkriti podatki o kreditni kartici iz računa za Google Payments.</translation>
<translation id="4923417429809017348">Stran je bila iz neznanega jezika prevedena v jezik »<ph name="LANGUAGE_LANGUAGE" />«</translation>
<translation id="4923459931733593730">Plačilo</translation>
<translation id="4926049483395192435">Vrednost mora biti določena.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> sporoča:</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Dejanja</translation>
<translation id="4958444002117714549">Razširi seznam</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Če je to omogočeno, Chrome shrani kopijo kartice v tej napravi zaradi hitrejšega izpolnjevanja obrazcev.</translation>
<translation id="5018422839182700155">Te strani ni mogoče odpreti</translation>
<translation id="5019198164206649151">Neprimerno stanje rezervne shrambe</translation>
-<translation id="5020990877659450221">S te strani</translation>
<translation id="5023310440958281426">Preverite skrbnikove pravilnike</translation>
<translation id="5029568752722684782">Počisti kopijo</translation>
<translation id="503069730517007720">Korensko potrdilo za programsko opremo »<ph name="SOFTWARE_NAME" />« je obvezno, vendar ni nameščeno. Skrbnik za IT lahko za odpravo te težave upošteva navodila za konfiguracijo za programsko opremo »<ph name="SOFTWARE_NAME" />«. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Računalnik</translation>
<translation id="5179510805599951267">Ni v <ph name="ORIGINAL_LANGUAGE" />? Obvestite nas o tej napaki</translation>
<translation id="5190835502935405962">Vrstica z zaznamki</translation>
+<translation id="5201306358585911203">Vdelana stran na tej spletni strani sporoča:</translation>
<translation id="5205222826937269299">Ime je obvezno</translation>
<translation id="5222812217790122047">E-poštni naslov je obvezen</translation>
<translation id="522700295135997067">To spletno mesto vam je morda pravkar ukradlo geslo</translation>
<translation id="5230733896359313003">Naslov za pošiljanje</translation>
<translation id="5251803541071282808">Oblak</translation>
-<translation id="5277279256032773186">Uporabljate Chrome v službi? Podjetja lahko upravljajo nastavitve Chroma za zaposlene. Preberite več o tem.</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Upoštevajte ta navodila, če želite začasno onemogočiti programsko opremo, da se boste lahko povezali v splet. Potrebujete skrbniške pravice.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">preveriti povezavo</translation>
<translation id="5610807607761827392">Kartice in naslove je mogoče upravljati v <ph name="BEGIN_LINK" />nastavitvah<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Spletno mesto <ph name="HOST_NAME" /> vas je prevečkrat preusmerilo.</translation>
-<translation id="5622887735448669177">Ali želite zapustiti to spletno mesto?</translation>
<translation id="5629630648637658800">Nastavitev pravilnika ni bilo mogoče naložiti</translation>
<translation id="5631439013527180824">Neveljaven žeton za upravljanje naprave</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Ali želite izpolniti podatke kreditne kartice?</translation>
<translation id="5803412860119678065">Ali želite izpolniti podatke za kartico <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Povezava z domeno <ph name="DOMAIN" /> je šifrirana z zastarelo šifrirno zbirko.</translation>
-<translation id="5810928923025889964">Z vdelane strani na tej spletni strani</translation>
<translation id="5813119285467412249">&amp;Uveljavi dodajanje</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>
<translation id="5866257070973731571">Dodajanje telefonske številke</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Dodajanje več podatkov</translation>
<translation id="6447842834002726250">Piškotki</translation>
<translation id="6451458296329894277">Potrdite ponovno pošiljanje obrazca</translation>
-<translation id="6456339708790392414">Plačilo</translation>
<translation id="647261751007945333">Pravilniki za naprave</translation>
<translation id="6477321094435799029">Chrome je zaznal nenavadno kodo na tej strani in jo zaradi zaščite vaših osebnih podatkov (na primer gesel, telefonskih številk in kreditnih kartic) blokiral.</translation>
<translation id="6489534406876378309">Začetek prenašanja zrušitev v storitev</translation>
<translation id="6507833130742554667">Sprejema kreditne in debetne kartice.</translation>
<translation id="6508722015517270189">Znova zaženite Chrome</translation>
-<translation id="6521373090216409766">Ali želite znova naložiti to spletno mesto?</translation>
<translation id="6529602333819889595">&amp;Uveljavi izbris</translation>
<translation id="6534179046333460208">Predlogi za Fizični splet</translation>
<translation id="6550675742724504774">Možnosti</translation>
-<translation id="6556239504065605927">Varna povezava</translation>
<translation id="6556915248009097796">Datum poteka: <ph name="EXPIRATION_DATE_ABBR" />, zadnja uporaba: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Skrbnik še ni odobril</translation>
<translation id="6569060085658103619">Ogledujete si stran razširitve</translation>
<translation id="6596325263575161958">Možnosti šifriranja</translation>
+<translation id="6604181099783169992">Tipala za gibanje in svetlobe</translation>
<translation id="6624427990725312378">Podatki o stiku</translation>
<translation id="6626291197371920147">Dodajanje veljavne številke kartice</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Iskanje</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Upravljani zaznamki</translation>
<translation id="7298195798382681320">Priporočeni</translation>
<translation id="7309308571273880165">Poročilo o zrušitvi, zajeto takrat: <ph name="CRASH_TIME" /> (uporabnik je zahteval nalaganje; ni še bilo naloženo)</translation>
+<translation id="7320336641823683070">Pomoč pri povezavi</translation>
<translation id="7334320624316649418">&amp;Uveljavi razvrstitev</translation>
<translation id="733923710415886693">Potrdilo strežnika ni bilo razkrito na podlagi pravilnika o preglednosti potrdila.</translation>
<translation id="7353601530677266744">Ukazna vrstica</translation>
@@ -900,6 +935,7 @@
<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="785549533363645510">Kljub temu pa niste nevidni. Z uporabo načina brez beleženja zgodovine 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="7862185352068345852">Želite zapustiti spletno mesto?</translation>
<translation id="7878176543348854470">Sprejema debetne in kreditne kartice.</translation>
<translation id="7878562273885520351">Geslo je morda ogroženo</translation>
<translation id="7887683347370398519">Preverite CVC in poskusite znova</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Uporabi globalno privzeto (Vprašaj)</translation>
<translation id="8042918947222776840">Izbira načina prevzema</translation>
<translation id="8057711352706143257">Programska oprema »<ph name="SOFTWARE_NAME" />« ni pravilno konfigurirana. Običajno težavo odpravite tako, da odstranite programsko opremo »<ph name="SOFTWARE_NAME" />«. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Želite znova naložiti spletno mesto?</translation>
<translation id="8088680233425245692">Članka si ni bilo mogoče ogledati.</translation>
<translation id="8091372947890762290">Čakanje na aktivacijo v strežniku</translation>
<translation id="8094917007353911263">Omrežje, ki ga uporabljate, morda zahteva, da obiščete <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">Neveljaven posodobitveni URL za razširitev z ID-jem »<ph name="EXTENSION_ID" />«.</translation>
<translation id="8202097416529803614">Povzetek naročila</translation>
<translation id="8205463626947051446">Spletno mesto prikazuje vsiljive oglase</translation>
+<translation id="8211406090763984747">Povezava je varna</translation>
<translation id="8218327578424803826">Dodeljena lokacija:</translation>
<translation id="8225771182978767009">Oseba, ki je nastavila ta računalnik, je blokirala to spletno mesto.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Prikaz vseh shranjenih gesel</translation>
<translation id="8261506727792406068">Izbriši</translation>
<translation id="8267698848189296333">Prijava kot: <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Prijava</translation>
<translation id="8288807391153049143">Prikaz potrdila</translation>
<translation id="8289355894181816810">Če niste prepričani, kaj to pomeni, se obrnite na skrbnika omrežja.</translation>
<translation id="8293206222192510085">Dodaj zaznamek</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Sprejete kreditne in predplačniške kartice</translation>
<translation id="8759274551635299824">Ta kartica je potekla</translation>
<translation id="8761567432415473239">Googlova funkcija varnega brskanja je nedavno <ph name="BEGIN_LINK" />odkrila škodljive programe<ph name="END_LINK" /> na spletnem mestu <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Naprava USB</translation>
<translation id="8790007591277257123">&amp;Uveljavi izbris</translation>
<translation id="8800988563907321413">Tu so prikazani predlogi v bližini</translation>
<translation id="8820817407110198400">Zaznamki</translation>
diff --git a/chromium/components/strings/components_strings_sr.xtb b/chromium/components/strings/components_strings_sr.xtb
index c11944753a9..6e94c2a9d70 100644
--- a/chromium/components/strings/components_strings_sr.xtb
+++ b/chromium/components/strings/components_strings_sr.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Одштампај...</translation>
<translation id="1181037720776840403">Уклони</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Аутоматски пријави<ph name="END_WHITEPAPER_LINK" /> Google-у детаље о могућим безбедносним инцидентима. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Плаћање није довршено</translation>
<translation id="1201402288615127009">Даље</translation>
<translation id="1201895884277373915">Више са овог сајта</translation>
<translation id="1206967143813997005">Неисправан потпис иницијалима</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Извештај о отказивању је снимљен <ph name="CRASH_TIME" /> (још увек није отпремљен или игнорисан)</translation>
<translation id="1270502636509132238">Начин преузимања</translation>
<translation id="1285320974508926690">Никад не преводи овај сајт</translation>
+<translation id="1294154142200295408">Варијације командне линије</translation>
<translation id="129553762522093515">Недавно затворено</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Покушајте да обришете колачиће<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Активности ће <ph name="BEGIN_EMPHASIS" />можда ипак бити видљиве<ph name="END_EMPHASIS" /> за:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Платне и кредитне картице које се прихватају</translation>
<translation id="1519264250979466059">Датум верзије</translation>
<translation id="1527263332363067270">Чека се веза…</translation>
+<translation id="1532118530259321453">Ова страница наводи:</translation>
<translation id="153384715582417236">То је све за сада</translation>
<translation id="154408704832528245">Одаберите адресу за доставу</translation>
<translation id="1549470594296187301">JavaScript мора да буде омогућен да бисте користили ову функцију.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />да проверите прокси и заштитни зид<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Поштански број</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 предлог}one{# предлог}few{# предлога}other{# предлога}}</translation>
-<translation id="2065985942032347596">Потребна је потврда идентитета</translation>
<translation id="2079545284768500474">Опозови</translation>
<translation id="20817612488360358">Подешено је да се користе системска подешавања проксија, али је наведена експлицитна конфигурација проксија.</translation>
<translation id="2091887806945687916">Звук</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Откажи плаћање</translation>
<translation id="2147827593068025794">Синхронизација у позадини</translation>
<translation id="2148613324460538318">Додај картицу</translation>
-<translation id="2149973817440762519">Измените обележивач</translation>
<translation id="2154054054215849342">Синхронизација није доступна за домен</translation>
<translation id="2154484045852737596">Измените картицу</translation>
<translation id="2166049586286450108">Потпуни администраторски приступ</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Одаберите адресу преузимања</translation>
<translation id="2740531572673183784">Потврди</translation>
<translation id="2742870351467570537">Уклони изабране ставке</translation>
-<translation id="2744590937989388266">Са уграђене странице на овој страници</translation>
<translation id="277133753123645258">Начин слања</translation>
<translation id="277499241957683684">Недостаје евиденција уређаја</translation>
<translation id="2784949926578158345">Веза је враћена на почетне вредности.</translation>
<translation id="2788784517760473862">Кредитне картице које се прихватају</translation>
<translation id="2794233252405721443">Сајт је блокиран</translation>
-<translation id="2795286477369100655">Желите ли да напустите овај сајт?</translation>
<translation id="2799020568854403057">Сајт који ћете посетити садржи штетне апликације</translation>
<translation id="2803306138276472711">Google безбедно прегледање је недавно <ph name="BEGIN_LINK" />открило малвер<ph name="END_LINK" /> на <ph name="SITE" />. Веб-сајтови који су обично безбедни се понекад заразе малвером.</translation>
<translation id="2824775600643448204">Трака за адресу и претрагу</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Унос на листи „<ph name="ENTRY_INDEX" />“: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Аутоматски је блокирано</translation>
<translation id="3024663005179499861">Погрешан тип смерница</translation>
-<translation id="3032412215588512954">Желите ли поново да учитате овај сат?</translation>
<translation id="3037605927509011580">О, не!</translation>
<translation id="3039538478787849737">Желите ли да сачувате картицу на Google-у?</translation>
<translation id="3041612393474885105">Информације о сертификату</translation>
@@ -310,6 +306,7 @@
бисте се уверили да прокси сервер функционише. Ако мислите да не
треба да користите прокси сервер:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> на: <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Откажи плаћање</translation>
<translation id="3207960819495026254">Обележено</translation>
<translation id="3209375525920864198">Унесите важећи назив сесије.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Менаџер може да га деблокира за вас</translation>
<translation id="3566021033012934673">Веза није приватна</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Уграђена страница на <ph name="SITE" /> наводи:</translation>
<translation id="358285529439630156">Прихватају се кредитне и припејд картице.</translation>
<translation id="3582930987043644930">Додајте име</translation>
<translation id="3583757800736429874">&amp;Понови премештање</translation>
<translation id="3586931643579894722">Сакриј детаље</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Отклоните грешке при повезивању&lt;/h1&gt;
+ &lt;p&gt;Ако вам се прикаже порука о грешци када пробате да посетите неки веб-сајт, пробајте следећа решења.&lt;/p&gt;
+ &lt;h2&gt;Отклоните већину грешака при повезивању&lt;/h2&gt;
+ &lt;p&gt;Ако пробате да посетите неки веб-сајт и он неће да се отвори, прво пробајте да отклоните грешку помоћу следећих корака за решавање проблема:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Проверите да ли сте правилно написали веб-адресу.&lt;/li&gt;
+ &lt;li&gt;Проверите да ли интернет веза нормално ради.&lt;/li&gt;
+ &lt;li&gt;Контактирајте власника веб-сајта.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Потражите помоћ за одређену поруку о грешци&lt;/h2&gt;
+ &lt;h3&gt;„Веза није приватна“, „NET::ERR_CERT_AUTHORITY_INVALID“, „ERR_CERT_COMMON_NAME_INVALID“, „NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM“ или „Грешка у вези са SSL сертификатом“&lt;/h3&gt;
+ &lt;h4&gt;1. корак: Пријавите се на портал&lt;/h4&gt;
+ &lt;p&gt;За Wi-Fi мреже на местима попут кафића или аеродрома треба да се пријавите. Да бисте видели страницу за пријављивање, посетите страницу која користи &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Идите на било који веб-сајт који почиње са &lt;code&gt;http://&lt;/code&gt;, као што је &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;На страници за пријављивање која се отвори пријавите се да бисте користили интернет.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;2. корак: Отворите страницу у режиму без архивирања (само за рачунар)&lt;/h4&gt;
+ &lt;p&gt;Страницу коју сте посетили отворите у прозору без архивирања.&lt;/p&gt;
+ &lt;p&gt;Ако се страница отвори, то значи да додатак за Chrome не ради како треба. Да бисте отклонили грешку, искључите додатак.&lt;/p&gt;
+ &lt;h4&gt;3. корак: Ажурирајте оперативни систем&lt;/h4&gt;
+ &lt;p&gt;Проверите да ли је уређај ажуриран.&lt;/p&gt;
+ &lt;h4&gt;4. корак: Привремено искључите антивирус&lt;/h4&gt;
+ &lt;p&gt;Ова грешка ће вам се приказати ако имате антивирусни софтвер који пружа „HTTPS заштиту“ или „HTTPS скенирање“. Антивирус спречава Chrome да вам пружа безбедносне функције.&lt;/p&gt;
+ &lt;p&gt;Да бисте решили проблем, искључите антивирусни софтвер. Ако страница ради када искључите софтвер, искључите тај софтвер када користите безбедне сајтове.&lt;/p&gt;
+ &lt;p&gt;Не заборавите да поново укључите антивирусни програм када завршите.&lt;/p&gt;
+ &lt;h4&gt;5. корак: Потражите додатну помоћ&lt;/h4&gt;
+ &lt;p&gt;Ако вам се грешка и даље приказује, контактирајте власника веб-сајта.&lt;/p&gt;
+ &lt;h3&gt;„Повежите се на мрежу“&lt;/h3&gt;
+ &lt;p&gt;Ова грешка ће вам се приказати ако користите Wi-Fi портал где морате да се пријавите да бисте се повезали на интернет.&lt;/p&gt;
+ &lt;p&gt;Да бисте отклонили грешку, кликните на &lt;strong&gt;Повежи се&lt;/strong&gt; на страници коју покушавате да отворите.&lt;/p&gt;
+ &lt;h3&gt;„Сат касни“, „Сат жури“ или „NET::ERR_CERT_DATE_INVALID“&lt;/h3&gt;
+ &lt;p&gt;Ова грешка ће вам се приказати ако датум и време на рачунару или мобилном уређају нису тачни.&lt;/p&gt;
+ &lt;p&gt;Да бисте отклонили грешку, отворите сат на уређају. Проверите да ли су датум и време тачни.&lt;/p&gt;
+ &lt;h3&gt;„Софтвер на вашем рачунару онемогућава Chrome-у да се безбедно повеже на веб“ (само на Windows рачунарима)&lt;/h3&gt;
+ &lt;p&gt;Ова грешка ће вам се приказати ако имате Superfish софтвер на Windows рачунару.&lt;/p&gt;
+ &lt;p&gt;Пратите ове кораке за привремено онемогућавање софтвера да бисте се повезали на интернет. Требаће вам привилегије администратора.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Кликните на &lt;strong&gt;Start&lt;/strong&gt; (Покрени), затим потражите и изаберите &lt;strong&gt;„View local services“&lt;/strong&gt; (Прикажи локалне услуге)
+ &lt;li&gt;Изаберите &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;У опцији &lt;strong&gt;Startup type&lt;/strong&gt; (Тип покретања) изаберите &lt;strong&gt;Disabled&lt;/strong&gt; (Онемогућено)
+ &lt;li&gt;У опцији &lt;strong&gt;Service status&lt;/strong&gt; (Статус услуге) кликните на &lt;strong&gt;Stop&lt;/strong&gt; (Заустави)
+ &lt;li&gt;Кликните на &lt;strong&gt;Apply&lt;/strong&gt; (Примени), па на &lt;strong&gt;OK&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="3615877443314183785">Унесите важећи датум истека</translation>
<translation id="36224234498066874">Обриши податке прегледања...</translation>
<translation id="362276910939193118">Прикажи комплетну историју</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Да ли желите да сачувате ову картицу на Google налогу и на овом уређају?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Истиче <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Са <ph name="SITE" /></translation>
<translation id="382518646247711829">Ако користите прокси сервер...</translation>
<translation id="3828924085048779000">Није дозвољено да поље за приступну фразу буде празно.</translation>
<translation id="385051799172605136">Назад</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">ИД извештаја о отказивању је отпремљен <ph name="CRASH_ID" /> (ИД локалног отказивања: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Овај сервер не може да докаже да је <ph name="DOMAIN" />; његов безбедносни сертификат не наводи Алтернативне називе субјекта. Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.</translation>
<translation id="3949601375789751990">Историја прегледања ће се појавити овде</translation>
+<translation id="3950820424414687140">Пријави ме</translation>
<translation id="3963721102035795474">Режим читаоца</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{None}=1{Са 1 сајта }one{Са # сајта }few{Са # сајта }other{Са # сајтова }}</translation>
<translation id="397105322502079400">Израчунавање...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Серијски број уређаја је неважећи</translation>
<translation id="410351446219883937">Аутоплеј</translation>
<translation id="4103763322291513355">Посетите &lt;strong&gt;chrome://policy&lt;/strong&gt; да бисте видели листу URL-ова стављених на црну листу и друге смернице које је наметнуо администратор система.</translation>
+<translation id="4110652170750985508">Прегледајте уплату</translation>
<translation id="4116663294526079822">Увек дозволи на овом сајту</translation>
<translation id="4117700440116928470">Опсег смерница није подржан.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{још 1}one{још #}few{још #}other{још #}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Без корисничког имена)</translation>
<translation id="4275830172053184480">Поновно покретање уређаја</translation>
<translation id="4280429058323657511">, истиче <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Пријављивање</translation>
<translation id="4312866146174492540">Блокирај (подразумевано)</translation>
<translation id="4325863107915753736">Нисмо успели да пронађемо чланак</translation>
<translation id="4326324639298822553">Проверите датум истека и пробајте поново</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Картице и адресе су из Chrome-а и са вашег Google налога (<ph name="ACCOUNT_EMAIL" />). Њима можете да управљате у <ph name="BEGIN_LINK" />подешавњима<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Детаљи</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Са уграђене странице на <ph name="SITE" /></translation>
<translation id="4558551763791394412">Покушајте да онемогућите додатке.</translation>
<translation id="457875822857220463">Испорука</translation>
<translation id="4582800630050655161">Могли бисте да изгубите приступ Google налогу или би могло да дође до крађе идентитета. Chromium препоручује да одмах промените лозинку.</translation>
<translation id="4587425331216688090">Желите ли да уклоните адресу из Chrome-а?</translation>
<translation id="4592951414987517459">Веза са доменом <ph name="DOMAIN" /> је шифрована помоћу модерног пакета за шифровање.</translation>
<translation id="4594403342090139922">&amp;Опозови брисање</translation>
-<translation id="4611292653554630842">Пријави ме</translation>
<translation id="4619615317237390068">Картице са других уређаја</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Овај сервер не може да докаже да је <ph name="DOMAIN" />; његов безбедносни сертификат садржи грешке. Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Веза је прекинута</translation>
<translation id="471880041731876836">Немате дозволу да посетите овај сајт</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />да покренете Windows дијагностику мреже<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Плаћање</translation>
<translation id="4726672564094551039">Поново учитај смернице</translation>
<translation id="4728558894243024398">Платформа</translation>
<translation id="4736825316280949806">Поново покрените Chromium</translation>
-<translation id="4737498291095696011">Са ове странице</translation>
<translation id="4744603770635761495">Путања извршне датотеке</translation>
<translation id="4749685221585524849">Последњи пут коришћено: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Информације (на пример, лозинке или бројеви кредитних картица) су приватне када се шаљу овом сајту.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Приказ</translation>
<translation id="4854362297993841467">Овај начин испоруке није доступан. Испробајте неки други начин.</translation>
<translation id="4858792381671956233">Питао/ла си родитеље да ли смеш да посетиш овај сајт</translation>
-<translation id="4871132632506079383">Са уграђене странице на <ph name="SITE" /></translation>
<translation id="4880827082731008257">Претражи историју</translation>
+<translation id="4881695831933465202">Отвори</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Потврда идентитета је обавезна</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{и јој 1 веб-страница}one{и још # веб-страница}few{и још # веб-странице}other{и још # веб-страница}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Унесите CVC за картицу <ph name="CREDIT_CARD" />. Када будете потврдили, подаци о картици са налога за Google плаћања ће бити послати овом сајту.</translation>
<translation id="4923417429809017348">Ова страница је преведена са непознатог језика на <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Плаћање</translation>
<translation id="4926049483395192435">Мора да буде наведено.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> наводи:</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Радње</translation>
<translation id="4958444002117714549">Прошири листу</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Ако је ова опција омогућена, Chrome ће складиштити копију картице на овом уређају ради бржег попуњавања образаца.</translation>
<translation id="5018422839182700155">Не можемо да отворимо ову страницу</translation>
<translation id="5019198164206649151">Складиште тока података је у лошем стању</translation>
-<translation id="5020990877659450221">Са ове странице</translation>
<translation id="5023310440958281426">Проверите смернице администратора</translation>
<translation id="5029568752722684782">Обриши копију</translation>
<translation id="503069730517007720">Основни сертификат за софтвер „<ph name="SOFTWARE_NAME" />“ је обавезан, али није инсталиран. ИТ администратор треба да прегледа упутства за конфигурацију софтвера „<ph name="SOFTWARE_NAME" />“ да би решио овај проблем. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Рачунар</translation>
<translation id="5179510805599951267">Није <ph name="ORIGINAL_LANGUAGE" />? Пријавите ову грешку</translation>
<translation id="5190835502935405962">Трака са обележивачима</translation>
+<translation id="5201306358585911203">Уграђена страница на овој веб-страници наводи:</translation>
<translation id="5205222826937269299">Име је обавезно</translation>
<translation id="5222812217790122047">Имејл је обавезан</translation>
<translation id="522700295135997067">Овај сајт вам је можда управо украо лозинку</translation>
<translation id="5230733896359313003">Адреса за слање</translation>
<translation id="5251803541071282808">Клауд</translation>
-<translation id="5277279256032773186">Да ли користите Chrome на послу? Предузеће може да управља подешавањима Chrome-а за запослене. Сазнајте више</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Пратите ове кораке да бисте привремено онемогућили софтвер и приступили вебу. Требаће вам привилегије администратора.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">да проверите везу</translation>
<translation id="5610807607761827392">Картицама и адресама можете да управљате у <ph name="BEGIN_LINK" />Подешавањима<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Хост <ph name="HOST_NAME" /> вас је преусмерио превелики број пута.</translation>
-<translation id="5622887735448669177">Желите ли да напустите овај сајт?</translation>
<translation id="5629630648637658800">Учитавање подешавања смерница није успело</translation>
<translation id="5631439013527180824">Неважећи токен за управљање уређајима</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Желите ли да попуните информације о картици?</translation>
<translation id="5803412860119678065">Желите ли да попуните подацима <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">Веза са доменом <ph name="DOMAIN" /> је шифрована помоћу застарелог пакета за шифровање.</translation>
-<translation id="5810928923025889964">Са уграђене странице на овој страници</translation>
<translation id="5813119285467412249">&amp;Понови додавање</translation>
<translation id="5838278095973806738">Немојте да уносите осетљиве информације на овом сајту (на пример, лозинке или кредитне картице) јер нападачи могу да их украду.</translation>
<translation id="5866257070973731571">Додајте број телефона</translation>
@@ -729,21 +765,19 @@
<translation id="6446608382365791566">Додајте још информација</translation>
<translation id="6447842834002726250">Колачићи</translation>
<translation id="6451458296329894277">Потврђивање поновног слања обрасца</translation>
-<translation id="6456339708790392414">Плаћање</translation>
<translation id="647261751007945333">Смернице за уређај</translation>
<translation id="6477321094435799029">Chrome је открио неуобичајени кôд на овој страници и блокирао је ради заштите ваших личних података (попут лозинки, бројева телефона или бројева кредитних картица).</translation>
<translation id="6489534406876378309">Покрени отпремање отказивања</translation>
<translation id="6507833130742554667">Прихватају се кредитне и дебитне картице.</translation>
<translation id="6508722015517270189">Поново покрените Chrome</translation>
-<translation id="6521373090216409766">Желите ли поново да учитате овај сајт?</translation>
<translation id="6529602333819889595">&amp;Понови брисање</translation>
<translation id="6534179046333460208">Предлози Интернета око нас</translation>
<translation id="6550675742724504774">Опције</translation>
-<translation id="6556239504065605927">Безбедна веза</translation>
<translation id="6556915248009097796">Истиче: <ph name="EXPIRATION_DATE_ABBR" />, последњи пут коришћено: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Менаџер га још увек није одобрио</translation>
<translation id="6569060085658103619">Прегледате страницу додатка.</translation>
<translation id="6596325263575161958">Опције шифровања</translation>
+<translation id="6604181099783169992">Сензори за покрет или светло</translation>
<translation id="6624427990725312378">Контакт информације</translation>
<translation id="6626291197371920147">Додајте важећи број картице</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> претрага</translation>
@@ -815,6 +849,7 @@
<translation id="7275334191706090484">Обележивачи којим се управља</translation>
<translation id="7298195798382681320">Препоручено</translation>
<translation id="7309308571273880165">Извештај о отказивању је снимљен <ph name="CRASH_TIME" /> (корисник треба да га отпреми, још увек није отпремљен)</translation>
+<translation id="7320336641823683070">Помоћ при повезивању</translation>
<translation id="7334320624316649418">&amp;Понови промену редоследа</translation>
<translation id="733923710415886693">Сертификат сервера није откривен помоћу Транспарентности сертификата.</translation>
<translation id="7353601530677266744">Командна линија</translation>
@@ -899,6 +934,7 @@
<translation id="782886543891417279">Wi-Fi мрежа коју користите (<ph name="WIFI_NAME" />) ће можда захтевати да посетите страницу за пријављивање.</translation>
<translation id="785549533363645510">Али, нисте невидљиви. Преласком у режим без архивирања нећете сакрити прегледање од послодавца, интернет провајдера или веб-сајтова које посећујете.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" />: <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
+<translation id="7862185352068345852">Желите ли да напустите сајт?</translation>
<translation id="7878176543348854470">Прихватају се дебитне и припејд картице.</translation>
<translation id="7878562273885520351">Лозинка је можда компромитована</translation>
<translation id="7887683347370398519">Проверите CVC и покушајте поново</translation>
@@ -921,6 +957,7 @@
<translation id="8041940743680923270">Користи глобалну подразумевану вредност (Питај)</translation>
<translation id="8042918947222776840">Одаберите начин преузимања</translation>
<translation id="8057711352706143257">Софтвер „<ph name="SOFTWARE_NAME" />“ није правилно конфигурисан. Деинсталирање софтвера „<ph name="SOFTWARE_NAME" />“ обично решава проблем. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Желите ли поново да учитате сајт?</translation>
<translation id="8088680233425245692">Прегледање чланка није успело.</translation>
<translation id="8091372947890762290">Активација је на чекању на серверу</translation>
<translation id="8094917007353911263">Мрежа коју користите ће можда захтевати да посетите <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -936,6 +973,7 @@
<translation id="8201077131113104583">Неважећи URL за ажурирање за додатак са ИД-ом „<ph name="EXTENSION_ID" />“.</translation>
<translation id="8202097416529803614">Резиме поруџбине</translation>
<translation id="8205463626947051446">Сајт приказује огласе који ометају</translation>
+<translation id="8211406090763984747">Веза је безбедна</translation>
<translation id="8218327578424803826">Додељена локација:</translation>
<translation id="8225771182978767009">Особа која је подесила овај рачунар је одлучила да блокира овај сајт.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -947,6 +985,7 @@
<translation id="825929999321470778">Прикажи све сачуване лозинке</translation>
<translation id="8261506727792406068">Избриши</translation>
<translation id="8267698848189296333">Пријављујете се као <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Пријави ме</translation>
<translation id="8288807391153049143">Прикажи сертификат</translation>
<translation id="8289355894181816810">Контактирајте администратора мреже ако нисте сигурни шта то значи.</translation>
<translation id="8293206222192510085">Додавање обележивача</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">Кредитне и припејд картице које се прихватају</translation>
<translation id="8759274551635299824">Ова картица је истекла</translation>
<translation id="8761567432415473239">Google безбедно прегледање је недавно <ph name="BEGIN_LINK" />открило штетне програме<ph name="END_LINK" /> на <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">USB уређај</translation>
<translation id="8790007591277257123">&amp;Понови брисање</translation>
<translation id="8800988563907321413">Предлози у близини ће се приказивати овде</translation>
<translation id="8820817407110198400">Обележивачи</translation>
diff --git a/chromium/components/strings/components_strings_sv.xtb b/chromium/components/strings/components_strings_sv.xtb
index efe25ea7256..6e4a1d04772 100644
--- a/chromium/components/strings/components_strings_sv.xtb
+++ b/chromium/components/strings/components_strings_sv.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">Skriv &amp;ut...</translation>
<translation id="1181037720776840403">Ta bort</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Rapportera uppgifter<ph name="END_WHITEPAPER_LINK" /> om möjliga säkerhetsincidenter till Google automatiskt. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Betalningen slutfördes inte</translation>
<translation id="1201402288615127009">Nästa</translation>
<translation id="1201895884277373915">Mer från den här webbplatsen</translation>
<translation id="1206967143813997005">Felaktig första signatur</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Felrapport skapades <ph name="CRASH_TIME" /> (har ännu inte laddats upp eller ignorerats)</translation>
<translation id="1270502636509132238">Alternativ för utlämning</translation>
<translation id="1285320974508926690">Översätt aldrig den här webbplatsen</translation>
+<translation id="1294154142200295408">Varianter på kommandoraden</translation>
<translation id="129553762522093515">Nyligen stängda</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Testa att rensa cookies<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Din aktivitet <ph name="BEGIN_EMPHASIS" />kanske fortfarande är synlig<ph name="END_EMPHASIS" /> för:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Godkända kredit- och betalkort</translation>
<translation id="1519264250979466059">Programversionsdatum</translation>
<translation id="1527263332363067270">Väntar på anslutning …</translation>
+<translation id="1532118530259321453">På den här sidan står det</translation>
<translation id="153384715582417236">Det var allt för den här gången</translation>
<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>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />kontrollera proxyn och brandväggen<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">ZIP</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 förslag}other{# förslag}}</translation>
-<translation id="2065985942032347596">Verifiering krävs</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="2091887806945687916">Ljud</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Avbryt betalningen</translation>
<translation id="2147827593068025794">Bakgrundssynkronisering</translation>
<translation id="2148613324460538318">Lägg till kort</translation>
-<translation id="2149973817440762519">Redigera bokmärke</translation>
<translation id="2154054054215849342">Synkronisering är inte tillgänglig för din domän</translation>
<translation id="2154484045852737596">Redigera kortet</translation>
<translation id="2166049586286450108">Fullständig administrativ åtkomst</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Välj hämtningsadress</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Ta bort valda objekt</translation>
-<translation id="2744590937989388266">Från en inbäddad sida på den här sidan</translation>
<translation id="277133753123645258">Fraktalternativ</translation>
<translation id="277499241957683684">Enhetsregister saknas</translation>
<translation id="2784949926578158345">Anslutningen återställdes.</translation>
<translation id="2788784517760473862">Godkända kreditkort</translation>
<translation id="2794233252405721443">Webbplatsen har blockerats</translation>
-<translation id="2795286477369100655">Vill du lämna webbplatsen?</translation>
<translation id="2799020568854403057">Det finns skadliga appar på webbplatsen du är på väg till</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="2824775600643448204">Adress- och sökfält</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Listposten <ph name="ENTRY_INDEX" />: <ph name="ERROR" /></translation>
<translation id="301521992641321250">Blockerades automatiskt</translation>
<translation id="3024663005179499861">Felaktig policytyp</translation>
-<translation id="3032412215588512954">Vill du läsa in den här webbplatsen igen?</translation>
<translation id="3037605927509011580">Oj, ett fel har uppstått!</translation>
<translation id="3039538478787849737">Vill du spara kortet hos Google?</translation>
<translation id="3041612393474885105">Certifikatinformation</translation>
@@ -310,6 +306,7 @@
kontrollera att proxyservern fungerar. Om du inte tror att du ska
använda en proxyserver:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> på <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Avbryt betalningen</translation>
<translation id="3207960819495026254">Bokmärkt</translation>
<translation id="3209375525920864198">Ange ett giltigt sessionsnamn.</translation>
@@ -367,11 +364,58 @@
<translation id="3556433843310711081">En ansvarig kan ta bort blockeringen</translation>
<translation id="3566021033012934673">Anslutningen är inte privat</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">På en inbäddad sida på <ph name="SITE" /> står det</translation>
<translation id="358285529439630156">Kreditkort och förbetalda kort kan användas.</translation>
<translation id="3582930987043644930">Lägg till namn</translation>
<translation id="3583757800736429874">&amp;Gör om Flytta</translation>
<translation id="3586931643579894722">Dölj detaljerad information</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Åtgärda anslutningsproblem&lt;/h1&gt;
+ &lt;p&gt;Om ett felmeddelande visas när du försöker besöka en webbplats testar du följande åtgärder.&lt;/p&gt;
+ &lt;h2&gt;Åtgärda de vanligaste anslutningsfelen&lt;/h2&gt;
+ &lt;p&gt;Om det inte går att öppna en webbplats testar du först om du kan åtgärda problemet på något av följande sätt:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Kontrollera att webbadressen inte innehåller stavfel.&lt;/li&gt;
+ &lt;li&gt;Kontrollera att internetanslutningen fungerar normalt.&lt;/li&gt;
+ &lt;li&gt;Kontakta webbplatsens ägare.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Få hjälp med ett felmeddelande&lt;/h2&gt;
+ &lt;h3&gt;Anslutningen är inte privat eller
+NET::ERR_CERT_AUTHORITY_INVALID eller ERR_CERT_COMMON_NAME_INVALID eller NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM eller SSL-certifikatfel&lt;/h3&gt;
+ &lt;h4&gt;Steg 1: Logga in på portalen&lt;/h4&gt;
+ &lt;p&gt;När du använder Wi-Fi-nätverk på exempelvis kaféer eller flygplatser behöver du logga in. Inloggningssidan visas om du försöker öppna en sida som använder &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Öppna en webbplats som börjar med &lt;code&gt;http://&lt;/code&gt;, till exempel &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;När inloggningssidan visas loggar du in så att du kommer ut på internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Steg 2: Öppna sidan i inkognitoläge (endast datorer)&lt;/h4&gt;
+ &lt;p&gt;Öppna sidan du försökte besöka i ett inkognitofönster.&lt;/p&gt;
+ &lt;p&gt;Om sidan öppnas är det ett tillägg i Chrome som inte fungerar som det ska. Åtgärda problemet genom att inaktivera tillägget.&lt;/p&gt;
+ &lt;h4&gt;Steg 3: Uppdatera operativsystemet&lt;/h4&gt;
+ &lt;p&gt;Kontrollera att operativsystemet på enheten är uppdaterat.&lt;/p&gt;
+ &lt;h4&gt;Steg 4: Inaktivera antivirusprogrammet tillfälligt&lt;/h4&gt;
+ &lt;p&gt;Felet visas om du har ett antivirusprogram med HTTPS-skydd eller HTTPS-genomsökning. Antivirusprogrammet stör Chromes säkerhetsfunktioner.&lt;/p&gt;
+ &lt;p&gt;Testa att stänga av antivirusprogrammet. Om sidan öppnas måste du inaktivera antivirusprogrammet när du använder säkra webbplatser.&lt;/p&gt;
+ &lt;p&gt;Glöm inte att aktivera antivirusprogrammet igen efteråt.&lt;/p&gt;
+ &lt;h4&gt;Steg 5: Få mer hjälp&lt;/h4&gt;
+ &lt;p&gt;Om felet fortfarande visas kontaktar du webbplatsens ägare.&lt;/p&gt;
+ &lt;h3&gt;Anslut till ett nätverk&lt;/h3&gt;
+ &lt;p&gt;Felet visas om du använder en Wi-Fi-portal där du måste logga in innan du kommer ut på internet.&lt;/p&gt;
+ &lt;p&gt;Åtgärda felet genom att klicka på &lt;strong&gt;Anslut&lt;/strong&gt; på sidan du försöker öppna.&lt;/p&gt;
+ &lt;h3&gt;Klockan går efter, Klockan går före eller NET::ERR_CERT_DATE_INVALID&lt;/h3&gt;
+ &lt;p&gt;Felet visas om klockan går fel eller fel datum är inställt på datorn eller den mobila enheten.&lt;/p&gt;
+ &lt;p&gt;Åtgärda felet genom att öppna klockan på enheten och ställa in rätt tid och datum.&lt;/p&gt;
+ &lt;h3&gt;Programvara på datorn förhindrar att Chrome ansluter till internet på ett säkert sätt (endast Windows-datorer)&lt;/h3&gt;
+ &lt;p&gt;Det här felmeddelandet visas om du har programvaran Superfish på Windows-datorn.&lt;/p&gt;
+ &lt;p&gt;Inaktivera programvaran tillfälligt enligt anvisningarna nedan så att du kan komma ut på internet. Du måste ha administratörsbehörighet.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Klicka på &lt;strong&gt;Start&lt;/strong&gt; och sök efter och välj &lt;strong&gt;Se lokala tjänster&lt;/strong&gt;
+ &lt;li&gt;Välj &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Under &lt;strong&gt;Startmetod&lt;/strong&gt; väljer du &lt;strong&gt;Inaktiverad&lt;/strong&gt;
+ &lt;li&gt;Under &lt;strong&gt;Tjänststatus&lt;/strong&gt; klickar du på &lt;strong&gt;Stoppa&lt;/strong&gt;
+ &lt;li&gt;Klicka på &lt;strong&gt;Verkställ&lt;/strong&gt; och sedan på &lt;strong&gt;OK&lt;/strong&gt;
+ &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="3615877443314183785">Ange ett giltigt utgångsdatum</translation>
<translation id="36224234498066874">Rensa webbinformation ...</translation>
<translation id="362276910939193118">Visa fullständig historik</translation>
@@ -404,7 +448,6 @@
<translation id="3778403066972421603">Vill du spara det här kortet i Google-kontot och på den här enheten?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Utgångsdatum: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Från <ph name="SITE" /></translation>
<translation id="382518646247711829">Om du använder en proxyserver ...</translation>
<translation id="3828924085048779000">Lösenfrasen får inte vara tom.</translation>
<translation id="385051799172605136">Bakåt</translation>
@@ -418,6 +461,7 @@
<translation id="3945915738023014686">Id i den uppladdade felrapporten <ph name="CRASH_ID" /> (Lokalt krasch-id: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Servern kunde inte bevisa att den är <ph name="DOMAIN" /> eftersom inga alternativa namn på certifikatobjektet anges i säkerhetscertifikatet. Detta kan bero på en felaktig konfigurering eller att en angripare manipulerat anslutningen.</translation>
<translation id="3949601375789751990">Webbhistoriken visas här</translation>
+<translation id="3950820424414687140">Logga in</translation>
<translation id="3963721102035795474">Läsarläge</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Ingen}=1{Från 1 webbplats }other{Från # webbplatser }}</translation>
<translation id="397105322502079400">Beräknar ...</translation>
@@ -434,6 +478,7 @@
<translation id="4103249731201008433">Enhetens serienummer är ogiltigt</translation>
<translation id="410351446219883937">Automatisk uppspelning</translation>
<translation id="4103763322291513355">Besök &lt;strong&gt;chrome://policy&lt;/strong&gt; om du vill visa listan med webbadresser som inte är godkända och andra policyer som angetts av systemadministratören.</translation>
+<translation id="4110652170750985508">Granska betalningen</translation>
<translation id="4116663294526079822">Tillåt alltid på den här webbplatsen</translation>
<translation id="4117700440116928470">Principens omfattning stöds inte.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 till}other{# till}}</translation>
@@ -460,7 +505,6 @@
<translation id="4269787794583293679">(Inget användarnamn)</translation>
<translation id="4275830172053184480">Starta om enheten</translation>
<translation id="4280429058323657511">, utgångsdatum <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Logga in</translation>
<translation id="4312866146174492540">Blockera (standard)</translation>
<translation id="4325863107915753736">Det gick inte att hitta artikeln</translation>
<translation id="4326324639298822553">Kontrollera utgångsdatum och försök igen</translation>
@@ -482,14 +526,12 @@
<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="4522570452068850558">Info</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Från en inbäddad sida på <ph name="SITE" /></translation>
<translation id="4558551763791394412">Testa att inaktivera tilläggen.</translation>
<translation id="457875822857220463">Leverans</translation>
<translation id="4582800630050655161">Du kan förlora tillgången till Google-kontot eller bli utsatt för identitetsstöld. Du rekommenderas att ändra lösenordet nu.</translation>
<translation id="4587425331216688090">Vill du ta bort adressen från Chrome?</translation>
<translation id="4592951414987517459">Anslutningen till <ph name="DOMAIN" /> är krypterad med en modern krypteringssvit.</translation>
<translation id="4594403342090139922">&amp;Ångra Ta bort</translation>
-<translation id="4611292653554630842">Logga in</translation>
<translation id="4619615317237390068">Flikar från andra enheter</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Servern kunde inte bevisa att den är <ph name="DOMAIN" /> eftersom dess säkerhetscertifikat innehåller fel. Detta kan orsakas av en felaktig konfigurering eller att någon spärrar anslutningen.</translation>
@@ -499,11 +541,9 @@
<translation id="4708268264240856090">Anslutningen avbröts</translation>
<translation id="471880041731876836">Du har inte behörighet att besöka den här webbplatsen.</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" /> köra nätverksdiagnostik för Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Din betalning</translation>
<translation id="4726672564094551039">Läs in policyer på nytt</translation>
<translation id="4728558894243024398">Plattform</translation>
<translation id="4736825316280949806">Starta om Chromium</translation>
-<translation id="4737498291095696011">Från den här sidan</translation>
<translation id="4744603770635761495">Sökväg till körbar fil</translation>
<translation id="4749685221585524849">Användes senast den <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Dina uppgifter (till exempel lösenord eller kreditkortsnummer) är privata när de skickas till den här webbplatsen.</translation>
@@ -522,16 +562,16 @@
<translation id="4850886885716139402">Visa</translation>
<translation id="4854362297993841467">Det här leveranssättet är inte tillgängligt. Testa ett annat alternativ.</translation>
<translation id="4858792381671956233">Du har frågat dina föräldrar om lov att besöka den här webbplatsen.</translation>
-<translation id="4871132632506079383">Från en inbäddad sida på <ph name="SITE" /></translation>
<translation id="4880827082731008257">Sök i historiken</translation>
+<translation id="4881695831933465202">Öppna</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Autentisering krävs</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{och en till webbsida}other{och # till webbsidor}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
-<translation id="4919958102839282947">Ange CVC-koden för <ph name="CREDIT_CARD" />. När du bekräftar delas kortuppgifter från Google betalningskonto med webbplatsen.</translation>
+<translation id="4919958102839282947">Ange CVC-koden för <ph name="CREDIT_CARD" />. När du bekräftar delas kortuppgifter från Google Paymens-betalningskonto med webbplatsen.</translation>
<translation id="4923417429809017348">Sidan har översatts från ett okänt språk till <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Betalning</translation>
<translation id="4926049483395192435">Värdet måste anges.</translation>
+<translation id="4926159001844873046">Från <ph name="SITE" />:</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Åtgärder</translation>
<translation id="4958444002117714549">Expandera lista</translation>
@@ -540,7 +580,6 @@
<translation id="5002932099480077015">Om alternativet är aktiverat sparar Chrome en kopia av kortet på enheten så att det går snabbare att fylla i formulär.</translation>
<translation id="5018422839182700155">Det går inte att öppna den här sidan</translation>
<translation id="5019198164206649151">Säkerhetskopian har dålig status</translation>
-<translation id="5020990877659450221">Från den här sidan</translation>
<translation id="5023310440958281426">Kontrollera administratörsprinciperna</translation>
<translation id="5029568752722684782">Ta bort kopia</translation>
<translation id="503069730517007720">Ett rotcertifikat för <ph name="SOFTWARE_NAME" /> krävs men har inte installerats. IT-administratören bör granska konfigurationsanvisningarna för <ph name="SOFTWARE_NAME" /> och åtgärda problemet. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -557,7 +596,7 @@
<translation id="5094747076828555589">Servern kunde inte bevisa att den är <ph name="DOMAIN" /> eftersom Chromium inte litar på dess säkerhetscertifikat. Detta kan orsakas av en felaktig konfigurering eller att någon spärrar anslutningen.</translation>
<translation id="5095208057601539847">Provins</translation>
<translation id="5115563688576182185">(64 bitar)</translation>
-<translation id="5121084798328133320">När du bekräftar delas kortuppgifter från Google betalningskonto med webbplatsen.</translation>
+<translation id="5121084798328133320">När du bekräftar delas kortuppgifter från Google Payments-konto med webbplatsen.</translation>
<translation id="5128122789703661928">Sessionen med det här namnet går inte att radera.</translation>
<translation id="5141240743006678641">Kryptera synkroniserade lösenord med dina inloggningsuppgifter för Google</translation>
<translation id="5145883236150621069">Felkoden ingår i policysvaret</translation>
@@ -566,12 +605,12 @@
<translation id="5172758083709347301">Dator</translation>
<translation id="5179510805599951267">Inte på <ph name="ORIGINAL_LANGUAGE" />? Rapportera felet</translation>
<translation id="5190835502935405962">Bokmärkesfältet</translation>
+<translation id="5201306358585911203">På en inbäddad sida på den här sidan står det</translation>
<translation id="5205222826937269299">Namn måste anges</translation>
<translation id="5222812217790122047">E-postadress måste anges</translation>
<translation id="522700295135997067">Webbplatsen kan ha stulit ditt lösenord</translation>
<translation id="5230733896359313003">Leveransadress</translation>
<translation id="5251803541071282808">Moln</translation>
-<translation id="5277279256032773186">Använder du Chrome på jobbet? Företag kan hantera de anställdas inställningar i Chrome. Läs mer</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Följ stegen nedan för att inaktivera programvaran tillfälligt så att du kan komma ut på internet. Du måste ha administratörsbehörighet.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +672,6 @@
<translation id="5610142619324316209">kontrollera anslutningen</translation>
<translation id="5610807607761827392">Du hanterar kort och adresser under <ph name="BEGIN_LINK" />Inställningar<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> omdirigerade dig för många gånger.</translation>
-<translation id="5622887735448669177">Vill du lämna den här webbplatsen?</translation>
<translation id="5629630648637658800">Det gick inte att läsa in policyinställningarna</translation>
<translation id="5631439013527180824">Ogiltig enhetshanteringstoken</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>
@@ -656,7 +694,6 @@
<translation id="5786044859038896871">Vill du att kortuppgifterna ska fyllas i?</translation>
<translation id="5803412860119678065">Vill du att uppgifterna om <ph name="CARD_DETAIL" /> ska fyllas i?</translation>
<translation id="5810442152076338065">Anslutningen till <ph name="DOMAIN" /> är krypterad med en gammal krypteringssvit.</translation>
-<translation id="5810928923025889964">Från en inbäddad sida på den här sidan</translation>
<translation id="5813119285467412249">&amp;Gör om Lägg till</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>
<translation id="5866257070973731571">Ange telefonnummer</translation>
@@ -730,21 +767,19 @@
<translation id="6446608382365791566">Lägg till mer information</translation>
<translation id="6447842834002726250">Cookies</translation>
<translation id="6451458296329894277">Bekräfta återsändning av formulär</translation>
-<translation id="6456339708790392414">Din betalning</translation>
<translation id="647261751007945333">Enhetspolicyer</translation>
<translation id="6477321094435799029">Chrome har identifierat ovanlig kod på sidan och blockerat den för att skydda dina personliga uppgifter (som lösenord, telefonnummer och kreditkortsuppgifter).</translation>
<translation id="6489534406876378309">Börja överföra information om krascher</translation>
<translation id="6507833130742554667">Kreditkort och betalkort får användas.</translation>
<translation id="6508722015517270189">Starta om Chrome</translation>
-<translation id="6521373090216409766">Vill du läsa in webbplatsen igen?</translation>
<translation id="6529602333819889595">&amp;Gör om Ta bort</translation>
<translation id="6534179046333460208">Förslag från Physical Web</translation>
<translation id="6550675742724504774">Alternativ</translation>
-<translation id="6556239504065605927">Säker anslutning</translation>
<translation id="6556915248009097796">Giltigt till: <ph name="EXPIRATION_DATE_ABBR" />, användes senast den <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Den ansvarige har inte godkänt den ännu</translation>
<translation id="6569060085658103619">Du visar en tilläggssida</translation>
<translation id="6596325263575161958">Krypteringsalternativ</translation>
+<translation id="6604181099783169992">Rörelse- eller ljussensorer</translation>
<translation id="6624427990725312378">Kontaktuppgifter</translation>
<translation id="6626291197371920147">Lägg till ett giltigt kortnummer</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Sök</translation>
@@ -816,6 +851,7 @@
<translation id="7275334191706090484">Hanterade bokmärken</translation>
<translation id="7298195798382681320">Rekommenderas</translation>
<translation id="7309308571273880165">Felrapport som skapades <ph name="CRASH_TIME" /> (uppladdning begärdes av användaren, har ännu inte laddats upp)</translation>
+<translation id="7320336641823683070">Anslutningshjälp</translation>
<translation id="7334320624316649418">&amp;Gör om Ändra ordning</translation>
<translation id="733923710415886693">Servercertifikatet har inte lämnats ut via Certifikattransparens.</translation>
<translation id="7353601530677266744">Kommandorad</translation>
@@ -900,6 +936,7 @@
<translation id="782886543891417279">Wi-Fi-nätverket du använder (<ph name="WIFI_NAME" />) kanske kräver att du besöker dess inloggningssida.</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="7862185352068345852">Vill du lämna webbplatsen?</translation>
<translation id="7878176543348854470">Betalkort och förbetalda kort får användas.</translation>
<translation id="7878562273885520351">Lösenordet kan vara utsatt för risk</translation>
<translation id="7887683347370398519">Kontrollera CVC-koden och försök igen</translation>
@@ -922,6 +959,7 @@
<translation id="8041940743680923270">Använd global standardinställning (Fråga)</translation>
<translation id="8042918947222776840">Välj hämtningsalternativ</translation>
<translation id="8057711352706143257"><ph name="SOFTWARE_NAME" /> har inte konfigurerats korrekt. Ofta hjälper det att avinstallera <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Vill du läsa in webbplatsen igen?</translation>
<translation id="8088680233425245692">Det gick inte att visa artikeln.</translation>
<translation id="8091372947890762290">Aktiveringen väntar på servern</translation>
<translation id="8094917007353911263">Nätverket du använder kanske kräver att du besöker <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +975,7 @@
<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>
<translation id="8205463626947051446">Webbplatsen brukar visa påträngande annonser</translation>
+<translation id="8211406090763984747">Anslutningen är säker</translation>
<translation id="8218327578424803826">Tilldelad plats:</translation>
<translation id="8225771182978767009">Personen som konfigurerade datorn har valt att blockera den här webbplatsen.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +987,7 @@
<translation id="825929999321470778">Visa alla sparade lösenord</translation>
<translation id="8261506727792406068">Radera</translation>
<translation id="8267698848189296333">Loggar in som <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Logga in</translation>
<translation id="8288807391153049143">Visa certifikat</translation>
<translation id="8289355894181816810">Kontakta din nätverksadministratör om du är osäker på vad det här innebär.</translation>
<translation id="8293206222192510085">Lägg till bokmärke</translation>
@@ -999,6 +1039,7 @@
<translation id="874846938927089722">Godkända kreditkort och förbetalda kort</translation>
<translation id="8759274551635299824">Kortets giltighetstid har löpt ut</translation>
<translation id="8761567432415473239">Googles tjänst Säker webbsökning <ph name="BEGIN_LINK" />hittade skadliga program<ph name="END_LINK" /> på <ph name="SITE" /> nyligen.</translation>
+<translation id="8763927697961133303">USB-enhet</translation>
<translation id="8790007591277257123">&amp;Gör om Ta bort</translation>
<translation id="8800988563907321413">Förslag på webbsidor i närheten visas här</translation>
<translation id="8820817407110198400">Bokmärken</translation>
@@ -1016,7 +1057,7 @@
<translation id="8932102934695377596">Klockan går efter</translation>
<translation id="893332455753468063">Lägg till namn</translation>
<translation id="8938939909778640821">Godkända kreditkort och förbetalda kort</translation>
-<translation id="8952525071319348207">Uppdatera kortinformationen genom att ange utgångsdatumet och CVC-koden för <ph name="CREDIT_CARD" />. När du bekräftar delas kortuppgifter från Google betalningskonto med webbplatsen.</translation>
+<translation id="8952525071319348207">Uppdatera kortinformationen genom att ange utgångsdatumet och CVC-koden för <ph name="CREDIT_CARD" />. När du bekräftar delas kortuppgifter från Google Payments-konto med webbplatsen.</translation>
<translation id="8957210676456822347">Auktorisering av infångstportal</translation>
<translation id="8971063699422889582">Servercertifikatet har gått ut.</translation>
<translation id="8978053250194585037"><ph name="BEGIN_LINK" />Nätfiske<ph name="END_LINK" /> upptäcktes nyligen av Google Säker webbsökning på <ph name="SITE" />. Webbplatser som används för nätfiske imiterar andra webbplatser i syfte att lura dig.</translation>
diff --git a/chromium/components/strings/components_strings_sw.xtb b/chromium/components/strings/components_strings_sw.xtb
index 2160df18791..8d5f4e52af1 100644
--- a/chromium/components/strings/components_strings_sw.xtb
+++ b/chromium/components/strings/components_strings_sw.xtb
@@ -25,13 +25,12 @@
<translation id="1150979032973867961">Seva hii haikuweza kuthibitisha kuwa ni <ph name="DOMAIN" />; cheti chake cha usalama hakiaminiwi na mfumo wa uendeshaji wa kompyuta yako. Hii inaweza kusababishwa na usanidi usiofaa au mvamizi kuingilia muunganisho wako.</translation>
<translation id="1151972924205500581">Nenosiri linahitajika</translation>
<translation id="1152921474424827756">Fikia <ph name="BEGIN_LINK" />nakala iliyowekwa kwenye akiba<ph name="END_LINK" /> ya <ph name="URL" /></translation>
-<translation id="1158211211994409885"><ph name="HOST_NAME" /> ilifunga muunganisho bila kutarajia.</translation>
+<translation id="1158211211994409885"><ph name="HOST_NAME" /> imefunga muunganisho bila kutarajiwa.</translation>
<translation id="1161325031994447685">Kuunganisha tena kwenye Wi-Fi</translation>
<translation id="1165039591588034296">Hitilafu</translation>
<translation id="1175364870820465910">&amp;Chapisha...</translation>
<translation id="1181037720776840403">Ondoa</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Ripoti kiotomatiki<ph name="END_WHITEPAPER_LINK" /> kwa Google kuhusu maelezo ya uwezekano wa matukio yasiyo salama. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Malipo Hayajakamilika</translation>
<translation id="1201402288615127009">Ifuatayo</translation>
<translation id="1201895884277373915">Zaidi kutoka kwenye tovuti hii</translation>
<translation id="1206967143813997005">Sahihi mbaya ya mwanzo</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Ripoti ya kuacha kufanya kazi iliyochukuliwa <ph name="CRASH_TIME" /> (haijapakiwa au imepuuzwa)</translation>
<translation id="1270502636509132238">Mbinu ya Kuchukua</translation>
<translation id="1285320974508926690">Kamwe usitafsiri tovuti hii</translation>
+<translation id="1294154142200295408">Tofauti za miundo ya amri</translation>
<translation id="129553762522093515">Vilivyofungwa hivi karibuni</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Jaribu kufuta vidakuzi kwenye kivinjari chako<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Huenda bado shughuli zako <ph name="BEGIN_EMPHASIS" />Zitaonwa<ph name="END_EMPHASIS" /> na:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Kadi za mikopo na za malipo zinazokubaliwa</translation>
<translation id="1519264250979466059">Unda Tarehe</translation>
<translation id="1527263332363067270">Inasubiri muunganisho...</translation>
+<translation id="1532118530259321453">Ukurasa huu unasema</translation>
<translation id="153384715582417236">Hayo yanatosha kwa sasa</translation>
<translation id="154408704832528245">Chagua Mahali Bidhaa Itakapopelekwa</translation>
<translation id="1549470594296187301">Lazima JavaScript iwashwe ili utumie kipengele hiki.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Kuangalia seva mbadala na kinga-mtandao<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Msimbo wa eneo</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{Pendekezo 1}other{Mapendekezo #}}</translation>
-<translation id="2065985942032347596">Uthibitishaji Unahitajika</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="2091887806945687916">Sauti</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Ghairi malipo</translation>
<translation id="2147827593068025794">Usawazishaji wa Chini Chini</translation>
<translation id="2148613324460538318">Ongeza Kadi</translation>
-<translation id="2149973817440762519">Badilisha Alamisho</translation>
<translation id="2154054054215849342">Huduma ya usawazishaji haipatikani kwa ajili ya kikoa chako</translation>
<translation id="2154484045852737596">Badilisha kadi</translation>
<translation id="2166049586286450108">Idhini Kamili ya Kufikia ya Msimamizi</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Chagua Anwani ya Mahali pa Kuchukulia Bidhaa</translation>
<translation id="2740531572673183784">Sawa</translation>
<translation id="2742870351467570537">Ondoa vipengee vilivyochaguliwa</translation>
-<translation id="2744590937989388266">Kutoka Ukurasa Uliopachikwa kwenye Ukurasa Huu</translation>
<translation id="277133753123645258">Mbinu ya usafirishaji</translation>
<translation id="277499241957683684">Rekodi ya kifaa inayokosekana</translation>
<translation id="2784949926578158345">Muunganisho uliwekwa upya.</translation>
<translation id="2788784517760473862">Kadi za malipo zinazokubaliwa</translation>
<translation id="2794233252405721443">Tovuti imezuiwa</translation>
-<translation id="2795286477369100655">Ungependa Kufunga Tovuti Hii?</translation>
<translation id="2799020568854403057">Kuna programu hasidi kwenye tovuti unayotaka kuifungua</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="2824775600643448204">Upau wa anwani na utafutaji</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Ingizo orodha "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Imezuiwa kiotomatiki</translation>
<translation id="3024663005179499861">Aina mbaya ya sera</translation>
-<translation id="3032412215588512954">Ungependa kupakia upya tovuti hii?</translation>
<translation id="3037605927509011580">Lo!</translation>
<translation id="3039538478787849737">Ungependa kuhifadhi kadi hii kwenye Google?</translation>
<translation id="3041612393474885105">Maelezo ya Cheti</translation>
@@ -310,6 +306,7 @@
kuhakikisha kuwa seva mbadala inafanya kazi. Ikiwa huamini kwamba unapaswa kuwa
ukitumia seva mbadala:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> kwenye <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Ghairi Malipo</translation>
<translation id="3207960819495026254">Imealamishwa</translation>
<translation id="3209375525920864198">Tafadhali andika jina sahihi la kipindi.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Msimamizi wako anaweza kukuondolea kizuizi</translation>
<translation id="3566021033012934673">Muunganisho wako si wa faragha</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Ukurasa uliopachikwa kwenye <ph name="SITE" /> unasema</translation>
<translation id="358285529439630156">Kadi za mikopo na za kulipia awali zinazokubaliwa.</translation>
<translation id="3582930987043644930">Ongeza jina</translation>
<translation id="3583757800736429874">Rudia Hatua</translation>
<translation id="3586931643579894722">Ficha maelezo</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">K&lt;h1&gt;Rekebisha hitilafu za muunganisho&lt;/h1&gt;
+ &lt;p&gt;Ukipata ujumbe wa hitilafu unapojaribu kutembelea tovuti, jaribu marekebisho haya.&lt;/p&gt;
+ &lt;h2&gt;Rekebisha hitilafu nyingi za muunganisho&lt;/h2&gt;
+ &lt;p&gt;Kama unajaribu kutembelea tovuti na haifunguki, jaribu kwanza kurekebisha hitilafu kwa kufuata hatua hizi za utatuzi:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Angalia makosa ya tahajia kwenye anwani ya tovuti.&lt;/li&gt;
+ &lt;li&gt;Hakikisha kuwa muunganisho wako wa intaneti unafanya kazi kama kawaida.&lt;/li&gt;
+ &lt;li&gt;Wasiliana na mmiliki wa tovuti.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Pata usaidizi kuhusu ujumbe wa hitilafu mahususi&lt;/h2&gt;
+ &lt;h3&gt;"Muunganisho wako si wa faragha" au "NET::ERR_CERT_AUTHORITY_INVALID" au "ERR_CERT_COMMON_NAME_INVALID" au "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" au "kuna hitilafu ya cheti cha SSL"&lt;/h3&gt;
+ &lt;h4&gt;Hatua ya 1: Ingia katika akaunti ya tovuti&lt;/h4&gt;
+ &lt;p&gt;Unatakiwa uingie katika akaunti ikiwa unatumia mitandao ya Wi-Fi katika maeneo kama vile mikahawa au viwanja vya ndege. Ili uangalie ukurasa wa kuingia katika akaunti, tembelea ukurasa ambao unatumia&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Nenda kwenye tovuti yoyote inayoanza kwa &lt;code&gt;http://&lt;/code&gt;, kama vile &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Ingia katika akaunti ili utumie intaneti kupitia ukurasa wa kuingia katika akaunti unaofunguka, .&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Hatua ya 2: Fungua ukurasa katika Hali fiche (kwenye kompyuta pekee)&lt;/h4&gt;
+ &lt;p&gt;Fungua ukurasa uliokuwa unatembelea katika Dirisha Fiche.&lt;/p&gt;
+ &lt;p&gt;Ukurasa ukifunguka, itamaanisha kuwa kiendelezi cha Chrome hakifanyi kazi vizuri. Zima kiendelezi ili urekebishe hitilafu hii.&lt;/p&gt;
+ &lt;h4&gt;Hatua ya 3: Sasisha mfumo wako wa uendeshaji&lt;/h4&gt;
+ &lt;p&gt;Hakikisha kuwa kifaa chako kinatumia toleo jipya.&lt;/p&gt;
+ &lt;h4&gt;Hatua ya 4: Zima kingavirusi yako kwa muda&lt;/h4&gt;
+ &lt;p&gt;Utaona hitilafu hii kama una programu ya kingavirusi ambayo inatoa "ulinzi wa HTTPS" au "ukaguzi wa HTTPS." Kingavirusi inazuia Chrome kudumisha usalama.&lt;/p&gt;
+ &lt;p&gt;Zima programu yako ya kingavirusi yako ili urekebishe tatizo hili. Kama ukurasa utafanya kazi baada ya kuzima programu, washa programu hii wakati utatumia tovuti salama.&lt;/p&gt;
+ &lt;p&gt;Kumbuka kuwasha tena programu yako ya kingavirusi unapomaliza.&lt;/p&gt;
+ &lt;h4&gt;Hatua ya 5: Pata usaidizi zaidi&lt;/h4&gt;
+ &lt;p&gt;Kama bado unaona hitilafu, wasiliana na mmiliki wa tovuti.&lt;/p&gt;
+ &lt;h3&gt;"Unganisha kwenye mtandao"&lt;/h3&gt;
+ &lt;p&gt;Utaona hitilafu hii kama utatumia mtandao Wi-Fi ambapo utatakiwa uingie 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 kuufungua.&lt;/p&gt;
+ &lt;h3&gt;"Saa yako iko nyuma" au "Saa yako iko mbele" au "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Utaona hitilafu hii ikiwa saa na tarehe kwenye kompyuta au kifaa chako si sahihi.&lt;/p&gt;
+ &lt;p&gt;Fungua saa ya kifaa chako ili urekebishe hitilafu hii. Hakikisha kuwa saa na tarehe ni sahihi.&lt;/p&gt;
+ &lt;h3&gt;"Programu kwenye kompyuta yako inazuia Chrome isiunganishe kwenye wavuti kwa njia salama" (Kompyuta za Windows pekee)&lt;/h3&gt;
+ &lt;p&gt;Utaona ujumbe huu wa hitilafu ikiwa una programu ya Superfish kwenye kompyuta yako ya Windows.&lt;/p&gt;
+ &lt;p&gt;Fuata hatua hizi ili uzime progamu kwa muda na uweze kufikia wavuti. Utahitaji haki za msimamizi.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Bofya &lt;strong&gt;Anza&lt;/strong&gt;, kisha tafuta na uchague&lt;strong&gt;"Angalia huduma za ndani"&lt;/strong&gt;
+ &lt;li&gt;Chagua &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Chini ya &lt;strong&gt;Aina ya kuanzisha&lt;/strong&gt;, Chagua &lt;strong&gt;Imezimwa&lt;/strong&gt;
+ &lt;li&gt;Chini ya &lt;strong&gt;Hali ya huduma&lt;/strong&gt;, bofya &lt;strong&gt;Simamisha&lt;/strong&gt;
+ &lt;li&gt;Bofya &lt;strong&gt;Weka&lt;/strong&gt;, kisha ubofye &lt;strong&gt;SAWA&lt;/strong&gt;
+ &lt;li&gt;Tembelea &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Kituo cha usaidizi cha Chrome&lt;/a&gt; ili upate maelezo zaidi kuhusu jinsi ya kuondoa kabisa programu kwenye kompyuta yako
+ &lt;/ol&gt;</translation>
<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>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Je, ungependa kuhifadhi kadi hii kwenye Akaunti yako ya Google na kwenye kifaa hiki?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Muda wa matumizi utakwisha <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Kutoka tovuti ya <ph name="SITE" /></translation>
<translation id="382518646247711829">Ukitumia seva mbadala...</translation>
<translation id="3828924085048779000">Kaulisiri tupu hairuhusiwi.</translation>
<translation id="385051799172605136">Nyuma</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">Kitambulisho cha Ripoti ya Kuacha Kufanya Kazi Kilichopakiwa <ph name="CRASH_ID" /> (Kitambulisho cha Kuacha Kufanya Kazi cha Ndani ya Kifaa: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Seva hii haikuweza kuthibitisha kuwa ni <ph name="DOMAIN" />; cheti chake cha usalama hakibainishi Majina Mbadala ya Mada. Hii inaweza kusababishwa na uwekaji mipangilio usiofaa au muunganisho wako kukatwa na mvamizi.</translation>
<translation id="3949601375789751990">Historia yako ya kuvinjari itaonekana hapa</translation>
+<translation id="3950820424414687140">Ingia</translation>
<translation id="3963721102035795474">Hali ya Usomaji</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Hamna}=1{Kutoka kwenye tovuti 1 }other{Kutoka kwenye tovuti # }}</translation>
<translation id="397105322502079400">Inakokotoa...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Namabari tambulishi ya kifaa ni batili</translation>
<translation id="410351446219883937">Kucheza kiotomatiki</translation>
<translation id="4103763322291513355">Tembelea &lt;strong&gt;chrome://policy&lt;/strong&gt; ili kuona orodha ya URL zilizoondolewa idhini na sera zingine zinazosimamiwa na msimamizi wako wa mfumo.</translation>
+<translation id="4110652170750985508">Kagua malipo yako</translation>
<translation id="4116663294526079822">Ruhusu mara kwa mara kwenye tovuti hii</translation>
<translation id="4117700440116928470">Upeo wa sera hauwezi kutumika.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{Nyingine 1 }other{Nyingine #}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Hakuna jina la mtumiaji)</translation>
<translation id="4275830172053184480">Washa upya kifaa chako</translation>
<translation id="4280429058323657511">, muda wa kutumika utakwisha <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Ingia</translation>
<translation id="4312866146174492540">Zuia (chaguo-msingi)</translation>
<translation id="4325863107915753736">Haikupata makala</translation>
<translation id="4326324639298822553">Angalia tarehe kuisha kwa muda wa matumizi halafu ujajibu tena</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Kadi na anwani zinatoka Chrome na Akaunti yako ya Google (<ph name="ACCOUNT_EMAIL" />). Unaweza kuzidhibiti katika <ph name="BEGIN_LINK" />Mipangilio<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Maelezo</translation>
<translation id="4552089082226364758">Mmweko</translation>
-<translation id="4554702541363482291">Kutoka Ukurasa Uliopachikwa kwenye <ph name="SITE" /></translation>
<translation id="4558551763791394412">Jaribu kuzima viendelezi vyako.</translation>
<translation id="457875822857220463">Usafirishaji</translation>
<translation id="4582800630050655161">Unaweza kupoteza uwezo wa kufikia Akaunti yako ya Google au kuibiwa utambulisho. Chromium inapendekeza ubadilishe nenosiri lako la sasa.</translation>
<translation id="4587425331216688090">Ungependa kuondoa anwani kutoka kwenye Chrome?</translation>
<translation id="4592951414987517459">Muunganisho wako kwenye <ph name="DOMAIN" /> umesimbwa kwa njia fiche kwa kutumia mipangilio ya kriptografia ya kisasa.</translation>
<translation id="4594403342090139922">Tendua Kufuta</translation>
-<translation id="4611292653554630842">Ingia katika akaunti</translation>
<translation id="4619615317237390068">Vichupo kutoka kwenye vifaa vingine</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Seva hii haikuweza kuthibitisha kuwa ni <ph name="DOMAIN" />; cheti chake cha usalama kina hitilafu. Hii inaweza kusababishwa na usanidi usiofaa au mvamizi kuingilia muunganisho wako.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Muunganisho wako umekatizwa</translation>
<translation id="471880041731876836">Huna ruhusa ya kutembelea tovuti hii</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Kuendesha Zana ya Windows ya Kuchunguza Mtandao<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Malipo yako</translation>
<translation id="4726672564094551039">Pakia sera upya</translation>
<translation id="4728558894243024398">Mfumo wa uendeshaji</translation>
<translation id="4736825316280949806">Zima na uwashe Chromium</translation>
-<translation id="4737498291095696011">Kutoka Ukurasa Huu</translation>
<translation id="4744603770635761495">Njia Tekelezi</translation>
<translation id="4749685221585524849">Mara ya mwisho ilitumika <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Maelezo yako (kwa mfano, manenosiri, au nambari za kadi za mikopo) ni ya faragha yanapotumwa kwenye tovuti hii.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Mwonekano</translation>
<translation id="4854362297993841467">Njia hii ya kusafirisha haitumiki. Jaribu njia tofauti.</translation>
<translation id="4858792381671956233">Umewaomba wazazi wako ruhusa ya kuutembelea ukurasa huu.</translation>
-<translation id="4871132632506079383">Kutoka ukurasa uliopachikwa kwenye <ph name="SITE" /></translation>
<translation id="4880827082731008257">Tafuta katika historia</translation>
+<translation id="4881695831933465202">Fungua</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Unahitaji kuthibitisha</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{na ukurasa 1 zaidi wa wavuti}other{na kurasa # zaidi za wavuti}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Weka CVC ya <ph name="CREDIT_CARD" />. Baada ya kuthibitisha, maelezo ya kadi kutoka akaunti yako ya malipo ya Google yatashirikiwa na tovuti hii.</translation>
<translation id="4923417429809017348">Ukurasa huu umetafsiriwa kutoka katika lugha ambayo haijulikani hadi <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Malipo</translation>
<translation id="4926049483395192435">Sharti ibainishwe.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> inasema</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Vitendo</translation>
<translation id="4958444002117714549">Panua orodha</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Ikiwashwa, Chrome itahifadhi nakala ya kadi yako kwenye kifaa hiki kwa ajili ya kujaza fomu haraka zaidi.</translation>
<translation id="5018422839182700155">Ukurasa huu haufunguki</translation>
<translation id="5019198164206649151">Hifadhi la kucheleza liko katika hali mbaya</translation>
-<translation id="5020990877659450221">Kutoka ukurasa huu</translation>
<translation id="5023310440958281426">Angalia sera za msimamizi wako</translation>
<translation id="5029568752722684782">Futa nakala</translation>
<translation id="503069730517007720">Cheti cha msingi cha "<ph name="SOFTWARE_NAME" />" kinahitajika lakini hakijasakinishwa. Ni lazima msimamizi wako wa TEHAMA asome mipangilio ya "<ph name="SOFTWARE_NAME" />" ili atatue tatizo hili. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Mashine</translation>
<translation id="5179510805599951267">Haiko katika <ph name="ORIGINAL_LANGUAGE" />? Ripoti hitilafu hii</translation>
<translation id="5190835502935405962">Sehemu ya Alamisho</translation>
+<translation id="5201306358585911203">Ukurasa uliopachikwa kwenye ukurasa huu unasema</translation>
<translation id="5205222826937269299">Jina linahitajika</translation>
<translation id="5222812217790122047">Anwani ya barua pepe inahitajika</translation>
<translation id="522700295135997067">Huenda tovuti hii imeiba nenosiri lako</translation>
<translation id="5230733896359313003">Anwani ya Mahali Bidhaa Zitakapopelekwa</translation>
<translation id="5251803541071282808">Wingu</translation>
-<translation id="5277279256032773186">Je, unatumia Chrome kazini? Kampuni zinaweza kudhibiti mipangilio ya Chrome ya wafanyikazi wao. Pata maelezo zaidi</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Zifuate hatua hizi za kuisitisha programu kwa muda ili ufike kwenye wavuti. Utahitaji mamlaka ya msimamizi.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Kuangalia muunganisho</translation>
<translation id="5610807607761827392">Unaweza kudhibiti maelezo ya kadi na anwani katika <ph name="BEGIN_LINK" />Mipangilio<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> imekuelekeza upya mara nyingi mno.</translation>
-<translation id="5622887735448669177">Ungependa kuondoka kwenye tovuti hii?</translation>
<translation id="5629630648637658800">Imeshindwa kupakia mipangilio ya sera</translation>
<translation id="5631439013527180824">Ishara ya usimamizi wa kifaa batili</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Ungependa kujaza maelezo ya kadi yako?</translation>
<translation id="5803412860119678065">Ungependa kujaza maelezo ya <ph name="CARD_DETAIL" /> yako?</translation>
<translation id="5810442152076338065">Muunganisho wako kwenye <ph name="DOMAIN" /> umesimbwa kwa njia fiche kwa kutumia mipangilio ya kriptografia ya zamani.</translation>
-<translation id="5810928923025889964">Kutoka ukurasa uliopachikwa kwenye ukurasa huu</translation>
<translation id="5813119285467412249">Rudia Kuongeza</translation>
<translation id="5838278095973806738">Hupaswi kuweka maelezo nyeti kwenye tovuti hii (kwa mfano, manenosiri au kadi za mikopo), kwa sababu wavamizi wanaweza kuyaiba.</translation>
<translation id="5866257070973731571">Ongeza Nambari ya Simu</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Ongeza maelezo zaidi</translation>
<translation id="6447842834002726250">Vidakuzi</translation>
<translation id="6451458296329894277">Thibitisha kuwa Fomu Iwasilishwe Tena</translation>
-<translation id="6456339708790392414">Malipo Yako</translation>
<translation id="647261751007945333">Sera za kifaa</translation>
<translation id="6477321094435799029">Chrome imegundua nambari ya kuthibitisha isiyo ya kawaida kwenye ukurasa huu na ikaizuia ili kulinda maelezo ya binafsi (kwa mfano, manenosiri, nambari za simu na kadi za mikopo).</translation>
<translation id="6489534406876378309">Anza kupakia matukio ya kuacha kufanya kazi</translation>
<translation id="6507833130742554667">Kadi za mikopo na malipo zinakubaliwa.</translation>
<translation id="6508722015517270189">Zima na uwashe Chrome</translation>
-<translation id="6521373090216409766">Ungependa Kupakia upya Tovuti Hii?</translation>
<translation id="6529602333819889595">Rudia Kufuta</translation>
<translation id="6534179046333460208">Mapendekezo ya Wavuti kila Mahali</translation>
<translation id="6550675742724504774">Chaguo</translation>
-<translation id="6556239504065605927">Muunganisho salama</translation>
<translation id="6556915248009097796">Muda wa kutumika utakwisha: <ph name="EXPIRATION_DATE_ABBR" />, mara ya mwisho ilitumika <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Msimamizi wako bado hajaiidhinisha</translation>
<translation id="6569060085658103619">Unaangalia ukurasa wa kiendelezi</translation>
<translation id="6596325263575161958">Chaguo za usimbaji fiche</translation>
+<translation id="6604181099783169992">Vitambuzi vya Mwendo au Mwangaza</translation>
<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>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Alamisho Zinazosimamiwa</translation>
<translation id="7298195798382681320">Zinazopendekezwa</translation>
<translation id="7309308571273880165">Ripoti ya kuacha kufanya kazi iliyochukuliwa <ph name="CRASH_TIME" /> (kipakiwa kilichoombwa na mtumiaji bado hakijapakiwa)</translation>
+<translation id="7320336641823683070">Usaidizi kuhusu Muunganisho</translation>
<translation id="7334320624316649418">Rudia Kupanga Upya</translation>
<translation id="733923710415886693">Cheti cha seva hakikufichuliwa kupitia Uwazi wa Cheti.</translation>
<translation id="7353601530677266744">Mbinu ya Amri</translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">Wi-Fi unayotumia (<ph name="WIFI_NAME" />) inaweza kukuhitaji kutembelea ukurasa wake wa kuingia katika akaunti.</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="7862185352068345852">Ungependa kufunga tovuti?</translation>
<translation id="7878176543348854470">Kadi za malipo na za kulipia awali zinakubaliwa.</translation>
<translation id="7878562273885520351">Huenda nenosiri lako limetambulika</translation>
<translation id="7887683347370398519">Angalia CVC yako na ujaribu tena</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Tumia chaguo-msingi la duniani (Uliza)</translation>
<translation id="8042918947222776840">Chagua Mbinu ya Kuchukua Bidhaa</translation>
<translation id="8057711352706143257">Haikuweka mipangilio ya "<ph name="SOFTWARE_NAME" />" kwa njia sahihi. Kwa kawaida, kuondoa "<ph name="SOFTWARE_NAME" />" hurekebisha tatizo hili. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Ungependa kupakia upya tovuti?</translation>
<translation id="8088680233425245692">Haikufaulu kuangalia makala.</translation>
<translation id="8091372947890762290">Uwashaji unasubiri kwenye seva</translation>
<translation id="8094917007353911263">Mtandao unaotumia unaweza kukuhitaji kutembelea <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">URL ya sasisho si sahihi kwa kiendelezi chenye Kitambulisho "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Muhtasari wa agizo</translation>
<translation id="8205463626947051446">Tovuti hii huonyesha matangazo yanayokatiza matumizi</translation>
+<translation id="8211406090763984747">Muunganisho ni salama</translation>
<translation id="8218327578424803826">Mahali Palipohawilishwa:</translation>
<translation id="8225771182978767009">Mtu ambaye aliweka mipangilio ya kompyuta hii ameamua kuzuia tovuti hii.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Onyesha Manenosiri Yote Yaliyohifadhiwa</translation>
<translation id="8261506727792406068">Futa</translation>
<translation id="8267698848189296333">Ingia katika akaunti ukitumia <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Ingia</translation>
<translation id="8288807391153049143">Onyesha cheti</translation>
<translation id="8289355894181816810">Wasiliana na msimamizi wako wa mtandao iwapo huna uhakika kile ambacho hiki kinamaanisha.</translation>
<translation id="8293206222192510085">Ongeza Alamisho</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">Kadi za Mikopo na za Kulipia Awali Zinazokubaliwa</translation>
<translation id="8759274551635299824">Muda wa matumizi wa kadi hii umekwisha</translation>
<translation id="8761567432415473239">Kuvinjari Salama kwa Google <ph name="BEGIN_LINK" />kulipata programu zinazodhuru<ph name="END_LINK" /> kwenye <ph name="SITE" /> hivi karibuni.</translation>
+<translation id="8763927697961133303">Kifaa cha USB</translation>
<translation id="8790007591277257123">Rudia kufuta</translation>
<translation id="8800988563907321413">Mapendekezo ya maudhui ya uhamishaji wa karibu yataonekana hapa</translation>
<translation id="8820817407110198400">Alamisho</translation>
diff --git a/chromium/components/strings/components_strings_ta.xtb b/chromium/components/strings/components_strings_ta.xtb
index a45d08bae5f..07e465eb34b 100644
--- a/chromium/components/strings/components_strings_ta.xtb
+++ b/chromium/components/strings/components_strings_ta.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;அச்சிடு...</translation>
<translation id="1181037720776840403">அகற்று</translation>
<translation id="1184214524891303587">பாதுகாப்பிற்கு இடையூறு விளைவிக்கும் சாத்தியமுள்ள செயல்பாடு குறித்த விவரங்களை Googleக்குத் <ph name="BEGIN_WHITEPAPER_LINK" />தானாகவே அனுப்பு<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">பணப்பரிமாற்றம் முடியவில்லை</translation>
<translation id="1201402288615127009">அடுத்தது</translation>
<translation id="1201895884277373915">இந்தத் தளம் கூடுதலாக வழங்குபவை</translation>
<translation id="1206967143813997005">தொடக்கக் கையொப்பம் சரியானதல்ல</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575"><ph name="CRASH_TIME" /> அன்று சிதைவு அறிக்கை பெறப்பட்டது (இன்னும் பதிவேற்றப்படவில்லை அல்லது புறக்கணிக்கப்படவில்லை)</translation>
<translation id="1270502636509132238">பிக்அப் முறை</translation>
<translation id="1285320974508926690">இந்த தளத்தை எப்போதும் மொழிபெயர்க்க வேண்டாம்</translation>
+<translation id="1294154142200295408">கட்டளை வரி மாற்று வடிவங்கள்</translation>
<translation id="129553762522093515">சமீபத்தில் மூடியவை</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />குக்கீகளை அழிக்கவும்<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">இருப்பினும், பின்வரும் தரப்பினர் உங்கள் செயல்பாட்டைப் <ph name="BEGIN_EMPHASIS" />பார்க்க முடியும்<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">ஏற்கப்படும் கிரெடிட் மற்றும் டெபிட் கார்டுகள்</translation>
<translation id="1519264250979466059">உருவாக்கிய தேதி</translation>
<translation id="1527263332363067270">இணைப்பிற்காகக் காத்திருக்கிறது…</translation>
+<translation id="1532118530259321453">இந்தப் பக்கம் தெரிவிப்பது:</translation>
<translation id="153384715582417236">அவ்வளவு தான்!</translation>
<translation id="154408704832528245">டெலிவரி முகவரியைத் தேர்வு செய்</translation>
<translation id="1549470594296187301">இந்த அம்சத்தைப் பயன்படுத்த JavaScript இயக்கப்பட வேண்டும்.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />ப்ராக்ஸி மற்றும் ஃபயர்வாலைச் சரிபார்த்தல்<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">ஜிப் குறியீடு</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 பரிந்துரை}other{# பரிந்துரைகள்}}</translation>
-<translation id="2065985942032347596">அங்கீகாரம் தேவைப்படுகிறது</translation>
<translation id="2079545284768500474">செயல்தவிர்</translation>
<translation id="20817612488360358">கணினி ப்ராக்ஸி அமைப்புகள் பயன்படுத்த அமைக்கப்பட்டுள்ளது. வெளிப்படையான ப்ராக்ஸி உள்ளமைவும் குறிப்பிடப்பட்டுள்ளது.</translation>
<translation id="2091887806945687916">ஒலி</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">பேமண்ட்டை ரத்துசெய்</translation>
<translation id="2147827593068025794">பின்புல ஒத்திசைவு</translation>
<translation id="2148613324460538318">கார்டைச் சேர்</translation>
-<translation id="2149973817440762519">புக்மார்க்கை மாற்றுக</translation>
<translation id="2154054054215849342">உங்கள் டொமைனுக்கு ஒத்திசைத்தல் சேவை முடக்கப்பட்டுள்ளது</translation>
<translation id="2154484045852737596">கார்டைத் திருத்தவும்</translation>
<translation id="2166049586286450108">முழு நிர்வாகி அணுகல்</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">பிக்அப் முகவரியைத் தேர்வு செய்</translation>
<translation id="2740531572673183784">சரி</translation>
<translation id="2742870351467570537">தேர்ந்தெடுத்த உருப்படிகளை அகற்றுக</translation>
-<translation id="2744590937989388266">இந்தப் பக்கத்திலுள்ள உட்பொதிக்கப்பட்ட பக்கத்திலிருந்து</translation>
<translation id="277133753123645258">ஷிப்பிங் முறை</translation>
<translation id="277499241957683684">சாதனப் பதிவு இல்லை</translation>
<translation id="2784949926578158345">இணைப்பு மீட்டமைக்கப்பட்டது.</translation>
<translation id="2788784517760473862">ஏற்கப்படும் கிரெடிட் கார்டுகள்</translation>
<translation id="2794233252405721443">தளம் தடுக்கப்பட்டது</translation>
-<translation id="2795286477369100655">தளத்திலிருந்து வெளியேறவா?</translation>
<translation id="2799020568854403057">தளத்தில் தீங்கிழைக்கும் பயன்பாடுகள் உள்ளன</translation>
<translation id="2803306138276472711">Google பாதுகாப்பு உலாவலானது சமீபத்தில் <ph name="SITE" /> இல் <ph name="BEGIN_LINK" />தீம்பொருள் உள்ளதைக் கண்டுபிடித்தது<ph name="END_LINK" />. இயல்பாகவே பாதுகாப்பாக இருக்கும் இணையதளங்களும் சில சமயங்களில் தீம்பொருளினால் பாதிக்கப்பட்டிருக்கும்.</translation>
<translation id="2824775600643448204">முகவரி மற்றும் தேடல் பட்டி</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">பட்டியல் உள்ளீடு "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">தானாகத் தடுக்கப்பட்டது</translation>
<translation id="3024663005179499861">தவறான கொள்கை வகை</translation>
-<translation id="3032412215588512954">தளத்தை மீண்டும் ஏற்றவா?</translation>
<translation id="3037605927509011580">அச்சச்சோ!</translation>
<translation id="3039538478787849737">Google இல் கார்டைச் சேமிக்கவா?</translation>
<translation id="3041612393474885105">சான்றிதழ் தகவல்</translation>
@@ -307,6 +303,7 @@
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">தீவு</translation>
<translation id="3176929007561373547">பிராக்சி சர்வர் இயக்கத்தில் உள்ளது என்பதை உறுதிப்படுத்த உங்கள் பிராக்சி அமைப்புகளைச் சரிபார்க்கவும் அல்லது நெட்வொர்க் நிர்வாகியைத் தொடர்புகொள்ளவும். நீங்கள் பிராக்சி சர்வரைப் பயன்படுத்துகிறீர்கள் என்பதை நம்பவில்லை என்றால், பின்வருவதைச் செய்யவும்:<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="SERVER_NAME" /> இல் <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">கட்டணம் செலுத்துவதை ரத்துசெய்</translation>
<translation id="3207960819495026254">புக்மார்க் செய்யப்பட்டது</translation>
<translation id="3209375525920864198">சரியான அமர்வுப் பெயரை உள்ளிடவும்.</translation>
@@ -364,11 +361,57 @@
<translation id="3556433843310711081">உங்களுக்காக, தளத்தின் தடுப்பை உங்கள் நிர்வாகி நீக்க முடியும்</translation>
<translation id="3566021033012934673">உங்கள் இணைப்பு தனிப்பட்டது அல்ல</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" /> இல் உள்ள உட்பொதிக்கப்பட்ட பக்கம் தெரிவிப்பது:</translation>
<translation id="358285529439630156">கிரெடிட் மற்றும் ப்ரீபெய்டு கார்டுகள் ஏற்கப்படுகின்றன.</translation>
<translation id="3582930987043644930">பெயரைச் சேர்</translation>
<translation id="3583757800736429874">&amp;நகர்த்தலை மீண்டும் செய்</translation>
<translation id="3586931643579894722">விவரங்களை மறை</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;இணைப்புப் பிழைகளைச் சரிசெய்யவும்&lt;/h1&gt;
+ &lt;p&gt;இணையதளத்தைப் பார்க்க முயலும்போது பிழைச் செய்தியைப் பெற்றால், இவற்றைப் பயன்படுத்திச் சரிசெய்ய முயலவும்.&lt;/p&gt;
+ &lt;h2&gt;பெரும்பாலான பிழைகளைச் சரிசெய்யலாம்&lt;/h2&gt;
+ &lt;p&gt;இணையதளத்தைப் பார்க்க முயலும்போது அது திறக்கவில்லை எனில், முதலில் இந்தப் பிழையறிந்து திருத்துதல் படிகளைப் பயன்படுத்தி, பிழையைச் சரிசெய்ய முயலவும்:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;இணைய முகவரியில் எழுத்துப்பிழைகள் உள்ளனவா எனச் சரிபார்க்கவும்.&lt;/li&gt;
+ &lt;li&gt;உங்கள் இணைய இணைப்பு வழக்கம் போல செயல்படுகிறதா என்பதைச் சரிபார்க்கவும்.&lt;/li&gt;
+ &lt;li&gt;இணையதள உரிமையாளரைத் தொடர்புகொள்ளவும்.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;குறிப்பிட்ட பிழைச் செய்திக்கான உதவியைப் பெறுங்கள்&lt;/h2&gt;
+ &lt;h3&gt;"உங்கள் இணைப்பு தனிப்பட்டது அல்ல" அல்லது "NET::ERR_CERT_AUTHORITY_INVALID" அல்லது "ERR_CERT_COMMON_NAME_INVALID" அல்லது "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" அல்லது "SSL சான்றிதழ் பிழை"&lt;/h3&gt;
+ &lt;h4&gt;படி 1: போர்ட்டலில் உள்நுழையவும்&lt;/h4&gt;
+ &lt;p&gt;கஃபேக்கள் அல்லது விமான நிலையங்கள் போன்ற இடங்களில் உள்ள வைஃபை நெட்வொர்க்குகளைப் பயன்படுத்த நீங்கள் உள்நுழைய வேண்டியிருக்கும். உள்நுழைவுப் பக்கத்தைப் பார்க்க, &lt;code&gt;http://&lt;/code&gt; என்பதைப் பயன்படுத்தும் பக்கத்திற்குச் செல்லவும்.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;&lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt; போன்று, &lt;code&gt;http://&lt;/code&gt; எனத் தொடங்கும் ஏதேனும் ஓர் இணையதளத்திற்கும் செல்லவும்.&lt;/li&gt;
+ &lt;li&gt;அவ்வாறு திறக்கும் உள்நுழைவுப் பக்கத்தில் உள்நுழைந்து, இணையத்தைப் பயன்படுத்தவும்.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;படி 2: மறைநிலை பயன்முறையில் பக்கத்தைத் திறக்கவும் (கணினியில் மட்டும்)&lt;/h4&gt;
+ &lt;p&gt;நீங்கள் பார்த்த பக்கத்தை மறைநிலை சாளரத்தில் திறக்கவும்.&lt;/p&gt;
+ &lt;p&gt;அந்தப் பக்கம் திறந்தால், Chrome நீட்டிப்பானது சரியாக வேலை செய்யவில்லை என்று பொருள். பிழையைச் சரிசெய்ய, நீட்டிப்பை முடக்கவும்.&lt;/p&gt;
+ &lt;h4&gt;படி 3: உங்கள் ஆப்ரேட்டிங் சிஸ்டத்தைப் புதுப்பிக்கவும்&lt;/h4&gt;
+ &lt;p&gt;உங்கள் சாதனம் சமீபத்திய பதிப்பில் இயங்குகிறதா என்பதை உறுதிப்படுத்தவும்.&lt;/p&gt;
+ &lt;h4&gt;படி 4: உங்கள் வைரஸ்தடுப்பைத் தற்காலிகமாக முடக்கவும்&lt;/h4&gt;
+ &lt;p&gt; "HTTPS பாதுகாப்பு" அல்லது "HTTPS ஸ்கேன் செய்தல்" போன்ற அம்சங்களை வழங்கும் வைரஸ்தடுப்பு மென்பொருளைக் கொண்டிருந்தால், இந்தப் பிழையைப் பார்ப்பீர்கள். பாதுகாப்பை வழங்குவதிலிருந்து Chromeஐ வைரஸ்தடுப்பு தடுக்கிறது.&lt;/p&gt;
+ &lt;p&gt;சிக்கலைச் சரிசெய்ய, உங்கள் வைரஸ்தடுப்பு மென்பொருளை முடக்கவும். மென்பொருளை முடக்கிய பிறகு பக்கம் வேலை செய்தால், பாதுகாப்பான தளங்களைப் பயன்படுத்தும் போது இந்த மென்பொருளை முடக்கவும்.&lt;/p&gt;
+ &lt;p&gt;பக்கத்தைப் பயன்படுத்திய பிறகு, மறக்காமல் உங்கள் வைரஸ்தடுப்பு மென்பொருளை மீண்டும் இயக்கவும்.&lt;/p&gt;
+ &lt;h4&gt;படி 5: கூடுதல் உதவி பெறுங்கள்&lt;/h4&gt;
+ &lt;p&gt;அப்போதும் பிழை வந்தால், இணையதள உரிமையாளரைத் தொடர்புகொள்ளவும்.&lt;/p&gt;
+ &lt;h3&gt;"நெட்வொர்க்குடன் இணைக்கவும்"&lt;/h3&gt;
+ &lt;p&gt;சில வைஃபை போர்ட்டல்களில், இணையத்தைப் பயன்படுத்தும் முன்பு நீங்கள் உள்நுழைய வேண்டியிருக்கும். அது போன்ற போர்ட்டல்களைப் பயன்படுத்தினால், இந்தப் பிழையைப் பார்ப்பீர்கள்.&lt;/p&gt;
+ &lt;p&gt;பிழையைச் சரிசெய்ய, நீங்கள் திறக்க முயலும் பக்கத்தில் உள்ள &lt;strong&gt;இணை&lt;/strong&gt; என்பதைக் கிளிக் செய்யவும்.&lt;/p&gt;
+ &lt;h3&gt;"நேரம் பின்தங்கியுள்ளது" அல்லது "நேரம் கூடுதலாக அமைக்கப்பட்டுள்ளது" அல்லது "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;உங்கள் கணினி அல்லது மொபைல் சாதனத்தின் தேதி மற்றும் நேரம் தவறாக இருந்தால், இந்தப் பிழையைப் பார்ப்பீர்கள்.&lt;/p&gt;
+ &lt;p&gt;இந்தப் பிழையைச் சரிசெய்ய, உங்கள் சாதனத்தின் கடிகாரத்தைத் திறக்கவும். நேரமும் தேதியும் சரியாக இருப்பதை உறுதிப்படுத்தவும்.&lt;/p&gt;
+ &lt;h3&gt;"பாதுகாப்பாக இணையத்துடன் இணைவதிலிருந்து, Chromeஐ உங்கள் கணினியில் உள்ள மென்பொருள் தடுக்கிறது" (Windows கணினிகள் மட்டும்)&lt;/h3&gt;
+ &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;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; என்பதைக் கிளிக் செய்யவும்
+ &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="3615877443314183785">சரியான காலாவதித் தேதியை உள்ளிடவும்</translation>
<translation id="36224234498066874">உலாவல் தரவை அழி...</translation>
<translation id="362276910939193118">முழு வரலாற்றையும் காண்பி</translation>
@@ -387,7 +430,7 @@
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">ஏற்றுகிறது…</translation>
<translation id="3712624925041724820">உரிமம் முடிந்தது</translation>
-<translation id="3714780639079136834">மொபைல் தரவு அல்லது வைஃபையை இயக்குதல்</translation>
+<translation id="3714780639079136834">மொபைல் டேட்டா அல்லது வைஃபையை இயக்குதல்</translation>
<translation id="3715597595485130451">வைஃபையுடன் இணைத்தல்</translation>
<translation id="3717027428350673159"><ph name="BEGIN_LINK" />ப்ராக்ஸி, ஃபயர்வால் மற்றும் DNS உள்ளமைவைச் சரிபார்த்தல்<ph name="END_LINK" /></translation>
<translation id="372429172604983730">வைரஸ்தடுப்பு, ஃபயர்வால், இணைய வடிப்பான் அல்லது ப்ராக்ஸி மென்பொருள் உள்ளிட்ட பயன்பாடுகள் இந்தப் பிழையை ஏற்படுத்தக்கூடும்.</translation>
@@ -401,7 +444,6 @@
<translation id="3778403066972421603">கார்டை உங்கள் Google கணக்கிலும் இந்தச் சாதனத்திலும் சேமிக்க விரும்புகிறீர்களா?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">காலாவதி: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929"><ph name="SITE" /> இலிருந்து</translation>
<translation id="382518646247711829">நீங்கள் பிராக்சி சர்வரைப் பயன்படுத்தினால்....</translation>
<translation id="3828924085048779000">வெற்று கடவுச்சொற்றொடருக்கு அனுமதியில்லை.</translation>
<translation id="385051799172605136">முந்தைய பக்கம்</translation>
@@ -415,6 +457,7 @@
<translation id="3945915738023014686">பதிவேற்றிய சிதைவு அறிக்கை ஐடி <ph name="CRASH_ID" /> (அகச் சிதைவு ஐடி: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">இது <ph name="DOMAIN" /> தான் என்பதை, இந்தச் சேவையகத்தால் உறுதிப்படுத்த முடியவில்லை; பொருள் மாற்றுப் பெயர்களை அதன் பாதுகாப்புச் சான்றிதழ் குறிப்பிடவில்லை. இது தவறான உள்ளமைவினால் ஏற்பட்டிருக்கலாம் அல்லது தீங்கிழைப்பவர் உங்கள் இணைப்பில் குறுக்கிட்டிருக்கலாம்.</translation>
<translation id="3949601375789751990">உலாவல் வரலாறு இங்கே தோன்றும்</translation>
+<translation id="3950820424414687140">உள்நுழைக</translation>
<translation id="3963721102035795474">படித்தல் பயன்முறை</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{ஏதுமில்லை}=1{1 தளத்திலிருந்து }other{# தளங்களிலிருந்து }}</translation>
<translation id="397105322502079400">கணக்கிடுகிறது...</translation>
@@ -431,6 +474,7 @@
<translation id="4103249731201008433">சாதன சீரியல் எண் தவறானது</translation>
<translation id="410351446219883937">தானியங்கி</translation>
<translation id="4103763322291513355">ஏற்கத்தகாத URLகளின் பட்டியலையும் உங்கள் கணினி நிர்வாகியால் செயற்படுத்தப்படும் பிற கொள்கைகளையும் காண &lt;strong&gt;chrome://policy&lt;/strong&gt; ஐப் பார்வையிடவும்.</translation>
+<translation id="4110652170750985508">உங்கள் கட்டணத்தை மதிப்பாய்வு செய்யவும்</translation>
<translation id="4116663294526079822">இந்தத் தளத்தில் எப்போதும் அனுமதி</translation>
<translation id="4117700440116928470">கொள்கையின் நோக்கம் ஆதரிக்கப்படவில்லை.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{மேலும் ஒன்று}other{மேலும் #}}</translation>
@@ -457,7 +501,6 @@
<translation id="4269787794583293679">(பயனர்பெயர் இல்லை)</translation>
<translation id="4275830172053184480">உங்கள் சாதனத்தை மீண்டும் தொடங்கவும்</translation>
<translation id="4280429058323657511">, காலாவதித் தேதி: <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">உள்நுழை</translation>
<translation id="4312866146174492540">தடு (இயல்பு)</translation>
<translation id="4325863107915753736">கட்டுரையைக் கண்டறிய முடியவில்லை</translation>
<translation id="4326324639298822553">காலாவதித் தேதியைச் சரிபார்த்து, மீண்டும் முயலவும்</translation>
@@ -479,14 +522,12 @@
<translation id="4515275063822566619">கார்டுகளும் முகவரிகளும் Chrome இலிருந்தும் <ph name="ACCOUNT_EMAIL" /> எனும் உங்கள் Google கணக்கிலிருந்தும் பெறப்பட்டவையாகும். <ph name="BEGIN_LINK" />அமைப்புகளில்<ph name="END_LINK" /> அவற்றை நிர்வகிக்கலாம்.</translation>
<translation id="4522570452068850558">விவரங்கள்</translation>
<translation id="4552089082226364758">ஃப்ளாஷ்</translation>
-<translation id="4554702541363482291"><ph name="SITE" /> இல் உள்ள உட்பொதிக்கப்பட்ட பக்கத்திலிருந்து</translation>
<translation id="4558551763791394412">நீட்டிப்புகளை முடக்கவும்.</translation>
<translation id="457875822857220463">டெலிவரி</translation>
<translation id="4582800630050655161">Google கணக்கிற்கான அணுகலை நீங்கள் இழக்கக்கூடும் அல்லது அடையாளத் திருட்டை எதிர்கொள்ளக்கூடும். இப்போதே உங்கள் கடவுச்சொல்லை மாற்றும்படி Chromium பரிந்துரைக்கிறது.</translation>
<translation id="4587425331216688090">Chrome இலிருந்து முகவரியை அகற்றவா?</translation>
<translation id="4592951414987517459">நவீன சைபர் சூட்டைப் பயன்படுத்தி <ph name="DOMAIN" /> உடனான உங்கள் இணைப்பு என்க்ரிப்ட் செய்யப்பட்டது.</translation>
<translation id="4594403342090139922">&amp;நீக்குதலைச் செயல்தவிர்</translation>
-<translation id="4611292653554630842">உள்நுழைக</translation>
<translation id="4619615317237390068">பிற சாதனங்களின் தாவல்கள்</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">இது <ph name="DOMAIN" /> தான் என்பதை இந்தச் சேவையகம் உறுதிப்படுத்தவில்லை; இதன் பாதுகாப்புச் சான்றிதழில் பிழைகள் உள்ளன. இது தவறான உள்ளமைவால் ஏற்பட்டிருக்கலாம் அல்லது தீங்கிழைப்பவர் உங்கள் இணைப்பில் குறுக்கிட்டிருக்கலாம்.</translation>
@@ -496,11 +537,9 @@
<translation id="4708268264240856090">உங்கள் இணைப்பில் தடங்கல் ஏற்பட்டது</translation>
<translation id="471880041731876836">இந்தத் தளத்தைப் பார்ப்பதற்கான அனுமதி உங்களிடம் இல்லை</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows நெட்வொர்க் டயக்னஸ்டிக்ஸ் கருவியை இயக்கவும்<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">உங்கள் கட்டணம்</translation>
<translation id="4726672564094551039">கொள்கைகளை மீண்டும் ஏற்று</translation>
<translation id="4728558894243024398">ப்ளாட்ஃபார்ம்</translation>
<translation id="4736825316280949806">Chromiumஐ மீண்டும் தொடங்கவும்</translation>
-<translation id="4737498291095696011">இந்தப் பக்கத்திலிருந்து</translation>
<translation id="4744603770635761495">இயக்கநிரல் பாதை</translation>
<translation id="4749685221585524849">கடைசியாகப் பயன்படுத்தியது: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">உங்கள் தகவலை (எடுத்துக்காட்டு: கடவுச்சொற்கள் அல்லது கிரெடிட் கார்டு எண்கள்) இந்தத் தளத்திற்கு அனுப்பும் போது, தனிப்பட்டதாக இருக்கும்.</translation>
@@ -519,16 +558,16 @@
<translation id="4850886885716139402">காட்சி</translation>
<translation id="4854362297993841467">இந்த டெலிவரி முறை இல்லை. வேறு முறையைப் பயன்படுத்திப் பார்க்கவும்.</translation>
<translation id="4858792381671956233">இந்தத் தளத்தைப் பார்வையிடலாமா என, நீங்கள் பெற்றோரிடம் கேட்டுள்ளீர்கள்</translation>
-<translation id="4871132632506079383"><ph name="SITE" /> இல் உள்ள உட்பொதிக்கப்பட்ட பக்கத்திலிருந்து</translation>
<translation id="4880827082731008257">வரலாற்றில் தேடு</translation>
+<translation id="4881695831933465202">திற</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">அங்கீகரிப்பு தேவை</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{மேலும் ஒரு இணையப் பக்கம்}other{மேலும் # இணையப் பக்கங்கள்}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947"><ph name="CREDIT_CARD" /> இன் CVC எண்ணை உள்ளிடவும். உறுதிசெய்த பின்னர், உங்கள் Google Payments கணக்கிலிருக்கும் கார்டு விவரங்கள் இந்தத் தளத்துடன் பகிரப்படும்.</translation>
<translation id="4923417429809017348">ஒரு அறியப்படாத மொழியிலிருந்து <ph name="LANGUAGE_LANGUAGE" /> -க்கு இந்தப் பக்கம் மொழிபெயர்க்கப்பட்டுள்ளது</translation>
<translation id="4923459931733593730">கட்டண முறை</translation>
<translation id="4926049483395192435">கட்டாயம் குறிப்பிட வேண்டும்.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> தெரிவிப்பது:</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">செயல்கள்</translation>
<translation id="4958444002117714549">பட்டியலை விரி</translation>
@@ -537,7 +576,6 @@
<translation id="5002932099480077015">இயக்கப்பட்டால், விரைவாகப் படிவத்தை நிரப்ப உங்கள் கார்டின் நகலை இச்சாதனத்தில் Chrome சேமித்து வைக்கும்.</translation>
<translation id="5018422839182700155">பக்கத்தைத் திறக்க முடியவில்லை</translation>
<translation id="5019198164206649151">தவறான நிலையில் மீட்பு சேமிப்பு உள்ளது</translation>
-<translation id="5020990877659450221">இந்தப் பக்கத்திலிருந்து</translation>
<translation id="5023310440958281426">உங்கள் நிர்வாகியின் கொள்கைகளைச் சரிபார்க்கவும்</translation>
<translation id="5029568752722684782">நகலை அழி</translation>
<translation id="503069730517007720">"<ph name="SOFTWARE_NAME" />" மென்பொருளுக்கு மூலச் சான்றிதழ் தேவை, ஆனால் நிறுவப்படவில்லை. இந்தச் சிக்கலைச் சரிசெய்ய, "<ph name="SOFTWARE_NAME" />" மென்பொருளின் உள்ளமைவு வழிமுறைகளை ஐடி நிர்வாகி பின்பற்ற வேண்டும். <ph name="FURTHER_EXPLANATION" /></translation>
@@ -563,12 +601,12 @@
<translation id="5172758083709347301">இயந்திரம்</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> இல் இல்லையா? இந்தப் பிழையை தெரிவிக்கவும்</translation>
<translation id="5190835502935405962">புக்மார்க்குகள் பட்டி</translation>
+<translation id="5201306358585911203">இந்தப் பக்கத்திலுள்ள உட்பொதிக்கப்பட்ட பக்கம் தெரிவிப்பது:</translation>
<translation id="5205222826937269299">பெயர் தேவை</translation>
<translation id="5222812217790122047">மின்னஞ்சல் தேவை</translation>
<translation id="522700295135997067">உங்கள் கடவுச்சொல்லை இந்தத் தளம் திருடியிருக்கலாம்</translation>
<translation id="5230733896359313003">ஷிப்பிங் முகவரி</translation>
<translation id="5251803541071282808">கிளவுடு</translation>
-<translation id="5277279256032773186">பணியில் Chromeஐப் பயன்படுத்துகிறீர்களா? வணிக நிறுவனங்கள் தங்களின் பணியாளர்களுக்கான Chrome அமைப்புகளை நிர்வகிக்கலாம். மேலும் அறிக</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />மென்பொருளைத் தற்காலிகமாக முடக்கி, இணையத்துடன் இணைவதற்கு, பின்வரும் படிகளைப் பின்பற்றவும். உங்களுக்கு நிர்வாகி முன்னுரிமைகள் தேவைப்படும்.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -630,7 +668,6 @@
<translation id="5610142619324316209">இணைப்பைச் சரிபார்த்தல்</translation>
<translation id="5610807607761827392"><ph name="BEGIN_LINK" />அமைப்புகளில்<ph name="END_LINK" /> கார்டுகளையும் முகவரிகளையும் நிர்வகிக்கலாம்.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> உங்களைப் பலமுறை திசைதிருப்பம் செய்தது.</translation>
-<translation id="5622887735448669177">தளத்திலிருந்து வெளியேறவா?</translation>
<translation id="5629630648637658800">கொள்கை அமைப்புகளை ஏற்றுவதில் தோல்வி</translation>
<translation id="5631439013527180824">தவறான சாதன நிர்வாக டோக்கன்</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>
@@ -653,7 +690,6 @@
<translation id="5786044859038896871">கார்டு தகவலை நிரப்ப விரும்புகிறீர்களா?</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" />ஐ நிரப்ப விரும்புகிறீர்களா?</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" />க்கான உங்கள் இணைப்பு, நடைமுறையில் இல்லாத சைபர் சூட்டைப் பயன்படுத்தி என்க்ரிப்ட் செய்யப்பட்டது.</translation>
-<translation id="5810928923025889964">இந்தப் பக்கத்தின் உட்பொதிக்கப்பட்ட பக்கத்திலிருந்து</translation>
<translation id="5813119285467412249">&amp;சேர்த்தலை மீண்டும் செய்</translation>
<translation id="5838278095973806738">தீங்கிழைப்பவர்கள் திருடிவிடலாம் என்பதால், இந்தத் தளத்தில் முக்கியத் தகவலை (எடுத்துக்காட்டு: கடவுச்சொற்கள் அல்லது கிரெடிட் கார்டுகள்) உள்ளிட வேண்டாம்.</translation>
<translation id="5866257070973731571">மொபைல் எண்ணைச் சேர்க்கவும்</translation>
@@ -726,21 +762,19 @@
<translation id="6446608382365791566">மேலும் தகவலைச் சேர்க்கவும்</translation>
<translation id="6447842834002726250">குக்கீகள்</translation>
<translation id="6451458296329894277">படிவ மறுசமர்ப்பிப்பை உறுதிசெய்க</translation>
-<translation id="6456339708790392414">உங்கள் கட்டணம்</translation>
<translation id="647261751007945333">சாதனக் கொள்கைகள்</translation>
<translation id="6477321094435799029">இந்தப் பக்கத்தில் வழக்கத்திற்கு மாறான குறியீடு இருப்பதை Chrome கண்டறிந்துள்ளது, மேலும் உங்கள் தனிப்பட்ட தகவலை (எடுத்துக்காட்டு: கடவுச்சொற்கள், ஃபோன் எண்கள் மற்றும் கிரெடிட் கார்டுகள்) பாதுகாக்க அதைத் தடுத்துள்ளது.</translation>
<translation id="6489534406876378309">சிதைவுகளைப் பதிவேற்றுவதைத் தொடங்கு</translation>
<translation id="6507833130742554667">கிரெடிட் மற்றும் டெபிட் கார்டுகள் ஏற்கப்படுகின்றன.</translation>
<translation id="6508722015517270189">Chromeஐ மீண்டும் தொடங்கவும்</translation>
-<translation id="6521373090216409766">தளத்தை மீண்டும் ஏற்றவா?</translation>
<translation id="6529602333819889595">&amp;நீக்குதலை மீண்டும் செய்</translation>
<translation id="6534179046333460208">இயல்நிலை இணையப் பரிந்துரைகள்</translation>
<translation id="6550675742724504774">விருப்பத்தேர்வுகள்</translation>
-<translation id="6556239504065605927">பாதுகாப்பான இணைப்பு</translation>
<translation id="6556915248009097796">காலாவதி: <ph name="EXPIRATION_DATE_ABBR" />, கடைசியாகப் பயன்படுத்தியது: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">இன்னும் உங்கள் நிர்வாகி அனுமதிக்கவில்லை</translation>
<translation id="6569060085658103619">நீட்டிப்புப் பக்கத்தைப் பார்க்கிறீர்கள்</translation>
<translation id="6596325263575161958">குறியாக்க விருப்பங்கள்</translation>
+<translation id="6604181099783169992">நகர்வு அல்லது ஒளி உணர்விகள்</translation>
<translation id="6624427990725312378">தொடர்புத் தகவல்</translation>
<translation id="6626291197371920147">சரியான கார்டு எண்ணைச் சேர்க்கவும்</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> தேடல்</translation>
@@ -812,6 +846,7 @@
<translation id="7275334191706090484">நிர்வகிக்கப்படும் புக்மார்க்குகள்</translation>
<translation id="7298195798382681320">பரிந்துரைத்தவை</translation>
<translation id="7309308571273880165"><ph name="CRASH_TIME" /> அன்று சிதைவு அறிக்கை பெறப்பட்டது (பயனர் பதிவேற்றக் கோரியுள்ளார், இன்னும் பதிவேற்றப்படவில்லை)</translation>
+<translation id="7320336641823683070">இணைப்பிற்கான உதவி</translation>
<translation id="7334320624316649418">&amp;மறுவரிசைப்படுத்தலை மீண்டும் செய்</translation>
<translation id="733923710415886693">சான்றிதழ் வெளிப்படைத்தன்மை மூலம் சேவையகத்தின் சான்றிதழ் வெளியிடப்படவில்லை.</translation>
<translation id="7353601530677266744">கட்டளை வரி</translation>
@@ -896,6 +931,7 @@
<translation id="782886543891417279">நீங்கள் பயன்படுத்திக் கொண்டிருக்கும் (<ph name="WIFI_NAME" />) வைஃபை, அதன் உள்நுழைவுப் பக்கத்தை நீங்கள் பார்க்கக் கோரலாம்.</translation>
<translation id="785549533363645510">இருப்பினும், நீங்கள் மறைந்திருக்கமாட்டீர்கள். மறைநிலைக்குச் செல்வது பணிக்கமர்த்தும் நிறுவனம், இணையச் சேவை வழங்குநர் அல்லது நீங்கள் செல்லும் இணையதளங்களிடம் உங்கள் உலாவலை மறைக்காது.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">தளத்திலிருந்து வெளியேறவா?</translation>
<translation id="7878176543348854470">டெபிட் மற்றும் ப்ரீபெய்டு கார்டுகள் ஏற்கப்படுகின்றன.</translation>
<translation id="7878562273885520351">உங்கள் கடவுச்சொல் திருடப்பட்டிருக்கலாம்</translation>
<translation id="7887683347370398519">CVCஐச் சோதித்து, மீண்டும் முயற்சிக்கவும்</translation>
@@ -918,6 +954,7 @@
<translation id="8041940743680923270">முழுமையான இயல்புநிலையைப் பயன்படுத்து (கேள்)</translation>
<translation id="8042918947222776840">பிக்அப் முறையைத் தேர்வு செய்</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" மென்பொருள் சரியாக உள்ளமைக்கப்படவில்லை. வழக்கமாக, "<ph name="SOFTWARE_NAME" />"ஐ நிறுவல் நீக்கினால் சிக்கல் சரியாகிவிடும். <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">தளத்தை மீண்டும் ஏற்றவா?</translation>
<translation id="8088680233425245692">கட்டுரையைக் காட்டுவதில் தோல்வி.</translation>
<translation id="8091372947890762290">சேவையகத்தில் செயலாக்கம் நிலுவையிலுள்ளது</translation>
<translation id="8094917007353911263">நீங்கள் பயன்படுத்திக் கொண்டிருக்கும் நெட்வொர்க், அதன் <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />ஐ நீங்கள் பார்க்கக் கோரலாம்.</translation>
@@ -933,6 +970,7 @@
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" ஐடியுடன் கூடிய நீட்டிப்பிற்கான தவறான புதுப்பிப்பு URL.</translation>
<translation id="8202097416529803614">ஆர்டர் பற்றிய சுருக்கவிவரம்</translation>
<translation id="8205463626947051446">தளத்தில் குறுக்கிடும் விளம்பரங்கள் அடிக்கடிக் காட்டப்படும்</translation>
+<translation id="8211406090763984747">இணைப்பு பாதுகாப்பானது</translation>
<translation id="8218327578424803826">ஒதுக்கிய இருப்பிடம்:</translation>
<translation id="8225771182978767009">இந்தக் கணினியை அமைத்த நபர் இந்தத் தளத்தைத் தடுக்கும்படி தேர்வுசெய்துள்ளார்.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -944,6 +982,7 @@
<translation id="825929999321470778">சேமித்த எல்லாக் கடவுச்சொற்களையும் காட்டு</translation>
<translation id="8261506727792406068">நீக்கு</translation>
<translation id="8267698848189296333"><ph name="USERNAME" /> ஆக உள்நுழைகிறீர்கள்</translation>
+<translation id="8286036467436129157">உள்நுழை</translation>
<translation id="8288807391153049143">சான்றிதழைக் காட்டும்</translation>
<translation id="8289355894181816810">இதன் பொருள் உங்களுக்குத் தெரியவில்லையெனில் உங்கள் பிணைய நிர்வாகியைத் தொடர்புகொள்ளவும்.</translation>
<translation id="8293206222192510085">புக்மார்க்கைச் சேர்</translation>
@@ -994,6 +1033,7 @@
<translation id="874846938927089722">ஏற்கப்படும் கிரெடிட் மற்றும் ப்ரீபெய்டு கார்டுகள்</translation>
<translation id="8759274551635299824">கார்டு காலாவதியாகிவிட்டது</translation>
<translation id="8761567432415473239">Google பாதுகாப்பான தேடல், <ph name="SITE" /> இல் சமீபத்தில் <ph name="BEGIN_LINK" />தீங்கான நிரல்களைக் கண்டறிந்தது<ph name="END_LINK" />.</translation>
+<translation id="8763927697961133303">USB சாதனம்</translation>
<translation id="8790007591277257123">&amp;நீக்குதலை மீண்டும் செய்</translation>
<translation id="8800988563907321413">உங்கள் அருகிலுள்ளவற்றுக்கான பரிந்துரைகள் இங்கே தோன்றும்</translation>
<translation id="8820817407110198400">புத்தகக்குறிகள்</translation>
diff --git a/chromium/components/strings/components_strings_te.xtb b/chromium/components/strings/components_strings_te.xtb
index c836666f9c4..a79f300ee4a 100644
--- a/chromium/components/strings/components_strings_te.xtb
+++ b/chromium/components/strings/components_strings_te.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;ముద్రించు...</translation>
<translation id="1181037720776840403">తొలగించు</translation>
<translation id="1184214524891303587">సంభావ్య భద్రతా సంఘటనల గురించిన వివరాలను Googleకి <ph name="BEGIN_WHITEPAPER_LINK" />స్వయంచాలకంగా నివేదిస్తుంది<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">చెల్లింపు పూర్తి కాలేదు</translation>
<translation id="1201402288615127009">తదుపరి</translation>
<translation id="1201895884277373915">ఈ సైట్ నుండి మరింత</translation>
<translation id="1206967143813997005">తప్పు ప్రారంభ సంతకం</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">క్రాష్ నివేదిక <ph name="CRASH_TIME" />కి సంగ్రహించబడింది (ఇంకా అప్‌లోడ్ చేయలేదు లేదా విస్మరించబడింది)</translation>
<translation id="1270502636509132238">పికప్ పద్ధతి</translation>
<translation id="1285320974508926690">ఈ సైట్‌ను అనువదించవద్దు</translation>
+<translation id="1294154142200295408">ఆదేశ-పంక్తి వ్యత్యాసాలు</translation>
<translation id="129553762522093515">ఇటీవల మూసివెయ్యబడినవి</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />మీ కుక్కీలను తీసివేయడానికి ప్రయత్నించండి<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">మీ కార్యాచరణ వీరికి <ph name="BEGIN_EMPHASIS" />ఇప్పటికీ కనిపించవచ్చు<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">ఆమోదించబడిన క్రెడిట్ మరియు డెబిట్ కార్డ్‌లు</translation>
<translation id="1519264250979466059">రూపకల్పన తేదీ</translation>
<translation id="1527263332363067270">కనెక్షన్ కోసం వేచి ఉన్నాము...</translation>
+<translation id="1532118530259321453">ఈ పేజీ ఇలా చెబుతోంది</translation>
<translation id="153384715582417236">ఇప్పటికి ఇంతే</translation>
<translation id="154408704832528245">బట్వాడా చిరునామాను ఎంచుకోండి</translation>
<translation id="1549470594296187301">ఈ లక్షణాన్ని ఉపయోగించడానికి జావాస్క్రిప్ట్ తప్పనిసరిగా ప్రారంభించాలి.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />ప్రాక్సీ మరియు ఫైర్‌వాల్‌ను తనిఖీ చేయడం<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">జిప్ కోడ్</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 సూచన}other{# సూచనలు}}</translation>
-<translation id="2065985942032347596">ప్రామాణీకరణ అవసరం</translation>
<translation id="2079545284768500474">చర్య రద్దు</translation>
<translation id="20817612488360358">సిస్టమ్ ప్రాక్సీ సెట్టింగ్‌లు ఉపయోగించడానికి సెట్ చేయబడ్డాయి కానీ స్పష్టమైన ప్రాక్సీ కాన్ఫిగరేషన్ కూడా పేర్కొనబడింది.</translation>
<translation id="2091887806945687916">ధ్వని</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">చెల్లింపును రద్దు చేయి</translation>
<translation id="2147827593068025794">నేపథ్య సమకాలీకరణ</translation>
<translation id="2148613324460538318">కార్డ్‌ని జోడించు</translation>
-<translation id="2149973817440762519">బుక్‌మార్క్‌ను సవరించు</translation>
<translation id="2154054054215849342">సమకాలీకరణ మీ డొమైన్‌కు అందుబాటులో లేదు</translation>
<translation id="2154484045852737596">కార్డ్‌ను సవరించండి</translation>
<translation id="2166049586286450108">పూర్తి నిర్వాహక ప్రాప్యత</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">పికప్ చిరునామాను ఎంచుకోండి</translation>
<translation id="2740531572673183784">సరే</translation>
<translation id="2742870351467570537">ఎంచుకున్న అంశాలను తీసివేయండి</translation>
-<translation id="2744590937989388266">ఈ పేజీలోని పొందుపరిచిన పేజీ నుండి</translation>
<translation id="277133753123645258">రవాణా పద్ధతి</translation>
<translation id="277499241957683684">పరికరం రికార్డ్ లేదు</translation>
<translation id="2784949926578158345">కనెక్షన్ మళ్ళీ సెట్ చెయ్యబడింది.</translation>
<translation id="2788784517760473862">ఆమోదించబడిన క్రెడిట్ కార్డ్‌లు</translation>
<translation id="2794233252405721443">సైట్ బ్లాక్ చేయబడింది</translation>
-<translation id="2795286477369100655">మీరు ఈ సైట్‌ నుండి నిష్క్రమించాలనుకుంటున్నారా?</translation>
<translation id="2799020568854403057">రాబోయే సైట్ హానికరమైన యాప్‌లను కలిగి ఉంది</translation>
<translation id="2803306138276472711">Google సురక్షిత బ్రౌజింగ్ ఇటీవల <ph name="SITE" />లో <ph name="BEGIN_LINK" />మాల్వేర్‌ని గుర్తించింది<ph name="END_LINK" />. సాధారణంగా సురక్షితమైన వెబ్‌సైట్‌‌లకు కూడా కొన్నిసార్లు మాల్వేర్ సోకుతుంది.</translation>
<translation id="2824775600643448204">చిరునామా మరియు శోధన బార్</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">జాబితా నమోదు "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">స్వయంచాలకంగా బ్లాక్ చేయబడింది</translation>
<translation id="3024663005179499861">చెల్లని విధాన రకం</translation>
-<translation id="3032412215588512954">మీరు ఈ సైట్‌ను మళ్లీ లోడ్ చేయాలనుకుంటున్నారా?</translation>
<translation id="3037605927509011580">ఆవ్, స్నాప్!</translation>
<translation id="3039538478787849737">కార్డ్‌ని Googleకు సేవ్ చేయాలా?</translation>
<translation id="3041612393474885105">సర్టిఫికెట్ సమాచారం</translation>
@@ -310,6 +306,7 @@
మీ నెట్‌వర్క్ నిర్వాహకుడిని సంప్రదించండి. మీరు ప్రాక్సీ సర్వర్‌నే ఉపయోగిస్తున్నట్లు మీకు
నమ్మకంగా లేకుంటే:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="SERVER_NAME" />లో <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">చెల్లింపును రద్దు చేయండి</translation>
<translation id="3207960819495026254">బుక్‌మార్క్ చేయబడింది</translation>
<translation id="3209375525920864198">దయచేసి చెల్లుబాటు అయ్యే సెషన్ పేరుని నమోదు చేయండి.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">మీ నిర్వాహకుడు మీ కోసం దీన్ని అన్‌బ్లాక్ చేయగలరు</translation>
<translation id="3566021033012934673">మీ కనెక్షన్ ప్రైవేట్ కాదు</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" />లో పొందుపరిచిన పేజీ ఇలా చెబుతోంది</translation>
<translation id="358285529439630156">క్రెడిట్ మరియు ప్రీపెయిడ్ కార్డ్‌లు ఆమోదించబడతాయి.</translation>
<translation id="3582930987043644930">పేరు జోడించండి</translation>
<translation id="3583757800736429874">&amp;తరలించడాన్ని పునరావృతం చేయి</translation>
<translation id="3586931643579894722">వివరాలను దాచిపెట్టు</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;కనెక్షన్ ఎర్రర్‌లను పరిష్కరించండి&lt;/h1&gt;
+ &lt;p&gt;మీరు వెబ్‌సైట్‌ని సందర్శించడానికి ప్రయత్నించినప్పుడు ఎర్రర్ వస్తే, ఈ పరిష్కారాలను ప్రయత్నించండి.&lt;/p&gt;
+ &lt;h2&gt;అనేక కనెక్షన్ ఎర్రర్‌లను పరిష్కరించండి&lt;/h2&gt;
+ &lt;p&gt;మీరు వెబ్‌సైట్‌ని సందర్శించడానికి ప్రయత్నించినా, అది తెరుచుకోకుంటే, ముందు ఈ సమస్య నివారణ ప్రక్రియ దశలతో ఎర్రర్‌ని పరిష్కరించడానికి ప్రయత్నించండి:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;వెబ్ చిరునామాలో అక్షర దోషాలు ఉన్నాయేమో చూడండి.&lt;/li&gt;
+ &lt;li&gt;మీ ఇంటర్నెట్ కనెక్షన్ సరిగ్గా ఉన్నట్లు నిర్ధారించుకోండి.&lt;/li&gt;
+ &lt;li&gt;వెబ్‌సైట్ యజమానిని సంప్రదించండి.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;నిర్దిష్ట ఎర్రర్ సందేశాన్ని ఉపయోగించి సహాయం పొందండి&lt;/h2&gt;
+ &lt;h3&gt;"మీ కనెక్షన్ ప్రైవేట్ కాదు" లేదా "NET::ERR_CERT_AUTHORITY_INVALID" లేదా "ERR_CERT_COMMON_NAME_INVALID" లేదా "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" లేదా "SSL సర్టిఫికేట్ ఎర్రర్"&lt;/h3&gt;
+ &lt;h4&gt;1వ దశ: పోర్టల్‌కి సైన్ ఇన్ చేయండి&lt;/h4&gt;
+ &lt;p&gt;కెఫేలు లేదా విమానాశ్రయాలు వంటి స్థలాలలో ఉన్న Wi-Fi నెట్‌వర్క్‌లకు మీరు సైన్ ఇన్ చేయాల్సి ఉంటుంది. సైన్ ఇన్ పేజీని చూడటం కోసం, &lt;code&gt;http://&lt;/code&gt;ని ఉపయోగించే పేజీని సందర్శించండి.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;&lt;code&gt;http://&lt;/code&gt;తో ప్రారంభమయ్యే ఏదైనా సైట్‌కి వెళ్లండి, ఉదాహరణకు &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;తెరుచుకునే సైన్ ఇన్ పేజీలో, ఇంటర్నెట్‌ను ఉపయోగించడానికి సైన్ ఇన్ చేయండి.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;2వ దశ: పేజీని అజ్ఞాత మోడ్‌లో తెరవండి (కంప్యూటర్ మాత్రమే)&lt;/h4&gt;
+ &lt;p&gt;మీరు సందర్శిస్తున్న పేజీని అజ్ఞాత విండోలో తెరవండి.&lt;/p&gt;
+ &lt;p&gt;పేజీ తెరుచుకున్నట్లయితే, Chrome ఎక్స్‌టెన్షన్‌ సరిగ్గా పని చేయడం లేదని అర్థం. ఎర్రర్‌ని పరిష్కరించాలంటే, ఆ ఎక్స్‌టెన్షన్‌ని ఆఫ్ చేయండి.&lt;/p&gt;
+ &lt;h4&gt;3వ దశ: మీ ఆపరేటింగ్ సిస్టమ్‌ని అప్‌డేట్ చేయండి&lt;/h4&gt;
+ &lt;p&gt;మీ పరికరంలో తాజా అప్‌డేట్‌లు అన్నీ ఇన్‌స్టాల్ చేయబడినట్టు నిర్ధారించుకోండి.&lt;/p&gt;
+ &lt;h4&gt;4వ దశ: మీ యాంటీవైరస్‌ని తాత్కాలికంగా ఆఫ్ చేయండి&lt;/h4&gt;
+ &lt;p&gt;మీ వద్ద "HTTPS రక్షణ" లేదా "HTTPS స్కానింగ్" అందించే యాంటీవైరస్ సాఫ్ట్‌వేర్ ఉన్నట్లయితే మీకు ఈ ఎర్రర్ కనిపించవచ్చు. యాంటీవైరస్ కారణంగా Chrome భద్రతను అందించలేకపోతోంది.&lt;/p&gt;
+ &lt;p&gt;సమస్యను పరిష్కరించాలంటే, మీ యాంటీవైరస్ సాఫ్ట్‌వేర్‌ని ఆఫ్ చేయండి. సాఫ్ట్‌వేర్‌ని ఆఫ్ చేసిన తర్వాత పేజీ పని చేసినట్లయితే, మీరు సురక్షిత సైట్‌లను ఉపయోగించేటప్పుడు ఈ సాఫ్ట్‌వేర్‌ని ఆఫ్ చేయండి.&lt;/p&gt;
+ &lt;p&gt;మీ పని పూర్తయిన తర్వాత తప్పక మీ యాంటీవైరస్ ప్రోగ్రామ్‌ని తిరిగి ఆన్ చేయండి.&lt;/p&gt;
+ &lt;h4&gt;5వ దశ: అదనపు సహాయం పొందండి&lt;/h4&gt;
+ &lt;p&gt;ఇప్పటికీ మీకు ఎర్రర్ కనిపిస్తున్నట్లయితే, వెబ్‌సైట్ యజమానిని సంప్రదించండి.&lt;/p&gt;
+ &lt;h3&gt;"నెట్‌వర్క్‌కు కనెక్ట్ చేయండి"&lt;/h3&gt;
+ &lt;p&gt;ఆన్‌లైన్‌కి వెళ్లడం కంటే ముందు సైన్ ఇన్ చేయాల్సిన Wi-Fi పోర్టల్‌ని మీరు ఉపయోగిస్తున్నట్లయితే మీకు ఈ ఎర్రర్ కనిపించవచ్చు.&lt;/p&gt;
+ &lt;p&gt;ఎర్రర్‌ని పరిష్కరించాలంటే, మీరు తెరవాలనుకుంటున్న పేజీలో &lt;strong&gt;కనెక్ట్ చేయి&lt;/strong&gt;ని క్లిక్ చేయండి.&lt;/p&gt;
+ &lt;h3&gt;"మీ గడియారం ఆలస్యంగా ఉంది" లేదా "మీ గడియారం ముందుగా ఉంది" లేదా "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;మీ కంప్యూటర్ లేదా మొబైల్ పరికరం యొక్క తేదీ మరియు సమయం ఖచ్చితంగా లేకపోవడం వలన మీకు ఈ ఎర్రర్ కనిపిస్తుంది.&lt;/p&gt;
+ &lt;p&gt;ఎర్రర్‌ని పరిష్కరించాలంటే, మీ పరికరం యొక్క గడియారాన్ని తెరవండి. సమయం మరియు తేదీ సరిగ్గానే ఉన్నట్లు నిర్ధారించుకోండి.&lt;/p&gt;
+ &lt;h3&gt;"మీ కంప్యూటర్‌లోని సాఫ్ట్‌వేర్ కారణంగా Chrome సురక్షితంగా వెబ్‌కి కనెక్ట్ చేయలేకపోయింది" (Windows కంప్యూటర్‌లలో మాత్రమే)&lt;/h3&gt;
+ &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;li&gt;&lt;strong&gt;VisualDiscovery&lt;/strong&gt;ని ఎంచుకోండి
+ &lt;li&gt;&lt;strong&gt;ప్రారంభం రకం&lt;/strong&gt;లో, &lt;trong&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;వర్తింపజేయి&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="3615877443314183785">చెల్లుబాటు అయ్యే గడువు ముగింపు తేదీని నమోదు చేయండి</translation>
<translation id="36224234498066874">బ్రౌజింగ్ డేటాను క్లియర్ చెయ్యి...</translation>
<translation id="362276910939193118">పూర్తి చరిత్రను చూపించు</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">ఈ కార్డ్‌ని మీ Google ఖాతాకు మరియు ఈ పరికరంలో సేవ్ చేయాలనుకుంటున్నారా?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">గడువు ముగింపు <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929"><ph name="SITE" /> నుండి</translation>
<translation id="382518646247711829">మీరు ప్రాక్సీ సర్వర్‌ను ఉపయోగిస్తే...</translation>
<translation id="3828924085048779000">ఖాళీ పాస్‌ఫ్రేజ్ అనుమతించబడదు.</translation>
<translation id="385051799172605136">వెనుకకు</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">క్రాష్ నివేదిక ID <ph name="CRASH_ID" /> (స్థానిక క్రాష్ ID: <ph name="CRASH_LOCAL_ID" />) అప్‌లోడ్ చేయబడింది</translation>
<translation id="3949571496842715403">ఈ సర్వర్ తను <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రంలో విషయ ప్రత్యామ్నాయ పేర్లు పేర్కొనబడలేదు. తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా హ్యాకర్ మీ కనెక్షన్‌కి అంతరాయం కలిగించడం వలన ఇలా జరిగి ఉండవచ్చు.</translation>
<translation id="3949601375789751990">మీ బ్రౌజింగ్ చరిత్ర ఇక్కడ కనిపిస్తుంది</translation>
+<translation id="3950820424414687140">సైన్ ఇన్</translation>
<translation id="3963721102035795474">పాఠకుని మోడ్</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{ఏవీ కాదు}=1{1 సైట్ నుండి }other{# సైట్‌ల నుండి }}</translation>
<translation id="397105322502079400">గణిస్తోంది...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">పరికరం క్రమ సంఖ్య చెల్లదు</translation>
<translation id="410351446219883937">స్వీయ ప్లే</translation>
<translation id="4103763322291513355">నిరోధిత జాబితాలో ఉన్న URLల జాబితాను మరియు మీ సిస్టమ్ నిర్వాహకుని ద్వారా అమలు చేయబడిన ఇతర విధానాలను చూడటానికి &lt;strong&gt;chrome://policy&lt;/strong&gt;ని సందర్శించండి.</translation>
+<translation id="4110652170750985508">మీ చెల్లింపును సమీక్షించండి</translation>
<translation id="4116663294526079822">ఈ సైట్‌లో ఎల్లప్పుడూ అనుమతించు</translation>
<translation id="4117700440116928470">విధానం పరిధికి మద్దతు లేదు.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{మరో 1}other{మరో #}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(వినియోగదారు పేరు లేదు)</translation>
<translation id="4275830172053184480">మీ పరికరాన్ని పునఃప్రారంభించండి</translation>
<translation id="4280429058323657511">, గడువు ముగింపు <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">లాగిన్</translation>
<translation id="4312866146174492540">బ్లాక్ చేయి (డిఫాల్ట్)</translation>
<translation id="4325863107915753736">కథనాన్ని కనుగొనడం విఫలమైంది</translation>
<translation id="4326324639298822553">మీ గడువు ముగింపు తేదీని తనిఖీ చేసి, ఆపై మళ్లీ ప్రయత్నించండి</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">కార్డ్‌లు మరియు చిరునామాలు Chrome మరియు మీ Google ఖాతా (<ph name="ACCOUNT_EMAIL" />) నుండి పొందినవి. మీరు <ph name="BEGIN_LINK" />సెట్టింగ్‌లు<ph name="END_LINK" />లో వాటిని నిర్వహించవచ్చు.</translation>
<translation id="4522570452068850558">వివరాలు</translation>
<translation id="4552089082226364758">ఫ్లాష్</translation>
-<translation id="4554702541363482291"><ph name="SITE" />లో పొందుపరిచిన పేజీ నుండి</translation>
<translation id="4558551763791394412">మీ పొడిగింపులను నిలిపివేయడం ప్రయత్నించండి.</translation>
<translation id="457875822857220463">బట్వాడా</translation>
<translation id="4582800630050655161">మీరు మీ Google ఖాతాకు ప్రాప్యతను కోల్పోవచ్చు లేదా గుర్తింపు సమాచారం చౌర్యం కావచ్చు. Chromium వెంటనే మీ పాస్‌వర్డ్‌ను మార్చుకోవాల్సిందిగా సిఫార్సు చేస్తోంది.</translation>
<translation id="4587425331216688090">Chrome నుండి చిరునామాను తీసివేయాలా?</translation>
<translation id="4592951414987517459"><ph name="DOMAIN" />కి గల మీ కనెక్షన్ ఆధునిక సైఫర్ సూట్ ఉపయోగించి గుప్తీకరించబడింది.</translation>
<translation id="4594403342090139922">&amp;తొలగించడాన్ని రద్దు చేయి</translation>
-<translation id="4611292653554630842">లాగిన్ చేయండి</translation>
<translation id="4619615317237390068">ఇతర పరికరాల్లోని ట్యాబ్‌లు</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రంలో లోపాలు ఉన్నాయి. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కి అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">మీ కనెక్షన్‌కు అంతరాయం ఏర్పడింది</translation>
<translation id="471880041731876836">ఈ సైట్‌ను సందర్శించడానికి మీకు అనుమతి లేదు</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows నెట్‌వర్క్ సమస్య విశ్లేషణలను అమలు చేయడం<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">మీ చెల్లింపు</translation>
<translation id="4726672564094551039">విధానాలను మళ్లీ లోడ్ చేయి</translation>
<translation id="4728558894243024398">ప్లాట్‌ఫారమ్</translation>
<translation id="4736825316280949806">Chromiumని పునఃప్రారంభించండి</translation>
-<translation id="4737498291095696011">ఈ పేజీ నుండి</translation>
<translation id="4744603770635761495">అమలు చేయగల మార్గం</translation>
<translation id="4749685221585524849">చివరిగా ఉపయోగించినది <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">మీ సమాచారాన్ని (ఉదాహరణకు, పాస్‌వర్డ్‌లు లేదా క్రెడిట్ కార్డ్ నంబర్‌లు) ఈ సైట్‌కి పంపినప్పుడు అది ప్రైవేట్‌గా ఉంచబడుతుంది.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">వీక్షణ</translation>
<translation id="4854362297993841467">ఈ బట్వాడా పద్ధతి అందుబాటులో లేదు. వేరే పద్ధతిని ప్రయత్నించండి.</translation>
<translation id="4858792381671956233">ఈ సైట్‌ను సందర్శించడానికి అనుమతించమని కోరుతూ మీ తల్లిదండ్రులకు అభ్యర్థన పంపారు</translation>
-<translation id="4871132632506079383"><ph name="SITE" />లో పొందుపరిచిన పేజీ నుండి</translation>
<translation id="4880827082731008257">శోధన చరిత్ర</translation>
+<translation id="4881695831933465202">తెరువు</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">ప్రమాణీకరణ అవసరం</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{మరియు మరో 1 వెబ్ పేజీ}other{మరియు మరో # వెబ్ పేజీలు}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947"><ph name="CREDIT_CARD" /> కార్డ్ CVCని నమోదు చేయండి. మీరు నిర్ధారించిన తర్వాత, మీ Google చెల్లింపుల ఖాతా నుండి కార్డ్ వివరాలు ఈ సైట్‌తో షేర్ చేయబడతాయి.</translation>
<translation id="4923417429809017348">ఈ పేజీ తెలియని భాష నుండి <ph name="LANGUAGE_LANGUAGE" />కు అనువదించబడింది</translation>
<translation id="4923459931733593730">చెల్లింపు</translation>
<translation id="4926049483395192435">ఖచ్చితంగా పేర్కొనాలి.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> ఇలా చెబుతోంది</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">చర్యలు</translation>
<translation id="4958444002117714549">జాబితాను విస్తరించు</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">ప్రారంభిస్తే, వేగవంతమైన ఫారమ్ పూరింపు కోసం Chrome ఈ పరికరంలో మీ కార్డ్ కాపీని నిల్వ చేస్తుంది.</translation>
<translation id="5018422839182700155">ఈ పేజీని తెరవడం సాధ్యపడదు</translation>
<translation id="5019198164206649151">బ్యాకింగ్ నిల్వ చెల్లని స్థితిలో ఉంది</translation>
-<translation id="5020990877659450221">ఈ పేజీ నుండి</translation>
<translation id="5023310440958281426">మీ నిర్వాహకుని విధానాలను చూడండి</translation>
<translation id="5029568752722684782">కాపీని తీసివేయి</translation>
<translation id="503069730517007720">"<ph name="SOFTWARE_NAME" />" యొక్క రూట్ సర్టిఫికేట్ అవసరం, కానీ అది ఇన్‌స్టాల్ చేయబడలేదు. ఈ సమస్యను పరిష్కరించాలంటే, మీ IT నిర్వాహకులు "<ph name="SOFTWARE_NAME" />" యొక్క కాన్ఫిగరేషన్ సూచనలను పరిశీలించాలి. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">మెషీన్</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" />లో లేదా? ఈ లోపాన్ని నివేదించండి</translation>
<translation id="5190835502935405962">బుక్‌మార్క్‌ల బార్</translation>
+<translation id="5201306358585911203">ఈ పేజీలోని పొందుపరిచిన పేజీ ఇలా చెబుతోంది</translation>
<translation id="5205222826937269299">పేరు ఆవశ్యకం</translation>
<translation id="5222812217790122047">ఇమెయిల్ ఆవశ్యకం</translation>
<translation id="522700295135997067">ఈ సైట్ ఇప్పుడే మీ పాస్‌వర్డ్‌ను దొంగిలించి ఉండటానికి ఆస్కారం ఉంది</translation>
<translation id="5230733896359313003">బట్వాడా చిరునామా</translation>
<translation id="5251803541071282808">క్లౌడ్</translation>
-<translation id="5277279256032773186">కార్యాలయంలో Chrome ఉపయోగిస్తున్నారా? వ్యాపార సంస్థలు తమ ఉద్యోగుల కోసం Chrome సెట్టింగ్‌లను నిర్వహించగలవు. మరింత తెలుసుకోండి</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />సాఫ్ట్‌వేర్‌ను తాత్కాలికంగా నిలిపివేయడానికి ఈ దశలను పాటించండి తద్వారా మీరు వెబ్‌ను ప్రాప్యత చేయవచ్చు. మీకు నిర్వాహక అధికారాలు అవసరం.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">కనెక్షన్‌ను తనిఖీ చేయడం</translation>
<translation id="5610807607761827392">మీరు కార్డ్‌లు మరియు చిరునామాలను <ph name="BEGIN_LINK" />సెట్టింగ్‌ల<ph name="END_LINK" />లో నిర్వహించగలరు.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> మిమ్మల్ని అనేక సార్లు దారి మళ్లించింది.</translation>
-<translation id="5622887735448669177">మీరు ఈ సైట్‌ నుండి నిష్క్రమించాలనుకుంటున్నారా?</translation>
<translation id="5629630648637658800">విధాన సెట్టింగ్‌లను లోడ్ చేయడంలో విఫలమైంది</translation>
<translation id="5631439013527180824">చెల్లని పరికర నిర్వహణ టోకెన్</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">మీరు మీ కార్డ్ సమాచారం పూరించాలనుకుంటున్నారా?</translation>
<translation id="5803412860119678065">మీరు మీ <ph name="CARD_DETAIL" /> కార్డ్ సమాచారం పూరించాలనుకుంటున్నారా?</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" />కి గల మీ కనెక్షన్ వాడుకలో లేని సైఫర్ సూట్ ఉపయోగించి గుప్తీకరించబడింది.</translation>
-<translation id="5810928923025889964">ఈ పేజీలోని పొందుపరిచిన పేజీ నుండి</translation>
<translation id="5813119285467412249">&amp;జోడించడాన్ని పునరావృతం చేయి</translation>
<translation id="5838278095973806738">మీరు ఈ సైట్‌లో ఎలాంటి గోప్యమైన సమాచారాన్ని నమోదు చేయకూడదు (ఉదాహరణకు, పాస్‌వర్డ్‌లు లేదా క్రెడిట్ కార్డ్‌లు), దాడికి పాల్పడేవారు ఆ సమాచారం దొంగిలించే అవకాశం ఉంటుంది.</translation>
<translation id="5866257070973731571">ఫోన్ నంబర్‌ను జోడించండి</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">మరింత సమాచారాన్ని జోడించండి</translation>
<translation id="6447842834002726250">కుక్కీలు</translation>
<translation id="6451458296329894277">ఫారమ్ పునఃసమర్పణను నిర్థారించండి</translation>
-<translation id="6456339708790392414">మీ చెల్లింపు</translation>
<translation id="647261751007945333">పరికర విధానాలు</translation>
<translation id="6477321094435799029">Chrome ఈ పేజీలో అసాధారణ కోడ్‌ను గుర్తించింది మరియు మీ వ్యక్తిగత సమాచారం (ఉదాహరణకు, పాస్‌వర్డ్‌లు, ఫోన్ నంబర్‌లు మరియు క్రెడిట్ కార్డ్‌లు) రక్షించడానికి దాన్ని బ్లాక్ చేసింది.</translation>
<translation id="6489534406876378309">క్రాష్‌లను అప్‌లోడ్ చేయడాన్ని ప్రారంభించండి</translation>
<translation id="6507833130742554667">క్రెడిట్ మరియు డెబిట్ కార్డ్‌లు ఆమోదించబడతాయి.</translation>
<translation id="6508722015517270189">Chromeను పునఃప్రారంభించండి</translation>
-<translation id="6521373090216409766">మీరు ఈ సైట్‌ను మళ్లీ లోడ్ చేయాలనుకుంటున్నారా?</translation>
<translation id="6529602333819889595">&amp;తొలగించడాన్ని పునరావృతం చేయి</translation>
<translation id="6534179046333460208">ప్రత్యక్ష వెబ్ సూచనలు</translation>
<translation id="6550675742724504774">ఎంపికలు</translation>
-<translation id="6556239504065605927">సురక్షిత కనెక్షన్</translation>
<translation id="6556915248009097796">గడువు ముగింపు: <ph name="EXPIRATION_DATE_ABBR" />, చివరిగా ఉపయోగించినది <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">మీ నిర్వాహకుడు దీన్ని ఇంకా ఆమోదించలేదు</translation>
<translation id="6569060085658103619">మీరు పొడిగింపు పేజీని వీక్షిస్తున్నారు</translation>
<translation id="6596325263575161958">గుప్తీకరణ ఎంపికలు</translation>
+<translation id="6604181099783169992">చలనం లేదా కాంతి సర్దుబాటు సెన్సార్‌లు</translation>
<translation id="6624427990725312378">సంప్రదింపు సమాచారం</translation>
<translation id="6626291197371920147">చెల్లుబాటయ్యే కార్డ్ నంబర్‌ను జోడించండి</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> శోధన</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">నిర్వహించబడిన బుక్‌మార్క్‌లు</translation>
<translation id="7298195798382681320">సిఫార్సు చేయబడినవి</translation>
<translation id="7309308571273880165"><ph name="CRASH_TIME" /> తేదీన సంగ్రహించిన క్రాష్ నివేదిక (అప్‌లోడ్ చేయాల్సిందిగా వినియోగదారుకు అభ్యర్థన, ఇంకా అప్‌లోడ్ చేయలేదు)</translation>
+<translation id="7320336641823683070">కనెక్షన్ సహాయం</translation>
<translation id="7334320624316649418">&amp;మళ్లీ క్రమం చేయడాన్ని పునరావృతం చేయి</translation>
<translation id="733923710415886693">సర్వర్ ప్రమాణపత్రాన్ని ప్రమాణపత్రం పారదర్శకత ద్వారా బహిరంగపరచలేదు.</translation>
<translation id="7353601530677266744">ఆదేశ పంక్తి</translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">మీరు ఉపయోగిస్తున్న Wi-Fi (<ph name="WIFI_NAME" />)కి మీరు దాని లాగిన్ పేజీని సందర్శించడం అవసరం.</translation>
<translation id="785549533363645510">అయితే, మీరు అదృశ్యంగా ఉండరు. అజ్ఞాతంలోకి వెళ్లడం వలన మీ బ్రౌజింగ్ మీ యజమానికి, మీ ఇంటర్నెట్ సేవా ప్రదాతకు లేదా మీరు సందర్శించే వెబ్‌సైట్‌లకు కనిపించకుండా దాచబడదు.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">సైట్ నుండి నిష్క్రమించాలా?</translation>
<translation id="7878176543348854470">డెబిట్ మరియు ప్రీపెయిడ్ కార్డ్‌లు ఆమోదించబడతాయి.</translation>
<translation id="7878562273885520351">మీ పాస్‌వర్డ్ ఎవరికైనా తెలిసిపోయి ఉండవచ్చు</translation>
<translation id="7887683347370398519">మీ CVCని తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">సార్వజనీన డిఫాల్ట్‌ను ఉపయోగించు (అడుగు)</translation>
<translation id="8042918947222776840">పికప్ పద్ధతిని ఎంచుకోండి</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />"ని సరిగ్గా కాన్ఫిగర్ చేయలేదు. సాధారణంగా "<ph name="SOFTWARE_NAME" />"ని అన్ఇన్‌స్టాల్ చేయడం ద్వారా సమస్య పరిష్కారం కావచ్చు. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">సైట్‌ని తిరిగి లోడ్ చేయాలా?</translation>
<translation id="8088680233425245692">కథనాన్ని వీక్షించడంలో విఫలమైంది.</translation>
<translation id="8091372947890762290">సక్రియం సర్వర్‌లో పెండింగ్‌లో ఉంది</translation>
<translation id="8094917007353911263">మీరు ఉపయోగిస్తున్న నెట్‌వర్క్‌కి మీరు <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />ని సందర్శించడం అవసరం.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">ID "<ph name="EXTENSION_ID" />" ఉన్న పొడిగింపు కోసం నవీకరణ URL చెల్లదు.</translation>
<translation id="8202097416529803614">ఆర్డర్ సారాంశం</translation>
<translation id="8205463626947051446">సైట్ అనుచితమైన ప్రకటనలను చూపవచ్చు</translation>
+<translation id="8211406090763984747">కనెక్షన్ సురక్షితంగా ఉంది</translation>
<translation id="8218327578424803826">కేటాయించిన స్థానం:</translation>
<translation id="8225771182978767009">ఈ కంప్యూటర్‌ను సెటప్ చేసిన వ్యక్తి ఈ సైట్‌ను బ్లాక్ చేయడానికి ఎంచుకున్నారు.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">సేవ్ చేసిన అన్ని పాస్‌వర్డ్‌లను చూపండి</translation>
<translation id="8261506727792406068">తొలగించు</translation>
<translation id="8267698848189296333"><ph name="USERNAME" />గా సైన్ ఇన్ చేస్తోంది</translation>
+<translation id="8286036467436129157">సైన్ ఇన్ చేయండి</translation>
<translation id="8288807391153049143">సర్టిఫికేట్‌ని చూపు</translation>
<translation id="8289355894181816810">మీకు దీని గురించి ఖచ్చితంగా తెలియకుంటే మీ నెట్‌వర్క్ నిర్వాహకుని సంప్రదించండి.</translation>
<translation id="8293206222192510085">బుక్‌మార్క్‌లను జోడించు</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">ఆమోదించే క్రెడిట్ మరియు ప్రీపెయిడ్ కార్డ్‌లు</translation>
<translation id="8759274551635299824">ఈ కార్డ్ గడువు ముగిసింది</translation>
<translation id="8761567432415473239">Google సురక్షిత బ్రౌజింగ్ ఇటీవల <ph name="SITE" />లో <ph name="BEGIN_LINK" />హానికర ప్రోగ్రామ్‍లను కనుగొనింది<ph name="END_LINK" />.</translation>
+<translation id="8763927697961133303">USB పరికరం</translation>
<translation id="8790007591277257123">&amp;తొలగించడాన్ని పునరావృతం చేయి</translation>
<translation id="8800988563907321413">మీ సమీపంలోని సూచనలు ఇక్కడ కనిపిస్తాయి</translation>
<translation id="8820817407110198400">బుక్‌మార్క్‌లు</translation>
diff --git a/chromium/components/strings/components_strings_th.xtb b/chromium/components/strings/components_strings_th.xtb
index 9fb4e0df483..04ffd0b0993 100644
--- a/chromium/components/strings/components_strings_th.xtb
+++ b/chromium/components/strings/components_strings_th.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;พิมพ์...</translation>
<translation id="1181037720776840403">ลบ</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />รายงาน<ph name="END_WHITEPAPER_LINK" />รายละเอียดของเหตุการณ์ความปลอดภัยที่เป็นไปได้ต่อ Google โดยอัตโนมัติ <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">การชำระเงินไม่เสร็จสมบูรณ์</translation>
<translation id="1201402288615127009">ถัดไป</translation>
<translation id="1201895884277373915">เพิ่มเติมจากไซต์นี้</translation>
<translation id="1206967143813997005">ลายเซ็นเริ่มต้นไม่ถูกต้อง</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">รายงานข้อขัดข้องเมื่อ <ph name="CRASH_TIME" /> (ยังไม่ได้อัปโหลดหรือละเว้น)</translation>
<translation id="1270502636509132238">วิธีการรับสินค้า</translation>
<translation id="1285320974508926690">ไม่ต้องแปลไซต์นี้</translation>
+<translation id="1294154142200295408">บรรทัดคำสั่งรูปแบบต่างๆ</translation>
<translation id="129553762522093515">เพิ่งปิด</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />ลองล้างคุกกี้<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">ผู้อื่น<ph name="BEGIN_EMPHASIS" />อาจยังมองเห็น<ph name="END_EMPHASIS" />กิจกรรมของคุณ:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">บัตรเครดิตและบัตรเดบิตที่ยอมรับ</translation>
<translation id="1519264250979466059">วันที่สร้าง</translation>
<translation id="1527263332363067270">กำลังรอการเชื่อมต่อ…</translation>
+<translation id="1532118530259321453">หน้านี้บอกว่า</translation>
<translation id="153384715582417236">เสร็จเรียบร้อย</translation>
<translation id="154408704832528245">เลือกที่อยู่สำหรับนำส่งสินค้า</translation>
<translation id="1549470594296187301">ต้องเปิดใช้ JavaScript เพื่อใช้ฟีเจอร์นี้</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />ตรวจสอบพร็อกซีและไฟร์วอลล์<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">รหัสไปรษณีย์</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 คำแนะนำ}other{# คำแนะนำ}}</translation>
-<translation id="2065985942032347596">ต้องมีการตรวจสอบความถูกต้อง</translation>
<translation id="2079545284768500474">เลิกทำ</translation>
<translation id="20817612488360358">มีการกำหนดให้ใช้การตั้งค่าพร็อกซีระบบ แต่ก็มีการระบุการกำหนดค่าพร็อกซีอย่างชัดเจนไว้ด้วยเช่นกัน</translation>
<translation id="2091887806945687916">เสียง</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">ยกเลิกการชำระเงิน</translation>
<translation id="2147827593068025794">การซิงค์ในแบ็กกราวด์</translation>
<translation id="2148613324460538318">เพิ่มบัตร</translation>
-<translation id="2149973817440762519">แก้ไขบุ๊กมาร์ก</translation>
<translation id="2154054054215849342">ไม่มีการซิงค์สำหรับโดเมนของคุณ</translation>
<translation id="2154484045852737596">แก้ไขบัตร</translation>
<translation id="2166049586286450108">การเข้าถึงระดับผู้ดูแลระบบโดยสมบูรณ์</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">เลือกที่อยู่สำหรับรับสินค้า</translation>
<translation id="2740531572673183784">ตกลง</translation>
<translation id="2742870351467570537">นำรายการที่เลือกออก </translation>
-<translation id="2744590937989388266">จากหน้าที่ฝังไว้ในหน้าเว็บนี้</translation>
<translation id="277133753123645258">วิธีการจัดส่งสินค้า</translation>
<translation id="277499241957683684">ไม่มีอุปกรณ์บันทึก</translation>
<translation id="2784949926578158345">การเชื่อมต่อได้รับการรีเซ็ตแล้ว</translation>
<translation id="2788784517760473862">บัตรเครดิตที่ยอมรับ</translation>
<translation id="2794233252405721443">เว็บไซต์ที่ถูกบล็อก</translation>
-<translation id="2795286477369100655">คุณต้องการออกจากเว็บไซต์นี้ใช่ไหม</translation>
<translation id="2799020568854403057">ไซต์ที่จะเปิดมีแอปอันตราย</translation>
<translation id="2803306138276472711">เมื่อเร็วๆ นี้ Google Safe Browsing <ph name="BEGIN_LINK" />ตรวจพบมัลแวร์<ph name="END_LINK" />ใน <ph name="SITE" /> เว็บไซต์ที่โดยปกติจะปลอดภัยบางครั้งอาจติดมัลแวร์</translation>
<translation id="2824775600643448204">ที่อยู่และแถบค้นหา</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">รายการที่เข้ามา "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">ถูกบล็อกโดยอัตโนมัติ</translation>
<translation id="3024663005179499861">ประเภทนโยบายไม่ถูกต้อง</translation>
-<translation id="3032412215588512954">คุณต้องการโหลดเว็บไซต์นี้ซ้ำใช่ไหม</translation>
<translation id="3037605927509011580">แย่จัง!</translation>
<translation id="3039538478787849737">บันทึกบัตรไว้ใน Google ไหม</translation>
<translation id="3041612393474885105">ข้อมูลในใบรับรอง</translation>
@@ -310,6 +306,7 @@
ตรวจสอบว่าพร็อกซีเซิร์ฟเวอร์ทำงานอยู่ หากคุณคิดว่าไม่ควร
ใช้พร็อกซีเซิร์ฟเวอร์ ให้ดำเนินการดังนี้:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> ใน <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">ยกเลิกการชำระเงิน</translation>
<translation id="3207960819495026254">บุ๊กมาร์กแล้ว</translation>
<translation id="3209375525920864198">โปรดป้อนชื่อเซสชันที่ถูกต้อง</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">ผู้จัดการสามารถเลิกบล็อกเว็บไซต์ให้คุณ</translation>
<translation id="3566021033012934673">การเชื่อมต่อของคุณไม่เป็นส่วนตัว</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">หน้าที่ฝังไว้ใน <ph name="SITE" /> บอกว่า</translation>
<translation id="358285529439630156">รับบัตรเครดิตและบัตรเติมเงิน</translation>
<translation id="3582930987043644930">เพิ่มชื่อ</translation>
<translation id="3583757800736429874">&amp;ทำซ้ำการย้าย</translation>
<translation id="3586931643579894722">ซ่อนรายละเอียด</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;แก้ไขข้อผิดพลาดในการเชื่อมต่อ&lt;/h1&gt;
+ &lt;p&gt;หากคุณได้รับข้อความแสดงข้อผิดพลาดเมื่อพยายามเข้าชมเว็บไซต์ ลองทำตามวิธีแก้ไขต่อไปนี้&lt;/p&gt;
+ &lt;h2&gt;แก้ไขข้อผิดพลาดในการเชื่อมต่อส่วนใหญ่&lt;/h2&gt;
+ &lt;p&gt;หากคุณพยายามเข้าชมเว็บไซต์ แต่เว็บไซต์ไม่เปิดขึ้นมา ให้ลองแก้ข้อผิดพลาดด้วยขั้นตอนการแก้ปัญหาต่อไปนี้&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;ตรวจสอบที่อยู่เว็บไซต์ว่ามีการพิมพ์ผิดหรือไม่&lt;/li&gt;
+ &lt;li&gt;ตรวจสอบว่าการเชื่อมต่ออินเทอร์เน็ตใช้งานได้ปกติ&lt;/li&gt;
+ &lt;li&gt;ติดต่อเจ้าของเว็บไซต์&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;รับความช่วยเหลือเกี่ยวกับข้อความแสดงข้อผิดพลาดที่เจาะจง&lt;/h2&gt;
+ &lt;h3&gt;"การเชื่อมต่อไม่เป็นส่วนตัว" หรือ "NET::ERR_CERT_AUTHORITY_INVALID" หรือ "ERR_CERT_COMMON_NAME_INVALID" หรือ "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" หรือ "ข้อผิดพลาดของใบรับรอง SSL"&lt;/h3&gt;
+ &lt;h4&gt;ขั้นตอนที่ 1: ลงชื่อเข้าใช้พอร์ทัล&lt;/h4&gt;
+ &lt;p&gt;เครือข่าย Wi-Fi ในสถานที่หลายแห่งอย่างร้านกาแฟหรือสนามบินจำเป็นต้องให้คุณลงชื่อเข้าใช้ หากต้องการดูหน้าลงชื่อเข้าใช้ โปรดไปที่หน้าเว็บที่ใช้ &lt;code&gt;http://&lt;/code&gt;&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;ไปยังเว็บไซต์ที่ขึ้นต้นด้วย &lt;code&gt;http://&lt;/code&gt; เช่น &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;&lt;/li&gt;
+ &lt;li&gt;ในหน้าลงชื่อเข้าใช้ที่เปิดขึ้นมา ให้ลงชื่อเข้าใช้เพื่อใช้อินเทอร์เน็ต&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;ขั้นตอนที่ 2: เปิดหน้าเว็บในโหมดไม่ระบุตัวตน (เฉพาะคอมพิวเตอร์)&lt;/h4&gt;
+ &lt;p&gt;เปิดหน้าเว็บที่คุณได้เข้าชมในหน้าต่างที่ไม่ระบุตัวตน&lt;/p&gt;
+ &lt;p&gt;หากหน้าเว็บเปิดขึ้นมาแต่ส่วนขยาย Chrome ทำงานผิดปกติ ให้ปิดส่วนขยายนั้นเพื่อแก้ไขข้อผิดพลาด&lt;/p&gt;
+ &lt;h4&gt;ขั้นตอนที่ 3: อัปเดตระบบปฏิบัติการ&lt;/h4&gt;
+ &lt;p&gt;ตรวจสอบว่าอัปเดตระบบปฏิบัติการของอุปกรณ์เป็นเวอร์ชันล่าสุดแล้ว&lt;/p&gt;
+ &lt;h4&gt;ขั้นตอนที่ 4: ปิดโปรแกรมป้องกันไวรัสชั่วคราว&lt;/h4&gt;
+ &lt;p&gt;คุณจะเห็นการตั้งค่านี้หากอุปกรณ์มีซอฟต์แวร์ป้องกันไวรัสที่ให้ "การป้องกัน HTTPS" หรือ "การสแกน HTTPS" ซึ่งขัดขวางการรักษาความปลอดภัยของ Chrome&lt;/p&gt;
+ &lt;p&gt;ปิดซอฟต์แวร์ป้องกันไวรัสเพื่อการแก้ไขปัญหานี้ หากหน้าเว็บทำงานเป็นปกติหลังจากปิดซอฟต์แวร์แล้ว ให้ปิดซอฟต์แวร์นี้เมื่อคุณใช้งานเว็บไซต์ที่มีความปลอดภัย&lt;/p&gt;
+ &lt;p&gt;อย่าลืมเปิดโปรแกรมป้องกันไวรัสเมื่อใช้งานเว็บไซต์เสร็จแล้ว&lt;/p&gt;
+ &lt;h4&gt;ขั้นตอนที่ 5: รับความช่วยเหลือเพิ่มเติม&lt;/h4&gt;
+ &lt;p&gt;หากคุณยังคงเห็นข้อผิดพลาด ให้ติดต่อเจ้าของเว็บไซต์&lt;/p&gt;
+ &lt;h3&gt;"เชื่อมต่อเครือข่าย"&lt;/h3&gt;
+ &lt;p&gt;คุณจะเห็นข้อผิดพลาดนี้หากกำลังใช้พอร์ทัล Wi-Fi ที่ต้องลงชื่อเข้าใช้เพื่อออนไลน์&lt;/p&gt;
+ &lt;p&gt;ในการแก้ไขข้อผิดพลาด ให้คลิก&lt;strong&gt;เชื่อมต่อ&lt;/strong&gt;ในหน้าเว็บที่คุณจะเปิด&lt;/p&gt;
+ &lt;h3&gt;"นาฬิกาของคุณช้ากว่าปัจจุบัน" หรือ "นาฬิกาของคุณเร็วกว่าปัจจุบัน" หรือ "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;คุณจะเห็นข้อผิดพลาดนี้หากวันที่และเวลาของคอมพิวเตอร์หรืออุปกรณ์เคลื่อนที่ไม่ถูกต้อง&lt;/p&gt;
+ &lt;p&gt;ในการแก้ไขข้อผิดพลาด ให้เปิดนาฬิกาของอุปกรณ์ แล้วตรวจสอบว่าวันที่และเวลาถูกต้อง&lt;/p&gt;
+ &lt;h3&gt;"ซอฟต์แวร์ในคอมพิวเตอร์ของคุณทำให้ Chrome เชื่อมต่อกับเว็บอย่างปลอดภัยไม่ได้" (คอมพิวเตอร์ที่ใช้ระบบปฏิบัติการ Windows เท่านั้น)&lt;/h3&gt;
+ &lt;p&gt;คุณจะเห็นข้อผิดพลาดนี้ หากคุณมีซอฟต์แวร์ Superfish ในคอมพิวเตอร์ที่ใช้ระบบปฏิบัติการ Windows&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;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;
+ &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="3615877443314183785">ป้อนวันที่หมดอายุที่ถูกต้อง</translation>
<translation id="36224234498066874">ล้างข้อมูลการท่องเว็บ</translation>
<translation id="362276910939193118">แสดงประวัติการเข้าชมทั้งหมด</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">คุณต้องการบันทึกบัตรนี้ลงในบัญชี Google และในอุปกรณ์นี้ไหม</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">หมดอายุ <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">จาก <ph name="SITE" /></translation>
<translation id="382518646247711829">หากคุณใช้พร็อกซีเซิร์ฟเวอร์...</translation>
<translation id="3828924085048779000">ข้อความรหัสผ่านต้องไม่เว้นว่างไว้</translation>
<translation id="385051799172605136">กลับ</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">อัปโหลดรหัสรายงานข้อขัดข้อง <ph name="CRASH_ID" /> แล้ว (รหัสข้อขัดข้องในเครื่อง: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">เซิร์ฟเวอร์นี้ไม่สามารถพิสูจน์ได้ว่าเป็น <ph name="DOMAIN" /> เพราะใบรับรองความปลอดภัยไม่ได้ระบุชื่อสำรองของหัวเรื่อง โดยอาจเกิดจากการกำหนดค่าผิดหรือผู้โจมตีที่ขัดขวางการเชื่อมต่อของคุณ</translation>
<translation id="3949601375789751990">ประวัติการท่องเว็บของคุณจะปรากฏที่นี่</translation>
+<translation id="3950820424414687140">ลงชื่อเข้าใช้</translation>
<translation id="3963721102035795474">โหมดนักอ่าน</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{ไม่มี}=1{จากเว็บไซต์ 1 แห่ง }other{จากเว็บไซต์ # แห่ง }}</translation>
<translation id="397105322502079400">กำลังคำนวณ...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">หมายเลขซีเรียลของอุปกรณ์ไม่ถูกต้อง</translation>
<translation id="410351446219883937">เล่นอัตโนมัติ</translation>
<translation id="4103763322291513355">ไปที่ &lt;strong&gt;chrome://policy&lt;/strong&gt; เพื่อดูรายการของ URL ที่ไม่ได้รับอนุญาต และนโยบายอื่นๆ ที่ผู้ดูแลระบบของคุณบังคับใช้</translation>
+<translation id="4110652170750985508">ตรวจสอบการชำระเงิน</translation>
<translation id="4116663294526079822">อนุญาตบนไซต์นี้เสมอ</translation>
<translation id="4117700440116928470">ขอบข่ายนโยบายไม่ได้รับการสนับสนุน</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{อีก 1 รายการ}other{อีก # รายการ}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(ไม่มีชื่อผู้ใช้)</translation>
<translation id="4275830172053184480">รีสตาร์ทอุปกรณ์ของคุณ</translation>
<translation id="4280429058323657511">หมดอายุ <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">เข้าสู่ระบบ</translation>
<translation id="4312866146174492540">บล็อก (ค่าเริ่มต้น)</translation>
<translation id="4325863107915753736">การค้นหาบทความล้มเหลว</translation>
<translation id="4326324639298822553">ตรวจสอบวันหมดอายุแล้วลองอีกครั้ง</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">ข้อมูลบัตรและที่อยู่มาจาก Chrome และบัญชี Google (<ph name="ACCOUNT_EMAIL" />) คุณสามารถจัดการข้อมูลเหล่านี้ใน<ph name="BEGIN_LINK" />การตั้งค่า<ph name="END_LINK" /></translation>
<translation id="4522570452068850558">รายละเอียด</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">จากหน้าที่ฝังไว้ที่ <ph name="SITE" /></translation>
<translation id="4558551763791394412">ลองปิดใช้ส่วนขยาย</translation>
<translation id="457875822857220463">การจัดส่ง</translation>
<translation id="4582800630050655161">คุณอาจไม่สามารถเข้าถึงบัญชี Google หรือถูกโจรกรรมข้อมูลประจำตัว Chromium ขอแนะนำให้เปลี่ยนรหัสผ่านตอนนี้เลย</translation>
<translation id="4587425331216688090">นำที่อยู่ออกจาก Chrome ไหม</translation>
<translation id="4592951414987517459">มีการเข้ารหัสการเชื่อมต่อของคุณกับ <ph name="DOMAIN" /> ด้วยชุดการเข้ารหัสที่ทันสมัย</translation>
<translation id="4594403342090139922">&amp;เลิกทำการนำออก</translation>
-<translation id="4611292653554630842">ลงชื่อเข้าสู่ระบบ</translation>
<translation id="4619615317237390068">แท็บจากอุปกรณ์อื่นๆ</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">เซิร์ฟเวอร์นี้ไม่สามารถพิสูจน์ได้ว่าเป็น <ph name="DOMAIN" /> เพราะใบรับรองความปลอดภัยมีข้อผิดพลาด โดยอาจเกิดจากการกำหนดค่าผิดหรือผู้บุกรุกที่ขัดขวางการเชื่อมต่อของคุณ</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">การเชื่อมต่อของคุณขัดข้อง</translation>
<translation id="471880041731876836">คุณไม่มีสิทธิ์เข้าชมไซต์นี้</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />เรียกใช้การวินิจฉัยเครือข่ายของ Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">การชำระเงินของคุณ</translation>
<translation id="4726672564094551039">โหลดนโยบายซ้ำ</translation>
<translation id="4728558894243024398">แพลตฟอร์ม</translation>
<translation id="4736825316280949806">รีสตาร์ท Chromium</translation>
-<translation id="4737498291095696011">จากหน้านี้</translation>
<translation id="4744603770635761495">เส้นทางปฏิบัติการ</translation>
<translation id="4749685221585524849">ใช้ล่าสุดเมื่อ <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">ข้อมูลของคุณ (ตัวอย่างเช่น รหัสผ่านหรือหมายเลขบัตรเครดิต) จะเป็นส่วนตัวเมื่อส่งมายังเว็บไซต์นี้</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">มุมมอง</translation>
<translation id="4854362297993841467">วิธีการนำส่งสินค้านี้ไม่พร้อมให้บริการ โปรดลองใช้วิธีการอื่น</translation>
<translation id="4858792381671956233">คุณถามผู้ปกครองแล้วว่าสามารถเข้าชมเว็บไซต์นี้ได้ไหม</translation>
-<translation id="4871132632506079383">จากหน้าที่ฝังไว้ที่ <ph name="SITE" /></translation>
<translation id="4880827082731008257">ค้นประวัติการเข้าชม</translation>
+<translation id="4881695831933465202">เปิด</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" /> และ <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">ต้องมีการตรวจสอบสิทธิ์</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{และหน้าเว็บอีก 1 หน้า}other{และหน้าเว็บอีก # หน้า}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">ป้อน CVC สำหรับ <ph name="CREDIT_CARD" /> เมื่อยืนยันแล้ว ระบบจะแชร์รายละเอียดของบัตรจากบัญชี Google Payments กับเว็บไซต์นี้</translation>
<translation id="4923417429809017348">หน้านี้แปลจากภาษาที่ไม่รู้จักเป็นภาษา <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">การชำระเงิน</translation>
<translation id="4926049483395192435">ต้องระบุ</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> บอกว่า</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">การทำงาน</translation>
<translation id="4958444002117714549">ขยายรายการ</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">หากเปิดใช้ Chrome จะเก็บสำเนาการ์ดของคุณในอุปกรณ์นี้เพื่อให้การกรอกฟอร์มทำได้เร็วขึ้น</translation>
<translation id="5018422839182700155">ไม่สามารถเปิดหน้านี้</translation>
<translation id="5019198164206649151">ไม่สามารถจัดเก็บเนื่องจากระบบแบ็คเอนด์อยู่ในสถานะไม่ดี</translation>
-<translation id="5020990877659450221">จากหน้านี้</translation>
<translation id="5023310440958281426">ตรวจสอบนโยบายของผู้ดูแลระบบของคุณ</translation>
<translation id="5029568752722684782">ล้างสำเนา</translation>
<translation id="503069730517007720">ไม่ได้ติดตั้งใบรับรองรากที่จำเป็นของ "<ph name="SOFTWARE_NAME" />" ผู้ดูแลระบบ IT ควรดูวิธีการกำหนดค่าของ "<ph name="SOFTWARE_NAME" />" เพื่อแก้ไขปัญหานี้ <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">ผู้ใช้คอมพิวเตอร์นี้</translation>
<translation id="5179510805599951267">หากไม่มีในภาษา <ph name="ORIGINAL_LANGUAGE" /> ให้รายงานข้อผิดพลาดนี้</translation>
<translation id="5190835502935405962">แถบบุ๊กมาร์ก</translation>
+<translation id="5201306358585911203">หน้าที่ฝังไว้ในหน้าเว็บนี้บอกว่า</translation>
<translation id="5205222826937269299">ต้องระบุชื่อ</translation>
<translation id="5222812217790122047">ต้องระบุอีเมล</translation>
<translation id="522700295135997067">ไซต์นี้อาจเพิ่งขโมยรหัสผ่านของคุณไป</translation>
<translation id="5230733896359313003">ที่อยู่ในการจัดส่ง</translation>
<translation id="5251803541071282808">ระบบคลาวด์</translation>
-<translation id="5277279256032773186">หากใช้ Chrome ที่ทำงาน ธุรกิจสามารถจัดการการตั้งค่า Chrome ให้พนักงานของตนได้ เรียนรู้เพิ่มเติม</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />ทำตามขั้นตอนการปิดใช้ซอฟต์แวร์ชั่วคราวต่อไปนี้เพื่อให้เข้าสู่เว็บได้ คุณจะต้องมีสิทธิ์ของผู้ดูแลระบบ<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">ตรวจสอบการเชื่อมต่อ</translation>
<translation id="5610807607761827392">คุณสามารถจัดการบัตรและที่อยู่ใน<ph name="BEGIN_LINK" />การตั้งค่า<ph name="END_LINK" /></translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> เปลี่ยนเส้นทางของคุณบ่อยเกินไป</translation>
-<translation id="5622887735448669177">คุณต้องการออกจากเว็บไซต์นี้ใช่ไหม</translation>
<translation id="5629630648637658800">ไม่สามารถโหลดการตั้งค่านโยบาย</translation>
<translation id="5631439013527180824">โทเค็นการจัดการอุปกรณ์ไม่ถูกต้อง</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">คุณต้องการกรอกข้อมูลบัตรไหม</translation>
<translation id="5803412860119678065">คุณต้องการกรอกข้อมูล <ph name="CARD_DETAIL" /> ไหม</translation>
<translation id="5810442152076338065">มีการเข้ารหัสการเชื่อมต่อของคุณกับ <ph name="DOMAIN" /> ด้วยชุดการเข้ารหัสที่ล้าสมัยแล้ว</translation>
-<translation id="5810928923025889964">จากหน้าที่ฝังไว้ในหน้าเว็บนี้</translation>
<translation id="5813119285467412249">&amp;ทำซ้ำการเพิ่ม</translation>
<translation id="5838278095973806738">คุณไม่ควรป้อนข้อมูลที่ละเอียดอ่อนบนเว็บไซต์นี้ (ตัวอย่างเช่น รหัสผ่านหรือบัตรเครดิต) เนื่องจากผู้โจมตีอาจขโมยข้อมูลดังกล่าวไปได้</translation>
<translation id="5866257070973731571">เพิ่มหมายเลขโทรศัพท์</translation>
@@ -693,7 +729,7 @@
<translation id="614940544461990577">ลอง:</translation>
<translation id="6151417162996330722">ใบรับรองเซิร์ฟเวอร์มีระยะเวลาที่สามารถใช้ได้นานเกินไป</translation>
<translation id="6157877588268064908">หากต้องการดูวิธีการจัดส่งสินค้าและข้อกำหนด โปรดเลือกที่อยู่</translation>
-<translation id="6165508094623778733">เรียนรู้เพิ่มเติม</translation>
+<translation id="6165508094623778733">ดูข้อมูลเพิ่มเติม</translation>
<translation id="6169916984152623906">ขณะนี้คุณสามารถท่องเว็บแบบเป็นส่วนตัว และผู้อื่นที่ใช้อุปกรณ์เครื่องนี้จะไม่เห็นกิจกรรมของคุณ แต่จะมีการบันทึกการดาวน์โหลดและบุ๊กมาร์กไว้</translation>
<translation id="6177128806592000436">การเชื่อมต่อกับเว็บไซต์นี้ไม่ปลอดภัย</translation>
<translation id="6203231073485539293">ตรวจสอบการเชื่อมต่ออินเทอร์เน็ต</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">เพิ่มข้อมูลเพิ่มเติม</translation>
<translation id="6447842834002726250">คุกกี้</translation>
<translation id="6451458296329894277">ยืนยันการส่งแบบฟอร์มอีกครั้ง</translation>
-<translation id="6456339708790392414">การชำระเงินของคุณ</translation>
<translation id="647261751007945333">นโยบายอุปกรณ์</translation>
<translation id="6477321094435799029">Chrome ได้ตรวจพบรหัสที่ผิดปกติบนหน้านี้และได้บล็อกรหัสดังกล่าวเพื่อปกป้องข้อมูลส่วนบุคคลของคุณ (เช่น รหัสผ่าน หมายเลขโทรศัพท์ และบัตรเครดิต)</translation>
<translation id="6489534406876378309">เริ่มอัปโหลดข้อขัดข้อง</translation>
<translation id="6507833130742554667">รับบัตรเครดิตและบัตรเดบิต</translation>
<translation id="6508722015517270189">รีสตาร์ท Chrome</translation>
-<translation id="6521373090216409766">คุณต้องการโหลดเว็บไซต์นี้ซ้ำใช่ไหม</translation>
<translation id="6529602333819889595">&amp;ทำซ้ำการนำออก</translation>
<translation id="6534179046333460208">คำแนะนำ Physical Web</translation>
<translation id="6550675742724504774">ตัวเลือก</translation>
-<translation id="6556239504065605927">การเชื่อมต่อที่ปลอดภัย</translation>
<translation id="6556915248009097796">วันที่หมดอายุ: <ph name="EXPIRATION_DATE_ABBR" /> ใช้ล่าสุดเมื่อ <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">ผู้จัดการยังไม่ได้อนุมัติเว็บไซต์นี้</translation>
<translation id="6569060085658103619">คุณกำลังดูหน้าส่วนขยาย</translation>
<translation id="6596325263575161958">ตัวเลือกการเข้ารหัส</translation>
+<translation id="6604181099783169992">เซ็นเซอร์จับความเคลื่อนไหวหรือเซ็นเซอร์แสง</translation>
<translation id="6624427990725312378">ข้อมูลติดต่อ</translation>
<translation id="6626291197371920147">เพิ่มหมายเลขบัตรที่ถูกต้อง</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> ค้นหา</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">บุ๊กมาร์กที่มีการจัดการ</translation>
<translation id="7298195798382681320">แนะนำ</translation>
<translation id="7309308571273880165">รายงานข้อขัดข้องเมื่อ <ph name="CRASH_TIME" /> (ผู้ใช้ขอการอัปโหลด ยังไม่ได้อัปโหลด)</translation>
+<translation id="7320336641823683070">ความช่วยเหลือเกี่ยวกับการเชื่อมต่อ</translation>
<translation id="7334320624316649418">&amp;ทำซ้ำการจัดลำดับใหม่</translation>
<translation id="733923710415886693">ไม่มีการเปิดเผยใบรับรองของเซิร์ฟเวอร์ผ่านความโปร่งใสของใบรับรอง</translation>
<translation id="7353601530677266744">บรรทัดคำสั่ง </translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">Wi-Fi ที่คุณใช้ (<ph name="WIFI_NAME" />) อาจต้องการให้คุณไปที่หน้าการเข้าสู่ระบบ</translation>
<translation id="785549533363645510">อย่างไรก็ตาม ระบบยังมองเห็นคุณ การเข้าสู่โหมดไม่ระบุตัวตนไม่ได้เป็นการซ่อนการท่องเว็บจากนายจ้างของคุณ ผู้ให้บริการอินเทอร์เน็ต หรือเว็บไซต์ที่คุณเข้าชม</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">ออกจากเว็บไซต์ไหม</translation>
<translation id="7878176543348854470">รับบัตรเดบิตและบัตรเติมเงิน</translation>
<translation id="7878562273885520351">รหัสผ่านของคุณอาจถูกขโมยได้</translation>
<translation id="7887683347370398519">ตรวจสอบ CVC และลองอีกครั้ง</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">ใช้ค่าเริ่มต้นสากล (ถาม)</translation>
<translation id="8042918947222776840">เลือกวิธีรับสินค้า</translation>
<translation id="8057711352706143257">กำหนดค่า "<ph name="SOFTWARE_NAME" />" ไม่ถูกต้อง การถอนการติดตั้ง "<ph name="SOFTWARE_NAME" />" มักแก้ไขปัญหานี้ได้ <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">โหลดเว็บไซต์ซ้ำไหม</translation>
<translation id="8088680233425245692">การดูบทความล้มเหลว</translation>
<translation id="8091372947890762290">กำลังรอการเปิดใช้งานบนเซิร์ฟเวอร์</translation>
<translation id="8094917007353911263">เครือข่ายที่คุณใช้อาจต้องการให้คุณไปที่ <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /></translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">การอัปเดต URL ไม่ถูกต้องสำหรับส่วนขยายรหัส "<ph name="EXTENSION_ID" />"</translation>
<translation id="8202097416529803614">ข้อมูลสรุปคำสั่งซื้อ</translation>
<translation id="8205463626947051446">ไซต์มักแสดงโฆษณาที่แทรก</translation>
+<translation id="8211406090763984747">การเชื่อมต่อปลอดภัย</translation>
<translation id="8218327578424803826">ตำแหน่งที่มอบหมาย:</translation>
<translation id="8225771182978767009">ผู้ที่ตั้งค่าคอมพิวเตอร์เครื่องนี้เลือกบล็อกเว็บไซต์นี้</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">แสดงรหัสผ่านที่บันทึกไว้ทั้งหมด</translation>
<translation id="8261506727792406068">ลบ</translation>
<translation id="8267698848189296333">ลงชื่อเข้าใช้ด้วย <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">ลงชื่อเข้าใช้</translation>
<translation id="8288807391153049143">แสดงใบรับรอง</translation>
<translation id="8289355894181816810">ติดต่อผู้ดูแลระบบเครือข่ายของคุณหากไม่แน่ใจว่าข้อความนี้หมายถึงอะไร</translation>
<translation id="8293206222192510085">เพิ่มบุ๊กมาร์ก</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">บัตรเครดิตและบัตรเติมเงินที่ยอมรับ</translation>
<translation id="8759274551635299824">บัตรนี้หมดอายุแล้ว</translation>
<translation id="8761567432415473239">Google Safe Browsing <ph name="BEGIN_LINK" />พบโปรแกรมที่เป็นอันตราย<ph name="END_LINK" />บน <ph name="SITE" /> เมื่อเร็วๆ นี้</translation>
+<translation id="8763927697961133303">อุปกรณ์ USB</translation>
<translation id="8790007591277257123">&amp;ทำซ้ำการนำออก</translation>
<translation id="8800988563907321413">คำแนะนำในบริเวณใกล้เคียงจะปรากฏที่นี่</translation>
<translation id="8820817407110198400">บุ๊กมาร์ก</translation>
diff --git a/chromium/components/strings/components_strings_tr.xtb b/chromium/components/strings/components_strings_tr.xtb
index 3e10e4f921c..acca93461ff 100644
--- a/chromium/components/strings/components_strings_tr.xtb
+++ b/chromium/components/strings/components_strings_tr.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">Ya&amp;zdır...</translation>
<translation id="1181037720776840403">Kaldır</translation>
<translation id="1184214524891303587">Olası güvenlik olaylarının ayrıntılarını Google'a <ph name="BEGIN_WHITEPAPER_LINK" />otomatik olarak bildir<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Ödeme İşlemi Tamamlanmadı</translation>
<translation id="1201402288615127009">Sonraki</translation>
<translation id="1201895884277373915">Bu siteden daha çok</translation>
<translation id="1206967143813997005">Başlangıç anahtarlı imza hatalı</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Kilitlenme raporu yakalanma zamanı: <ph name="CRASH_TIME" /> (henüz yüklenmedi veya yoksayıldı)</translation>
<translation id="1270502636509132238">Alma Yöntemi</translation>
<translation id="1285320974508926690">Bu siteyi hiçbir zaman çevirme</translation>
+<translation id="1294154142200295408">Komut satırı varyasyonları</translation>
<translation id="129553762522093515">Son kapatılan</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Çerezlerinizi temizlemeyi deneyin<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Etkinliğiniz şunlar tarafından <ph name="BEGIN_EMPHASIS" />yine de görülebilir<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Kabul edilen kredi ve banka kartları</translation>
<translation id="1519264250979466059">Oluşturma Tarihi</translation>
<translation id="1527263332363067270">Bağlantı bekleniyor…</translation>
+<translation id="1532118530259321453">Bu sayfanın mesajı</translation>
<translation id="153384715582417236">Şimdilik hepsi bu</translation>
<translation id="154408704832528245">Teslimat Adresi Seç</translation>
<translation id="1549470594296187301">Bu özelliğin kullanılabilmesi için JavaScript etkinleştirilmelidir.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Proxy'yi ve güvenlik duvarını kontrol etme<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Posta kodu</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 öneri}other{# öneri}}</translation>
-<translation id="2065985942032347596">Kimlik Doğrulaması Gerekiyor</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="2091887806945687916">Ses</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Ödemeyi iptal et</translation>
<translation id="2147827593068025794">Arka Plan Senkronizasyonu</translation>
<translation id="2148613324460538318">Kart Ekle</translation>
-<translation id="2149973817440762519">Yer İşaretini Düzenle</translation>
<translation id="2154054054215849342">Senkronizasyon alan adınızda kullanılamıyor</translation>
<translation id="2154484045852737596">Kartı düzenle</translation>
<translation id="2166049586286450108">Tam Yönetici Erişimi</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Alınacağı Adres Seç</translation>
<translation id="2740531572673183784">Tamam</translation>
<translation id="2742870351467570537">Seçilen öğeleri kaldır</translation>
-<translation id="2744590937989388266">Bu Sayfadaki Yerleşik bir Sayfadan</translation>
<translation id="277133753123645258">Gönderim yöntemi</translation>
<translation id="277499241957683684">Eksik cihaz kaydı</translation>
<translation id="2784949926578158345">Bağlantı sıfırlandı.</translation>
<translation id="2788784517760473862">Kabul edilen kredi kartları</translation>
<translation id="2794233252405721443">Site engellenmiş</translation>
-<translation id="2795286477369100655">Bu Siteden Ayrılmak İstiyor musunuz?</translation>
<translation id="2799020568854403057">Girmekte olduğunuz site zararlı uygulamalar içeriyor</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="2824775600643448204">Adres ve arama çubuğu</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Liste girişi "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Otomatik olarak engellendi</translation>
<translation id="3024663005179499861">Yanlış politika türü</translation>
-<translation id="3032412215588512954">Bu siteyi yeniden yüklemek istiyor musunuz?</translation>
<translation id="3037605927509011580">Hay aksi!</translation>
<translation id="3039538478787849737">Kart Google'a kaydedilsin mi?</translation>
<translation id="3041612393474885105">Sertifika Bilgileri</translation>
@@ -310,6 +306,7 @@
proxy ayarlarınızı kontrol edin veya ağ yöneticinize danışın. Proxy sunucu
kullanmamanız gerektiğini düşünüyorsanız:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="SERVER_NAME" /> üzerinde <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">Ödemeyi iptal et</translation>
<translation id="3207960819495026254">Yer işareti koyuldu</translation>
<translation id="3209375525920864198">Lütfen geçerli bir oturum adı girin.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Yöneticiniz engellemeyi kaldırabilir</translation>
<translation id="3566021033012934673">Bağlantınız gizli değil</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" /> web sitesindeki yerleşik bir sayfanın mesajı</translation>
<translation id="358285529439630156">Kredi ve ön ödemeli kartlar kabul edilir.</translation>
<translation id="3582930987043644930">Ad ekleyin</translation>
<translation id="3583757800736429874">Taşımayı &amp;Yeniden Yap</translation>
<translation id="3586931643579894722">Ayrıntıları gizle</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Bağlantı hatalarını düzeltme&lt;/h1&gt;
+ &lt;p&gt;Bir web sitesini ziyaret etmeye çalıştığınızda hata mesajı alıyorsanız burada belirtilen düzeltmeleri deneyin.&lt;/p&gt;
+ &lt;h2&gt;Bağlantı hatalarının çoğunu düzeltme&lt;/h2&gt;
+ &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;
+ &lt;ol&gt;
+ &lt;li&gt;Web adresinde yazım hatası olup olmadığını kontrol edin.&lt;/li&gt;
+ &lt;li&gt;İnternet bağlantınızın normal bir şekilde çalıştığından emin olun.&lt;/li&gt;
+ &lt;li&gt;Web sitesinin sahibiyle iletişim kurun.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Belirli bir hata mesajıyla ilgili yardım alma&lt;/h2&gt;
+ &lt;h3&gt;"Bağlantınız gizli değil", "NET::ERR_CERT_AUTHORITY_INVALID", "ERR_CERT_COMMON_NAME_INVALID", "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" veya "SSL sertifikası hatası"&lt;/h3&gt;
+ &lt;h4&gt;1. Adım: Portalda oturum açın&lt;/h4&gt;
+ &lt;p&gt;Kafe veya havaalanı gibi yerlerdeki kablosuz ağlar sizden oturum açmanızı ister. Oturum açma sayfasını görmek için &lt;code&gt;http://&lt;/code&gt; kullanan bir sayfayı ziyaret edin.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;&lt;code&gt;http://&lt;/code&gt; ile başlayan herhangi bir web sitesine (örneğin, &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;) gidin.&lt;/li&gt;
+ &lt;li&gt;Karşınıza gelen oturum açma sayfasında oturum açarak interneti kullanmaya başlayın.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;2. Adım: Sayfayı Gizli modda açın (sadece bilgisayar)&lt;/h4&gt;
+ &lt;p&gt;Ziyaret etmekte olduğunuz sayfayı Gizli pencerede açın.&lt;/p&gt;
+ &lt;p&gt;Sayfa açılırsa bir Chrome uzantısı düzgün çalışmıyor demektir. Hatayı düzeltmek için uzantıyı kapatın.&lt;/p&gt;
+ &lt;h4&gt;3. Adım: İşletim sisteminizi güncelleyin&lt;/h4&gt;
+ &lt;p&gt;Cihazınızın güncel olduğundan emin olun.&lt;/p&gt;
+ &lt;h4&gt;4. Adım: Virüsten koruma yazılımınızı geçici olarak kapatın&lt;/h4&gt;
+ &lt;p&gt;"HTTPS koruması" veya "HTTPS taraması" sağlayan bir virüsten koruma yazılımı kullanıyorsanız bu hatayı görürsünüz. Virüsten koruma yazılımı, Chrome'un güvenlik işlevini engeller.&lt;/p&gt;
+ &lt;p&gt;Sorunu çözmek için virüsten koruma yazılımınızı kapatın. Yazılım kapandıktan sonra sayfa çalışıyorsa, güvenli siteleri kullanacağınız zaman bu yazılımı kapatın.&lt;/p&gt;
+ &lt;p&gt;İşiniz bittiğinde virüsten koruma programınızı tekrar açmayı unutmayın.&lt;/p&gt;
+ &lt;h4&gt;5. Adım: Daha fazla yardım alın&lt;/h4&gt;
+ &lt;p&gt;Hatayı görmeye devam ederseniz web sitesi sahibiyle iletişime geçin.&lt;/p&gt;
+ &lt;h3&gt;"Ağa bağlanın"&lt;/h3&gt;
+ &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;
+ &lt;h3&gt;"Saatiniz geri", "Saatiniz ileri" veya Net::ERR_CERT_DATE_INVALID&lt;/h3&gt;
+ &lt;p&gt;Bilgisayarınızın veya mobil cihazınızın tarihi ve saati doğru değilse bu hatayı görürsünüz.&lt;/p&gt;
+ &lt;p&gt;Hatayı gidermek için cihazınızın saatini açın. Saat ve tarih ayarının doğru olduğundan emin olun.&lt;/p&gt;
+ &lt;h3&gt;"Bilgisayarınızdaki yazılım, Chrome'un web'e güvenli bir şekilde bağlanmasını engelliyor" (yalnızca Windows bilgisayarlar)&lt;/h3&gt;
+ &lt;p&gt;Windows bilgisayarınızda Superfish yazılımı varsa bu hatayı görürsünüz.&lt;/p&gt;
+ &lt;p&gt;Web'e ulaşabilmeniz amacıyla yazılımı geçici olarak devre dışı bırakmak için bu adımları uygulayın. Bu adımları gerçekleştirmek için yönetici ayrıcalıklarınızın olması gerekir.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;&lt;strong&gt;Başlat&lt;/strong&gt;'ı tıklayın, ardından &lt;strong&gt;"Yerel hizmetleri görüntüle"&lt;/strong&gt;yi arayın ve seçin
+ &lt;li&gt;&lt;strong&gt;VisualDiscovery&lt;/strong&gt;'yi seçin
+ &lt;li&gt;&lt;strong&gt;Başlatma türü&lt;/strong&gt;'nün altında &lt;strong&gt;Devre dışı&lt;/strong&gt;'nı seçin
+ &lt;li&gt;&lt;strong&gt;Hizmet durumu&lt;/strong&gt;'nun altında &lt;strong&gt;Durdur&lt;/strong&gt;'u seçin
+ &lt;li&gt;&lt;strong&gt;Uygula&lt;/strong&gt;'yı, ardından &lt;strong&gt;Tamam&lt;/strong&gt;'ı tıklayın
+ &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="3615877443314183785">Geçerli bir son kullanma tarihi girin</translation>
<translation id="36224234498066874">Göz Atma Verilerini Temizle...</translation>
<translation id="362276910939193118">Tam Geçmişi Göster</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Bu kartı Google Hesabınıza ve bu cihaza kaydetmek istiyor musunuz?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Son kullanma tarihi: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929"><ph name="SITE" /> web sitesinden</translation>
<translation id="382518646247711829">Proxy sunucu kullanıyorsanız...</translation>
<translation id="3828924085048779000">Boş parolaya izin verilmez.</translation>
<translation id="385051799172605136">Geri</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">Kilitlenme Raporu Kimliği <ph name="CRASH_ID" /> Yüklendi (Yerel Kilitlenme Kimliği: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Bu sunucu <ph name="DOMAIN" /> olduğunu kanıtlayamadı. Güvenlik sertifikasında Konu Diğer Adları belirtilmiyor. Bu durum, bir yanlış yapılandırmadan veya bağlantınıza müdahale eden bir saldırgandan kaynaklanıyor olabilir.</translation>
<translation id="3949601375789751990">Göz atma geçmişiniz burada görünür</translation>
+<translation id="3950820424414687140">Oturum açın</translation>
<translation id="3963721102035795474">Okuyucu Modu</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Yok}=1{1 siteden }other{# siteden }}</translation>
<translation id="397105322502079400">Hesaplanııyor...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Cihazın seri numarası geçersiz</translation>
<translation id="410351446219883937">Otomatik oynatma</translation>
<translation id="4103763322291513355">Kara listeye alınmış URL'lerin ve sistem yöneticinizin zorunlu tuttuğu diğer politikaların listesini görmek için &lt;strong&gt;chrome://policy&lt;/strong&gt; adresini ziyaret edin.</translation>
+<translation id="4110652170750985508">Ödemenizi inceleyin</translation>
<translation id="4116663294526079822">Bu sitede her zaman izin ver</translation>
<translation id="4117700440116928470">Politika kapsamı desteklenmiyor.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 öğe daha}other{# öğe daha}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Kullanıcı adı yok)</translation>
<translation id="4275830172053184480">Cihazınızı yeniden başlatın</translation>
<translation id="4280429058323657511">, son kullanma tarihi <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Giriş Yap</translation>
<translation id="4312866146174492540">Engelle (varsayılan)</translation>
<translation id="4325863107915753736">Makale bulunamadı</translation>
<translation id="4326324639298822553">Son kullanma tarihini kontrol edip tekrar deneyin</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Kart ve adres bilgileri Chrome'dan ve Google Hesabınızdan (<ph name="ACCOUNT_EMAIL" />) alınmaktadır. Bunları <ph name="BEGIN_LINK" />Ayarlar<ph name="END_LINK" />'dan yönetebilirsiniz.</translation>
<translation id="4522570452068850558">Ayrıntılar</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291"><ph name="SITE" /> Web Sitesindeki Yerleşik bir Sayfadan</translation>
<translation id="4558551763791394412">Uzantılarınızı devre dışı bırakmayı deneyin</translation>
<translation id="457875822857220463">Teslimat</translation>
<translation id="4582800630050655161">Google Hesabınıza erişimi kaybedebilir veya kimlik hırsızlığına maruz kalabilirsiniz. Chromium, şifrenizi hemen değiştirmenizi önerir.</translation>
<translation id="4587425331216688090">Adres Chrome'dan kaldırılsın mı?</translation>
<translation id="4592951414987517459"><ph name="DOMAIN" /> ile olan bağlantınız modern bir şifre seti kullanılarak şifrelendi.</translation>
<translation id="4594403342090139922">Silmeyi &amp;Geri Al</translation>
-<translation id="4611292653554630842">Giriş yap</translation>
<translation id="4619615317237390068">Diğer cihazlardan sekmeler</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Bu sunucu <ph name="DOMAIN" /> olduğunu kanıtlayamadı. Güvenlik sertifikasında hatalar var. Bu durum, bir yanlış yapılandırmadan veya bağlantıya müdahale eden bir saldırgandan kaynaklanıyor olabilir.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Bağlantınız kesildi</translation>
<translation id="471880041731876836">Bu siteyi ziyaret etmek için izniniz yok</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows Ağ Teşhislerini Çalıştırma<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Ödemeniz</translation>
<translation id="4726672564094551039">Politikaları yeniden yükle</translation>
<translation id="4728558894243024398">Platform</translation>
<translation id="4736825316280949806">Chromium'u yeniden başlatın</translation>
-<translation id="4737498291095696011">Bu Sayfadan</translation>
<translation id="4744603770635761495">Çalıştırılabilir Yol</translation>
<translation id="4749685221585524849">Son kullanıldığı tarih: <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Bilgileriniz (örneğin şifreler veya kredi kartı numaraları), bu siteye gönderilirken gizli olur.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Görüntüle</translation>
<translation id="4854362297993841467">Bu teslimat yöntemi kullanılamıyor. Farklı bir yöntem deneyin.</translation>
<translation id="4858792381671956233">Ebeveynlerinize bu siteyi ziyaret etmenizin uygun olup olmadığını sordunuz</translation>
-<translation id="4871132632506079383"><ph name="SITE" /> web sitesindeki yerleşik bir sayfadan</translation>
<translation id="4880827082731008257">Geçmişte ara</translation>
+<translation id="4881695831933465202">Aç</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Kimlik doğrulaması gerekiyor</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{ve 1 web sayfası daha}other{ve # web sayfası daha}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947"><ph name="CREDIT_CARD" /> numaralı kartın CVC kodunu girin. Onayladığınızda Google Payments hesabınızdaki kart bilgileriniz bu siteyle paylaşılır.</translation>
<translation id="4923417429809017348">Bu sayfa, bilinmeyen bir dilden <ph name="LANGUAGE_LANGUAGE" /> diline çevrildi</translation>
<translation id="4923459931733593730">Ödeme</translation>
<translation id="4926049483395192435">Belirtilmelidir.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> web sitesinin mesajı</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">İşlemler</translation>
<translation id="4958444002117714549">Listeyi genişlet</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Bu seçenek etkinleştirildiğinde Chrome, formları daha hızlı doldurmak için kartınızın bir kopyasını bu cihazda saklar.</translation>
<translation id="5018422839182700155">Bu sayfa açılamıyor</translation>
<translation id="5019198164206649151">Yedekleme deposu kötü durumda</translation>
-<translation id="5020990877659450221">Bu sayfadan</translation>
<translation id="5023310440958281426">Yöneticinizin politikalarını inceleyin.</translation>
<translation id="5029568752722684782">Kopyayı temizle</translation>
<translation id="503069730517007720">"<ph name="SOFTWARE_NAME" />" için bir kök sertifika gerekli, ancak yüklenmemiş. BT yöneticiniz bu sorunu çözmek için "<ph name="SOFTWARE_NAME" />" ile ilgili yapılandırma talimatlarına bakmalıdır. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Makine</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> dilinde değil mi? Bu hatayı bildirin</translation>
<translation id="5190835502935405962">Yer İşareti Çubuğu</translation>
+<translation id="5201306358585911203">Bu sayfadaki yerleşik bir sayfanın mesajı</translation>
<translation id="5205222826937269299">Ad gerekli</translation>
<translation id="5222812217790122047">E-posta gerekli</translation>
<translation id="522700295135997067">Bu site az önce şifrenizi çalmış olabilir</translation>
<translation id="5230733896359313003">Gönderim Adresi</translation>
<translation id="5251803541071282808">Bulut</translation>
-<translation id="5277279256032773186">Chrome'u işte mi kullanıyorsunuz? İşletmeler, çalışanları için Chrome ayarlarını yönetebilir. Daha fazla bilgi edinin</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Web'e ulaşabilmeniz amacıyla yazılımı geçici olarak devre dışı bırakmak için bu adımları uygulayın. Bu adımları gerçekleştirmek için yönetici ayrıcalıklarınızın olması gerekir.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Bağlantınızı kontrol etme</translation>
<translation id="5610807607761827392">Kartları ve adresleri <ph name="BEGIN_LINK" />Ayarlar<ph name="END_LINK" />'da yönetebilirsiniz.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> sizi çok fazla kez yönlendirdi.</translation>
-<translation id="5622887735448669177">Bu siteden ayrılmak istiyor musunuz?</translation>
<translation id="5629630648637658800">Politika ayarları yüklenemedi</translation>
<translation id="5631439013527180824">Geçersiz cihaz yönetimi jetonu</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Kart bilgilerinizin doldurulmasını istiyor musunuz?</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" /> kartınıza ait bilgilerin doldurulmasını istiyor musunuz?</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> ile olan bağlantınız eski bir şifre seti kullanılarak şifrelendi.</translation>
-<translation id="5810928923025889964">Bu sayfadaki yerleşik bir sayfadan</translation>
<translation id="5813119285467412249">Eklemeyi &amp;Yeniden Yap</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>
<translation id="5866257070973731571">Telefon Numarası Ekleyin</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Daha fazla bilgi ekleyin</translation>
<translation id="6447842834002726250">Çerezler</translation>
<translation id="6451458296329894277">Yeniden Form Gönderme İşlemini Onayla</translation>
-<translation id="6456339708790392414">Ödemeniz</translation>
<translation id="647261751007945333">Cihaz politikaları</translation>
<translation id="6477321094435799029">Chrome, bu sayfada olağan dışı kod tespit etti ve kişisel bilgilerinizi (örneğin, şifreler, telefon numaraları ve kredi kartları) korumak için sayfayı engelledi.</translation>
<translation id="6489534406876378309">Kilitlenmeleri yüklemeye başla</translation>
<translation id="6507833130742554667">Kredi ve banka kartları kabul edilir.</translation>
<translation id="6508722015517270189">Chrome'u yeniden başlatın</translation>
-<translation id="6521373090216409766">Bu Siteyi Yeniden Yüklemek İstiyor musunuz?</translation>
<translation id="6529602333819889595">Silmeyi &amp;Yeniden Yap</translation>
<translation id="6534179046333460208">Fiziksel Web önerileri</translation>
<translation id="6550675742724504774">Seçenekler</translation>
-<translation id="6556239504065605927">Güvenli bağlantı</translation>
<translation id="6556915248009097796">Son kullanım tarihi: <ph name="EXPIRATION_DATE_ABBR" />, son kullanıldığı tarih: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Yöneticiniz henüz onaylamadı</translation>
<translation id="6569060085658103619">Bir uzantı sayfası görüntülüyorsunuz</translation>
<translation id="6596325263575161958">Şifreleme seçenekleri</translation>
+<translation id="6604181099783169992">Hareket veya Işık Sensörleri</translation>
<translation id="6624427990725312378">İletişim Bilgileri</translation>
<translation id="6626291197371920147">Geçerli kart numarası ekle</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Arama</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Yönetilen Yer İşaretleri</translation>
<translation id="7298195798382681320">Önerilenler</translation>
<translation id="7309308571273880165">Kilitlenme raporu yakalandı (<ph name="CRASH_TIME" />) (yükleme kullanıcı tarafından istendi, ancak henüz yüklenmedi)</translation>
+<translation id="7320336641823683070">Bağlantı Yardımı</translation>
<translation id="7334320624316649418">Sıralama değişikliğini &amp;yeniden yap</translation>
<translation id="733923710415886693">Sunucunun sertifikası, Sertifika Şeffaflığı aracılığıyla açıklanmadı.</translation>
<translation id="7353601530677266744">Komut Satırı</translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">Kullandığınız kablosuz bağlantı ağı (<ph name="WIFI_NAME" />) giriş sayfasını ziyaret etmenizi gerektiriyor olabilir.</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="7862185352068345852">Siteden çıkılsın mı?</translation>
<translation id="7878176543348854470">Banka kartları ve ön ödemeli kartlar kabul edilir.</translation>
<translation id="7878562273885520351">Şifrenizin güvenliği ihlal edilmiş olabilir</translation>
<translation id="7887683347370398519">CVC'nizi kontrol edin ve tekrar deneyin</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Genel varsayılanı kullan (Sor)</translation>
<translation id="8042918947222776840">Alma Yöntemi Seç</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" doğru şekilde yapılandırılmamış. Genellikle "<ph name="SOFTWARE_NAME" />" kaldırıldığında sorun çözülür. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Site yeniden yüklensin mi?</translation>
<translation id="8088680233425245692">Makale görüntülenemedi.</translation>
<translation id="8091372947890762290">Etkinleştirme sunucuda bekliyor</translation>
<translation id="8094917007353911263">Kullandığınız ağ <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> adresini ziyaret etmenizi gerektiriyor olabilir.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" kodlu uzantı için geçersiz güncelleme URL'si.</translation>
<translation id="8202097416529803614">Sipariş özeti</translation>
<translation id="8205463626947051446">Site, araya giren reklamlar gösterme eğiliminde</translation>
+<translation id="8211406090763984747">Bağlantı güvenli</translation>
<translation id="8218327578424803826">Atanan Konum:</translation>
<translation id="8225771182978767009">Bu bilgisayarı kuran kişi bu siteyi engellemeyi seçmiş.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Tüm Kayıtlı Şifreleri Göster</translation>
<translation id="8261506727792406068">Sil</translation>
<translation id="8267698848189296333"><ph name="USERNAME" /> olarak oturum açılıyor</translation>
+<translation id="8286036467436129157">Oturum Aç</translation>
<translation id="8288807391153049143">Sertifikayı göster</translation>
<translation id="8289355894181816810">Bunun ne anlama geldiğini bilmiyorsanız ağ yöneticinizle bağlantı kurun.</translation>
<translation id="8293206222192510085">Yer İşareti Ekle</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">Kabul Edilen Kredi Kartları ve Ön Ödemeli Kartlar</translation>
<translation id="8759274551635299824">Bu kartın kullanım süresi doldu</translation>
<translation id="8761567432415473239">Google Güvenli Tarama, yakın zamanda <ph name="SITE" /> sitesinde <ph name="BEGIN_LINK" />zararlı programlar buldu<ph name="END_LINK" />.</translation>
+<translation id="8763927697961133303">USB cihaz</translation>
<translation id="8790007591277257123">Silmeyi &amp;yeniden yap</translation>
<translation id="8800988563907321413">Yakın çevrenizle ilgili öneriler burada görünür</translation>
<translation id="8820817407110198400">Favoriler</translation>
diff --git a/chromium/components/strings/components_strings_uk.xtb b/chromium/components/strings/components_strings_uk.xtb
index 068c0b5cd32..b4cc55eb7af 100644
--- a/chromium/components/strings/components_strings_uk.xtb
+++ b/chromium/components/strings/components_strings_uk.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;Друк...</translation>
<translation id="1181037720776840403">Видалити</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Автоматично надсилати<ph name="END_WHITEPAPER_LINK" /> в Google інформацію про можливі порушення безпеки. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Оплату не завершено</translation>
<translation id="1201402288615127009">Далі</translation>
<translation id="1201895884277373915">Більше з цього сайту</translation>
<translation id="1206967143813997005">Недійсний підпис</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Звіт про аварійне завершення роботи о <ph name="CRASH_TIME" /> (ще не завантажено або пропущено)</translation>
<translation id="1270502636509132238">Спосіб отримання</translation>
<translation id="1285320974508926690">Ніколи не перекладати цей сайт</translation>
+<translation id="1294154142200295408">Варіанти командного рядка</translation>
<translation id="129553762522093515">Нещодавно закриті</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Спробуйте видалити файли cookie<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Дані про вашу активність <ph name="BEGIN_EMPHASIS" />усе ще можуть бачити<ph name="END_EMPHASIS" />:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Прийнятні кредитні та дебетові картки</translation>
<translation id="1519264250979466059">Дата створення версії</translation>
<translation id="1527263332363067270">Очікується з’єднання…</translation>
+<translation id="1532118530259321453">Повідомлення з цієї сторінки</translation>
<translation id="153384715582417236">Більше нічого немає</translation>
<translation id="154408704832528245">Вибрати адресу доставки</translation>
<translation id="1549470594296187301">Щоб користуватися цією функцією, потрібно ввімкнути JavaScript.</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />перевірити проксі-сервер і брандмауер<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Поштовий індекс</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 пропозиція}one{# пропозиція}few{# пропозиції}many{# пропозицій}other{# пропозиції}}</translation>
-<translation id="2065985942032347596">Потрібна автентифікація</translation>
<translation id="2079545284768500474">Відмінити</translation>
<translation id="20817612488360358">Системні параметри проксі-сервера налаштовано для використання, але чітко вказано налаштування проксі-сервера.</translation>
<translation id="2091887806945687916">Сигнал</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Скасувати оплату</translation>
<translation id="2147827593068025794">Фонова синхронізація</translation>
<translation id="2148613324460538318">Додати картку</translation>
-<translation id="2149973817440762519">Редагувати закладку</translation>
<translation id="2154054054215849342">Синхронізація недоступна для вашого домену</translation>
<translation id="2154484045852737596">Редагувати картку</translation>
<translation id="2166049586286450108">Повний адміністративний доступ</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Вибрати адресу отримання</translation>
<translation id="2740531572673183784">OK</translation>
<translation id="2742870351467570537">Видалити вибрані елементи</translation>
-<translation id="2744590937989388266">Від вбудованої сторінки на цій сторінці</translation>
<translation id="277133753123645258">Спосіб відправлення</translation>
<translation id="277499241957683684">Відсутній запис пристрою</translation>
<translation id="2784949926578158345">З’єднання було скинуто.</translation>
<translation id="2788784517760473862">Прийнятні кредитні картки</translation>
<translation id="2794233252405721443">Сайт заблоковано</translation>
-<translation id="2795286477369100655">Покинути цей сайт?</translation>
<translation id="2799020568854403057">Сайт містить шкідливі додатки</translation>
<translation id="2803306138276472711">Функція безпечного перегляду від Google нещодавно <ph name="BEGIN_LINK" />виявила зловмисне програмне забезпечення<ph name="END_LINK" /> на сайті <ph name="SITE" />. Іноді зловмисне програмне забезпечення заражає зазвичай безпечні веб-сайти.</translation>
<translation id="2824775600643448204">Адресний і пошуковий рядок</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Елемент списку "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Блокується автоматично</translation>
<translation id="3024663005179499861">Неправильний тип правила</translation>
-<translation id="3032412215588512954">Оновити цей сайт?</translation>
<translation id="3037605927509011580">От халепа!</translation>
<translation id="3039538478787849737">Зберегти картку в Google?</translation>
<translation id="3041612393474885105">Інформація про сертифікат</translation>
@@ -310,6 +306,7 @@
щоб переконатися, що проксі-сервер працює. Якщо ви вважаєте, що не потрібно
використовувати проксі-сервер, виконайте вказані нижче дії.
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> на сервері <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Скасувати оплату</translation>
<translation id="3207960819495026254">Створено закладку</translation>
<translation id="3209375525920864198">Введіть дійсну назву сеансу.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Адміністратор може розблокувати його</translation>
<translation id="3566021033012934673">З’єднання не конфіденційне</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Повідомлення з вбудованої сторінки сайту <ph name="SITE" /></translation>
<translation id="358285529439630156">Кредитні та передплачені картки, які приймаються.</translation>
<translation id="3582930987043644930">Додати ім’я</translation>
<translation id="3583757800736429874">&amp;Повторити переміщення</translation>
<translation id="3586931643579894722">Сховати докладні дані</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Як виправити помилки з’єднання&lt;/h1&gt;
+ &lt;p&gt;Якщо з’являється повідомлення про помилку, коли ви намагаєтеся відкрити веб-сайт, спробуйте наведені нижче рішення.&lt;/p&gt;
+ &lt;h2&gt;Як виправити більшість помилок з’єднання&lt;/h2&gt;
+ &lt;p&gt;Якщо веб-сайт не відкривається:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;перевірте, чи у веб-адресі немає помилок;&lt;/li&gt;
+ &lt;li&gt;переконайтеся, що інтернет-з’єднання стабільне;&lt;/li&gt;
+ &lt;li&gt;зв’яжіться з власником веб-сайту.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Як виправити конкретну помилку&lt;/h2&gt;
+ &lt;h3&gt;"З’єднання не конфіденційне", "NET::ERR_CERT_AUTHORITY_INVALID", "ERR_CERT_COMMON_NAME_INVALID", "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" або "Помилка сертифіката SSL"&lt;/h3&gt;
+ &lt;h4&gt;Крок 1. Увійдіть на портал&lt;/h4&gt;
+ &lt;p&gt;Щоб під’єднатися до мережі Wi-Fi у кафе, аеропорту тощо, потрібно ввійти в обліковий запис. Щоб відкрилася сторінка входу, перейдіть на сторінку з протоколом &lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Перейдіть на будь-який веб-сайт, що починається з &lt;code&gt;http://&lt;/code&gt;, як-от &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Відкриється сторінка входу. Увійдіть, щоб користуватись Інтернетом.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Крок 2. Відкрийте веб-сторінку в режимі анонімного перегляду (лише на комп’ютері)&lt;/h4&gt;
+ &lt;p&gt;Відкрийте веб-сторінку, яку ви переглядали, в анонімному вікні.&lt;/p&gt;
+ &lt;p&gt;Якщо сторінка відкриється, помилку спричиняє розширення Chrome. Щоб виправити помилку, вимкніть розширення.&lt;/p&gt;
+ &lt;h4&gt;Крок 3. Оновіть операційну систему&lt;/h4&gt;
+ &lt;p&gt;Переконайтеся, що пристрій оновлено.&lt;/p&gt;
+ &lt;h4&gt;Крок 4. Тимчасово вимкніть антивірусну програму&lt;/h4&gt;
+ &lt;p&gt;Це повідомлення з’являється, якщо встановлено антивірусну програму з функцією захисту або сканування HTTPS, яка блокує систему безпеки Chrome.&lt;/p&gt;
+ &lt;p&gt;Щоб вирішити цю проблему, вимкніть антивірусну програму. Якщо веб-сторінка працює, вимикайте антивірус, коли переглядаєте захищені сайти.&lt;/p&gt;
+ &lt;p&gt;Закінчивши, не забудьте знову ввімкнути антивірусну програму.&lt;/p&gt;
+ &lt;h4&gt;Крок 5. Отримайте додаткову довідку&lt;/h4&gt;
+ &lt;p&gt;Якщо повідомлення про помилку не зникає, зв’яжіться з власником веб-сайту.&lt;/p&gt;
+ &lt;h3&gt;"Під’єднайте пристрій до мережі"&lt;/h3&gt;
+ &lt;p&gt;Це повідомлення про помилку з’являється, якщо ви користуєтеся порталом мережі Wi-Fi, на який потрібно ввійти, перш ніж під’єднатися до мережі.&lt;/p&gt;
+ &lt;p&gt;Щоб виправити цю помилку, натисніть опцію &lt;strong&gt;Під’єднатися&lt;/strong&gt; на сторінці, яку хочете відкрити.&lt;/p&gt;
+ &lt;h3&gt;"Ваш годинник відстає", "Ваш годинник спішить" або "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Це повідомлення про помилку з’являється, якщо дата й час на комп’ютері або мобільному пристрої неправильні.&lt;/p&gt;
+ &lt;p&gt;Щоб виправити цю помилку, відкрийте годинник на пристрої. Перевірте, чи дата й час правильні.&lt;/p&gt;
+ &lt;h3&gt;"Програмне забезпечення на вашому комп’ютері перешкоджає веб-переглядачеві Chrome безпечно під’єднуватися до Інтернету" (лише на комп’ютерах з ОС Windows)&lt;/h3&gt;
+ &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;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;
+ &lt;li&gt;Натисніть &lt;strong&gt;Застосувати&lt;/strong&gt;, а потім – кнопку &lt;strong&gt;OK&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="3615877443314183785">Введіть дійсний термін дії</translation>
<translation id="36224234498066874">Очистити дані веб-перегляду...</translation>
<translation id="362276910939193118">Показати повну історію</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Зберегти дані картки у вашому обліковому записі Google і на цьому пристрої?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Діє до <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Від сайту <ph name="SITE" /></translation>
<translation id="382518646247711829">Якщо ви використовуєте проксі-сервер…</translation>
<translation id="3828924085048779000">Порожня парольна фраза заборонена.</translation>
<translation id="385051799172605136">Назад</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">Ідентифікатор завантаженого звіту про аварійне завершення роботи: <ph name="CRASH_ID" /> (локальний ідентифікатор аварійного завершення роботи: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Цей сервер не зміг довести, що він – домен <ph name="DOMAIN" />. У його сертифікаті безпеки не вказано альтернативні імена. Імовірні причини: неправильна конфігурація або хтось намагається перехопити ваше з’єднання.</translation>
<translation id="3949601375789751990">Тут відображається ваша історія веб-перегляду</translation>
+<translation id="3950820424414687140">Увійти</translation>
<translation id="3963721102035795474">Режим перегляду</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Немає}=1{З 1 сайту }one{З # сайту }few{З # сайтів }many{З # сайтів }other{З # сайту }}</translation>
<translation id="397105322502079400">Обчислення...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Недійсний серійний номер пристрою</translation>
<translation id="410351446219883937">Автовідтворення</translation>
<translation id="4103763322291513355">Перейдіть на сторінку &lt;strong&gt;chrome://policy&lt;/strong&gt;, щоб переглянути список URL-адрес із "чорного" списку й інші правила, що примусово застосовується системним адміністратором.</translation>
+<translation id="4110652170750985508">Переглянути платіж</translation>
<translation id="4116663294526079822">Завжди дозволяти на цьому сайті</translation>
<translation id="4117700440116928470">Правило не підтримується.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{і ще 1 елемент даних}one{і ще # елемент даних}few{і ще # елементи даних}many{і ще # елементів даних}other{і ще # елемента даних}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Немає імені користувача)</translation>
<translation id="4275830172053184480">Перезапустіть пристрій</translation>
<translation id="4280429058323657511">, дійсна до <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Вхід</translation>
<translation id="4312866146174492540">Блокувати (за умовчанням)</translation>
<translation id="4325863107915753736">Статтю не знайдено</translation>
<translation id="4326324639298822553">Перевірте дату закінчення терміну дії та повторіть спробу</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Дані картки та список адрес містяться в Chrome і вашому обліковому записі Google (<ph name="ACCOUNT_EMAIL" />). Ними можна керувати в <ph name="BEGIN_LINK" />Налаштуваннях<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Деталі</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Від вбудованої сторінки на сайті <ph name="SITE" /></translation>
<translation id="4558551763791394412">Спробуйте вимкнути розширення.</translation>
<translation id="457875822857220463">Доставка</translation>
<translation id="4582800630050655161">Ви можете втратити доступ до облікового запису Google або хтось може викрасти вашу особисту інформацію. Chromium радить змінити пароль.</translation>
<translation id="4587425331216688090">Видалити адресу з Chrome?</translation>
<translation id="4592951414987517459">З’єднання з доменом <ph name="DOMAIN" /> шифрується за допомогою сучасного набору шифрів.</translation>
<translation id="4594403342090139922">&amp;Відмінити видалення</translation>
-<translation id="4611292653554630842">Увійти</translation>
<translation id="4619615317237390068">Вкладки з інших пристроїв</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Цей сервер не зміг довести, що він – домен <ph name="DOMAIN" />. Його сертифікат безпеки містить помилки. Імовірні причини: неправильна конфігурація або хтось намагається перехопити ваше з’єднання.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">З’єднання розірвано</translation>
<translation id="471880041731876836">У вас немає дозволу відвідувати цей сайт</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />провести діагностику мережі Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Ваш платіж</translation>
<translation id="4726672564094551039">Перезавантажити правила</translation>
<translation id="4728558894243024398">Платформа</translation>
<translation id="4736825316280949806">Перезапустіть Chromium</translation>
-<translation id="4737498291095696011">Від цієї сторінки</translation>
<translation id="4744603770635761495">Виконуваний шлях</translation>
<translation id="4749685221585524849">Востаннє використано <ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">Ваша інформація (як-от паролі та номери кредитних карток) залишається конфіденційною, коли надсилається на цей сайт.</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Перегляд</translation>
<translation id="4854362297993841467">Цей спосіб доставки недоступний. Виберіть інший спосіб.</translation>
<translation id="4858792381671956233">Ви надіслали батькам запит на перегляд цього сайту</translation>
-<translation id="4871132632506079383">Від вбудованої сторінки на сайті <ph name="SITE" /></translation>
<translation id="4880827082731008257">Пошук в історії</translation>
+<translation id="4881695831933465202">Відкрити</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Потрібна автентифікація</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{і ще 1 веб-сторінка}one{і ще # веб-сторінка}few{і ще # веб-сторінки}many{і ще # веб-сторінок}other{і ще # веб-сторінки}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Введіть код CVC картки <ph name="CREDIT_CARD" />. Щойно ви підтвердите дані картки з облікового запису Google Payments, цей сайт отримає доступ до них.</translation>
<translation id="4923417429809017348">Цю сторінку перекладено з невідомої мови оригіналу такою мовою: <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Оплата</translation>
<translation id="4926049483395192435">Потрібно вказати.</translation>
+<translation id="4926159001844873046">Повідомлення із сайту <ph name="SITE" /></translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" /> з <ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Дії</translation>
<translation id="4958444002117714549">Розгорнути список</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Коли цю функцію ввімкнено, Chrome зберігає копію даних вашої картки на пристрої, щоб ви могли швидше заповнювати форми.</translation>
<translation id="5018422839182700155">Не вдається відкрити цю сторінку</translation>
<translation id="5019198164206649151">Резервний носій пошкоджено</translation>
-<translation id="5020990877659450221">Від цієї сторінки</translation>
<translation id="5023310440958281426">Перегляньте правила свого адміністратора</translation>
<translation id="5029568752722684782">Видалити копію</translation>
<translation id="503069730517007720">Для програмного забезпечення <ph name="SOFTWARE_NAME" /> потрібен кореневий сертифікат, однак його не встановлено. Вашому IT-адміністратору потрібно переглянути вказівки з налаштування <ph name="SOFTWARE_NAME" />, щоб вирішити цю проблему. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Комп’ютер</translation>
<translation id="5179510805599951267">Це не <ph name="ORIGINAL_LANGUAGE" />? Повідомте про помилку</translation>
<translation id="5190835502935405962">Панель закладок</translation>
+<translation id="5201306358585911203">Повідомлення з вбудованої сторінки на цій сторінці</translation>
<translation id="5205222826937269299">Укажіть ім’я</translation>
<translation id="5222812217790122047">Укажіть електронну адресу</translation>
<translation id="522700295135997067">Можливо, хтось на цьому сайті щойно викрав ваш пароль</translation>
<translation id="5230733896359313003">Адреса доставки</translation>
<translation id="5251803541071282808">Хмара</translation>
-<translation id="5277279256032773186">Користуєтеся Chrome на роботі? Компанії можуть налаштовувати Chrome для своїх працівників. Докладніше</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Виконайте ці дії, щоб тимчасово вимкнути програмне забезпечення й отримати доступ до Інтернету. Для цього потрібні права адміністратора.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">перевірити наявність з’єднання</translation>
<translation id="5610807607761827392">Ви можете керувати картками й адресами в <ph name="BEGIN_LINK" />Налаштуваннях<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Хост <ph name="HOST_NAME" /> переспрямував вас забагато разів.</translation>
-<translation id="5622887735448669177">Покинути цей сайт?</translation>
<translation id="5629630648637658800">Помилка завантаження налаштувань правила</translation>
<translation id="5631439013527180824">Недійсний маркер керування пристрою</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Ввести дані кредитної картки?</translation>
<translation id="5803412860119678065">Ввести дані кредитної картки <ph name="CARD_DETAIL" />?</translation>
<translation id="5810442152076338065">З’єднання з доменом <ph name="DOMAIN" /> шифрується за допомогою застарілого набору шифрів.</translation>
-<translation id="5810928923025889964">Від вбудованої сторінки на цій сторінці</translation>
<translation id="5813119285467412249">&amp;Повторити додавання</translation>
<translation id="5838278095973806738">Не вводьте конфіденційну інформацію на цьому сайті (як-от паролі й дані кредитних карток). Зловмисники можуть викрасти її.</translation>
<translation id="5866257070973731571">Додайте номер телефону</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Додати більше інформації</translation>
<translation id="6447842834002726250">Cookie-файли</translation>
<translation id="6451458296329894277">Підтвердити повторне надсилання форми</translation>
-<translation id="6456339708790392414">Ваш платіж</translation>
<translation id="647261751007945333">Правила пристрою</translation>
<translation id="6477321094435799029">Chrome виявив на цій сторінці незвичний код і заблокував його, щоб захистити вашу особисту інформацію (наприклад, паролі, номери телефонів або кредитних карток).</translation>
<translation id="6489534406876378309">Почати завантаження даних про аварійне завершення роботи</translation>
<translation id="6507833130742554667">Кредитні та дебетові картки, які приймаються.</translation>
<translation id="6508722015517270189">Перезапустіть Chrome</translation>
-<translation id="6521373090216409766">Оновити цей сайт?</translation>
<translation id="6529602333819889595">&amp;Повторити видалення</translation>
<translation id="6534179046333460208">Пропозиції сервісу "Інтернет навколо нас"</translation>
<translation id="6550675742724504774">Параметри</translation>
-<translation id="6556239504065605927">Захищене з’єднання</translation>
<translation id="6556915248009097796">Востаннє використано <ph name="LAST_USED_DATE_NO_DETAIL" />, діє до <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="6563469144985748109">Адміністратор ще не схвалив його</translation>
<translation id="6569060085658103619">Ви переглядаєте сторінку розширень</translation>
<translation id="6596325263575161958">Параметри шифрування</translation>
+<translation id="6604181099783169992">Датчики руху чи світла</translation>
<translation id="6624427990725312378">Контактна інформація</translation>
<translation id="6626291197371920147">Додати дійсний номер картки</translation>
<translation id="6628463337424475685">Пошук <ph name="ENGINE" /></translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Закладки, якими керує адміністратор</translation>
<translation id="7298195798382681320">Рекомендоване</translation>
<translation id="7309308571273880165">Звіт про аварійне завершення роботи створено <ph name="CRASH_TIME" /> (ще не завантажено)</translation>
+<translation id="7320336641823683070">Довідка щодо з’єднання</translation>
<translation id="7334320624316649418">&amp;Повторити перевпорядкування</translation>
<translation id="733923710415886693">Сертифікат сервера не надав інформацію про перевірку.</translation>
<translation id="7353601530677266744">Командний рядок</translation>
@@ -900,6 +935,7 @@
<translation id="782886543891417279">Можливо, щоб під’єднатися до цієї мережі Wi-Fi (<ph name="WIFI_NAME" />), потрібно відвідати її сторінку входу.</translation>
<translation id="785549533363645510">Навіть у режимі анонімного перегляду ваш роботодавець, постачальник послуг Інтернету чи веб-сайти, які ви відвідуєте, можуть бачити, що ви переглядаєте.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" />: <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
+<translation id="7862185352068345852">Залишити сайт?</translation>
<translation id="7878176543348854470">Дебетові та передплачені картки, які приймаються.</translation>
<translation id="7878562273885520351">Ваш пароль можуть зламати</translation>
<translation id="7887683347370398519">Перевірте код CVC й повторіть спробу</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Використовувати глобальне налаштування за умовчанням (Запитувати)</translation>
<translation id="8042918947222776840">Вибрати спосіб отримання</translation>
<translation id="8057711352706143257"><ph name="SOFTWARE_NAME" /> налаштовано неправильно. Якщо видалити програмне забезпечення <ph name="SOFTWARE_NAME" />, проблема зазвичай зникає. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Оновити сайт?</translation>
<translation id="8088680233425245692">Не вдалося переглянути статтю.</translation>
<translation id="8091372947890762290">Активація очікує на сервері</translation>
<translation id="8094917007353911263">Можливо, щоб під’єднатися до цієї мережі, потрібно відвідати сторінку <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">Недійсна URL-адреса для оновлення розширення з ідентифікатором "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Підсумок замовлення</translation>
<translation id="8205463626947051446">Сайт часто показує нав’язливі оголошення</translation>
+<translation id="8211406090763984747">З’єднання безпечне</translation>
<translation id="8218327578424803826">Указане місцезнаходження:</translation>
<translation id="8225771182978767009">Користувач, який налаштував комп’ютер, заблокував цей сайт.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">Показати всі збережені паролі</translation>
<translation id="8261506727792406068">Видалити</translation>
<translation id="8267698848189296333">Ви входите як <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Вхід</translation>
<translation id="8288807391153049143">Показати сертифікат</translation>
<translation id="8289355894181816810">Зверніться до адміністратора своєї мережі, якщо ви не знаєте, що це означає.</translation>
<translation id="8293206222192510085">Додати закладку</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">Кредитні та передплачені картки, які приймаються до оплати</translation>
<translation id="8759274551635299824">Термін дії цієї картки минув</translation>
<translation id="8761567432415473239">Функція безпечного перегляду від Google нещодавно <ph name="BEGIN_LINK" />виявила шкідливі програми<ph name="END_LINK" /> на сайті <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Пристрій USB</translation>
<translation id="8790007591277257123">&amp;Повторити видалення</translation>
<translation id="8800988563907321413">Тут відображатимуться пропозиції</translation>
<translation id="8820817407110198400">Закладки</translation>
diff --git a/chromium/components/strings/components_strings_vi.xtb b/chromium/components/strings/components_strings_vi.xtb
index 5d5f710d88f..65a20d23407 100644
--- a/chromium/components/strings/components_strings_vi.xtb
+++ b/chromium/components/strings/components_strings_vi.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">&amp;In...</translation>
<translation id="1181037720776840403">Xóa</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />Tự động báo cáo<ph name="END_WHITEPAPER_LINK" /> chi tiết các sự cố bảo mật có thể xảy ra với Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">Thanh toán chưa hoàn tất</translation>
<translation id="1201402288615127009">Tiếp theo</translation>
<translation id="1201895884277373915">Thêm từ trang web này</translation>
<translation id="1206967143813997005">Chữ ký ban đầu không hợp lệ</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">Báo cáo sự cố được ghi lại vào <ph name="CRASH_TIME" /> (nhưng chưa tải lên hoặc đã bị bỏ qua)</translation>
<translation id="1270502636509132238">Phương thức nhận hàng</translation>
<translation id="1285320974508926690">Không bao giờ dịch trang web này</translation>
+<translation id="1294154142200295408">Các biến thể của dòng lệnh</translation>
<translation id="129553762522093515">Các tab đã đóng gần đây</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Thử xóa các cookie của bạn<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">Hoạt động của bạn <ph name="BEGIN_EMPHASIS" />có thể vẫn hiển thị<ph name="END_EMPHASIS" /> với:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">Thẻ tín dụng và thẻ ghi nợ được chấp nhận</translation>
<translation id="1519264250979466059">Ngày tạo</translation>
<translation id="1527263332363067270">Đang chờ kết nối…</translation>
+<translation id="1532118530259321453">Trang này cho biết</translation>
<translation id="153384715582417236">Hiện đã hoàn tất</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>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />Kiểm tra proxy và tường lửa<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">Mã zip</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 đề xuất}other{# đề xuất}}</translation>
-<translation id="2065985942032347596">Yêu cầu Xác thực</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="2091887806945687916">Âm thanh</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">Hủy thanh toán</translation>
<translation id="2147827593068025794">Đồng bộ hóa dưới nền</translation>
<translation id="2148613324460538318">Thêm thẻ</translation>
-<translation id="2149973817440762519">Chỉnh sửa dấu trang</translation>
<translation id="2154054054215849342">Tính năng đồng bộ hóa không khả dụng cho miền của bạn</translation>
<translation id="2154484045852737596">Chỉnh sửa thẻ</translation>
<translation id="2166049586286450108">Quyền truy cập quản trị đầy đủ</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">Chọn địa chỉ nhận hàng</translation>
<translation id="2740531572673183784">Ok</translation>
<translation id="2742870351467570537">Xóa các mục đã chọn</translation>
-<translation id="2744590937989388266">Từ một trang được nhúng trên trang này</translation>
<translation id="277133753123645258">Phương thức giao hàng</translation>
<translation id="277499241957683684">Thiếu hồ sơ thiết bị</translation>
<translation id="2784949926578158345">Kết nối đã được đặt lại.</translation>
<translation id="2788784517760473862">Thẻ tín dụng được chấp nhận</translation>
<translation id="2794233252405721443">Trang web đã bị chặn</translation>
-<translation id="2795286477369100655">Bạn có muốn rời khỏi trang web này không?</translation>
<translation id="2799020568854403057">Trang web bạn sắp truy cập chứa ứng dụng có hạ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="2824775600643448204">Thanh địa chỉ và tìm kiếm</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">Mục nhập danh sách "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
<translation id="301521992641321250">Tự động bị chặn</translation>
<translation id="3024663005179499861">Loại chính sách sai</translation>
-<translation id="3032412215588512954">Bạn có muốn tải lại trang web này không?</translation>
<translation id="3037605927509011580">Ôi, hỏng! </translation>
<translation id="3039538478787849737">Lưu thẻ vào Google?</translation>
<translation id="3041612393474885105">Thông tin Chứng chỉ</translation>
@@ -310,6 +306,7 @@
đảm bảo rằng máy chủ proxy đang hoạt động. Nếu bạn cho rằng mình không cần
sử dụng máy chủ proxy:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> trên <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Hủy thanh toán</translation>
<translation id="3207960819495026254">Đã được đánh dấu trang</translation>
<translation id="3209375525920864198">Vui lòng nhập tên phiên hợp lệ.</translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">Người quản lý của bạn có thể bỏ chặn trang web cho bạn</translation>
<translation id="3566021033012934673">Kết nối của bạn không phải là kết nối riêng tư</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
+<translation id="3576616784287504635">Một trang được nhúng tại <ph name="SITE" /> cho biết</translation>
<translation id="358285529439630156">Thẻ tín dụng và thẻ trả trước được chấp nhận.</translation>
<translation id="3582930987043644930">Thêm tên</translation>
<translation id="3583757800736429874">&amp;Làm lại di chuyển</translation>
<translation id="3586931643579894722">Ẩn chi tiết</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;Khắc phục lỗi kết nối&lt;/h1&gt;
+ &lt;p&gt;Nếu bạn nhận được thông báo lỗi khi cố truy cập vào một trang web, hãy thử các cách khắc phục sau.&lt;/p&gt;
+ &lt;h2&gt;Khắc phục hầu hết các lỗi kết nối&lt;/h2&gt;
+ &lt;p&gt;Nếu bạn cố truy cập vào một trang web nhưng trang đó không mở, trước tiên, hãy tìm cách khắc phục lỗi bằng các bước khắc phục sự cố dưới đây:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Kiểm tra xem địa chỉ web có lỗi chính tả không.&lt;/li&gt;
+ &lt;li&gt;Đảm bảo kết nối Internet hoạt động bình thường.&lt;/li&gt;
+ &lt;li&gt;Liên hệ với chủ sở hữu trang web.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;Nhận trợ giúp về một thông báo lỗi cụ thể&lt;/h2&gt;
+ &lt;h3&gt;"Kết nối của bạn không phải là kết nối riêng tư", "NET::ERR_CERT_AUTHORITY_INVALID", "ERR_CERT_COMMON_NAME_INVALID", "NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM" hoặc "lỗi chứng chỉ SSL"&lt;/h3&gt;
+ &lt;h4&gt;Bước 1: Đăng nhập vào cổng công tin&lt;/h4&gt;
+ &lt;p&gt;Mạng Wi-Fi ở những nơi như quán cà phê hoặc sân bay cần bạn phải đăng nhập. Để biết trang đăng nhập, hãy truy cập vào một trang sử dụng&lt;code&gt;http://&lt;/code&gt;.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Truy cập vào một trang web bất kỳ bắt đầu bằng &lt;code&gt;http://&lt;/code&gt;, chẳng hạn như &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;.&lt;/li&gt;
+ &lt;li&gt;Trên trang đăng nhập mở ra, hãy đăng nhập để sử dụng Internet.&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;Bước 2: Mở trang trong chế độ ẩn danh (chỉ dành cho máy tính)&lt;/h4&gt;
+ &lt;p&gt;Mở trang bạn đã truy cập trong cửa sổ ẩn danh.&lt;/p&gt;
+ &lt;p&gt;Nếu trang mở ra, tức là tiện ích của Chrome hiện hoạt động không đúng cách. Để khắc phục lỗi này, hãy tắt tiện ích đó.&lt;/p&gt;
+ &lt;h4&gt;Bước 3: Cập nhật hệ điều hành&lt;/h4&gt;
+ &lt;p&gt;Đảm bảo thiết bị của bạn được cập nhật.&lt;/p&gt;
+ &lt;h4&gt;Bước 4: Tạm thời tắt phần mềm diệt vi-rút&lt;/h4&gt;
+ &lt;p&gt;Bạn sẽ gặp lỗi này nếu có phần mềm diệt vi-rút cung cấp tính năng "Bảo vệ HTTPS" hoặc "Quét HTTPS". Phần mềm diệt vi-rút đang ngăn không cho Chrome cung cấp bảo mật.&lt;/p&gt;
+ &lt;p&gt;Để khắc phục vấn đề, hãy tắt phần mềm diệt vi-rút. Nếu trang hoạt động sau khi tắt phần mềm, hãy tắt phần mềm này khi bạn sử dụng trang web an toàn.&lt;/p&gt;
+ &lt;p&gt;Hãy nhớ bật lại chương trình diệt vi-rút khi đã hoàn tất.&lt;/p&gt;
+ &lt;h4&gt;Bước 5: Nhận thêm trợ giúp&lt;/h4&gt;
+ &lt;p&gt;Nếu bạn vẫn gặp lỗi này, hãy liên hệ với chủ sở hữu trang web.&lt;/p&gt;
+ &lt;h3&gt;"Kết nối mạng"&lt;/h3&gt;
+ &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 trước khi có thể vào mạng.&lt;/p&gt;
+ &lt;p&gt;Để khắc phục lỗi, 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;
+ &lt;h3&gt;"Đồng hồ của bạn chạy chậm", "Đồng hồ của bạn chạy nhanh" hoặc "NET::ERR_CERT_DATE_INVALID"&lt;/h3&gt;
+ &lt;p&gt;Bạn sẽ gặp lỗi này nếu ngày và giờ trên máy tính hay thiết bị di động của bạn không chính xác.&lt;/p&gt;
+ &lt;p&gt;Để khắc phục lỗi này, hãy mở đồng hồ trên thiết bị rồi đảm bảo rằng ngày và giờ chính xác.&lt;/p&gt;
+ &lt;h3&gt;"Phần mềm trên máy tính của bạn đang ngăn Chrome kết nối an toàn với web" (chỉ dành cho máy tính Windows)&lt;/h3&gt;
+ &lt;p&gt;Bạn sẽ gặp lỗi này nếu có phần mềm Superfish trên máy tính Windows.&lt;/p&gt;
+ &lt;p&gt;Thực hiện các bước sau để tạm tắt phần mềm giúp bạn có thể truy cập vào web. Bạn cần có đặc quyền của quản trị viên.&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;Nhấp vào &lt;strong&gt;Bắt đầu&lt;/strong&gt;, sau đó tìm kiếm và chọn &lt;strong&gt;"Xem dịch vụ cục bộ"&lt;/strong&gt;
+ &lt;li&gt;Chọn &lt;strong&gt;VisualDiscovery&lt;/strong&gt;
+ &lt;li&gt;Trong phần &lt;strong&gt;Kiểu khởi động&lt;/strong&gt;, hãy chọn &lt;strong&gt;Đã tắt&lt;/strong&gt;
+ &lt;li&gt;Trong phần &lt;strong&gt;Trạng thái dịch vụ&lt;/strong&gt;, hãy nhấp vào &lt;strong&gt;Dừng&lt;/strong&gt;
+ &lt;li&gt;Nhấp vào &lt;strong&gt;Áp dụng&lt;/strong&gt;, sau đó nhấp vào &lt;strong&gt;OK&lt;/strong&gt;
+ &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 khỏi máy tính của bạn
+ &lt;/ol&gt;</translation>
<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>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">Bạn có muốn lưu thẻ này vào Tài khoản Google của bạn và trên thiết bị này không?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">Ngày hết hạn <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">Từ <ph name="SITE" /></translation>
<translation id="382518646247711829">Nếu bạn sử dụng máy chủ proxy...</translation>
<translation id="3828924085048779000">Không cho phép cụm mật khẩu trống.</translation>
<translation id="385051799172605136">Quay lại</translation>
@@ -418,6 +460,7 @@
<translation id="3945915738023014686">ID báo cáo sự cố đã tải lên <ph name="CRASH_ID" /> (ID sự cố cục bộ: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">Máy chủ này không thể chứng minh được đó là <ph name="DOMAIN" />; chứng chỉ bảo mật của máy chủ không chỉ định Tên thay thế đối tượng. Điều này có thể do cấu hình sai hoặc có kẻ tấn công chặn kết nối của bạn.</translation>
<translation id="3949601375789751990">Lịch sử duyệt web của bạn xuất hiện ở đây</translation>
+<translation id="3950820424414687140">Đăng nhập</translation>
<translation id="3963721102035795474">Chế độ đọc</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{Không có}=1{Từ 1 trang web }other{Từ # trang web }}</translation>
<translation id="397105322502079400">Đang tính...</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">Số sê-ri thiết bị không hợp lệ</translation>
<translation id="410351446219883937">Tự động phát</translation>
<translation id="4103763322291513355">Truy cập &lt;strong&gt;chrome://policy&lt;/strong&gt; để xem danh sách các URL bị chặn quyền truy cập và các chính sách khác bị quản trị viên hệ thống buộc phải thực thi.</translation>
+<translation id="4110652170750985508">Xem xét thanh toán của bạn</translation>
<translation id="4116663294526079822">Luôn cho phép trên trang web này</translation>
<translation id="4117700440116928470">Phạm vi chính sách không được hỗ trợ.</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 mục khác}other{# mục khác}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(Không có tên người dùng)</translation>
<translation id="4275830172053184480">Khởi động lại thiết bị của bạn</translation>
<translation id="4280429058323657511">, hết hạn <ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">Đăng nhập</translation>
<translation id="4312866146174492540">Chặn (mặc định)</translation>
<translation id="4325863107915753736">Không tìm được bài viết</translation>
<translation id="4326324639298822553">Kiểm tra ngày hết hạn của bạn và thử lại</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">Thẻ và địa chỉ từ Chrome và Tài khoản Google của bạn (<ph name="ACCOUNT_EMAIL" />). Bạn có thể quản lý thẻ và địa chỉ trong <ph name="BEGIN_LINK" />Cài đặt<ph name="END_LINK" />.</translation>
<translation id="4522570452068850558">Chi tiết</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">Từ một trang được nhúng tại <ph name="SITE" /></translation>
<translation id="4558551763791394412">Thử tắt tiện ích.</translation>
<translation id="457875822857220463">Giao hàng</translation>
<translation id="4582800630050655161">Bạn có thể mất quyền truy cập vào Tài khoản Google của mình hoặc bị đánh cắp danh tính. Chromium khuyên bạn nên thay đổi mật khẩu của mình ngay bây giờ.</translation>
<translation id="4587425331216688090">Xóa địa chỉ khỏi Chrome?</translation>
<translation id="4592951414987517459">Kết nối của bạn tới <ph name="DOMAIN" /> được mã hóa bằng bộ số 0 hiện đại.</translation>
<translation id="4594403342090139922">&amp;Hoàn tác xóa</translation>
-<translation id="4611292653554630842">Đăng nhập</translation>
<translation id="4619615317237390068">Tab từ các thiết bị khác</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Máy chủ này không chứng minh được rằng đó là <ph name="DOMAIN" />; chứng chỉ bảo mật của máy chủ này có lỗi. Điều này có thể do định cấu hình sai hoặc có kẻ tấn công chặn kết nối của bạn.</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">Kết nối của bạn bị gián đoạn</translation>
<translation id="471880041731876836">Bạn không có quyền để truy cập trang web này</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Chạy Chẩn đoán mạng của Windows<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">Thanh toán của bạn</translation>
<translation id="4726672564094551039">Tải lại chính sách</translation>
<translation id="4728558894243024398">Nền tảng</translation>
<translation id="4736825316280949806">Khởi động lại Chromium</translation>
-<translation id="4737498291095696011">Từ trang này</translation>
<translation id="4744603770635761495">Đường dẫn thực thi</translation>
<translation id="4749685221585524849">Sử dụng lần cuối: <ph name="LAST_USED_MONTH" /></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>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">Xem</translation>
<translation id="4854362297993841467">Phương thức phân phối này không có sẵn. Hãy thử một phương thức khác.</translation>
<translation id="4858792381671956233">Bạn đã hỏi cha mẹ mình xem có thể truy cập vào trang này hay không</translation>
-<translation id="4871132632506079383">Từ một trang được nhúng tại <ph name="SITE" /></translation>
<translation id="4880827082731008257">Lịch sử tìm kiếm</translation>
+<translation id="4881695831933465202">Mở</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">Yêu cầu xác thực</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{và thêm 1 trang web}other{và thêm # trang web}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">Hãy nhập CVC cho <ph name="CREDIT_CARD" />. Sau khi bạn xác nhận, thông tin chi tiết thẻ từ tài khoản thanh toán Google của bạn sẽ được chia sẻ với trang web này.</translation>
<translation id="4923417429809017348">Trang này đã được dịch từ một ngôn ngữ không xác định sang <ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">Thanh toán</translation>
<translation id="4926049483395192435">Phải được chỉ định.</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> cho biết</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">Tác vụ</translation>
<translation id="4958444002117714549">Mở rộng danh sách</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">Nếu được bật, Chrome sẽ lưu trữ bản sao thẻ của bạn trên thiết bị này để điền vào biểu mẫu nhanh hơn.</translation>
<translation id="5018422839182700155">Không thể mở trang này</translation>
<translation id="5019198164206649151">Không thể lưu trữ do chương trình phụ trợ ở trạng thái xấu</translation>
-<translation id="5020990877659450221">Từ trang này</translation>
<translation id="5023310440958281426">Kiểm tra chính sách của quản trị viên của bạn</translation>
<translation id="5029568752722684782">Xóa bản sao</translation>
<translation id="503069730517007720">Cần có chứng chỉ gốc cho "<ph name="SOFTWARE_NAME" />" nhưng chứng chỉ này chưa được cài đặt. Hãy yêu cầu quản trị viên CNTT của bạn xem hướng dẫn cấu hình cho "<ph name="SOFTWARE_NAME" />" để khắc phục sự cố này. <ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">Máy</translation>
<translation id="5179510805599951267">Không ở <ph name="ORIGINAL_LANGUAGE" />? Báo cáo lỗi này</translation>
<translation id="5190835502935405962">Thanh Dấu trang</translation>
+<translation id="5201306358585911203">Một trang được nhúng trên trang này cho biết</translation>
<translation id="5205222826937269299">Cần có tên</translation>
<translation id="5222812217790122047">Cần có email</translation>
<translation id="522700295135997067">Trang web này có thể vừa đánh cắp mật khẩu của bạn</translation>
<translation id="5230733896359313003">Địa chỉ giao hàng</translation>
<translation id="5251803541071282808">Đám mây</translation>
-<translation id="5277279256032773186">Sử dụng Chrome ở cơ quan? Các doanh nghiệp có thể quản lý cài đặt Chrome cho nhân viên của họ. Tìm hiểu thêm</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />Hãy làm theo các bước sau để tạm thời vô hiệu hóa phần mềm nhằm giúp bạn có thể truy cập vào web. Bạn cần phải có đặc quyền của quản trị viên.<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">Kiểm tra kết nối</translation>
<translation id="5610807607761827392">Bạn có thể quản lý thẻ và địa chỉ trong <ph name="BEGIN_LINK" />Cài đặt<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> đã chuyển hướng bạn quá nhiều lần.</translation>
-<translation id="5622887735448669177">Bạn có muốn rời khỏi trang web này không?</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="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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">Bạn có muốn điền thông tin thẻ của mình không?</translation>
<translation id="5803412860119678065">Bạn có muốn điền <ph name="CARD_DETAIL" /> của mình không?</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="5810928923025889964">Từ một trang được nhúng trên trang này</translation>
<translation id="5813119285467412249">&amp;Làm lại thêm</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>
<translation id="5866257070973731571">Thêm số điện thoại</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">Thêm thông tin khác</translation>
<translation id="6447842834002726250">Cookie</translation>
<translation id="6451458296329894277">Xác nhận việc Gửi lại Biểu mẫu</translation>
-<translation id="6456339708790392414">Thanh toán của bạn</translation>
<translation id="647261751007945333">Chính sách thiết bị</translation>
<translation id="6477321094435799029">Chrome đã phát hiện mã bất thường trên trang này và đã chặn mã này để bảo vệ thông tin cá nhân của bạn (ví dụ như mật khẩu, số điện thoại và thẻ tín dụng).</translation>
<translation id="6489534406876378309">Bắt đầu tải lên sự cố</translation>
<translation id="6507833130742554667">Thẻ tín dụng và thẻ ghi nợ được chấp nhận.</translation>
<translation id="6508722015517270189">Khởi động lại Chrome</translation>
-<translation id="6521373090216409766">Bạn có muốn tải lại trang web này không?</translation>
<translation id="6529602333819889595">&amp;Làm lại xóa</translation>
<translation id="6534179046333460208">Đề xuất Web trong cuộc sống</translation>
<translation id="6550675742724504774">Tùy chọn</translation>
-<translation id="6556239504065605927">Kết nối an toàn</translation>
<translation id="6556915248009097796">Hết hạn: <ph name="EXPIRATION_DATE_ABBR" />, sử dụng lần cuối: <ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">Người quản lý của bạn chưa phê duyệt trang web</translation>
<translation id="6569060085658103619">Bạn đang xem trang tiện ích</translation>
<translation id="6596325263575161958">Tùy chọn mã hóa</translation>
+<translation id="6604181099783169992">Cảm biến chuyển động hoặc ánh sáng</translation>
<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>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">Dấu trang được quản lý</translation>
<translation id="7298195798382681320">Được đề xuất</translation>
<translation id="7309308571273880165">Báo cáo sự cố được ghi lại vào <ph name="CRASH_TIME" /> (người dùng yêu cầu tải lên, nhưng chưa được tải lên)</translation>
+<translation id="7320336641823683070">Trợ giúp kết nối</translation>
<translation id="7334320624316649418">&amp;Làm lại sắp xếp lại</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="7353601530677266744">Dòng Lệnh</translation>
@@ -900,6 +935,7 @@
<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="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="7862185352068345852">Rời khỏi trang web?</translation>
<translation id="7878176543348854470">Thẻ ghi nợ và thẻ trả trước được chấp nhận.</translation>
<translation id="7878562273885520351">Mật khẩu của bạn có thể bị xâm phạm</translation>
<translation id="7887683347370398519">Kiểm tra CVC của bạn và thử lại</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">Sử dụng cài đặt mặc định chung (Hỏi)</translation>
<translation id="8042918947222776840">Chọn phương thức nhận hàng</translation>
<translation id="8057711352706143257">Cấu hình của "<ph name="SOFTWARE_NAME" />" không chính xác. Việc gỡ cài đặt "<ph name="SOFTWARE_NAME" />" thường sẽ khắc phục được sự cố này. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">Tải lại trang web?</translation>
<translation id="8088680233425245692">Không xem được bài viết.</translation>
<translation id="8091372947890762290">Kích hoạt đang chờ xử lý trên máy chủ</translation>
<translation id="8094917007353911263">Mạng mà bạn đang sử dụng có thể yêu cầu bạn phải truy cập <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
@@ -937,6 +974,7 @@
<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>
<translation id="8205463626947051446">Trang web thường hiển thị quảng cáo xâm nhập</translation>
+<translation id="8211406090763984747">Kết nối an toàn</translation>
<translation id="8218327578424803826">Vị trí được gán:</translation>
<translation id="8225771182978767009">Người thiết lập máy tính này đã chọn chặn trang web này.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<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="8267698848189296333">Đăng nhập với tên <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">Đăng nhập</translation>
<translation id="8288807391153049143">Hiển thị chứng chỉ</translation>
<translation id="8289355894181816810">Hãy liên hệ với quản trị viên mạng của bạn nếu bạn không chắc chắn về điều này có ý nghĩa gì.</translation>
<translation id="8293206222192510085">Thêm Dấu trang</translation>
@@ -999,6 +1038,7 @@
<translation id="874846938927089722">Thẻ tín dụng và thẻ trả trước được chấp nhận</translation>
<translation id="8759274551635299824">Thẻ này đã hết hạn</translation>
<translation id="8761567432415473239">Gần đây, Duyệt web an toàn của Google <ph name="BEGIN_LINK" />tìm thấy chương trình độc hại<ph name="END_LINK" /> trên trang <ph name="SITE" />.</translation>
+<translation id="8763927697961133303">Thiết bị USB</translation>
<translation id="8790007591277257123">&amp;Làm lại xóa</translation>
<translation id="8800988563907321413">Đề xuất ở gần bạn xuất hiện ở đây</translation>
<translation id="8820817407110198400">Dấu trang</translation>
diff --git a/chromium/components/strings/components_strings_zh-CN.xtb b/chromium/components/strings/components_strings_zh-CN.xtb
index b293f1a43b2..6dae05e0001 100644
--- a/chromium/components/strings/components_strings_zh-CN.xtb
+++ b/chromium/components/strings/components_strings_zh-CN.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">打印(&amp;P)...</translation>
<translation id="1181037720776840403">删除</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />自动向 Google 报告<ph name="END_WHITEPAPER_LINK" />可能出现的安全事件的详细信息。<ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">未能完成付款</translation>
<translation id="1201402288615127009">下一步</translation>
<translation id="1201895884277373915">来自该网站的更多内容</translation>
<translation id="1206967143813997005">初始签名不正确</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">崩溃报告获取时间:<ph name="CRASH_TIME" />(该报告尚未上传或已被忽略)</translation>
<translation id="1270502636509132238">取货方式</translation>
<translation id="1285320974508926690">一律不翻译此网站</translation>
+<translation id="1294154142200295408">命令行变体</translation>
<translation id="129553762522093515">最近关闭的标签页</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />尝试清除 Cookie<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">以下各方<ph name="BEGIN_EMPHASIS" />可能仍会看到<ph name="END_EMPHASIS" />您的活动:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">接受的信用卡和借记卡</translation>
<translation id="1519264250979466059">构建日期</translation>
<translation id="1527263332363067270">正在等待建立连接…</translation>
+<translation id="1532118530259321453">此网页显示</translation>
<translation id="153384715582417236">暂无新内容</translation>
<translation id="154408704832528245">选择速递地址</translation>
<translation id="1549470594296187301">必须启用 JavaScript 才能使用此功能。</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />检查代理服务器和防火墙<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">邮编</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 条建议}other{# 条建议}}</translation>
-<translation id="2065985942032347596">需要进行身份验证</translation>
<translation id="2079545284768500474">撤消</translation>
<translation id="20817612488360358">已设置为使用系统代理设置,但同时指定了一个明确的代理配置。</translation>
<translation id="2091887806945687916">声音</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">取消付款</translation>
<translation id="2147827593068025794">后台同步</translation>
<translation id="2148613324460538318">添加支付卡</translation>
-<translation id="2149973817440762519">修改书签</translation>
<translation id="2154054054215849342">您的网域不支持同步</translation>
<translation id="2154484045852737596">修改支付卡</translation>
<translation id="2166049586286450108">完全的管理员访问权限</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">选择取货地址</translation>
<translation id="2740531572673183784">确定</translation>
<translation id="2742870351467570537">移除所选项</translation>
-<translation id="2744590937989388266">来自此网页上的一个嵌入式页面</translation>
<translation id="277133753123645258">送货方式</translation>
<translation id="277499241957683684">缺少设备记录</translation>
<translation id="2784949926578158345">连接已重置。</translation>
<translation id="2788784517760473862">接受的信用卡</translation>
<translation id="2794233252405721443">网站已被屏蔽</translation>
-<translation id="2795286477369100655">要离开该网站吗?</translation>
<translation id="2799020568854403057">您要访问的网站包含有害应用</translation>
<translation id="2803306138276472711">Google安全浏览功能最近在<ph name="SITE" />上<ph name="BEGIN_LINK" />检测到了恶意软件<ph name="END_LINK" />。平常非常安全的网站有时也会感染恶意软件。</translation>
<translation id="2824775600643448204">地址和搜索栏</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">列表条目“<ph name="ENTRY_INDEX" />”:<ph name="ERROR" /></translation>
<translation id="301521992641321250">已被自动禁止</translation>
<translation id="3024663005179499861">策略类型有误</translation>
-<translation id="3032412215588512954">要重新加载该网站吗?</translation>
<translation id="3037605927509011580">喔唷,崩溃啦!</translation>
<translation id="3039538478787849737">将卡片信息保存到 Google?</translation>
<translation id="3041612393474885105">证书信息</translation>
@@ -308,6 +304,7 @@
<translation id="3174168572213147020">岛</translation>
<translation id="3176929007561373547">请检查您的代理服务器设置或与网络管理员联系,以确保代理服务器正常运行。如果您认为自己不需要使用代理服务器,请执行以下操作:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956">“<ph name="SERVER_NAME" />”上的“<ph name="PRINTER_NAME" />”</translation>
<translation id="320323717674993345">取消付款</translation>
<translation id="3207960819495026254">已加书签</translation>
<translation id="3209375525920864198">请输入一个有效的会话名称。</translation>
@@ -365,11 +362,57 @@
<translation id="3556433843310711081">您的管理员可为您取消屏蔽此网站</translation>
<translation id="3566021033012934673">您的连接不是私密连接</translation>
<translation id="3574305903863751447"><ph name="COUNTRY" /><ph name="STATE" /><ph name="CITY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" /> 上的嵌入式页面显示</translation>
<translation id="358285529439630156">接受信用卡和预付卡。</translation>
<translation id="3582930987043644930">添加名称</translation>
<translation id="3583757800736429874">恢复移动(&amp;R)</translation>
<translation id="3586931643579894722">隐藏详细信息</translation>
<translation id="3600246354004376029"><ph name="TITLE" />,<ph name="DOMAIN" />,<ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;修正连接错误&lt;/h1&gt;
+ &lt;p&gt;如果您在尝试访问某个网站时收到了错误消息,请考虑尝试以下解决方法。&lt;/p&gt;
+ &lt;h2&gt;修正大多数连接错误&lt;/h2&gt;
+ &lt;p&gt;如果您尝试访问某个网站,但它未能正常打开,请先尝试按照下述问题排查步骤来修正该错误:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;检查网址拼写是否有误。&lt;/li&gt;
+ &lt;li&gt;确保您的互联网连接正常。&lt;/li&gt;
+ &lt;li&gt;与网站所有者联系。&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;针对某条具体的错误消息获取相关帮助&lt;/h2&gt;
+ &lt;h3&gt;“您的连接不是私密连接”、“NET::ERR_CERT_AUTHORITY_INVALID”、“ERR_CERT_COMMON_NAME_INVALID”、“NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM”或“SSL 证书错误”&lt;/h3&gt;
+ &lt;h4&gt;第 1 步:登录门户&lt;/h4&gt;
+ &lt;p&gt;咖啡馆或机场等地方的 Wi-Fi 网络会要求用户进行登录。您只需随意访问一个采用 &lt;code&gt;http://&lt;/code&gt; 作为网址开头的网页,即可看到登录页面。&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;前往任一个采用 &lt;code&gt;http://&lt;/code&gt; 作为网址开头的网站,例如 &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;。&lt;/li&gt;
+ &lt;li&gt;在随即打开的登录页面中,登录以便使用互联网。&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;第 2 步:在无痕模式下打开该网页(仅限计算机)&lt;/h4&gt;
+ &lt;p&gt;在无痕式窗口中打开您在第 1 步中访问的那个网页。&lt;/p&gt;
+ &lt;p&gt;如果该页面顺利打开了,则说明某款 Chrome 扩展程序出现了异常。要想修正该错误,请关闭这款扩展程序。&lt;/p&gt;
+ &lt;h4&gt;第 3 步:更新您的操作系统&lt;/h4&gt;
+ &lt;p&gt;确保您的设备运行的是最新版操作系统。&lt;/p&gt;
+ &lt;h4&gt;第 4 步:暂时关闭您的防病毒软件&lt;/h4&gt;
+ &lt;p&gt;如果您安装了可提供“HTTPS 保护”或“HTTPS 扫描”功能的防病毒软件,您就会看到这条错误消息。此类防病毒软件会阻止 Chrome 提供安全保护。&lt;/p&gt;
+ &lt;p&gt;要想解决该问题,请关闭您的防病毒软件。如果关闭防病毒软件后该网页可以正常打开,那么当您使用安全网站时,请一定关闭此软件。&lt;/p&gt;
+ &lt;p&gt;事后请记得要重新开启您的防病毒程序。&lt;/p&gt;
+ &lt;h4&gt;第 5 步:获取额外帮助&lt;/h4&gt;
+ &lt;p&gt;如果您仍会看到这条错误消息,请与网站所有者联系。&lt;/p&gt;
+ &lt;h3&gt;“连接到网络”&lt;/h3&gt;
+ &lt;p&gt;如果您正在使用一个要求用户必须登录才能访问互联网的 Wi-Fi 门户,您就会看到这条错误消息。&lt;/p&gt;
+ &lt;p&gt;要想修正该错误,请在您尝试打开的网页上点击&lt;strong&gt;连接&lt;/strong&gt;。&lt;/p&gt;
+ &lt;h3&gt;“您的时钟慢了”、“您的时钟快了”或“NET::ERR_CERT_DATE_INVALID”&lt;/h3&gt;
+ &lt;p&gt;如果您的计算机或移动设备的日期与时间不准确,您就会看到这条错误消息。&lt;/p&gt;
+ &lt;p&gt;要想修正该错误,请打开您设备的时钟,并确保日期与时间正确无误。&lt;/p&gt;
+ &lt;h3&gt;“您计算机上的软件导致 Chrome 无法安全地连接到网络”(仅限 Windows 计算机)&lt;/h3&gt;
+ &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;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;
+ &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="3615877443314183785">请输入有效的失效日期</translation>
<translation id="36224234498066874">清除浏览数据...</translation>
<translation id="362276910939193118">显示所有历史记录</translation>
@@ -401,7 +444,6 @@
<translation id="3778403066972421603">要将此卡的信息保存到您的 Google 帐号中和此设备上吗?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">失效日期:<ph name="EXPIRATION_YEAR" /> 年 <ph name="EXPIRATION_MONTH" /> 月</translation>
-<translation id="3800436529451849929">来自 <ph name="SITE" /></translation>
<translation id="382518646247711829">如果您使用代理服务器…</translation>
<translation id="3828924085048779000">密码输入字段不能留空。</translation>
<translation id="385051799172605136">后退</translation>
@@ -415,6 +457,7 @@
<translation id="3945915738023014686">已上传的崩溃报告的 ID:<ph name="CRASH_ID" />(本地崩溃 ID:<ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">此服务器无法证实它就是 <ph name="DOMAIN" /> - 它的安全证书没有指定主题备用名称。这可能是因为某项配置有误或某个攻击者拦截了您的连接。</translation>
<translation id="3949601375789751990">您的浏览记录会显示在此处</translation>
+<translation id="3950820424414687140">登录</translation>
<translation id="3963721102035795474">阅读器模式</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{无}=1{来自 1 个网站}other{来自 # 个网站}}</translation>
<translation id="397105322502079400">正在计算...</translation>
@@ -431,6 +474,7 @@
<translation id="4103249731201008433">设备序列号无效</translation>
<translation id="410351446219883937">自动播放</translation>
<translation id="4103763322291513355">请访问 &lt;strong&gt;chrome:// 政策&lt;/strong&gt;,查看列入黑名单的网址列表以及您的系统管理员强制要求执行的其他政策。</translation>
+<translation id="4110652170750985508">查看您的付款</translation>
<translation id="4116663294526079822">在此网站上始终允许</translation>
<translation id="4117700440116928470">政策范围不受支持。</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{1 项其他内容}other{# 项其他内容}}</translation>
@@ -457,7 +501,6 @@
<translation id="4269787794583293679">(无用户名)</translation>
<translation id="4275830172053184480">重启您的设备</translation>
<translation id="4280429058323657511">,到期日期:<ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">登录</translation>
<translation id="4312866146174492540">屏蔽(默认)</translation>
<translation id="4325863107915753736">找不到文章</translation>
<translation id="4326324639298822553">请检查您的信用卡到期日期,然后重试</translation>
@@ -479,14 +522,12 @@
<translation id="4515275063822566619">信用卡选项和地址选项均来自 Chrome 和您的 Google 帐号 (<ph name="ACCOUNT_EMAIL" />)。您可在<ph name="BEGIN_LINK" />设置<ph name="END_LINK" />中管理这些选项。</translation>
<translation id="4522570452068850558">详细信息</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">来自 <ph name="SITE" /> 上的一个嵌入式页面</translation>
<translation id="4558551763791394412">尝试停用扩展程序。</translation>
<translation id="457875822857220463">递送</translation>
<translation id="4582800630050655161">您可能会无法再访问自己的 Google 帐号,或者遭遇身份信息被盗用。Chromium 建议您立即更改密码。</translation>
<translation id="4587425331216688090">从 Chrome 中移除地址?</translation>
<translation id="4592951414987517459">您与 <ph name="DOMAIN" /> 之间的连接采用新型加密套件进行了加密。</translation>
<translation id="4594403342090139922">撤消删除(&amp;U)</translation>
-<translation id="4611292653554630842">登录</translation>
<translation id="4619615317237390068">从其他设备打开的标签页</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">此服务器无法证明它是<ph name="DOMAIN" />;其安全证书有误。出现此问题的原因可能是配置有误或您的连接被拦截了。</translation>
@@ -496,11 +537,9 @@
<translation id="4708268264240856090">您的连接已中断</translation>
<translation id="471880041731876836">您无权访问此网站</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />运行 Windows 网络诊断<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">您的付款</translation>
<translation id="4726672564094551039">重新加载政策</translation>
<translation id="4728558894243024398">平台</translation>
<translation id="4736825316280949806">重新启动 Chromium</translation>
-<translation id="4737498291095696011">来自此网页</translation>
<translation id="4744603770635761495">可执行文件路径</translation>
<translation id="4749685221585524849">上次使用日期:<ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">您发送给这个网站的信息(例如密码或信用卡号)不会外泄。</translation>
@@ -519,16 +558,16 @@
<translation id="4850886885716139402">视图</translation>
<translation id="4854362297993841467">该递送方式不可用。请另选一种方式。</translation>
<translation id="4858792381671956233">您已向父母发送请求,询问他们是否允许您访问此网站</translation>
-<translation id="4871132632506079383">来自 <ph name="SITE" /> 上的一个嵌入式页面</translation>
<translation id="4880827082731008257">搜索历史记录</translation>
+<translation id="4881695831933465202">打开</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />、<ph name="TYPE_2" />、<ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">需要进行身份验证</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{和另外 1 个网页}other{和另外 # 个网页}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">请输入 <ph name="CREDIT_CARD" /> 的银行卡验证码 (CVC)。在您确认之后,您的 Google Payments 帐号中的信用卡详细信息将会共享给该网站。</translation>
<translation id="4923417429809017348">翻译服务器已将此网页从某种未知语言翻译成了<ph name="LANGUAGE_LANGUAGE" />。</translation>
<translation id="4923459931733593730">付款</translation>
<translation id="4926049483395192435">必须指定。</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> 显示</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">操作</translation>
<translation id="4958444002117714549">展开列表</translation>
@@ -537,7 +576,6 @@
<translation id="5002932099480077015">如果您选中此项,Chrome 会将您的卡的副本存储在此设备上,以加快表单填写速度。</translation>
<translation id="5018422839182700155">无法打开此网页</translation>
<translation id="5019198164206649151">后备存储状态不佳</translation>
-<translation id="5020990877659450221">来自此网页</translation>
<translation id="5023310440958281426">请查看管理员制定的政策</translation>
<translation id="5029568752722684782">清除副本</translation>
<translation id="503069730517007720">必须为“<ph name="SOFTWARE_NAME" />”安装根证书,但您尚未安装该证书。您的 IT 管理员应仔细查看“<ph name="SOFTWARE_NAME" />”的配置说明,以解决此问题。<ph name="FURTHER_EXPLANATION" /></translation>
@@ -563,12 +601,12 @@
<translation id="5172758083709347301">本机</translation>
<translation id="5179510805599951267">不是<ph name="ORIGINAL_LANGUAGE" />?报告此错误</translation>
<translation id="5190835502935405962">书签栏</translation>
+<translation id="5201306358585911203">此网页上的嵌入式页面显示</translation>
<translation id="5205222826937269299">需要提供名称</translation>
<translation id="5222812217790122047">需要提供电子邮件地址</translation>
<translation id="522700295135997067">此网站可能刚刚盗取了您的密码</translation>
<translation id="5230733896359313003">送货地址</translation>
<translation id="5251803541071282808">云端</translation>
-<translation id="5277279256032773186">使用 Chrome 办公?企业可以为其员工管理 Chrome 设置。了解详情</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />按照下述步骤操作可临时停用此类软件,以便您能够连接到网络。您需要具有管理员权限。<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -630,7 +668,6 @@
<translation id="5610142619324316209">检查网络连接</translation>
<translation id="5610807607761827392">您可以在<ph name="BEGIN_LINK" />设置<ph name="END_LINK" />中管理信用卡和地址信息。</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> 将您重定向的次数过多。</translation>
-<translation id="5622887735448669177">要离开此网站吗?</translation>
<translation id="5629630648637658800">无法加载策略设置</translation>
<translation id="5631439013527180824">设备管理令牌无效</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>
@@ -653,7 +690,6 @@
<translation id="5786044859038896871">要填充您的信用卡信息吗?</translation>
<translation id="5803412860119678065">要填充您的“<ph name="CARD_DETAIL" />”吗?</translation>
<translation id="5810442152076338065">您与 <ph name="DOMAIN" /> 之间的连接采用过时的加密套件进行了加密。</translation>
-<translation id="5810928923025889964">来自此网页上的一个嵌入式页面</translation>
<translation id="5813119285467412249">恢复添加(&amp;R)</translation>
<translation id="5838278095973806738">请勿在此网站上输入任何敏感信息(例如密码或信用卡信息),因为攻击者可能会盗取这些信息。</translation>
<translation id="5866257070973731571">添加电话号码</translation>
@@ -726,21 +762,19 @@
<translation id="6446608382365791566">添加更多信息</translation>
<translation id="6447842834002726250">Cookie</translation>
<translation id="6451458296329894277">确认重新提交表单</translation>
-<translation id="6456339708790392414">您的付款</translation>
<translation id="647261751007945333">设备政策</translation>
<translation id="6477321094435799029">Chrome 在此网页上检测到了异常代码。为保护您的个人信息(例如密码、电话号码和信用卡信息),Chrome 已将该网页拦截。</translation>
<translation id="6489534406876378309">开始上传崩溃数据</translation>
<translation id="6507833130742554667">接受信用卡和借记卡。</translation>
<translation id="6508722015517270189">重新启动 Chrome</translation>
-<translation id="6521373090216409766">要重新加载该网站吗?</translation>
<translation id="6529602333819889595">恢复删除(&amp;R)</translation>
<translation id="6534179046333460208">实物网建议</translation>
<translation id="6550675742724504774">选项</translation>
-<translation id="6556239504065605927">安全连接</translation>
<translation id="6556915248009097796">到期日期:<ph name="EXPIRATION_DATE_ABBR" />;上次使用日期:<ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">您的管理员尚未批准此网站</translation>
<translation id="6569060085658103619">您正在查看扩展程序页面</translation>
<translation id="6596325263575161958">加密选项</translation>
+<translation id="6604181099783169992">动态传感器或光传感器</translation>
<translation id="6624427990725312378">联系信息</translation>
<translation id="6626291197371920147">添加有效的卡号</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> 搜索</translation>
@@ -812,6 +846,7 @@
<translation id="7275334191706090484">受管理的书签</translation>
<translation id="7298195798382681320">推荐</translation>
<translation id="7309308571273880165">崩溃报告获取时间:<ph name="CRASH_TIME" />(用户已请求上传,但尚未上传)</translation>
+<translation id="7320336641823683070">与连接相关的帮助</translation>
<translation id="7334320624316649418">恢复顺序调整(&amp;R)</translation>
<translation id="733923710415886693">该服务器的证书未通过证书透明度政策进行披露。</translation>
<translation id="7353601530677266744">命令行</translation>
@@ -896,6 +931,7 @@
<translation id="782886543891417279">您要使用的 Wi-Fi 网络(<ph name="WIFI_NAME" />)可能需要您访问其登录页面。</translation>
<translation id="785549533363645510">但是,这并不意味着您能完全隐身。即使您进入隐身模式,您的雇主、互联网服务提供商和您访问的网站仍然能看到您的浏览活动。</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">离开此网站?</translation>
<translation id="7878176543348854470">接受借记卡和预付卡。</translation>
<translation id="7878562273885520351">您的密码可能会被盗用</translation>
<translation id="7887683347370398519">请检查您的银行卡验证码 (CVC),然后重试</translation>
@@ -918,6 +954,7 @@
<translation id="8041940743680923270">使用全局默认设置(询问)</translation>
<translation id="8042918947222776840">选择取货方式</translation>
<translation id="8057711352706143257">“<ph name="SOFTWARE_NAME" />”的配置有误。卸载“<ph name="SOFTWARE_NAME" />”通常可解决此问题。<ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">重新加载此网站?</translation>
<translation id="8088680233425245692">无法查看文章。</translation>
<translation id="8091372947890762290">正等待在服务器上激活</translation>
<translation id="8094917007353911263">您要使用的网络可能需要您访问 <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />。</translation>
@@ -933,6 +970,7 @@
<translation id="8201077131113104583">ID 为“<ph name="EXTENSION_ID" />”的扩展程序的更新网址无效。</translation>
<translation id="8202097416529803614">订单摘要</translation>
<translation id="8205463626947051446">网站常常会展示侵扰性广告</translation>
+<translation id="8211406090763984747">连接是安全的</translation>
<translation id="8218327578424803826">分配的位置:</translation>
<translation id="8225771182978767009">设置此计算机的用户已选择屏蔽此网站。</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />、<ph name="TYPE_2" /></translation>
@@ -944,6 +982,7 @@
<translation id="825929999321470778">显示所有已保存的密码</translation>
<translation id="8261506727792406068">删除</translation>
<translation id="8267698848189296333">目前登录的帐号是 <ph name="USERNAME" /></translation>
+<translation id="8286036467436129157">登录</translation>
<translation id="8288807391153049143">显示证书</translation>
<translation id="8289355894181816810">如果您不确定这是什么意思,请与您的网络管理员联系。</translation>
<translation id="8293206222192510085">添加书签</translation>
@@ -995,6 +1034,7 @@
<translation id="874846938927089722">接受的信用卡和预付卡</translation>
<translation id="8759274551635299824">此信用卡已失效</translation>
<translation id="8761567432415473239">Google安全浏览功能最近在<ph name="SITE" />上<ph name="BEGIN_LINK" />发现了有害程序<ph name="END_LINK" />。</translation>
+<translation id="8763927697961133303">USB 设备</translation>
<translation id="8790007591277257123">恢复删除(&amp;R)</translation>
<translation id="8800988563907321413">此处将显示系统建议您浏览的附近网页</translation>
<translation id="8820817407110198400">书签</translation>
diff --git a/chromium/components/strings/components_strings_zh-TW.xtb b/chromium/components/strings/components_strings_zh-TW.xtb
index a5c3a20bd0c..683cd63d501 100644
--- a/chromium/components/strings/components_strings_zh-TW.xtb
+++ b/chromium/components/strings/components_strings_zh-TW.xtb
@@ -31,7 +31,6 @@
<translation id="1175364870820465910">列印(&amp;P)...</translation>
<translation id="1181037720776840403">移除</translation>
<translation id="1184214524891303587"><ph name="BEGIN_WHITEPAPER_LINK" />自動向 Google 回報<ph name="END_WHITEPAPER_LINK" />疑似安全性事件的詳細資料。<ph name="PRIVACY_PAGE_LINK" /></translation>
-<translation id="1193706408197842297">未完成付款程序</translation>
<translation id="1201402288615127009">繼續</translation>
<translation id="1201895884277373915">這個網站的更多內容</translation>
<translation id="1206967143813997005">縮寫簽名無效</translation>
@@ -47,6 +46,7 @@
<translation id="1264126396475825575">當機報告擷取時間:<ph name="CRASH_TIME" /> (尚未上傳或略過)</translation>
<translation id="1270502636509132238">取件方式</translation>
<translation id="1285320974508926690">一律不翻譯此網站</translation>
+<translation id="1294154142200295408">命令列變化版本</translation>
<translation id="129553762522093515">最近關閉的分頁</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />試試看清除 Cookie<ph name="END_LINK" /></translation>
<translation id="1333989956347591814">以下各方<ph name="BEGIN_EMPHASIS" />可能仍會看到<ph name="END_EMPHASIS" />你的活動:
@@ -74,6 +74,7 @@
<translation id="1517500485252541695">接受的信用卡和簽帳金融卡</translation>
<translation id="1519264250979466059">建立日期</translation>
<translation id="1527263332363067270">正在等待連線…</translation>
+<translation id="1532118530259321453">這個網頁顯示</translation>
<translation id="153384715582417236">暫無內容</translation>
<translation id="154408704832528245">選擇快遞地址</translation>
<translation id="1549470594296187301">您必須啟用 JavaScript 才能使用這項功能。</translation>
@@ -92,7 +93,7 @@
<translation id="1640180200866533862">使用者政策</translation>
<translation id="1640244768702815859">請嘗試<ph name="BEGIN_LINK" />造訪網站首頁<ph name="END_LINK" />。</translation>
<translation id="1644184664548287040">網路設定無效,無法匯入。</translation>
-<translation id="1644574205037202324">歷史紀錄</translation>
+<translation id="1644574205037202324">歷史記錄</translation>
<translation id="1645368109819982629">不支援的通訊協定</translation>
<translation id="1655462015569774233">{1,plural, =1{這個伺服器無法證明所在網域是 <ph name="DOMAIN" />;伺服器的安全性憑證已在昨天過期。這可能是因為設定錯誤,或是有攻擊者攔截您的連線。您電腦的時鐘目前設為 <ph name="CURRENT_DATE" />,這是正確的時間嗎?如果不是的話,請更新系統時鐘,然後重新整理這個網頁。}other{這個伺服器無法證明所在網域是 <ph name="DOMAIN" />;伺服器的安全性憑證已在 # 天前過期。這可能是因為設定錯誤,或是有攻擊者攔截您的連線。您電腦的時鐘目前設為 <ph name="CURRENT_DATE" />,這是正確的時間嗎?如果不是的話,請更新系統時鐘,然後重新整理這個網頁。}}</translation>
<translation id="1656489000284462475">取件</translation>
@@ -146,7 +147,6 @@
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />檢查 Proxy 和防火牆<ph name="END_LINK" /></translation>
<translation id="2053553514270667976">郵遞區號</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 個建議項目}other{# 個建議項目}}</translation>
-<translation id="2065985942032347596">需要驗證</translation>
<translation id="2079545284768500474">復原</translation>
<translation id="20817612488360358">雖然系統 Proxy 設定已設為使用,不過也指定了明確 Proxy 設定。</translation>
<translation id="2091887806945687916">音訊</translation>
@@ -160,7 +160,6 @@
<translation id="214556005048008348">取消付款</translation>
<translation id="2147827593068025794">背景同步處理</translation>
<translation id="2148613324460538318">新增卡片</translation>
-<translation id="2149973817440762519">編輯書籤</translation>
<translation id="2154054054215849342">你的網域無法使用同步功能</translation>
<translation id="2154484045852737596">編輯卡片資訊</translation>
<translation id="2166049586286450108">完整管理員存取權</translation>
@@ -228,7 +227,7 @@
<translation id="2650446666397867134">存取檔案遭拒</translation>
<translation id="2653659639078652383">提交</translation>
<translation id="2666117266261740852">關閉其他分頁或應用程式</translation>
-<translation id="2674170444375937751">確定要從你的紀錄中刪除這些網頁嗎?</translation>
+<translation id="2674170444375937751">確定要從你的記錄中刪除這些網頁嗎?</translation>
<translation id="2677748264148917807">離開</translation>
<translation id="2699302886720511147">接受的卡片</translation>
<translation id="2702801445560668637">閱讀清單</translation>
@@ -245,13 +244,11 @@
<translation id="2738330467931008676">選擇取件地址</translation>
<translation id="2740531572673183784">確定</translation>
<translation id="2742870351467570537">移除選取的項目</translation>
-<translation id="2744590937989388266">來自這個網頁上的嵌入式網頁</translation>
<translation id="277133753123645258">運送方式</translation>
-<translation id="277499241957683684">沒有裝置紀錄</translation>
+<translation id="277499241957683684">沒有裝置記錄</translation>
<translation id="2784949926578158345">連線已重設。</translation>
<translation id="2788784517760473862">接受的信用卡</translation>
<translation id="2794233252405721443">網站遭到封鎖</translation>
-<translation id="2795286477369100655">你要離開這個網站嗎?</translation>
<translation id="2799020568854403057">你要造訪的網站含有有害的應用程式</translation>
<translation id="2803306138276472711">Google 安全瀏覽功能最近在 <ph name="SITE" /> 上<ph name="BEGIN_LINK" />偵測到惡意軟體<ph name="END_LINK" />。即使是平常可以安全使用的網站,有時也會遭到惡意軟體感染。</translation>
<translation id="2824775600643448204">網址與搜尋列</translation>
@@ -285,7 +282,6 @@
<translation id="3010559122411665027">清單項目「<ph name="ENTRY_INDEX" />」:<ph name="ERROR" /></translation>
<translation id="301521992641321250">已自動封鎖</translation>
<translation id="3024663005179499861">政策類型有誤</translation>
-<translation id="3032412215588512954">您要重新載入這個網站嗎?</translation>
<translation id="3037605927509011580">糟糕!</translation>
<translation id="3039538478787849737">要將卡片資訊儲存到 Google 嗎?</translation>
<translation id="3041612393474885105">憑證資訊</translation>
@@ -303,13 +299,14 @@
<translation id="3154506275960390542">這個網頁中的表單可能不會經由安全途徑提交。其他人可能會在傳輸期間檢視你的資料,攻擊者也可能會修改這些資料,導致伺服器接收不同內容。</translation>
<translation id="3157931365184549694">還原</translation>
<translation id="3162559335345991374">目前使用的 Wi-Fi 網路可能會要求您造訪登入網頁。</translation>
-<translation id="3167968892399408617">當您關閉所有無痕式分頁後,您在其中瀏覽的網頁都不會保留在瀏覽器紀錄、Cookie 儲存庫或搜尋紀錄中。不過,您下載的檔案或建立的書籤全部都會保留下來。</translation>
+<translation id="3167968892399408617">當您關閉所有無痕式分頁後,您在其中瀏覽的網頁都不會保留在瀏覽器記錄、Cookie 儲存庫或搜尋記錄中。不過,您下載的檔案或建立的書籤全部都會保留下來。</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">島</translation>
<translation id="3176929007561373547">檢查您的 Proxy 設定,或是與您的網路管理員聯絡
確認您的 Proxy 伺服器運作正常。如果您認為自己不需要使用
Proxy 伺服器:
<ph name="PLATFORM_TEXT" /></translation>
+<translation id="3195213714973468956"><ph name="SERVER_NAME" /> 上的 <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">取消付款</translation>
<translation id="3207960819495026254">已加入書籤</translation>
<translation id="3209375525920864198">請輸入有效的工作階段名稱。</translation>
@@ -334,7 +331,7 @@
<translation id="3355823806454867987">變更 Proxy 設定...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />不會儲存<ph name="END_EMPHASIS" />下列資訊:
<ph name="BEGIN_LIST" />
- <ph name="LIST_ITEM" />你的瀏覽紀錄
+ <ph name="LIST_ITEM" />你的瀏覽記錄
<ph name="LIST_ITEM" />Cookie 和網站資料
<ph name="LIST_ITEM" />你在表單中輸入的資訊
<ph name="END_LIST" /></translation>
@@ -367,11 +364,57 @@
<translation id="3556433843310711081">你的管理員可以為你解除封鎖這個網站</translation>
<translation id="3566021033012934673">你的連線不是私人連線</translation>
<translation id="3574305903863751447"><ph name="COUNTRY" />,<ph name="STATE" />,<ph name="CITY" /></translation>
+<translation id="3576616784287504635"><ph name="SITE" /> 的嵌入式網頁顯示</translation>
<translation id="358285529439630156">接受信用卡和預付卡。</translation>
<translation id="3582930987043644930">新增名稱</translation>
<translation id="3583757800736429874">重做移動(&amp;R)</translation>
<translation id="3586931643579894722">隱藏詳細資訊</translation>
<translation id="3600246354004376029"><ph name="TITLE" />,<ph name="DOMAIN" />,<ph name="TIME" /></translation>
+<translation id="3602137825010714926">&lt;h1&gt;修正連線錯誤&lt;/h1&gt;
+ &lt;p&gt;如果您在嘗試瀏覽網站時收到錯誤訊息,建議您使用以下方法來修正問題。&lt;/p&gt;
+ &lt;h2&gt;修正常見連線錯誤&lt;/h2&gt;
+ &lt;p&gt;如果您無法順利開啟網站,請先嘗試按照以下疑難排解步驟修正相關錯誤:&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;檢查網址是否輸入錯誤。&lt;/li&gt;
+ &lt;li&gt;確認您的網際網路連線正常運作。&lt;/li&gt;
+ &lt;li&gt;與網站擁有者聯絡。&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h2&gt;瞭解如何修正特定錯誤訊息指出的錯誤&lt;/h2&gt;
+ &lt;h3&gt;「你的連線不是私人連線」、「NET::ERR_CERT_AUTHORITY_INVALID」、「ERR_CERT_COMMON_NAME_INVALID」、「NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM」或「SSL 憑證錯誤」&lt;/h3&gt;
+ &lt;h4&gt;步驟 1:從入口網站登入&lt;/h4&gt;
+ &lt;p&gt;咖啡館或機場等地點的 Wi-Fi 網路必須先登入才能使用。如要查看登入頁面,請造訪使用 &lt;code&gt;http://&lt;/code&gt; 的網頁。&lt;/p&gt;
+ &lt;ol&gt;
+ &lt;li&gt;前往網址開頭為 &lt;code&gt;http://&lt;/code&gt; 的任何網站,例如 &lt;a href="http://example.com" target="_blank"&gt;http://example.com&lt;/a&gt;。&lt;/li&gt;
+ &lt;li&gt;在隨即開啟的登入頁面登入後,即可使用網際網路。&lt;/li&gt;
+ &lt;/ol&gt;
+ &lt;h4&gt;步驟 2:以無痕模式開啟網頁 (僅適用於電腦)&lt;/h4&gt;
+ &lt;p&gt;使用無痕式視窗開啟您曾造訪的網頁。&lt;/p&gt;
+ &lt;p&gt;如果網頁可以順利開啟,表示有 Chrome 擴充功能並未正常運作。如要修正這項錯誤,請關閉該擴充功能。&lt;/p&gt;
+ &lt;h4&gt;步驟 3:更新您的作業系統&lt;/h4&gt;
+ &lt;p&gt;確認您的裝置已更新至最新版本的作業系統。&lt;/p&gt;
+ &lt;h4&gt;步驟 4:暫時關閉防毒軟體&lt;/h4&gt;
+ &lt;p&gt;如果您的電腦使用任何提供「HTTPS 保護」或「HTTPS 掃描」功能的防毒軟體,導致 Chrome 無法提供安全支援,系統就會顯示這則錯誤訊息。&lt;/p&gt;
+ &lt;p&gt;如要修正這個問題,請關閉防毒軟體。如果這麼做可以順利解決問題,代表您必須關閉防毒軟體,才能使用安全網站。&lt;/p&gt;
+ &lt;p&gt;事後請記得再次開啟防毒程式。&lt;/p&gt;
+ &lt;h4&gt;步驟 5:尋求更多協助&lt;/h4&gt;
+ &lt;p&gt;如果您仍看見錯誤訊息,請與網站擁有者聯絡。&lt;/p&gt;
+ &lt;h3&gt;「連線至網路」&lt;/h3&gt;
+ &lt;p&gt;如果您使用的 Wi-Fi 入口網站必須先登入才能連上網路,系統就會顯示這則錯誤訊息。&lt;/p&gt;
+ &lt;p&gt;如要修正這項錯誤,請在您要嘗試開啟的網頁上按一下 [連線]。&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
+ &lt;h3&gt;「你的時鐘時間過慢」、「你的時鐘時間過快」或「NET::ERR_CERT_DATE_INVALID」&lt;/h3&gt;
+ &lt;p&gt;如果畫面顯示這則錯誤訊息,表示您電腦或行動裝置的日期或時間不正確。&lt;/p&gt;
+ &lt;p&gt;如要修正這項錯誤,請開啟裝置的時鐘,確認時間和日期是否正確無誤。&lt;/p&gt;
+ &lt;h3&gt;「你的電腦上有軟體阻止 Chrome 建立安全的網路連線」(僅限 Windows 電腦)&lt;/h3&gt;
+ &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;選取 [VisualDiscovery]&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;&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;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome 說明中心&lt;/a&gt;瞭解如何將該軟體從電腦上永久移除
+ &lt;/ol&gt;</translation>
<translation id="3615877443314183785">請輸入有效的到期日</translation>
<translation id="36224234498066874">清除瀏覽資料...</translation>
<translation id="362276910939193118">顯示完整記錄</translation>
@@ -404,7 +447,6 @@
<translation id="3778403066972421603">你要將這張信用卡的資訊儲存到你在這個裝置上的 Google 帳戶嗎?</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3787705759683870569">到期日:<ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="3800436529451849929">來自 <ph name="SITE" /></translation>
<translation id="382518646247711829">如果你使用 Proxy 伺服器...</translation>
<translation id="3828924085048779000">通關密語欄位不得留空。</translation>
<translation id="385051799172605136">返回</translation>
@@ -417,7 +459,8 @@
<translation id="3909695131102177774"><ph name="LABEL" />:<ph name="ERROR" /></translation>
<translation id="3945915738023014686">已上傳的當機報告 ID:<ph name="CRASH_ID" /> (本機當機 ID:<ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="3949571496842715403">這個伺服器無法證明所屬網域為 <ph name="DOMAIN" />;其安全性憑證未指定主體別名。這可能是因為設定錯誤,或是有攻擊者攔截你的連線所致。</translation>
-<translation id="3949601375789751990">你的瀏覽紀錄會顯示在這裡</translation>
+<translation id="3949601375789751990">你的瀏覽記錄會顯示在這裡</translation>
+<translation id="3950820424414687140">登入</translation>
<translation id="3963721102035795474">閱讀器模式</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{無}=1{來自 1 個網站 }other{來自 # 個網站 }}</translation>
<translation id="397105322502079400">計算中…</translation>
@@ -434,6 +477,7 @@
<translation id="4103249731201008433">裝置序號無效</translation>
<translation id="410351446219883937">自動播放</translation>
<translation id="4103763322291513355">請前往 &lt;strong&gt;chrome://policy&lt;/strong&gt; 查看列入黑名單的網址清單,以及其他系統管理員強制執行的政策。</translation>
+<translation id="4110652170750985508">查看您的付款</translation>
<translation id="4116663294526079822">永遠允許在這個網站執行</translation>
<translation id="4117700440116928470">系統不支援這項政策的範圍。</translation>
<translation id="4129401438321186435">{COUNT,plural, =1{以及另外 1 項表單資料}other{以及另外 # 項表單資料}}</translation>
@@ -460,7 +504,6 @@
<translation id="4269787794583293679">(沒有使用者名稱)</translation>
<translation id="4275830172053184480">重新啟動裝置</translation>
<translation id="4280429058323657511">,到期日:<ph name="EXPIRATION_DATE_ABBR" /></translation>
-<translation id="4304224509867189079">登入</translation>
<translation id="4312866146174492540">封鎖 (預設)</translation>
<translation id="4325863107915753736">找不到文章</translation>
<translation id="4326324639298822553">請檢查信用卡到期日,然後再試一次</translation>
@@ -482,14 +525,12 @@
<translation id="4515275063822566619">信用卡和地址資訊皆來自 Chrome 和你的 Google 帳戶 (<ph name="ACCOUNT_EMAIL" />)。你可以在<ph name="BEGIN_LINK" />設定<ph name="END_LINK" />頁面管理這些資訊。</translation>
<translation id="4522570452068850558">詳細資訊</translation>
<translation id="4552089082226364758">Flash</translation>
-<translation id="4554702541363482291">來自 <ph name="SITE" /> 的嵌入式網頁</translation>
<translation id="4558551763791394412">試試看停用擴充功能。</translation>
<translation id="457875822857220463">快遞</translation>
<translation id="4582800630050655161">你可能失去了 Google 帳戶存取權,或身分遭到冒用。Chromium 建議你立即變更密碼。</translation>
<translation id="4587425331216688090">要從 Chrome 中移除地址嗎?</translation>
<translation id="4592951414987517459">您的 <ph name="DOMAIN" /> 連線使用新型加密套件進行加密。</translation>
<translation id="4594403342090139922">復原刪除(&amp;U)</translation>
-<translation id="4611292653554630842">登入</translation>
<translation id="4619615317237390068">在其他裝置上開啟的分頁</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">伺服器無法證明其屬於 <ph name="DOMAIN" /> 網域;其安全性憑證含有錯誤。這可能是因為設定錯誤,或有攻擊者攔截你的連線所致。</translation>
@@ -499,11 +540,9 @@
<translation id="4708268264240856090">您的連線已中斷</translation>
<translation id="471880041731876836">你沒有這個網站的瀏覽權限</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />執行 Windows 網路診斷<ph name="END_LINK" /></translation>
-<translation id="472349245089439925">你的付款</translation>
<translation id="4726672564094551039">重新載入政策</translation>
<translation id="4728558894243024398">平台</translation>
<translation id="4736825316280949806">重新啟動 Chromium</translation>
-<translation id="4737498291095696011">來自這個網頁</translation>
<translation id="4744603770635761495">可執行檔的路徑</translation>
<translation id="4749685221585524849">上次使用日期:<ph name="LAST_USED_MONTH" /></translation>
<translation id="4750917950439032686">你傳送給這個網站的資訊 (例如密碼或信用卡號碼) 不會外洩。</translation>
@@ -522,16 +561,16 @@
<translation id="4850886885716139402">檢視</translation>
<translation id="4854362297993841467">不支援所選的快遞方式,請改選其他方式。</translation>
<translation id="4858792381671956233">你已詢問家長是否同意你造訪這個網站</translation>
-<translation id="4871132632506079383">來自 <ph name="SITE" /> 的嵌入式網頁</translation>
-<translation id="4880827082731008257">搜尋紀錄</translation>
+<translation id="4880827082731008257">搜尋記錄</translation>
+<translation id="4881695831933465202">開啟</translation>
<translation id="4895877746940133817"><ph name="TYPE_1" />、<ph name="TYPE_2" />,<ph name="TYPE_3" /></translation>
-<translation id="4913131542719409934">需要進行驗證</translation>
<translation id="4914479371620770914">{URL_count,plural, =1{還有另外 1 個網頁}other{還有另外 # 個網頁}}</translation>
<translation id="4916962322362512664"><ph name="DEVICE_NAME" /></translation>
<translation id="4919958102839282947">請輸入 <ph name="CREDIT_CARD" /> 的信用卡安全碼。完成驗證後,這個網站就會取得你 Google 付款帳戶中的信用卡詳細資料。</translation>
<translation id="4923417429809017348">系統已將此網頁從不明語言翻譯成<ph name="LANGUAGE_LANGUAGE" /></translation>
<translation id="4923459931733593730">付款</translation>
<translation id="4926049483395192435">必須指定。</translation>
+<translation id="4926159001844873046"><ph name="SITE" /> 顯示</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
<translation id="495170559598752135">動作</translation>
<translation id="4958444002117714549">展開清單</translation>
@@ -540,7 +579,6 @@
<translation id="5002932099480077015">啟用後,Chrome 會將您的信用卡複本儲存在這個裝置上,以加快表單填寫速度。</translation>
<translation id="5018422839182700155">無法開啟這個網頁</translation>
<translation id="5019198164206649151">備份儲存狀態不佳</translation>
-<translation id="5020990877659450221">來自這個網頁</translation>
<translation id="5023310440958281426">請查看你的管理員政策</translation>
<translation id="5029568752722684782">清除複本</translation>
<translation id="503069730517007720">未安裝必要的「<ph name="SOFTWARE_NAME" />」根憑證。IT 管理員必須按照「<ph name="SOFTWARE_NAME" />」的設定說明修正這個問題。<ph name="FURTHER_EXPLANATION" /></translation>
@@ -566,12 +604,12 @@
<translation id="5172758083709347301">本機</translation>
<translation id="5179510805599951267">網頁內容不是<ph name="ORIGINAL_LANGUAGE" />嗎?請回報此錯誤</translation>
<translation id="5190835502935405962">書籤列</translation>
+<translation id="5201306358585911203">這個網頁上的嵌入式網頁顯示</translation>
<translation id="5205222826937269299">請輸入名稱</translation>
<translation id="5222812217790122047">請輸入電子郵件地址</translation>
<translation id="522700295135997067">這個網站剛剛可能竊取了你的密碼</translation>
<translation id="5230733896359313003">運送地址</translation>
<translation id="5251803541071282808">雲端</translation>
-<translation id="5277279256032773186">在工作環境使用 Chrome 嗎?企業可以管理員工的 Chrome 設定。瞭解詳情</translation>
<translation id="5281113152797308730"><ph name="BEGIN_PARAGRAPH" />請按照以下步驟暫時停用該軟體,以便順利連上網路。你需要管理員權限。<ph name="END_PARAGRAPH" />
<ph name="BEGIN_LIST" />
@@ -633,7 +671,6 @@
<translation id="5610142619324316209">檢查連線狀態</translation>
<translation id="5610807607761827392">你可以在<ph name="BEGIN_LINK" />設定<ph name="END_LINK" />中管理信用卡和地址資訊。</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> 將您重新導向的次數過多。</translation>
-<translation id="5622887735448669177">您要離開這個網站嗎?</translation>
<translation id="5629630648637658800">無法載入政策設定</translation>
<translation id="5631439013527180824">裝置管理符記無效</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>
@@ -656,7 +693,6 @@
<translation id="5786044859038896871">要填入你的信用卡資訊嗎?</translation>
<translation id="5803412860119678065">要填入你的 <ph name="CARD_DETAIL" /> 資訊嗎?</translation>
<translation id="5810442152076338065">您的 <ph name="DOMAIN" /> 連線使用過舊的加密套件進行加密。</translation>
-<translation id="5810928923025889964">來自這個網頁上的嵌入式網頁</translation>
<translation id="5813119285467412249">重做新增(&amp;R)</translation>
<translation id="5838278095973806738">請勿在這個網站上輸入任何機密資訊 (例如密碼或信用卡號碼),以免遭到攻擊者竊取。</translation>
<translation id="5866257070973731571">新增電話號碼</translation>
@@ -668,7 +704,7 @@
<translation id="5939518447894949180">重設</translation>
<translation id="5959728338436674663">自動傳送部分<ph name="BEGIN_WHITEPAPER_LINK" />系統資訊和網頁內容<ph name="END_WHITEPAPER_LINK" />給 Google,協助偵測危險的應用程式和網站。<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="5967592137238574583">編輯聯絡資訊</translation>
-<translation id="5967867314010545767">從紀錄中移除</translation>
+<translation id="5967867314010545767">從記錄中移除</translation>
<translation id="5972020793760134803">切換至分頁</translation>
<translation id="5975083100439434680">縮小</translation>
<translation id="597552863672748783">確認安全碼</translation>
@@ -686,7 +722,7 @@
<translation id="6047927260846328439">這項內容可能會試圖誘使你安裝軟體或提供個人資訊。<ph name="BEGIN_LINK" />仍要顯示<ph name="END_LINK" /></translation>
<translation id="6051221802930200923">目前無法造訪 <ph name="SITE" />,因為這個網站使用憑證鎖定功能。網路錯誤和攻擊行為通常是暫時性的,因此這個網頁可能稍後就會恢復正常狀態。</translation>
<translation id="6080696365213338172">你使用了管理員提供的憑證存取內容,因此管理員可攔截你傳送至「<ph name="DOMAIN" />」的資料。</translation>
-<translation id="610911394827799129">你的 Google 帳戶仍可能保留了其他類型的瀏覽紀錄 (可前往 <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> 查詢)。</translation>
+<translation id="610911394827799129">你的 Google 帳戶仍可能保留了其他類型的瀏覽記錄 (可前往 <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> 查詢)。</translation>
<translation id="6144381551823904650">{COUNT,plural, =0{無}=1{1 組密碼 (保持同步)}other{# 組密碼 (保持同步)}}</translation>
<translation id="6146055958333702838">檢查您的網路線是否穩固連接。重新啟動您可能正在使用的任何路由器、
數據機或其他網路裝置。</translation>
@@ -730,21 +766,19 @@
<translation id="6446608382365791566">新增詳細資訊</translation>
<translation id="6447842834002726250">Cookie</translation>
<translation id="6451458296329894277">確認重新提交表單</translation>
-<translation id="6456339708790392414">你的付款</translation>
<translation id="647261751007945333">裝置政策</translation>
<translation id="6477321094435799029">Chrome 在這個網頁上偵測到異常代碼。為了保護你的個人資訊 (包括密碼、電話號碼或信用卡資料),Chrome 已封鎖這個網頁。</translation>
<translation id="6489534406876378309">開始上傳當機報告</translation>
<translation id="6507833130742554667">接受信用卡和簽帳金融卡。</translation>
<translation id="6508722015517270189">重新啟動 Chrome</translation>
-<translation id="6521373090216409766">你要重新載入這個網站嗎?</translation>
<translation id="6529602333819889595">重做刪除(&amp;R)</translation>
<translation id="6534179046333460208">實體化網路建議</translation>
<translation id="6550675742724504774">選項</translation>
-<translation id="6556239504065605927">安全連線</translation>
<translation id="6556915248009097796">到期日:<ph name="EXPIRATION_DATE_ABBR" />,上次使用日期:<ph name="LAST_USED_DATE_NO_DETAIL" /></translation>
<translation id="6563469144985748109">你的管理員尚未核准這個網站</translation>
<translation id="6569060085658103619">目前顯示的是擴充功能頁面</translation>
<translation id="6596325263575161958">加密選項</translation>
+<translation id="6604181099783169992">動作或光源感應器</translation>
<translation id="6624427990725312378">聯絡資訊</translation>
<translation id="6626291197371920147">新增有效的信用卡號碼</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> 搜尋</translation>
@@ -816,6 +850,7 @@
<translation id="7275334191706090484">受管理書籤</translation>
<translation id="7298195798382681320">建議採用</translation>
<translation id="7309308571273880165">當機報告擷取時間:<ph name="CRASH_TIME" /> (使用者要求上傳,但尚未上傳)</translation>
+<translation id="7320336641823683070">連線說明</translation>
<translation id="7334320624316649418">重做重新排序(&amp;R)</translation>
<translation id="733923710415886693">伺服器憑證未依憑證透明化政策公開。</translation>
<translation id="7353601530677266744">命令列</translation>
@@ -898,8 +933,9 @@
<translation id="7815407501681723534">找到 <ph name="NUMBER_OF_RESULTS" /> 個與「<ph name="SEARCH_STRING" />」相符的<ph name="SEARCH_RESULTS" /></translation>
<translation id="7818867226424560206">政策管理</translation>
<translation id="782886543891417279">目前使用的 Wi-Fi 網路 (<ph name="WIFI_NAME" />) 可能會要求您造訪登入網頁。</translation>
-<translation id="785549533363645510">不過,這並不意味著您可以完全隱形。使用無痕模式時,您的雇主和網際網路服務供應商仍然可以追蹤您的瀏覽紀錄,您所造訪的網站也可能會記錄您的瀏覽行為。</translation>
+<translation id="785549533363645510">不過,這並不意味著您可以完全隱形。使用無痕模式時,您的雇主和網際網路服務供應商仍然可以追蹤您的瀏覽記錄,您所造訪的網站也可能會記錄您的瀏覽行為。</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
+<translation id="7862185352068345852">要離開網站嗎?</translation>
<translation id="7878176543348854470">接受簽帳金融卡和預付卡。</translation>
<translation id="7878562273885520351">你的密碼可能已經外洩</translation>
<translation id="7887683347370398519">請檢查您的 CVC,然後再試一次</translation>
@@ -922,6 +958,7 @@
<translation id="8041940743680923270">使用全域預設值 (要求確認)</translation>
<translation id="8042918947222776840">選擇取件方式</translation>
<translation id="8057711352706143257">「<ph name="SOFTWARE_NAME" />」的設定不正確。通常解除安裝「<ph name="SOFTWARE_NAME" />」即可修正這個問題。<ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8079031581361219619">要重新載入網站嗎?</translation>
<translation id="8088680233425245692">無法查看文章。</translation>
<translation id="8091372947890762290">尚未在伺服器上啟動</translation>
<translation id="8094917007353911263">目前使用的網路可能會要求您造訪 <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />。</translation>
@@ -937,6 +974,7 @@
<translation id="8201077131113104583">擴充功能 (ID:「<ph name="EXTENSION_ID" />」) 的更新網址無效。</translation>
<translation id="8202097416529803614">訂單摘要</translation>
<translation id="8205463626947051446">網站經常顯示侵入式廣告</translation>
+<translation id="8211406090763984747">已建立安全連線</translation>
<translation id="8218327578424803826">指派的位置:</translation>
<translation id="8225771182978767009">設定這部電腦的使用者選擇封鎖這個網站。</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />、<ph name="TYPE_2" /></translation>
@@ -948,6 +986,7 @@
<translation id="825929999321470778">顯示所有已儲存的密碼</translation>
<translation id="8261506727792406068">刪除</translation>
<translation id="8267698848189296333">正在以 <ph name="USERNAME" /> 的身分登入</translation>
+<translation id="8286036467436129157">登入</translation>
<translation id="8288807391153049143">顯示憑證</translation>
<translation id="8289355894181816810">如果你不確定這代表什麼意思,請與網路管理員聯絡。</translation>
<translation id="8293206222192510085">新增書籤</translation>
@@ -998,6 +1037,7 @@
<translation id="874846938927089722">接受的信用卡和預付卡</translation>
<translation id="8759274551635299824">這張信用卡已過期</translation>
<translation id="8761567432415473239">Google 安全瀏覽最近在「<ph name="SITE" />」<ph name="BEGIN_LINK" />發現了有害程式<ph name="END_LINK" />。</translation>
+<translation id="8763927697961133303">USB 裝置</translation>
<translation id="8790007591277257123">重做刪除(&amp;R)</translation>
<translation id="8800988563907321413">這裡會顯示系統建議你瀏覽的鄰近網頁</translation>
<translation id="8820817407110198400">書籤</translation>
diff --git a/chromium/components/subresource_filter/content/browser/async_document_subresource_filter.cc b/chromium/components/subresource_filter/content/browser/async_document_subresource_filter.cc
index 94dd8144395..9dd0c27595f 100644
--- a/chromium/components/subresource_filter/content/browser/async_document_subresource_filter.cc
+++ b/chromium/components/subresource_filter/content/browser/async_document_subresource_filter.cc
@@ -111,11 +111,11 @@ AsyncDocumentSubresourceFilter::AsyncDocumentSubresourceFilter(
// below task is posted.
base::PostTaskAndReplyWithResult(
task_runner_, FROM_HERE,
- base::Bind(&Core::Initialize, base::Unretained(core_.get()),
- base::Passed(&params), ruleset_handle->ruleset_.get()),
- base::Bind(&AsyncDocumentSubresourceFilter::OnActivateStateCalculated,
- weak_ptr_factory_.GetWeakPtr(),
- std::move(activation_state_callback)));
+ base::BindOnce(&Core::Initialize, base::Unretained(core_.get()),
+ std::move(params), ruleset_handle->ruleset_.get()),
+ base::BindOnce(&AsyncDocumentSubresourceFilter::OnActivateStateCalculated,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::move(activation_state_callback)));
}
AsyncDocumentSubresourceFilter::~AsyncDocumentSubresourceFilter() {
diff --git a/chromium/components/subresource_filter/content/browser/content_ruleset_service.cc b/chromium/components/subresource_filter/content/browser/content_ruleset_service.cc
index f9d1c334244..bad103daf2f 100644
--- a/chromium/components/subresource_filter/content/browser/content_ruleset_service.cc
+++ b/chromium/components/subresource_filter/content/browser/content_ruleset_service.cc
@@ -41,7 +41,7 @@ void CloseFileOnFileThread(base::File* file) {
return;
base::PostTaskWithTraits(FROM_HERE,
{base::TaskPriority::BACKGROUND, base::MayBlock()},
- base::Bind(&CloseFile, base::Passed(file)));
+ base::BindOnce(&CloseFile, std::move(*file)));
}
} // namespace
@@ -105,6 +105,11 @@ void ContentRulesetService::IndexAndStoreAndPublishRulesetIfNeeded(
unindexed_ruleset_info);
}
+void ContentRulesetService::SetIsAfterStartupForTesting() {
+ DCHECK(ruleset_service_);
+ ruleset_service_->set_is_after_startup_for_testing();
+}
+
void ContentRulesetService::Observe(
int type,
const content::NotificationSource& source,
diff --git a/chromium/components/subresource_filter/content/browser/content_ruleset_service.h b/chromium/components/subresource_filter/content/browser/content_ruleset_service.h
index 97c049e14a6..e3cc43f18d3 100644
--- a/chromium/components/subresource_filter/content/browser/content_ruleset_service.h
+++ b/chromium/components/subresource_filter/content/browser/content_ruleset_service.h
@@ -77,6 +77,8 @@ class ContentRulesetService : public RulesetServiceDelegate,
return ruleset_dealer_.get();
}
+ void SetIsAfterStartupForTesting();
+
private:
// content::NotificationObserver:
void Observe(int type,
diff --git a/chromium/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc b/chromium/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc
index ad3d4fae237..9a84f384585 100644
--- a/chromium/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc
+++ b/chromium/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
#include "base/time/time.h"
#include "components/subresource_filter/content/browser/page_load_statistics.h"
@@ -126,6 +127,11 @@ void ContentSubresourceFilterDriverFactory::NotifyPageActivationComputed(
}
void ContentSubresourceFilterDriverFactory::OnFirstSubresourceLoadDisallowed() {
+ if (matched_configuration_.activation_conditions.forced_activation) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "SubresourceFilter.PageLoad.ForcedActivation.DisallowedLoad", true);
+ return;
+ }
if (activation_options().should_suppress_notifications)
return;
// This shouldn't happen normally, but in the rare case that an IPC from a
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 bf16caff114..1f5ad609e45 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
@@ -56,6 +56,7 @@ void ContentSubresourceFilterThrottleManager::OnSubresourceFilterGoingAway() {
void ContentSubresourceFilterThrottleManager::RenderFrameDeleted(
content::RenderFrameHost* frame_host) {
activated_frame_hosts_.erase(frame_host);
+ ad_frames_.erase(frame_host);
DestroyRulesetHandleIfNoLongerUsed();
}
@@ -73,7 +74,7 @@ void ContentSubresourceFilterThrottleManager::ReadyToCommitNavigation(
// TODO(crbug.com/736249): Remove CHECKs in this file when the root cause of
// the crash is found.
- ActivationStateComputingNavigationThrottle* throttle = it->second;
+ ActivationStateComputingNavigationThrottle* throttle = it->second.throttle;
CHECK_EQ(navigation_handle, throttle->navigation_handle());
// Main frame throttles with disabled page-level activation will not have
@@ -93,10 +94,21 @@ void ContentSubresourceFilterThrottleManager::ReadyToCommitNavigation(
"activation_state", filter->activation_state().ToTracedValue());
throttle->WillSendActivationToRenderer();
+
+ // is_ad_subframe is guaranteed to have the correct value at this point since
+ // the ruleset checking and its notification is done before the navigation is
+ // resumed.
+ bool is_ad_subframe = it->second.is_ad_subframe;
+ DCHECK(!is_ad_subframe || level == ActivationLevel::DRYRUN);
+ DCHECK(!is_ad_subframe || !navigation_handle->IsInMainFrame());
+
content::RenderFrameHost* frame_host =
navigation_handle->GetRenderFrameHost();
+ if (is_ad_subframe)
+ ad_frames_.insert(frame_host);
+
frame_host->Send(new SubresourceFilterMsg_ActivateForNextCommittedLoad(
- frame_host->GetRoutingID(), filter->activation_state()));
+ frame_host->GetRoutingID(), filter->activation_state(), is_ad_subframe));
}
void ContentSubresourceFilterThrottleManager::DidFinishNavigation(
@@ -109,12 +121,14 @@ void ContentSubresourceFilterThrottleManager::DidFinishNavigation(
return;
}
- auto throttle = ongoing_activation_throttles_.find(navigation_handle);
+ auto throttle_it = ongoing_activation_throttles_.find(navigation_handle);
std::unique_ptr<AsyncDocumentSubresourceFilter> filter;
- if (throttle != ongoing_activation_throttles_.end()) {
- CHECK_EQ(navigation_handle, throttle->second->navigation_handle());
- filter = throttle->second->ReleaseFilter();
- ongoing_activation_throttles_.erase(throttle);
+ if (throttle_it != ongoing_activation_throttles_.end()) {
+ ActivationStateComputingNavigationThrottle* throttle =
+ throttle_it->second.throttle;
+ CHECK_EQ(navigation_handle, throttle->navigation_handle());
+ filter = throttle->ReleaseFilter();
+ ongoing_activation_throttles_.erase(throttle_it);
}
content::RenderFrameHost* frame_host =
@@ -196,8 +210,31 @@ void ContentSubresourceFilterThrottleManager::OnPageActivationComputed(
auto it = ongoing_activation_throttles_.find(navigation_handle);
if (it != ongoing_activation_throttles_.end()) {
- it->second->NotifyPageActivationWithRuleset(EnsureRulesetHandle(),
- activation_state);
+ it->second.throttle->NotifyPageActivationWithRuleset(EnsureRulesetHandle(),
+ activation_state);
+ }
+}
+
+void ContentSubresourceFilterThrottleManager::OnSubframeNavigationEvaluated(
+ content::NavigationHandle* navigation_handle,
+ LoadPolicy load_policy) {
+ DCHECK(!navigation_handle->IsInMainFrame());
+ auto it = ongoing_activation_throttles_.find(navigation_handle);
+ if (it == ongoing_activation_throttles_.end())
+ return;
+
+ // Note that is_ad_subframe is only relevant for
+ // LoadPolicy:WOULD_DISALLOW(dryrun mode), although also setting it for
+ // DISALLOW for completeness.
+ it->second.is_ad_subframe = load_policy != LoadPolicy::ALLOW;
+
+ // If this frame was not identified as an ad via ruleset matching, tag it
+ // based on whether its parent frame is an ad or not.
+ if (!it->second.is_ad_subframe) {
+ content::RenderFrameHost* parent_frame =
+ navigation_handle->GetParentFrame();
+ if (parent_frame && base::ContainsKey(ad_frames_, parent_frame))
+ it->second.is_ad_subframe = true;
}
}
@@ -215,7 +252,7 @@ void ContentSubresourceFilterThrottleManager::MaybeAppendNavigationThrottles(
DCHECK(!base::ContainsKey(ongoing_activation_throttles_, navigation_handle));
if (auto activation_throttle =
MaybeCreateActivationStateComputingThrottle(navigation_handle)) {
- ongoing_activation_throttles_[navigation_handle] =
+ ongoing_activation_throttles_[navigation_handle].throttle =
activation_throttle.get();
activation_throttle->set_destruction_closure(base::BindOnce(
&ContentSubresourceFilterThrottleManager::OnActivationThrottleDestroyed,
@@ -224,6 +261,11 @@ void ContentSubresourceFilterThrottleManager::MaybeAppendNavigationThrottles(
}
}
+bool ContentSubresourceFilterThrottleManager::IsFrameTaggedAsAdForTesting(
+ content::RenderFrameHost* frame_host) {
+ return base::ContainsKey(ad_frames_, frame_host);
+}
+
std::unique_ptr<SubframeNavigationFilteringThrottle>
ContentSubresourceFilterThrottleManager::
MaybeCreateSubframeNavigationFilteringThrottle(
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 1844dc37d5a..fdfec2fb79f 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
@@ -5,13 +5,15 @@
#ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_CONTENT_SUBRESOURCE_FILTER_THROTTLE_MANAGER_H_
#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_CONTENT_SUBRESOURCE_FILTER_THROTTLE_MANAGER_H_
+#include <map>
#include <memory>
-#include <unordered_map>
+#include <set>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
+#include "base/stl_util.h"
#include "components/subresource_filter/content/browser/subresource_filter_observer.h"
#include "components/subresource_filter/content/browser/verified_ruleset_dealer.h"
#include "components/subresource_filter/core/common/activation_decision.h"
@@ -84,6 +86,8 @@ class ContentSubresourceFilterThrottleManager
return ruleset_handle_.get();
}
+ bool IsFrameTaggedAsAdForTesting(content::RenderFrameHost* frame_host);
+
protected:
// content::WebContentsObserver:
void RenderFrameDeleted(content::RenderFrameHost* frame_host) override;
@@ -102,6 +106,9 @@ class ContentSubresourceFilterThrottleManager
content::NavigationHandle* navigation_handle,
ActivationDecision activation_decision,
const ActivationState& activation_state) override;
+ void OnSubframeNavigationEvaluated(
+ content::NavigationHandle* navigation_handle,
+ LoadPolicy load_policy) override;
private:
std::unique_ptr<SubframeNavigationFilteringThrottle>
@@ -140,17 +147,27 @@ class ContentSubresourceFilterThrottleManager
// For each RenderFrameHost where the last committed load has subresource
// filtering activated, owns the corresponding AsyncDocumentSubresourceFilter.
// It is possible for a frame to have a null filter.
- std::unordered_map<content::RenderFrameHost*,
- std::unique_ptr<AsyncDocumentSubresourceFilter>>
+ std::map<content::RenderFrameHost*,
+ std::unique_ptr<AsyncDocumentSubresourceFilter>>
activated_frame_hosts_;
// For each ongoing navigation that requires activation state computation,
// keeps track of the throttle that is carrying out that computation, so that
// the result can be retrieved when the navigation is ready to commit.
- std::unordered_map<content::NavigationHandle*,
- ActivationStateComputingNavigationThrottle*>
+ // is_ad_subframe is set if SubframeNavigationFilteringThrottle finds that the
+ // subframe URL matches the ruleset.
+ struct OngoingThrottleInfo {
+ ActivationStateComputingNavigationThrottle* throttle = nullptr;
+ bool is_ad_subframe = false;
+ };
+
+ std::map<content::NavigationHandle*, OngoingThrottleInfo>
ongoing_activation_throttles_;
+ // Set of frames that have been identified as ads, either through matching the
+ // ruleset or if their parent frame was an ad frame.
+ std::set<content::RenderFrameHost*> ad_frames_;
+
ScopedObserver<SubresourceFilterObserverManager, SubresourceFilterObserver>
scoped_observer_;
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 63971e654c7..f8800bf6577 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
@@ -27,7 +27,6 @@
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_renderer_host.h"
@@ -157,7 +156,8 @@ class ContentSubresourceFilterThrottleManagerTest
}
void ExpectActivationSignalForFrame(content::RenderFrameHost* rfh,
- bool expect_activation) {
+ bool expect_activation,
+ bool expect_is_ad_subframe = false) {
content::MockRenderProcessHost* render_process_host =
static_cast<content::MockRenderProcessHost*>(rfh->GetProcess());
const IPC::Message* message =
@@ -165,10 +165,12 @@ class ContentSubresourceFilterThrottleManagerTest
SubresourceFilterMsg_ActivateForNextCommittedLoad::ID);
ASSERT_EQ(expect_activation, !!message);
if (expect_activation) {
- std::tuple<ActivationState> args;
+ std::tuple<ActivationState, bool> args;
SubresourceFilterMsg_ActivateForNextCommittedLoad::Read(message, &args);
ActivationLevel level = std::get<0>(args).activation_level;
EXPECT_NE(ActivationLevel::DISABLED, level);
+ bool is_ad_subframe = std::get<1>(args);
+ EXPECT_EQ(expect_is_ad_subframe, is_ad_subframe);
}
render_process_host->sink().ClearMessages();
}
@@ -184,12 +186,14 @@ class ContentSubresourceFilterThrottleManagerTest
url, render_frame_host);
}
- void CreateSubframeWithTestNavigation(const GURL& url,
- content::RenderFrameHost* parent) {
+ content::RenderFrameHost* CreateSubframeWithTestNavigation(
+ const GURL& url,
+ content::RenderFrameHost* parent) {
content::RenderFrameHost* subframe =
content::RenderFrameHostTester::For(parent)->AppendChild(
base::StringPrintf("subframe-%s", url.spec().c_str()));
CreateTestNavigation(url, subframe);
+ return subframe;
}
void SimulateStartAndExpectResult(
@@ -346,7 +350,8 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
content::RenderFrameHost* child =
SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
// But it should still be activated.
- ExpectActivationSignalForFrame(child, true /* expect_activation */);
+ ExpectActivationSignalForFrame(child, true /* expect_activation */,
+ true /* is_ad_subframe */);
EXPECT_EQ(0, disallowed_notification_count());
}
@@ -363,9 +368,7 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
GURL("https://www.example.com/before-redirect.html"), main_rfh());
SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
content::NavigationThrottle::ThrottleAction expected_action =
- content::IsBrowserSideNavigationEnabled()
- ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE
- : content::NavigationThrottle::CANCEL;
+ content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;
SimulateRedirectAndExpectResult(
GURL("https://www.example.com/disallowed.html"), expected_action);
@@ -715,6 +718,105 @@ TEST_F(ContentSubresourceFilterThrottleManagerTest, LogActivation) {
base::ThreadTicks::IsSupported() ? 2 : 0);
}
+// Check to make sure we don't send an IPC with the ad tag bit for ad frames
+// that are successfully filtered.
+TEST_P(ContentSubresourceFilterThrottleManagerTest,
+ ActivateMainFrameAndFilterSubframeNavigationTaggedAsAd) {
+ // Commit a navigation that triggers page level activation.
+ NavigateAndCommitMainFrame(GURL(kTestURLWithActivation));
+ ExpectActivationSignalForFrame(main_rfh(), true /* expect_activation */,
+ false /* is_ad_subframe */);
+
+ // A disallowed subframe navigation should be successfully filtered.
+ content::RenderFrameHost* subframe = CreateSubframeWithTestNavigation(
+ GURL("https://www.example.com/disallowed.html"), main_rfh());
+
+ SimulateStartAndExpectResult(
+ content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+
+ EXPECT_EQ(1, disallowed_notification_count());
+
+ // Since the IPC is not actually sent, is_ad_subframe is not really checked
+ // but adding it here since we do tag even if its not a dryrun scenario.
+ ExpectActivationSignalForFrame(subframe, false /* expect_activation */,
+ true /* is_ad_subframe */);
+}
+
+TEST_P(ContentSubresourceFilterThrottleManagerTest,
+ DryRun_FrameTaggingAsAdPropagatesToChildFrame) {
+ NavigateAndCommitMainFrame(GURL(kTestURLWithDryRun));
+ ExpectActivationSignalForFrame(main_rfh(), true /* expect_activation */);
+
+ // A disallowed subframe navigation should not be filtered in dry-run mode.
+ CreateSubframeWithTestNavigation(
+ GURL("https://www.example.com/disallowed.html"), main_rfh());
+ SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ content::RenderFrameHost* child =
+ SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_TRUE(child);
+
+ // But it should still be activated.
+ ExpectActivationSignalForFrame(child, true /* expect_activation */,
+ true /* is_ad_subframe */);
+ EXPECT_TRUE(throttle_manager()->IsFrameTaggedAsAdForTesting(child));
+
+ // Create a subframe which is allowed as per ruleset but should still be
+ // tagged as ad because of its parent.
+ CreateSubframeWithTestNavigation(
+ GURL("https://www.example.com/allowed_by_ruleset.html"), child);
+ SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ content::RenderFrameHost* grandchild =
+ SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_TRUE(grandchild);
+ ExpectActivationSignalForFrame(grandchild, true /* expect_activation */,
+ true /* is_ad_subframe */);
+ EXPECT_TRUE(throttle_manager()->IsFrameTaggedAsAdForTesting(grandchild));
+
+ // Verify that a 2nd level nested frame should also be tagged.
+ CreateSubframeWithTestNavigation(
+ GURL("https://www.example.com/great_grandchild_allowed_by_ruleset.html"),
+ child);
+ SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ content::RenderFrameHost* greatGrandchild =
+ SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_TRUE(greatGrandchild);
+ ExpectActivationSignalForFrame(greatGrandchild, true /* expect_activation */,
+ true /* is_ad_subframe */);
+ EXPECT_TRUE(throttle_manager()->IsFrameTaggedAsAdForTesting(greatGrandchild));
+
+ EXPECT_EQ(0, disallowed_notification_count());
+}
+
+TEST_P(ContentSubresourceFilterThrottleManagerTest,
+ DryRun_AllowedsFrameNotTaggedAsAd) {
+ NavigateAndCommitMainFrame(GURL(kTestURLWithDryRun));
+ ExpectActivationSignalForFrame(main_rfh(), true /* expect_activation */);
+
+ CreateSubframeWithTestNavigation(
+ GURL("https://www.example.com/allowed_by_ruleset.html"), main_rfh());
+ SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ content::RenderFrameHost* child =
+ SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_TRUE(child);
+ ExpectActivationSignalForFrame(child, true /* expect_activation */,
+ false /* is_ad_subframe */);
+ EXPECT_FALSE(throttle_manager()->IsFrameTaggedAsAdForTesting(child));
+
+ // Create a subframe which is allowed as per ruleset and should not be tagged
+ // as ad because its parent is not tagged as well.
+ CreateSubframeWithTestNavigation(
+ GURL("https://www.example.com/also_allowed_by_ruleset.html"), child);
+ SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ content::RenderFrameHost* grandchild =
+ SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_TRUE(grandchild);
+ ExpectActivationSignalForFrame(grandchild, true /* expect_activation */,
+ false /* is_ad_subframe */);
+ EXPECT_FALSE(throttle_manager()->IsFrameTaggedAsAdForTesting(grandchild));
+
+ EXPECT_EQ(0, disallowed_notification_count());
+}
+
// TODO(csharrison): Make sure the following conditions are exercised in tests:
//
// - Synchronous navigations to about:blank. These hit issues with the
diff --git a/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc b/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
index c436bf7a668..4ecca05468e 100644
--- a/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
+++ b/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
@@ -15,7 +15,6 @@
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/console_message_level.h"
namespace subresource_filter {
@@ -107,11 +106,7 @@ void SubframeNavigationFilteringThrottle::OnCalculatedLoadPolicy(
// Other load policies will be reported in WillProcessResponse.
NotifyLoadPolicy();
- const bool block_and_collapse_is_supported =
- content::IsBrowserSideNavigationEnabled() ||
- stage == ThrottlingStage::WillStartRequest;
- CancelDeferredNavigation(
- block_and_collapse_is_supported ? BLOCK_REQUEST_AND_COLLAPSE : CANCEL);
+ CancelDeferredNavigation(BLOCK_REQUEST_AND_COLLAPSE);
} else {
Resume();
}
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 3f06669adc6..32b5677bf81 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
@@ -18,7 +18,6 @@
#include "components/subresource_filter/core/common/test_ruleset_creator.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents_observer.h"
-#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -125,7 +124,6 @@ class SubframeNavigationFilteringThrottleTest
}
void SimulateCommitErrorPage() {
- DCHECK(content::IsBrowserSideNavigationEnabled());
navigation_simulator_->CommitErrorPage();
}
@@ -158,9 +156,7 @@ TEST_F(SubframeNavigationFilteringThrottleTest, FilterOnRedirect) {
SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
content::NavigationThrottle::ThrottleAction expected_result =
- content::IsBrowserSideNavigationEnabled()
- ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE
- : content::NavigationThrottle::CANCEL;
+ content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;
SimulateRedirectAndExpectResult(GURL("https://example.test/disallowed.html"),
expected_result);
}
@@ -174,9 +170,7 @@ TEST_F(SubframeNavigationFilteringThrottleTest, FilterOnSecondRedirect) {
SimulateRedirectAndExpectResult(GURL("https://example.test/allowed2.html"),
content::NavigationThrottle::PROCEED);
content::NavigationThrottle::ThrottleAction expected_result =
- content::IsBrowserSideNavigationEnabled()
- ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE
- : content::NavigationThrottle::CANCEL;
+ content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;
SimulateRedirectAndExpectResult(GURL("https://example.test/disallowed.html"),
expected_result);
}
@@ -215,17 +209,13 @@ TEST_F(SubframeNavigationFilteringThrottleTest, DelayMetrics) {
InitializeDocumentSubresourceFilter(GURL("https://example.test"));
CreateTestSubframeAndInitNavigation(GURL("https://example.test/allowed.html"),
main_rfh());
- if (content::IsBrowserSideNavigationEnabled())
- navigation_simulator()->SetTransition(ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
+ navigation_simulator()->SetTransition(ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
content::NavigationThrottle::ThrottleAction expected_result =
- content::IsBrowserSideNavigationEnabled()
- ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE
- : content::NavigationThrottle::CANCEL;
+ content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;
SimulateRedirectAndExpectResult(GURL("https://example.test/disallowed.html"),
expected_result);
- if (content::IsBrowserSideNavigationEnabled())
- SimulateCommitErrorPage();
+ SimulateCommitErrorPage();
const char kFilterDelayDisallowed[] =
"SubresourceFilter.DocumentLoad.SubframeFilteringDelay.Disallowed";
diff --git a/chromium/components/subresource_filter/content/browser/verified_ruleset_dealer.cc b/chromium/components/subresource_filter/content/browser/verified_ruleset_dealer.cc
index 2ec1c37a5bb..33ce31ca38b 100644
--- a/chromium/components/subresource_filter/content/browser/verified_ruleset_dealer.cc
+++ b/chromium/components/subresource_filter/content/browser/verified_ruleset_dealer.cc
@@ -4,6 +4,8 @@
#include "components/subresource_filter/content/browser/verified_ruleset_dealer.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file.h"
@@ -79,8 +81,8 @@ void VerifiedRulesetDealer::Handle::SetRulesetFile(base::File file) {
DCHECK(sequence_checker_.CalledOnValidSequence());
task_runner_->PostTask(
FROM_HERE,
- base::Bind(&VerifiedRulesetDealer::SetRulesetFile,
- base::Unretained(dealer_.get()), base::Passed(&file)));
+ base::BindOnce(&VerifiedRulesetDealer::SetRulesetFile,
+ base::Unretained(dealer_.get()), std::move(file)));
}
// VerifiedRuleset and its Handle. ---------------------------------------------
diff --git a/chromium/components/subresource_filter/content/common/subresource_filter_messages.h b/chromium/components/subresource_filter/content/common/subresource_filter_messages.h
index 5c6ebb7c0c0..610310c05e8 100644
--- a/chromium/components/subresource_filter/content/common/subresource_filter_messages.h
+++ b/chromium/components/subresource_filter/content/common/subresource_filter_messages.h
@@ -58,8 +58,9 @@ IPC_MESSAGE_CONTROL1(SubresourceFilterMsg_SetRulesetForProcess,
// mojom::FrameNavigationControl::CommitNavigation.
//
// If no message arrives, the default behavior is ActivationLevel::DISABLED.
-IPC_MESSAGE_ROUTED1(SubresourceFilterMsg_ActivateForNextCommittedLoad,
- subresource_filter::ActivationState /* activation_state */)
+IPC_MESSAGE_ROUTED2(SubresourceFilterMsg_ActivateForNextCommittedLoad,
+ subresource_filter::ActivationState /* activation_state */,
+ bool /* is_ad_subframe */)
// ----------------------------------------------------------------------------
// Messages sent from the renderer to the browser.
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 98d900f18f1..7e5964c2734 100644
--- a/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.cc
+++ b/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.cc
@@ -37,7 +37,8 @@ SubresourceFilterAgent::SubresourceFilterAgent(
UnverifiedRulesetDealer* ruleset_dealer)
: content::RenderFrameObserver(render_frame),
content::RenderFrameObserverTracker<SubresourceFilterAgent>(render_frame),
- ruleset_dealer_(ruleset_dealer) {
+ ruleset_dealer_(ruleset_dealer),
+ is_ad_subframe_for_next_commit_(false) {
DCHECK(ruleset_dealer);
}
@@ -57,6 +58,11 @@ void SubresourceFilterAgent::SetSubresourceFilterForCommittedLoad(
web_frame->GetDocumentLoader()->SetSubresourceFilter(filter.release());
}
+void SubresourceFilterAgent::SetIsAdSubframeForDocument(bool is_ad_subframe) {
+ blink::WebLocalFrame* web_frame = render_frame()->GetWebFrame();
+ web_frame->GetDocumentLoader()->SetIsAdSubframe(is_ad_subframe);
+}
+
void SubresourceFilterAgent::
SignalFirstSubresourceDisallowedForCommittedLoad() {
render_frame()->Send(new SubresourceFilterHostMsg_DidDisallowFirstSubresource(
@@ -84,8 +90,10 @@ ActivationState SubresourceFilterAgent::GetParentActivationState(
}
void SubresourceFilterAgent::OnActivateForNextCommittedLoad(
- const ActivationState& activation_state) {
+ const ActivationState& activation_state,
+ bool is_ad_subframe) {
activation_state_for_next_commit_ = activation_state;
+ is_ad_subframe_for_next_commit_ = is_ad_subframe;
}
void SubresourceFilterAgent::RecordHistogramsOnLoadCommitted(
@@ -146,9 +154,10 @@ void SubresourceFilterAgent::RecordHistogramsOnLoadFinished() {
SendDocumentLoadStatistics(statistics);
}
-void SubresourceFilterAgent::ResetActivatonStateForNextCommit() {
+void SubresourceFilterAgent::ResetInfoForNextCommit() {
activation_state_for_next_commit_ =
ActivationState(ActivationLevel::DISABLED);
+ is_ad_subframe_for_next_commit_ = false;
}
void SubresourceFilterAgent::OnDestruct() {
@@ -172,8 +181,9 @@ void SubresourceFilterAgent::DidCommitProvisionalLoad(
const ActivationState activation_state =
use_parent_activation ? GetParentActivationState(render_frame())
: activation_state_for_next_commit_;
+ bool is_ad_subframe = is_ad_subframe_for_next_commit_;
- ResetActivatonStateForNextCommit();
+ ResetInfoForNextCommit();
// Do not pollute the histograms for empty main frame documents.
if (IsMainFrame() && !url.SchemeIsHTTPOrHTTPS() && !url.SchemeIsFile())
@@ -201,12 +211,14 @@ void SubresourceFilterAgent::DidCommitProvisionalLoad(
filter_for_last_committed_load_ = filter->AsWeakPtr();
SetSubresourceFilterForCommittedLoad(std::move(filter));
+ if (is_ad_subframe)
+ SetIsAdSubframeForDocument(true);
}
void SubresourceFilterAgent::DidFailProvisionalLoad(
const blink::WebURLError& error) {
// TODO(engedy): Add a test with `frame-ancestor` violation to exercise this.
- ResetActivatonStateForNextCommit();
+ ResetInfoForNextCommit();
}
void SubresourceFilterAgent::DidFinishLoad() {
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 73d7c1aa2bb..def12acfaee 100644
--- a/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.h
+++ b/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.h
@@ -52,6 +52,9 @@ class SubresourceFilterAgent
virtual void SetSubresourceFilterForCommittedLoad(
std::unique_ptr<blink::WebDocumentSubresourceFilter> filter);
+ // Sets in the underlying document, whether this is identified as an ad.
+ virtual void SetIsAdSubframeForDocument(bool is_ad_subframe);
+
// Informs the browser that the first subresource load has been disallowed for
// the most recently committed load. Not called if all resources are allowed.
virtual void SignalFirstSubresourceDisallowedForCommittedLoad();
@@ -66,10 +69,11 @@ class SubresourceFilterAgent
static ActivationState GetParentActivationState(
content::RenderFrame* render_frame);
- void OnActivateForNextCommittedLoad(const ActivationState& activation_state);
+ void OnActivateForNextCommittedLoad(const ActivationState& activation_state,
+ bool is_ad_subframe);
void RecordHistogramsOnLoadCommitted(const ActivationState& activation_state);
void RecordHistogramsOnLoadFinished();
- void ResetActivatonStateForNextCommit();
+ void ResetInfoForNextCommit();
// content::RenderFrameObserver:
void OnDestruct() override;
@@ -85,6 +89,13 @@ class SubresourceFilterAgent
ActivationState activation_state_for_next_commit_;
+ // This is received along with activation state in the
+ // SubresourceFilterMsg_ActivateForNextCommittedLoad IPC message. Specifies
+ // whether this is a subframe which is identified as an ad. Note that this
+ // will only be set in dry run mode because in blocking mode the frame would
+ // have been blocked.
+ bool is_ad_subframe_for_next_commit_;
+
base::WeakPtr<WebDocumentSubresourceFilterImpl>
filter_for_last_committed_load_;
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 92edf14e67e..84270e6b2c6 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
@@ -59,6 +59,12 @@ class SubresourceFilterAgentUnderTest : public SubresourceFilterAgent {
OnSetSubresourceFilterForCommittedLoadCalled();
}
+ void SetIsAdSubframeForDocument(bool is_ad_subframe) override {
+ is_ad_subframe_ = is_ad_subframe;
+ }
+
+ bool GetIsAdSubframe() { return is_ad_subframe_; }
+
blink::WebDocumentSubresourceFilter* filter() {
return last_injected_filter_.get();
}
@@ -68,6 +74,7 @@ class SubresourceFilterAgentUnderTest : public SubresourceFilterAgent {
}
private:
+ bool is_ad_subframe_ = false;
std::unique_ptr<blink::WebDocumentSubresourceFilter> last_injected_filter_;
DISALLOW_COPY_AND_ASSIGN(SubresourceFilterAgentUnderTest);
@@ -135,10 +142,12 @@ class SubresourceFilterAgentTest : public ::testing::Test {
// No DidFinishLoad is called in this case.
}
- void StartLoadAndSetActivationState(ActivationState state) {
+ void StartLoadAndSetActivationState(ActivationState state,
+ bool is_ad_subframe = false) {
agent_as_rfo()->DidStartProvisionalLoad(nullptr);
EXPECT_TRUE(agent_as_rfo()->OnMessageReceived(
- SubresourceFilterMsg_ActivateForNextCommittedLoad(0, state)));
+ SubresourceFilterMsg_ActivateForNextCommittedLoad(0, state,
+ is_ad_subframe)));
agent_as_rfo()->DidCommitProvisionalLoad(
true /* is_new_navigation */, false /* is_same_document_navigation */);
}
@@ -419,7 +428,8 @@ TEST_F(SubresourceFilterAgentTest,
ActivationState state(ActivationLevel::ENABLED);
state.measure_performance = true;
EXPECT_TRUE(agent_as_rfo()->OnMessageReceived(
- SubresourceFilterMsg_ActivateForNextCommittedLoad(0, state)));
+ SubresourceFilterMsg_ActivateForNextCommittedLoad(
+ 0, state, false /* is_ad_subframe */)));
agent_as_rfo()->DidFailProvisionalLoad(
blink::WebURLError(net::ERR_FAILED, blink::WebURL()));
agent_as_rfo()->DidStartProvisionalLoad(nullptr);
@@ -511,4 +521,16 @@ TEST_F(SubresourceFilterAgentTest,
filter->ReportDisallowedLoad();
}
+TEST_F(SubresourceFilterAgentTest, DryRun_DocumentIsAdSubframeTagging) {
+ base::HistogramTester histogram_tester;
+ ASSERT_NO_FATAL_FAILURE(
+ SetTestRulesetToDisallowURLsWithPathSuffix(kTestFirstURLPathSuffix));
+ ExpectSubresourceFilterGetsInjected();
+ StartLoadAndSetActivationState(ActivationState(ActivationLevel::DRYRUN),
+ true /* is_ad_subframe */);
+ ASSERT_TRUE(::testing::Mock::VerifyAndClearExpectations(agent()));
+
+ EXPECT_TRUE(agent()->GetIsAdSubframe());
+}
+
} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/core/browser/ruleset_service.cc b/chromium/components/subresource_filter/core/browser/ruleset_service.cc
index 896b289d7cb..f7b22ac1e19 100644
--- a/chromium/components/subresource_filter/core/browser/ruleset_service.cc
+++ b/chromium/components/subresource_filter/core/browser/ruleset_service.cc
@@ -215,10 +215,12 @@ decltype(&base::ReplaceFile) RulesetService::g_replace_file_func =
RulesetService::RulesetService(
PrefService* local_state,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner,
RulesetServiceDelegate* delegate,
const base::FilePath& indexed_ruleset_base_dir)
: local_state_(local_state),
- blocking_task_runner_(blocking_task_runner),
+ blocking_task_runner_(std::move(blocking_task_runner)),
+ background_task_runner_(std::move(background_task_runner)),
delegate_(delegate),
is_after_startup_(false),
indexed_ruleset_base_dir_(indexed_ruleset_base_dir) {
@@ -434,7 +436,7 @@ void RulesetService::InitializeAfterStartup() {
IndexedRulesetVersion most_recently_indexed_version;
most_recently_indexed_version.ReadFromPrefs(local_state_);
- blocking_task_runner_->PostTask(
+ background_task_runner_->PostTask(
FROM_HERE,
base::Bind(&IndexedRulesetLocator::DeleteObsoleteRulesets,
indexed_ruleset_base_dir_, most_recently_indexed_version));
@@ -452,7 +454,7 @@ void RulesetService::IndexAndStoreRuleset(
const WriteRulesetCallback& success_callback) {
DCHECK(!unindexed_ruleset_info.content_version.empty());
base::PostTaskAndReplyWithResult(
- blocking_task_runner_.get(), FROM_HERE,
+ background_task_runner_.get(), FROM_HERE,
base::Bind(&RulesetService::IndexAndWriteRuleset,
indexed_ruleset_base_dir_, unindexed_ruleset_info),
base::Bind(&RulesetService::OnWrittenRuleset, AsWeakPtr(),
diff --git a/chromium/components/subresource_filter/core/browser/ruleset_service.h b/chromium/components/subresource_filter/core/browser/ruleset_service.h
index ef84c0ca6e6..99becdd1e68 100644
--- a/chromium/components/subresource_filter/core/browser/ruleset_service.h
+++ b/chromium/components/subresource_filter/core/browser/ruleset_service.h
@@ -124,7 +124,7 @@ class IndexedRulesetLocator {
// versions, keeping only:
// -- the |most_recent_version|, if it is valid,
// -- versions of the current format that have a sentinel file present.
- // To be called on the |blocking_task_runner_|.
+ // To be called on the |background_task_runner_|.
static void DeleteObsoleteRulesets(
const base::FilePath& indexed_ruleset_base_dir,
const IndexedRulesetVersion& most_recent_version);
@@ -141,7 +141,13 @@ class IndexedRulesetLocator {
// version. The version information of the most recent successfully stored
// ruleset is written into |local_state|. The invariant is maintained that the
// version pointed to by preferences, if valid, will exist on disk at any point
-// in time. All file operations are posted to |blocking_task_runner|.
+// in time.
+//
+// Ruleset file opening is a critical for user experience operation. It is
+// posted to |blocking_task_runner|. Obsolete files deletion and rulesets
+// indexing are not critical for user experience. These tasks are posted to
+// |background_task_runner|. Since the two task runners are distinct you cannot
+// make guarantees about task ordering between them.
class RulesetService : public base::SupportsWeakPtr<RulesetService> {
public:
// Enumerates the possible outcomes of indexing a ruleset and writing it to
@@ -168,10 +174,12 @@ class RulesetService : public base::SupportsWeakPtr<RulesetService> {
// Creates a new instance that will immediately publish the most recently
// indexed version of the ruleset if one is available according to prefs.
// See class comments for details of arguments.
- RulesetService(PrefService* local_state,
- scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
- RulesetServiceDelegate* delegate,
- const base::FilePath& indexed_ruleset_base_dir);
+ RulesetService(
+ PrefService* local_state,
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+ RulesetServiceDelegate* delegate,
+ const base::FilePath& indexed_ruleset_base_dir);
virtual ~RulesetService();
// Indexes, stores, and publishes the given unindexed ruleset, unless its
@@ -187,6 +195,8 @@ class RulesetService : public base::SupportsWeakPtr<RulesetService> {
virtual void IndexAndStoreAndPublishRulesetIfNeeded(
const UnindexedRulesetInfo& unindexed_ruleset_info);
+ void set_is_after_startup_for_testing() { is_after_startup_ = true; }
+
private:
friend class SubresourceFilteringRulesetServiceTest;
FRIEND_TEST_ALL_PREFIXES(SubresourceFilteringRulesetServiceTest,
@@ -200,7 +210,7 @@ class RulesetService : public base::SupportsWeakPtr<RulesetService> {
// Reads the ruleset described in |unindexed_ruleset_info|, indexes it, and
// calls WriteRuleset() to persist the indexed ruleset. Returns the resulting
// indexed ruleset version, or an invalid version on error. To be called on
- // the |blocking_task_runner_|.
+ // the |background_task_runner|.
static IndexedRulesetVersion IndexAndWriteRuleset(
const base::FilePath& indexed_ruleset_base_dir,
const UnindexedRulesetInfo& unindexed_ruleset_info);
@@ -215,7 +225,7 @@ class RulesetService : public base::SupportsWeakPtr<RulesetService> {
// More specifically, it writes:
// -- the |indexed_ruleset_data| of the given |indexed_ruleset_size|,
// -- a copy of the LICENSE file at |license_path|, if exists.
- // Returns true on success. To be called on the |blocking_task_runner_|.
+ // Returns true on success. To be called on the |background_task_runner|.
// Attempts not to leave an incomplete copy in the target directory.
//
// Writing is factored out into this separate function so it can be
@@ -234,10 +244,10 @@ class RulesetService : public base::SupportsWeakPtr<RulesetService> {
// Performs indexing of the queued unindexed ruleset (if any) after start-up.
void InitializeAfterStartup();
- // Posts a task to the |blocking_task_runner_| to index and persist the given
- // unindexed ruleset. Then, on success, updates the most recently indexed
- // version in preferences and invokes |success_callback| on the calling
- // thread. There is no callback on failure.
+ // Posts a task to the |background_task_runner| to index and persist the
+ // given unindexed ruleset. Then, on success, updates the most recently
+ // indexed version in preferences and invokes |success_callback| on the
+ // calling thread. There is no callback on failure.
void IndexAndStoreRuleset(const UnindexedRulesetInfo& unindexed_ruleset_info,
const WriteRulesetCallback& success_callback);
@@ -248,8 +258,16 @@ class RulesetService : public base::SupportsWeakPtr<RulesetService> {
void OnOpenedRuleset(base::File::Error error);
PrefService* const local_state_;
+
+ // Task runner for tasks critical for user experience. The current ruleset
+ // file opening should be done on this task runner so as it throttles the
+ // first page load.
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
+ // Task runner for tasks that don't influence user experience. Obsolete files
+ // deletion and ruleset indexing should be done on this task runner.
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
+
// Must outlive |this| object.
RulesetServiceDelegate* delegate_;
diff --git a/chromium/components/subresource_filter/core/browser/ruleset_service_unittest.cc b/chromium/components/subresource_filter/core/browser/ruleset_service_unittest.cc
index bc35d4d7c0b..4cb09b82bff 100644
--- a/chromium/components/subresource_filter/core/browser/ruleset_service_unittest.cc
+++ b/chromium/components/subresource_filter/core/browser/ruleset_service_unittest.cc
@@ -17,12 +17,13 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/histogram_tester.h"
+#include "base/test/scoped_task_environment.h"
#include "base/test/test_simple_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/prefs/testing_pref_service.h"
#include "components/subresource_filter/core/browser/ruleset_service_delegate.h"
@@ -144,8 +145,10 @@ using testing::TestRulesetCreator;
class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
public:
SubresourceFilteringRulesetServiceTest()
- : task_runner_(new base::TestSimpleTaskRunner),
- task_runner_handle_(task_runner_) {}
+ : blocking_task_runner_(
+ base::MakeRefCounted<base::TestSimpleTaskRunner>()),
+ background_task_runner_(
+ base::MakeRefCounted<base::TestSimpleTaskRunner>()) {}
protected:
void SetUp() override {
@@ -153,7 +156,7 @@ class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
SetUpTempDir();
ResetRulesetService();
- RunUntilIdle();
+ RunBlockingUntilIdle();
ASSERT_NO_FATAL_FAILURE(
ruleset_creator_.CreateRulesetToDisallowURLsWithPathSuffix(
@@ -173,7 +176,8 @@ class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
void ResetRulesetService() {
mock_delegate_ = std::make_unique<MockRulesetServiceDelegate>();
service_ = std::make_unique<RulesetService>(
- &pref_service_, task_runner_, mock_delegate_.get(), base_dir());
+ &pref_service_, blocking_task_runner_, background_task_runner_,
+ mock_delegate_.get(), base_dir());
}
void ClearRulesetService() {
@@ -203,6 +207,32 @@ class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
service()->IndexAndStoreAndPublishRulesetIfNeeded(ruleset_info);
}
+ void WaitForIndexAndStoreAndPublishUpdatedRuleset(
+ const TestRulesetPair& test_ruleset_pair,
+ const std::string& new_content_version,
+ const base::FilePath& license_path = base::FilePath()) {
+ IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_pair,
+ new_content_version, license_path);
+ // Wait for indexing on background task runner.
+ RunBackgroundUntilIdle();
+ // Wait for file to be opened on blocking task runner.
+ RunBlockingUntilIdle();
+ }
+
+ void SimulateStartupCompletedAndWaitForTasks() {
+ DCHECK(mock_delegate());
+
+ mock_delegate()->SimulateStartupCompleted();
+
+ // Wait for |DeleteObsoleteFiles| and possible |IndexAndWriteRuleset|'s on
+ // background task runner.
+ RunBackgroundUntilIdle();
+
+ // Wait for possible |CreateOrOpen| ruleset file for publishing on blocking
+ // task runner.
+ RunBlockingUntilIdle();
+ }
+
bool WriteRuleset(const TestRulesetPair& test_ruleset_pair,
const IndexedRulesetVersion& indexed_version,
const base::FilePath& license_path = base::FilePath()) {
@@ -243,11 +273,19 @@ class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
GetExpectedVersionDirPath(version));
}
- void RunUntilIdle() { task_runner_->RunUntilIdle(); }
+ void RunBlockingUntilIdle() {
+ blocking_task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void RunBackgroundUntilIdle() {
+ background_task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
+ }
- void RunPendingTasksNTimes(size_t n) {
+ void RunBackgroundPendingTasksNTimes(size_t n) {
while (n--)
- task_runner_->RunPendingTasks();
+ background_task_runner_->RunPendingTasks();
}
void AssertValidRulesetFileWithContents(
@@ -263,7 +301,13 @@ class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
ASSERT_EQ(-1, file->Write(0, kTest, sizeof(kTest)));
}
- void AssertNoPendingTasks() { ASSERT_FALSE(task_runner_->HasPendingTask()); }
+ base::TestSimpleTaskRunner* blocking_task_runner() const {
+ return blocking_task_runner_.get();
+ }
+
+ base::TestSimpleTaskRunner* background_task_runner() const {
+ return background_task_runner_.get();
+ }
PrefService* prefs() { return &pref_service_; }
RulesetService* service() { return service_.get(); }
@@ -282,10 +326,11 @@ class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
}
private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
base::ScopedTempDir scoped_temp_dir_;
- scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
- base::ThreadTaskRunnerHandle task_runner_handle_;
+ scoped_refptr<base::TestSimpleTaskRunner> blocking_task_runner_;
+ scoped_refptr<base::TestSimpleTaskRunner> background_task_runner_;
TestingPrefServiceSimple pref_service_;
TestRulesetCreator ruleset_creator_;
@@ -466,7 +511,7 @@ TEST_F(SubresourceFilteringRulesetServiceTest, DeleteObsoleteRulesets) {
}
TEST_F(SubresourceFilteringRulesetServiceTest, Startup_NoRulesetNotPublished) {
- RunUntilIdle();
+ RunBlockingUntilIdle();
EXPECT_EQ(0u, mock_delegate()->published_rulesets().size());
}
@@ -481,7 +526,7 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
current_version.SaveToPrefs(prefs());
ResetRulesetService();
- RunUntilIdle();
+ RunBlockingUntilIdle();
EXPECT_EQ(0u, mock_delegate()->published_rulesets().size());
}
@@ -497,11 +542,10 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
ASSERT_FALSE(base::IsDirectoryEmpty(base_dir()));
ResetRulesetService();
- RunUntilIdle();
+ RunBackgroundUntilIdle();
EXPECT_EQ(0u, mock_delegate()->published_rulesets().size());
- mock_delegate()->SimulateStartupCompleted();
- RunUntilIdle();
+ SimulateStartupCompletedAndWaitForTasks();
IndexedRulesetVersion stored_version;
stored_version.ReadFromPrefs(prefs());
@@ -517,15 +561,14 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
WriteRuleset(test_ruleset_1(), current_version);
ResetRulesetService();
- RunUntilIdle();
+ RunBlockingUntilIdle();
ASSERT_EQ(1u, mock_delegate()->published_rulesets().size());
ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
&mock_delegate()->published_rulesets()[0],
test_ruleset_1().indexed.contents));
- mock_delegate()->SimulateStartupCompleted();
- RunUntilIdle();
+ SimulateStartupCompletedAndWaitForTasks();
EXPECT_EQ(1u, mock_delegate()->published_rulesets().size());
EXPECT_TRUE(
@@ -533,9 +576,9 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
}
TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_Published) {
- mock_delegate()->SimulateStartupCompleted();
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
- RunUntilIdle();
+ SimulateStartupCompletedAndWaitForTasks();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
+ kTestContentVersion1);
ASSERT_EQ(1u, mock_delegate()->published_rulesets().size());
ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
@@ -545,22 +588,20 @@ TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_Published) {
TEST_F(SubresourceFilteringRulesetServiceTest,
NewRulesetWithEmptyVersion_NotPublished) {
- mock_delegate()->SimulateStartupCompleted();
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), std::string());
- RunUntilIdle();
+ SimulateStartupCompletedAndWaitForTasks();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), std::string());
ASSERT_EQ(0u, mock_delegate()->published_rulesets().size());
}
TEST_F(SubresourceFilteringRulesetServiceTest,
NewRulesetEarly_PublishedAfterStartupCompleted) {
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
- RunUntilIdle();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
+ kTestContentVersion1);
ASSERT_EQ(0u, mock_delegate()->published_rulesets().size());
- mock_delegate()->SimulateStartupCompleted();
- RunUntilIdle();
+ SimulateStartupCompletedAndWaitForTasks();
ASSERT_EQ(1u, mock_delegate()->published_rulesets().size());
ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
@@ -579,8 +620,7 @@ TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_Persisted) {
// Indexing should be queued, and will be performed in a deferred manner,
// after start-up, at the same time with cleaning up obsoleted rulesets. Make
// sure it does not get immediately deleted.
- mock_delegate()->SimulateStartupCompleted();
- RunUntilIdle();
+ SimulateStartupCompletedAndWaitForTasks();
IndexedRulesetVersion stored_version;
stored_version.ReadFromPrefs(prefs());
@@ -599,15 +639,14 @@ TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_Persisted) {
EXPECT_EQ(kTestLicenseContents, actual_license_contents);
ResetRulesetService();
- RunUntilIdle();
+ RunBlockingUntilIdle();
ASSERT_EQ(1u, mock_delegate()->published_rulesets().size());
ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
&mock_delegate()->published_rulesets()[0],
test_ruleset_1().indexed.contents));
- mock_delegate()->SimulateStartupCompleted();
- RunUntilIdle();
+ SimulateStartupCompletedAndWaitForTasks();
EXPECT_TRUE(base::PathExists(GetExpectedRulesetDataFilePath(stored_version)));
@@ -638,8 +677,8 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
kTestContentVersion1, IndexedRulesetVersion::CurrentFormatVersion());
WriteRuleset(test_ruleset_2(), same_version_but_incomplete);
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
- RunUntilIdle();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
+ kTestContentVersion1);
IndexedRulesetVersion stored_version;
stored_version.ReadFromPrefs(prefs());
@@ -666,9 +705,8 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
ASSERT_NO_FATAL_FAILURE(
test_ruleset_creator()->CreateUnindexedRulesetWithRules(
{unfilled_rule}, &ruleset_with_unsupported_rule.unindexed));
- IndexAndStoreAndPublishUpdatedRuleset(ruleset_with_unsupported_rule,
- kTestContentVersion1);
- RunUntilIdle();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(ruleset_with_unsupported_rule,
+ kTestContentVersion1);
IndexedRulesetVersion stored_version;
stored_version.ReadFromPrefs(prefs());
@@ -697,7 +735,8 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
ruleset_info.ruleset_path = base::FilePath(); // Non-existent.
ruleset_info.content_version = kTestContentVersion1;
service()->IndexAndStoreAndPublishRulesetIfNeeded(ruleset_info);
- RunUntilIdle();
+ RunBackgroundUntilIdle();
+ RunBlockingUntilIdle();
IndexedRulesetVersion stored_version;
stored_version.ReadFromPrefs(prefs());
@@ -726,8 +765,8 @@ TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_ParseFailure) {
ASSERT_TRUE(base::AppendToFile(test_ruleset_1().unindexed.path,
kGarbage.data(),
static_cast<int>(kGarbage.size())));
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
- RunUntilIdle();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
+ kTestContentVersion1);
IndexedRulesetVersion stored_version;
stored_version.ReadFromPrefs(prefs());
@@ -759,16 +798,15 @@ TEST_F(SubresourceFilteringRulesetServiceDeathTest, NewRuleset_IndexingCrash) {
&RulesetService::g_index_ruleset_func, &MockCrashingIndexRuleset));
EXPECT_DEATH(
{
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
- kTestContentVersion1);
- RunUntilIdle();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
+ kTestContentVersion1);
},
"Synthetic crash");
#else
auto scoped_override(OverrideFunctionForScope(
&RulesetService::g_index_ruleset_func, &MockFailingIndexRuleset));
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
- RunUntilIdle();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
+ kTestContentVersion1);
#endif
// Expect that a sentinel file is left behind as a warning not to attempt
@@ -783,14 +821,13 @@ TEST_F(SubresourceFilteringRulesetServiceDeathTest, NewRuleset_IndexingCrash) {
base::HistogramTester histogram_tester;
ResetRulesetService();
- mock_delegate()->SimulateStartupCompleted();
- RunUntilIdle();
+ SimulateStartupCompletedAndWaitForTasks();
ASSERT_EQ(0u, mock_delegate()->published_rulesets().size());
// The subsequent indexing attempt should be aborted.
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
- RunUntilIdle();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
+ kTestContentVersion1);
IndexedRulesetVersion stored_version;
stored_version.ReadFromPrefs(prefs());
@@ -811,8 +848,8 @@ TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_WriteFailure) {
auto scoped_override(OverrideFunctionForScope(
&RulesetService::g_replace_file_func, &MockFailingReplaceFile));
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
- RunUntilIdle();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
+ kTestContentVersion1);
IndexedRulesetVersion stored_version;
stored_version.ReadFromPrefs(prefs());
@@ -842,11 +879,10 @@ TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_WriteFailure) {
TEST_F(SubresourceFilteringRulesetServiceTest,
NewRulesetTwice_SecondRulesetPrevails) {
mock_delegate()->SimulateStartupCompleted();
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
- RunUntilIdle();
-
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_2(), kTestContentVersion2);
- RunUntilIdle();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
+ kTestContentVersion1);
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_2(),
+ kTestContentVersion2);
// This verifies that the contents from the first version of the ruleset file
// can still be read after it has been deprecated.
@@ -866,13 +902,13 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
TEST_F(SubresourceFilteringRulesetServiceTest,
NewRulesetTwiceWithTheSameVersion_SecondIsIgnored) {
mock_delegate()->SimulateStartupCompleted();
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
- RunUntilIdle();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
+ kTestContentVersion1);
// For good measure, also violate the requirement that versions should
// uniquely identify the contents.
IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_2(), kTestContentVersion1);
- ASSERT_NO_FATAL_FAILURE(AssertNoPendingTasks());
+ ASSERT_FALSE(background_task_runner()->HasPendingTask());
ASSERT_EQ(1u, mock_delegate()->published_rulesets().size());
ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
@@ -898,8 +934,7 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_3(), kTestContentVersion3);
IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
- mock_delegate()->SimulateStartupCompleted();
- RunUntilIdle();
+ SimulateStartupCompletedAndWaitForTasks();
// Optionally permit the publication of the pre-existing ruleset, but the last
// published ruleset must be the one that was set the latest (and with a
@@ -922,14 +957,13 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
++num_tasks_inbetween) {
SCOPED_TRACE(::testing::Message() << "#Tasks: " << num_tasks_inbetween);
- mock_delegate()->SimulateStartupCompleted();
- RunUntilIdle();
+ SimulateStartupCompletedAndWaitForTasks();
IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
kTestContentVersion1);
- RunPendingTasksNTimes(num_tasks_inbetween);
+ RunBackgroundPendingTasksNTimes(num_tasks_inbetween);
ClearRulesetService();
- RunUntilIdle();
+ RunBlockingUntilIdle();
EXPECT_TRUE(base::DeleteFile(base_dir(), true));
ResetRulesetService();
@@ -937,7 +971,8 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
// Must pump out PostTaskWithReply tasks that are referencing the very same
// task runner to avoid circular dependencies and leaks on shutdown.
- RunUntilIdle();
+ RunBackgroundUntilIdle();
+ RunBlockingUntilIdle();
}
TEST_F(SubresourceFilteringRulesetServiceTest,
@@ -946,15 +981,13 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
++num_tasks_inbetween) {
SCOPED_TRACE(::testing::Message() << "#Tasks: " << num_tasks_inbetween);
- mock_delegate()->SimulateStartupCompleted();
- RunUntilIdle();
+ SimulateStartupCompletedAndWaitForTasks();
IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
kTestContentVersion1);
- RunPendingTasksNTimes(num_tasks_inbetween);
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_2(),
- kTestContentVersion2);
- RunUntilIdle();
+ RunBackgroundPendingTasksNTimes(num_tasks_inbetween);
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_2(),
+ kTestContentVersion2);
// Optionally permit a "hazardous" publication of either the old or new
// version of the ruleset, but the last ruleset message must be the new one.
@@ -977,7 +1010,7 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
EXPECT_EQ(kTestContentVersion2, stored_version.content_version);
ClearRulesetService();
- RunUntilIdle();
+ RunBlockingUntilIdle();
EXPECT_TRUE(base::DeleteFile(base_dir(), true));
IndexedRulesetVersion().SaveToPrefs(prefs());
@@ -987,12 +1020,44 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
TEST_F(SubresourceFilteringRulesetServiceTest, RulesetIsReadonly) {
mock_delegate()->SimulateStartupCompleted();
- IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
- RunUntilIdle();
+ WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
+ kTestContentVersion1);
ASSERT_EQ(1u, mock_delegate()->published_rulesets().size());
ASSERT_NO_FATAL_FAILURE(
AssertReadonlyRulesetFile(&mock_delegate()->published_rulesets()[0]));
}
+TEST_F(SubresourceFilteringRulesetServiceTest,
+ ParallelOpenOfTwoFilesPublishesOnlyLastOne) {
+ // Test emulates bail out situation when ruleset file opening is cheduled
+ // during another file opening.
+ SimulateStartupCompletedAndWaitForTasks();
+
+ // Schedule two indexing tasks on background task runner.
+ IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
+ IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_2(), kTestContentVersion2);
+ ASSERT_EQ(2u, background_task_runner()->NumPendingTasks());
+
+ // Run indexing. Responses are scheduled on the current thread task runner.
+ background_task_runner()->RunPendingTasks();
+
+ // Process both responses. Each one should schedule files opening on blocking
+ // task runner.
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(2u, blocking_task_runner()->NumPendingTasks());
+
+ // Run opening. Responses are scheduled on the current thread task runner.
+ blocking_task_runner()->RunPendingTasks();
+
+ // Process both respones.
+ base::RunLoop().RunUntilIdle();
+
+ // Only the last one should fire callback.
+ ASSERT_EQ(1u, mock_delegate()->published_rulesets().size());
+ ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
+ &mock_delegate()->published_rulesets()[0],
+ test_ruleset_2().indexed.contents));
+}
+
} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/core/browser/subresource_filter_features.cc b/chromium/components/subresource_filter/core/browser/subresource_filter_features.cc
index 01b845f8023..407eb2ebcc6 100644
--- a/chromium/components/subresource_filter/core/browser/subresource_filter_features.cc
+++ b/chromium/components/subresource_filter/core/browser/subresource_filter_features.cc
@@ -115,16 +115,18 @@ int ParseInt(const base::StringPiece value) {
std::vector<Configuration> FillEnabledPresetConfigurations(
std::map<std::string, std::string>* params) {
+ // If ad tagging is enabled, turn on the dryrun automatically.
+ bool ad_tagging_enabled = base::FeatureList::IsEnabled(kAdTagging);
const struct {
const char* name;
bool enabled_by_default;
Configuration (*factory_method)();
} kAvailablePresetConfigurations[] = {
- {kPresetLiveRunOnPhishingSites, false,
+ {kPresetLiveRunOnPhishingSites, true,
&Configuration::MakePresetForLiveRunOnPhishingSites},
- {kPresetPerformanceTestingDryRunOnAllSites, false,
+ {kPresetPerformanceTestingDryRunOnAllSites, ad_tagging_enabled,
&Configuration::MakePresetForPerformanceTestingDryRunOnAllSites},
- {kPresetLiveRunForBetterAds, false,
+ {kPresetLiveRunForBetterAds, true,
&Configuration::MakePresetForLiveRunForBetterAds}};
CommaSeparatedStrings enabled_presets(
@@ -186,7 +188,9 @@ std::vector<Configuration> ParseEnabledConfigurations() {
std::map<std::string, std::string> params;
base::GetFieldTrialParamsByFeature(kSafeBrowsingSubresourceFilter, &params);
- std::vector<Configuration> configs = FillEnabledPresetConfigurations(&params);
+ std::vector<Configuration> configs;
+ if (base::FeatureList::IsEnabled(kSafeBrowsingSubresourceFilter))
+ configs = FillEnabledPresetConfigurations(&params);
Configuration experimental_config = ParseExperimentalConfiguration(&params);
configs.push_back(std::move(experimental_config));
@@ -234,10 +238,11 @@ base::LazyInstance<scoped_refptr<ConfigurationList>>::Leaky
// Constant definitions -------------------------------------------------------
const base::Feature kSafeBrowsingSubresourceFilter{
- "SubresourceFilter", base::FEATURE_DISABLED_BY_DEFAULT};
+ "SubresourceFilter", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kSafeBrowsingSubresourceFilterExperimentalUI{
- "SubresourceFilterExperimentalUI", base::FEATURE_DISABLED_BY_DEFAULT};
+ "SubresourceFilterExperimentalUI", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kAdTagging{"AdTagging", base::FEATURE_DISABLED_BY_DEFAULT};
// Legacy name `activation_state` is used in variation parameters.
const char kActivationLevelParameterName[] = "activation_state";
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 e16c5bb8e87..ec85be4bb41 100644
--- a/chromium/components/subresource_filter/core/browser/subresource_filter_features.h
+++ b/chromium/components/subresource_filter/core/browser/subresource_filter_features.h
@@ -194,6 +194,10 @@ extern const base::Feature kSafeBrowsingSubresourceFilter;
// Enables the new experimental UI for the Subresource Filter.
extern const base::Feature kSafeBrowsingSubresourceFilterExperimentalUI;
+// Enables the tagging of ad frames and resource requests by using the
+// subresource_filter component in dry-run mode.
+extern const base::Feature kAdTagging;
+
// Name/values of the variation parameter controlling maximum activation level.
extern const char kActivationLevelParameterName[];
extern const char kActivationLevelDryRun[];
diff --git a/chromium/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc b/chromium/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc
index 1871ef444a4..bd88336b4fd 100644
--- a/chromium/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc
+++ b/chromium/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
+#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "components/subresource_filter/core/browser/subresource_filter_features_test_support.h"
#include "components/variations/variations_associated_data.h"
@@ -66,6 +67,14 @@ void ExpectAndRetrieveExactlyOneEnabledConfig(Configuration* actual_config) {
*actual_config = config_list->configs_by_decreasing_priority().front();
}
+void ExpectAndRetrieveExactlyOneExtraEnabledConfig(
+ Configuration* actual_config) {
+ DCHECK(actual_config);
+ const auto config_list = GetEnabledConfigurations();
+ ASSERT_EQ(3u, config_list->configs_by_decreasing_priority().size());
+ *actual_config = config_list->configs_by_decreasing_priority().back();
+}
+
void ExpectPresetCanBeEnabledByName(Configuration preset, const char* name) {
ScopedExperimentalStateToggle scoped_experimental_state(
base::FeatureList::OVERRIDE_ENABLE_FEATURE,
@@ -73,18 +82,25 @@ void ExpectPresetCanBeEnabledByName(Configuration preset, const char* name) {
const auto config_list = GetEnabledConfigurations();
EXPECT_THAT(config_list->configs_by_decreasing_priority(),
- ::testing::ElementsAre(preset, Configuration()));
+ ::testing::ElementsAre(
+ Configuration::MakePresetForLiveRunOnPhishingSites(),
+ Configuration::MakePresetForLiveRunForBetterAds(), preset,
+ Configuration()));
}
-void ExpectPresetIsEquivalentToVariationParams(
+void ExpectParamsGeneratePreset(
Configuration preset,
std::map<std::string, std::string> variation_params) {
ScopedExperimentalStateToggle scoped_experimental_state(
base::FeatureList::OVERRIDE_ENABLE_FEATURE, variation_params);
Configuration experimental_configuration;
- ExpectAndRetrieveExactlyOneEnabledConfig(&experimental_configuration);
- EXPECT_EQ(preset, experimental_configuration);
+ const auto config_list = GetEnabledConfigurations();
+ bool matched_preset = false;
+ for (auto it : config_list->configs_by_decreasing_priority()) {
+ matched_preset |= preset == it;
+ }
+ EXPECT_TRUE(matched_preset);
}
} // namespace
@@ -114,13 +130,17 @@ TEST(SubresourceFilterFeaturesTest, ActivationLevel) {
<< test_case.activation_level_param << "\"");
ScopedExperimentalStateToggle scoped_experimental_state(
- test_case.feature_enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
- : base::FeatureList::OVERRIDE_USE_DEFAULT,
+ test_case.feature_enabled ? base::FeatureList::OVERRIDE_USE_DEFAULT
+ : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
{{kActivationLevelParameterName, test_case.activation_level_param},
{kActivationScopeParameterName, kActivationScopeNoSites}});
Configuration actual_configuration;
- ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ if (test_case.feature_enabled) {
+ ExpectAndRetrieveExactlyOneExtraEnabledConfig(&actual_configuration);
+ } else {
+ ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ }
EXPECT_EQ(test_case.expected_activation_level,
actual_configuration.activation_options.activation_level);
EXPECT_EQ(ActivationScope::NO_SITES,
@@ -154,12 +174,16 @@ TEST(SubresourceFilterFeaturesTest, ActivationScope) {
ScopedExperimentalStateToggle scoped_experimental_state(
test_case.feature_enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
- : base::FeatureList::OVERRIDE_USE_DEFAULT,
+ : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
{{kActivationLevelParameterName, kActivationLevelDisabled},
{kActivationScopeParameterName, test_case.activation_scope_param}});
Configuration actual_configuration;
- ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ if (test_case.feature_enabled) {
+ ExpectAndRetrieveExactlyOneExtraEnabledConfig(&actual_configuration);
+ } else {
+ ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ }
EXPECT_EQ(ActivationLevel::DISABLED,
actual_configuration.activation_options.activation_level);
EXPECT_EQ(test_case.expected_activation_scope,
@@ -212,13 +236,17 @@ TEST(SubresourceFilterFeaturesTest, ActivationLevelAndScope) {
<< test_case.activation_scope_param << "\"");
ScopedExperimentalStateToggle scoped_experimental_state(
- test_case.feature_enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
- : base::FeatureList::OVERRIDE_USE_DEFAULT,
+ test_case.feature_enabled ? base::FeatureList::OVERRIDE_USE_DEFAULT
+ : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
{{kActivationLevelParameterName, test_case.activation_level_param},
{kActivationScopeParameterName, test_case.activation_scope_param}});
Configuration actual_configuration;
- ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ if (test_case.feature_enabled) {
+ ExpectAndRetrieveExactlyOneExtraEnabledConfig(&actual_configuration);
+ } else {
+ ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ }
EXPECT_EQ(test_case.expected_activation_level,
actual_configuration.activation_options.activation_level);
EXPECT_EQ(test_case.expected_activation_scope,
@@ -269,14 +297,18 @@ TEST(SubresourceFilterFeaturesTest, ActivationList) {
<< test_case.activation_list_param << "\"");
ScopedExperimentalStateToggle scoped_experimental_state(
- test_case.feature_enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
- : base::FeatureList::OVERRIDE_USE_DEFAULT,
+ test_case.feature_enabled ? base::FeatureList::OVERRIDE_USE_DEFAULT
+ : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
{{kActivationLevelParameterName, kActivationLevelDisabled},
{kActivationScopeParameterName, kActivationScopeNoSites},
{kActivationListsParameterName, test_case.activation_list_param}});
Configuration actual_configuration;
- ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ if (test_case.feature_enabled) {
+ ExpectAndRetrieveExactlyOneExtraEnabledConfig(&actual_configuration);
+ } else {
+ ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ }
EXPECT_EQ(test_case.expected_activation_list,
actual_configuration.activation_conditions.activation_list);
}
@@ -309,13 +341,17 @@ TEST(SubresourceFilterFeaturesTest, ActivationPriority) {
<< test_case.activation_priority_param << "\"");
ScopedExperimentalStateToggle scoped_experimental_state(
- test_case.feature_enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
- : base::FeatureList::OVERRIDE_USE_DEFAULT,
+ test_case.feature_enabled ? base::FeatureList::OVERRIDE_USE_DEFAULT
+ : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
{{kActivationPriorityParameterName,
test_case.activation_priority_param}});
Configuration actual_configuration;
- ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ if (test_case.feature_enabled) {
+ ExpectAndRetrieveExactlyOneExtraEnabledConfig(&actual_configuration);
+ } else {
+ ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ }
EXPECT_EQ(test_case.expected_priority,
actual_configuration.activation_conditions.priority);
}
@@ -346,13 +382,17 @@ TEST(SubresourceFilterFeaturesTest, PerfMeasurementRate) {
<< test_case.perf_measurement_param << "\"");
ScopedExperimentalStateToggle scoped_experimental_state(
- test_case.feature_enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
- : base::FeatureList::OVERRIDE_USE_DEFAULT,
+ test_case.feature_enabled ? base::FeatureList::OVERRIDE_USE_DEFAULT
+ : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
{{kPerformanceMeasurementRateParameterName,
test_case.perf_measurement_param}});
Configuration actual_configuration;
- ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ if (test_case.feature_enabled) {
+ ExpectAndRetrieveExactlyOneExtraEnabledConfig(&actual_configuration);
+ } else {
+ ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ }
EXPECT_EQ(
test_case.expected_perf_measurement_rate,
actual_configuration.activation_options.performance_measurement_rate);
@@ -381,13 +421,17 @@ TEST(SubresourceFilterFeaturesTest, SuppressNotifications) {
<< test_case.suppress_notifications_param << "\"");
ScopedExperimentalStateToggle scoped_experimental_state(
- test_case.feature_enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
- : base::FeatureList::OVERRIDE_USE_DEFAULT,
+ test_case.feature_enabled ? base::FeatureList::OVERRIDE_USE_DEFAULT
+ : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
{{kSuppressNotificationsParameterName,
test_case.suppress_notifications_param}});
Configuration actual_configuration;
- ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ if (test_case.feature_enabled) {
+ ExpectAndRetrieveExactlyOneExtraEnabledConfig(&actual_configuration);
+ } else {
+ ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ }
EXPECT_EQ(
test_case.expected_suppress_notifications_value,
actual_configuration.activation_options.should_suppress_notifications);
@@ -416,13 +460,17 @@ TEST(SubresourceFilterFeaturesTest, WhitelistSiteOnReload) {
<< test_case.whitelist_site_on_reload_param << "\"");
ScopedExperimentalStateToggle scoped_experimental_state(
- test_case.feature_enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
- : base::FeatureList::OVERRIDE_USE_DEFAULT,
+ test_case.feature_enabled ? base::FeatureList::OVERRIDE_USE_DEFAULT
+ : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
{{kWhitelistSiteOnReloadParameterName,
test_case.whitelist_site_on_reload_param}});
Configuration actual_configuration;
- ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ if (test_case.feature_enabled) {
+ ExpectAndRetrieveExactlyOneExtraEnabledConfig(&actual_configuration);
+ } else {
+ ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ }
EXPECT_EQ(test_case.expected_whitelist_site_on_reload_value,
actual_configuration.activation_options
.should_whitelist_site_on_reload);
@@ -444,12 +492,16 @@ TEST(SubresourceFilterFeaturesTest, RulesetFlavor) {
<< test_case.ruleset_flavor_param << "\"");
ScopedExperimentalStateToggle scoped_experimental_state(
- test_case.feature_enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
- : base::FeatureList::OVERRIDE_USE_DEFAULT,
+ test_case.feature_enabled ? base::FeatureList::OVERRIDE_USE_DEFAULT
+ : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
{{kRulesetFlavorParameterName, test_case.ruleset_flavor_param}});
Configuration actual_configuration;
- ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ if (test_case.feature_enabled) {
+ ExpectAndRetrieveExactlyOneExtraEnabledConfig(&actual_configuration);
+ } else {
+ ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ }
EXPECT_EQ(std::string(test_case.expected_ruleset_flavor_value),
actual_configuration.general_settings.ruleset_flavor);
}
@@ -515,30 +567,21 @@ TEST(SubresourceFilterFeaturesTest,
std::map<std::string, std::string>());
const auto config_list = GetEnabledConfigurations();
- EXPECT_THAT(config_list->configs_by_decreasing_priority(),
- ::testing::ElementsAre(Configuration()));
+ EXPECT_THAT(
+ config_list->configs_by_decreasing_priority(),
+ ::testing::ElementsAre(
+ Configuration::MakePresetForLiveRunOnPhishingSites(),
+ Configuration::MakePresetForLiveRunForBetterAds(), Configuration()));
EXPECT_EQ(std::string(),
config_list->lexicographically_greatest_ruleset_flavor());
}
-TEST(SubresourceFilterFeaturesTest, PresetForLiveRunOnPhishingSites) {
- ExpectPresetCanBeEnabledByName(
- Configuration::MakePresetForLiveRunOnPhishingSites(),
- kPresetLiveRunOnPhishingSites);
- ExpectPresetIsEquivalentToVariationParams(
- Configuration::MakePresetForLiveRunOnPhishingSites(),
- {{kActivationLevelParameterName, kActivationLevelEnabled},
- {kActivationScopeParameterName, kActivationScopeActivationList},
- {kActivationListsParameterName, kActivationListPhishingInterstitial},
- {kActivationPriorityParameterName, "1000"}});
-}
-
TEST(SubresourceFilterFeaturesTest,
PresetForPerformanceTestingDryRunOnAllSites) {
ExpectPresetCanBeEnabledByName(
Configuration::MakePresetForPerformanceTestingDryRunOnAllSites(),
kPresetPerformanceTestingDryRunOnAllSites);
- ExpectPresetIsEquivalentToVariationParams(
+ ExpectParamsGeneratePreset(
Configuration::MakePresetForPerformanceTestingDryRunOnAllSites(),
{{kActivationLevelParameterName, kActivationLevelDryRun},
{kActivationScopeParameterName, kActivationScopeAllSites},
@@ -547,16 +590,8 @@ TEST(SubresourceFilterFeaturesTest,
}
TEST(SubresourceFilterFeaturesTest, PresetForLiveRunOnBetterAdsSites) {
- ExpectPresetCanBeEnabledByName(
- Configuration::MakePresetForLiveRunForBetterAds(),
- kPresetLiveRunForBetterAds);
const Configuration config =
Configuration::MakePresetForLiveRunForBetterAds();
- ExpectPresetIsEquivalentToVariationParams(
- config, {{kActivationLevelParameterName, kActivationLevelEnabled},
- {kActivationScopeParameterName, kActivationScopeActivationList},
- {kActivationListsParameterName, kActivationListBetterAds},
- {kActivationPriorityParameterName, "800"}});
EXPECT_EQ(ActivationList::BETTER_ADS,
config.activation_conditions.activation_list);
EXPECT_EQ(ActivationScope::ACTIVATION_LIST,
@@ -573,12 +608,14 @@ TEST(SubresourceFilterFeaturesTest, PresetForLiveRunOnBetterAdsSites) {
TEST(SubresourceFilterFeaturesTest, ConfigurationPriorities) {
const std::vector<Configuration> expected_order_by_decreasing_priority = {
Configuration::MakePresetForLiveRunOnPhishingSites(),
+ Configuration::MakePresetForLiveRunForBetterAds(),
Configuration::MakePresetForPerformanceTestingDryRunOnAllSites(),
Configuration() /* default constructor */
};
std::vector<Configuration> shuffled_order = {
expected_order_by_decreasing_priority[2],
+ expected_order_by_decreasing_priority[3],
expected_order_by_decreasing_priority[0],
expected_order_by_decreasing_priority[1]};
subresource_filter::testing::ScopedSubresourceFilterConfigurator
@@ -591,13 +628,16 @@ TEST(SubresourceFilterFeaturesTest, ConfigurationPriorities) {
TEST(SubresourceFilterFeaturesTest, EnableDisableMultiplePresets) {
const std::string kPhishing(kPresetLiveRunOnPhishingSites);
const std::string kPerfTest(kPresetPerformanceTestingDryRunOnAllSites);
+ const std::string kBAS(kPresetLiveRunForBetterAds);
// The default config comes from the empty experimental configuration.
- const std::vector<Configuration> kDefaultConfig = {Configuration()};
- const std::vector<Configuration> kPhishingAndDefaultConfigs = {
- Configuration::MakePresetForLiveRunOnPhishingSites(), Configuration()};
+ const std::vector<Configuration> kEmptyConfig = {Configuration()};
+ const std::vector<Configuration> kDefaultConfig = {
+ Configuration::MakePresetForLiveRunOnPhishingSites(),
+ Configuration::MakePresetForLiveRunForBetterAds(), Configuration()};
const std::vector<Configuration> kAllConfigs = {
Configuration::MakePresetForLiveRunOnPhishingSites(),
+ Configuration::MakePresetForLiveRunForBetterAds(),
Configuration::MakePresetForPerformanceTestingDryRunOnAllSites(),
Configuration()};
@@ -608,13 +648,12 @@ TEST(SubresourceFilterFeaturesTest, EnableDisableMultiplePresets) {
} kTestCases[] = {
{"", "", kDefaultConfig},
{"garbage1", "garbage2", kDefaultConfig},
- {"", kPhishing + "," + kPerfTest, kDefaultConfig},
- {kPhishing, kPerfTest, kPhishingAndDefaultConfigs},
- {kPhishing + "," + kPerfTest, "garbage", kAllConfigs},
- {kPerfTest + "," + kPhishing, base::ToUpperASCII(kPerfTest),
- kPhishingAndDefaultConfigs},
- {kPerfTest + "," + kPhishing,
- ",,garbage, ," + kPerfTest + "," + kPhishing, kDefaultConfig},
+ {"", kPhishing + "," + kPerfTest + "," + kBAS, kEmptyConfig},
+ {kPhishing, kPerfTest, kDefaultConfig},
+ {kPerfTest, "garbage", kAllConfigs},
+ {kPerfTest, base::ToUpperASCII(kPerfTest), kDefaultConfig},
+ {kPerfTest + "," + kPhishing + "," + kBAS,
+ ",,garbage, ," + kPerfTest + "," + kPhishing + "," + kBAS, kEmptyConfig},
{base::ToUpperASCII(kPhishing) + "," + base::ToUpperASCII(kPerfTest), "",
kAllConfigs},
{",, ," + kPerfTest + ",," + kPhishing, "", kAllConfigs},
@@ -643,11 +682,12 @@ TEST(SubresourceFilterFeaturesTest,
EnableMultiplePresetsAndExperimentalConfig) {
const std::string kPhishing(kPresetLiveRunOnPhishingSites);
const std::string kPerfTest(kPresetPerformanceTestingDryRunOnAllSites);
+ const std::string kBAS(kPresetLiveRunForBetterAds);
const std::string kTestRulesetFlavor("foobar");
ScopedExperimentalStateToggle scoped_experimental_state(
base::FeatureList::OVERRIDE_ENABLE_FEATURE,
- {{kEnablePresetsParameterName, kPhishing + "," + kPerfTest},
+ {{kEnablePresetsParameterName, kPhishing + "," + kPerfTest + "," + kBAS},
{kActivationLevelParameterName, kActivationLevelDryRun},
{kActivationScopeParameterName, kActivationScopeActivationList},
{kActivationListsParameterName, kActivationListSubresourceFilter},
@@ -665,6 +705,7 @@ TEST(SubresourceFilterFeaturesTest,
config_list->configs_by_decreasing_priority(),
::testing::ElementsAre(
Configuration::MakePresetForLiveRunOnPhishingSites(),
+ Configuration::MakePresetForLiveRunForBetterAds(),
experimental_config,
Configuration::MakePresetForPerformanceTestingDryRunOnAllSites()));
EXPECT_EQ(kTestRulesetFlavor,
@@ -679,7 +720,7 @@ TEST(SubresourceFilterFeaturesTest, ForcedActivation_NotConfigurable) {
{"forced_activation", "true"}});
Configuration actual_configuration;
- ExpectAndRetrieveExactlyOneEnabledConfig(&actual_configuration);
+ ExpectAndRetrieveExactlyOneExtraEnabledConfig(&actual_configuration);
EXPECT_EQ(ActivationLevel::ENABLED,
actual_configuration.activation_options.activation_level);
EXPECT_EQ(ActivationScope::NO_SITES,
@@ -688,4 +729,22 @@ TEST(SubresourceFilterFeaturesTest, ForcedActivation_NotConfigurable) {
EXPECT_FALSE(actual_configuration.activation_conditions.forced_activation);
}
+TEST(SubresourceFilterFeaturesTest, AdTagging_EnablesDryRun) {
+ const Configuration dryrun =
+ Configuration::MakePresetForPerformanceTestingDryRunOnAllSites();
+ base::test::ScopedFeatureList scoped_feature;
+ scoped_feature.InitAndEnableFeature(kAdTagging);
+ EXPECT_TRUE(base::ContainsValue(
+ GetEnabledConfigurations()->configs_by_decreasing_priority(), dryrun));
+}
+
+TEST(SubresourceFilterFeaturesTest, AdTaggingDisabled_DisablesDryRun) {
+ const Configuration dryrun =
+ Configuration::MakePresetForPerformanceTestingDryRunOnAllSites();
+ base::test::ScopedFeatureList scoped_feature;
+ scoped_feature.InitAndDisableFeature(kAdTagging);
+ EXPECT_FALSE(base::ContainsValue(
+ GetEnabledConfigurations()->configs_by_decreasing_priority(), dryrun));
+}
+
} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/core/common/BUILD.gn b/chromium/components/subresource_filter/core/common/BUILD.gn
index 55111b6107f..3c6a955e0c5 100644
--- a/chromium/components/subresource_filter/core/common/BUILD.gn
+++ b/chromium/components/subresource_filter/core/common/BUILD.gn
@@ -58,6 +58,21 @@ static_library("test_support") {
]
}
+static_library("tools_lib") {
+ sources = [
+ "tools/filter_tool.cc",
+ "tools/filter_tool.h",
+ "tools/indexing_tool.cc",
+ "tools/indexing_tool.h",
+ ]
+ deps = [
+ ":common",
+ "//base",
+ "//components/url_pattern_index:util",
+ "//url",
+ ]
+}
+
source_set("unit_tests") {
testonly = true
sources = [
@@ -65,10 +80,13 @@ source_set("unit_tests") {
"first_party_origin_unittest.cc",
"indexed_ruleset_unittest.cc",
"scoped_timers_unittest.cc",
+ "tools/filter_tool_unittest.cc",
+ "tools/indexing_tool_unittest.cc",
]
deps = [
":common",
":test_support",
+ ":tools_lib",
"//base",
"//base/test:test_support",
"//components/url_pattern_index:test_support",
@@ -77,3 +95,27 @@ source_set("unit_tests") {
"//url",
]
}
+
+if (is_linux || is_mac || is_win) {
+ executable("subresource_filter_tool") {
+ sources = [
+ "tools/filter_tool_main.cc",
+ ]
+ deps = [
+ ":tools_lib",
+ "//base",
+ "//build/config:exe_and_shlib_deps",
+ ]
+ }
+
+ executable("subresource_indexing_tool") {
+ sources = [
+ "tools/indexing_tool_main.cc",
+ ]
+ deps = [
+ ":tools_lib",
+ "//base",
+ "//build/config:exe_and_shlib_deps",
+ ]
+ }
+}
diff --git a/chromium/components/subresource_filter/core/common/document_subresource_filter.cc b/chromium/components/subresource_filter/core/common/document_subresource_filter.cc
index 42b655c96bd..07bd2ae1ae5 100644
--- a/chromium/components/subresource_filter/core/common/document_subresource_filter.cc
+++ b/chromium/components/subresource_filter/core/common/document_subresource_filter.cc
@@ -77,4 +77,18 @@ LoadPolicy DocumentSubresourceFilter::GetLoadPolicy(
return LoadPolicy::ALLOW;
}
+const url_pattern_index::flat::UrlRule*
+DocumentSubresourceFilter::FindMatchingUrlRule(
+ const GURL& subresource_url,
+ url_pattern_index::proto::ElementType subresource_type) {
+ if (activation_state_.filtering_disabled_for_document)
+ return nullptr;
+ if (subresource_url.SchemeIs(url::kDataScheme))
+ return nullptr;
+
+ return ruleset_matcher_.MatchedUrlRule(
+ subresource_url, *document_origin_, subresource_type,
+ activation_state_.generic_blocking_rules_disabled);
+}
+
} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/core/common/document_subresource_filter.h b/chromium/components/subresource_filter/core/common/document_subresource_filter.h
index 66496e3bfa8..11305dedd78 100644
--- a/chromium/components/subresource_filter/core/common/document_subresource_filter.h
+++ b/chromium/components/subresource_filter/core/common/document_subresource_filter.h
@@ -56,6 +56,12 @@ class DocumentSubresourceFilter {
const GURL& subresource_url,
url_pattern_index::proto::ElementType subresource_type);
+ // Returns the matching rule that determines whether the request url and type
+ // should be allowed. If no rule matches, returns nullptr.
+ const url_pattern_index::flat::UrlRule* FindMatchingUrlRule(
+ const GURL& subresource_url,
+ url_pattern_index::proto::ElementType subresource_type);
+
private:
const ActivationState activation_state_;
const scoped_refptr<const MemoryMappedRuleset> ruleset_;
diff --git a/chromium/components/subresource_filter/core/common/document_subresource_filter_unittest.cc b/chromium/components/subresource_filter/core/common/document_subresource_filter_unittest.cc
index 2ecfcf54f3d..4e9c3759af4 100644
--- a/chromium/components/subresource_filter/core/common/document_subresource_filter_unittest.cc
+++ b/chromium/components/subresource_filter/core/common/document_subresource_filter_unittest.cc
@@ -91,6 +91,25 @@ TEST_F(DocumentSubresourceFilterTest, DryRun) {
EXPECT_EQ(0, statistics.num_loads_disallowed);
}
+TEST_F(DocumentSubresourceFilterTest, MatchingRuleDryRun) {
+ ActivationState activation_state(kDryRun);
+ activation_state.measure_performance = false;
+ DocumentSubresourceFilter filter(url::Origin(), activation_state, ruleset());
+
+ EXPECT_NE(nullptr,
+ filter.FindMatchingUrlRule(GURL(kTestAlphaURL), kImageType));
+ EXPECT_EQ(nullptr,
+ filter.FindMatchingUrlRule(GURL(kTestAlphaDataURI), kImageType));
+ EXPECT_NE(nullptr, filter.FindMatchingUrlRule(GURL(kTestAlphaWSURI),
+ proto::ELEMENT_TYPE_OTHER));
+ EXPECT_EQ(nullptr,
+ filter.FindMatchingUrlRule(GURL(kTestBetaURL), kImageType));
+ EXPECT_NE(nullptr,
+ filter.FindMatchingUrlRule(GURL(kTestAlphaURL), kSubdocumentType));
+ EXPECT_EQ(nullptr,
+ filter.FindMatchingUrlRule(GURL(kTestBetaURL), kSubdocumentType));
+}
+
TEST_F(DocumentSubresourceFilterTest, Enabled) {
auto test_impl = [this](bool measure_performance) {
ActivationState activation_state(kEnabled);
@@ -130,4 +149,23 @@ TEST_F(DocumentSubresourceFilterTest, Enabled) {
test_impl(false /* measure_performance */);
}
+TEST_F(DocumentSubresourceFilterTest, MatchingRuleEnabled) {
+ ActivationState activation_state(kEnabled);
+ activation_state.measure_performance = false;
+ DocumentSubresourceFilter filter(url::Origin(), activation_state, ruleset());
+
+ EXPECT_NE(nullptr,
+ filter.FindMatchingUrlRule(GURL(kTestAlphaURL), kImageType));
+ EXPECT_EQ(nullptr,
+ filter.FindMatchingUrlRule(GURL(kTestAlphaDataURI), kImageType));
+ EXPECT_NE(nullptr, filter.FindMatchingUrlRule(GURL(kTestAlphaWSURI),
+ proto::ELEMENT_TYPE_OTHER));
+ EXPECT_EQ(nullptr,
+ filter.FindMatchingUrlRule(GURL(kTestBetaURL), kImageType));
+ EXPECT_NE(nullptr,
+ filter.FindMatchingUrlRule(GURL(kTestAlphaURL), kSubdocumentType));
+ EXPECT_EQ(nullptr,
+ filter.FindMatchingUrlRule(GURL(kTestBetaURL), kSubdocumentType));
+}
+
} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/core/common/indexed_ruleset.cc b/chromium/components/subresource_filter/core/common/indexed_ruleset.cc
index 9378b0623ad..3fab20bda5b 100644
--- a/chromium/components/subresource_filter/core/common/indexed_ruleset.cc
+++ b/chromium/components/subresource_filter/core/common/indexed_ruleset.cc
@@ -94,15 +94,32 @@ bool IndexedRulesetMatcher::ShouldDisallowResourceLoad(
const FirstPartyOrigin& first_party,
proto::ElementType element_type,
bool disable_generic_rules) const {
+ const url_pattern_index::flat::UrlRule* rule =
+ MatchedUrlRule(url, first_party, element_type, disable_generic_rules);
+ return rule &&
+ !(rule->options() & url_pattern_index::flat::OptionFlag_IS_WHITELIST);
+}
+
+const url_pattern_index::flat::UrlRule* IndexedRulesetMatcher::MatchedUrlRule(
+ const GURL& url,
+ const FirstPartyOrigin& first_party,
+ url_pattern_index::proto::ElementType element_type,
+ bool disable_generic_rules) const {
const bool is_third_party = first_party.IsThirdParty(url);
- return !!blacklist_.FindMatch(url, first_party.origin(), element_type,
- proto::ACTIVATION_TYPE_UNSPECIFIED,
- is_third_party, disable_generic_rules,
- FindRuleStrategy::kAny) &&
- !whitelist_.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* blacklist_rule =
+ blacklist_.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* whitelist_rule = nullptr;
+ if (blacklist_rule) {
+ whitelist_rule =
+ whitelist_.FindMatch(url, first_party.origin(), element_type,
+ proto::ACTIVATION_TYPE_UNSPECIFIED, is_third_party,
+ disable_generic_rules, FindRuleStrategy::kAny);
+ return whitelist_rule ? whitelist_rule : blacklist_rule;
+ }
+ return nullptr;
}
} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/core/common/indexed_ruleset.h b/chromium/components/subresource_filter/core/common/indexed_ruleset.h
index defd8023d16..6a88af37b5f 100644
--- a/chromium/components/subresource_filter/core/common/indexed_ruleset.h
+++ b/chromium/components/subresource_filter/core/common/indexed_ruleset.h
@@ -104,6 +104,15 @@ class IndexedRulesetMatcher {
url_pattern_index::proto::ElementType element_type,
bool disable_generic_rules) const;
+ // Like ShouldDisallowResourceLoad, but returns the matching rule that
+ // determines whether the request should be allowed or not. Whitelist rules
+ // override blacklist rules. If no rule matches, returns nullptr.
+ const url_pattern_index::flat::UrlRule* MatchedUrlRule(
+ const GURL& url,
+ const FirstPartyOrigin& first_party,
+ url_pattern_index::proto::ElementType element_type,
+ bool disable_generic_rules) const;
+
private:
const flat::IndexedRuleset* root_;
diff --git a/chromium/components/subresource_filter/core/common/indexed_ruleset_unittest.cc b/chromium/components/subresource_filter/core/common/indexed_ruleset_unittest.cc
index e51a1404891..4ca98c09e6f 100644
--- a/chromium/components/subresource_filter/core/common/indexed_ruleset_unittest.cc
+++ b/chromium/components/subresource_filter/core/common/indexed_ruleset_unittest.cc
@@ -39,6 +39,16 @@ class SubresourceFilterIndexedRulesetTest : public ::testing::Test {
element_type, disable_generic_rules);
}
+ bool MatchingRule(base::StringPiece url,
+ base::StringPiece document_origin = nullptr,
+ proto::ElementType element_type = testing::kOther,
+ bool disable_generic_rules = false) const {
+ DCHECK(matcher_);
+ return matcher_->MatchedUrlRule(
+ GURL(url), FirstPartyOrigin(testing::GetOrigin(document_origin)),
+ element_type, disable_generic_rules) != nullptr;
+ }
+
bool ShouldDeactivate(
base::StringPiece document_url,
base::StringPiece parent_document_origin = nullptr,
@@ -128,7 +138,7 @@ TEST_F(SubresourceFilterIndexedRulesetTest, SimpleBlacklistAndWhitelist) {
Finish();
EXPECT_FALSE(ShouldAllow("http://blacklisted.com?filter=on"));
- EXPECT_TRUE(ShouldAllow("https://whitelisted.com?filter=on"));
+ EXPECT_TRUE(ShouldAllow("https://whitelisted.com/?filter=on"));
EXPECT_TRUE(ShouldAllow("https://notblacklisted.com"));
}
@@ -146,4 +156,55 @@ TEST_F(SubresourceFilterIndexedRulesetTest,
EXPECT_TRUE(ShouldAllow("https://xample.com"));
}
+TEST_F(SubresourceFilterIndexedRulesetTest, MatchingEmptyRuleset) {
+ Finish();
+ EXPECT_FALSE(MatchingRule(nullptr));
+ EXPECT_FALSE(MatchingRule("http://example.com"));
+ EXPECT_FALSE(MatchingRule("http://another.example.com?param=val"));
+}
+
+TEST_F(SubresourceFilterIndexedRulesetTest, MatchingNoRuleApplies) {
+ ASSERT_TRUE(AddSimpleRule("?filter_out="));
+ ASSERT_TRUE(AddSimpleRule("&filter_out="));
+ Finish();
+
+ EXPECT_FALSE(MatchingRule("http://example.com"));
+ EXPECT_FALSE(MatchingRule("http://example.com?filter_not"));
+}
+
+TEST_F(SubresourceFilterIndexedRulesetTest, MatchingSimpleBlacklist) {
+ ASSERT_TRUE(AddSimpleRule("?param="));
+ Finish();
+
+ EXPECT_FALSE(MatchingRule("https://example.com"));
+ EXPECT_TRUE(MatchingRule("http://example.org?param=image1"));
+}
+
+TEST_F(SubresourceFilterIndexedRulesetTest, MatchingSimpleWhitelist) {
+ ASSERT_TRUE(AddSimpleWhitelistRule("example.com/?filter_out="));
+ Finish();
+
+ EXPECT_FALSE(MatchingRule("https://example.com?filter_out=true"));
+}
+
+TEST_F(SubresourceFilterIndexedRulesetTest,
+ MatchingSimpleBlacklistAndWhitelist) {
+ ASSERT_TRUE(AddSimpleRule("?filter="));
+ ASSERT_TRUE(AddSimpleWhitelistRule("whitelisted.com/?filter="));
+ Finish();
+
+ EXPECT_TRUE(MatchingRule("http://blacklisted.com?filter=on"));
+ EXPECT_TRUE(MatchingRule("https://whitelisted.com?filter=on"));
+ EXPECT_FALSE(MatchingRule("https://notblacklisted.com"));
+}
+
+TEST_F(SubresourceFilterIndexedRulesetTest,
+ MatchingOneBlacklistAndOneDeactivationRule) {
+ ASSERT_TRUE(AddSimpleRule("example.com"));
+ ASSERT_TRUE(AddSimpleWhitelistRule("example.com", testing::kDocument));
+ Finish();
+ EXPECT_TRUE(MatchingRule("https://example.com"));
+ EXPECT_FALSE(MatchingRule("https://xample.com"));
+}
+
} // namespace subresource_filter
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 9ea5f663371..644f8bf79ee 100644
--- a/chromium/components/subresource_filter/core/common/test_ruleset_utils.cc
+++ b/chromium/components/subresource_filter/core/common/test_ruleset_utils.cc
@@ -4,6 +4,8 @@
#include "components/subresource_filter/core/common/test_ruleset_utils.h"
+#include <utility>
+
namespace subresource_filter {
namespace testing {
@@ -21,6 +23,18 @@ proto::UrlRule CreateSuffixRule(base::StringPiece suffix) {
return rule;
}
+proto::UrlRule CreateWhitelistSuffixRule(base::StringPiece suffix) {
+ proto::UrlRule rule;
+ rule.set_semantics(proto::RULE_SEMANTICS_WHITELIST);
+ rule.set_source_type(proto::SOURCE_TYPE_ANY);
+ rule.set_element_types(proto::ELEMENT_TYPE_ALL);
+ 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());
+ return rule;
+}
+
proto::UrlRule CreateWhitelistRuleForDocument(
base::StringPiece pattern,
int32_t activation_types,
diff --git a/chromium/components/subresource_filter/core/common/test_ruleset_utils.h b/chromium/components/subresource_filter/core/common/test_ruleset_utils.h
index 5c001c90b55..3c137c22709 100644
--- a/chromium/components/subresource_filter/core/common/test_ruleset_utils.h
+++ b/chromium/components/subresource_filter/core/common/test_ruleset_utils.h
@@ -19,6 +19,11 @@ namespace testing {
// the resource URL ends with |suffix|.
url_pattern_index::proto::UrlRule CreateSuffixRule(base::StringPiece suffix);
+// Creates a white URL rule which targets subresources of any type such that
+// the resource URL ends with |suffix|.
+url_pattern_index::proto::UrlRule CreateWhitelistSuffixRule(
+ base::StringPiece suffix);
+
// Same as CreateUrlRule(pattern, proto::URL_PATTERN_TYPE_WILDCARDED), but the
// rule applies to the specified |activation_types|, and to no element types.
// Additionally, it is restricted to a set of |domains| (if provided).
diff --git a/chromium/components/subresource_filter/core/common/tools/filter_tool.cc b/chromium/components/subresource_filter/core/common/tools/filter_tool.cc
new file mode 100644
index 00000000000..9862813fc9e
--- /dev/null
+++ b/chromium/components/subresource_filter/core/common/tools/filter_tool.cc
@@ -0,0 +1,187 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/subresource_filter/core/common/tools/filter_tool.h"
+
+#include <istream>
+#include <ostream>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "base/strings/string_split.h"
+#include "components/subresource_filter/core/common/activation_level.h"
+#include "components/subresource_filter/core/common/activation_state.h"
+#include "components/subresource_filter/core/common/document_subresource_filter.h"
+#include "components/subresource_filter/core/common/load_policy.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/url_rule_util.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace subresource_filter {
+
+namespace {
+
+url::Origin ParseOrigin(base::StringPiece arg) {
+ GURL origin_url(arg);
+ LOG_IF(FATAL, !origin_url.is_valid()) << "Invalid origin";
+ return url::Origin::Create(origin_url);
+}
+
+GURL ParseRequestUrl(base::StringPiece arg) {
+ GURL request_url(arg);
+ LOG_IF(FATAL, !request_url.is_valid());
+ return request_url;
+}
+
+url_pattern_index::proto::ElementType ParseType(base::StringPiece type) {
+ // If the user provided a resource type, use it. Else if it's the empty string
+ // it will default to ELEMENT_TYPE_OTHER.
+ if (type == "other")
+ return url_pattern_index::proto::ELEMENT_TYPE_OTHER;
+ if (type == "script")
+ return url_pattern_index::proto::ELEMENT_TYPE_SCRIPT;
+ if (type == "image")
+ return url_pattern_index::proto::ELEMENT_TYPE_IMAGE;
+ if (type == "stylesheet")
+ return url_pattern_index::proto::ELEMENT_TYPE_STYLESHEET;
+ if (type == "object")
+ return url_pattern_index::proto::ELEMENT_TYPE_OBJECT;
+ if (type == "xmlhttprequest")
+ return url_pattern_index::proto::ELEMENT_TYPE_XMLHTTPREQUEST;
+ if (type == "object_subrequest")
+ return url_pattern_index::proto::ELEMENT_TYPE_OBJECT_SUBREQUEST;
+ if (type == "subdocument")
+ return url_pattern_index::proto::ELEMENT_TYPE_SUBDOCUMENT;
+ if (type == "ping")
+ return url_pattern_index::proto::ELEMENT_TYPE_PING;
+ if (type == "media")
+ return url_pattern_index::proto::ELEMENT_TYPE_MEDIA;
+ if (type == "font")
+ return url_pattern_index::proto::ELEMENT_TYPE_FONT;
+ if (type == "popup")
+ return url_pattern_index::proto::ELEMENT_TYPE_POPUP;
+ if (type == "websocket")
+ return url_pattern_index::proto::ELEMENT_TYPE_WEBSOCKET;
+
+ return url_pattern_index::proto::ELEMENT_TYPE_OTHER;
+}
+
+const url_pattern_index::flat::UrlRule* FindMatchingUrlRule(
+ const subresource_filter::MemoryMappedRuleset* ruleset,
+ const url::Origin& document_origin,
+ const GURL& request_url,
+ url_pattern_index::proto::ElementType type) {
+ subresource_filter::DocumentSubresourceFilter filter(
+ document_origin,
+ subresource_filter::ActivationState(
+ subresource_filter::ActivationLevel::ENABLED),
+ ruleset);
+
+ return filter.FindMatchingUrlRule(request_url, type);
+}
+
+} // namespace
+
+FilterTool::FilterTool(
+ scoped_refptr<const subresource_filter::MemoryMappedRuleset> ruleset,
+ std::ostream* output)
+ : ruleset_(std::move(ruleset)), output_(output) {}
+
+FilterTool::~FilterTool() = default;
+
+void FilterTool::Match(const std::string& document_origin,
+ const std::string& url,
+ const std::string& type) {
+ bool blocked;
+ const url_pattern_index::flat::UrlRule* rule =
+ MatchImpl(document_origin, url, type, &blocked);
+ PrintResult(blocked, rule, document_origin, url, type);
+}
+
+void FilterTool::MatchBatch(std::istream* request_stream) {
+ MatchBatchImpl(request_stream, true /* print each request */, 1);
+}
+
+void FilterTool::MatchRules(std::istream* request_stream, int min_match_count) {
+ MatchBatchImpl(request_stream, false /* print each request */,
+ min_match_count);
+}
+
+void FilterTool::PrintResult(bool blocked,
+ const url_pattern_index::flat::UrlRule* rule,
+ base::StringPiece document_origin,
+ base::StringPiece url,
+ base::StringPiece type) {
+ *output_ << (blocked ? "BLOCKED " : "ALLOWED ");
+ if (rule) {
+ *output_ << url_pattern_index::FlatUrlRuleToString(rule) << " ";
+ }
+ *output_ << document_origin << " " << url << " " << type << std::endl;
+}
+
+const url_pattern_index::flat::UrlRule* FilterTool::MatchImpl(
+ base::StringPiece document_origin,
+ base::StringPiece url,
+ base::StringPiece type,
+ bool* blocked) {
+ const url_pattern_index::flat::UrlRule* rule =
+ FindMatchingUrlRule(ruleset_.get(), ParseOrigin(document_origin),
+ ParseRequestUrl(url), ParseType(type));
+
+ *blocked = rule && !(rule->options() &
+ url_pattern_index::flat::OptionFlag_IS_WHITELIST);
+ return rule;
+}
+
+// If |print_each_request| is true, then the result of each match is written
+// to |output_|, just as in Match. Otherwise, the set of matching rules is
+// written to |output_|.
+void FilterTool::MatchBatchImpl(std::istream* request_stream,
+ bool print_each_request,
+ int min_match_count) {
+ std::unordered_map<const url_pattern_index::flat::UrlRule*, int>
+ matched_rules;
+
+ std::string line;
+ while (std::getline(*request_stream, line)) {
+ if (line.empty())
+ continue;
+
+ std::vector<base::StringPiece> strings = base::SplitStringPiece(
+ line, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+ LOG_IF(FATAL, strings.size() != 3u)
+ << "Incorrect number of arguments found in batch record";
+
+ base::StringPiece origin = strings[0];
+ base::StringPiece request_url = strings[1];
+ base::StringPiece request_type = strings[2];
+
+ bool blocked;
+ const url_pattern_index::flat::UrlRule* rule =
+ MatchImpl(origin, request_url, request_type, &blocked);
+ if (rule)
+ matched_rules[rule] += 1;
+
+ if (print_each_request)
+ PrintResult(blocked, rule, origin, request_url, request_type);
+ }
+
+ if (print_each_request)
+ return;
+
+ for (auto rule_and_count : matched_rules) {
+ if (rule_and_count.second >= min_match_count) {
+ *output_ << url_pattern_index::FlatUrlRuleToString(rule_and_count.first)
+ .c_str()
+ << std::endl;
+ }
+ }
+}
+
+} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/core/common/tools/filter_tool.h b/chromium/components/subresource_filter/core/common/tools/filter_tool.h
new file mode 100644
index 00000000000..f762df07a43
--- /dev/null
+++ b/chromium/components/subresource_filter/core/common/tools/filter_tool.h
@@ -0,0 +1,82 @@
+// Copyright 2018 The Chromium Authors. All 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_CORE_COMMON_TOOLS_FILTER_TOOL_H_
+#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TOOLS_FILTER_TOOL_H_
+
+#include <istream>
+#include <ostream>
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/strings/string_piece.h"
+#include "components/subresource_filter/core/common/memory_mapped_ruleset.h"
+
+namespace url_pattern_index {
+namespace flat {
+struct UrlRule;
+}
+} // namespace url_pattern_index
+
+namespace subresource_filter {
+
+// FilterTool provides utility functions for matching a given ruleset against
+// requests and writes the results to an output stream.
+class FilterTool {
+ public:
+ // |output| must outlive this object.
+ FilterTool(
+ scoped_refptr<const subresource_filter::MemoryMappedRuleset> ruleset,
+ std::ostream* output);
+ ~FilterTool();
+
+ // Checks the ruleset for a request with document origin |document_origin|,
+ // sub-resource request |url|, and |type|. If a blacklist rule matches the
+ // request, it is considered the match. If multiple blacklist rules match,
+ // one is arbitrarily chosen as the match. If a blacklist rule matches and a
+ // whitelist rule matches, a whitelist rule is the match. The output is
+ // written to |output_| in a space- delimited line. The first column is
+ // either BLOCKED or ALLOWED. The second is any matching rule. The following
+ // columns are the input arguments.
+ void Match(const std::string& document_origin,
+ const std::string& url,
+ const std::string& type);
+
+ // Like Match, but for multiple requests. The requests are provided in
+ // |request_stream| in form: "document_origin url type\n".
+ void MatchBatch(std::istream* request_stream);
+
+ // Like Match, but instead of writing the result of each request, it writes
+ // the set of matched rules to |output_|. Use |min_match_count| to filter the
+ // list of written rules to those that were matched at least |min_match_count|
+ // times.
+ void MatchRules(std::istream* request_stream, int min_match_count);
+
+ private:
+ void PrintResult(bool blocked,
+ const url_pattern_index::flat::UrlRule* rule,
+ base::StringPiece document_origin,
+ base::StringPiece url,
+ base::StringPiece type);
+
+ const url_pattern_index::flat::UrlRule* MatchImpl(
+ base::StringPiece document_origin,
+ base::StringPiece url,
+ base::StringPiece type,
+ bool* blocked);
+
+ void MatchBatchImpl(std::istream* request_stream,
+ bool print_each_request,
+ int min_match_count);
+
+ scoped_refptr<const subresource_filter::MemoryMappedRuleset> ruleset_;
+ std::ostream* output_;
+
+ DISALLOW_COPY_AND_ASSIGN(FilterTool);
+};
+
+} // namespace subresource_filter
+
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TOOLS_FILTER_TOOL_H_
diff --git a/chromium/components/subresource_filter/core/common/tools/filter_tool_main.cc b/chromium/components/subresource_filter/core/common/tools/filter_tool_main.cc
new file mode 100644
index 00000000000..0fa65830b66
--- /dev/null
+++ b/chromium/components/subresource_filter/core/common/tools/filter_tool_main.cc
@@ -0,0 +1,168 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <utility>
+
+#include "base/command_line.h"
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+
+#include "components/subresource_filter/core/common/tools/filter_tool.h"
+
+namespace {
+
+// If you change any of the switch strings, update the kHelpMsg accordingly.
+const char kSwitchRuleset[] = "ruleset";
+const char kSwitchOrigin[] = "document_origin";
+const char kSwitchUrl[] = "url";
+const char kSwitchType[] = "type";
+const char kSwitchInputFile[] = "input_file";
+const char kSwitchMinMatches[] = "min_matches";
+
+const char kMatchCommand[] = "match";
+const char kMatchRulesCommand[] = "match_rules";
+const char kMatchBatchCommand[] = "match_batch";
+
+const char kHelpMsg[] = R"(
+ subresource_filter_tool --ruleset=<indexed_ruleset_path> command
+
+ subresource_filter_tool is a utility for querying a ruleset, and provides
+ multiple commands:
+
+ * match --document-origin=<origin> --url=<request_url> --type=<request_type>
+ Prints if the request would be blocked or allowed, as well as a
+ matching ruleset rule (if one matches). The output format is:
+ <BLOCKED/ALLOWED> <UrlRule if any> <document_origin> <request_url>
+ <type>
+
+ For a given request if a whitelist rule matches as well as a blacklist
+ rule, the whitelist rule is printed but not the blacklist rule.
+
+ * match_batch --input_file=<csv_file_path>
+ Like match, except it does the same for each request in a space
+ delimited file. The file format is:
+ <document_origin> <request_url> <type>
+
+ * match_rules --input_file=<csv_file_path> --min_matches=<optional>
+ For each record in the given whitespace delimited file (see
+ match_batch for input file format), records the matching rule (see
+ match command above) and prints all of the matched rules at the end.
+
+ Which rules get recorded:
+ If only a blacklist rule(s) matches, a blacklist rule is
+ returned (chosen at random from list of matching blacklist rules). If
+ both blacklist and whitelist rules match, a whitelist rule is
+ returned. If only a whitelist rule matches, it's not recorded.
+
+ |min_matches| is the minimum number of times the rule has to be
+ matched to be included in the output. If not specified, the default is
+ 1.
+)";
+
+void PrintHelp() {
+ printf("%s\n\n", kHelpMsg);
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ base::CommandLine::Init(argc, argv);
+ base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
+
+ base::CommandLine::StringVector args = command_line.GetArgs();
+
+ if (args.size() != 1U) {
+ PrintHelp();
+ return 1;
+ }
+
+ if (!command_line.HasSwitch(kSwitchRuleset)) {
+ PrintHelp();
+ return 1;
+ }
+
+ base::File rules_file(command_line.GetSwitchValuePath(kSwitchRuleset),
+ base::File::FLAG_OPEN | base::File::FLAG_READ);
+
+ if (!rules_file.IsValid()) {
+ std::cerr << "Could not open file: "
+ << command_line.GetSwitchValueASCII(kSwitchRuleset) << std::endl;
+ PrintHelp();
+ return 1;
+ }
+
+ auto ruleset = base::MakeRefCounted<subresource_filter::MemoryMappedRuleset>(
+ std::move(rules_file));
+
+ LOG_IF(FATAL, ruleset->length() == 0u) << "Empty ruleset file";
+
+ subresource_filter::FilterTool filter_tool(std::move(ruleset), &std::cout);
+
+ std::string cmd;
+#if defined(OS_WIN)
+ cmd = base::UTF16ToASCII(args[0]);
+#else
+ cmd = args[0];
+#endif
+
+ if (cmd != kMatchCommand && cmd != kMatchRulesCommand &&
+ cmd != kMatchBatchCommand) {
+ std::cerr << "Not a recognized command " << cmd << std::endl;
+ PrintHelp();
+ return 1;
+ }
+
+ if (cmd == kMatchCommand) {
+ if (!command_line.HasSwitch(kSwitchOrigin) ||
+ !command_line.HasSwitch(kSwitchUrl) ||
+ !command_line.HasSwitch(kSwitchType)) {
+ std::cerr << "Missing argument for match command:" << std::endl;
+ PrintHelp();
+ return 1;
+ }
+
+ const std::string document_origin =
+ command_line.GetSwitchValueASCII(kSwitchOrigin);
+ const std::string url = command_line.GetSwitchValueASCII(kSwitchUrl);
+ const std::string type = command_line.GetSwitchValueASCII(kSwitchType);
+
+ filter_tool.Match(document_origin, url, type);
+
+ return 0;
+ }
+
+ int min_match_count = 0;
+ 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;
+ PrintHelp();
+ return 1;
+ }
+
+ if (!command_line.HasSwitch(kSwitchInputFile)) {
+ PrintHelp();
+ return 1;
+ }
+
+ std::ifstream requests_stream(
+ command_line.GetSwitchValueASCII(kSwitchInputFile));
+
+ if (cmd == kMatchBatchCommand) {
+ filter_tool.MatchBatch(&requests_stream);
+ } else if (cmd == kMatchRulesCommand) {
+ filter_tool.MatchRules(&requests_stream, min_match_count);
+ }
+
+ return 0;
+}
diff --git a/chromium/components/subresource_filter/core/common/tools/filter_tool_unittest.cc b/chromium/components/subresource_filter/core/common/tools/filter_tool_unittest.cc
new file mode 100644
index 00000000000..fa188810eb0
--- /dev/null
+++ b/chromium/components/subresource_filter/core/common/tools/filter_tool_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/subresource_filter/core/common/tools/filter_tool.h"
+
+#include <algorithm>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "components/subresource_filter/core/common/memory_mapped_ruleset.h"
+#include "components/subresource_filter/core/common/test_ruleset_creator.h"
+#include "components/subresource_filter/core/common/test_ruleset_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace subresource_filter {
+
+namespace proto = url_pattern_index::proto;
+
+namespace {
+
+// See if two strings contain the same lines (regardless of line ordering).
+bool StringsHaveSameLines(const std::string& a, const std::string& b) {
+ std::istringstream stream_a(a), stream_b(b);
+ std::vector<std::string> lines_a, lines_b;
+ std::string line;
+
+ while (std::getline(stream_a, line))
+ lines_a.push_back(line);
+
+ while (std::getline(stream_b, line))
+ lines_b.push_back(line);
+
+ std::sort(lines_a.begin(), lines_a.end());
+ std::sort(lines_b.begin(), lines_b.end());
+ return lines_a == lines_b;
+}
+
+class FilterToolTest : public ::testing::Test {
+ public:
+ FilterToolTest() {}
+
+ protected:
+ void SetUp() override {
+ CreateRuleset();
+ filter_tool_ = std::make_unique<FilterTool>(ruleset_, &out_stream_);
+ }
+
+ void CreateRuleset() {
+ std::vector<proto::UrlRule> rules;
+ rules.push_back(testing::CreateSuffixRule("disallowed1.png"));
+ rules.push_back(testing::CreateSuffixRule("disallowed2.png"));
+ rules.push_back(testing::CreateSuffixRule("disallowed3.png"));
+ rules.push_back(
+ testing::CreateWhitelistSuffixRule("whitelist/disallowed1.png"));
+ rules.push_back(
+ testing::CreateWhitelistSuffixRule("whitelist/disallowed2.png"));
+
+ ASSERT_NO_FATAL_FAILURE(test_ruleset_creator_.CreateRulesetWithRules(
+ rules, &test_ruleset_pair_));
+
+ ruleset_ = new MemoryMappedRuleset(
+ testing::TestRuleset::Open(test_ruleset_pair_.indexed));
+ }
+
+ testing::TestRulesetCreator test_ruleset_creator_;
+ testing::TestRulesetPair test_ruleset_pair_;
+ scoped_refptr<const MemoryMappedRuleset> ruleset_;
+ std::ostringstream out_stream_;
+ std::unique_ptr<FilterTool> filter_tool_;
+
+ DISALLOW_COPY_AND_ASSIGN(FilterToolTest);
+};
+
+TEST_F(FilterToolTest, MatchBlacklist) {
+ filter_tool_->Match("http://example.com",
+ "http://example.com/disallowed1.png", "image");
+
+ std::string expected =
+ "BLOCKED disallowed1.png| http://example.com "
+ "http://example.com/disallowed1.png "
+ "image\n";
+ EXPECT_EQ(expected, out_stream_.str());
+}
+
+TEST_F(FilterToolTest, MatchWhitelist) {
+ filter_tool_->Match("http://example.com",
+ "http://example.com/whitelist/disallowed1.png", "image");
+ std::string expected =
+ "ALLOWED @@whitelist/disallowed1.png| http://example.com "
+ "http://example.com/whitelist/disallowed1.png "
+ "image\n";
+ EXPECT_EQ(expected, out_stream_.str());
+}
+
+TEST_F(FilterToolTest, NoMatch) {
+ filter_tool_->Match("http://example.com", "http://example.com/noproblem.png",
+ "image");
+
+ std::string expected =
+ "ALLOWED http://example.com http://example.com/noproblem.png image\n";
+ EXPECT_EQ(expected, out_stream_.str());
+}
+
+TEST_F(FilterToolTest, MatchBatch) {
+ std::stringstream batch_queries;
+ batch_queries
+ << "http://example.com http://example.com/disallowed1.png image\n"
+ "http://example.com http://example.com/disallowed2.png image\n"
+ "http://example.com http://example.com/whitelist/disallowed2.png "
+ "image\n";
+
+ filter_tool_->MatchBatch(&batch_queries);
+
+ std::string expected =
+ "BLOCKED disallowed1.png| http://example.com "
+ "http://example.com/disallowed1.png image\n"
+ "BLOCKED disallowed2.png| http://example.com "
+ "http://example.com/disallowed2.png image\n"
+ "ALLOWED @@whitelist/disallowed2.png| http://example.com "
+ "http://example.com/whitelist/disallowed2.png image\n";
+
+ EXPECT_EQ(expected, out_stream_.str());
+}
+
+TEST_F(FilterToolTest, MatchRules) {
+ std::stringstream batch_queries;
+ batch_queries
+ << "http://example.com http://example.com/disallowed1.png image\n"
+ "http://example.com http://example.com/disallowed1.png image\n"
+ "http://example.com http://example.com/disallowed2.png image\n"
+ "http://example.com http://example.com/whitelist/disallowed2.png "
+ "image\n";
+
+ filter_tool_->MatchRules(&batch_queries, 1);
+
+ std::string result = out_stream_.str();
+
+ std::string expected =
+ "disallowed1.png|\n"
+ "disallowed2.png|\n"
+ "@@whitelist/disallowed2.png|\n";
+
+ EXPECT_TRUE(StringsHaveSameLines(expected, out_stream_.str()));
+}
+
+TEST_F(FilterToolTest, MatchRulesMinCount) {
+ std::stringstream batch_queries;
+ batch_queries
+ << "http://example.com http://example.com/disallowed1.png image\n"
+ "http://example.com http://example.com/disallowed1.png image\n"
+ "http://example.com http://example.com/disallowed2.png image\n"
+ "http://example.com http://example.com/whitelist/disallowed2.png "
+ "image\n"
+ "http://example.com http://example.com/whitelist/disallowed2.png "
+ "image\n"
+ "http://example.com http://example.com/whitelist/disallowed2.png "
+ "image\n";
+
+ filter_tool_->MatchRules(&batch_queries, 2);
+
+ std::string expected =
+ "disallowed1.png|\n"
+ "@@whitelist/disallowed2.png|\n";
+
+ EXPECT_TRUE(StringsHaveSameLines(expected, out_stream_.str()));
+}
+
+} // namespace
+
+} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/core/common/tools/indexing_tool.cc b/chromium/components/subresource_filter/core/common/tools/indexing_tool.cc
new file mode 100644
index 00000000000..832a5728852
--- /dev/null
+++ b/chromium/components/subresource_filter/core/common/tools/indexing_tool.cc
@@ -0,0 +1,53 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/subresource_filter/core/common/tools/indexing_tool.h"
+
+#include <utility>
+
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/numerics/safe_conversions.h"
+#include "components/subresource_filter/core/common/indexed_ruleset.h"
+#include "components/url_pattern_index/copying_file_stream.h"
+#include "components/url_pattern_index/proto/rules.pb.h"
+#include "components/url_pattern_index/unindexed_ruleset.h"
+
+namespace subresource_filter {
+
+bool IndexAndWriteRuleset(const base::FilePath& unindexed_path,
+ const base::FilePath& indexed_path) {
+ if (!base::PathExists(unindexed_path) ||
+ !base::DirectoryExists(indexed_path.DirName())) {
+ return false;
+ }
+
+ base::File unindexed_file(unindexed_path,
+ base::File::FLAG_OPEN | base::File::FLAG_READ);
+
+ subresource_filter::RulesetIndexer indexer;
+
+ url_pattern_index::CopyingFileInputStream copying_stream(
+ std::move(unindexed_file));
+ google::protobuf::io::CopyingInputStreamAdaptor zero_copy_stream_adaptor(
+ &copying_stream, 4096 /* buffer_size */);
+ url_pattern_index::UnindexedRulesetReader reader(&zero_copy_stream_adaptor);
+
+ url_pattern_index::proto::FilteringRules ruleset_chunk;
+
+ while (reader.ReadNextChunk(&ruleset_chunk)) {
+ for (const auto& rule : ruleset_chunk.url_rules()) {
+ indexer.AddUrlRule(rule);
+ }
+ }
+
+ indexer.Finish();
+
+ base::WriteFile(indexed_path, reinterpret_cast<const char*>(indexer.data()),
+ base::checked_cast<int>(indexer.size()));
+
+ return true;
+}
+
+} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/core/common/tools/indexing_tool.h b/chromium/components/subresource_filter/core/common/tools/indexing_tool.h
new file mode 100644
index 00000000000..3dbade98898
--- /dev/null
+++ b/chromium/components/subresource_filter/core/common/tools/indexing_tool.h
@@ -0,0 +1,21 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TOOLS_INDEXING_TOOL_H_
+#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TOOLS_INDEXING_TOOL_H_
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+
+namespace subresource_filter {
+
+// Given |unindexed_path|, which is a path to an unindexed ruleset, writes the
+// indexed (flatbuffer) version to |indexed_path|. Returns false if there was
+// something wrong with the given paths.
+bool IndexAndWriteRuleset(const base::FilePath& unindexed_path,
+ const base::FilePath& indexed_path);
+
+} // namespace subresource_filter
+
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TOOLS_INDEXING_TOOL_H_
diff --git a/chromium/components/subresource_filter/core/common/tools/indexing_tool_main.cc b/chromium/components/subresource_filter/core/common/tools/indexing_tool_main.cc
new file mode 100644
index 00000000000..2d335d529c4
--- /dev/null
+++ b/chromium/components/subresource_filter/core/common/tools/indexing_tool_main.cc
@@ -0,0 +1,41 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "components/subresource_filter/core/common/tools/indexing_tool.h"
+
+const char kHelpMsg[] = R"(
+ subresource_indexing_tool <unindexed_ruleset_file> <output_file>
+
+ subresource_indexing_tool will open the |unindexed_ruleset_file| and output
+ an indexed version in |output_file|.
+)";
+
+void PrintHelp() {
+ printf("%s\n\n", kHelpMsg);
+}
+
+int main(int argc, char* argv[]) {
+ base::CommandLine::Init(argc, argv);
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ base::CommandLine::StringVector args = command_line.GetArgs();
+
+ if (args.size() < 2U) {
+ PrintHelp();
+ return 1;
+ }
+
+ base::FilePath unindexed_path(args[0]);
+ base::FilePath indexed_path(args[1]);
+
+ if (!subresource_filter::IndexAndWriteRuleset(unindexed_path, indexed_path)) {
+ LOG(ERROR) << "There was an error. Be sure that the first argument points "
+ "to a valid unindexed file and that the second argument is "
+ "in an existing directory.";
+ }
+}
diff --git a/chromium/components/subresource_filter/core/common/tools/indexing_tool_unittest.cc b/chromium/components/subresource_filter/core/common/tools/indexing_tool_unittest.cc
new file mode 100644
index 00000000000..807f4d9446d
--- /dev/null
+++ b/chromium/components/subresource_filter/core/common/tools/indexing_tool_unittest.cc
@@ -0,0 +1,117 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/subresource_filter/core/common/tools/indexing_tool.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/string_number_conversions.h"
+#include "components/subresource_filter/core/common/test_ruleset_creator.h"
+#include "components/subresource_filter/core/common/test_ruleset_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace subresource_filter {
+
+namespace proto = url_pattern_index::proto;
+
+namespace {
+
+std::vector<uint8_t> ReadFileContents(const base::FilePath& file_path) {
+ base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+
+ size_t length = base::checked_cast<size_t>(file.GetLength());
+ std::vector<uint8_t> contents(length);
+ static_assert(sizeof(uint8_t) == sizeof(char), "Expected char = byte.");
+ file.Read(0, reinterpret_cast<char*>(contents.data()),
+ base::checked_cast<int>(length));
+ return contents;
+}
+
+class IndexingToolTest : public ::testing::Test {
+ public:
+ IndexingToolTest() {}
+
+ protected:
+ void SetUp() override { ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); }
+
+ base::FilePath GetUniquePath() {
+ base::FilePath path = scoped_temp_dir_.GetPath().AppendASCII(
+ base::IntToString(file_count_++));
+ return path;
+ }
+
+ void CreateSimpleRuleset() {
+ std::vector<proto::UrlRule> rules;
+ rules.push_back(testing::CreateSuffixRule("disallowed1.png"));
+ rules.push_back(testing::CreateSuffixRule("disallowed2.png"));
+ rules.push_back(testing::CreateSuffixRule("disallowed3.png"));
+ rules.push_back(
+ testing::CreateWhitelistSuffixRule("whitelist/disallowed1.png"));
+ rules.push_back(
+ testing::CreateWhitelistSuffixRule("whitelist/disallowed2.png"));
+
+ ASSERT_NO_FATAL_FAILURE(test_ruleset_creator_.CreateRulesetWithRules(
+ rules, &test_ruleset_pair_));
+ }
+
+ void WriteUnindexedRulesetToFile(const base::FilePath& path) {
+ // Write the test unindexed data to a file.
+ const std::vector<uint8_t>& unindexed_data =
+ test_ruleset_pair_.unindexed.contents;
+ base::WriteFile(path, reinterpret_cast<const char*>(unindexed_data.data()),
+ base::checked_cast<int>(unindexed_data.size()));
+ }
+
+ int file_count_ = 0;
+ base::ScopedTempDir scoped_temp_dir_;
+ testing::TestRulesetCreator test_ruleset_creator_;
+ testing::TestRulesetPair test_ruleset_pair_;
+
+ DISALLOW_COPY_AND_ASSIGN(IndexingToolTest);
+};
+
+TEST_F(IndexingToolTest, UnindexedFileDoesNotExist) {
+ // There is no file at the unindexed position, so it should return false.
+ EXPECT_FALSE(IndexAndWriteRuleset(GetUniquePath(), GetUniquePath()));
+}
+
+TEST_F(IndexingToolTest, IndexedDirectoryDoesNotExist) {
+ // Create a valid unindexed file.
+ base::FilePath unindexed_path = GetUniquePath();
+ CreateSimpleRuleset();
+ WriteUnindexedRulesetToFile(unindexed_path);
+
+ // The indexed path is in a non-existant directory.
+ base::FilePath indexed_path =
+ scoped_temp_dir_.GetPath().AppendASCII("foo/bar");
+
+ // This should fail because the directory for indexed_path doesn't exist.
+ EXPECT_FALSE(IndexAndWriteRuleset(unindexed_path, indexed_path));
+}
+
+TEST_F(IndexingToolTest, VerifyOutput) {
+ base::FilePath unindexed_path = GetUniquePath();
+ base::FilePath indexed_path = GetUniquePath();
+
+ CreateSimpleRuleset();
+ WriteUnindexedRulesetToFile(unindexed_path);
+
+ // Convert the unindexed data to indexed data, and write the result to
+ // indexed_path.
+ EXPECT_TRUE(IndexAndWriteRuleset(unindexed_path, indexed_path));
+
+ // Verify that the output equals the test indexed data.
+ std::vector<uint8_t> indexed_data = ReadFileContents(indexed_path);
+ EXPECT_EQ(test_ruleset_pair_.indexed.contents, indexed_data);
+}
+
+} // namespace
+
+} // namespace subresource_filter
diff --git a/chromium/components/suggestions/image_encoder_ios.mm b/chromium/components/suggestions/image_encoder_ios.mm
index d182926bb82..716c1c3c5d7 100644
--- a/chromium/components/suggestions/image_encoder_ios.mm
+++ b/chromium/components/suggestions/image_encoder_ios.mm
@@ -7,8 +7,9 @@
#include <stddef.h>
#import <UIKit/UIKit.h>
+#include <memory>
+
#include "base/mac/scoped_cftyperef.h"
-#include "base/memory/ptr_util.h"
#include "skia/ext/skia_utils_ios.h"
namespace suggestions {
@@ -17,7 +18,7 @@ std::unique_ptr<SkBitmap> DecodeJPEGToSkBitmap(const void* encoded_data,
size_t size) {
NSData* data = [NSData dataWithBytes:encoded_data length:size];
UIImage* image = [UIImage imageWithData:data scale:1.0];
- return base::MakeUnique<SkBitmap>(
+ return std::make_unique<SkBitmap>(
skia::CGImageToSkBitmap(image.CGImage, [image size], YES));
}
diff --git a/chromium/components/suggestions/image_manager.cc b/chromium/components/suggestions/image_manager.cc
index 27e2b190e1c..58db8e2e659 100644
--- a/chromium/components/suggestions/image_manager.cc
+++ b/chromium/components/suggestions/image_manager.cc
@@ -157,20 +157,22 @@ bool ImageManager::GetImageURL(const GURL& url, GURL* image_url) {
return true;
}
-void ImageManager::QueueCacheRequest(
- const GURL& url, const GURL& image_url, ImageCallback callback) {
+void ImageManager::QueueCacheRequest(const GURL& url,
+ const GURL& image_url,
+ ImageCallback callback) {
// To be served when the database has loaded.
ImageCacheRequestMap::iterator it = pending_cache_requests_.find(url);
- if (it == pending_cache_requests_.end()) {
- ImageCacheRequest request;
- request.url = url;
- request.image_url = image_url;
- request.callbacks.push_back(callback);
- pending_cache_requests_[url] = request;
- } else {
+ if (it != pending_cache_requests_.end()) {
// Request already queued for this url.
it->second.callbacks.push_back(callback);
+ return;
}
+
+ ImageCacheRequest request;
+ request.url = url;
+ request.image_url = image_url;
+ request.callbacks.push_back(callback);
+ pending_cache_requests_[url] = request;
}
void ImageManager::OnCacheImageDecoded(
@@ -298,6 +300,7 @@ void ImageManager::ServePendingCacheRequests() {
ServeFromCacheOrNetwork(request.url, request.image_url, *callback_it);
}
}
+ pending_cache_requests_.clear();
}
} // namespace suggestions
diff --git a/chromium/components/suggestions/image_manager.h b/chromium/components/suggestions/image_manager.h
index 04ffc002b77..b48f14da560 100644
--- a/chromium/components/suggestions/image_manager.h
+++ b/chromium/components/suggestions/image_manager.h
@@ -72,6 +72,7 @@ class ImageManager : public image_fetcher::ImageFetcherDelegate {
FRIEND_TEST_ALL_PREFIXES(ImageManagerTest, GetImageForURLNetworkCacheHit);
FRIEND_TEST_ALL_PREFIXES(ImageManagerTest,
GetImageForURLNetworkCacheNotInitialized);
+ FRIEND_TEST_ALL_PREFIXES(ImageManagerTest, QueueImageRequest);
// Used for testing.
ImageManager();
@@ -101,8 +102,9 @@ class ImageManager : public image_fetcher::ImageFetcherDelegate {
// and returns true. Otherwise just returns false.
bool GetImageURL(const GURL& url, GURL* image_url);
- void QueueCacheRequest(
- const GURL& url, const GURL& image_url, ImageCallback callback);
+ void QueueCacheRequest(const GURL& url,
+ const GURL& image_url,
+ ImageCallback callback);
void ServeFromCacheOrNetwork(
const GURL& url, const GURL& image_url, ImageCallback callback);
diff --git a/chromium/components/suggestions/image_manager_unittest.cc b/chromium/components/suggestions/image_manager_unittest.cc
index d37a59201e6..e7afb374fdb 100644
--- a/chromium/components/suggestions/image_manager_unittest.cc
+++ b/chromium/components/suggestions/image_manager_unittest.cc
@@ -224,4 +224,44 @@ TEST_F(ImageManagerTest, GetImageForURLNetworkCacheHit) {
EXPECT_EQ(1, num_callback_valid_called_);
}
+TEST_F(ImageManagerTest, QueueImageRequest) {
+ SuggestionsProfile suggestions_profile;
+ ChromeSuggestion* suggestion = suggestions_profile.add_suggestions();
+ suggestion->set_url(kTestUrl1);
+ // The URL we set is invalid, to show that it will fail from network.
+ suggestion->set_thumbnail(kInvalidImagePath);
+
+ // Create the ImageManager with an added entry in the database.
+ AddEntry(GetSampleImageData(kTestUrl1), &db_model_);
+ FakeDB<ImageData>* fake_db = new FakeDB<ImageData>(&db_model_);
+ image_manager_.reset(CreateImageManager(fake_db));
+ image_manager_->Initialize(suggestions_profile);
+
+ base::RunLoop run_loop1;
+ base::RunLoop run_loop2;
+ image_manager_->GetImageForURL(
+ GURL(kTestUrl1), base::BindRepeating(&ImageManagerTest::OnImageAvailable,
+ base::Unretained(this), &run_loop1));
+ image_manager_->GetImageForURL(
+ GURL(kTestUrl1), base::BindRepeating(&ImageManagerTest::OnImageAvailable,
+ base::Unretained(this), &run_loop2));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(0, num_callback_null_called_);
+ EXPECT_EQ(0, num_callback_valid_called_);
+ EXPECT_EQ(1u, image_manager_->pending_cache_requests_.size());
+ EXPECT_EQ(
+ 2u,
+ image_manager_->pending_cache_requests_.begin()->second.callbacks.size());
+
+ fake_db->InitCallback(true);
+ fake_db->LoadCallback(true);
+ run_loop1.Run();
+ run_loop2.Run();
+
+ EXPECT_EQ(0, num_callback_null_called_);
+ EXPECT_EQ(2, num_callback_valid_called_);
+ EXPECT_EQ(0u, image_manager_->pending_cache_requests_.size());
+}
+
} // namespace suggestions
diff --git a/chromium/components/suggestions/suggestions_service_impl_unittest.cc b/chromium/components/suggestions/suggestions_service_impl_unittest.cc
index 077428bcfae..8e88e9f5577 100644
--- a/chromium/components/suggestions/suggestions_service_impl_unittest.cc
+++ b/chromium/components/suggestions/suggestions_service_impl_unittest.cc
@@ -44,9 +44,7 @@ using testing::StrictMock;
namespace {
-const char kGaiaId[] = "foo_gaia";
const char kEmail[] = "foo_email";
-const char kRefreshToken[] = "foo_token";
const char kSuggestionsUrlPath[] = "/chromesuggestions";
const char kBlacklistUrlPath[] = "/chromesuggestions/blacklist";
const char kBlacklistClearUrlPath[] = "/chromesuggestions/blacklist/clear";
@@ -143,8 +141,7 @@ class SuggestionsServiceTest : public testing::Test {
mock_thumbnail_manager_(nullptr),
mock_blacklist_store_(nullptr),
test_suggestions_store_(nullptr) {
- identity_test_env_.MakePrimaryAccountAvailable(kGaiaId, kEmail,
- kRefreshToken);
+ identity_test_env_.MakePrimaryAccountAvailable(kEmail);
identity_test_env_.SetAutomaticIssueOfAccessTokens(true);
}
diff --git a/chromium/components/sync/BUILD.gn b/chromium/components/sync/BUILD.gn
index a1ec9be133e..a6a75a2ba1b 100644
--- a/chromium/components/sync/BUILD.gn
+++ b/chromium/components/sync/BUILD.gn
@@ -10,8 +10,6 @@ import("//testing/test.gni")
jumbo_static_library("sync") {
sources = [
- "base/attachment_id_proto.cc",
- "base/attachment_id_proto.h",
"base/bind_to_task_runner.h",
"base/cancelation_observer.cc",
"base/cancelation_observer.h",
@@ -159,24 +157,6 @@ jumbo_static_library("sync") {
"driver/user_selectable_sync_type.h",
"engine/activation_context.cc",
"engine/activation_context.h",
- "engine/attachments/attachment_downloader.cc",
- "engine/attachments/attachment_downloader.h",
- "engine/attachments/attachment_store_backend.cc",
- "engine/attachments/attachment_store_backend.h",
- "engine/attachments/attachment_store_frontend.cc",
- "engine/attachments/attachment_store_frontend.h",
- "engine/attachments/attachment_uploader.cc",
- "engine/attachments/attachment_uploader.h",
- "engine/attachments/attachment_util.cc",
- "engine/attachments/attachment_util.h",
- "engine/attachments/fake_attachment_downloader.cc",
- "engine/attachments/fake_attachment_downloader.h",
- "engine/attachments/fake_attachment_uploader.cc",
- "engine/attachments/fake_attachment_uploader.h",
- "engine/attachments/in_memory_attachment_store.cc",
- "engine/attachments/in_memory_attachment_store.h",
- "engine/attachments/on_disk_attachment_store.cc",
- "engine/attachments/on_disk_attachment_store.h",
"engine/commit_queue.cc",
"engine/commit_queue.h",
"engine/configure_reason.h",
@@ -254,10 +234,6 @@ jumbo_static_library("sync") {
"engine_impl/all_status.h",
"engine_impl/apply_control_data_updates.cc",
"engine_impl/apply_control_data_updates.h",
- "engine_impl/attachments/attachment_downloader_impl.cc",
- "engine_impl/attachments/attachment_downloader_impl.h",
- "engine_impl/attachments/attachment_uploader_impl.cc",
- "engine_impl/attachments/attachment_uploader_impl.h",
"engine_impl/backoff_delay_provider.cc",
"engine_impl/backoff_delay_provider.h",
"engine_impl/clear_server_data.cc",
@@ -401,20 +377,6 @@ jumbo_static_library("sync") {
"js/js_event_handler.h",
"js/sync_js_controller.cc",
"js/sync_js_controller.h",
- "model/attachments/attachment.cc",
- "model/attachments/attachment.h",
- "model/attachments/attachment_id.cc",
- "model/attachments/attachment_id.h",
- "model/attachments/attachment_metadata.cc",
- "model/attachments/attachment_metadata.h",
- "model/attachments/attachment_service.cc",
- "model/attachments/attachment_service.h",
- "model/attachments/attachment_service_proxy.cc",
- "model/attachments/attachment_service_proxy.h",
- "model/attachments/attachment_service_proxy_for_test.cc",
- "model/attachments/attachment_service_proxy_for_test.h",
- "model/attachments/attachment_store.cc",
- "model/attachments/attachment_store.h",
"model/change_processor.cc",
"model/change_processor.h",
"model/conflict_resolution.cc",
@@ -462,9 +424,6 @@ jumbo_static_library("sync") {
"model/time.h",
"model_impl/accumulating_metadata_change_list.cc",
"model_impl/accumulating_metadata_change_list.h",
- "model_impl/attachments/attachment_service_impl.cc",
- "model_impl/attachments/attachment_service_impl.h",
- "model_impl/attachments/task_queue.h",
"model_impl/in_memory_metadata_change_list.cc",
"model_impl/in_memory_metadata_change_list.h",
"model_impl/model_type_store_backend.cc",
@@ -599,10 +558,9 @@ jumbo_static_library("sync") {
"//components/os_crypt",
"//components/pref_registry",
"//components/prefs",
- "//components/reading_list/features:reading_list_enable_flags",
+ "//components/reading_list/features:reading_list_buildflags",
"//components/signin/core/browser",
"//components/strings",
- "//components/sync/engine_impl/attachments/proto",
"//components/variations",
"//components/version_info",
"//crypto",
@@ -838,7 +796,6 @@ static_library("test_support_driver") {
source_set("unit_tests") {
testonly = true
sources = [
- "base/attachment_id_proto_unittest.cc",
"base/bind_to_task_runner_unittest.cc",
"base/cancelation_signal_unittest.cc",
"base/cryptographer_unittest.cc",
@@ -873,12 +830,6 @@ source_set("unit_tests") {
"driver/startup_controller_unittest.cc",
"driver/sync_stopped_reporter_unittest.cc",
"driver/sync_util_unittest.cc",
- "engine/attachments/attachment_store_frontend_unittest.cc",
- "engine/attachments/attachment_store_test_template.h",
- "engine/attachments/fake_attachment_downloader_unittest.cc",
- "engine/attachments/fake_attachment_uploader_unittest.cc",
- "engine/attachments/in_memory_attachment_store_unittest.cc",
- "engine/attachments/on_disk_attachment_store_unittest.cc",
"engine/cycle/sync_cycle_snapshot_unittest.cc",
"engine/model_safe_worker_unittest.cc",
"engine/net/http_bridge_unittest.cc",
@@ -886,8 +837,6 @@ source_set("unit_tests") {
"engine/sync_backend_registrar_unittest.cc",
"engine/ui_model_worker_unittest.cc",
"engine_impl/apply_control_data_updates_unittest.cc",
- "engine_impl/attachments/attachment_downloader_impl_unittest.cc",
- "engine_impl/attachments/attachment_uploader_impl_unittest.cc",
"engine_impl/backoff_delay_provider_unittest.cc",
"engine_impl/cycle/nudge_tracker_unittest.cc",
"engine_impl/cycle/status_controller_unittest.cc",
@@ -917,10 +866,6 @@ source_set("unit_tests") {
"engine_impl/worker_entity_tracker_unittest.cc",
"js/js_event_details_unittest.cc",
"js/sync_js_controller_unittest.cc",
- "model/attachments/attachment_id_unittest.cc",
- "model/attachments/attachment_metadata_unittest.cc",
- "model/attachments/attachment_service_proxy_unittest.cc",
- "model/attachments/attachment_unittest.cc",
"model/entity_data_unittest.cc",
"model/model_type_sync_bridge_unittest.cc",
"model/mutable_data_batch_unittest.cc",
@@ -929,8 +874,6 @@ source_set("unit_tests") {
"model/sync_error_unittest.cc",
"model/sync_merge_result_unittest.cc",
"model_impl/accumulating_metadata_change_list_unittest.cc",
- "model_impl/attachments/attachment_service_impl_unittest.cc",
- "model_impl/attachments/task_queue_unittest.cc",
"model_impl/model_type_store_backend_unittest.cc",
"model_impl/model_type_store_impl_unittest.cc",
"model_impl/passthrough_metadata_change_list_unittest.cc",
@@ -978,7 +921,6 @@ source_set("unit_tests") {
"//components/os_crypt:test_support",
"//components/prefs:test_support",
"//components/signin/core/browser:test_support",
- "//components/sync/engine_impl/attachments/proto",
"//components/sync_preferences",
"//components/sync_preferences:test_support",
"//components/variations",
diff --git a/chromium/components/sync/engine_impl/attachments/proto/BUILD.gn b/chromium/components/sync/engine_impl/attachments/proto/BUILD.gn
deleted file mode 100644
index 6b0a0d28163..00000000000
--- a/chromium/components/sync/engine_impl/attachments/proto/BUILD.gn
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/protobuf/proto_library.gni")
-
-proto_library("proto") {
- # This should only get compiled into the sync component.
- visibility = [
- "//components/sync",
- "//components/sync:unit_tests",
- ]
-
- sources = [
- "attachment_store.proto",
- ]
-}
diff --git a/chromium/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc b/chromium/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc
index 8fe1338846f..0da34411051 100644
--- a/chromium/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc
+++ b/chromium/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc
@@ -74,8 +74,8 @@ class SyncBookmarkDataTypeControllerTest : public testing::Test,
profile_sync_factory_ =
std::make_unique<syncer::SyncApiComponentFactoryMock>(
model_associator_, change_processor_);
- bookmark_dtc_ = std::make_unique<BookmarkDataTypeController>(
- base::Bind(&base::DoNothing), this);
+ bookmark_dtc_ =
+ std::make_unique<BookmarkDataTypeController>(base::DoNothing(), this);
}
protected:
diff --git a/chromium/components/sync_preferences/pref_model_associator.cc b/chromium/components/sync_preferences/pref_model_associator.cc
index 89420a9d6c3..401d614defd 100644
--- a/chromium/components/sync_preferences/pref_model_associator.cc
+++ b/chromium/components/sync_preferences/pref_model_associator.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include <iterator>
+#include <memory>
#include <utility>
#include "base/auto_reset.h"
@@ -242,7 +243,7 @@ std::unique_ptr<base::Value> PrefModelAssociator::MergePreference(
if (client_->IsMergeableListPreference(name))
return MergeListValues(local_value, server_value);
if (client_->IsMergeableDictionaryPreference(name)) {
- return base::MakeUnique<base::Value>(
+ return std::make_unique<base::Value>(
MergeDictionaryValues(local_value, server_value));
}
}
@@ -427,7 +428,7 @@ void PrefModelAssociator::AddSyncedPrefObserver(const std::string& name,
std::unique_ptr<SyncedPrefObserverList>& observers =
synced_pref_observers_[name];
if (!observers)
- observers = base::MakeUnique<SyncedPrefObserverList>();
+ observers = std::make_unique<SyncedPrefObserverList>();
observers->AddObserver(observer);
}
diff --git a/chromium/components/sync_preferences/pref_model_associator_unittest.cc b/chromium/components/sync_preferences/pref_model_associator_unittest.cc
index ceaf48f327e..55682ad9434 100644
--- a/chromium/components/sync_preferences/pref_model_associator_unittest.cc
+++ b/chromium/components/sync_preferences/pref_model_associator_unittest.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/values.h"
#include "components/prefs/scoped_user_pref_update.h"
@@ -132,7 +131,7 @@ TEST_F(ListPreferenceMergeTest, LocalEmpty) {
}
TEST_F(ListPreferenceMergeTest, ServerNull) {
- auto null_value = base::MakeUnique<base::Value>();
+ auto null_value = std::make_unique<base::Value>();
{
ListPrefUpdate update(pref_service_.get(), kListPrefName);
base::ListValue* local_list_value = update.Get();
@@ -254,7 +253,7 @@ TEST_F(DictionaryPreferenceMergeTest, LocalEmpty) {
}
TEST_F(DictionaryPreferenceMergeTest, ServerNull) {
- auto null_value = base::MakeUnique<base::Value>();
+ auto null_value = std::make_unique<base::Value>();
{
DictionaryPrefUpdate update(pref_service_.get(), kDictionaryPrefName);
base::DictionaryValue* local_dict_value = update.Get();
diff --git a/chromium/components/sync_preferences/pref_service_syncable.cc b/chromium/components/sync_preferences/pref_service_syncable.cc
index c132e1eb199..96e192dbf69 100644
--- a/chromium/components/sync_preferences/pref_service_syncable.cc
+++ b/chromium/components/sync_preferences/pref_service_syncable.cc
@@ -22,7 +22,7 @@
#include "services/preferences/public/cpp/in_process_service_factory.h"
#include "services/preferences/public/cpp/persistent_pref_store_client.h"
#include "services/preferences/public/cpp/pref_registry_serializer.h"
-#include "services/preferences/public/interfaces/preferences.mojom.h"
+#include "services/preferences/public/mojom/preferences.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace sync_preferences {
@@ -30,17 +30,17 @@ namespace sync_preferences {
PrefServiceSyncable::PrefServiceSyncable(
std::unique_ptr<PrefNotifierImpl> pref_notifier,
std::unique_ptr<PrefValueStore> pref_value_store,
- PersistentPrefStore* user_prefs,
- user_prefs::PrefRegistrySyncable* pref_registry,
+ scoped_refptr<PersistentPrefStore> user_prefs,
+ scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry,
const PrefModelAssociatorClient* pref_model_associator_client,
- base::Callback<void(PersistentPrefStore::PrefReadError)>
+ base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>
read_error_callback,
bool async)
: PrefService(std::move(pref_notifier),
std::move(pref_value_store),
- user_prefs,
- pref_registry,
- read_error_callback,
+ std::move(user_prefs),
+ std::move(pref_registry),
+ std::move(read_error_callback),
async),
pref_service_forked_(false),
pref_sync_associator_(pref_model_associator_client, syncer::PREFERENCES),
@@ -54,17 +54,17 @@ PrefServiceSyncable::PrefServiceSyncable(
&PrefServiceSyncable::ProcessPrefChange, base::Unretained(this)));
// Add already-registered syncable preferences to PrefModelAssociator.
- for (PrefRegistry::const_iterator it = pref_registry->begin();
- it != pref_registry->end(); ++it) {
- const std::string& path = it->first;
+ for (const auto& entry : *pref_registry_) {
+ const std::string& path = entry.first;
AddRegisteredSyncablePreference(path,
pref_registry_->GetRegistrationFlags(path));
}
// Watch for syncable preferences registered after this point.
- pref_registry->SetSyncableRegistrationCallback(
- base::Bind(&PrefServiceSyncable::AddRegisteredSyncablePreference,
- base::Unretained(this)));
+ static_cast<user_prefs::PrefRegistrySyncable*>(pref_registry_.get())
+ ->SetSyncableRegistrationCallback(base::BindRepeating(
+ &PrefServiceSyncable::AddRegisteredSyncablePreference,
+ base::Unretained(this)));
}
PrefServiceSyncable::~PrefServiceSyncable() {
@@ -75,7 +75,8 @@ PrefServiceSyncable::~PrefServiceSyncable() {
user_prefs::PrefRegistrySyncable::SyncableRegistrationCallback());
}
-PrefServiceSyncable* PrefServiceSyncable::CreateIncognitoPrefService(
+std::unique_ptr<PrefServiceSyncable>
+PrefServiceSyncable::CreateIncognitoPrefService(
PrefStore* incognito_extension_pref_store,
const std::vector<const char*>& overlay_pref_names,
std::unique_ptr<PrefValueStore::Delegate> delegate) {
@@ -107,11 +108,10 @@ PrefServiceSyncable* PrefServiceSyncable::CreateIncognitoPrefService(
nullptr, // recommended
forked_registry->defaults().get(), pref_notifier.get(),
std::move(delegate));
- PrefServiceSyncable* incognito_service = new PrefServiceSyncable(
+ return std::make_unique<PrefServiceSyncable>(
std::move(pref_notifier), std::move(pref_value_store),
- incognito_pref_store.get(), forked_registry.get(),
+ std::move(incognito_pref_store), std::move(forked_registry),
pref_sync_associator_.client(), read_error_callback_, false);
- return incognito_service;
}
bool PrefServiceSyncable::IsSyncing() {
diff --git a/chromium/components/sync_preferences/pref_service_syncable.h b/chromium/components/sync_preferences/pref_service_syncable.h
index 7a2c9f043df..f425965a986 100644
--- a/chromium/components/sync_preferences/pref_service_syncable.h
+++ b/chromium/components/sync_preferences/pref_service_syncable.h
@@ -38,10 +38,10 @@ class PrefServiceSyncable : public PrefService {
PrefServiceSyncable(
std::unique_ptr<PrefNotifierImpl> pref_notifier,
std::unique_ptr<PrefValueStore> pref_value_store,
- PersistentPrefStore* user_prefs,
- user_prefs::PrefRegistrySyncable* pref_registry,
+ scoped_refptr<PersistentPrefStore> user_prefs,
+ scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry,
const PrefModelAssociatorClient* pref_model_associato_client,
- base::Callback<void(PersistentPrefStore::PrefReadError)>
+ base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>
read_error_callback,
bool async);
~PrefServiceSyncable() override;
@@ -51,7 +51,7 @@ class PrefServiceSyncable : public PrefService {
// individual extension pref store (to cache the effective extension prefs for
// incognito windows). |overlay_pref_names| is a list of preference names
// whose changes will not be persisted by the returned incognito pref service.
- PrefServiceSyncable* CreateIncognitoPrefService(
+ std::unique_ptr<PrefServiceSyncable> CreateIncognitoPrefService(
PrefStore* incognito_extension_pref_store,
const std::vector<const char*>& overlay_pref_names,
std::unique_ptr<PrefValueStore::Delegate> delegate);
diff --git a/chromium/components/sync_preferences/pref_service_syncable_factory.cc b/chromium/components/sync_preferences/pref_service_syncable_factory.cc
index 10cb2a57eaf..a920488478f 100644
--- a/chromium/components/sync_preferences/pref_service_syncable_factory.cc
+++ b/chromium/components/sync_preferences/pref_service_syncable_factory.cc
@@ -57,7 +57,7 @@ void PrefServiceSyncableFactory::SetPrefModelAssociatorClient(
}
std::unique_ptr<PrefServiceSyncable> PrefServiceSyncableFactory::CreateSyncable(
- user_prefs::PrefRegistrySyncable* pref_registry,
+ scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry,
std::unique_ptr<PrefValueStore::Delegate> delegate) {
TRACE_EVENT0("browser", "PrefServiceSyncableFactory::CreateSyncable");
auto pref_notifier = std::make_unique<PrefNotifierImpl>();
@@ -68,8 +68,8 @@ std::unique_ptr<PrefServiceSyncable> PrefServiceSyncableFactory::CreateSyncable(
pref_notifier.get(), std::move(delegate));
return std::make_unique<PrefServiceSyncable>(
std::move(pref_notifier), std::move(pref_value_store), user_prefs_.get(),
- pref_registry, pref_model_associator_client_, read_error_callback_,
- async_);
+ std::move(pref_registry), pref_model_associator_client_,
+ read_error_callback_, async_);
}
} // namespace sync_preferences
diff --git a/chromium/components/sync_preferences/pref_service_syncable_factory.h b/chromium/components/sync_preferences/pref_service_syncable_factory.h
index b6726b377b7..9e7a0c71d87 100644
--- a/chromium/components/sync_preferences/pref_service_syncable_factory.h
+++ b/chromium/components/sync_preferences/pref_service_syncable_factory.h
@@ -46,11 +46,11 @@ class PrefServiceSyncableFactory : public PrefServiceFactory {
// |delegate| might be null during test or if we're not using the Mojo pref
// service.
std::unique_ptr<PrefServiceSyncable> CreateSyncable(
- user_prefs::PrefRegistrySyncable* registry,
+ scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry,
std::unique_ptr<PrefValueStore::Delegate> delegate = nullptr);
private:
- PrefModelAssociatorClient* pref_model_associator_client_;
+ PrefModelAssociatorClient* pref_model_associator_client_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(PrefServiceSyncableFactory);
};
diff --git a/chromium/components/sync_preferences/pref_service_syncable_unittest.cc b/chromium/components/sync_preferences/pref_service_syncable_unittest.cc
index e607be0ba2e..5a1c94ebe42 100644
--- a/chromium/components/sync_preferences/pref_service_syncable_unittest.cc
+++ b/chromium/components/sync_preferences/pref_service_syncable_unittest.cc
@@ -12,13 +12,10 @@
#include "base/json/json_string_value_serializer.h"
#include "base/json/json_writer.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/scoped_user_pref_update.h"
-#include "components/sync/model/attachments/attachment_id.h"
-#include "components/sync/model/attachments/attachment_service_proxy_for_test.h"
#include "components/sync/model/sync_change.h"
#include "components/sync/model/sync_data.h"
#include "components/sync/model/sync_error_factory_mock.h"
@@ -138,9 +135,7 @@ class PrefServiceSyncableTest : public testing::Test {
pref_one->set_value(serialized);
return syncer::SyncChange(
FROM_HERE, type,
- syncer::SyncData::CreateRemoteData(
- id, entity, base::Time(), syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ syncer::SyncData::CreateRemoteData(id, entity, base::Time()));
}
void AddToRemoteDataList(const std::string& name,
@@ -153,10 +148,8 @@ class PrefServiceSyncableTest : 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(
- ++next_pref_remote_sync_node_id_, one, base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ out->push_back(SyncData::CreateRemoteData(++next_pref_remote_sync_node_id_,
+ one, base::Time()));
}
void InitWithSyncDataTakeOutput(const syncer::SyncDataList& initial_data,
@@ -164,7 +157,7 @@ class PrefServiceSyncableTest : public testing::Test {
test_processor_ = new TestSyncProcessorStub(output);
syncer::SyncMergeResult r = pref_sync_service_->MergeDataAndStartSyncing(
syncer::PREFERENCES, initial_data, base::WrapUnique(test_processor_),
- base::MakeUnique<syncer::SyncErrorFactoryMock>());
+ std::make_unique<syncer::SyncErrorFactoryMock>());
EXPECT_FALSE(r.error().IsSet());
}
@@ -208,9 +201,6 @@ class PrefServiceSyncableTest : public testing::Test {
PrefModelAssociator* pref_sync_service_;
TestSyncProcessorStub* test_processor_;
- // TODO(tim): Remove this by fixing AttachmentServiceProxyForTest.
- base::MessageLoop loop_;
-
int next_pref_remote_sync_node_id_;
};
@@ -304,7 +294,7 @@ TEST_F(PrefServiceSyncableTest, FailModelAssociation) {
stub->FailNextProcessSyncChanges();
syncer::SyncMergeResult r = pref_sync_service_->MergeDataAndStartSyncing(
syncer::PREFERENCES, syncer::SyncDataList(), base::WrapUnique(stub),
- base::MakeUnique<syncer::SyncErrorFactoryMock>());
+ std::make_unique<syncer::SyncErrorFactoryMock>());
EXPECT_TRUE(r.error().IsSet());
}
@@ -539,7 +529,7 @@ TEST_F(PrefServiceSyncableTest, DeletePreference) {
InitWithNoSyncData();
- auto null_value = base::MakeUnique<base::Value>();
+ auto null_value = std::make_unique<base::Value>();
syncer::SyncChangeList list;
list.push_back(MakeRemoteChange(1, kStringPrefName, *null_value,
SyncChange::ACTION_DELETE));
diff --git a/chromium/components/sync_sessions/BUILD.gn b/chromium/components/sync_sessions/BUILD.gn
index 7212996b09b..8752d9a22ad 100644
--- a/chromium/components/sync_sessions/BUILD.gn
+++ b/chromium/components/sync_sessions/BUILD.gn
@@ -11,32 +11,16 @@ static_library("sync_sessions") {
"lost_navigations_recorder.h",
"open_tabs_ui_delegate.cc",
"open_tabs_ui_delegate.h",
- "revisit/bookmarks_by_url_provider_impl.cc",
- "revisit/bookmarks_by_url_provider_impl.h",
- "revisit/bookmarks_page_revisit_observer.cc",
- "revisit/bookmarks_page_revisit_observer.h",
- "revisit/current_tab_matcher.cc",
- "revisit/current_tab_matcher.h",
- "revisit/offset_tab_matcher.cc",
- "revisit/offset_tab_matcher.h",
- "revisit/page_equality.h",
- "revisit/page_revisit_broadcaster.cc",
- "revisit/page_revisit_broadcaster.h",
- "revisit/page_visit_observer.h",
- "revisit/sessions_page_revisit_observer.cc",
- "revisit/sessions_page_revisit_observer.h",
- "revisit/typed_url_page_revisit_observer.cc",
- "revisit/typed_url_page_revisit_observer.h",
- "revisit/typed_url_page_revisit_task.cc",
- "revisit/typed_url_page_revisit_task.h",
+ "open_tabs_ui_delegate_impl.cc",
+ "open_tabs_ui_delegate_impl.h",
"session_data_type_controller.cc",
"session_data_type_controller.h",
+ "sessions_global_id_mapper.cc",
+ "sessions_global_id_mapper.h",
"sessions_sync_manager.cc",
"sessions_sync_manager.h",
"sync_sessions_client.cc",
"sync_sessions_client.h",
- "sync_sessions_metrics.cc",
- "sync_sessions_metrics.h",
"synced_session.cc",
"synced_session.h",
"synced_session_tracker.cc",
@@ -73,8 +57,8 @@ static_library("sync_sessions") {
static_library("test_support") {
testonly = true
sources = [
- "fake_sync_sessions_client.cc",
- "fake_sync_sessions_client.h",
+ "mock_sync_sessions_client.cc",
+ "mock_sync_sessions_client.h",
"session_sync_test_helper.cc",
"session_sync_test_helper.h",
]
@@ -83,6 +67,7 @@ static_library("test_support") {
":sync_sessions",
"//base",
"//components/sync",
+ "//testing/gmock",
"//testing/gtest",
"//url",
]
@@ -95,15 +80,10 @@ source_set("unit_tests") {
sources = [
"favicon_cache_unittest.cc",
"lost_navigations_recorder_unittest.cc",
- "revisit/bookmarks_page_revisit_observer_unittest.cc",
- "revisit/current_tab_matcher_unittest.cc",
- "revisit/offset_tab_matcher_unittest.cc",
- "revisit/page_revisit_broadcaster_unittest.cc",
- "revisit/sessions_page_revisit_observer_unittest.cc",
- "revisit/typed_url_page_revisit_task_unittest.cc",
+ "open_tabs_ui_delegate_impl_unittest.cc",
"session_data_type_controller_unittest.cc",
+ "sessions_global_id_mapper_unittest.cc",
"sessions_sync_manager_unittest.cc",
- "sync_sessions_metrics_unittest.cc",
"synced_session_tracker_unittest.cc",
"tab_node_pool_unittest.cc",
"task_tracker_unittest.cc",
diff --git a/chromium/components/sync_sessions/fake_sync_sessions_client.cc b/chromium/components/sync_sessions/fake_sync_sessions_client.cc
deleted file mode 100644
index 3ef4ae03835..00000000000
--- a/chromium/components/sync_sessions/fake_sync_sessions_client.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/fake_sync_sessions_client.h"
-#include "components/sync_sessions/local_session_event_router.h"
-
-#include "url/gurl.h"
-
-namespace sync_sessions {
-
-FakeSyncSessionsClient::FakeSyncSessionsClient() {}
-FakeSyncSessionsClient::~FakeSyncSessionsClient() {}
-
-bookmarks::BookmarkModel* FakeSyncSessionsClient::GetBookmarkModel() {
- return nullptr;
-}
-
-favicon::FaviconService* FakeSyncSessionsClient::GetFaviconService() {
- return nullptr;
-}
-
-history::HistoryService* FakeSyncSessionsClient::GetHistoryService() {
- return nullptr;
-}
-
-bool FakeSyncSessionsClient::ShouldSyncURL(const GURL& url) const {
- return url.is_valid();
-}
-
-SyncedWindowDelegatesGetter*
-FakeSyncSessionsClient::GetSyncedWindowDelegatesGetter() {
- return nullptr;
-}
-
-LocalSessionEventRouter* FakeSyncSessionsClient::GetLocalSessionEventRouter() {
- return nullptr;
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/fake_sync_sessions_client.h b/chromium/components/sync_sessions/fake_sync_sessions_client.h
deleted file mode 100644
index acffdce1f3a..00000000000
--- a/chromium/components/sync_sessions/fake_sync_sessions_client.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SYNC_SESSIONS_FAKE_SYNC_SESSIONS_CLIENT_H_
-#define COMPONENTS_SYNC_SESSIONS_FAKE_SYNC_SESSIONS_CLIENT_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "components/sync_sessions/sync_sessions_client.h"
-
-namespace sync_sessions {
-
-// Fake implementation of a SyncSessionsClient for testing.
-class FakeSyncSessionsClient : public SyncSessionsClient {
- public:
- FakeSyncSessionsClient();
- ~FakeSyncSessionsClient() override;
-
- // SyncSessionsClient:
- bookmarks::BookmarkModel* GetBookmarkModel() override;
- favicon::FaviconService* GetFaviconService() override;
- history::HistoryService* GetHistoryService() override;
- bool ShouldSyncURL(const GURL& url) const override;
- SyncedWindowDelegatesGetter* GetSyncedWindowDelegatesGetter() override;
- LocalSessionEventRouter* GetLocalSessionEventRouter() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FakeSyncSessionsClient);
-};
-
-} // namespace sync_sessions
-
-#endif // COMPONENTS_SYNC_SESSIONS_FAKE_SYNC_SESSIONS_CLIENT_H_
diff --git a/chromium/components/sync_sessions/favicon_cache_unittest.cc b/chromium/components/sync_sessions/favicon_cache_unittest.cc
index cde237666bb..8e910fa776e 100644
--- a/chromium/components/sync_sessions/favicon_cache_unittest.cc
+++ b/chromium/components/sync_sessions/favicon_cache_unittest.cc
@@ -11,8 +11,6 @@
#include "base/strings/stringprintf.h"
#include "base/test/scoped_task_environment.h"
#include "base/time/time.h"
-#include "components/sync/model/attachments/attachment_id.h"
-#include "components/sync/model/attachments/attachment_service_proxy_for_test.h"
#include "components/sync/model/sync_change_processor_wrapper_for_test.h"
#include "components/sync/model/sync_error_factory_mock.h"
#include "components/sync/model/time.h"
@@ -617,20 +615,12 @@ TEST_F(SyncFaviconCacheTest, SyncExistingRemote) {
sync_pb::EntitySpecifics image_specifics, tracking_specifics;
FillImageSpecifics(BuildFaviconData(i),
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
}
syncer::SyncMergeResult merge_result =
@@ -696,20 +686,12 @@ TEST_F(SyncFaviconCacheTest, SyncMergesImages) {
FillImageSpecifics(test_data,
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(test_data,
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
}
syncer::SyncMergeResult merge_result =
@@ -781,20 +763,12 @@ TEST_F(SyncFaviconCacheTest, SyncMergesTracking) {
FillImageSpecifics(test_data,
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(test_data,
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
}
syncer::SyncMergeResult merge_result =
@@ -846,31 +820,17 @@ TEST_F(SyncFaviconCacheTest, ReceiveStaleImages) {
sync_pb::EntitySpecifics image_specifics, tracking_specifics;
FillImageSpecifics(BuildFaviconData(i),
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
image_specifics.mutable_favicon_image()->clear_favicon_web();
stale_changes.push_back(syncer::SyncChange(
- FROM_HERE,
- syncer::SyncChange::ACTION_UPDATE,
- syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create())));
+ FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time())));
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
}
SetUpInitialSync(initial_image_data, initial_tracking_data);
@@ -899,32 +859,18 @@ TEST_F(SyncFaviconCacheTest, ReceiveNewImages) {
FillImageSpecifics(test_data,
image_specifics.mutable_favicon_image());
new_changes.push_back(syncer::SyncChange(
- FROM_HERE,
- syncer::SyncChange::ACTION_UPDATE,
- syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create())));
+ FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time())));
image_specifics.mutable_favicon_image()
->mutable_favicon_web()
->mutable_favicon()
->append("old");
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
}
SetUpInitialSync(initial_image_data, initial_tracking_data);
@@ -947,28 +893,14 @@ TEST_F(SyncFaviconCacheTest, ReceiveSameImages) {
FillImageSpecifics(test_data,
image_specifics.mutable_favicon_image());
same_changes.push_back(syncer::SyncChange(
- FROM_HERE,
- syncer::SyncChange::ACTION_UPDATE,
- syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create())));
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time())));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
}
SetUpInitialSync(initial_image_data, initial_tracking_data);
@@ -991,31 +923,18 @@ TEST_F(SyncFaviconCacheTest, ReceiveStaleTracking) {
sync_pb::EntitySpecifics image_specifics, tracking_specifics;
FillImageSpecifics(BuildFaviconData(i),
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
tracking_specifics.mutable_favicon_tracking()->set_last_visit_time_ms(-1);
- stale_changes.push_back(syncer::SyncChange(
- FROM_HERE,
- syncer::SyncChange::ACTION_UPDATE,
- syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create())));
+ stale_changes.push_back(
+ syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
+ syncer::SyncData::CreateRemoteData(
+ 1, tracking_specifics, base::Time())));
}
SetUpInitialSync(initial_image_data, initial_tracking_data);
@@ -1043,30 +962,17 @@ TEST_F(SyncFaviconCacheTest, ReceiveNewTracking) {
sync_pb::EntitySpecifics image_specifics, tracking_specifics;
FillImageSpecifics(BuildFaviconData(i),
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
- new_changes.push_back(syncer::SyncChange(
- FROM_HERE,
- syncer::SyncChange::ACTION_UPDATE,
- syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create())));
+ new_changes.push_back(
+ syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
+ syncer::SyncData::CreateRemoteData(
+ 1, tracking_specifics, base::Time())));
tracking_specifics.mutable_favicon_tracking()->set_last_visit_time_ms(i-1);
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
}
SetUpInitialSync(initial_image_data, initial_tracking_data);
@@ -1088,29 +994,16 @@ TEST_F(SyncFaviconCacheTest, ReceiveSameTracking) {
sync_pb::EntitySpecifics image_specifics, tracking_specifics;
FillImageSpecifics(BuildFaviconData(i),
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
- same_changes.push_back(syncer::SyncChange(
- FROM_HERE,
- syncer::SyncChange::ACTION_UPDATE,
- syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create())));
+ 1, tracking_specifics, base::Time()));
+ same_changes.push_back(
+ syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
+ syncer::SyncData::CreateRemoteData(
+ 1, tracking_specifics, base::Time())));
}
SetUpInitialSync(initial_image_data, initial_tracking_data);
@@ -1129,38 +1022,19 @@ TEST_F(SyncFaviconCacheTest, DeleteFavicons) {
sync_pb::EntitySpecifics image_specifics, tracking_specifics;
FillImageSpecifics(BuildFaviconData(i),
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
- tracking_deletions.push_back(syncer::SyncChange(
- FROM_HERE,
- syncer::SyncChange::ACTION_DELETE,
- syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create())));
+ 1, tracking_specifics, base::Time()));
+ tracking_deletions.push_back(
+ syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_DELETE,
+ syncer::SyncData::CreateRemoteData(
+ 1, tracking_specifics, base::Time())));
image_deletions.push_back(syncer::SyncChange(
- FROM_HERE,
- syncer::SyncChange::ACTION_DELETE,
- syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create())));
+ FROM_HERE, syncer::SyncChange::ACTION_DELETE,
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time())));
}
SetUpInitialSync(initial_image_data, initial_tracking_data);
@@ -1190,20 +1064,12 @@ TEST_F(SyncFaviconCacheTest, ExpireOnMergeData) {
sync_pb::EntitySpecifics image_specifics, tracking_specifics;
FillImageSpecifics(BuildFaviconData(i),
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
expected_icons.push_back(i);
TestFaviconData favicon = BuildFaviconData(i+kMaxSyncFavicons);
@@ -1261,44 +1127,25 @@ TEST_F(SyncFaviconCacheTest, NoExpireOnProcessSyncChanges) {
sync_pb::EntitySpecifics image_specifics, tracking_specifics;
FillImageSpecifics(BuildFaviconData(i),
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
// Set up new tracking specifics for the icons received at change time.
expected_icons.push_back(i + kMaxSyncFavicons);
FillImageSpecifics(BuildFaviconData(i + kMaxSyncFavicons),
image_specifics.mutable_favicon_image());
image_changes.push_back(syncer::SyncChange(
- FROM_HERE,
- syncer::SyncChange::ACTION_ADD,
- syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create())));
+ FROM_HERE, syncer::SyncChange::ACTION_ADD,
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time())));
FillTrackingSpecifics(BuildFaviconData(i + kMaxSyncFavicons),
tracking_specifics.mutable_favicon_tracking());
- tracking_changes.push_back(syncer::SyncChange(
- FROM_HERE,
- syncer::SyncChange::ACTION_ADD,
- syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create())));
+ tracking_changes.push_back(
+ syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD,
+ syncer::SyncData::CreateRemoteData(
+ 1, tracking_specifics, base::Time())));
}
SetUpInitialSync(initial_image_data, initial_tracking_data);
@@ -1451,20 +1298,12 @@ TEST_F(SyncFaviconCacheTest, HistoryFullClear) {
sync_pb::EntitySpecifics image_specifics, tracking_specifics;
FillImageSpecifics(test_data,
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
}
SetUpInitialSync(initial_image_data, initial_tracking_data);
@@ -1509,20 +1348,12 @@ TEST_F(SyncFaviconCacheTest, HistorySubsetClear) {
sync_pb::EntitySpecifics image_specifics, tracking_specifics;
FillImageSpecifics(test_data,
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
}
SetUpInitialSync(initial_image_data, initial_tracking_data);
@@ -1632,28 +1463,18 @@ TEST_F(SyncFaviconCacheTest, UpdatedOrphans) {
sync_pb::EntitySpecifics image_specifics;
FillImageSpecifics(BuildFaviconData(i),
image_specifics.mutable_favicon_image());
- initial_image_changes.push_back(syncer::SyncChange(
- FROM_HERE,
- syncer::SyncChange::ACTION_ADD,
- syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create())));
+ initial_image_changes.push_back(
+ syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD,
+ syncer::SyncData::CreateRemoteData(
+ 1, image_specifics, base::Time())));
} else {
sync_pb::EntitySpecifics tracking_specifics;
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
- initial_tracking_changes.push_back(syncer::SyncChange(
- FROM_HERE,
- syncer::SyncChange::ACTION_ADD,
- syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create())));
+ initial_tracking_changes.push_back(
+ syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD,
+ syncer::SyncData::CreateRemoteData(
+ 1, tracking_specifics, base::Time())));
}
}
@@ -1712,12 +1533,8 @@ TEST_F(SyncFaviconCacheTest, PartialAssociationInfo) {
sync_pb::EntitySpecifics image_specifics;
FillImageSpecifics(BuildFaviconData(i),
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
image_specifics.mutable_favicon_image()->clear_favicon_web();
}
@@ -1739,22 +1556,14 @@ TEST_F(SyncFaviconCacheTest, NullFaviconVisitTime) {
sync_pb::EntitySpecifics image_specifics, tracking_specifics;
FillImageSpecifics(BuildFaviconData(i),
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
tracking_specifics.mutable_favicon_tracking()->set_last_visit_time_ms(
syncer::TimeToProtoTime(base::Time()));
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
}
cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
@@ -1809,20 +1618,12 @@ TEST_F(SyncFaviconCacheTest, VisitFaviconClockSkew) {
base::Time::Now() + base::TimeDelta::FromMinutes(kClockSkew));
FillImageSpecifics(test_data,
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
FillTrackingSpecifics(test_data,
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
}
SetUpInitialSync(initial_image_data, initial_tracking_data);
@@ -1872,22 +1673,14 @@ TEST_F(SyncFaviconCacheTest, MixedThreshold) {
// Push the images forward by 5, to match the unsynced favicons.
FillImageSpecifics(BuildFaviconData(i + 5),
image_specifics.mutable_favicon_image());
- initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- image_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ initial_image_data.push_back(
+ syncer::SyncData::CreateRemoteData(1, image_specifics, base::Time()));
sync_pb::EntitySpecifics tracking_specifics;
FillTrackingSpecifics(BuildFaviconData(i),
tracking_specifics.mutable_favicon_tracking());
initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
- 1,
- tracking_specifics,
- base::Time(),
- syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ 1, tracking_specifics, base::Time()));
}
SetUpInitialSync(initial_image_data, initial_tracking_data);
diff --git a/chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc b/chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc
index b984b927159..85162364158 100644
--- a/chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc
+++ b/chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc
@@ -9,7 +9,6 @@
#include "base/message_loop/message_loop.h"
#include "base/test/histogram_tester.h"
-#include "components/sync/model/attachments/attachment_service_proxy_for_test.h"
#include "components/sync/syncable/entry.h"
#include "components/sync/syncable/mutable_entry.h"
#include "components/sync/syncable/syncable_base_transaction.h"
diff --git a/chromium/components/sync_sessions/mock_sync_sessions_client.cc b/chromium/components/sync_sessions/mock_sync_sessions_client.cc
new file mode 100644
index 00000000000..d6bc31ecc4a
--- /dev/null
+++ b/chromium/components/sync_sessions/mock_sync_sessions_client.cc
@@ -0,0 +1,17 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync_sessions/mock_sync_sessions_client.h"
+#include "components/sync_sessions/local_session_event_router.h"
+
+namespace sync_sessions {
+
+MockSyncSessionsClient::MockSyncSessionsClient() {
+ ON_CALL(*this, ShouldSyncURL(testing::_))
+ .WillByDefault(testing::Return(true));
+}
+
+MockSyncSessionsClient::~MockSyncSessionsClient() {}
+
+} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/mock_sync_sessions_client.h b/chromium/components/sync_sessions/mock_sync_sessions_client.h
new file mode 100644
index 00000000000..c2c20c5edc8
--- /dev/null
+++ b/chromium/components/sync_sessions/mock_sync_sessions_client.h
@@ -0,0 +1,30 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SYNC_SESSIONS_MOCK_SYNC_SESSIONS_CLIENT_H_
+#define COMPONENTS_SYNC_SESSIONS_MOCK_SYNC_SESSIONS_CLIENT_H_
+
+#include "components/sync_sessions/sync_sessions_client.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "url/gurl.h"
+
+namespace sync_sessions {
+
+class MockSyncSessionsClient : public SyncSessionsClient {
+ public:
+ // By default, ShouldSyncURL() always returns true.
+ MockSyncSessionsClient();
+ ~MockSyncSessionsClient() override;
+
+ MOCK_METHOD0(GetBookmarkModel, bookmarks::BookmarkModel*());
+ MOCK_METHOD0(GetFaviconService, favicon::FaviconService*());
+ MOCK_METHOD0(GetHistoryService, history::HistoryService*());
+ MOCK_CONST_METHOD1(ShouldSyncURL, bool(const GURL& url));
+ MOCK_METHOD0(GetSyncedWindowDelegatesGetter, SyncedWindowDelegatesGetter*());
+ MOCK_METHOD0(GetLocalSessionEventRouter, LocalSessionEventRouter*());
+};
+
+} // namespace sync_sessions
+
+#endif // COMPONENTS_SYNC_SESSIONS_MOCK_SYNC_SESSIONS_CLIENT_H_
diff --git a/chromium/components/sync_sessions/open_tabs_ui_delegate_impl.cc b/chromium/components/sync_sessions/open_tabs_ui_delegate_impl.cc
new file mode 100644
index 00000000000..8295bbe85eb
--- /dev/null
+++ b/chromium/components/sync_sessions/open_tabs_ui_delegate_impl.cc
@@ -0,0 +1,112 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync_sessions/open_tabs_ui_delegate_impl.h"
+
+#include <algorithm>
+
+#include "components/sync_sessions/favicon_cache.h"
+#include "components/sync_sessions/sync_sessions_client.h"
+#include "components/sync_sessions/synced_session_tracker.h"
+
+namespace sync_sessions {
+namespace {
+
+// Comparator function for use with std::sort that will sort tabs by
+// descending timestamp (i.e., most recent first).
+bool TabsRecencyComparator(const sessions::SessionTab* t1,
+ const sessions::SessionTab* t2) {
+ return t1->timestamp > t2->timestamp;
+}
+
+// Comparator function for use with std::sort that will sort sessions by
+// descending modified_time (i.e., most recent first).
+bool SessionsRecencyComparator(const SyncedSession* s1,
+ const SyncedSession* s2) {
+ return s1->modified_time > s2->modified_time;
+}
+
+} // namespace
+
+OpenTabsUIDelegateImpl::OpenTabsUIDelegateImpl(
+ const SyncSessionsClient* sessions_client,
+ const SyncedSessionTracker* session_tracker,
+ const FaviconCache* favicon_cache,
+ const DeleteForeignSessionCallback& delete_foreign_session_cb)
+ : sessions_client_(sessions_client),
+ session_tracker_(session_tracker),
+ favicon_cache_(favicon_cache),
+ delete_foreign_session_cb_(delete_foreign_session_cb) {}
+
+OpenTabsUIDelegateImpl::~OpenTabsUIDelegateImpl() {}
+
+bool OpenTabsUIDelegateImpl::GetSyncedFaviconForPageURL(
+ const std::string& page_url,
+ scoped_refptr<base::RefCountedMemory>* favicon_png) const {
+ return favicon_cache_->GetSyncedFaviconForPageURL(GURL(page_url),
+ favicon_png);
+}
+
+bool OpenTabsUIDelegateImpl::GetAllForeignSessions(
+ std::vector<const SyncedSession*>* sessions) {
+ if (!session_tracker_->LookupAllForeignSessions(
+ sessions, SyncedSessionTracker::PRESENTABLE))
+ return false;
+ std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator);
+ return true;
+}
+
+bool OpenTabsUIDelegateImpl::GetForeignSession(
+ const std::string& tag,
+ std::vector<const sessions::SessionWindow*>* windows) {
+ return session_tracker_->LookupSessionWindows(tag, windows);
+}
+
+bool OpenTabsUIDelegateImpl::GetForeignTab(const std::string& tag,
+ const SessionID::id_type tab_id,
+ const sessions::SessionTab** tab) {
+ const sessions::SessionTab* synced_tab = nullptr;
+ bool success = session_tracker_->LookupSessionTab(tag, tab_id, &synced_tab);
+ if (success)
+ *tab = synced_tab;
+ return success;
+}
+
+bool OpenTabsUIDelegateImpl::GetForeignSessionTabs(
+ const std::string& tag,
+ std::vector<const sessions::SessionTab*>* tabs) {
+ std::vector<const sessions::SessionWindow*> windows;
+ if (!session_tracker_->LookupSessionWindows(tag, &windows))
+ return false;
+
+ // Prune those tabs that are not syncable or are NewTabPage, then sort them
+ // from most recent to least recent, independent of which window the tabs were
+ // from.
+ for (size_t j = 0; j < windows.size(); ++j) {
+ const sessions::SessionWindow* window = windows[j];
+ for (size_t t = 0; t < window->tabs.size(); ++t) {
+ sessions::SessionTab* const tab = window->tabs[t].get();
+ if (tab->navigations.empty())
+ continue;
+ const sessions::SerializedNavigationEntry& current_navigation =
+ tab->navigations.at(tab->normalized_navigation_index());
+ if (!sessions_client_->ShouldSyncURL(current_navigation.virtual_url()))
+ continue;
+ tabs->push_back(tab);
+ }
+ }
+ std::sort(tabs->begin(), tabs->end(), TabsRecencyComparator);
+ return true;
+}
+
+void OpenTabsUIDelegateImpl::DeleteForeignSession(const std::string& tag) {
+ delete_foreign_session_cb_.Run(tag);
+}
+
+bool OpenTabsUIDelegateImpl::GetLocalSession(
+ const SyncedSession** local_session) {
+ return session_tracker_->LookupLocalSession(local_session);
+}
+
+} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/open_tabs_ui_delegate_impl.h b/chromium/components/sync_sessions/open_tabs_ui_delegate_impl.h
new file mode 100644
index 00000000000..3c6984432aa
--- /dev/null
+++ b/chromium/components/sync_sessions/open_tabs_ui_delegate_impl.h
@@ -0,0 +1,63 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SYNC_SESSIONS_OPEN_TABS_UI_DELEGATE_IMPL_H_
+#define COMPONENTS_SYNC_SESSIONS_OPEN_TABS_UI_DELEGATE_IMPL_H_
+
+#include <string>
+#include <vector>
+
+#include "components/sync_sessions/open_tabs_ui_delegate.h"
+
+namespace sync_sessions {
+
+class FaviconCache;
+class SyncSessionsClient;
+class SyncedSessionTracker;
+
+class OpenTabsUIDelegateImpl : public OpenTabsUIDelegate {
+ public:
+ using DeleteForeignSessionCallback =
+ base::RepeatingCallback<void(const std::string&)>;
+
+ // |sessions_client|, |session_tracker| and |favicon_cache| must not be null
+ // and must outlive this object. |delete_foreign_session_cb| allows to
+ // forward calls to DeleteForeignSession() which this class doesn't implement.
+ OpenTabsUIDelegateImpl(
+ const SyncSessionsClient* sessions_client,
+ const SyncedSessionTracker* session_tracker,
+ const FaviconCache* favicon_cache,
+ const DeleteForeignSessionCallback& delete_foreign_session_cb);
+ ~OpenTabsUIDelegateImpl() override;
+
+ // OpenTabsUIDelegate implementation.
+ bool GetSyncedFaviconForPageURL(
+ const std::string& pageurl,
+ scoped_refptr<base::RefCountedMemory>* favicon_png) const override;
+ bool GetAllForeignSessions(
+ std::vector<const SyncedSession*>* sessions) override;
+ bool GetForeignSession(
+ const std::string& tag,
+ std::vector<const sessions::SessionWindow*>* windows) override;
+ bool GetForeignTab(const std::string& tag,
+ SessionID::id_type tab_id,
+ const sessions::SessionTab** tab) override;
+ bool GetForeignSessionTabs(
+ const std::string& tag,
+ std::vector<const sessions::SessionTab*>* tabs) override;
+ void DeleteForeignSession(const std::string& tag) override;
+ bool GetLocalSession(const SyncedSession** local_session) override;
+
+ private:
+ const SyncSessionsClient* const sessions_client_;
+ const SyncedSessionTracker* session_tracker_;
+ const FaviconCache* favicon_cache_;
+ DeleteForeignSessionCallback delete_foreign_session_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(OpenTabsUIDelegateImpl);
+};
+
+} // namespace sync_sessions
+
+#endif // COMPONENTS_SYNC_SESSIONS_OPEN_TABS_UI_DELEGATE_IMPL_H_
diff --git a/chromium/components/sync_sessions/open_tabs_ui_delegate_impl_unittest.cc b/chromium/components/sync_sessions/open_tabs_ui_delegate_impl_unittest.cc
new file mode 100644
index 00000000000..6859f26b6f7
--- /dev/null
+++ b/chromium/components/sync_sessions/open_tabs_ui_delegate_impl_unittest.cc
@@ -0,0 +1,174 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync_sessions/open_tabs_ui_delegate_impl.h"
+
+#include <vector>
+
+#include "base/time/time.h"
+#include "components/sessions/core/serialized_navigation_entry_test_helper.h"
+#include "components/sync_sessions/mock_sync_sessions_client.h"
+#include "components/sync_sessions/synced_session_tracker.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sync_sessions {
+namespace {
+
+using sessions::SessionTab;
+using testing::ElementsAre;
+using testing::Field;
+using testing::Pointee;
+using testing::Property;
+
+const char kSessionTag1[] = "foreign1";
+const char kSessionTag2[] = "foreign2";
+const char kSessionTag3[] = "foreign3";
+const SessionID::id_type kWindowId1 = 1;
+const SessionID::id_type kWindowId2 = 2;
+const SessionID::id_type kWindowId3 = 3;
+const SessionID::id_type kTabId1 = 111;
+const SessionID::id_type kTabId2 = 222;
+const SessionID::id_type kTabId3 = 333;
+
+void IngnoreForeignSessionDeletion(const std::string& session_tag) {}
+
+class OpenTabsUIDelegateImplTest : public testing::Test {
+ protected:
+ OpenTabsUIDelegateImplTest()
+ : session_tracker_(&mock_sync_sessions_client_),
+ delegate_(&mock_sync_sessions_client_,
+ &session_tracker_,
+ /*favicon_cache=*/nullptr,
+ base::BindRepeating(&IngnoreForeignSessionDeletion)) {}
+
+ testing::NiceMock<MockSyncSessionsClient> mock_sync_sessions_client_;
+ SyncedSessionTracker session_tracker_;
+ OpenTabsUIDelegateImpl delegate_;
+};
+
+TEST_F(OpenTabsUIDelegateImplTest, ShouldSortSessions) {
+ const base::Time kTime0 = base::Time::Now();
+
+ // Create three sessions, with one window and tab each.
+ session_tracker_.PutWindowInSession(kSessionTag1, kWindowId1);
+ session_tracker_.PutTabInWindow(kSessionTag1, kWindowId1, kTabId1);
+ session_tracker_.GetTab(kSessionTag1, kTabId1)
+ ->navigations.push_back(
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
+ "http://url1", "title1"));
+ session_tracker_.GetSession(kSessionTag1)->modified_time =
+ kTime0 + base::TimeDelta::FromSeconds(3);
+
+ session_tracker_.PutWindowInSession(kSessionTag2, kWindowId2);
+ session_tracker_.PutTabInWindow(kSessionTag2, kWindowId2, kTabId2);
+ session_tracker_.GetTab(kSessionTag2, kTabId2)
+ ->navigations.push_back(
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
+ "http://url2", "title2"));
+ session_tracker_.GetSession(kSessionTag2)->modified_time =
+ kTime0 + base::TimeDelta::FromSeconds(1);
+
+ session_tracker_.PutWindowInSession(kSessionTag3, kWindowId3);
+ session_tracker_.PutTabInWindow(kSessionTag3, kWindowId3, kTabId3);
+ session_tracker_.GetTab(kSessionTag3, kTabId3)
+ ->navigations.push_back(
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
+ "http://url3", "title3"));
+ session_tracker_.GetSession(kSessionTag3)->modified_time =
+ kTime0 + base::TimeDelta::FromSeconds(2);
+
+ std::vector<const SyncedSession*> sessions;
+ EXPECT_TRUE(delegate_.GetAllForeignSessions(&sessions));
+ EXPECT_THAT(sessions,
+ ElementsAre(Field(&SyncedSession::session_tag, kSessionTag1),
+ Field(&SyncedSession::session_tag, kSessionTag3),
+ Field(&SyncedSession::session_tag, kSessionTag2)));
+}
+
+TEST_F(OpenTabsUIDelegateImplTest, ShouldSortTabs) {
+ const base::Time kTime0 = base::Time::Now();
+ session_tracker_.PutWindowInSession(kSessionTag1, kWindowId1);
+ session_tracker_.PutWindowInSession(kSessionTag1, kWindowId2);
+ session_tracker_.PutTabInWindow(kSessionTag1, kWindowId1, kTabId1);
+ session_tracker_.PutTabInWindow(kSessionTag1, kWindowId2, kTabId2);
+ session_tracker_.PutTabInWindow(kSessionTag1, kWindowId2, kTabId3);
+
+ sessions::SessionTab* tab1 = session_tracker_.GetTab(kSessionTag1, kTabId1);
+ tab1->navigations.push_back(
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
+ "http://url1", "title1"));
+ tab1->timestamp = kTime0 + base::TimeDelta::FromSeconds(3);
+
+ sessions::SessionTab* tab2 = session_tracker_.GetTab(kSessionTag1, kTabId2);
+ tab2->navigations.push_back(
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
+ "http://url1", "title1"));
+ tab2->timestamp = kTime0 + base::TimeDelta::FromSeconds(1);
+
+ sessions::SessionTab* tab3 = session_tracker_.GetTab(kSessionTag1, kTabId3);
+ tab3->navigations.push_back(
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
+ "http://url1", "title1"));
+ tab3->timestamp = kTime0 + base::TimeDelta::FromSeconds(2);
+
+ std::vector<const SessionTab*> tabs;
+ EXPECT_TRUE(delegate_.GetForeignSessionTabs(kSessionTag1, &tabs));
+ EXPECT_THAT(tabs,
+ ElementsAre(Pointee(Field(&SessionTab::tab_id,
+ Property(&SessionID::id, kTabId1))),
+ Pointee(Field(&SessionTab::tab_id,
+ Property(&SessionID::id, kTabId3))),
+ Pointee(Field(&SessionTab::tab_id,
+ Property(&SessionID::id, kTabId2)))));
+}
+
+TEST_F(OpenTabsUIDelegateImplTest, ShouldSkipNonPresentable) {
+ // Create two sessions, with one window and tab each, but only the second
+ // contains a navigation.
+ session_tracker_.PutWindowInSession(kSessionTag1, kWindowId1);
+ session_tracker_.PutTabInWindow(kSessionTag1, kWindowId1, kTabId1);
+ session_tracker_.GetTab(kSessionTag1, kTabId1);
+
+ session_tracker_.PutWindowInSession(kSessionTag2, kWindowId2);
+ session_tracker_.PutTabInWindow(kSessionTag2, kWindowId2, kTabId2);
+ session_tracker_.GetTab(kSessionTag2, kTabId2)
+ ->navigations.push_back(
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
+ "http://url2", "title2"));
+
+ std::vector<const SyncedSession*> sessions;
+ EXPECT_TRUE(delegate_.GetAllForeignSessions(&sessions));
+ EXPECT_THAT(sessions,
+ ElementsAre(Field(&SyncedSession::session_tag, kSessionTag2)));
+}
+
+TEST_F(OpenTabsUIDelegateImplTest, ShouldSkipNonSyncableTabs) {
+ ON_CALL(mock_sync_sessions_client_, ShouldSyncURL(GURL("http://url1")))
+ .WillByDefault(testing::Return(false));
+
+ // Create two sessions, with one window and tab each. The first of the two
+ // contains a URL that should not be synced.
+ session_tracker_.PutWindowInSession(kSessionTag1, kWindowId1);
+ session_tracker_.PutTabInWindow(kSessionTag1, kWindowId1, kTabId1);
+ session_tracker_.GetTab(kSessionTag1, kTabId1)
+ ->navigations.push_back(
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
+ "http://url1", "title1"));
+
+ session_tracker_.PutWindowInSession(kSessionTag2, kWindowId2);
+ session_tracker_.PutTabInWindow(kSessionTag2, kWindowId2, kTabId2);
+ session_tracker_.GetTab(kSessionTag2, kTabId2)
+ ->navigations.push_back(
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
+ "http://url2", "title2"));
+
+ std::vector<const SyncedSession*> sessions;
+ EXPECT_TRUE(delegate_.GetAllForeignSessions(&sessions));
+ EXPECT_THAT(sessions,
+ ElementsAre(Field(&SyncedSession::session_tag, kSessionTag2)));
+}
+
+} // namespace
+} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/bookmarks_by_url_provider_impl.cc b/chromium/components/sync_sessions/revisit/bookmarks_by_url_provider_impl.cc
deleted file mode 100644
index 7d234cd64ef..00000000000
--- a/chromium/components/sync_sessions/revisit/bookmarks_by_url_provider_impl.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/bookmarks_by_url_provider_impl.h"
-
-#include "components/bookmarks/browser/bookmark_model.h"
-#include "components/bookmarks/browser/bookmark_node.h"
-#include "url/gurl.h"
-
-namespace sync_sessions {
-
-BookmarksByUrlProviderImpl::BookmarksByUrlProviderImpl(
- bookmarks::BookmarkModel* model)
- : model_(model) {}
-
-void BookmarksByUrlProviderImpl::GetNodesByURL(
- const GURL& url,
- std::vector<const bookmarks::BookmarkNode*>* nodes) {
- model_->GetNodesByURL(url, nodes);
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/bookmarks_by_url_provider_impl.h b/chromium/components/sync_sessions/revisit/bookmarks_by_url_provider_impl.h
deleted file mode 100644
index 45252d32b44..00000000000
--- a/chromium/components/sync_sessions/revisit/bookmarks_by_url_provider_impl.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SYNC_SESSIONS_REVISIT_BOOKMARKS_BY_URL_PROVIDER_IMPL_H_
-#define COMPONENTS_SYNC_SESSIONS_REVISIT_BOOKMARKS_BY_URL_PROVIDER_IMPL_H_
-
-#include <vector>
-
-#include "base/macros.h"
-#include "components/sync_sessions/revisit/bookmarks_page_revisit_observer.h"
-
-class GURL;
-
-namespace bookmarks {
-class BookmarkModel;
-class BookmarkNode;
-} // namespace bookmarks
-
-namespace sync_sessions {
-
-// Simple implementation of BookmarksByUrlProvider that delegates to a
-// BookmarkModel. It holds a non-owning pointer, with the assumption that this
-// object is destroyed before the BookmarkModel.
-class BookmarksByUrlProviderImpl : public BookmarksByUrlProvider {
- public:
- explicit BookmarksByUrlProviderImpl(bookmarks::BookmarkModel* model);
- void GetNodesByURL(
- const GURL& url,
- std::vector<const bookmarks::BookmarkNode*>* nodes) override;
-
- private:
- bookmarks::BookmarkModel* model_;
- DISALLOW_COPY_AND_ASSIGN(BookmarksByUrlProviderImpl);
-};
-
-} // namespace sync_sessions
-
-#endif // COMPONENTS_SYNC_SESSIONS_REVISIT_BOOKMARKS_BY_URL_PROVIDER_IMPL_H_
diff --git a/chromium/components/sync_sessions/revisit/bookmarks_page_revisit_observer.cc b/chromium/components/sync_sessions/revisit/bookmarks_page_revisit_observer.cc
deleted file mode 100644
index 813348a85e9..00000000000
--- a/chromium/components/sync_sessions/revisit/bookmarks_page_revisit_observer.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/bookmarks_page_revisit_observer.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "base/metrics/histogram_macros.h"
-#include "base/time/time.h"
-#include "components/bookmarks/browser/bookmark_model.h"
-#include "components/bookmarks/browser/bookmark_node.h"
-#include "url/gurl.h"
-
-namespace sync_sessions {
-
-BookmarksPageRevisitObserver::BookmarksPageRevisitObserver(
- std::unique_ptr<BookmarksByUrlProvider> provider)
- : provider_(std::move(provider)) {}
-
-BookmarksPageRevisitObserver::~BookmarksPageRevisitObserver() {}
-
-void BookmarksPageRevisitObserver::OnPageVisit(
- const GURL& url,
- const TransitionType transition) {
- base::TimeTicks start(base::TimeTicks::Now());
-
- std::vector<const bookmarks::BookmarkNode*> nodes;
- provider_->GetNodesByURL(url, &nodes);
- if (nodes.empty()) {
- UMA_HISTOGRAM_ENUMERATION("Sync.PageRevisitBookmarksMissTransition",
- transition,
- PageVisitObserver::kTransitionTypeLast);
- } else {
- auto last_added = std::max_element(
- nodes.begin(), nodes.end(),
- [](const bookmarks::BookmarkNode* a, const bookmarks::BookmarkNode* b) {
- return a->date_added() < b->date_added();
- });
- REVISIT_HISTOGRAM_AGE("Sync.PageRevisitBookmarksMatchAge",
- (*last_added)->date_added());
- UMA_HISTOGRAM_ENUMERATION("Sync.PageRevisitBookmarksMatchTransition",
- transition,
- PageVisitObserver::kTransitionTypeLast);
- }
-
- base::TimeDelta duration(base::TimeTicks::Now() - start);
- UMA_HISTOGRAM_TIMES("Sync.PageRevisitBookmarksDuration", duration);
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/bookmarks_page_revisit_observer.h b/chromium/components/sync_sessions/revisit/bookmarks_page_revisit_observer.h
deleted file mode 100644
index e0161495e13..00000000000
--- a/chromium/components/sync_sessions/revisit/bookmarks_page_revisit_observer.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SYNC_SESSIONS_REVISIT_BOOKMARKS_PAGE_REVISIT_OBSERVER_H_
-#define COMPONENTS_SYNC_SESSIONS_REVISIT_BOOKMARKS_PAGE_REVISIT_OBSERVER_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "components/sync_sessions/revisit/page_visit_observer.h"
-
-class GURL;
-
-namespace bookmarks {
-class BookmarkNode;
-} // namespace bookmarks
-
-namespace sync_sessions {
-
-// A simple interface to abstract away who is providing bookmarks.
-class BookmarksByUrlProvider {
- public:
- // Fills the passed vector with all bookmark nodes for the given URL.
- virtual void GetNodesByURL(
- const GURL& url,
- std::vector<const bookmarks::BookmarkNode*>* nodes) = 0;
- virtual ~BookmarksByUrlProvider() {}
-};
-
-// Responds to OnPageVisit events by looking for bookmarks with matching URLs,
-// and emits metrics about the results. If multiple bookmarks match, the most
-// recently created one is used. Currently there isn't enough information to
-// determine modificatoin times or remote vs local. This observer does all
-// processing in task/thread, which is okay since it only accesses values in
-// memory. Potential slow downs could occur when it fails to get bookmarks lock
-// and when the number of matching Bookmarks for a single URL is very large.
-class BookmarksPageRevisitObserver : public PageVisitObserver {
- public:
- explicit BookmarksPageRevisitObserver(
- std::unique_ptr<BookmarksByUrlProvider> provider);
- ~BookmarksPageRevisitObserver() override;
- void OnPageVisit(const GURL& url, const TransitionType transition) override;
-
- private:
- std::unique_ptr<BookmarksByUrlProvider> provider_;
- DISALLOW_COPY_AND_ASSIGN(BookmarksPageRevisitObserver);
-};
-
-} // namespace sync_sessions
-
-#endif // COMPONENTS_SYNC_SESSIONS_REVISIT_BOOKMARKS_PAGE_REVISIT_OBSERVER_H_
diff --git a/chromium/components/sync_sessions/revisit/bookmarks_page_revisit_observer_unittest.cc b/chromium/components/sync_sessions/revisit/bookmarks_page_revisit_observer_unittest.cc
deleted file mode 100644
index e9dd2cea622..00000000000
--- a/chromium/components/sync_sessions/revisit/bookmarks_page_revisit_observer_unittest.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/bookmarks_page_revisit_observer.h"
-
-#include "base/test/histogram_tester.h"
-#include "components/bookmarks/browser/bookmark_node.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace sync_sessions {
-
-namespace {
-
-static const GURL kExampleGurl = GURL("http://www.example.com");
-
-class TestBookmarksByUrlProvider : public BookmarksByUrlProvider {
- public:
- TestBookmarksByUrlProvider(
- const std::vector<const bookmarks::BookmarkNode*>& nodes)
- : nodes_(nodes) {}
- void GetNodesByURL(
- const GURL& url,
- std::vector<const bookmarks::BookmarkNode*>* nodes) override {
- *nodes = nodes_;
- }
-
- private:
- const std::vector<const bookmarks::BookmarkNode*>& nodes_;
-};
-
-} // namespace
-
-void RunObserver(const std::vector<const bookmarks::BookmarkNode*>& nodes) {
- BookmarksPageRevisitObserver observer(
- std::make_unique<TestBookmarksByUrlProvider>(nodes));
- observer.OnPageVisit(kExampleGurl, PageVisitObserver::kTransitionPage);
-}
-
-void ExpectMiss(const std::vector<const bookmarks::BookmarkNode*>& nodes) {
- base::HistogramTester histogram_tester;
- RunObserver(nodes);
- histogram_tester.ExpectUniqueSample("Sync.PageRevisitBookmarksMissTransition",
- PageVisitObserver::kTransitionPage, 1);
- histogram_tester.ExpectTotalCount("Sync.PageRevisitBookmarksDuration", 1);
-}
-
-void ExpectMatch(const std::vector<const bookmarks::BookmarkNode*>& nodes) {
- base::HistogramTester histogram_tester;
- RunObserver(nodes);
- histogram_tester.ExpectTotalCount("Sync.PageRevisitBookmarksMatchAge", 1);
- histogram_tester.ExpectUniqueSample(
- "Sync.PageRevisitBookmarksMatchTransition",
- PageVisitObserver::kTransitionPage, 1);
- histogram_tester.ExpectTotalCount("Sync.PageRevisitBookmarksDuration", 1);
-}
-
-TEST(BookmarksPageRevisitObserver, NoMatchingBookmarks) {
- std::vector<const bookmarks::BookmarkNode*> nodes;
- ExpectMiss(nodes);
-}
-
-TEST(BookmarksPageRevisitObserver, OneMatchingBookmark) {
- bookmarks::BookmarkNode node(kExampleGurl);
- std::vector<const bookmarks::BookmarkNode*> nodes;
- nodes.push_back(&node);
- ExpectMatch(nodes);
-}
-
-TEST(BookmarksPageRevisitObserver, MultipleMatchingBookmarks) {
- bookmarks::BookmarkNode node1(kExampleGurl);
- bookmarks::BookmarkNode node2(kExampleGurl);
- std::vector<const bookmarks::BookmarkNode*> nodes;
- nodes.push_back(&node1);
- nodes.push_back(&node2);
- ExpectMatch(nodes);
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/current_tab_matcher.cc b/chromium/components/sync_sessions/revisit/current_tab_matcher.cc
deleted file mode 100644
index 2f70eb344c9..00000000000
--- a/chromium/components/sync_sessions/revisit/current_tab_matcher.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/current_tab_matcher.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "base/time/time.h"
-#include "components/sessions/core/serialized_navigation_entry.h"
-#include "components/sessions/core/session_types.h"
-
-namespace sync_sessions {
-
-CurrentTabMatcher::CurrentTabMatcher(const PageEquality& page_equality)
- : page_equality_(page_equality) {}
-
-void CurrentTabMatcher::Check(const sessions::SessionTab* tab) {
- if (tab->navigations.empty()) {
- return;
- }
- const sessions::SerializedNavigationEntry& currentEntry =
- tab->navigations[tab->normalized_navigation_index()];
- // Cannot rely on SerializedNavigationEntry timestamps, they're
- // not set for foreign sessions. Instead rely on tab timestamps.
- if (page_equality_.IsSamePage(currentEntry.virtual_url()) &&
- (most_recent_match_ == nullptr ||
- tab->timestamp > most_recent_match_->timestamp)) {
- most_recent_match_ = tab;
- }
-}
-
-void CurrentTabMatcher::Emit(
- const PageVisitObserver::TransitionType transition) {
- if (most_recent_match_ == nullptr) {
- UMA_HISTOGRAM_ENUMERATION("Sync.PageRevisitTabMissTransition", transition,
- PageVisitObserver::kTransitionTypeLast);
- } else {
- REVISIT_HISTOGRAM_AGE("Sync.PageRevisitTabMatchAge",
- most_recent_match_->timestamp);
- UMA_HISTOGRAM_ENUMERATION("Sync.PageRevisitTabMatchTransition", transition,
- PageVisitObserver::kTransitionTypeLast);
- }
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/current_tab_matcher.h b/chromium/components/sync_sessions/revisit/current_tab_matcher.h
deleted file mode 100644
index 2aa037c81f2..00000000000
--- a/chromium/components/sync_sessions/revisit/current_tab_matcher.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SYNC_SESSIONS_REVISIT_CURRENT_TAB_MATCHER_H_
-#define COMPONENTS_SYNC_SESSIONS_REVISIT_CURRENT_TAB_MATCHER_H_
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "components/sync_sessions/revisit/page_equality.h"
-#include "components/sync_sessions/revisit/page_visit_observer.h"
-
-namespace sessions {
-struct SessionTab;
-}; // namespace sessions
-
-namespace sync_sessions {
-
-// This class checks the current navigation entry for the given tabs to see if
-// they correspond to the same page we were constructed to look for. Upon
-// finding multiple matches, the most recently modified will be chosen.
-class CurrentTabMatcher {
- public:
- explicit CurrentTabMatcher(const PageEquality& page_equality);
- void Check(const sessions::SessionTab* tab);
- void Emit(const PageVisitObserver::TransitionType transition);
-
- private:
- FRIEND_TEST_ALL_PREFIXES(CurrentTabMatcherTest, Timestamp);
-
- const PageEquality page_equality_;
- const sessions::SessionTab* most_recent_match_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(CurrentTabMatcher);
-};
-
-} // namespace sync_sessions
-
-#endif // COMPONENTS_SYNC_SESSIONS_REVISIT_CURRENT_TAB_MATCHER_H_
diff --git a/chromium/components/sync_sessions/revisit/current_tab_matcher_unittest.cc b/chromium/components/sync_sessions/revisit/current_tab_matcher_unittest.cc
deleted file mode 100644
index 4add6b797e0..00000000000
--- a/chromium/components/sync_sessions/revisit/current_tab_matcher_unittest.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/current_tab_matcher.h"
-
-#include <memory>
-#include <string>
-
-#include "base/test/histogram_tester.h"
-#include "base/time/time.h"
-#include "components/sessions/core/serialized_navigation_entry.h"
-#include "components/sessions/core/serialized_navigation_entry_test_helper.h"
-#include "components/sessions/core/session_types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-using sessions::SessionTab;
-
-namespace sync_sessions {
-
-namespace {
-
-const char kExampleUrl[] = "http://www.example.com";
-const char kDifferentUrl[] = "http://www.different.com";
-
-sessions::SerializedNavigationEntry Entry(const std::string& url) {
- return sessions::SerializedNavigationEntryTestHelper::CreateNavigation(url,
- "");
-}
-
-std::unique_ptr<SessionTab> Tab(const int index, const base::Time timestamp) {
- std::unique_ptr<SessionTab> tab(new SessionTab());
- tab->current_navigation_index = index;
- tab->timestamp = timestamp;
- return tab;
-}
-
-void VerifyMatch(CurrentTabMatcher* matcher) {
- base::HistogramTester histogram_tester;
- matcher->Emit(PageVisitObserver::kTransitionPage);
- histogram_tester.ExpectUniqueSample("Sync.PageRevisitTabMatchTransition",
- PageVisitObserver::kTransitionPage, 1);
- histogram_tester.ExpectTotalCount("Sync.PageRevisitTabMatchAge", 1);
-}
-
-void VerifyMiss(CurrentTabMatcher* matcher) {
- base::HistogramTester histogram_tester;
- matcher->Emit(PageVisitObserver::kTransitionPage);
- histogram_tester.ExpectUniqueSample("Sync.PageRevisitTabMissTransition",
- PageVisitObserver::kTransitionPage, 1);
-}
-
-} // namespace
-
-TEST(CurrentTabMatcherTest, NoCheck) {
- CurrentTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- VerifyMiss(&matcher);
-}
-
-TEST(CurrentTabMatcherTest, EmptyTab) {
- std::unique_ptr<SessionTab> tab = Tab(0, base::Time::Now());
- CurrentTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab.get());
- VerifyMiss(&matcher);
-}
-
-TEST(CurrentTabMatcherTest, SameUrl) {
- std::unique_ptr<SessionTab> tab = Tab(0, base::Time::Now());
- tab->navigations.push_back(Entry(kExampleUrl));
-
- CurrentTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab.get());
- VerifyMatch(&matcher);
-}
-
-TEST(CurrentTabMatcherTest, DifferentUrl) {
- std::unique_ptr<SessionTab> tab = Tab(0, base::Time::Now());
- tab->navigations.push_back(Entry(kDifferentUrl));
-
- CurrentTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab.get());
- VerifyMiss(&matcher);
-}
-
-TEST(CurrentTabMatcherTest, DifferentIndex) {
- std::unique_ptr<SessionTab> tab = Tab(0, base::Time::Now());
- tab->navigations.push_back(Entry(kDifferentUrl));
- tab->navigations.push_back(Entry(kExampleUrl));
-
- CurrentTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab.get());
- VerifyMiss(&matcher);
-}
-
-TEST(CurrentTabMatcherTest, Timestamp) {
- std::unique_ptr<SessionTab> tab1 = Tab(0, base::Time::UnixEpoch());
- tab1->navigations.push_back(Entry(kExampleUrl));
-
- std::unique_ptr<SessionTab> tab2 = Tab(0, base::Time::Now());
- tab2->navigations.push_back(Entry(kExampleUrl));
-
- CurrentTabMatcher matcher1((PageEquality(GURL(kExampleUrl))));
- matcher1.Check(tab1.get());
- matcher1.Check(tab2.get());
- ASSERT_EQ(tab2.get(), matcher1.most_recent_match_);
-
- // Now repeat the same test but check the tabs in the opposite order.
- CurrentTabMatcher matcher2((PageEquality(GURL(kExampleUrl))));
- matcher2.Check(tab2.get());
- matcher2.Check(tab1.get());
- ASSERT_EQ(tab2.get(), matcher2.most_recent_match_);
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/offset_tab_matcher.cc b/chromium/components/sync_sessions/revisit/offset_tab_matcher.cc
deleted file mode 100644
index 545f2ef0152..00000000000
--- a/chromium/components/sync_sessions/revisit/offset_tab_matcher.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/offset_tab_matcher.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-
-#include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
-#include "components/sessions/core/serialized_navigation_entry.h"
-#include "components/sessions/core/session_types.h"
-
-namespace sync_sessions {
-
-namespace {
-
-// This is an upper bound of the max size of positive offset we will emit
-// correct metrics for. Anything larger than this will be clamped to this value.
-// This value doesn't exactly correspond to what we actually expect, this value
-// is currently larger than expected. This value is more for the safety of our
-// sparse histogram usage. It is assumed that the max negative offset is
-// symmetrical and can be found by taking the negative of this value.
-const int kMaxOffset = 10;
-
-} // namespace
-
-OffsetTabMatcher::OffsetTabMatcher(const PageEquality& page_equality)
- : page_equality_(page_equality) {}
-
-void OffsetTabMatcher::Check(const sessions::SessionTab* tab) {
- const int current_index = tab->normalized_navigation_index();
- for (std::size_t i = 0; i < tab->navigations.size(); ++i) {
- // Ignore the entry if it is the current entry. There's actually some
- // ambiguity here, the index of a tab is located in two places. Hopefully
- // they are equal, but it is possible for the index() accessor of an entry
- // to be different from the index in the tab's vector. Theoretically this
- // should not happen outside of tab construction logic, but to be safe all
- // matcher logic treats the index in the vector as the authoritative index.
- // We chose this because the other matcher wants efficient random access.
- if (current_index >= 0 && (std::size_t)current_index == i) {
- continue;
- }
- const int offset = i - current_index;
- if (page_equality_.IsSamePage(tab->navigations[i].virtual_url()) &&
- (best_tab_ == nullptr || best_tab_->timestamp < tab->timestamp ||
- (best_tab_->timestamp == tab->timestamp && best_offset_ < offset))) {
- best_tab_ = tab;
- best_offset_ = offset;
- }
- }
-}
-
-void OffsetTabMatcher::Emit(
- const PageVisitObserver::TransitionType transition) {
- if (best_tab_ == nullptr) {
- UMA_HISTOGRAM_ENUMERATION("Sync.PageRevisitNavigationMissTransition",
- transition,
- PageVisitObserver::kTransitionTypeLast);
- } else {
- // The sparse macro allows us to handle negative offsets. However, we need
- // to be careful when doing this because of the unrestricted nature of
- // sparse we could end up with a very large output space across many
- // clients. So we clamp on a resonable bound that's larger than we expect to
- // be sure no unexpected data causes problems.
- base::UmaHistogramSparse("Sync.PageRevisitNavigationMatchOffset",
- Clamp(best_offset_, -kMaxOffset, kMaxOffset));
- REVISIT_HISTOGRAM_AGE("Sync.PageRevisitNavigationMatchAge",
- best_tab_->timestamp);
- UMA_HISTOGRAM_ENUMERATION("Sync.PageRevisitNavigationMatchTransition",
- transition,
- PageVisitObserver::kTransitionTypeLast);
- }
-}
-
-int OffsetTabMatcher::Clamp(const int input, const int lower, const int upper) {
- return std::max(lower, std::min(upper, input));
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/offset_tab_matcher.h b/chromium/components/sync_sessions/revisit/offset_tab_matcher.h
deleted file mode 100644
index 725b05bf27a..00000000000
--- a/chromium/components/sync_sessions/revisit/offset_tab_matcher.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SYNC_SESSIONS_REVISIT_OFFSET_TAB_MATCHER_H_
-#define COMPONENTS_SYNC_SESSIONS_REVISIT_OFFSET_TAB_MATCHER_H_
-
-#include "base/macros.h"
-#include "components/sync_sessions/revisit/page_equality.h"
-#include "components/sync_sessions/revisit/page_visit_observer.h"
-
-namespace sessions {
-struct SessionTab;
-}; // namespace sessions
-
-namespace sync_sessions {
-
-// This class looks for tabs that have matching pages that are not the current
-// navigation entry. This corresponds to the pages you would arrive at if you
-// pressed the forward/backwards buttons. The goal is to emit metrics for the
-// most recent/current entry. So to break ties of multiple entries that match,
-// first the timestamp on the tab is used, followed by the index of the entry.
-// This isn't necessarily perfect at determining the most recent, but it should
-// be a reasonable enough approximation.
-class OffsetTabMatcher {
- public:
- explicit OffsetTabMatcher(const PageEquality& page_equality);
- void Check(const sessions::SessionTab* tab);
- void Emit(const PageVisitObserver::TransitionType transition);
-
- private:
- int Clamp(int input, int lower, int upper);
-
- const PageEquality page_equality_;
- const sessions::SessionTab* best_tab_ = nullptr;
- // Invalid while best_tab_ is nullptr.
- int best_offset_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(OffsetTabMatcher);
-};
-
-} // namespace sync_sessions
-
-#endif // COMPONENTS_SYNC_SESSIONS_REVISIT_OFFSET_TAB_MATCHER_H_
diff --git a/chromium/components/sync_sessions/revisit/offset_tab_matcher_unittest.cc b/chromium/components/sync_sessions/revisit/offset_tab_matcher_unittest.cc
deleted file mode 100644
index 4388c29d241..00000000000
--- a/chromium/components/sync_sessions/revisit/offset_tab_matcher_unittest.cc
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/offset_tab_matcher.h"
-
-#include <memory>
-#include <string>
-
-#include "base/test/histogram_tester.h"
-#include "base/time/time.h"
-#include "components/sessions/core/serialized_navigation_entry.h"
-#include "components/sessions/core/serialized_navigation_entry_test_helper.h"
-#include "components/sessions/core/session_types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-using sessions::SessionTab;
-
-namespace sync_sessions {
-
-namespace {
-
-const char kExampleUrl[] = "http://www.example.com";
-const char kDifferentUrl[] = "http://www.different.com";
-
-sessions::SerializedNavigationEntry Entry(const std::string& url) {
- return sessions::SerializedNavigationEntryTestHelper::CreateNavigation(url,
- "");
-}
-
-std::unique_ptr<SessionTab> Tab(
- const int index,
- const base::Time timestamp = base::Time::Now()) {
- std::unique_ptr<SessionTab> tab(new SessionTab());
- tab->current_navigation_index = index;
- tab->timestamp = timestamp;
- return tab;
-}
-
-void VerifyMatch(OffsetTabMatcher* matcher, const int offset) {
- base::HistogramTester histogram_tester;
- matcher->Emit(PageVisitObserver::kTransitionPage);
- histogram_tester.ExpectUniqueSample("Sync.PageRevisitNavigationMatchOffset",
- offset, 1);
- histogram_tester.ExpectUniqueSample(
- "Sync.PageRevisitNavigationMatchTransition",
- PageVisitObserver::kTransitionPage, 1);
- histogram_tester.ExpectTotalCount("Sync.PageRevisitNavigationMatchAge", 1);
-}
-
-void VerifyMiss(OffsetTabMatcher* matcher) {
- base::HistogramTester histogram_tester;
- matcher->Emit(PageVisitObserver::kTransitionPage);
- histogram_tester.ExpectUniqueSample(
- "Sync.PageRevisitNavigationMissTransition",
- PageVisitObserver::kTransitionPage, 1);
-}
-
-} // namespace
-
-TEST(OffsetTabMatcherTest, NoCheck) {
- OffsetTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- VerifyMiss(&matcher);
-}
-
-TEST(OffsetTabMatcherTest, EmptyTab) {
- std::unique_ptr<SessionTab> tab = Tab(0);
- OffsetTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab.get());
- VerifyMiss(&matcher);
-}
-
-TEST(OffsetTabMatcherTest, HasMatchForward) {
- std::unique_ptr<SessionTab> tab = Tab(0);
- tab->navigations.push_back(Entry(kDifferentUrl));
- tab->navigations.push_back(Entry(kExampleUrl));
-
- OffsetTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab.get());
- VerifyMatch(&matcher, 1);
-}
-
-TEST(OffsetTabMatcherTest, HasMatchBackward) {
- std::unique_ptr<SessionTab> tab = Tab(1);
- tab->navigations.push_back(Entry(kExampleUrl));
- tab->navigations.push_back(Entry(kDifferentUrl));
-
- OffsetTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab.get());
- VerifyMatch(&matcher, -1);
-}
-
-TEST(OffsetTabMatcherTest, NoMatch) {
- std::unique_ptr<SessionTab> tab = Tab(0);
- tab->navigations.push_back(Entry(kExampleUrl));
- tab->navigations.push_back(Entry(kDifferentUrl));
-
- OffsetTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab.get());
- VerifyMiss(&matcher);
-}
-
-TEST(OffsetTabMatcherTest, MultipleBackwardOffsets) {
- std::unique_ptr<SessionTab> tab = Tab(4);
- tab->navigations.push_back(Entry(kExampleUrl));
- tab->navigations.push_back(Entry(kExampleUrl));
- tab->navigations.push_back(Entry(kExampleUrl)); // Expected.
- tab->navigations.push_back(Entry(kDifferentUrl));
- tab->navigations.push_back(Entry(kExampleUrl)); // Current.
-
- OffsetTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab.get());
- VerifyMatch(&matcher, -2);
-}
-
-TEST(OffsetTabMatcherTest, MultipleOffsets) {
- std::unique_ptr<SessionTab> tab = Tab(1);
- tab->navigations.push_back(Entry(kExampleUrl));
- tab->navigations.push_back(Entry(kExampleUrl)); // Current.
- tab->navigations.push_back(Entry(kExampleUrl));
- tab->navigations.push_back(Entry(kExampleUrl)); // Expected.
- tab->navigations.push_back(Entry(kDifferentUrl));
-
- OffsetTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab.get());
- VerifyMatch(&matcher, 2);
-}
-
-TEST(OffsetTabMatcherTest, VeryForwardOffset) {
- std::unique_ptr<SessionTab> tab = Tab(0);
- for (int i = 0; i < 20; i++) {
- tab->navigations.push_back(Entry(kDifferentUrl));
- }
- tab->navigations.push_back(Entry(kExampleUrl));
-
- OffsetTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab.get());
- // Expect the offset to be clamped to +10.
- VerifyMatch(&matcher, 10);
-}
-
-TEST(OffsetTabMatcherTest, VeryBackwardOffset) {
- std::unique_ptr<SessionTab> tab = Tab(20);
- tab->navigations.push_back(Entry(kExampleUrl));
- for (int i = 0; i < 20; i++) {
- tab->navigations.push_back(Entry(kDifferentUrl));
- }
-
- OffsetTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab.get());
- // Expect the offset to be clamped to -10.
- VerifyMatch(&matcher, -10);
-}
-
-TEST(OffsetTabMatcherTest, MultipleTabs) {
- std::unique_ptr<SessionTab> tab1 = Tab(0, base::Time::UnixEpoch());
- tab1->navigations.push_back(Entry(kExampleUrl));
- tab1->navigations.push_back(Entry(kExampleUrl));
-
- std::unique_ptr<SessionTab> tab2 = Tab(1, base::Time::Now());
- tab2->navigations.push_back(Entry(kExampleUrl));
- tab2->navigations.push_back(Entry(kExampleUrl));
-
- OffsetTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab1.get());
- matcher.Check(tab2.get());
- VerifyMatch(&matcher, -1);
-}
-
-TEST(OffsetTabMatcherTest, MultipleTabsSameTime) {
- base::Time shared_now = base::Time::Now();
-
- std::unique_ptr<SessionTab> tab1 = Tab(0, shared_now);
- tab1->navigations.push_back(Entry(kExampleUrl));
- tab1->navigations.push_back(Entry(kExampleUrl));
-
- std::unique_ptr<SessionTab> tab2 = Tab(1, shared_now);
- tab2->navigations.push_back(Entry(kExampleUrl));
- tab2->navigations.push_back(Entry(kExampleUrl));
-
- OffsetTabMatcher matcher((PageEquality(GURL(kExampleUrl))));
- matcher.Check(tab1.get());
- matcher.Check(tab2.get());
- VerifyMatch(&matcher, 1);
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/page_equality.h b/chromium/components/sync_sessions/revisit/page_equality.h
deleted file mode 100644
index 6f678277198..00000000000
--- a/chromium/components/sync_sessions/revisit/page_equality.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SYNC_SESSIONS_REVISIT_PAGE_EQUALITY_H_
-#define COMPONENTS_SYNC_SESSIONS_REVISIT_PAGE_EQUALITY_H_
-
-#include "url/gurl.h"
-
-namespace sync_sessions {
-
-// An extremely simplistic approach to determining page equality, given two
-// URLs. Some of the notable examples this fails to accommodate are varying
-// schemes, mobile subdomains, unimpactful query parameters/fragments, and
-// page changing headers/cookies.
-class PageEquality {
- public:
- explicit PageEquality(const GURL& url) : url_(url) {}
- PageEquality(const PageEquality&) = default;
- bool IsSamePage(const GURL& url) const { return url == url_; }
-
- private:
- const GURL url_;
-};
-
-} // namespace sync_sessions
-
-#endif // COMPONENTS_SYNC_SESSIONS_REVISIT_PAGE_EQUALITY_H_
diff --git a/chromium/components/sync_sessions/revisit/page_revisit_broadcaster.cc b/chromium/components/sync_sessions/revisit/page_revisit_broadcaster.cc
deleted file mode 100644
index 77e4cdf63ea..00000000000
--- a/chromium/components/sync_sessions/revisit/page_revisit_broadcaster.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/page_revisit_broadcaster.h"
-
-#include <string>
-
-#include "base/metrics/field_trial.h"
-#include "components/bookmarks/browser/bookmark_model.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/sync_sessions/revisit/bookmarks_by_url_provider_impl.h"
-#include "components/sync_sessions/revisit/bookmarks_page_revisit_observer.h"
-#include "components/sync_sessions/revisit/sessions_page_revisit_observer.h"
-#include "components/sync_sessions/revisit/typed_url_page_revisit_observer.h"
-#include "components/sync_sessions/sessions_sync_manager.h"
-#include "components/sync_sessions/sync_sessions_client.h"
-
-namespace sync_sessions {
-
-namespace {
-
-// Simple implementation of ForeignSessionsProvider that delegates to
-// SessionsSyncManager. It holds onto a non-owning pointer, with the assumption
-// that this class is only used by classes owned by SessionsSyncManager itself.
-class SessionsSyncManagerWrapper : public ForeignSessionsProvider {
- public:
- explicit SessionsSyncManagerWrapper(SessionsSyncManager* manager)
- : manager_(manager) {}
- ~SessionsSyncManagerWrapper() override {}
- bool GetAllForeignSessions(
- std::vector<const SyncedSession*>* sessions) override {
- return manager_->GetAllForeignSessions(sessions);
- }
-
- private:
- SessionsSyncManager* manager_;
- DISALLOW_COPY_AND_ASSIGN(SessionsSyncManagerWrapper);
-};
-
-} // namespace
-
-PageRevisitBroadcaster::PageRevisitBroadcaster(
- SessionsSyncManager* manager,
- SyncSessionsClient* sessions_client)
- : sessions_client_(sessions_client) {
- const std::string group_name =
- base::FieldTrialList::FindFullName("PageRevisitInstrumentation");
- bool shouldInstrument = group_name == "Enabled";
- if (shouldInstrument) {
- revisit_observers_.push_back(std::make_unique<SessionsPageRevisitObserver>(
- std::make_unique<SessionsSyncManagerWrapper>(manager)));
-
- history::HistoryService* history = sessions_client_->GetHistoryService();
- if (history) {
- revisit_observers_.push_back(
- std::make_unique<TypedUrlPageRevisitObserver>(history));
- }
-
- bookmarks::BookmarkModel* bookmarks = sessions_client_->GetBookmarkModel();
- if (bookmarks) {
- revisit_observers_.push_back(
- std::make_unique<BookmarksPageRevisitObserver>(
- std::make_unique<BookmarksByUrlProviderImpl>(bookmarks)));
- }
- }
-}
-
-PageRevisitBroadcaster::~PageRevisitBroadcaster() {}
-
-void PageRevisitBroadcaster::OnPageVisit(const GURL& url,
- const ui::PageTransition transition) {
- if (sessions_client_->ShouldSyncURL(url)) {
- PageVisitObserver::TransitionType converted(
- ConvertTransitionEnum(transition));
- for (auto& observer : revisit_observers_) {
- observer->OnPageVisit(url, converted);
- }
- }
-}
-
-// Static
-PageVisitObserver::TransitionType PageRevisitBroadcaster::ConvertTransitionEnum(
- const ui::PageTransition original) {
- switch (ui::PageTransitionStripQualifier(original)) {
- case ui::PAGE_TRANSITION_LINK:
- if (original & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR) {
- return PageVisitObserver::kTransitionCopyPaste;
- } else {
- return PageVisitObserver::kTransitionPage;
- }
- case ui::PAGE_TRANSITION_TYPED:
- return PageVisitObserver::kTransitionOmniboxUrl;
-
- case ui::PAGE_TRANSITION_AUTO_BOOKMARK:
- return PageVisitObserver::kTransitionBookmark;
-
- case ui::PAGE_TRANSITION_AUTO_SUBFRAME:
- case ui::PAGE_TRANSITION_MANUAL_SUBFRAME:
- // These are not expected, we only expect top-level frame transitions.
- return PageVisitObserver::kTransitionUnknown;
-
- case ui::PAGE_TRANSITION_GENERATED:
- return PageVisitObserver::kTransitionOmniboxDefaultSearch;
-
- case ui::PAGE_TRANSITION_AUTO_TOPLEVEL:
- if (original & ui::PAGE_TRANSITION_FORWARD_BACK) {
- return PageVisitObserver::kTransitionForwardBackward;
- } else {
- return PageVisitObserver::kTransitionUnknown;
- }
-
- case ui::PAGE_TRANSITION_FORM_SUBMIT:
- return PageVisitObserver::kTransitionPage;
-
- case ui::PAGE_TRANSITION_RELOAD:
- // Refreshing pages also carry PAGE_TRANSITION_RELOAD but the url never
- // changes so we don't expect to ever get them.
- return PageVisitObserver::kTransitionRestore;
-
- case ui::PAGE_TRANSITION_KEYWORD:
- case ui::PAGE_TRANSITION_KEYWORD_GENERATED:
- return PageVisitObserver::kTransitionOmniboxTemplateSearch;
-
- default:
- return PageVisitObserver::kTransitionUnknown;
- }
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/page_revisit_broadcaster.h b/chromium/components/sync_sessions/revisit/page_revisit_broadcaster.h
deleted file mode 100644
index 150320c0622..00000000000
--- a/chromium/components/sync_sessions/revisit/page_revisit_broadcaster.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SYNC_SESSIONS_REVISIT_PAGE_REVISIT_BROADCASTER_H_
-#define COMPONENTS_SYNC_SESSIONS_REVISIT_PAGE_REVISIT_BROADCASTER_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "components/sync_sessions/revisit/page_visit_observer.h"
-#include "ui/base/page_transition_types.h"
-#include "url/gurl.h"
-
-namespace sync_sessions {
-class SyncSessionsClient;
-}
-
-namespace sync_sessions {
-
-class SessionsSyncManager;
-
-// This class has the job of creating and holding onto the PageVisitObservers
-// that are to be notified on page change for purposes of instrumenting
-// revisists.
-class PageRevisitBroadcaster {
- public:
- PageRevisitBroadcaster(SessionsSyncManager* manager,
- SyncSessionsClient* sessions_client);
- ~PageRevisitBroadcaster();
-
- // Broadcasts to all observers the given page visit event. Should only be
- // called when the url changes.
- void OnPageVisit(const GURL& url, const ui::PageTransition transition);
-
- private:
- friend class SyncPageRevisitBroadcasterTest;
-
- // We convert between enums here for a couple reasons. We don't want to force
- // observers to depend on ui/, and the high bit masks don't work for emitting
- // histograms. Some of the high bit masks correspond to cases we're
- // particularly interested in and want to treat as first class values.
- static PageVisitObserver::TransitionType ConvertTransitionEnum(
- const ui::PageTransition original);
-
- // The client of this sync sessions datatype.
- SyncSessionsClient* const sessions_client_;
-
- std::vector<std::unique_ptr<PageVisitObserver>> revisit_observers_;
-
- DISALLOW_COPY_AND_ASSIGN(PageRevisitBroadcaster);
-};
-
-} // namespace sync_sessions
-
-#endif // COMPONENTS_SYNC_SESSIONS_REVISIT_PAGE_REVISIT_BROADCASTER_H_
diff --git a/chromium/components/sync_sessions/revisit/page_revisit_broadcaster_unittest.cc b/chromium/components/sync_sessions/revisit/page_revisit_broadcaster_unittest.cc
deleted file mode 100644
index a2e13fd403c..00000000000
--- a/chromium/components/sync_sessions/revisit/page_revisit_broadcaster_unittest.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/page_revisit_broadcaster.h"
-
-#include <stdint.h>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace sync_sessions {
-
-class SyncPageRevisitBroadcasterTest : public ::testing::Test {
- protected:
- PageVisitObserver::TransitionType Convert(
- const ui::PageTransition conversionInput) {
- return PageRevisitBroadcaster::ConvertTransitionEnum(conversionInput);
- }
-
- void Check(const PageVisitObserver::TransitionType expected,
- const ui::PageTransition conversionInput) {
- EXPECT_EQ(expected, Convert(conversionInput));
- }
-
- void Check(const PageVisitObserver::TransitionType expected,
- const int32_t conversionInput) {
- Check(expected, ui::PageTransitionFromInt(conversionInput));
- }
-};
-
-TEST_F(SyncPageRevisitBroadcasterTest, ConvertPageInteraction) {
- Check(PageVisitObserver::kTransitionPage, ui::PAGE_TRANSITION_LINK);
- Check(PageVisitObserver::kTransitionPage,
- ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_BLOCKED);
- Check(PageVisitObserver::kTransitionPage,
- ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FORWARD_BACK);
- // Don't check ui::PAGE_TRANSITION_FROM_ADDRESS_BAR, this is actually a copy
- // and paste action when combined with ui::PAGE_TRANSITION_LINK.
- Check(PageVisitObserver::kTransitionPage,
- ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_HOME_PAGE);
- Check(PageVisitObserver::kTransitionPage,
- ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FROM_API);
- Check(PageVisitObserver::kTransitionPage,
- ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CHAIN_START);
- Check(PageVisitObserver::kTransitionPage,
- ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CHAIN_END);
- Check(PageVisitObserver::kTransitionPage,
- ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT);
- Check(PageVisitObserver::kTransitionPage,
- ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_SERVER_REDIRECT);
- Check(PageVisitObserver::kTransitionPage,
- ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_IS_REDIRECT_MASK);
-}
-
-TEST_F(SyncPageRevisitBroadcasterTest, ConvertOmniboxURL) {
- Check(PageVisitObserver::kTransitionOmniboxUrl, ui::PAGE_TRANSITION_TYPED);
- Check(PageVisitObserver::kTransitionOmniboxUrl,
- ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
-}
-
-TEST_F(SyncPageRevisitBroadcasterTest, ConvertOmniboxDefaultSearch) {
- Check(PageVisitObserver::kTransitionOmniboxDefaultSearch,
- ui::PAGE_TRANSITION_GENERATED);
- Check(PageVisitObserver::kTransitionOmniboxDefaultSearch,
- ui::PAGE_TRANSITION_GENERATED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
-}
-
-TEST_F(SyncPageRevisitBroadcasterTest, ConvertOmniboxTemplateSearch) {
- Check(PageVisitObserver::kTransitionOmniboxTemplateSearch,
- ui::PAGE_TRANSITION_KEYWORD);
- Check(PageVisitObserver::kTransitionOmniboxTemplateSearch,
- ui::PAGE_TRANSITION_KEYWORD | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
- Check(PageVisitObserver::kTransitionOmniboxTemplateSearch,
- ui::PAGE_TRANSITION_KEYWORD_GENERATED);
- Check(PageVisitObserver::kTransitionOmniboxTemplateSearch,
- ui::PAGE_TRANSITION_KEYWORD_GENERATED |
- ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
-}
-
-TEST_F(SyncPageRevisitBroadcasterTest, ConvertBookmark) {
- Check(PageVisitObserver::kTransitionBookmark,
- ui::PAGE_TRANSITION_AUTO_BOOKMARK);
-}
-
-TEST_F(SyncPageRevisitBroadcasterTest, ConvertCopyPaste) {
- Check(PageVisitObserver::kTransitionCopyPaste,
- ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
-}
-
-TEST_F(SyncPageRevisitBroadcasterTest, ConvertForwardBackward) {
- Check(PageVisitObserver::kTransitionForwardBackward,
- ui::PAGE_TRANSITION_AUTO_TOPLEVEL | ui::PAGE_TRANSITION_FORWARD_BACK);
-}
-
-TEST_F(SyncPageRevisitBroadcasterTest, ConvertRestore) {
- Check(PageVisitObserver::kTransitionRestore, ui::PAGE_TRANSITION_RELOAD);
-}
-
-TEST_F(SyncPageRevisitBroadcasterTest, ConvertUnknown) {
- Check(PageVisitObserver::kTransitionUnknown,
- ui::PAGE_TRANSITION_AUTO_SUBFRAME);
- Check(PageVisitObserver::kTransitionUnknown,
- ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
- Check(PageVisitObserver::kTransitionUnknown,
- ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/page_visit_observer.h b/chromium/components/sync_sessions/revisit/page_visit_observer.h
deleted file mode 100644
index 477d7245f1f..00000000000
--- a/chromium/components/sync_sessions/revisit/page_visit_observer.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SYNC_SESSIONS_REVISIT_PAGE_VISIT_OBSERVER_H_
-#define COMPONENTS_SYNC_SESSIONS_REVISIT_PAGE_VISIT_OBSERVER_H_
-
-#include <string>
-
-#include "base/metrics/histogram_macros.h"
-#include "base/time/time.h"
-
-class GURL;
-
-namespace sync_sessions {
-
-// The upper bound of 90 days and the bucket count of 100 try to strike a
-// balance. We want multiple single minute digit buckets, but also notice
-// differences that happen many weeks ago. It also helps that typed URLs age out
-// around 90 days, which makes these values even more fitting. These might not
-// handle bookmarks quite as elegantly, but we're less interested in knowing the
-// age of very old objects. This must be defind as a macro instead of a static
-// method because the histogram macro makes an inline static variable that must
-// be unique for separately named histograms.
-#define REVISIT_HISTOGRAM_AGE(name, timestamp) \
- UMA_HISTOGRAM_CUSTOM_COUNTS(name, \
- (base::Time::Now() - timestamp).InMinutes(), 1, \
- base::TimeDelta::FromDays(90).InMinutes(), 100)
-
-// An interface that allows observers to be notified when a page is visited.
-class PageVisitObserver {
- public:
- // This enum represents the most common ways to visit a new page/URL.
- enum TransitionType {
- kTransitionPage = 0,
- kTransitionOmniboxUrl = 1,
- kTransitionOmniboxDefaultSearch = 2,
- kTransitionOmniboxTemplateSearch = 3,
- kTransitionBookmark = 4,
- kTransitionCopyPaste = 5,
- kTransitionForwardBackward = 6,
- kTransitionRestore = 7,
- kTransitionUnknown = 8,
- kTransitionTypeLast = 9,
- };
-
- virtual ~PageVisitObserver() {}
- virtual void OnPageVisit(const GURL& url,
- const TransitionType transition) = 0;
-};
-
-} // namespace sync_sessions
-
-#endif // COMPONENTS_SYNC_SESSIONS_REVISIT_PAGE_VISIT_OBSERVER_H_
diff --git a/chromium/components/sync_sessions/revisit/sessions_page_revisit_observer.cc b/chromium/components/sync_sessions/revisit/sessions_page_revisit_observer.cc
deleted file mode 100644
index 1a99c70a7dd..00000000000
--- a/chromium/components/sync_sessions/revisit/sessions_page_revisit_observer.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/sessions_page_revisit_observer.h"
-
-#include <utility>
-
-#include "base/metrics/histogram_macros.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "components/sessions/core/session_types.h"
-#include "components/sync_sessions/revisit/current_tab_matcher.h"
-#include "components/sync_sessions/revisit/offset_tab_matcher.h"
-#include "components/sync_sessions/revisit/page_equality.h"
-#include "components/sync_sessions/synced_session.h"
-#include "url/gurl.h"
-
-namespace sync_sessions {
-
-SessionsPageRevisitObserver::SessionsPageRevisitObserver(
- std::unique_ptr<ForeignSessionsProvider> provider)
- : provider_(std::move(provider)) {}
-
-SessionsPageRevisitObserver::~SessionsPageRevisitObserver() {}
-
-void SessionsPageRevisitObserver::OnPageVisit(
- const GURL& url,
- const PageVisitObserver::TransitionType transition) {
- // We need to be invoked and eventually execute on the thread which owns the
- // session objects the provider will give us. However, this work is not
- // especially time sensitive, and so we post a task to perform this to get out
- // of the way of any currently executing logic.
-
- // Bind this task to this->AsWeakPtr() so that if we're destructed this task
- // just vanish instead of breaking things.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&SessionsPageRevisitObserver::CheckForRevisit,
- this->AsWeakPtr(), url, transition));
-}
-
-void SessionsPageRevisitObserver::CheckForRevisit(
- const GURL& url,
- const PageVisitObserver::TransitionType transition) {
- base::TimeTicks start(base::TimeTicks::Now());
-
- // We want to match tabs/navigation entries in two slightly different ways. We
- // value the current url/navigation entry of a tab more highly, and want to
- // actually seperate metrics from the backwards/forwards entries. And then
- // to make things a little bit messier, we only have an accurate modified time
- // for the tabs/current entries. So use index offset for forward/back entries.
- PageEquality page_equality(url);
- CurrentTabMatcher current_matcher(page_equality);
- OffsetTabMatcher offset_matcher(page_equality);
-
- std::vector<const SyncedSession*> foreign_sessions;
- if (provider_->GetAllForeignSessions(&foreign_sessions)) {
- for (const SyncedSession* session : foreign_sessions) {
- for (const auto& key_value : session->windows) {
- for (const auto& tab : key_value.second->wrapped_window.tabs) {
- // These matchers look identical and could easily implement an
- // interface and we could iterate through a vector of matchers here.
- // However this would cause quite a bit of overhead at the inner most
- // loop of something that takes linear time in relation to the number
- // of open foreign tabs. A small fraction of users have thousands of
- // open tabs.
- current_matcher.Check(tab.get());
- offset_matcher.Check(tab.get());
- }
- }
- }
- }
-
- // emit even if there are no foreign sessions so that that counts all match.
- current_matcher.Emit(transition);
- offset_matcher.Emit(transition);
-
- base::TimeDelta duration(base::TimeTicks::Now() - start);
- UMA_HISTOGRAM_TIMES("Sync.PageRevisitSessionDuration", duration);
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/sessions_page_revisit_observer.h b/chromium/components/sync_sessions/revisit/sessions_page_revisit_observer.h
deleted file mode 100644
index 87d653e2d0c..00000000000
--- a/chromium/components/sync_sessions/revisit/sessions_page_revisit_observer.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SYNC_SESSIONS_REVISIT_SESSIONS_PAGE_REVISIT_OBSERVER_H_
-#define COMPONENTS_SYNC_SESSIONS_REVISIT_SESSIONS_PAGE_REVISIT_OBSERVER_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "components/sync_sessions/revisit/page_visit_observer.h"
-
-class GURL;
-
-namespace sync_sessions {
-
-struct SyncedSession;
-
-// A simple interface to abstract away who is providing sessions.
-class ForeignSessionsProvider {
- public:
- // Fills the already instantiated passed vector with all foreign sessions.
- // Returned boolean representes if there were foreign sessions and the vector
- // should be examimed.
- virtual bool GetAllForeignSessions(
- std::vector<const SyncedSession*>* sessions) = 0;
- virtual ~ForeignSessionsProvider() {}
-};
-
-// An implementation of PageVisitObserver that checks the given page's url
-// against in memory session information to detect if we've seen this page
-// before, constituting a revisit. Then histogram information is emitted about
-// this page navigation.
-class SessionsPageRevisitObserver
- : public PageVisitObserver,
- public base::SupportsWeakPtr<SessionsPageRevisitObserver> {
- public:
- explicit SessionsPageRevisitObserver(
- std::unique_ptr<ForeignSessionsProvider> provider);
- ~SessionsPageRevisitObserver() override;
- void OnPageVisit(const GURL& url, const TransitionType transition) override;
-
- private:
- friend class SessionsPageRevisitObserverTest;
-
- // Although the signature is identical to OnPageVisit(...), this method
- // actually does all of the work. The assumption is that this method is the
- // target of a PostTask call coming from OnPageVisit(...).
- void CheckForRevisit(const GURL& url, const TransitionType transition);
-
- std::unique_ptr<ForeignSessionsProvider> provider_;
-
- DISALLOW_COPY_AND_ASSIGN(SessionsPageRevisitObserver);
-};
-
-} // namespace sync_sessions
-
-#endif // COMPONENTS_SYNC_SESSIONS_REVISIT_SESSIONS_PAGE_REVISIT_OBSERVER_H_
diff --git a/chromium/components/sync_sessions/revisit/sessions_page_revisit_observer_unittest.cc b/chromium/components/sync_sessions/revisit/sessions_page_revisit_observer_unittest.cc
deleted file mode 100644
index 97878c08f8c..00000000000
--- a/chromium/components/sync_sessions/revisit/sessions_page_revisit_observer_unittest.cc
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/sessions_page_revisit_observer.h"
-
-#include <string>
-#include <utility>
-
-#include "base/test/histogram_tester.h"
-#include "components/sessions/core/serialized_navigation_entry.h"
-#include "components/sessions/core/serialized_navigation_entry_test_helper.h"
-#include "components/sessions/core/session_types.h"
-#include "components/sync_sessions/synced_session.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-using sessions::SessionTab;
-using sessions::SessionWindow;
-
-namespace sync_sessions {
-
-namespace {
-
-static const char kExampleUrl[] = "http://www.example.com";
-static const char kDifferentUrl[] = "http://www.different.com";
-
-class TestForeignSessionsProvider : public ForeignSessionsProvider {
- public:
- TestForeignSessionsProvider(const std::vector<const SyncedSession*>& sessions,
- bool return_value)
- : sessions_(sessions), return_value_(return_value) {}
- ~TestForeignSessionsProvider() override {}
-
- bool GetAllForeignSessions(
- std::vector<const SyncedSession*>* sessions) override {
- sessions->clear();
- *sessions = sessions_;
- return return_value_;
- }
-
- private:
- const std::vector<const SyncedSession*>& sessions_;
- const bool return_value_;
-};
-
-} // namespace
-
-class SessionsPageRevisitObserverTest : public ::testing::Test {
- protected:
- void CheckAndExpect(SessionsPageRevisitObserver* observer,
- const GURL& url,
- const bool current_match,
- const bool offset_match) {
- base::HistogramTester histogram_tester;
- observer->CheckForRevisit(url, PageVisitObserver::kTransitionPage);
-
- histogram_tester.ExpectTotalCount("Sync.PageRevisitTabMatchTransition",
- current_match ? 1 : 0);
- histogram_tester.ExpectTotalCount("Sync.PageRevisitTabMissTransition",
- current_match ? 0 : 1);
- histogram_tester.ExpectTotalCount(
- "Sync.PageRevisitNavigationMatchTransition", offset_match ? 1 : 0);
- histogram_tester.ExpectTotalCount(
- "Sync.PageRevisitNavigationMissTransition", offset_match ? 0 : 1);
- histogram_tester.ExpectTotalCount("Sync.PageRevisitSessionDuration", 1);
- }
-
- void CheckAndExpect(const SyncedSession* session,
- const GURL& url,
- const bool current_match,
- const bool offset_match) {
- std::vector<const SyncedSession*> sessions;
- sessions.push_back(session);
- SessionsPageRevisitObserver observer(
- std::make_unique<TestForeignSessionsProvider>(sessions, true));
- CheckAndExpect(&observer, url, current_match, offset_match);
- }
-};
-
-TEST_F(SessionsPageRevisitObserverTest, RunMatchersNoSessions) {
- std::vector<const SyncedSession*> sessions;
- SessionsPageRevisitObserver observer(
- std::make_unique<TestForeignSessionsProvider>(sessions, true));
- CheckAndExpect(&observer, GURL(kExampleUrl), false, false);
-}
-
-TEST_F(SessionsPageRevisitObserverTest, RunMatchersNoWindows) {
- auto session = std::make_unique<SyncedSession>();
- CheckAndExpect(session.get(), GURL(kExampleUrl), false, false);
-}
-
-TEST_F(SessionsPageRevisitObserverTest, RunMatchersNoTabs) {
- auto session = std::make_unique<SyncedSession>();
- session->windows[0] = std::make_unique<SyncedSessionWindow>();
- CheckAndExpect(session.get(), GURL(kExampleUrl), false, false);
-}
-
-TEST_F(SessionsPageRevisitObserverTest, RunMatchersNoEntries) {
- auto window = std::make_unique<SyncedSessionWindow>();
- window->wrapped_window.tabs.push_back(std::make_unique<SessionTab>());
- auto session = std::make_unique<SyncedSession>();
- session->windows[0] = std::move(window);
- CheckAndExpect(session.get(), GURL(kExampleUrl), false, false);
-}
-
-TEST_F(SessionsPageRevisitObserverTest, RunMatchersSingle) {
- auto tab = std::make_unique<SessionTab>();
- tab->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- kExampleUrl, ""));
- tab->current_navigation_index = 0;
- auto window = std::make_unique<SyncedSessionWindow>();
- window->wrapped_window.tabs.push_back(std::move(tab));
- auto session = std::make_unique<SyncedSession>();
- session->windows[0] = std::move(window);
- CheckAndExpect(session.get(), GURL(kExampleUrl), true, false);
-}
-
-TEST_F(SessionsPageRevisitObserverTest, RunMatchersFalseProvider) {
- auto tab = std::make_unique<SessionTab>();
- tab->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- kExampleUrl, ""));
- tab->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- kExampleUrl, ""));
- tab->current_navigation_index = 1;
- auto window = std::make_unique<SyncedSessionWindow>();
- window->wrapped_window.tabs.push_back(std::move(tab));
- auto session = std::make_unique<SyncedSession>();
- session->windows[0] = std::move(window);
-
- // The provider returns false when asked for foreign sessions, even though
- // it has has a valid tab.
- std::vector<const SyncedSession*> sessions;
- sessions.push_back(session.get());
- SessionsPageRevisitObserver observer(
- std::make_unique<TestForeignSessionsProvider>(sessions, false));
- CheckAndExpect(&observer, GURL(kExampleUrl), false, false);
-}
-
-TEST_F(SessionsPageRevisitObserverTest, RunMatchersMany) {
- auto tab1 = std::make_unique<SessionTab>();
- tab1->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- kExampleUrl, ""));
- tab1->current_navigation_index = 0;
-
- auto tab2 = std::make_unique<SessionTab>();
- tab2->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- kDifferentUrl, ""));
- tab2->current_navigation_index = 0;
-
- auto tab3 = std::make_unique<SessionTab>();
- tab3->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- kDifferentUrl, ""));
- tab3->current_navigation_index = 0;
-
- auto tab4 = std::make_unique<SessionTab>();
- tab4->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- kExampleUrl, ""));
- tab4->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- kDifferentUrl, ""));
- tab4->current_navigation_index = 1;
-
- auto window1 = std::make_unique<SyncedSessionWindow>();
- window1->wrapped_window.tabs.push_back(std::move(tab1));
- auto window2 = std::make_unique<SyncedSessionWindow>();
- window2->wrapped_window.tabs.push_back(std::move(tab2));
- auto window3 = std::make_unique<SyncedSessionWindow>();
- window3->wrapped_window.tabs.push_back(std::move(tab3));
- window3->wrapped_window.tabs.push_back(std::move(tab4));
-
- auto session1 = std::make_unique<SyncedSession>();
- session1->windows[1] = std::move(window1);
- auto session2 = std::make_unique<SyncedSession>();
- session2->windows[2] = std::move(window2);
- session2->windows[3] = std::move(window3);
-
- std::vector<const SyncedSession*> sessions;
- sessions.push_back(session1.get());
- sessions.push_back(session2.get());
- SessionsPageRevisitObserver observer(
- std::make_unique<TestForeignSessionsProvider>(sessions, true));
-
- base::HistogramTester histogram_tester;
- CheckAndExpect(&observer, GURL(kExampleUrl), true, true);
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/typed_url_page_revisit_observer.cc b/chromium/components/sync_sessions/revisit/typed_url_page_revisit_observer.cc
deleted file mode 100644
index 58816acc4da..00000000000
--- a/chromium/components/sync_sessions/revisit/typed_url_page_revisit_observer.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/typed_url_page_revisit_observer.h"
-
-#include <memory>
-
-#include "components/history/core/browser/history_service.h"
-#include "components/sync_sessions/revisit/typed_url_page_revisit_task.h"
-#include "url/gurl.h"
-
-namespace sync_sessions {
-
-TypedUrlPageRevisitObserver::TypedUrlPageRevisitObserver(
- history::HistoryService* history)
- : history_(base::AsWeakPtr(history)) {}
-
-TypedUrlPageRevisitObserver::~TypedUrlPageRevisitObserver() {}
-
-void TypedUrlPageRevisitObserver::OnPageVisit(
- const GURL& url,
- const PageVisitObserver::TransitionType transition) {
- if (history_) {
- history_->ScheduleDBTask(
- std::make_unique<TypedUrlPageRevisitTask>(url, transition),
- &task_tracker_);
- }
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/typed_url_page_revisit_observer.h b/chromium/components/sync_sessions/revisit/typed_url_page_revisit_observer.h
deleted file mode 100644
index fc69d1de824..00000000000
--- a/chromium/components/sync_sessions/revisit/typed_url_page_revisit_observer.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SYNC_SESSIONS_REVISIT_TYPED_URL_PAGE_REVISIT_OBSERVER_H_
-#define COMPONENTS_SYNC_SESSIONS_REVISIT_TYPED_URL_PAGE_REVISIT_OBSERVER_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/task/cancelable_task_tracker.h"
-#include "components/sync_sessions/revisit/page_visit_observer.h"
-
-class GURL;
-
-namespace history {
-class HistoryService;
-} // namespace history
-
-namespace sync_sessions {
-
-// This class's job is to respond to OnPageVisit events and launch a task to
-// the history thread to perform the requisite checks and instrumentation. It is
-// important that this object is created and called on the same thread, since it
-// creates and uses a weak pointer to the HistoryService.
-class TypedUrlPageRevisitObserver : public PageVisitObserver {
- public:
- explicit TypedUrlPageRevisitObserver(history::HistoryService* history);
- ~TypedUrlPageRevisitObserver() override;
- void OnPageVisit(const GURL& url,
- const PageVisitObserver::TransitionType transition) override;
-
- private:
- const base::WeakPtr<history::HistoryService> history_;
- // This is never used to cancel tasks, but required by the history interface.
- base::CancelableTaskTracker task_tracker_;
-
- DISALLOW_COPY_AND_ASSIGN(TypedUrlPageRevisitObserver);
-};
-
-} // namespace sync_sessions
-
-#endif // COMPONENTS_SYNC_SESSIONS_REVISIT_TYPED_URL_PAGE_REVISIT_OBSERVER_H_
diff --git a/chromium/components/sync_sessions/revisit/typed_url_page_revisit_task.cc b/chromium/components/sync_sessions/revisit/typed_url_page_revisit_task.cc
deleted file mode 100644
index 240cdc3c45f..00000000000
--- a/chromium/components/sync_sessions/revisit/typed_url_page_revisit_task.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/typed_url_page_revisit_task.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "base/time/time.h"
-#include "components/history/core/browser/history_backend.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/history/core/browser/url_row.h"
-
-namespace sync_sessions {
-
-TypedUrlPageRevisitTask::TypedUrlPageRevisitTask(
- const GURL& url,
- const PageVisitObserver::TransitionType transition)
- : url_(url), transition_(transition) {}
-
-TypedUrlPageRevisitTask::~TypedUrlPageRevisitTask() {}
-
-bool TypedUrlPageRevisitTask::FillVisitsAndSources(
- history::HistoryBackend* backend,
- history::VisitVector* visits,
- history::VisitSourceMap* sources) {
- history::URLRow row;
- return backend->GetURL(url_, &row) &&
- backend->GetVisitsForURL(row.id(), visits) &&
- backend->GetVisitsSource(*visits, sources);
-}
-
-bool TypedUrlPageRevisitTask::FindLastSyncedMatchAge(
- history::HistoryBackend* backend,
- base::Time* lastVisitTime) {
- history::VisitVector visits;
- history::VisitSourceMap sources;
- if (FillVisitsAndSources(backend, &visits, &sources)) {
- // The visits are in chronological order. We only care about the most
- // recent remote visit, so iterate backwards.
- for (auto row_itr = visits.rbegin(); row_itr != visits.rend(); ++row_itr) {
- auto map_itr = sources.find(row_itr->visit_id);
- if (map_itr != sources.end() &&
- map_itr->second == history::SOURCE_SYNCED) {
- *lastVisitTime = row_itr->visit_time;
- return true;
- }
- }
- }
- return false;
-}
-
-bool TypedUrlPageRevisitTask::RunOnDBThread(history::HistoryBackend* backend,
- history::HistoryDatabase* db) {
- base::TimeTicks start(base::TimeTicks::Now());
- base::Time lastVisitTime;
- if (FindLastSyncedMatchAge(backend, &lastVisitTime)) {
- REVISIT_HISTOGRAM_AGE("Sync.PageRevisitTypedUrlMatchAge", lastVisitTime);
- UMA_HISTOGRAM_ENUMERATION("Sync.PageRevisitTypedUrlMatchTransition",
- transition_,
- PageVisitObserver::kTransitionTypeLast);
- } else {
- UMA_HISTOGRAM_ENUMERATION("Sync.PageRevisitTypedUrlMissTransition",
- transition_,
- PageVisitObserver::kTransitionTypeLast);
- }
-
- base::TimeDelta duration(base::TimeTicks::Now() - start);
- UMA_HISTOGRAM_TIMES("Sync.PageRevisitTypedUrlDuration", duration);
-
- // This indicates success and retring is not needed.
- return true;
-}
-
-void TypedUrlPageRevisitTask::DoneRunOnMainThread() {}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/revisit/typed_url_page_revisit_task.h b/chromium/components/sync_sessions/revisit/typed_url_page_revisit_task.h
deleted file mode 100644
index 49b43983d6e..00000000000
--- a/chromium/components/sync_sessions/revisit/typed_url_page_revisit_task.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SYNC_SESSIONS_REVISIT_TYPED_URL_PAGE_REVISIT_TASK_H_
-#define COMPONENTS_SYNC_SESSIONS_REVISIT_TYPED_URL_PAGE_REVISIT_TASK_H_
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "components/history/core/browser/history_db_task.h"
-#include "components/history/core/browser/history_types.h"
-#include "components/sync_sessions/revisit/page_visit_observer.h"
-#include "url/gurl.h"
-
-namespace base {
-class Time;
-} // namespace base
-
-namespace history {
-class HistoryBackend;
-class HistoryDatabase;
-} // namespace history
-
-namespace sync_sessions {
-
-// This is the actual logic to check if the history database has a foreign,
-// synced, typed URL record for a given page/URL or not. This class implements
-// the HistoryDBTask interface with the assumption that is is being run by the
-// history mechanisms and on the correct thread.
-class TypedUrlPageRevisitTask : public history::HistoryDBTask {
- public:
- TypedUrlPageRevisitTask(const GURL& url,
- const PageVisitObserver::TransitionType transition);
- ~TypedUrlPageRevisitTask() override;
- bool RunOnDBThread(history::HistoryBackend* backend,
- history::HistoryDatabase* db) override;
- void DoneRunOnMainThread() override;
-
- private:
- FRIEND_TEST_ALL_PREFIXES(TypedUrlPageRevisitTaskTest, MultipleMatches);
-
- // Returns if there was a previously synced match. lastVisitTime is an out
- // parameter. Its value is not read, but will be set if the return value is
- // true.
- bool FindLastSyncedMatchAge(history::HistoryBackend* backend,
- base::Time* lastVisitTime);
-
- // Returns if there are visits and sources the instance url value, and
- // populates the parameters repspectively. Virtual so that unit tests can
- // override this functionality.
- virtual bool FillVisitsAndSources(history::HistoryBackend* backend,
- history::VisitVector* visits,
- history::VisitSourceMap* sources);
-
- const GURL url_;
- const PageVisitObserver::TransitionType transition_;
-
- DISALLOW_COPY_AND_ASSIGN(TypedUrlPageRevisitTask);
-};
-
-} // namespace sync_sessions
-
-#endif // COMPONENTS_SYNC_SESSIONS_REVISIT_TYPED_URL_PAGE_REVISIT_TASK_H_
diff --git a/chromium/components/sync_sessions/revisit/typed_url_page_revisit_task_unittest.cc b/chromium/components/sync_sessions/revisit/typed_url_page_revisit_task_unittest.cc
deleted file mode 100644
index ac6db2c1e32..00000000000
--- a/chromium/components/sync_sessions/revisit/typed_url_page_revisit_task_unittest.cc
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/revisit/typed_url_page_revisit_task.h"
-
-#include "base/test/histogram_tester.h"
-#include "base/time/time.h"
-#include "components/history/core/browser/history_backend.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace sync_sessions {
-
-namespace {
-
-class FakeTask : public TypedUrlPageRevisitTask {
- public:
- FakeTask(const PageVisitObserver::TransitionType transition,
- bool result,
- const history::VisitVector& visits,
- const history::VisitSourceMap& sources)
- : TypedUrlPageRevisitTask(GURL("http://www.example.com"), transition),
- result_(result),
- visits_(visits),
- sources_(sources) {}
-
- bool FillVisitsAndSources(history::HistoryBackend* backend,
- history::VisitVector* visits,
- history::VisitSourceMap* sources) override {
- *visits = visits_;
- *sources = sources_;
- return result_;
- }
-
- private:
- const bool result_;
- const history::VisitVector visits_;
- const history::VisitSourceMap sources_;
-};
-
-void VerifyMatch(TypedUrlPageRevisitTask* task,
- const PageVisitObserver::TransitionType transition) {
- base::HistogramTester histogram_tester;
- task->RunOnDBThread(nullptr, nullptr);
- histogram_tester.ExpectTotalCount("Sync.PageRevisitTypedUrlMatchAge", 1);
- histogram_tester.ExpectUniqueSample("Sync.PageRevisitTypedUrlMatchTransition",
- PageVisitObserver::kTransitionPage, 1);
- histogram_tester.ExpectTotalCount("Sync.PageRevisitTypedUrlDuration", 1);
-}
-
-void VerifyMiss(TypedUrlPageRevisitTask* task,
- const PageVisitObserver::TransitionType transition) {
- base::HistogramTester histogram_tester;
- task->RunOnDBThread(nullptr, nullptr);
- histogram_tester.ExpectUniqueSample("Sync.PageRevisitTypedUrlMissTransition",
- PageVisitObserver::kTransitionPage, 1);
- histogram_tester.ExpectTotalCount("Sync.PageRevisitTypedUrlDuration", 1);
-}
-
-history::VisitRow Row(history::VisitID id) {
- history::VisitRow row;
- row.visit_id = id;
- return row;
-}
-
-history::VisitRow Row(history::VisitID id, base::Time visit_time) {
- history::VisitRow row;
- row.visit_id = id;
- row.visit_time = visit_time;
- return row;
-}
-
-} // namespace
-
-TEST(TypedUrlPageRevisitTaskTest, NoMatchesFillReturnsFalse) {
- history::VisitVector visits;
- history::VisitSourceMap sources;
- FakeTask task(PageVisitObserver::TransitionType::kTransitionPage, false,
- visits, sources);
- VerifyMiss(&task, PageVisitObserver::kTransitionPage);
-}
-
-TEST(TypedUrlPageRevisitTaskTest, NoMatchesFillReturnsTrue) {
- history::VisitVector visits;
- history::VisitSourceMap sources;
- FakeTask task(PageVisitObserver::TransitionType::kTransitionPage, true,
- visits, sources);
- VerifyMiss(&task, PageVisitObserver::kTransitionPage);
-}
-
-TEST(TypedUrlPageRevisitTaskTest, NoSyncedSources) {
- history::VisitVector visits;
- visits.push_back(Row(1));
- visits.push_back(Row(2));
- visits.push_back(Row(3));
- visits.push_back(Row(4));
- visits.push_back(Row(5));
- visits.push_back(Row(6));
- visits.push_back(Row(7));
-
- history::VisitSourceMap sources;
- sources[1] = history::SOURCE_BROWSED;
- sources[2] = history::SOURCE_EXTENSION;
- sources[3] = history::SOURCE_EXTENSION;
- sources[4] = history::SOURCE_FIREFOX_IMPORTED;
- sources[5] = history::SOURCE_IE_IMPORTED;
- sources[6] = history::SOURCE_SAFARI_IMPORTED;
- // No source for id 7.
-
- FakeTask task(PageVisitObserver::TransitionType::kTransitionPage, true,
- visits, sources);
- VerifyMiss(&task, PageVisitObserver::kTransitionPage);
-}
-
-TEST(TypedUrlPageRevisitTaskTest, SingleMatch) {
- history::VisitVector visits;
- visits.push_back(Row(1));
-
- history::VisitSourceMap sources;
- sources[1] = history::SOURCE_SYNCED;
-
- FakeTask task(PageVisitObserver::TransitionType::kTransitionPage, true,
- visits, sources);
- VerifyMatch(&task, PageVisitObserver::kTransitionPage);
-}
-
-TEST(TypedUrlPageRevisitTaskTest, MultipleMatches) {
- base::Time expected = base::Time::UnixEpoch() + base::TimeDelta::FromDays(1);
- history::VisitVector visits;
- visits.push_back(Row(1, base::Time::UnixEpoch()));
- visits.push_back(Row(2, expected));
- visits.push_back(
- Row(3, base::Time::UnixEpoch() + base::TimeDelta::FromDays(2)));
-
- history::VisitSourceMap sources;
- sources[1] = history::SOURCE_SYNCED;
- sources[2] = history::SOURCE_SYNCED;
- // No source for id 3.
-
- FakeTask task(PageVisitObserver::TransitionType::kTransitionPage, true,
- visits, sources);
- base::Time lastVisitTime;
- ASSERT_TRUE(task.FindLastSyncedMatchAge(nullptr, &lastVisitTime));
- ASSERT_EQ(expected, lastVisitTime);
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/session_data_type_controller_unittest.cc b/chromium/components/sync_sessions/session_data_type_controller_unittest.cc
index 570964cebf2..31aca023f15 100644
--- a/chromium/components/sync_sessions/session_data_type_controller_unittest.cc
+++ b/chromium/components/sync_sessions/session_data_type_controller_unittest.cc
@@ -7,6 +7,7 @@
#include <set>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
@@ -18,7 +19,7 @@
#include "components/sync/device_info/local_device_info_provider_mock.h"
#include "components/sync/driver/fake_sync_client.h"
#include "components/sync/driver/sync_api_component_factory_mock.h"
-#include "components/sync_sessions/fake_sync_sessions_client.h"
+#include "components/sync_sessions/mock_sync_sessions_client.h"
#include "components/sync_sessions/synced_window_delegate.h"
#include "components/sync_sessions/synced_window_delegates_getter.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -81,21 +82,6 @@ class MockSyncedWindowDelegatesGetter : public SyncedWindowDelegatesGetter {
SyncedWindowDelegateMap delegates_;
};
-class TestSyncSessionsClient : public FakeSyncSessionsClient {
- public:
- SyncedWindowDelegatesGetter* GetSyncedWindowDelegatesGetter() override {
- return synced_window_getter_;
- }
-
- void SetSyncedWindowDelegatesGetter(
- SyncedWindowDelegatesGetter* synced_window_getter) {
- synced_window_getter_ = synced_window_getter;
- }
-
- private:
- SyncedWindowDelegatesGetter* synced_window_getter_;
-};
-
class SessionDataTypeControllerTest : public testing::Test,
public syncer::FakeSyncClient {
public:
@@ -109,7 +95,7 @@ class SessionDataTypeControllerTest : public testing::Test,
PrefService* GetPrefService() override { return &prefs_; }
SyncSessionsClient* GetSyncSessionsClient() override {
- return sync_sessions_client_.get();
+ return &mock_sync_sessions_client_;
}
void SetUp() override {
@@ -118,17 +104,17 @@ class SessionDataTypeControllerTest : public testing::Test,
synced_window_delegate_ = std::make_unique<MockSyncedWindowDelegate>();
synced_window_getter_ = std::make_unique<MockSyncedWindowDelegatesGetter>();
- sync_sessions_client_ = std::make_unique<TestSyncSessionsClient>();
synced_window_getter_->Add(synced_window_delegate_.get());
- sync_sessions_client_->SetSyncedWindowDelegatesGetter(
- synced_window_getter_.get());
+
+ ON_CALL(mock_sync_sessions_client_, GetSyncedWindowDelegatesGetter())
+ .WillByDefault(testing::Return(synced_window_getter_.get()));
local_device_ = std::make_unique<LocalDeviceInfoProviderMock>(
"cache_guid", "Wayne Gretzky's Hacking Box", "Chromium 10k",
"Chrome 10k", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id");
controller_ = std::make_unique<SessionDataTypeController>(
- base::Bind(&base::DoNothing), this, local_device_.get(),
+ base::DoNothing(), this, local_device_.get(),
kSavingBrowserHistoryDisabled);
load_finished_ = false;
@@ -187,7 +173,7 @@ class SessionDataTypeControllerTest : public testing::Test,
std::unique_ptr<MockSyncedWindowDelegate> synced_window_delegate_;
std::unique_ptr<MockSyncedWindowDelegatesGetter> synced_window_getter_;
syncer::SyncApiComponentFactoryMock profile_sync_factory_;
- std::unique_ptr<TestSyncSessionsClient> sync_sessions_client_;
+ testing::NiceMock<MockSyncSessionsClient> mock_sync_sessions_client_;
std::unique_ptr<LocalDeviceInfoProviderMock> local_device_;
std::unique_ptr<SessionDataTypeController> controller_;
diff --git a/chromium/components/sync_sessions/session_sync_test_helper.cc b/chromium/components/sync_sessions/session_sync_test_helper.cc
index 90076fd542e..d7734a989d7 100644
--- a/chromium/components/sync_sessions/session_sync_test_helper.cc
+++ b/chromium/components/sync_sessions/session_sync_test_helper.cc
@@ -51,7 +51,7 @@ void SessionSyncTestHelper::VerifySyncedSession(
const std::vector<std::vector<SessionID::id_type>>& windows,
const SyncedSession& session) {
ASSERT_EQ(tag, session.session_tag);
- ASSERT_EQ(SyncedSession::TYPE_LINUX, session.device_type);
+ ASSERT_EQ(sync_pb::SyncEnums_DeviceType_TYPE_LINUX, session.device_type);
ASSERT_EQ(kClientName, session.session_name);
ASSERT_EQ(windows.size(), session.windows.size());
diff --git a/chromium/components/sync_sessions/sessions_global_id_mapper.cc b/chromium/components/sync_sessions/sessions_global_id_mapper.cc
new file mode 100644
index 00000000000..3b467ed6a9b
--- /dev/null
+++ b/chromium/components/sync_sessions/sessions_global_id_mapper.cc
@@ -0,0 +1,122 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync_sessions/sessions_global_id_mapper.h"
+
+#include <utility>
+
+#include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
+
+namespace sync_sessions {
+namespace {
+
+// Clean up navigation tracking when we have over this many global_ids.
+const size_t kNavigationTrackingCleanupThreshold = 100;
+
+// When we clean up navigation tracking, delete this many global_ids.
+const int kNavigationTrackingCleanupAmount = 10;
+
+// Used to record conflict information into histogram Sync.GlobalIdConflict.
+enum SyncGlobalIdConflict {
+ CONFLICT = 0,
+ NO_CONFLICT_NEW_ID,
+ NO_CONFLICT_SAME_IDS,
+ CONFLICT_MAX,
+};
+
+} // namespace
+
+SessionsGlobalIdMapper::SessionsGlobalIdMapper() = default;
+
+SessionsGlobalIdMapper::~SessionsGlobalIdMapper() = default;
+
+void SessionsGlobalIdMapper::AddGlobalIdChangeObserver(
+ syncer::GlobalIdChange callback) {
+ global_id_change_observers_.push_back(std::move(callback));
+}
+
+int64_t SessionsGlobalIdMapper::GetLatestGlobalId(int64_t global_id) {
+ auto g2u_iter = global_to_unique_.find(global_id);
+ if (g2u_iter != global_to_unique_.end()) {
+ auto u2g_iter = unique_to_current_global_.find(g2u_iter->second);
+ if (u2g_iter != unique_to_current_global_.end()) {
+ return u2g_iter->second;
+ }
+ }
+ return global_id;
+}
+
+void SessionsGlobalIdMapper::TrackNavigationIds(const base::Time& timestamp,
+ int unique_id) {
+ // The expectation is that global_id will update for a given unique_id, which
+ // should accurately and uniquely represent a single navigation. It is
+ // theoretically possible for two unique_ids to map to the same global_id, but
+ // hopefully rare enough that it doesn't cause much harm. Lets record metrics
+ // verify this theory.
+ int64_t global_id = timestamp.ToInternalValue();
+ // It is possible that the global_id has not been set yet for this navigation.
+ // In this case there's nothing here for us to track yet.
+ if (global_id == 0) {
+ return;
+ }
+
+ DCHECK_NE(0, unique_id);
+
+ auto g2u_iter = global_to_unique_.find(global_id);
+ if (g2u_iter == global_to_unique_.end()) {
+ global_to_unique_.insert(g2u_iter, std::make_pair(global_id, unique_id));
+ UMA_HISTOGRAM_ENUMERATION("Sync.GlobalIdConflict", NO_CONFLICT_NEW_ID,
+ CONFLICT_MAX);
+ } else if (g2u_iter->second != unique_id) {
+ UMA_HISTOGRAM_ENUMERATION("Sync.GlobalIdConflict", CONFLICT, CONFLICT_MAX);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("Sync.GlobalIdConflict", NO_CONFLICT_SAME_IDS,
+ CONFLICT_MAX);
+ }
+
+ auto u2g_iter = unique_to_current_global_.find(unique_id);
+ if (u2g_iter == unique_to_current_global_.end()) {
+ unique_to_current_global_.insert(u2g_iter,
+ std::make_pair(unique_id, global_id));
+ } else if (u2g_iter->second != global_id) {
+ // Remember the old_global_id before we insert and invalidate out iter.
+ int64_t old_global_id = u2g_iter->second;
+
+ // TODO(skym): Use insert_or_assign with hint once on C++17.
+ unique_to_current_global_[unique_id] = global_id;
+
+ // This should be done after updating unique_to_current_global_ in case one
+ // of our observers calls into GetLatestGlobalId().
+ for (auto& observer : global_id_change_observers_) {
+ observer.Run(old_global_id, global_id);
+ }
+ }
+
+ CleanupNavigationTracking();
+}
+
+void SessionsGlobalIdMapper::CleanupNavigationTracking() {
+ DCHECK(kNavigationTrackingCleanupThreshold >
+ kNavigationTrackingCleanupAmount);
+
+ // |global_to_unique_| is implicitly ordered by least recently created, which
+ // means we can drop from the beginning.
+ if (global_to_unique_.size() > kNavigationTrackingCleanupThreshold) {
+ auto iter = global_to_unique_.begin();
+ std::advance(iter, kNavigationTrackingCleanupAmount);
+ global_to_unique_.erase(global_to_unique_.begin(), iter);
+
+ // While |unique_id|s do get bigger for the most part, this isn't a great
+ // thing to make assumptions about, and an old tab may get refreshed often
+ // and still be very important. So instead just delete anything that's
+ // orphaned from |global_to_unique_|.
+ base::EraseIf(unique_to_current_global_,
+ [this](const std::pair<int, int64_t> kv) {
+ return !base::ContainsKey(global_to_unique_, kv.second);
+ });
+ }
+}
+
+} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/sessions_global_id_mapper.h b/chromium/components/sync_sessions/sessions_global_id_mapper.h
new file mode 100644
index 00000000000..907cca383a6
--- /dev/null
+++ b/chromium/components/sync_sessions/sessions_global_id_mapper.h
@@ -0,0 +1,40 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SYNC_SESSIONS_SESSIONS_GLOBAL_ID_MAPPER_H_
+#define COMPONENTS_SYNC_SESSIONS_SESSIONS_GLOBAL_ID_MAPPER_H_
+
+#include <map>
+#include <vector>
+
+#include "base/time/time.h"
+#include "components/sync/user_events/global_id_mapper.h"
+
+namespace sync_sessions {
+
+// Actual implementation of GlobalIdMapper used by sessions.
+class SessionsGlobalIdMapper : public syncer::GlobalIdMapper {
+ public:
+ SessionsGlobalIdMapper();
+ ~SessionsGlobalIdMapper();
+
+ // GlobalIdMapper implementation.
+ void AddGlobalIdChangeObserver(syncer::GlobalIdChange callback) override;
+ int64_t GetLatestGlobalId(int64_t global_id) override;
+
+ void TrackNavigationIds(const base::Time& timestamp, int unique_id);
+
+ private:
+ void CleanupNavigationTracking();
+
+ std::map<int64_t, int> global_to_unique_;
+ std::map<int, int64_t> unique_to_current_global_;
+ std::vector<syncer::GlobalIdChange> global_id_change_observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(SessionsGlobalIdMapper);
+};
+
+} // namespace sync_sessions
+
+#endif // COMPONENTS_SYNC_SESSIONS_SESSIONS_GLOBAL_ID_MAPPER_H_
diff --git a/chromium/components/sync_sessions/sessions_global_id_mapper_unittest.cc b/chromium/components/sync_sessions/sessions_global_id_mapper_unittest.cc
new file mode 100644
index 00000000000..566b32c23f2
--- /dev/null
+++ b/chromium/components/sync_sessions/sessions_global_id_mapper_unittest.cc
@@ -0,0 +1,83 @@
+// 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/sync_sessions/sessions_global_id_mapper.h"
+
+#include "base/test/mock_callback.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sync_sessions {
+namespace {
+
+using testing::_;
+
+const base::Time kTime1 = base::Time::FromInternalValue(110);
+const base::Time kTime2 = base::Time::FromInternalValue(120);
+const base::Time kTime3 = base::Time::FromInternalValue(130);
+const base::Time kTime4 = base::Time::FromInternalValue(140);
+const base::Time kTime5 = base::Time::FromInternalValue(150);
+
+// Tests that GetLatestGlobalId returns correct mappings for updated global_ids.
+TEST(SessionsGlobalIdMapperTest, GetLatestGlobalId) {
+ SessionsGlobalIdMapper mapper;
+
+ mapper.TrackNavigationIds(kTime1, /*unique_id=*/1);
+ mapper.TrackNavigationIds(kTime2, /*unique_id=*/2);
+ mapper.TrackNavigationIds(kTime3, /*unique_id=*/2);
+ mapper.TrackNavigationIds(kTime4, /*unique_id=*/2);
+
+ EXPECT_EQ(kTime1.ToInternalValue(),
+ mapper.GetLatestGlobalId(kTime1.ToInternalValue()));
+ EXPECT_EQ(kTime4.ToInternalValue(),
+ mapper.GetLatestGlobalId(kTime2.ToInternalValue()));
+ EXPECT_EQ(kTime4.ToInternalValue(),
+ mapper.GetLatestGlobalId(kTime3.ToInternalValue()));
+ EXPECT_EQ(kTime4.ToInternalValue(),
+ mapper.GetLatestGlobalId(kTime4.ToInternalValue()));
+ // kTime5 is not mapped, so itself should be returned.
+ EXPECT_EQ(kTime5.ToInternalValue(),
+ mapper.GetLatestGlobalId(kTime5.ToInternalValue()));
+}
+
+// Tests that the global_id mapping is eventually dropped after we reach our
+// threshold for the amount to remember.
+TEST(SessionsGlobalIdMapperTest, Cleanup) {
+ SessionsGlobalIdMapper mapper;
+
+ base::Time current_time = kTime1;
+ mapper.TrackNavigationIds(current_time, /*unique_id=*/1);
+
+ for (int i = 0; i < 105; i++) {
+ current_time =
+ base::Time::FromInternalValue(current_time.ToInternalValue() + 1);
+ mapper.TrackNavigationIds(current_time, /*unique_id=*/1);
+ }
+
+ // Threshold is 100, kTime1 should be dropped, kTime1+10 should not.
+ EXPECT_EQ(kTime1.ToInternalValue(),
+ mapper.GetLatestGlobalId(kTime1.ToInternalValue()));
+ EXPECT_EQ(current_time.ToInternalValue(),
+ mapper.GetLatestGlobalId(10 + kTime1.ToInternalValue()));
+}
+
+// Tests that subscribers to AddGlobalIdChangeObserver are notified when a
+// global_id is noticed to have been changed.
+TEST(SessionsGlobalIdMapperTest, AddObserver) {
+ SessionsGlobalIdMapper mapper;
+
+ mapper.TrackNavigationIds(kTime1, /*unique_id=*/1);
+
+ base::MockCallback<syncer::GlobalIdChange> mock_callback;
+ EXPECT_CALL(mock_callback, Run(_, _)).Times(0);
+
+ mapper.AddGlobalIdChangeObserver(mock_callback.Get());
+
+ EXPECT_CALL(mock_callback,
+ Run(kTime1.ToInternalValue(), kTime2.ToInternalValue()))
+ .Times(0);
+}
+
+} // namespace
+} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/sessions_sync_manager.cc b/chromium/components/sync_sessions/sessions_sync_manager.cc
index 9972d4725cf..78957df0725 100644
--- a/chromium/components/sync_sessions/sessions_sync_manager.cc
+++ b/chromium/components/sync_sessions/sessions_sync_manager.cc
@@ -42,42 +42,10 @@ const int kMaxSyncFavicons = 200;
// The maximum number of navigations in each direction we care to sync.
const int kMaxSyncNavigationCount = 6;
-// The URL at which the set of synced tabs is displayed. We treat it differently
-// from all other URL's as accessing it triggers a sync refresh of Sessions.
-const char kNTPOpenTabSyncURL[] = "chrome://newtab/#open_tabs";
-
// Default number of days without activity after which a session is considered
// stale and becomes a candidate for garbage collection.
const int kDefaultStaleSessionThresholdDays = 14; // 2 weeks.
-// Clean up navigation tracking when we have over this many global_ids.
-const size_t kNavigationTrackingCleanupThreshold = 100;
-
-// When we clean up navigation tracking, delete this many global_ids.
-const int kNavigationTrackingCleanupAmount = 10;
-
-// Used to record conflict information into histogram Sync.GlobalIdConflict.
-enum SyncGlobalIdConflict {
- CONFLICT = 0,
- NO_CONFLICT_NEW_ID,
- NO_CONFLICT_SAME_IDS,
- CONFLICT_MAX,
-};
-
-// Comparator function for use with std::sort that will sort tabs by
-// descending timestamp (i.e., most recent first).
-bool TabsRecencyComparator(const sessions::SessionTab* t1,
- const sessions::SessionTab* t2) {
- return t1->timestamp > t2->timestamp;
-}
-
-// Comparator function for use with std::sort that will sort sessions by
-// descending modified_time (i.e., most recent first).
-bool SessionsRecencyComparator(const SyncedSession* s1,
- const SyncedSession* s2) {
- return s1->modified_time > s2->modified_time;
-}
-
std::string TabNodeIdToTag(const std::string& machine_tag, int tab_node_id) {
CHECK_GT(tab_node_id, TabNodePool::kInvalidTabNodeID)
<< "https://crbug.com/639009";
@@ -124,25 +92,9 @@ bool ShouldSyncTabId(SessionID::id_type tab_id) {
return true;
}
-SyncedSession::DeviceType ProtoDeviceTypeToSyncedSessionDeviceType(
- sync_pb::SyncEnums::DeviceType proto_device_type) {
- switch (proto_device_type) {
- case sync_pb::SyncEnums_DeviceType_TYPE_WIN:
- return SyncedSession::TYPE_WIN;
- case sync_pb::SyncEnums_DeviceType_TYPE_MAC:
- return SyncedSession::TYPE_MACOSX;
- case sync_pb::SyncEnums_DeviceType_TYPE_LINUX:
- return SyncedSession::TYPE_LINUX;
- case sync_pb::SyncEnums_DeviceType_TYPE_CROS:
- return SyncedSession::TYPE_CHROMEOS;
- case sync_pb::SyncEnums_DeviceType_TYPE_PHONE:
- return SyncedSession::TYPE_PHONE;
- case sync_pb::SyncEnums_DeviceType_TYPE_TABLET:
- return SyncedSession::TYPE_TABLET;
- case sync_pb::SyncEnums_DeviceType_TYPE_OTHER:
- return SyncedSession::TYPE_OTHER;
- }
- return SyncedSession::TYPE_OTHER;
+bool IsWindowSyncable(const SyncedWindowDelegate& window_delegate) {
+ return window_delegate.ShouldSync() && window_delegate.GetTabCount() &&
+ window_delegate.HasWindow();
}
} // namespace
@@ -154,13 +106,18 @@ SessionsSyncManager::SessionsSyncManager(
syncer::SyncPrefs* sync_prefs,
LocalDeviceInfoProvider* local_device,
LocalSessionEventRouter* router,
- const base::Closure& sessions_updated_callback,
- const base::Closure& datatype_refresh_callback)
+ const base::RepeatingClosure& sessions_updated_callback)
: sessions_client_(sessions_client),
session_tracker_(sessions_client),
favicon_cache_(sessions_client->GetFaviconService(),
sessions_client->GetHistoryService(),
kMaxSyncFavicons),
+ open_tabs_ui_delegate_(
+ sessions_client,
+ &session_tracker_,
+ &favicon_cache_,
+ base::BindRepeating(&SessionsSyncManager::DeleteForeignSessionFromUI,
+ base::Unretained(this))),
local_tab_pool_out_of_sync_(true),
sync_prefs_(sync_prefs),
local_device_(local_device),
@@ -168,9 +125,7 @@ SessionsSyncManager::SessionsSyncManager(
local_session_header_node_id_(TabNodePool::kInvalidTabNodeID),
stale_session_threshold_days_(kDefaultStaleSessionThresholdDays),
local_event_router_(router),
- page_revisit_broadcaster_(this, sessions_client),
sessions_updated_callback_(sessions_updated_callback),
- datatype_refresh_callback_(datatype_refresh_callback),
task_tracker_(std::make_unique<TaskTracker>()) {}
SessionsSyncManager::~SessionsSyncManager() {}
@@ -275,8 +230,7 @@ void SessionsSyncManager::AssociateWindows(
SyncedSession* current_session =
session_tracker_.GetSession(current_machine_tag());
current_session->session_name = current_session_name_;
- current_session->device_type =
- ProtoDeviceTypeToSyncedSessionDeviceType(current_device_type_);
+ current_session->device_type = current_device_type_;
current_session->session_tag = current_machine_tag();
SyncedWindowDelegatesGetter::SyncedWindowDelegateMap windows =
@@ -297,11 +251,11 @@ void SessionsSyncManager::AssociateWindows(
// A copy of the specifics must be made because |current_session| will be
// updated in place and therefore can't be relied on as the source of truth.
- sync_pb::SessionHeader header_specifics;
- header_specifics.CopyFrom(current_session->ToSessionHeaderProto());
- session_tracker_.ResetSessionTracking(current_machine_tag());
- PopulateSyncedSessionFromSpecifics(current_machine_tag(), header_specifics,
- base::Time::Now(), current_session);
+ sync_pb::SessionSpecifics specifics;
+ specifics.set_session_tag(current_machine_tag());
+ specifics.mutable_header()->CopyFrom(
+ current_session->ToSessionHeaderProto());
+ UpdateTrackerWithSpecifics(specifics, base::Time::Now(), &session_tracker_);
// The tab entities stored in sync have outdated SessionId values. Go
// through and update them to the new SessionIds.
@@ -320,8 +274,41 @@ void SessionsSyncManager::AssociateWindows(
}
}
- // TODO(skym): Scan for duplicate sync ids and remove,
- // https://crbug.com/639009.
+ // Each sync id should only ever be used once. Previously there existed a race
+ // condition which could cause them to be duplicated, see
+ // https://crbug.com/639009 for more information. This counts the number of
+ // times each id is used so that the second window/tab loop can act on every
+ // tab using duplicate ids. Lastly, it is important to note that this
+ // duplication scan is only checking the in-memory tab state. On Android, if
+ // we have no tabbed window, we may also have sync data with conflicting sync
+ // ids, but to keep this logic simple and less error prone, we do not attempt
+ // to do anything clever.
+ std::map<int, size_t> sync_id_count;
+ int duplicate_count = 0;
+ for (auto& window_iter_pair : windows) {
+ const SyncedWindowDelegate* window_delegate = window_iter_pair.second;
+ if (IsWindowSyncable(*window_delegate)) {
+ for (int j = 0; j < window_delegate->GetTabCount(); ++j) {
+ SyncedTabDelegate* synced_tab = window_delegate->GetTabAt(j);
+ if (synced_tab &&
+ synced_tab->GetSyncId() != TabNodePool::kInvalidTabNodeID) {
+ auto iter = sync_id_count.find(synced_tab->GetSyncId());
+ if (iter == sync_id_count.end()) {
+ sync_id_count.insert(iter,
+ std::make_pair(synced_tab->GetSyncId(), 1));
+ } else {
+ // If an id is used more than twice, this count will be a bit odd,
+ // but for our purposes, it will be sufficient.
+ duplicate_count++;
+ iter->second++;
+ }
+ }
+ }
+ }
+ }
+ if (duplicate_count > 0) {
+ UMA_HISTOGRAM_COUNTS_100("Sync.SesssionsDuplicateSyncId", duplicate_count);
+ }
for (auto& window_iter_pair : windows) {
const SyncedWindowDelegate* window_delegate = window_iter_pair.second;
@@ -335,8 +322,7 @@ void SessionsSyncManager::AssociateWindows(
// its possible for us to get a handle to a browser that is about to be
// removed. If the tab count is 0 or the window is null, the browser is
// about to be deleted, so we ignore it.
- if (window_delegate->ShouldSync() && window_delegate->GetTabCount() &&
- window_delegate->HasWindow()) {
+ if (IsWindowSyncable(*window_delegate)) {
SessionID::id_type window_id = window_delegate->GetSessionId();
DVLOG(1) << "Associating window " << window_id << " with "
<< window_delegate->GetTabCount() << " tabs.";
@@ -351,6 +337,20 @@ void SessionsSyncManager::AssociateWindows(
if (!synced_tab || !ShouldSyncTabId(tab_id))
continue;
+ if (synced_tab->GetSyncId() != TabNodePool::kInvalidTabNodeID) {
+ auto duplicate_iter = sync_id_count.find(synced_tab->GetSyncId());
+ DCHECK(duplicate_iter != sync_id_count.end());
+ if (duplicate_iter->second > 1) {
+ // Strip the id before processing it. This is going to mean it'll be
+ // treated the same as a new tab. If it's also a placeholder, we'll
+ // have no data about it, sync it cannot be synced until it is
+ // loaded. It is too difficult to try to guess which of the multiple
+ // tabs using the same id actually corresponds to the existing sync
+ // data.
+ synced_tab->SetSyncId(TabNodePool::kInvalidTabNodeID);
+ }
+ }
+
// Placeholder tabs are those without WebContents, either because they
// were never loaded into memory or they were evicted from memory
// (typically only on Android devices). They only have a tab id,
@@ -503,8 +503,6 @@ void SessionsSyncManager::AssociateTab(SyncedTabDelegate* const tab_delegate,
if (new_url != old_url) {
favicon_cache_.OnFaviconVisited(
new_url, tab_delegate->GetFaviconURLAtIndex(current_index));
- page_revisit_broadcaster_.OnPageVisit(
- new_url, tab_delegate->GetTransitionAtIndex(current_index));
}
}
@@ -567,40 +565,12 @@ bool SessionsSyncManager::RebuildAssociations() {
return !merge_result.error().IsSet();
}
-bool SessionsSyncManager::IsValidSessionHeader(
- const sync_pb::SessionHeader& header) {
- // Verify that tab IDs appear only once within a session.
- // Intended to prevent http://crbug.com/360822.
- std::set<int> session_tab_ids;
- for (int i = 0; i < header.window_size(); ++i) {
- const sync_pb::SessionWindow& window = header.window(i);
- for (int j = 0; j < window.tab_size(); ++j) {
- const int tab_id = window.tab(j);
- bool success = session_tab_ids.insert(tab_id).second;
- if (!success)
- return false;
- }
- }
-
- return true;
-}
-
void SessionsSyncManager::OnLocalTabModified(SyncedTabDelegate* modified_tab) {
- if (!modified_tab->IsBeingDestroyed()) {
- GURL virtual_url =
- modified_tab->GetVirtualURLAtIndex(modified_tab->GetCurrentEntryIndex());
- if (virtual_url.is_valid() &&
- virtual_url.spec() == kNTPOpenTabSyncURL) {
- DVLOG(1) << "Triggering sync refresh for sessions datatype.";
- if (!datatype_refresh_callback_.is_null())
- datatype_refresh_callback_.Run();
- }
- }
-
sessions::SerializedNavigationEntry current;
modified_tab->GetSerializedNavigationAtIndex(
modified_tab->GetCurrentEntryIndex(), &current);
- TrackNavigationIds(current);
+ global_id_mapper_.TrackNavigationIds(current.timestamp(),
+ current.unique_id());
if (local_tab_pool_out_of_sync_) {
// If our tab pool is corrupt, pay the price of a full re-association to
@@ -679,13 +649,6 @@ syncer::SyncDataList SessionsSyncManager::GetAllSyncData(
return list;
}
-bool SessionsSyncManager::GetLocalSession(const SyncedSession** local_session) {
- if (current_machine_tag().empty())
- return false;
- *local_session = session_tracker_.GetSession(current_machine_tag());
- return true;
-}
-
syncer::SyncError SessionsSyncManager::ProcessSyncChanges(
const base::Location& from_here,
const syncer::SyncChangeList& change_list) {
@@ -701,6 +664,8 @@ syncer::SyncError SessionsSyncManager::ProcessSyncChanges(
DCHECK(it->sync_data().GetSpecifics().has_session());
const sync_pb::SessionSpecifics& session =
it->sync_data().GetSpecifics().session();
+ const base::Time mtime =
+ syncer::SyncDataRemote(it->sync_data()).GetModifiedTime();
switch (it->change_type()) {
case syncer::SyncChange::ACTION_DELETE:
// Deletions are all or nothing (since we only ever delete entire
@@ -740,8 +705,12 @@ syncer::SyncError SessionsSyncManager::ProcessSyncChanges(
LOG(WARNING) << "Dropping modification to local session.";
return syncer::SyncError();
}
- UpdateTrackerWithSpecifics(
- session, syncer::SyncDataRemote(it->sync_data()).GetModifiedTime());
+ UpdateTrackerWithSpecifics(session, mtime, &session_tracker_);
+ // If a favicon or favicon urls are present, load the URLs and visit
+ // times into the in-memory favicon cache.
+ if (session.has_tab()) {
+ RefreshFaviconVisitTimesFromForeignTab(session.tab(), mtime);
+ }
break;
default:
NOTREACHED() << "Processing sync changes failed, unknown change type.";
@@ -767,15 +736,6 @@ syncer::SyncChange SessionsSyncManager::TombstoneTab(
}
}
-bool SessionsSyncManager::GetAllForeignSessions(
- std::vector<const SyncedSession*>* sessions) {
- if (!session_tracker_.LookupAllForeignSessions(
- sessions, SyncedSessionTracker::PRESENTABLE))
- return false;
- std::sort(sessions->begin(), sessions->end(), SessionsRecencyComparator);
- return true;
-}
-
bool SessionsSyncManager::InitFromSyncModel(
const syncer::SyncDataList& sync_data,
syncer::SyncChangeList* new_changes) {
@@ -801,7 +761,14 @@ bool SessionsSyncManager::InitFromSyncModel(
new_changes->push_back(tombstone);
} else if (specifics.session_tag() != current_machine_tag()) {
if (TagHashFromSpecifics(specifics) == remote.GetClientTagHash()) {
- UpdateTrackerWithSpecifics(specifics, remote.GetModifiedTime());
+ UpdateTrackerWithSpecifics(specifics, remote.GetModifiedTime(),
+ &session_tracker_);
+ // If a favicon or favicon urls are present, load the URLs and visit
+ // times into the in-memory favicon cache.
+ if (specifics.has_tab()) {
+ RefreshFaviconVisitTimesFromForeignTab(specifics.tab(),
+ remote.GetModifiedTime());
+ }
} else {
// In the past, like years ago, we believe that some session data was
// created with bad tag hashes. This causes any change this client makes
@@ -847,7 +814,7 @@ bool SessionsSyncManager::InitFromSyncModel(
}
UpdateTrackerWithSpecifics(rewritten_specifics,
- remote.GetModifiedTime());
+ remote.GetModifiedTime(), &session_tracker_);
DVLOG(1) << "Loaded local header and rewrote " << session_id_map.size()
<< " ids.";
@@ -888,8 +855,8 @@ bool SessionsSyncManager::InitFromSyncModel(
rewritten_specifics.mutable_tab()->set_tab_id(new_tab_id);
session_tracker_.ReassociateLocalTab(
rewritten_specifics.tab_node_id(), new_tab_id);
- UpdateTrackerWithSpecifics(rewritten_specifics,
- remote.GetModifiedTime());
+ UpdateTrackerWithSpecifics(
+ rewritten_specifics, remote.GetModifiedTime(), &session_tracker_);
}
}
}
@@ -910,90 +877,6 @@ bool SessionsSyncManager::InitFromSyncModel(
return found_current_header;
}
-void SessionsSyncManager::UpdateTrackerWithSpecifics(
- const sync_pb::SessionSpecifics& specifics,
- const base::Time& modification_time) {
- std::string session_tag = specifics.session_tag();
- SyncedSession* session = session_tracker_.GetSession(session_tag);
- if (specifics.has_header()) {
- // Read in the header data for this session. Header data is
- // essentially a collection of windows, each of which has an ordered id list
- // for their tabs.
-
- if (!IsValidSessionHeader(specifics.header())) {
- LOG(WARNING) << "Ignoring session node with invalid header "
- << "and tag " << session_tag << ".";
- return;
- }
-
- // Load (or create) the SyncedSession object for this client.
- const sync_pb::SessionHeader& header = specifics.header();
-
- // Reset the tab/window tracking for this session (must do this before
- // we start calling PutWindowInSession and PutTabInWindow so that all
- // unused tabs/windows get cleared by the CleanupSession(...) call).
- session_tracker_.ResetSessionTracking(session_tag);
-
- PopulateSyncedSessionFromSpecifics(session_tag, header, modification_time,
- session);
-
- // Delete any closed windows and unused tabs as necessary.
- session_tracker_.CleanupSession(session_tag);
- } else if (specifics.has_tab()) {
- const sync_pb::SessionTab& tab_s = specifics.tab();
- SessionID::id_type tab_id = tab_s.tab_id();
- DVLOG(1) << "Populating " << session_tag << "'s tab id " << tab_id
- << " from node " << specifics.tab_node_id();
-
- // Ensure the tracker is aware of the tab node id. Deleting foreign sessions
- // requires deleting all relevant tab nodes, and it's easier to track the
- // tab node ids themselves separately from the tab ids.
- //
- // Note that TabIDs are not stable across restarts of a client. Consider
- // this example with two tabs:
- //
- // http://a.com TabID1 --> NodeIDA
- // http://b.com TabID2 --> NodeIDB
- //
- // After restart, tab ids are reallocated. e.g, one possibility:
- // http://a.com TabID2 --> NodeIDA
- // http://b.com TabID1 --> NodeIDB
- //
- // If that happened on a remote client, here we will see an update to
- // TabID1 with tab_node_id changing from NodeIDA to NodeIDB, and TabID2
- // with tab_node_id changing from NodeIDB to NodeIDA.
- //
- // We can also wind up here if we created this tab as an out-of-order
- // update to the header node for this session before actually associating
- // the tab itself, so the tab node id wasn't available at the time and
- // is currently kInvalidTabNodeID.
- //
- // In both cases, we can safely throw it into the set of node ids.
- session_tracker_.OnTabNodeSeen(session_tag, specifics.tab_node_id());
- sessions::SessionTab* tab = session_tracker_.GetTab(session_tag, tab_id);
- if (!tab->timestamp.is_null() && tab->timestamp > modification_time) {
- DVLOG(1) << "Ignoring " << session_tag << "'s session tab " << tab_id
- << " with earlier modification time: " << tab->timestamp
- << " vs " << modification_time;
- return;
- }
-
- // Update SessionTab based on protobuf.
- tab->SetFromSyncData(tab_s, modification_time);
-
- // If a favicon or favicon urls are present, load the URLs and visit
- // times into the in-memory favicon cache.
- RefreshFaviconVisitTimesFromForeignTab(tab_s, modification_time);
-
- // Update the last modified time.
- if (session->modified_time < modification_time)
- session->modified_time = modification_time;
- } else {
- LOG(WARNING) << "Ignoring session node with missing header/tab "
- << "fields and tag " << session_tag << ".";
- }
-}
-
void SessionsSyncManager::InitializeCurrentMachineTag(
const std::string& cache_guid) {
DCHECK(current_machine_tag_.empty());
@@ -1010,67 +893,6 @@ void SessionsSyncManager::InitializeCurrentMachineTag(
}
}
-void SessionsSyncManager::PopulateSyncedSessionFromSpecifics(
- const std::string& session_tag,
- const sync_pb::SessionHeader& header_specifics,
- base::Time mtime,
- SyncedSession* synced_session) {
- if (header_specifics.has_client_name())
- synced_session->session_name = header_specifics.client_name();
- if (header_specifics.has_device_type()) {
- synced_session->device_type = ProtoDeviceTypeToSyncedSessionDeviceType(
- header_specifics.device_type());
- }
- synced_session->modified_time =
- std::max(mtime, synced_session->modified_time);
-
- // Process all the windows and their tab information.
- int num_windows = header_specifics.window_size();
- DVLOG(1) << "Populating " << session_tag << " with " << num_windows
- << " windows.";
-
- for (int i = 0; i < num_windows; ++i) {
- const sync_pb::SessionWindow& window_s = header_specifics.window(i);
- SessionID::id_type window_id = window_s.window_id();
- session_tracker_.PutWindowInSession(session_tag, window_id);
- PopulateSyncedSessionWindowFromSpecifics(
- session_tag, window_s, synced_session->modified_time,
- synced_session->windows[window_id].get());
- }
-}
-
-// static
-void SessionsSyncManager::PopulateSyncedSessionWindowFromSpecifics(
- const std::string& session_tag,
- const sync_pb::SessionWindow& specifics,
- base::Time mtime,
- SyncedSessionWindow* synced_session_window) {
- sessions::SessionWindow* session_window =
- &synced_session_window->wrapped_window;
- if (specifics.has_window_id())
- session_window->window_id.set_id(specifics.window_id());
- if (specifics.has_selected_tab_index())
- session_window->selected_tab_index = specifics.selected_tab_index();
- synced_session_window->window_type = specifics.browser_type();
- if (specifics.has_browser_type()) {
- if (specifics.browser_type() ==
- sync_pb::SessionWindow_BrowserType_TYPE_TABBED) {
- session_window->type = sessions::SessionWindow::TYPE_TABBED;
- } else {
- // Note: custom tabs are treated like popup windows on restore, as you can
- // restore a custom tab on a platform that doesn't support them.
- session_window->type = sessions::SessionWindow::TYPE_POPUP;
- }
- }
- session_window->timestamp = mtime;
- session_window->tabs.clear();
- for (int i = 0; i < specifics.tab_size(); i++) {
- SessionID::id_type tab_id = specifics.tab(i);
- session_tracker_.PutTabInWindow(session_tag, session_window->window_id.id(),
- tab_id);
- }
-}
-
void SessionsSyncManager::RefreshFaviconVisitTimesFromForeignTab(
const sync_pb::SessionTab& tab,
const base::Time& modification_time) {
@@ -1087,18 +909,6 @@ void SessionsSyncManager::RefreshFaviconVisitTimesFromForeignTab(
}
}
-bool SessionsSyncManager::GetSyncedFaviconForPageURL(
- const std::string& page_url,
- scoped_refptr<base::RefCountedMemory>* favicon_png) const {
- return favicon_cache_.GetSyncedFaviconForPageURL(GURL(page_url), favicon_png);
-}
-
-void SessionsSyncManager::DeleteForeignSession(const std::string& tag) {
- syncer::SyncChangeList changes;
- DeleteForeignSessionInternal(tag, &changes);
- sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
-}
-
void SessionsSyncManager::DeleteForeignSessionInternal(
const std::string& tag,
syncer::SyncChangeList* change_output) {
@@ -1121,6 +931,12 @@ void SessionsSyncManager::DeleteForeignSessionInternal(
sessions_updated_callback_.Run();
}
+void SessionsSyncManager::DeleteForeignSessionFromUI(const std::string& tag) {
+ syncer::SyncChangeList changes;
+ DeleteForeignSessionInternal(tag, &changes);
+ sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
+}
+
bool SessionsSyncManager::DisassociateForeignSession(
const std::string& foreign_session_tag) {
DCHECK_NE(foreign_session_tag, current_machine_tag());
@@ -1128,49 +944,6 @@ bool SessionsSyncManager::DisassociateForeignSession(
return session_tracker_.DeleteForeignSession(foreign_session_tag);
}
-bool SessionsSyncManager::GetForeignSession(
- const std::string& tag,
- std::vector<const sessions::SessionWindow*>* windows) {
- return session_tracker_.LookupSessionWindows(tag, windows);
-}
-
-bool SessionsSyncManager::GetForeignSessionTabs(
- const std::string& tag,
- std::vector<const sessions::SessionTab*>* tabs) {
- std::vector<const sessions::SessionWindow*> windows;
- if (!session_tracker_.LookupSessionWindows(tag, &windows))
- return false;
-
- // Prune those tabs that are not syncable or are NewTabPage, then sort them
- // from most recent to least recent, independent of which window the tabs were
- // from.
- for (size_t j = 0; j < windows.size(); ++j) {
- const sessions::SessionWindow* window = windows[j];
- for (size_t t = 0; t < window->tabs.size(); ++t) {
- sessions::SessionTab* const tab = window->tabs[t].get();
- if (tab->navigations.empty())
- continue;
- const sessions::SerializedNavigationEntry& current_navigation =
- tab->navigations.at(tab->normalized_navigation_index());
- if (!sessions_client_->ShouldSyncURL(current_navigation.virtual_url()))
- continue;
- tabs->push_back(tab);
- }
- }
- std::sort(tabs->begin(), tabs->end(), TabsRecencyComparator);
- return true;
-}
-
-bool SessionsSyncManager::GetForeignTab(const std::string& tag,
- const SessionID::id_type tab_id,
- const sessions::SessionTab** tab) {
- const sessions::SessionTab* synced_tab = nullptr;
- bool success = session_tracker_.LookupSessionTab(tag, tab_id, &synced_tab);
- if (success)
- *tab = synced_tab;
- return success;
-}
-
void SessionsSyncManager::AssociateRestoredPlaceholderTab(
const SyncedTabDelegate& tab_delegate,
SessionID::id_type new_tab_id,
@@ -1283,6 +1056,14 @@ FaviconCache* SessionsSyncManager::GetFaviconCache() {
return &favicon_cache_;
}
+SessionsGlobalIdMapper* SessionsSyncManager::GetGlobalIdMapper() {
+ return &global_id_mapper_;
+}
+
+OpenTabsUIDelegate* SessionsSyncManager::GetOpenTabsUIDelegate() {
+ return &open_tabs_ui_delegate_;
+}
+
SyncedWindowDelegatesGetter*
SessionsSyncManager::synced_window_delegates_getter() const {
return sessions_client_->GetSyncedWindowDelegatesGetter();
@@ -1312,22 +1093,6 @@ void SessionsSyncManager::DoGarbageCollection() {
sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
}
-void SessionsSyncManager::AddGlobalIdChangeObserver(
- syncer::GlobalIdChange callback) {
- global_id_change_observers_.push_back(std::move(callback));
-}
-
-int64_t SessionsSyncManager::GetLatestGlobalId(int64_t global_id) {
- auto g2u_iter = global_to_unique_.find(global_id);
- if (g2u_iter != global_to_unique_.end()) {
- auto u2g_iter = unique_to_current_global_.find(g2u_iter->second);
- if (u2g_iter != unique_to_current_global_.end()) {
- return u2g_iter->second;
- }
- }
- return global_id;
-}
-
// static
std::string SessionsSyncManager::TagHashFromSpecifics(
const sync_pb::SessionSpecifics& specifics) {
@@ -1335,85 +1100,12 @@ std::string SessionsSyncManager::TagHashFromSpecifics(
TagFromSpecifics(specifics));
}
-void SessionsSyncManager::TrackNavigationIds(
- const sessions::SerializedNavigationEntry& current) {
- // The expectation is that global_id will update for a given unique_id, which
- // should accurately and uniquely represent a single navigation. It is
- // theoretically possible for two unique_ids to map to the same global_id, but
- // hopefully rare enough that it doesn't cause much harm. Lets record metrics
- // verify this theory.
- int64_t global_id = current.timestamp().ToInternalValue();
- // It is possible that the global_id has not been set yet for this navigation.
- // In this case there's nothing here for us to track yet.
- if (global_id == 0) {
- return;
- }
-
- int unique_id = current.unique_id();
- DCHECK_NE(0, unique_id);
-
- auto g2u_iter = global_to_unique_.find(global_id);
- if (g2u_iter == global_to_unique_.end()) {
- global_to_unique_.insert(g2u_iter, std::make_pair(global_id, unique_id));
- UMA_HISTOGRAM_ENUMERATION("Sync.GlobalIdConflict", NO_CONFLICT_NEW_ID,
- CONFLICT_MAX);
- } else if (g2u_iter->second != unique_id) {
- UMA_HISTOGRAM_ENUMERATION("Sync.GlobalIdConflict", CONFLICT, CONFLICT_MAX);
- } else {
- UMA_HISTOGRAM_ENUMERATION("Sync.GlobalIdConflict", NO_CONFLICT_SAME_IDS,
- CONFLICT_MAX);
- }
-
- auto u2g_iter = unique_to_current_global_.find(unique_id);
- if (u2g_iter == unique_to_current_global_.end()) {
- unique_to_current_global_.insert(u2g_iter,
- std::make_pair(unique_id, global_id));
- } else if (u2g_iter->second != global_id) {
- // Remember the old_global_id before we insert and invalidate out iter.
- int64_t old_global_id = u2g_iter->second;
-
- // TODO(skym): Use insert_or_assign with hint once on C++17.
- unique_to_current_global_[unique_id] = global_id;
-
- // This should be done after updating unique_to_current_global_ in case one
- // of our observers calls into GetLatestGlobalId().
- for (auto& observer : global_id_change_observers_) {
- observer.Run(old_global_id, global_id);
- }
- }
-
- CleanupNavigationTracking();
-}
-
-void SessionsSyncManager::CleanupNavigationTracking() {
- DCHECK(kNavigationTrackingCleanupThreshold >
- kNavigationTrackingCleanupAmount);
-
- // |global_to_unique_| is implicitly ordered by least recently created, which
- // means we can drop from the beginning.
- if (global_to_unique_.size() > kNavigationTrackingCleanupThreshold) {
- auto iter = global_to_unique_.begin();
- std::advance(iter, kNavigationTrackingCleanupAmount);
- global_to_unique_.erase(global_to_unique_.begin(), iter);
-
- // While |unique_id|s do get bigger for the most part, this isn't a great
- // thing to make assumptions about, and an old tab may get refreshed often
- // and still be very important. So instead just delete anything that's
- // orphaned from |global_to_unique_|.
- base::EraseIf(unique_to_current_global_,
- [this](const std::pair<int, int64_t> kv) {
- return !base::ContainsKey(global_to_unique_, kv.second);
- });
- }
-}
-
bool SessionsSyncManager::ScanForTabbedWindow() {
for (auto& window_iter_pair :
synced_window_delegates_getter()->GetSyncedWindowDelegates()) {
if (window_iter_pair.second->IsTypeTabbed()) {
const SyncedWindowDelegate* window_delegate = window_iter_pair.second;
- if (window_delegate->ShouldSync() && window_delegate->GetTabCount() &&
- window_delegate->HasWindow()) {
+ if (IsWindowSyncable(*window_delegate)) {
// When only custom tab windows are open, often we'll have a seemingly
// okay type tabbed window, but GetTabAt will return null for each
// index. This case is exactly what this method needs to protect
@@ -1428,4 +1120,4 @@ bool SessionsSyncManager::ScanForTabbedWindow() {
return false;
}
-}; // namespace sync_sessions
+} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/sessions_sync_manager.h b/chromium/components/sync_sessions/sessions_sync_manager.h
index eea4a2f2f84..a97a6caada6 100644
--- a/chromium/components/sync_sessions/sessions_sync_manager.h
+++ b/chromium/components/sync_sessions/sessions_sync_manager.h
@@ -24,12 +24,11 @@
#include "components/sync/base/sync_prefs.h"
#include "components/sync/device_info/device_info.h"
#include "components/sync/model/syncable_service.h"
-#include "components/sync/user_events/global_id_mapper.h"
#include "components/sync_sessions/favicon_cache.h"
#include "components/sync_sessions/local_session_event_router.h"
#include "components/sync_sessions/lost_navigations_recorder.h"
-#include "components/sync_sessions/open_tabs_ui_delegate.h"
-#include "components/sync_sessions/revisit/page_revisit_broadcaster.h"
+#include "components/sync_sessions/open_tabs_ui_delegate_impl.h"
+#include "components/sync_sessions/sessions_global_id_mapper.h"
#include "components/sync_sessions/synced_session.h"
#include "components/sync_sessions/synced_session_tracker.h"
#include "components/sync_sessions/task_tracker.h"
@@ -41,10 +40,8 @@ class SyncPrefs;
} // namespace syncer
namespace sync_pb {
-class SessionHeader;
class SessionSpecifics;
class SessionTab;
-class SessionWindow;
} // namespace sync_pb
namespace extensions {
@@ -53,22 +50,20 @@ class ExtensionSessionsTest;
namespace sync_sessions {
+class SessionsGlobalIdMapper;
class SyncedTabDelegate;
class SyncedWindowDelegatesGetter;
// Contains all logic for associating the Chrome sessions model and
// the sync sessions model.
class SessionsSyncManager : public syncer::SyncableService,
- public OpenTabsUIDelegate,
- public LocalSessionEventHandler,
- public syncer::GlobalIdMapper {
+ public LocalSessionEventHandler {
public:
SessionsSyncManager(SyncSessionsClient* sessions_client,
syncer::SyncPrefs* sync_prefs,
syncer::LocalDeviceInfoProvider* local_device,
LocalSessionEventRouter* router,
- const base::Closure& sessions_updated_callback,
- const base::Closure& datatype_refresh_callback);
+ const base::RepeatingClosure& sessions_updated_callback);
~SessionsSyncManager() override;
// syncer::SyncableService implementation.
@@ -83,24 +78,6 @@ class SessionsSyncManager : public syncer::SyncableService,
const base::Location& from_here,
const syncer::SyncChangeList& change_list) override;
- // OpenTabsUIDelegate implementation.
- bool GetSyncedFaviconForPageURL(
- const std::string& pageurl,
- scoped_refptr<base::RefCountedMemory>* favicon_png) const override;
- bool GetAllForeignSessions(
- std::vector<const SyncedSession*>* sessions) override;
- bool GetForeignSession(
- const std::string& tag,
- std::vector<const sessions::SessionWindow*>* windows) override;
- bool GetForeignTab(const std::string& tag,
- SessionID::id_type tab_id,
- const sessions::SessionTab** tab) override;
- bool GetForeignSessionTabs(
- const std::string& tag,
- std::vector<const sessions::SessionTab*>* tabs) override;
- void DeleteForeignSession(const std::string& tag) override;
- bool GetLocalSession(const SyncedSession** local_session) override;
-
// LocalSessionEventHandler implementation.
void OnLocalTabModified(SyncedTabDelegate* modified_tab) override;
void OnFaviconsChanged(const std::set<GURL>& page_urls,
@@ -120,16 +97,13 @@ class SessionsSyncManager : public syncer::SyncableService,
// sessions data downloaded (sync cycles complete).
void DoGarbageCollection();
- // GlobalIdMapper implementation.
- void AddGlobalIdChangeObserver(syncer::GlobalIdChange callback) override;
- int64_t GetLatestGlobalId(int64_t global_id) override;
+ SessionsGlobalIdMapper* GetGlobalIdMapper();
+
+ OpenTabsUIDelegate* GetOpenTabsUIDelegate();
private:
friend class extensions::ExtensionSessionsTest;
friend class SessionsSyncManagerTest;
- FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, PopulateSyncedSession);
- FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, PopulateSessionWindow);
- FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, ValidTabs);
FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, SetSessionTabFromDelegate);
FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest,
SetSessionTabFromDelegateNavigationIndex);
@@ -143,13 +117,10 @@ class SessionsSyncManager : public syncer::SyncableService,
ProcessForeignDeleteTabsWithReusedNodeIds);
FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest,
SaveUnassociatedNodesForReassociation);
- FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, MergeDeletesCorruptNode);
FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, MergeDeletesBadHash);
FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest,
MergeLocalSessionExistingTabs);
FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest,
- CheckPrerenderedWebContentsSwap);
- FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest,
AssociateWindowsDontReloadTabs);
FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest, SwappedOutOnRestore);
FRIEND_TEST_ALL_PREFIXES(SessionsSyncManagerTest,
@@ -157,11 +128,6 @@ class SessionsSyncManager : public syncer::SyncableService,
void InitializeCurrentMachineTag(const std::string& cache_guid);
- // Load and add window or tab data from synced specifics to our internal
- // tracking.
- void UpdateTrackerWithSpecifics(const sync_pb::SessionSpecifics& specifics,
- const base::Time& modification_time);
-
// Returns true if |sync_data| contained a header node for the current
// machine, false otherwise. |new_changes| is a link to the SyncChange
// pipeline that exists in the caller's context. This function will append
@@ -193,21 +159,8 @@ class SessionsSyncManager : public syncer::SyncableService,
void DeleteForeignSessionInternal(const std::string& tag,
syncer::SyncChangeList* change_output);
- // Used to populate a session header from the session specifics header
- // provided.
- void PopulateSyncedSessionFromSpecifics(
- const std::string& session_tag,
- const sync_pb::SessionHeader& header_specifics,
- base::Time mtime,
- SyncedSession* synced_session);
-
- // Builds |synced_session_window| from the session specifics window
- // provided and updates the SessionTracker with foreign session data created.
- void PopulateSyncedSessionWindowFromSpecifics(
- const std::string& session_tag,
- const sync_pb::SessionWindow& specifics,
- base::Time mtime,
- SyncedSessionWindow* synced_session_window);
+ // Same as above but it also notifies the processor.
+ void DeleteForeignSessionFromUI(const std::string& tag);
// Resync local window information. Updates the local sessions header node
// with the status of open windows and the order of tabs they contain. Should
@@ -275,10 +228,6 @@ class SessionsSyncManager : public syncer::SyncableService,
// See |local_tab_pool_out_of_sync_|.
bool RebuildAssociations();
- // Validates the content of a SessionHeader protobuf.
- // Returns false if validation fails.
- static bool IsValidSessionHeader(const sync_pb::SessionHeader& header);
-
// Calculates the tag hash from a specifics object. Calculating the hash is
// something we typically want to avoid doing in the model type like this.
// However, the only place that understands how to generate a tag from the
@@ -291,10 +240,6 @@ class SessionsSyncManager : public syncer::SyncableService,
SyncedWindowDelegatesGetter* synced_window_delegates_getter() const;
- void TrackNavigationIds(const sessions::SerializedNavigationEntry& current);
-
- void CleanupNavigationTracking();
-
// On Android, it's possible to not have any tabbed windows when only custom
// tabs are currently open. This means that there is tab data that will be
// restored later, but we cannot access it. This method is an elaborate way to
@@ -306,6 +251,8 @@ class SessionsSyncManager : public syncer::SyncableService,
SyncedSessionTracker session_tracker_;
FaviconCache favicon_cache_;
+ SessionsGlobalIdMapper global_id_mapper_;
+ OpenTabsUIDelegateImpl open_tabs_ui_delegate_;
// Tracks whether our local representation of which sync nodes map to what
// tabs (belonging to the current local session) is inconsistent. This can
@@ -341,28 +288,16 @@ class SessionsSyncManager : public syncer::SyncableService,
LocalSessionEventRouter* local_event_router_;
- // Owns revisiting instrumentation logic for page visit events.
- PageRevisitBroadcaster page_revisit_broadcaster_;
-
std::unique_ptr<sync_sessions::LostNavigationsRecorder>
lost_navigations_recorder_;
// Callback to inform interested observer that new sessions data has arrived.
- base::Closure sessions_updated_callback_;
-
- // Callback to inform sync that a sync data refresh is requested.
- base::Closure datatype_refresh_callback_;
+ base::RepeatingClosure sessions_updated_callback_;
// Tracks Chrome Tasks, which associates navigations, with tab and navigation
// changes of current session.
std::unique_ptr<TaskTracker> task_tracker_;
- // Used to track global_ids that should be used when referencing various
- // pieces of sessions data, and notify observer when things have changed.
- std::map<int64_t, int> global_to_unique_;
- std::map<int, int64_t> unique_to_current_global_;
- std::vector<syncer::GlobalIdChange> global_id_change_observers_;
-
DISALLOW_COPY_AND_ASSIGN(SessionsSyncManager);
};
diff --git a/chromium/components/sync_sessions/sessions_sync_manager_unittest.cc b/chromium/components/sync_sessions/sessions_sync_manager_unittest.cc
index c47117a824d..54dc8c2bea3 100644
--- a/chromium/components/sync_sessions/sessions_sync_manager_unittest.cc
+++ b/chromium/components/sync_sessions/sessions_sync_manager_unittest.cc
@@ -15,10 +15,8 @@
#include "components/sync/device_info/local_device_info_provider_mock.h"
#include "components/sync/driver/fake_sync_client.h"
#include "components/sync/driver/sync_api_component_factory.h"
-#include "components/sync/model/attachments/attachment_id.h"
-#include "components/sync/model/attachments/attachment_service_proxy_for_test.h"
#include "components/sync/model/sync_error_factory_mock.h"
-#include "components/sync_sessions/fake_sync_sessions_client.h"
+#include "components/sync_sessions/mock_sync_sessions_client.h"
#include "components/sync_sessions/session_sync_test_helper.h"
#include "components/sync_sessions/sync_sessions_client.h"
#include "components/sync_sessions/synced_tab_delegate.h"
@@ -127,22 +125,17 @@ testing::AssertionResult ChangeTypeMatches(
class SessionNotificationObserver {
public:
- SessionNotificationObserver()
- : notified_of_update_(false), notified_of_refresh_(false) {}
+ SessionNotificationObserver() : notified_of_update_(false) {}
void NotifyOfUpdate() { notified_of_update_ = true; }
- void NotifyOfRefresh() { notified_of_refresh_ = true; }
bool notified_of_update() const { return notified_of_update_; }
- bool notified_of_refresh() const { return notified_of_refresh_; }
void Reset() {
notified_of_update_ = false;
- notified_of_refresh_ = false;
}
private:
bool notified_of_update_;
- bool notified_of_refresh_;
};
// A SyncedTabDelegate fake for testing. It simulates a normal
@@ -484,49 +477,25 @@ class DummyRouter : public LocalSessionEventRouter {
LocalSessionEventHandler* handler_ = nullptr;
};
-// Provides ability to override SyncedWindowDelegatesGetter.
-// All other calls are passed through to the original FakeSyncSessionsClient.
-class SyncSessionsClientShim : public FakeSyncSessionsClient {
- public:
- explicit SyncSessionsClientShim(
- SyncedWindowDelegatesGetter* synced_window_getter)
- : synced_window_getter_(synced_window_getter) {}
- ~SyncSessionsClientShim() override {}
-
- SyncedWindowDelegatesGetter* GetSyncedWindowDelegatesGetter() override {
- // The idea here is to allow the test code override the default
- // SyncedWindowDelegatesGetter provided by |sync_sessions_client_|.
- // If |synced_window_getter_| is explicitly set, return it; otherwise return
- // the default one provided by |sync_sessions_client_|.
- return synced_window_getter_;
- }
-
- private:
- SyncedWindowDelegatesGetter* synced_window_getter_;
-};
-
} // namespace
class SessionsSyncManagerTest : public testing::Test {
protected:
- SessionsSyncManagerTest() {}
-
void SetUp() override {
+ ON_CALL(mock_sync_sessions_client_, GetSyncedWindowDelegatesGetter())
+ .WillByDefault(testing::Return(&window_getter_));
+
local_device_ = std::make_unique<LocalDeviceInfoProviderMock>(
"cache_guid", "Wayne Gretzky's Hacking Box", "Chromium 10k",
"Chrome 10k", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id");
sync_client_ = std::make_unique<syncer::FakeSyncClient>();
- sessions_client_shim_ =
- std::make_unique<SyncSessionsClientShim>(&window_getter_);
sync_prefs_ =
std::make_unique<syncer::SyncPrefs>(sync_client_->GetPrefService());
router_ = std::make_unique<DummyRouter>();
manager_ = std::make_unique<SessionsSyncManager>(
- sessions_client_shim(), sync_prefs_.get(), local_device_.get(),
+ &mock_sync_sessions_client_, sync_prefs_.get(), local_device_.get(),
router_.get(),
base::Bind(&SessionNotificationObserver::NotifyOfUpdate,
- base::Unretained(&observer_)),
- base::Bind(&SessionNotificationObserver::NotifyOfRefresh,
base::Unretained(&observer_)));
}
@@ -550,9 +519,6 @@ class SessionsSyncManagerTest : public testing::Test {
LocalDeviceInfoProvider* local_device() { return local_device_.get(); }
SessionNotificationObserver* observer() { return &observer_; }
syncer::SyncPrefs* sync_prefs() { return sync_prefs_.get(); }
- SyncSessionsClient* sessions_client_shim() {
- return sessions_client_shim_.get();
- }
SyncedWindowDelegatesGetter* window_getter() { return &window_getter_; }
void InitWithSyncDataTakeOutput(const SyncDataList& initial_data,
@@ -675,8 +641,7 @@ class SessionsSyncManagerTest : public testing::Test {
base::Time mtime = base::Time()) const {
// The server ID is never relevant to these tests, so just use 1.
return SyncData::CreateRemoteData(
- 1, entity, mtime, syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create(),
+ 1, entity, mtime,
SessionsSyncManager::TagHashFromSpecifics(entity.session()));
}
@@ -796,7 +761,7 @@ class SessionsSyncManagerTest : public testing::Test {
private:
std::unique_ptr<syncer::FakeSyncClient> sync_client_;
- std::unique_ptr<SyncSessionsClientShim> sessions_client_shim_;
+ testing::NiceMock<MockSyncSessionsClient> mock_sync_sessions_client_;
std::unique_ptr<syncer::SyncPrefs> sync_prefs_;
SessionNotificationObserver observer_;
std::unique_ptr<DummyRouter> router_;
@@ -1098,6 +1063,87 @@ TEST_F(SessionsSyncManagerTest, PreserveTabbedDataCustomTab) {
VerifyLocalHeaderChange(out[1], 2, 2);
}
+// Create a placeholder and a non-placeholder that have the same sync ids. Only
+// the non-placeholder should survive. This state should be impossible for up
+// to date clients to enter.
+TEST_F(SessionsSyncManagerTest, ConflictingSyncIdsWithPlaceholder) {
+ syncer::SyncDataList in;
+ syncer::SyncChangeList out;
+
+ // First sync with one tab and one window.
+ TestSyncedWindowDelegate* window = AddWindow();
+ AddTab(window->GetSessionId(), kFoo1);
+ InitWithSyncDataTakeOutput(in, &out);
+
+ in = GetDataFromChanges(out);
+ int conflicting_sync_id =
+ out[1].sync_data().GetSpecifics().session().tab_node_id();
+ out.clear();
+ // There should be two entities, a header and a tab.
+ ASSERT_EQ(2U, in.size());
+
+ manager()->StopSyncing(syncer::SESSIONS);
+
+ // The main window's tab is now a placeholder, and we have a conflicting id
+ // for the custom tab. They should both have their tab ids reset, but the
+ // placeholder cannot be fixed, and will be dropped. Only the custom tab will
+ // show up now.
+ PlaceholderTabDelegate tab2(SessionID().id(), conflicting_sync_id);
+ window->OverrideTabAt(0, &tab2);
+
+ TestSyncedWindowDelegate* window2 = AddWindow();
+ SessionID new_window_id;
+ window2->OverrideWindowId(new_window_id.id());
+ window2->OverrideWindowTypeToCustomTab();
+ TestSyncedTabDelegate* tab3 = AddTab(window2->GetSessionId(), kBar1);
+ tab3->SetSyncId(conflicting_sync_id);
+ window2->OverrideTabAt(0, tab3);
+
+ InitWithSyncDataTakeOutput(ConvertToRemote(in), &out);
+
+ ASSERT_TRUE(ChangeTypeMatches(
+ out, {SyncChange::ACTION_ADD, SyncChange::ACTION_UPDATE}));
+ VerifyLocalTabChange(out[0], 1, kBar1);
+ VerifyLocalHeaderChange(out[1], 1, 1);
+}
+
+// Create two tabs with the same sync id, which is an invalid state. The manager
+// should strip both of the sync ids, and then new ones should be generated.
+// This state should be impossible for up to date clients to enter.
+TEST_F(SessionsSyncManagerTest, ConflictingSyncIdsBothReal) {
+ syncer::SyncDataList in;
+ syncer::SyncChangeList out;
+
+ TestSyncedWindowDelegate* window = AddWindow();
+ TestSyncedTabDelegate* tab1 = AddTab(window->GetSessionId(), kFoo1);
+ TestSyncedTabDelegate* tab2 = AddTab(window->GetSessionId(), kBar1);
+
+ // The pool wants to start vending numbers 0, 1, 2, ... etc. So we're
+ // guaranteed that when the manager clears the sync ids, it will be replaced
+ // with smaller values.
+ int dupe_sync_id = 13;
+ tab1->SetSyncId(dupe_sync_id);
+ tab2->SetSyncId(dupe_sync_id);
+
+ InitWithSyncDataTakeOutput(in, &out);
+ // Header creation, two tab creations, and header update.
+ ASSERT_TRUE(ChangeTypeMatches(
+ out, {SyncChange::ACTION_ADD, SyncChange::ACTION_ADD,
+ SyncChange::ACTION_ADD, SyncChange::ACTION_UPDATE}));
+ VerifyLocalHeaderChange(out[0], 0, 0);
+ VerifyLocalTabChange(out[1], 1, kFoo1);
+ VerifyLocalTabChange(out[2], 1, kBar1);
+ VerifyLocalHeaderChange(out[3], 1, 2);
+
+ // The sync ids should have been fixed.
+ EXPECT_NE(dupe_sync_id,
+ out[1].sync_data().GetSpecifics().session().tab_node_id());
+ EXPECT_NE(dupe_sync_id,
+ out[2].sync_data().GetSpecifics().session().tab_node_id());
+ EXPECT_NE(out[1].sync_data().GetSpecifics().session().tab_node_id(),
+ out[2].sync_data().GetSpecifics().session().tab_node_id());
+}
+
// Tests MergeDataAndStartSyncing with sync data but no local data.
TEST_F(SessionsSyncManagerTest, MergeWithInitialForeignSession) {
std::vector<SessionID::id_type> tab_list1(std::begin(kTabIds1),
@@ -1125,7 +1171,8 @@ TEST_F(SessionsSyncManagerTest, MergeWithInitialForeignSession) {
EXPECT_TRUE(FilterOutLocalHeaderChanges(&output)->empty());
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(1U, foreign_sessions.size());
std::vector<std::vector<SessionID::id_type>> session_reference;
session_reference.push_back(tab_list1);
@@ -1156,7 +1203,8 @@ TEST_F(SessionsSyncManagerTest, MergeLocalSessionExistingTabs) {
// Check that this machine's data is not included in the foreign windows.
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_FALSE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_FALSE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
VerifyLocalHeaderChange(out[0], 0, 0);
VerifyLocalTabChange(out[1], tab->GetEntryCount(), kBaz1);
@@ -1203,7 +1251,8 @@ TEST_F(SessionsSyncManagerTest, MergeWithLocalAndForeignTabs) {
// Verify foreign data.
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
std::vector<std::vector<SessionID::id_type>> session_reference;
session_reference.push_back(tab_list1);
helper()->VerifySyncedSession(kTag1, session_reference,
@@ -1265,7 +1314,8 @@ TEST_F(SessionsSyncManagerTest, UpdatesAfterMixedMerge) {
// Check that the foreign session was associated and retrieve the data.
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(1U, foreign_sessions.size());
ASSERT_EQ(
4U,
@@ -1286,7 +1336,8 @@ TEST_F(SessionsSyncManagerTest, UpdatesAfterMixedMerge) {
manager()->ProcessSyncChanges(FROM_HERE, changes);
changes.clear();
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
std::vector<std::vector<SessionID::id_type>> meta2_reference;
meta2_reference.push_back(tag2_tab_list);
ASSERT_EQ(2U, foreign_sessions.size());
@@ -1310,7 +1361,8 @@ TEST_F(SessionsSyncManagerTest, UpdatesAfterMixedMerge) {
AddTabsToChangeList(tabs1, SyncChange::ACTION_UPDATE, &removal);
manager()->ProcessSyncChanges(FROM_HERE, removal);
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(2U, foreign_sessions.size());
ASSERT_EQ(
3U,
@@ -1325,9 +1377,11 @@ TEST_F(SessionsSyncManagerTest, DeleteForeignSession) {
SyncChangeList changes;
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_FALSE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_FALSE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
manager()->DeleteForeignSessionInternal(kTag1, &changes);
- ASSERT_FALSE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_FALSE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
EXPECT_TRUE(changes.empty());
// Fill an instance of session specifics with a foreign session's data.
@@ -1338,17 +1392,20 @@ TEST_F(SessionsSyncManagerTest, DeleteForeignSession) {
helper()->BuildForeignSession(kTag1, tab_list1, &tabs));
// Update associator with the session's meta node, window, and tabs.
- manager()->UpdateTrackerWithSpecifics(meta, base::Time());
+ UpdateTrackerWithSpecifics(meta, base::Time(), &manager()->session_tracker_);
for (std::vector<sync_pb::SessionSpecifics>::iterator iter = tabs.begin();
iter != tabs.end(); ++iter) {
- manager()->UpdateTrackerWithSpecifics(*iter, base::Time());
+ UpdateTrackerWithSpecifics(*iter, base::Time(),
+ &manager()->session_tracker_);
}
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(1U, foreign_sessions.size());
// Now delete the foreign session.
manager()->DeleteForeignSessionInternal(kTag1, &changes);
- EXPECT_FALSE(manager()->GetAllForeignSessions(&foreign_sessions));
+ EXPECT_FALSE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
EXPECT_EQ(5U, changes.size());
ASSERT_TRUE(AllOfChangesAreType(changes, SyncChange::ACTION_DELETE));
@@ -1386,7 +1443,8 @@ TEST_F(SessionsSyncManagerTest, WriteForeignSessionToNodeTabsFirst) {
// Check that the foreign session was associated and retrieve the data.
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(1U, foreign_sessions.size());
std::vector<std::vector<SessionID::id_type>> session_reference;
session_reference.push_back(tab_list1);
@@ -1424,7 +1482,8 @@ TEST_F(SessionsSyncManagerTest, WriteForeignSessionToNodeMissingTabs) {
// Check that the foreign session was associated and retrieve the data.
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(1U, foreign_sessions.size());
ASSERT_EQ(2U, foreign_sessions[0]->windows.size());
ASSERT_EQ(
@@ -1443,7 +1502,8 @@ TEST_F(SessionsSyncManagerTest, WriteForeignSessionToNodeMissingTabs) {
// Check that the foreign session was associated and retrieve the data.
foreign_sessions.clear();
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(1U, foreign_sessions.size());
ASSERT_EQ(1U, foreign_sessions[0]->windows.size());
std::vector<std::vector<SessionID::id_type>> session_reference;
@@ -1507,7 +1567,8 @@ TEST_F(SessionsSyncManagerTest, ProcessForeignDelete) {
manager()->ProcessSyncChanges(FROM_HERE, changes);
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(1U, foreign_sessions.size());
changes.clear();
@@ -1515,7 +1576,8 @@ TEST_F(SessionsSyncManagerTest, ProcessForeignDelete) {
changes.push_back(MakeRemoteChange(meta, SyncChange::ACTION_DELETE));
manager()->ProcessSyncChanges(FROM_HERE, changes);
- EXPECT_FALSE(manager()->GetAllForeignSessions(&foreign_sessions));
+ EXPECT_FALSE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
}
TEST_F(SessionsSyncManagerTest, ProcessForeignDeleteTabs) {
@@ -1570,7 +1632,8 @@ TEST_F(SessionsSyncManagerTest, ProcessForeignDeleteTabs) {
manager()->ProcessSyncChanges(FROM_HERE, changes);
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(1U, foreign_sessions.size());
std::vector<std::vector<SessionID::id_type>> session_reference;
session_reference.push_back(update_list);
@@ -1801,9 +1864,8 @@ TEST_F(SessionsSyncManagerTest, MergeDeletesBadHash) {
sync_pb::SessionSpecifics bad_header(
helper()->BuildForeignSession(bad_header_tag, empty_ids, &empty_tabs));
entity.mutable_session()->CopyFrom(bad_header);
- foreign_data.push_back(SyncData::CreateRemoteData(
- 1, entity, base::Time(), syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create(), "bad_header_tag_hash"));
+ foreign_data.push_back(SyncData::CreateRemoteData(1, entity, base::Time(),
+ "bad_header_tag_hash"));
const std::string good_tag_tab = "good_tag_tab";
sync_pb::SessionSpecifics good_tab;
@@ -1814,9 +1876,8 @@ TEST_F(SessionsSyncManagerTest, MergeDeletesBadHash) {
sync_pb::SessionSpecifics bad_tab;
helper()->BuildTabSpecifics(bad_tab_tag, 0, 2, &bad_tab);
entity.mutable_session()->CopyFrom(bad_tab);
- foreign_data.push_back(SyncData::CreateRemoteData(
- 1, entity, base::Time(), syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create(), "bad_tab_tag_hash"));
+ foreign_data.push_back(
+ SyncData::CreateRemoteData(1, entity, base::Time(), "bad_tab_tag_hash"));
SyncChangeList output;
InitWithSyncDataTakeOutput(foreign_data, &output);
@@ -1986,7 +2047,8 @@ TEST_F(SessionsSyncManagerTest, ForeignSessionModifiedTime) {
output.clear();
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(3U, foreign_sessions.size());
EXPECT_EQ(newest_time, foreign_sessions[0]->modified_time);
EXPECT_EQ(newest_time, foreign_sessions[1]->modified_time);
@@ -2024,7 +2086,8 @@ TEST_F(SessionsSyncManagerTest, DoGarbageCollection) {
// Check that the foreign session was associated and retrieve the data.
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(2U, foreign_sessions.size());
foreign_sessions.clear();
@@ -2038,7 +2101,8 @@ TEST_F(SessionsSyncManagerTest, DoGarbageCollection) {
SyncDataLocal(output[i].sync_data()).GetTag());
}
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(1U, foreign_sessions.size());
std::vector<std::vector<SessionID::id_type>> session_reference;
session_reference.push_back(tab_list2);
@@ -2099,7 +2163,8 @@ TEST_F(SessionsSyncManagerTest, DoGarbageCollectionOrphans) {
// Although we have 3 foreign sessions, only 1 is valid/clean enough.
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(1U, foreign_sessions.size());
foreign_sessions.clear();
@@ -2137,13 +2202,15 @@ TEST_F(SessionsSyncManagerTest, GarbageCollectionHonoursUpdate) {
// Check that the foreign session was associated and retrieve the data.
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(1U, foreign_sessions.size());
foreign_sessions.clear();
// Verify the now non-stale session does not get deleted.
manager()->DoGarbageCollection();
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(1U, foreign_sessions.size());
std::vector<std::vector<SessionID::id_type>> session_reference;
session_reference.push_back(tab_list1);
@@ -2198,23 +2265,10 @@ TEST_F(SessionsSyncManagerTest, NotifiedOfLocalRemovalOfForeignSession) {
observer()->Reset();
ASSERT_FALSE(observer()->notified_of_update());
- manager()->DeleteForeignSession(tag);
+ manager()->GetOpenTabsUIDelegate()->DeleteForeignSession(tag);
ASSERT_TRUE(observer()->notified_of_update());
}
-// Tests that opening the other devices page triggers a session sync refresh.
-// This page only exists on mobile platforms today; desktop has a
-// search-enhanced NTP without other devices.
-TEST_F(SessionsSyncManagerTest, NotifiedOfRefresh) {
- SessionID::id_type window_id = AddWindow()->GetSessionId();
- ASSERT_FALSE(observer()->notified_of_refresh());
- InitWithNoSyncData();
- TestSyncedTabDelegate* tab = AddTab(window_id, kFoo1);
- EXPECT_FALSE(observer()->notified_of_refresh());
- NavigateTab(tab, "chrome://newtab/#open_tabs");
- EXPECT_TRUE(observer()->notified_of_refresh());
-}
-
// Tests receipt of duplicate tab IDs in the same window. This should never
// happen, but we want to make sure the client won't do anything bad if it does
// receive such garbage input data.
@@ -2316,7 +2370,8 @@ TEST_F(SessionsSyncManagerTest, ReceiveDuplicateUnassociatedTabs) {
InitWithSyncDataTakeOutput(initial_data, &output);
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
const std::vector<std::unique_ptr<sessions::SessionTab>>& window_tabs =
foreign_sessions[0]->windows.find(0)->second->wrapped_window.tabs;
@@ -2354,7 +2409,8 @@ TEST_F(SessionsSyncManagerTest, GetAllForeignSessions) {
InitWithSyncDataTakeOutput(initial_data, &output);
std::vector<const SyncedSession*> foreign_sessions;
- ASSERT_TRUE(manager()->GetAllForeignSessions(&foreign_sessions));
+ ASSERT_TRUE(manager()->GetOpenTabsUIDelegate()->GetAllForeignSessions(
+ &foreign_sessions));
ASSERT_EQ(2U, foreign_sessions.size());
ASSERT_GT(foreign_sessions[0]->modified_time,
foreign_sessions[1]->modified_time);
@@ -2394,7 +2450,8 @@ TEST_F(SessionsSyncManagerTest, GetForeignSessionTabs) {
InitWithSyncDataTakeOutput(initial_data, &output);
std::vector<const sessions::SessionTab*> tabs;
- ASSERT_TRUE(manager()->GetForeignSessionTabs(kTag1, &tabs));
+ ASSERT_TRUE(
+ manager()->GetOpenTabsUIDelegate()->GetForeignSessionTabs(kTag1, &tabs));
// Assert that the size matches the total number of tabs and that the order
// is from most recent to least.
ASSERT_EQ(tab_list1.size() + tab_list2.size(), tabs.size());
@@ -2532,9 +2589,10 @@ TEST_F(SessionsSyncManagerTest, RestoredPlacholderTabNodeDeleted) {
}
// Check the behavior for a placeholder tab in one window being mapped to the
-// same sync entity as a tab in another window. If the placeholder is associated
-// last, the original tab should be unmapped from the first window, and reused
-// by the placeholder in the new window..
+// same sync entity as a tab in another window. The order should not matter.
+// Instead, they both should have their sync data discarded, sync ids reset, and
+// then re-created where possible (not possible for the placeholder). Assuming a
+// well behaved client, this should never happen.
TEST_F(SessionsSyncManagerTest, PlaceholderConflictAcrossWindows) {
syncer::SyncDataList in;
syncer::SyncChangeList out;
@@ -2559,25 +2617,18 @@ TEST_F(SessionsSyncManagerTest, PlaceholderConflictAcrossWindows) {
out.clear();
InitWithSyncDataTakeOutput(in, &out);
- // The tab entity will be overwritten twice. Once with the information for
- // tab 1 and then again with the information for tab 2. This will be followed
- // by a header change reflecting only the final tab.
- ASSERT_TRUE(
- ChangeTypeMatches(out,
- {SyncChange::ACTION_UPDATE, SyncChange::ACTION_UPDATE,
- SyncChange::ACTION_UPDATE}));
- VerifyLocalHeaderChange(out[2], 2, 1);
+ // The two tabs have the same sync id, which is not allowed. They will have
+ // their ids stripped and re-generated. But the placeholder cannot survive
+ // this and will not show up in results. Because we have potentially new sync
+ // ids, the essentially re-created tab will be an ADD.
+ ASSERT_TRUE(ChangeTypeMatches(
+ out, {SyncChange::ACTION_ADD, SyncChange::ACTION_UPDATE}));
+ VerifyLocalHeaderChange(out[1], 1, 1);
VerifyLocalTabChange(out[0], 1, kFoo1);
- EXPECT_EQ(sync_id, out[0].sync_data().GetSpecifics().session().tab_node_id());
EXPECT_EQ(tab1->GetSessionId(),
out[0].sync_data().GetSpecifics().session().tab().tab_id());
- // Because tab 2 is a placeholder, tab 1's URL will be preserved.
- VerifyLocalTabChange(out[1], 1, kFoo1);
- EXPECT_EQ(sync_id, out[1].sync_data().GetSpecifics().session().tab_node_id());
- EXPECT_EQ(tab2.GetSessionId(),
- out[1].sync_data().GetSpecifics().session().tab().tab_id());
- EXPECT_EQ(window2->GetSessionId(),
- out[1].sync_data().GetSpecifics().session().tab().window_id());
+ EXPECT_EQ(tab1->GetSyncId(),
+ out[0].sync_data().GetSpecifics().session().tab_node_id());
}
// Tests that task ids are generated for navigations on local tabs.
@@ -2629,80 +2680,4 @@ TEST_F(SessionsSyncManagerTest, TrackTasksOnLocalTabModified) {
EXPECT_EQ(tab.navigation(1).ancestor_task_id(0), tab.navigation(0).task_id());
}
-void CaptureGlobalIdChange(int64_t* old_ptr,
- int64_t* new_ptr,
- int64_t old_id,
- int64_t new_id) {
- *old_ptr = old_id;
- *new_ptr = new_id;
-}
-
-// Tests that subscribers to AddGlobalIdChangeObserver are notified when a
-// global_id is noticed to have been changed.
-TEST_F(SessionsSyncManagerTest, AddGlobalIdChangeObserver) {
- TestSyncedWindowDelegate* window = AddWindow();
- SessionID::id_type window_id = window->GetSessionId();
- SyncChangeList out;
- InitWithSyncDataTakeOutput(SyncDataList(), &out);
-
- int64_t old_id = -1;
- int64_t new_id = -1;
- manager()->AddGlobalIdChangeObserver(
- base::Bind(&CaptureGlobalIdChange, &old_id, &new_id));
-
- TestSyncedTabDelegate* tab = AddTab(window_id, kFoo1, kTime1);
- EXPECT_EQ(-1, old_id);
- EXPECT_EQ(-1, new_id);
-
- ReloadTab(tab, kTime2);
- EXPECT_EQ(kTime1.ToInternalValue(), old_id);
- EXPECT_EQ(kTime2.ToInternalValue(), new_id);
-}
-
-// Tests that GetLatestGlobalId returns correct mappings for updated global_ids.
-TEST_F(SessionsSyncManagerTest, GetLatestGlobalId) {
- TestSyncedWindowDelegate* window = AddWindow();
- SessionID::id_type window_id = window->GetSessionId();
- SyncChangeList out;
- InitWithSyncDataTakeOutput(SyncDataList(), &out);
-
- TestSyncedTabDelegate* tab = AddTab(window_id, kFoo1, kTime1);
- ReloadTab(tab, kTime2);
- ReloadTab(tab, kTime3);
-
- EXPECT_EQ(kTime3.ToInternalValue(),
- manager()->GetLatestGlobalId(kTime1.ToInternalValue()));
- EXPECT_EQ(kTime3.ToInternalValue(),
- manager()->GetLatestGlobalId(kTime2.ToInternalValue()));
- EXPECT_EQ(kTime3.ToInternalValue(),
- manager()->GetLatestGlobalId(kTime3.ToInternalValue()));
- // kTime4 is not mapped, so itself should be returned.
- EXPECT_EQ(kTime4.ToInternalValue(),
- manager()->GetLatestGlobalId(kTime4.ToInternalValue()));
-}
-
-// Tests that the global_id mapping is eventually dropped after we reach out
-// threshold for the amount to remember.
-TEST_F(SessionsSyncManagerTest, GlobalIdMapperCleanup) {
- TestSyncedWindowDelegate* window = AddWindow();
- SessionID::id_type window_id = window->GetSessionId();
- SyncChangeList out;
- InitWithSyncDataTakeOutput(SyncDataList(), &out);
-
- base::Time current_time = kTime1;
- TestSyncedTabDelegate* tab = AddTab(window_id, kFoo1, current_time);
-
- for (int i = 0; i < 105; i++) {
- current_time =
- base::Time::FromInternalValue(current_time.ToInternalValue() + 1);
- ReloadTab(tab, current_time);
- }
-
- // Threshold is 100, kTime1 should be dropped, kTime1+10 should not.
- EXPECT_EQ(kTime1.ToInternalValue(),
- manager()->GetLatestGlobalId(kTime1.ToInternalValue()));
- EXPECT_EQ(current_time.ToInternalValue(),
- manager()->GetLatestGlobalId(10 + kTime1.ToInternalValue()));
-}
-
} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/sync_sessions_metrics.cc b/chromium/components/sync_sessions/sync_sessions_metrics.cc
deleted file mode 100644
index b5cf37e3473..00000000000
--- a/chromium/components/sync_sessions/sync_sessions_metrics.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/sync_sessions_metrics.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/time/time.h"
-#include "components/sessions/core/session_types.h"
-#include "components/sync_sessions/sessions_sync_manager.h"
-#include "components/sync_sessions/synced_session.h"
-
-namespace sync_sessions {
-
-// static
-void SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP(
- SessionsSyncManager* sessions_sync_manager) {
- if (sessions_sync_manager != nullptr) {
- std::vector<const SyncedSession*> foreign_sessions;
- sessions_sync_manager->GetAllForeignSessions(&foreign_sessions);
- base::Time best(MaxTabTimestamp(foreign_sessions));
- base::Time now(base::Time::Now());
- // Don't emit metrics if the foreign tab is timestamped in the future. While
- // the timestamp is set on a different machine, and we may lose some
- // fraction of metrics to clock skew, we don't want the potential to have
- // bad machines with clocks many hours off causing lots of seemingly 0
- // second entries.
- if (base::Time::UnixEpoch() < best && best <= now) {
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Sync.YoungestForeignTabAgeOnNTP", (now - best).InSeconds(), 1,
- base::TimeDelta::FromDays(14).InSeconds(), 100);
- }
- }
-}
-
-// static
-base::Time SyncSessionsMetrics::MaxTabTimestamp(
- const std::vector<const SyncedSession*>& sessions) {
- // While Sessions are ordered by recency, windows and tabs are not. Because
- // the timestamp of sessions are updated when windows/tabs are removed, we
- // only need to search until all the remaining sessions are older than the
- // most recent tab we've found so far.
- base::Time best(base::Time::UnixEpoch());
- for (const SyncedSession* session : sessions) {
- if (session->modified_time < best) {
- break;
- }
- for (const auto& key_value : session->windows) {
- for (const auto& tab : key_value.second->wrapped_window.tabs) {
- best = std::max(best, tab->timestamp);
- }
- }
- }
- return best;
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/sync_sessions_metrics.h b/chromium/components/sync_sessions/sync_sessions_metrics.h
deleted file mode 100644
index 90770b42118..00000000000
--- a/chromium/components/sync_sessions/sync_sessions_metrics.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SYNC_SESSIONS_SYNC_SESSIONS_METRICS_H_
-#define COMPONENTS_SYNC_SESSIONS_SYNC_SESSIONS_METRICS_H_
-
-#include <vector>
-
-namespace base {
-class Time;
-} // namespace base
-
-namespace sync_sessions {
-
-class SessionsSyncManager;
-struct SyncedSession;
-
-class SyncSessionsMetrics {
- public:
- // Records via an UMA histogram the age of the youngest foreign tab the given
- // manager is aware of. No attempt is made to aquire a more recent version of
- // world. If anything goes wrong, such as the manager being null, no foreign
- // session present, or a foreign tab with a timestamp in the future then no
- // metric is emitted.
- static void RecordYoungestForeignTabAgeOnNTP(
- SessionsSyncManager* sessions_sync_manager);
-
- private:
- friend class SyncSessionsMetricsTest;
-
- // Returns the highest timestamp for any tab in the given sessions. Note that
- // sessions should be sorted by timestamp, and session timestamps should
- // always be greater or equal to children window/tab timestamps. No navigation
- // timestamps are checked.
- static base::Time MaxTabTimestamp(
- const std::vector<const SyncedSession*>& sessions);
-};
-
-} // namespace sync_sessions
-
-#endif // COMPONENTS_SYNC_SESSIONS_SYNC_SESSIONS_METRICS_H_
diff --git a/chromium/components/sync_sessions/sync_sessions_metrics_unittest.cc b/chromium/components/sync_sessions/sync_sessions_metrics_unittest.cc
deleted file mode 100644
index 4e06278a4b0..00000000000
--- a/chromium/components/sync_sessions/sync_sessions_metrics_unittest.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync_sessions/sync_sessions_metrics.h"
-
-#include <algorithm>
-#include <memory>
-
-#include "base/test/histogram_tester.h"
-#include "base/time/time.h"
-#include "components/sessions/core/session_types.h"
-#include "components/sync_sessions/fake_sync_sessions_client.h"
-#include "components/sync_sessions/sessions_sync_manager.h"
-#include "components/sync_sessions/synced_session.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using sessions::SessionWindow;
-using sessions::SessionTab;
-using base::Time;
-using base::TimeDelta;
-
-namespace sync_sessions {
-
-namespace {
-
-class FakeSessionsSyncManager : public SessionsSyncManager {
- public:
- FakeSessionsSyncManager(SyncSessionsClient* sessions_client,
- std::vector<std::unique_ptr<SyncedSession>>* sessions)
- : SessionsSyncManager(sessions_client,
- nullptr,
- nullptr,
- nullptr,
- base::Closure(),
- base::Closure()),
- sessions_(sessions) {}
-
- bool GetAllForeignSessions(
- std::vector<const SyncedSession*>* sessions) override {
- for (auto& session : *sessions_) {
- sessions->push_back(session.get());
- }
- return true;
- }
-
- private:
- std::vector<std::unique_ptr<SyncedSession>>* sessions_;
-};
-
-Time SecondsFromEpoch(int seconds) {
- return Time::UnixEpoch() + TimeDelta::FromSeconds(seconds);
-}
-
-} // namespace
-
-class SyncSessionsMetricsTest : public ::testing::Test {
- protected:
- SyncSessionsMetricsTest() : fake_manager_(&fake_client_, &sessions_) {}
-
- // Sets the tab/window/session timestamps and creates anything needed. The new
- // calls in here are safe because the session/window objects are going to
- // delete all their children when their destructors are invoked.
- void PushTab(size_t tabIndex, int windowIndex, Time timestamp) {
- // First add sessions/windows as necessary.
- while (tabIndex >= sessions_.size()) {
- sessions_.push_back(std::make_unique<SyncedSession>());
- }
- if (sessions_[tabIndex]->windows.find(windowIndex) ==
- sessions_[tabIndex]->windows.end()) {
- sessions_[tabIndex]->windows[windowIndex] =
- std::make_unique<SyncedSessionWindow>();
- }
-
- sessions_[tabIndex]->modified_time =
- std::max(sessions_[tabIndex]->modified_time, timestamp);
- sessions_[tabIndex]->windows[windowIndex]->wrapped_window.timestamp =
- std::max(
- sessions_[tabIndex]->windows[windowIndex]->wrapped_window.timestamp,
- timestamp);
- sessions_[tabIndex]->windows[windowIndex]->wrapped_window.tabs.push_back(
- std::make_unique<SessionTab>());
- sessions_[tabIndex]
- ->windows[windowIndex]
- ->wrapped_window.tabs.back()
- ->timestamp = timestamp;
- }
-
- // Removes the last tab at the given indexes. The idexes provided should be
- // valid for existing data, this method does not check their validity. Windows
- // are not cleaned up/removed if they're left with 0 tabs.
- void PopTab(size_t tabIndex, int windowIndex, Time timestamp) {
- sessions_[tabIndex]->modified_time =
- std::max(sessions_[tabIndex]->modified_time, timestamp);
- sessions_[tabIndex]->windows[windowIndex]->wrapped_window.timestamp =
- std::max(
- sessions_[tabIndex]->windows[windowIndex]->wrapped_window.timestamp,
- timestamp);
- sessions_[tabIndex]->windows[windowIndex]->wrapped_window.tabs.pop_back();
- }
-
- // Runs MaxTabTimestamp on the current sessions data.
- Time MaxTabTimestamp() {
- std::vector<const SyncedSession*> typed_sessions;
- for (auto& session : sessions_) {
- typed_sessions.push_back(session.get());
- }
- return SyncSessionsMetrics::MaxTabTimestamp(typed_sessions);
- }
-
- SessionsSyncManager* get_sessions_sync_manager() { return &fake_manager_; }
-
- private:
- std::vector<std::unique_ptr<SyncedSession>> sessions_;
- FakeSyncSessionsClient fake_client_;
- FakeSessionsSyncManager fake_manager_;
-};
-
-TEST_F(SyncSessionsMetricsTest, NoWindows) {
- ASSERT_EQ(Time::UnixEpoch(), MaxTabTimestamp());
-}
-
-TEST_F(SyncSessionsMetricsTest, NoTabs) {
- PushTab(0, 0, SecondsFromEpoch(1));
- PopTab(0, 0, SecondsFromEpoch(2));
- ASSERT_EQ(Time::UnixEpoch(), MaxTabTimestamp());
-}
-
-TEST_F(SyncSessionsMetricsTest, OneTab) {
- PushTab(0, 0, SecondsFromEpoch(1));
- ASSERT_EQ(SecondsFromEpoch(1), MaxTabTimestamp());
-}
-
-TEST_F(SyncSessionsMetricsTest, MultipleTabs) {
- PushTab(0, 0, SecondsFromEpoch(1));
- PushTab(0, 0, SecondsFromEpoch(3));
- PushTab(0, 0, SecondsFromEpoch(2));
- ASSERT_EQ(SecondsFromEpoch(3), MaxTabTimestamp());
-}
-
-TEST_F(SyncSessionsMetricsTest, MultipleWindows) {
- PushTab(0, 1, SecondsFromEpoch(1));
- PushTab(0, 2, SecondsFromEpoch(3));
- PushTab(0, 3, SecondsFromEpoch(2));
- ASSERT_EQ(SecondsFromEpoch(3), MaxTabTimestamp());
-}
-
-TEST_F(SyncSessionsMetricsTest, OrderedSessions) {
- PushTab(0, 0, SecondsFromEpoch(3));
- PushTab(1, 0, SecondsFromEpoch(2));
- PushTab(2, 0, SecondsFromEpoch(1));
- ASSERT_EQ(SecondsFromEpoch(3), MaxTabTimestamp());
-}
-
-TEST_F(SyncSessionsMetricsTest, NonOrderedSessions) {
- // While 2 is not the max, it should give up when it sees the tab at index 1.
- // This is breaking the assumptions of the logic we're testing, and thus we
- // expect to return an incorrect ansewr. What this test is really verifying
- // is that the logic that finds the most recent timestamp is is exiting early
- // instead of inefficiently examining all foreign tabs.
- PushTab(0, 0, SecondsFromEpoch(2));
- PushTab(1, 0, SecondsFromEpoch(1));
- PushTab(2, 0, SecondsFromEpoch(3));
- ASSERT_EQ(SecondsFromEpoch(2), MaxTabTimestamp());
-}
-
-TEST_F(SyncSessionsMetricsTest, OrderedSessionsWithDeletedTab) {
- // Tab/window with index 0 is going to be the most recent, but the recent tab
- // was removed. The algorithm should continue on and find the tab in index 1.
- PushTab(0, 0, SecondsFromEpoch(1));
- PushTab(0, 0, SecondsFromEpoch(4));
- PopTab(0, 0, SecondsFromEpoch(5));
- PushTab(1, 0, SecondsFromEpoch(3));
- PushTab(2, 0, SecondsFromEpoch(2));
- ASSERT_EQ(SecondsFromEpoch(3), MaxTabTimestamp());
-}
-
-TEST_F(SyncSessionsMetricsTest, SkipEmitNoManager) {
- base::HistogramTester histogram_tester;
- PushTab(0, 0, Time::Now() - TimeDelta::FromHours(1));
- SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP(nullptr);
- histogram_tester.ExpectTotalCount("Sync.YoungestForeignTabAgeOnNTP", 0);
-}
-
-TEST_F(SyncSessionsMetricsTest, SkipEmitNoSessions) {
- base::HistogramTester histogram_tester;
- SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP(
- get_sessions_sync_manager());
- histogram_tester.ExpectTotalCount("Sync.YoungestForeignTabAgeOnNTP", 0);
-}
-
-TEST_F(SyncSessionsMetricsTest, SkipEmitInvalidTimestamp) {
- base::HistogramTester histogram_tester;
- // Foreign session is far in the future, it should be ignored.
- PushTab(0, 0, Time::Now() + TimeDelta::FromHours(1));
- SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP(
- get_sessions_sync_manager());
- histogram_tester.ExpectTotalCount("Sync.YoungestForeignTabAgeOnNTP", 0);
-}
-
-TEST_F(SyncSessionsMetricsTest, EmitNormalCase) {
- base::HistogramTester histogram_tester;
- PushTab(0, 0, Time::Now() - TimeDelta::FromHours(1));
- SyncSessionsMetrics::RecordYoungestForeignTabAgeOnNTP(
- get_sessions_sync_manager());
- histogram_tester.ExpectTotalCount("Sync.YoungestForeignTabAgeOnNTP", 1);
-}
-
-} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/synced_session.cc b/chromium/components/sync_sessions/synced_session.cc
index 0cba248c8f6..a096259f93e 100644
--- a/chromium/components/sync_sessions/synced_session.cc
+++ b/chromium/components/sync_sessions/synced_session.cc
@@ -23,7 +23,7 @@ sync_pb::SessionWindow SyncedSessionWindow::ToSessionWindowProto() const {
}
SyncedSession::SyncedSession()
- : session_tag("invalid"), device_type(TYPE_UNSET) {}
+ : session_tag("invalid"), device_type(sync_pb::SyncEnums::TYPE_UNSET) {}
SyncedSession::~SyncedSession() {}
@@ -34,31 +34,7 @@ sync_pb::SessionHeader SyncedSession::ToSessionHeaderProto() const {
w->CopyFrom(window_pair.second->ToSessionWindowProto());
}
header.set_client_name(session_name);
- switch (device_type) {
- case SyncedSession::TYPE_WIN:
- header.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_WIN);
- break;
- case SyncedSession::TYPE_MACOSX:
- header.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_MAC);
- break;
- case SyncedSession::TYPE_LINUX:
- header.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
- break;
- case SyncedSession::TYPE_CHROMEOS:
- header.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_CROS);
- break;
- case SyncedSession::TYPE_PHONE:
- header.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_PHONE);
- break;
- case SyncedSession::TYPE_TABLET:
- header.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_TABLET);
- break;
- case SyncedSession::TYPE_OTHER:
- // Intentionally fall-through
- default:
- header.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_OTHER);
- break;
- }
+ header.set_device_type(device_type);
return header;
}
diff --git a/chromium/components/sync_sessions/synced_session.h b/chromium/components/sync_sessions/synced_session.h
index c3471ae20d4..f6c37f41693 100644
--- a/chromium/components/sync_sessions/synced_session.h
+++ b/chromium/components/sync_sessions/synced_session.h
@@ -15,6 +15,7 @@
#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"
namespace sync_sessions {
@@ -40,19 +41,6 @@ struct SyncedSessionWindow {
// list of windows along with a unique session identifer (tag) and meta-data
// about the device being synced.
struct SyncedSession {
- // The type of device.
- // Please keep in sync with ForeignSessionHelper.java
- enum DeviceType {
- TYPE_UNSET = 0,
- TYPE_WIN = 1,
- TYPE_MACOSX = 2,
- TYPE_LINUX = 3,
- TYPE_CHROMEOS = 4,
- TYPE_OTHER = 5,
- TYPE_PHONE = 6,
- TYPE_TABLET = 7
- };
-
SyncedSession();
~SyncedSession();
@@ -62,7 +50,7 @@ struct SyncedSession {
std::string session_name;
// Type of device this session is from.
- DeviceType device_type;
+ sync_pb::SyncEnums::DeviceType device_type;
// Last time this session was modified remotely. This is the max of the header
// and all children tab mtimes.
@@ -82,30 +70,6 @@ struct SyncedSession {
// SyncedSessionTracker::GetTabImpl for a concrete example of id reuse.
std::set<int> tab_node_ids;
- // Converts the DeviceType enum value to a string. This is used
- // in the NTP handler for foreign sessions for matching session
- // types to an icon style.
- std::string DeviceTypeAsString() const {
- switch (device_type) {
- case SyncedSession::TYPE_WIN:
- return "win";
- case SyncedSession::TYPE_MACOSX:
- return "macosx";
- case SyncedSession::TYPE_LINUX:
- return "linux";
- case SyncedSession::TYPE_CHROMEOS:
- return "chromeos";
- case SyncedSession::TYPE_OTHER:
- return "other";
- case SyncedSession::TYPE_PHONE:
- return "phone";
- case SyncedSession::TYPE_TABLET:
- return "tablet";
- default:
- return std::string();
- }
- }
-
// Convert this object to its protocol buffer equivalent. Shallow conversion,
// does not create SessionTab protobufs.
sync_pb::SessionHeader ToSessionHeaderProto() const;
diff --git a/chromium/components/sync_sessions/synced_session_tracker.cc b/chromium/components/sync_sessions/synced_session_tracker.cc
index 2a6960c7500..6d9566eb35f 100644
--- a/chromium/components/sync_sessions/synced_session_tracker.cc
+++ b/chromium/components/sync_sessions/synced_session_tracker.cc
@@ -4,12 +4,15 @@
#include "components/sync_sessions/synced_session_tracker.h"
+#include <algorithm>
#include <utility>
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/sync/protocol/session_specifics.pb.h"
#include "components/sync_sessions/sync_sessions_client.h"
#include "components/sync_sessions/synced_tab_delegate.h"
+
namespace sync_sessions {
namespace {
@@ -42,6 +45,84 @@ bool IsPresentable(SyncSessionsClient* sessions_client,
return false;
}
+// Verify that tab IDs appear only once within a session. Intended to prevent
+// http://crbug.com/360822.
+bool IsValidSessionHeader(const sync_pb::SessionHeader& header) {
+ std::set<int> session_tab_ids;
+ for (int i = 0; i < header.window_size(); ++i) {
+ const sync_pb::SessionWindow& window = header.window(i);
+ for (int j = 0; j < window.tab_size(); ++j) {
+ const int tab_id = window.tab(j);
+ bool success = session_tab_ids.insert(tab_id).second;
+ if (!success)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void PopulateSyncedSessionWindowFromSpecifics(
+ const std::string& session_tag,
+ const sync_pb::SessionWindow& specifics,
+ base::Time mtime,
+ SyncedSessionWindow* synced_session_window,
+ SyncedSessionTracker* tracker) {
+ sessions::SessionWindow* session_window =
+ &synced_session_window->wrapped_window;
+ if (specifics.has_window_id())
+ session_window->window_id.set_id(specifics.window_id());
+ if (specifics.has_selected_tab_index())
+ session_window->selected_tab_index = specifics.selected_tab_index();
+ synced_session_window->window_type = specifics.browser_type();
+ if (specifics.has_browser_type()) {
+ if (specifics.browser_type() ==
+ sync_pb::SessionWindow_BrowserType_TYPE_TABBED) {
+ session_window->type = sessions::SessionWindow::TYPE_TABBED;
+ } else {
+ // Note: custom tabs are treated like popup windows on restore, as you can
+ // restore a custom tab on a platform that doesn't support them.
+ session_window->type = sessions::SessionWindow::TYPE_POPUP;
+ }
+ }
+ session_window->timestamp = mtime;
+ session_window->tabs.clear();
+ for (int i = 0; i < specifics.tab_size(); i++) {
+ SessionID::id_type tab_id = specifics.tab(i);
+ tracker->PutTabInWindow(session_tag, session_window->window_id.id(),
+ tab_id);
+ }
+}
+
+void PopulateSyncedSessionFromSpecifics(
+ const std::string& session_tag,
+ const sync_pb::SessionHeader& header_specifics,
+ base::Time mtime,
+ SyncedSession* synced_session,
+ SyncedSessionTracker* tracker) {
+ if (header_specifics.has_client_name())
+ synced_session->session_name = header_specifics.client_name();
+ if (header_specifics.has_device_type()) {
+ synced_session->device_type = header_specifics.device_type();
+ }
+ synced_session->modified_time =
+ std::max(mtime, synced_session->modified_time);
+
+ // Process all the windows and their tab information.
+ int num_windows = header_specifics.window_size();
+ DVLOG(1) << "Populating " << session_tag << " with " << num_windows
+ << " windows.";
+
+ for (int i = 0; i < num_windows; ++i) {
+ const sync_pb::SessionWindow& window_s = header_specifics.window(i);
+ SessionID::id_type window_id = window_s.window_id();
+ tracker->PutWindowInSession(session_tag, window_id);
+ PopulateSyncedSessionWindowFromSpecifics(
+ session_tag, window_s, synced_session->modified_time,
+ synced_session->windows[window_id].get(), tracker);
+ }
+}
+
} // namespace
SyncedSessionTracker::SyncedSessionTracker(SyncSessionsClient* sessions_client)
@@ -140,8 +221,7 @@ SyncedSession* SyncedSessionTracker::GetSession(
if (synced_session_map_.find(session_tag) != synced_session_map_.end())
return synced_session_map_[session_tag].get();
- std::unique_ptr<SyncedSession> synced_session =
- std::make_unique<SyncedSession>();
+ auto synced_session = std::make_unique<SyncedSession>();
DVLOG(1) << "Creating new session with tag " << session_tag << " at "
<< synced_session.get();
synced_session->session_tag = session_tag;
@@ -161,7 +241,8 @@ bool SyncedSessionTracker::DeleteForeignSession(
if (iter != synced_session_map_.end()) {
// An implicitly created session that has children tabs but no header node
// will have never had the device_type changed from unset.
- header_existed = iter->second->device_type != SyncedSession::TYPE_UNSET;
+ header_existed =
+ iter->second->device_type != sync_pb::SyncEnums::TYPE_UNSET;
// SyncedSession's destructor will trigger deletion of windows which will in
// turn trigger the deletion of tabs. This doesn't affect the convenience
// maps.
@@ -335,8 +416,7 @@ sessions::SessionTab* SyncedSessionTracker::GetTab(
<< "'s seen tab " << tab_id << " at " << tab_ptr << " " << title;
}
} else {
- std::unique_ptr<sessions::SessionTab> tab =
- std::make_unique<sessions::SessionTab>();
+ auto tab = std::make_unique<sessions::SessionTab>();
tab_ptr = tab.get();
tab->tab_id.set_id(tab_id);
synced_tab_map_[session_tag][tab_id] = tab_ptr;
@@ -493,4 +573,84 @@ void SyncedSessionTracker::Clear() {
local_session_tag_.clear();
}
+void UpdateTrackerWithSpecifics(const sync_pb::SessionSpecifics& specifics,
+ base::Time modification_time,
+ SyncedSessionTracker* tracker) {
+ std::string session_tag = specifics.session_tag();
+ SyncedSession* session = tracker->GetSession(session_tag);
+ if (specifics.has_header()) {
+ // Read in the header data for this session. Header data is
+ // essentially a collection of windows, each of which has an ordered id list
+ // for their tabs.
+
+ if (!IsValidSessionHeader(specifics.header())) {
+ LOG(WARNING) << "Ignoring session node with invalid header "
+ << "and tag " << session_tag << ".";
+ return;
+ }
+
+ // Load (or create) the SyncedSession object for this client.
+ const sync_pb::SessionHeader& header = specifics.header();
+
+ // Reset the tab/window tracking for this session (must do this before
+ // we start calling PutWindowInSession and PutTabInWindow so that all
+ // unused tabs/windows get cleared by the CleanupSession(...) call).
+ tracker->ResetSessionTracking(session_tag);
+
+ PopulateSyncedSessionFromSpecifics(session_tag, header, modification_time,
+ session, tracker);
+
+ // Delete any closed windows and unused tabs as necessary.
+ tracker->CleanupSession(session_tag);
+ } else if (specifics.has_tab()) {
+ const sync_pb::SessionTab& tab_s = specifics.tab();
+ SessionID::id_type tab_id = tab_s.tab_id();
+ DVLOG(1) << "Populating " << session_tag << "'s tab id " << tab_id
+ << " from node " << specifics.tab_node_id();
+
+ // Ensure the tracker is aware of the tab node id. Deleting foreign sessions
+ // requires deleting all relevant tab nodes, and it's easier to track the
+ // tab node ids themselves separately from the tab ids.
+ //
+ // Note that TabIDs are not stable across restarts of a client. Consider
+ // this example with two tabs:
+ //
+ // http://a.com TabID1 --> NodeIDA
+ // http://b.com TabID2 --> NodeIDB
+ //
+ // After restart, tab ids are reallocated. e.g, one possibility:
+ // http://a.com TabID2 --> NodeIDA
+ // http://b.com TabID1 --> NodeIDB
+ //
+ // If that happened on a remote client, here we will see an update to
+ // TabID1 with tab_node_id changing from NodeIDA to NodeIDB, and TabID2
+ // with tab_node_id changing from NodeIDB to NodeIDA.
+ //
+ // We can also wind up here if we created this tab as an out-of-order
+ // update to the header node for this session before actually associating
+ // the tab itself, so the tab node id wasn't available at the time and
+ // is currently kInvalidTabNodeID.
+ //
+ // In both cases, we can safely throw it into the set of node ids.
+ tracker->OnTabNodeSeen(session_tag, specifics.tab_node_id());
+ sessions::SessionTab* tab = tracker->GetTab(session_tag, tab_id);
+ if (!tab->timestamp.is_null() && tab->timestamp > modification_time) {
+ DVLOG(1) << "Ignoring " << session_tag << "'s session tab " << tab_id
+ << " with earlier modification time: " << tab->timestamp
+ << " vs " << modification_time;
+ return;
+ }
+
+ // Update SessionTab based on protobuf.
+ tab->SetFromSyncData(tab_s, modification_time);
+
+ // Update the last modified time.
+ if (session->modified_time < modification_time)
+ session->modified_time = modification_time;
+ } else {
+ LOG(WARNING) << "Ignoring session node with missing header/tab "
+ << "fields and tag " << session_tag << ".";
+ }
+}
+
} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/synced_session_tracker.h b/chromium/components/sync_sessions/synced_session_tracker.h
index a8c9480f48f..8510dfbeafd 100644
--- a/chromium/components/sync_sessions/synced_session_tracker.h
+++ b/chromium/components/sync_sessions/synced_session_tracker.h
@@ -19,6 +19,10 @@
#include "components/sync_sessions/synced_session.h"
#include "components/sync_sessions/tab_node_pool.h"
+namespace sync_pb {
+class SessionSpecifics;
+}
+
namespace sync_sessions {
class SyncSessionsClient;
@@ -255,6 +259,12 @@ class SyncedSessionTracker {
DISALLOW_COPY_AND_ASSIGN(SyncedSessionTracker);
};
+// Helper function to load and add window or tab data from synced specifics to
+// our internal tracking in SyncedSessionTracker.
+void UpdateTrackerWithSpecifics(const sync_pb::SessionSpecifics& specifics,
+ base::Time modification_time,
+ SyncedSessionTracker* tracker);
+
} // namespace sync_sessions
#endif // COMPONENTS_SYNC_SESSIONS_SYNCED_SESSION_TRACKER_H_
diff --git a/chromium/components/sync_sessions/synced_session_tracker_unittest.cc b/chromium/components/sync_sessions/synced_session_tracker_unittest.cc
index 88cdf646fa2..60102cbf8ba 100644
--- a/chromium/components/sync_sessions/synced_session_tracker_unittest.cc
+++ b/chromium/components/sync_sessions/synced_session_tracker_unittest.cc
@@ -8,7 +8,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "components/sessions/core/serialized_navigation_entry_test_helper.h"
-#include "components/sync_sessions/fake_sync_sessions_client.h"
+#include "components/sync_sessions/mock_sync_sessions_client.h"
#include "components/sync_sessions/synced_tab_delegate.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -21,7 +21,6 @@ namespace sync_sessions {
namespace {
const char kValidUrl[] = "http://www.example.com";
-const char kInvalidUrl[] = "invalid.url";
const char kTag[] = "tag";
const char kTag2[] = "tag2";
const char kTag3[] = "tag3";
@@ -101,8 +100,10 @@ class SyncedSessionTrackerTest : public testing::Test {
<< unmapped_tab_count;
}
+ MockSyncSessionsClient* GetSyncSessionsClient() { return &sessions_client_; }
+
private:
- FakeSyncSessionsClient sessions_client_;
+ testing::NiceMock<MockSyncSessionsClient> sessions_client_;
SyncedSessionTracker tracker_;
};
@@ -144,6 +145,10 @@ TEST_F(SyncedSessionTrackerTest, PutTabInWindow) {
}
TEST_F(SyncedSessionTrackerTest, LookupAllForeignSessions) {
+ const char kInvalidUrl[] = "invalid.url";
+ ON_CALL(*GetSyncSessionsClient(), ShouldSyncURL(GURL(kInvalidUrl)))
+ .WillByDefault(testing::Return(false));
+
std::vector<const SyncedSession*> sessions;
ASSERT_FALSE(GetTracker()->LookupAllForeignSessions(
&sessions, SyncedSessionTracker::PRESENTABLE));
@@ -225,7 +230,7 @@ TEST_F(SyncedSessionTrackerTest, Complex) {
SyncedSession* session = GetTracker()->GetSession(kTag);
SyncedSession* session2 = GetTracker()->GetSession(kTag2);
SyncedSession* session3 = GetTracker()->GetSession(kTag3);
- session3->device_type = SyncedSession::TYPE_OTHER;
+ session3->device_type = sync_pb::SyncEnums_DeviceType_TYPE_LINUX;
ASSERT_EQ(3U, GetTracker()->num_synced_sessions());
ASSERT_TRUE(session);
diff --git a/chromium/components/sync_wifi/wifi_config_delegate_chromeos_unittest.cc b/chromium/components/sync_wifi/wifi_config_delegate_chromeos_unittest.cc
index 882a83934fa..8930aabd4db 100644
--- a/chromium/components/sync_wifi/wifi_config_delegate_chromeos_unittest.cc
+++ b/chromium/components/sync_wifi/wifi_config_delegate_chromeos_unittest.cc
@@ -10,7 +10,6 @@
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "chromeos/network/managed_network_configuration_handler.h"
#include "chromeos/network/network_handler_callbacks.h"
@@ -223,7 +222,7 @@ TEST_F(WifiConfigDelegateChromeOsTest,
if (!create_configuration_error_callback().is_null()) {
create_configuration_error_callback().Run(
"Config.CreateConfiguration Failed",
- base::MakeUnique<base::DictionaryValue>());
+ std::make_unique<base::DictionaryValue>());
}
}
diff --git a/chromium/components/sync_wifi/wifi_credential.cc b/chromium/components/sync_wifi/wifi_credential.cc
index bf6294a3f27..38da1cf21e8 100644
--- a/chromium/components/sync_wifi/wifi_credential.cc
+++ b/chromium/components/sync_wifi/wifi_credential.cc
@@ -4,6 +4,8 @@
#include "components/sync_wifi/wifi_credential.h"
+#include <memory>
+
#include "base/i18n/streaming_utf8_validator.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
@@ -49,10 +51,10 @@ std::unique_ptr<base::DictionaryValue> WifiCredential::ToOncProperties() const {
if (!WifiSecurityClassToOncSecurityString(security_class(), &onc_security)) {
NOTREACHED() << "Failed to convert SecurityClass with value "
<< security_class();
- return base::MakeUnique<base::DictionaryValue>();
+ return std::make_unique<base::DictionaryValue>();
}
- auto onc_properties = base::MakeUnique<base::DictionaryValue>();
+ auto onc_properties = std::make_unique<base::DictionaryValue>();
onc_properties->SetString(onc::toplevel_config::kType,
onc::network_type::kWiFi);
// TODO(quiche): Switch to the HexSSID property, once ONC fully supports it.
diff --git a/chromium/components/sync_wifi/wifi_credential_syncable_service_factory.cc b/chromium/components/sync_wifi/wifi_credential_syncable_service_factory.cc
index 607e4b8bfd2..27417393b62 100644
--- a/chromium/components/sync_wifi/wifi_credential_syncable_service_factory.cc
+++ b/chromium/components/sync_wifi/wifi_credential_syncable_service_factory.cc
@@ -4,10 +4,10 @@
#include "components/sync_wifi/wifi_credential_syncable_service_factory.h"
+#include <memory>
#include <string>
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/sync_wifi/wifi_config_delegate.h"
@@ -94,7 +94,7 @@ WifiCredentialSyncableServiceFactory::BuildWifiConfigDelegateChromeOs(
// ChromeBrowserMainPartsChromeos, and destroyed after all
// KeyedService instances are destroyed.
chromeos::NetworkHandler* network_handler = chromeos::NetworkHandler::Get();
- return base::MakeUnique<WifiConfigDelegateChromeOs>(
+ return std::make_unique<WifiConfigDelegateChromeOs>(
GetUserHash(context, !ignore_login_state_for_test_),
network_handler->managed_network_configuration_handler());
}
diff --git a/chromium/components/sync_wifi/wifi_credential_syncable_service_unittest.cc b/chromium/components/sync_wifi/wifi_credential_syncable_service_unittest.cc
index 31a4f3475d9..f3b717614e4 100644
--- a/chromium/components/sync_wifi/wifi_credential_syncable_service_unittest.cc
+++ b/chromium/components/sync_wifi/wifi_credential_syncable_service_unittest.cc
@@ -14,8 +14,6 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/time/time.h"
-#include "components/sync/model/attachments/attachment_id.h"
-#include "components/sync/model/attachments/attachment_service_proxy_for_test.h"
#include "components/sync/model/fake_sync_change_processor.h"
#include "components/sync/model/sync_change.h"
#include "components/sync/model/sync_data.h"
@@ -135,8 +133,7 @@ class WifiCredentialSyncableServiceTest : public testing::Test {
syncer::SyncData::CreateRemoteData(
sync_item_id,
MakeWifiCredentialSpecifics(ssid, security_class, passphrase),
- base::Time(), syncer::AttachmentIdList(),
- syncer::AttachmentServiceProxyForTest::Create()));
+ base::Time()));
}
void StartSyncing() {
@@ -145,7 +142,7 @@ class WifiCredentialSyncableServiceTest : public testing::Test {
change_processor_ = change_processor.get();
syncable_service_->MergeDataAndStartSyncing(
syncer::WIFI_CREDENTIALS, syncer::SyncDataList(),
- std::move(change_processor), base::MakeUnique<SyncErrorFactoryMock>());
+ std::move(change_processor), std::make_unique<SyncErrorFactoryMock>());
}
private:
diff --git a/chromium/components/task_scheduler_util/browser/BUILD.gn b/chromium/components/task_scheduler_util/browser/BUILD.gn
deleted file mode 100644
index 502d832e378..00000000000
--- a/chromium/components/task_scheduler_util/browser/BUILD.gn
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-static_library("browser") {
- sources = [
- "initialization.cc",
- "initialization.h",
- ]
-
- deps = [
- "//base",
- "//base:base_static",
- "//components/task_scheduler_util/common",
- "//components/variations",
- ]
-}
diff --git a/chromium/components/task_scheduler_util/browser/DEPS b/chromium/components/task_scheduler_util/browser/DEPS
deleted file mode 100644
index 80f6f908e13..00000000000
--- a/chromium/components/task_scheduler_util/browser/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+components/variations",
-]
diff --git a/chromium/components/task_scheduler_util/browser/initialization.cc b/chromium/components/task_scheduler_util/browser/initialization.cc
deleted file mode 100644
index 89e98907dd2..00000000000
--- a/chromium/components/task_scheduler_util/browser/initialization.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/task_scheduler_util/browser/initialization.h"
-
-#include <map>
-#include <string>
-
-#include "build/build_config.h"
-#include "components/task_scheduler_util/common/variations_util.h"
-#include "components/variations/variations_associated_data.h"
-
-namespace task_scheduler_util {
-
-namespace {
-
-constexpr char kFieldTrialName[] = "BrowserScheduler";
-
-} // namespace
-
-std::unique_ptr<base::TaskScheduler::InitParams>
-GetBrowserTaskSchedulerInitParamsFromVariations() {
- std::map<std::string, std::string> variation_params;
- if (!::variations::GetVariationParams(kFieldTrialName, &variation_params))
- return nullptr;
-
- std::unique_ptr<base::TaskScheduler::InitParams> init_params =
- GetTaskSchedulerInitParams(
- "", variation_params, base::SchedulerBackwardCompatibility::DISABLED);
-#if defined(OS_WIN)
- if (init_params) {
- init_params->shared_worker_pool_environment =
- base::TaskScheduler::InitParams::SharedWorkerPoolEnvironment::COM_MTA;
- }
-#endif // defined(OS_WIN)
- return init_params;
-}
-
-} // namespace task_scheduler_util
diff --git a/chromium/components/task_scheduler_util/browser/initialization.h b/chromium/components/task_scheduler_util/browser/initialization.h
deleted file mode 100644
index 102f6981567..00000000000
--- a/chromium/components/task_scheduler_util/browser/initialization.h
+++ /dev/null
@@ -1,21 +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_TASK_SCHEDULER_UTIL_BROWSER_INITIALIZATION_H_
-#define COMPONENTS_TASK_SCHEDULER_UTIL_BROWSER_INITIALIZATION_H_
-
-#include <memory>
-
-#include "base/task_scheduler/task_scheduler.h"
-
-namespace task_scheduler_util {
-
-// Gets a TaskScheduler::InitParams object to initialize TaskScheduler in the
-// browser based off variations. Returns nullptr on failure.
-std::unique_ptr<base::TaskScheduler::InitParams>
-GetBrowserTaskSchedulerInitParamsFromVariations();
-
-} // namespace task_scheduler_util
-
-#endif // COMPONENTS_TASK_SCHEDULER_UTIL_BROWSER_INITIALIZATION_H_
diff --git a/chromium/components/task_scheduler_util/common/BUILD.gn b/chromium/components/task_scheduler_util/common/BUILD.gn
index 94bbb32322b..ee178bf8a3b 100644
--- a/chromium/components/task_scheduler_util/common/BUILD.gn
+++ b/chromium/components/task_scheduler_util/common/BUILD.gn
@@ -10,7 +10,6 @@ static_library("common") {
deps = [
"//base",
- "//components/variations",
]
}
@@ -22,7 +21,7 @@ source_set("unit_tests") {
deps = [
":common",
"//base",
- "//components/variations",
+ "//components/variations:test_support",
"//testing/gtest",
]
}
diff --git a/chromium/components/task_scheduler_util/common/DEPS b/chromium/components/task_scheduler_util/common/DEPS
index 80f6f908e13..be216e98a5e 100644
--- a/chromium/components/task_scheduler_util/common/DEPS
+++ b/chromium/components/task_scheduler_util/common/DEPS
@@ -1,3 +1,3 @@
include_rules = [
- "+components/variations",
+ "+components/variations/variations_params_manager.h",
]
diff --git a/chromium/components/task_scheduler_util/common/variations_util.cc b/chromium/components/task_scheduler_util/common/variations_util.cc
index eaef402bdb6..21e86db6434 100644
--- a/chromium/components/task_scheduler_util/common/variations_util.cc
+++ b/chromium/components/task_scheduler_util/common/variations_util.cc
@@ -4,36 +4,25 @@
#include "components/task_scheduler_util/common/variations_util.h"
-#include "base/command_line.h"
+#include <map>
+#include <string>
+
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
+#include "base/metrics/field_trial_params.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 "base/task_scheduler/initialization_util.h"
#include "base/time/time.h"
-#include "components/variations/variations_associated_data.h"
namespace task_scheduler_util {
namespace {
-#if !defined(OS_IOS)
-constexpr char kTaskSchedulerVariationParamsSwitch[] =
- "task-scheduler-variation-params";
-
-constexpr char kSeparator[] = "|";
-
-bool ContainsSeparator(const std::string& str) {
- return str.find(kSeparator) != std::string::npos;
-}
-#endif // !defined(OS_IOS)
-
// Builds a SchedulerWorkerPoolParams from the pool descriptor in
-// |variation_params[variation_param_prefix + pool_name]| and
-// |backward_compatibility|. Returns an invalid SchedulerWorkerPoolParams on
-// failure.
+// |variation_params[variation_param_prefix + pool_name]|. Returns an invalid
+// SchedulerWorkerPoolParams on failure.
//
// The pool descriptor is a semi-colon separated value string with the following
// items:
@@ -46,9 +35,7 @@ bool ContainsSeparator(const std::string& str) {
std::unique_ptr<base::SchedulerWorkerPoolParams> GetWorkerPoolParams(
base::StringPiece variation_param_prefix,
base::StringPiece pool_name,
- const std::map<std::string, std::string>& variation_params,
- base::SchedulerBackwardCompatibility backward_compatibility =
- base::SchedulerBackwardCompatibility::DISABLED) {
+ const std::map<std::string, std::string>& variation_params) {
auto pool_descriptor_it =
variation_params.find(base::StrCat({variation_param_prefix, pool_name}));
if (pool_descriptor_it == variation_params.end())
@@ -76,11 +63,10 @@ std::unique_ptr<base::SchedulerWorkerPoolParams> GetWorkerPoolParams(
return nullptr;
}
- auto params = base::MakeUnique<base::SchedulerWorkerPoolParams>(
+ auto params = std::make_unique<base::SchedulerWorkerPoolParams>(
base::RecommendedMaxNumberOfThreadsInPool(min, max, cores_multiplier,
offset),
- base::TimeDelta::FromMilliseconds(detach_milliseconds),
- backward_compatibility);
+ base::TimeDelta::FromMilliseconds(detach_milliseconds));
if (params->max_threads() <= 0) {
DLOG(ERROR) << "Invalid max threads in the Worker Pool Descriptor: "
@@ -101,10 +87,11 @@ std::unique_ptr<base::SchedulerWorkerPoolParams> GetWorkerPoolParams(
} // namespace
std::unique_ptr<base::TaskScheduler::InitParams> GetTaskSchedulerInitParams(
- base::StringPiece variation_param_prefix,
- const std::map<std::string, std::string>& variation_params,
- base::SchedulerBackwardCompatibility
- foreground_blocking_backward_compatibility) {
+ base::StringPiece variation_param_prefix) {
+ std::map<std::string, std::string> variation_params;
+ if (!base::GetFieldTrialParams("BrowserScheduler", &variation_params))
+ return nullptr;
+
const auto background_worker_pool_params = GetWorkerPoolParams(
variation_param_prefix, "Background", variation_params);
const auto background_blocking_worker_pool_params = GetWorkerPoolParams(
@@ -112,8 +99,7 @@ std::unique_ptr<base::TaskScheduler::InitParams> GetTaskSchedulerInitParams(
const auto foreground_worker_pool_params = GetWorkerPoolParams(
variation_param_prefix, "Foreground", variation_params);
const auto foreground_blocking_worker_pool_params = GetWorkerPoolParams(
- variation_param_prefix, "ForegroundBlocking", variation_params,
- foreground_blocking_backward_compatibility);
+ variation_param_prefix, "ForegroundBlocking", variation_params);
if (!background_worker_pool_params ||
!background_blocking_worker_pool_params ||
@@ -122,62 +108,23 @@ std::unique_ptr<base::TaskScheduler::InitParams> GetTaskSchedulerInitParams(
return nullptr;
}
- return base::MakeUnique<base::TaskScheduler::InitParams>(
+ return std::make_unique<base::TaskScheduler::InitParams>(
*background_worker_pool_params, *background_blocking_worker_pool_params,
*foreground_worker_pool_params, *foreground_blocking_worker_pool_params);
}
-#if !defined(OS_IOS)
-void AddVariationParamsToCommandLine(base::StringPiece key_prefix,
- base::CommandLine* command_line) {
- DCHECK(command_line);
-
- std::map<std::string, std::string> variation_params;
- if (!variations::GetVariationParams("BrowserScheduler", &variation_params))
- return;
-
- std::vector<base::StringPiece> parts;
- for (const auto& key_value : variation_params) {
- if (base::StartsWith(key_value.first, key_prefix,
- base::CompareCase::SENSITIVE)) {
- if (ContainsSeparator(key_value.first) ||
- ContainsSeparator(key_value.second)) {
- DLOG(ERROR)
- << "Unexpected Character in Task Scheduler Variation Params: "
- << key_value.first << " [" << key_value.second << "]";
- return;
- }
- parts.push_back(key_value.first);
- parts.push_back(key_value.second);
- }
- }
-
- if (!parts.empty()) {
- command_line->AppendSwitchASCII(kTaskSchedulerVariationParamsSwitch,
- base::JoinString(parts, kSeparator));
- }
+std::unique_ptr<base::TaskScheduler::InitParams>
+GetTaskSchedulerInitParamsForBrowser() {
+ // Variations params for the browser processes have no prefix.
+ constexpr char kVariationParamPrefix[] = "";
+ return GetTaskSchedulerInitParams(kVariationParamPrefix);
}
-std::map<std::string, std::string> GetVariationParamsFromCommandLine(
- const base::CommandLine& command_line) {
- const auto serialized_variation_params =
- command_line.GetSwitchValueASCII(kTaskSchedulerVariationParamsSwitch);
- const auto parts =
- base::SplitStringPiece(serialized_variation_params, kSeparator,
- base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- std::map<std::string, std::string> variation_params;
- for (auto it = parts.begin(); it != parts.end(); ++it) {
- base::StringPiece key = *it;
- ++it;
- if (it == parts.end()) {
- NOTREACHED();
- return std::map<std::string, std::string>();
- }
- base::StringPiece value = *it;
- variation_params[key.as_string()] = value.as_string();
- }
- return variation_params;
+std::unique_ptr<base::TaskScheduler::InitParams>
+GetTaskSchedulerInitParamsForRenderer() {
+ // Variations params for renderer processes are prefixed with "Renderer".
+ constexpr char kVariationParamPrefix[] = "Renderer";
+ return GetTaskSchedulerInitParams(kVariationParamPrefix);
}
-#endif // !defined(OS_IOS)
} // namespace task_scheduler_util
diff --git a/chromium/components/task_scheduler_util/common/variations_util.h b/chromium/components/task_scheduler_util/common/variations_util.h
index 3fd49ce7a76..991f23cd931 100644
--- a/chromium/components/task_scheduler_util/common/variations_util.h
+++ b/chromium/components/task_scheduler_util/common/variations_util.h
@@ -5,44 +5,31 @@
#ifndef COMPONENTS_TASK_SCHEDULER_UTIL_COMMON_VARIATIONS_UTIL_H_
#define COMPONENTS_TASK_SCHEDULER_UTIL_COMMON_VARIATIONS_UTIL_H_
-#include <map>
#include <memory>
-#include <string>
#include "base/strings/string_piece.h"
-#include "base/task_scheduler/scheduler_worker_params.h"
#include "base/task_scheduler/task_scheduler.h"
-#include "build/build_config.h"
-
-namespace base {
-class CommandLine;
-}
namespace task_scheduler_util {
-// Builds a TaskScheduler::InitParams from pool descriptors in
-// |variations_params| that are prefixed with |variation_param_prefix|.
-// |foreground_blocking_backward_compatibility| controls backward compatibility
-// in the foreground blocking pool. Returns nullptr on failure.
+// Builds a TaskScheduler::InitParams from variations params that are prefixed
+// with |variation_param_prefix| in the BrowserScheduler field trial. Returns
+// nullptr on failure.
+//
+// TODO(fdoray): Move this to the anonymous namespace in the .cc file.
+// https://crbug.com/810049
std::unique_ptr<base::TaskScheduler::InitParams> GetTaskSchedulerInitParams(
- base::StringPiece variation_param_prefix,
- const std::map<std::string, std::string>& variation_params,
- base::SchedulerBackwardCompatibility
- foreground_blocking_backward_compatibility =
- base::SchedulerBackwardCompatibility::DISABLED);
-
-#if !defined(OS_IOS)
-// Serializes variation params from the BrowserScheduler field trial whose key
-// start with |prefix| to the --task-scheduler-variation-params switch of
-// |command_line|.
-void AddVariationParamsToCommandLine(base::StringPiece key_prefix,
- base::CommandLine* command_line);
-
-// Returns a map of key-value pairs deserialized from the
-// --task-scheduler-variation-params switch of |command_line|.
-std::map<std::string, std::string> GetVariationParamsFromCommandLine(
- const base::CommandLine& command_line);
-#endif // !defined(OS_IOS)
+ base::StringPiece variation_param_prefix);
+
+// Builds a TaskScheduler::InitParams to use in the browser process from
+// variation params in the BrowserScheduler field trial.
+std::unique_ptr<base::TaskScheduler::InitParams>
+GetTaskSchedulerInitParamsForBrowser();
+
+// Builds a TaskScheduler::InitParams to use in renderer processes from
+// variation params in the BrowserScheduler field trial.
+std::unique_ptr<base::TaskScheduler::InitParams>
+GetTaskSchedulerInitParamsForRenderer();
} // namespace task_scheduler_util
diff --git a/chromium/components/task_scheduler_util/common/variations_util_unittest.cc b/chromium/components/task_scheduler_util/common/variations_util_unittest.cc
index 453c62e0d61..57b50a4ddc6 100644
--- a/chromium/components/task_scheduler_util/common/variations_util_unittest.cc
+++ b/chromium/components/task_scheduler_util/common/variations_util_unittest.cc
@@ -6,42 +6,30 @@
#include <map>
#include <string>
-#include <vector>
-#include "build/build_config.h"
-#include "base/command_line.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/task_scheduler/scheduler_worker_params.h"
#include "base/task_scheduler/scheduler_worker_pool_params.h"
-#include "components/variations/variations_associated_data.h"
+#include "components/variations/variations_params_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace task_scheduler_util {
namespace {
-using SchedulerBackwardCompatibility = base::SchedulerBackwardCompatibility;
-
-#if !defined(OS_IOS)
-constexpr char kFieldTrialName[] = "BrowserScheduler";
-constexpr char kFieldTrialTestGroup[] = "Test";
-constexpr char kTaskSchedulerVariationParamsSwitch[] =
- "task-scheduler-variation-params";
-#endif // !defined(OS_IOS)
-
class TaskSchedulerUtilVariationsUtilTest : public testing::Test {
- public:
- TaskSchedulerUtilVariationsUtilTest() : field_trial_list_(nullptr) {}
- ~TaskSchedulerUtilVariationsUtilTest() override {
- // Ensure that the maps are cleared between tests, since they are stored as
- // process singletons.
- variations::testing::ClearAllVariationIDs();
- variations::testing::ClearAllVariationParams();
+ protected:
+ TaskSchedulerUtilVariationsUtilTest() = default;
+
+ void SetVariationParams(
+ const std::map<std::string, std::string>& variation_params) {
+ variation_params_manager_.SetVariationParams("BrowserScheduler",
+ variation_params);
}
private:
- base::FieldTrialList field_trial_list_;
+ variations::testing::VariationParamsManager variation_params_manager_;
DISALLOW_COPY_AND_ASSIGN(TaskSchedulerUtilVariationsUtilTest);
};
@@ -54,10 +42,9 @@ TEST_F(TaskSchedulerUtilVariationsUtilTest, OrderingParams5) {
variation_params["RendererBackgroundBlocking"] = "2;2;1;0;52";
variation_params["RendererForeground"] = "4;4;1;0;62";
variation_params["RendererForegroundBlocking"] = "8;8;1;0;72";
+ SetVariationParams(variation_params);
- auto init_params = GetTaskSchedulerInitParams(
- "Renderer", variation_params,
- base::SchedulerBackwardCompatibility::INIT_COM_STA);
+ auto init_params = GetTaskSchedulerInitParams("Renderer");
ASSERT_TRUE(init_params);
EXPECT_EQ(1, init_params->background_worker_pool_params.max_threads());
@@ -90,14 +77,13 @@ TEST_F(TaskSchedulerUtilVariationsUtilTest, OrderingParams5) {
EXPECT_EQ(base::TimeDelta::FromMilliseconds(72),
init_params->foreground_blocking_worker_pool_params
.suggested_reclaim_time());
- EXPECT_EQ(base::SchedulerBackwardCompatibility::INIT_COM_STA,
+ EXPECT_EQ(base::SchedulerBackwardCompatibility::DISABLED,
init_params->foreground_blocking_worker_pool_params
.backward_compatibility());
}
TEST_F(TaskSchedulerUtilVariationsUtilTest, NoData) {
- EXPECT_FALSE(GetTaskSchedulerInitParams(
- "Renderer", std::map<std::string, std::string>()));
+ EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer"));
}
TEST_F(TaskSchedulerUtilVariationsUtilTest, IncompleteParameters) {
@@ -106,7 +92,8 @@ TEST_F(TaskSchedulerUtilVariationsUtilTest, IncompleteParameters) {
variation_params["RendererBackgroundBlocking"] = "2;2;1;0";
variation_params["RendererForeground"] = "4;4;1;0";
variation_params["RendererForegroundBlocking"] = "8;8;1;0";
- EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer", variation_params));
+ SetVariationParams(variation_params);
+ EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer"));
}
TEST_F(TaskSchedulerUtilVariationsUtilTest, InvalidParametersFormat) {
@@ -115,7 +102,8 @@ TEST_F(TaskSchedulerUtilVariationsUtilTest, InvalidParametersFormat) {
variation_params["RendererBackgroundBlocking"] = "a;b;c;d;e";
variation_params["RendererForeground"] = "a;b;c;d;e";
variation_params["RendererForegroundBlocking"] = "a;b;c;d;e";
- EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer", variation_params));
+ SetVariationParams(variation_params);
+ EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer"));
}
TEST_F(TaskSchedulerUtilVariationsUtilTest, ZeroMaxThreads) {
@@ -126,7 +114,8 @@ TEST_F(TaskSchedulerUtilVariationsUtilTest, ZeroMaxThreads) {
variation_params["RendererBackgroundBlocking"] = "2;2;1;0;52";
variation_params["RendererForeground"] = "4;4;1;0;62";
variation_params["RendererForegroundBlocking"] = "8;8;1;0;72";
- EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer", variation_params));
+ SetVariationParams(variation_params);
+ EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer"));
}
TEST_F(TaskSchedulerUtilVariationsUtilTest, NegativeMaxThreads) {
@@ -137,7 +126,8 @@ TEST_F(TaskSchedulerUtilVariationsUtilTest, NegativeMaxThreads) {
variation_params["RendererBackgroundBlocking"] = "2;2;1;0;52";
variation_params["RendererForeground"] = "4;4;1;0;62";
variation_params["RendererForegroundBlocking"] = "8;8;1;0;72";
- EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer", variation_params));
+ SetVariationParams(variation_params);
+ EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer"));
}
TEST_F(TaskSchedulerUtilVariationsUtilTest, NegativeSuggestedReclaimTime) {
@@ -148,79 +138,8 @@ TEST_F(TaskSchedulerUtilVariationsUtilTest, NegativeSuggestedReclaimTime) {
variation_params["RendererBackgroundBlocking"] = "2;2;1;0;52";
variation_params["RendererForeground"] = "4;4;1;0;62";
variation_params["RendererForegroundBlocking"] = "8;8;1;0;72";
- EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer", variation_params));
-}
-
-#if !defined(OS_IOS)
-// Verify that AddVariationParamsToCommandLine() serializes BrowserScheduler
-// variation params that start with the specified prefix to the command line and
-// that GetVariationParamsFromCommandLine() correctly deserializes them.
-TEST_F(TaskSchedulerUtilVariationsUtilTest, CommandLine) {
- std::map<std::string, std::string> in_variation_params;
- in_variation_params["PrefixFoo"] = "Foo";
- in_variation_params["PrefixBar"] = "Bar";
- in_variation_params["NoPrefix"] = "NoPrefix";
- ASSERT_TRUE(variations::AssociateVariationParams(
- kFieldTrialName, kFieldTrialTestGroup, in_variation_params));
- base::FieldTrialList::CreateFieldTrial(kFieldTrialName, kFieldTrialTestGroup);
-
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- AddVariationParamsToCommandLine("Prefix", &command_line);
- const std::map<std::string, std::string> out_variation_params =
- GetVariationParamsFromCommandLine(command_line);
-
- std::map<std::string, std::string> expected_out_variation_params;
- expected_out_variation_params["PrefixFoo"] = "Foo";
- expected_out_variation_params["PrefixBar"] = "Bar";
- EXPECT_EQ(expected_out_variation_params, out_variation_params);
-}
-
-// Verify that AddVariationParamsToCommandLine() doesn't add anything to the
-// command line when a BrowserScheduler variation param key contains |. A key
-// that contains | wouldn't be deserialized correctly by
-// GetVariationParamsFromCommandLine().
-TEST_F(TaskSchedulerUtilVariationsUtilTest,
- CommandLineSeparatorInVariationParamsKey) {
- std::map<std::string, std::string> in_variation_params;
- in_variation_params["PrefixFoo"] = "Foo";
- in_variation_params["PrefixKey|"] = "Value";
- ASSERT_TRUE(variations::AssociateVariationParams(
- kFieldTrialName, kFieldTrialTestGroup, in_variation_params));
- base::FieldTrialList::CreateFieldTrial(kFieldTrialName, kFieldTrialTestGroup);
-
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- AddVariationParamsToCommandLine("Prefix", &command_line);
- EXPECT_TRUE(
- command_line.GetSwitchValueASCII(kTaskSchedulerVariationParamsSwitch)
- .empty());
-}
-
-// Verify that AddVariationParamsToCommandLine() doesn't add anything to the
-// command line when a BrowserScheduler variation param value contains |. A
-// value that contains | wouldn't be deserialized correctly by
-// GetVariationParamsFromCommandLine().
-TEST_F(TaskSchedulerUtilVariationsUtilTest,
- CommandLineSeparatorInVariationParamsValue) {
- std::map<std::string, std::string> in_variation_params;
- in_variation_params["PrefixFoo"] = "Foo";
- in_variation_params["PrefixKey"] = "Value|";
- ASSERT_TRUE(variations::AssociateVariationParams(
- kFieldTrialName, kFieldTrialTestGroup, in_variation_params));
- base::FieldTrialList::CreateFieldTrial(kFieldTrialName, kFieldTrialTestGroup);
-
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- AddVariationParamsToCommandLine("Prefix", &command_line);
- EXPECT_TRUE(
- command_line.GetSwitchValueASCII(kTaskSchedulerVariationParamsSwitch)
- .empty());
-}
-
-// Verify that GetVariationParamsFromCommandLine() returns an empty map when the
-// command line doesn't have a --task-scheduler-variation-params switch.
-TEST_F(TaskSchedulerUtilVariationsUtilTest, CommandLineNoSwitch) {
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- EXPECT_TRUE(GetVariationParamsFromCommandLine(command_line).empty());
+ SetVariationParams(variation_params);
+ EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer"));
}
-#endif // !defined(OS_IOS)
} // namespace task_scheduler_util
diff --git a/chromium/components/task_scheduler_util/renderer/BUILD.gn b/chromium/components/task_scheduler_util/renderer/BUILD.gn
deleted file mode 100644
index 473fcd24bce..00000000000
--- a/chromium/components/task_scheduler_util/renderer/BUILD.gn
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-if (!is_ios) {
- static_library("renderer") {
- sources = [
- "initialization.cc",
- "initialization.h",
- ]
-
- deps = [
- "//base",
- "//components/task_scheduler_util/common",
- ]
- }
-}
diff --git a/chromium/components/task_scheduler_util/renderer/initialization.cc b/chromium/components/task_scheduler_util/renderer/initialization.cc
deleted file mode 100644
index 854bfe0d334..00000000000
--- a/chromium/components/task_scheduler_util/renderer/initialization.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/task_scheduler_util/renderer/initialization.h"
-
-#include "base/command_line.h"
-#include "components/task_scheduler_util/common/variations_util.h"
-
-namespace task_scheduler_util {
-
-std::unique_ptr<base::TaskScheduler::InitParams>
-GetRendererTaskSchedulerInitParamsFromCommandLine() {
- return GetTaskSchedulerInitParams(
- "Renderer", GetVariationParamsFromCommandLine(
- *base::CommandLine::ForCurrentProcess()));
-}
-
-} // namespace task_scheduler_util
diff --git a/chromium/components/task_scheduler_util/renderer/initialization.h b/chromium/components/task_scheduler_util/renderer/initialization.h
deleted file mode 100644
index 9199c6bb198..00000000000
--- a/chromium/components/task_scheduler_util/renderer/initialization.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_TASK_SCHEDULER_UTIL_RENDERER_INITIALIZATION_H_
-#define COMPONENTS_TASK_SCHEDULER_UTIL_RENDERER_INITIALIZATION_H_
-
-#include <memory>
-
-#include "base/task_scheduler/task_scheduler.h"
-
-namespace task_scheduler_util {
-
-// Gets a TaskScheduler::InitParams object to initialize TaskScheduler in a
-// renderer based off variations specified on the command line. Returns nullptr
-// on failure.
-std::unique_ptr<base::TaskScheduler::InitParams>
-GetRendererTaskSchedulerInitParamsFromCommandLine();
-
-} // namespace task_scheduler_util
-
-#endif // COMPONENTS_TASK_SCHEDULER_UTIL_RENDERER_INITIALIZATION_H_
diff --git a/chromium/components/timers/alarm_timer_chromeos.cc b/chromium/components/timers/alarm_timer_chromeos.cc
index da011e31813..17180385da4 100644
--- a/chromium/components/timers/alarm_timer_chromeos.cc
+++ b/chromium/components/timers/alarm_timer_chromeos.cc
@@ -8,13 +8,13 @@
#include <sys/timerfd.h>
#include <algorithm>
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/debug/task_annotator.h"
#include "base/files/file_util.h"
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/pending_task.h"
#include "base/trace_event/trace_event.h"
@@ -72,7 +72,7 @@ void AlarmTimer::Reset() {
// Set up the pending task.
base::Timer::set_desired_run_time(
delay.is_zero() ? base::TimeTicks() : base::TimeTicks::Now() + delay);
- pending_task_ = base::MakeUnique<base::PendingTask>(
+ pending_task_ = std::make_unique<base::PendingTask>(
base::Timer::posted_from(), base::Timer::user_task(),
base::Timer::desired_run_time());
diff --git a/chromium/components/timers/alarm_timer_unittest.cc b/chromium/components/timers/alarm_timer_unittest.cc
index 78494add760..1a10edb5c0c 100644
--- a/chromium/components/timers/alarm_timer_unittest.cc
+++ b/chromium/components/timers/alarm_timer_unittest.cc
@@ -11,7 +11,6 @@
#include "base/files/file_descriptor_watcher_posix.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
@@ -253,9 +252,9 @@ TEST(AlarmTimerTest, MessageLoopShutdown) {
// if debug heap checking is enabled.
bool did_run = false;
{
- auto loop = base::MakeUnique<base::MessageLoopForIO>();
+ auto loop = std::make_unique<base::MessageLoopForIO>();
auto file_descriptor_watcher =
- base::MakeUnique<base::FileDescriptorWatcher>(loop.get());
+ std::make_unique<base::FileDescriptorWatcher>(loop.get());
OneShotAlarmTimerTester a(&did_run, kTenMilliseconds);
OneShotAlarmTimerTester b(&did_run, kTenMilliseconds);
OneShotAlarmTimerTester c(&did_run, kTenMilliseconds);
@@ -282,8 +281,7 @@ TEST(AlarmTimerTest, NonRepeatIsRunning) {
base::FileDescriptorWatcher file_descriptor_watcher(&loop);
timers::OneShotAlarmTimer timer;
EXPECT_FALSE(timer.IsRunning());
- timer.Start(FROM_HERE, base::TimeDelta::FromDays(1),
- base::Bind(&base::DoNothing));
+ 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.
@@ -300,8 +298,7 @@ TEST(AlarmTimerTest, NonRepeatIsRunning) {
base::FileDescriptorWatcher file_descriptor_watcher(&loop);
timers::SimpleAlarmTimer timer;
EXPECT_FALSE(timer.IsRunning());
- timer.Start(FROM_HERE, base::TimeDelta::FromDays(1),
- base::Bind(&base::DoNothing));
+ 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.
@@ -322,8 +319,7 @@ TEST(AlarmTimerTest, RetainRepeatIsRunning) {
base::FileDescriptorWatcher file_descriptor_watcher(&loop);
timers::RepeatingAlarmTimer timer;
EXPECT_FALSE(timer.IsRunning());
- timer.Start(FROM_HERE, base::TimeDelta::FromDays(1),
- base::Bind(&base::DoNothing));
+ 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.
@@ -345,8 +341,7 @@ TEST(AlarmTimerTest, RetainNonRepeatIsRunning) {
base::FileDescriptorWatcher file_descriptor_watcher(&loop);
timers::SimpleAlarmTimer timer;
EXPECT_FALSE(timer.IsRunning());
- timer.Start(FROM_HERE, base::TimeDelta::FromDays(1),
- base::Bind(&base::DoNothing));
+ 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.
diff --git a/chromium/components/toolbar/BUILD.gn b/chromium/components/toolbar/BUILD.gn
index bbcadbd5250..ca4130785c6 100644
--- a/chromium/components/toolbar/BUILD.gn
+++ b/chromium/components/toolbar/BUILD.gn
@@ -46,7 +46,8 @@ static_library("vector_icons") {
static_library("toolbar") {
sources = [
- "features.h",
+ "toolbar_field_trial.cc",
+ "toolbar_field_trial.h",
"toolbar_model.h",
"toolbar_model_delegate.h",
"toolbar_model_impl.cc",
diff --git a/chromium/components/toolbar/test_toolbar_model.cc b/chromium/components/toolbar/test_toolbar_model.cc
index 59a81d9a9d4..a465092ec4f 100644
--- a/chromium/components/toolbar/test_toolbar_model.cc
+++ b/chromium/components/toolbar/test_toolbar_model.cc
@@ -18,7 +18,11 @@ TestToolbarModel::TestToolbarModel()
TestToolbarModel::~TestToolbarModel() {}
-base::string16 TestToolbarModel::GetFormattedURL(size_t* prefix_end) const {
+base::string16 TestToolbarModel::GetFormattedFullURL() const {
+ return text_;
+}
+
+base::string16 TestToolbarModel::GetURLForDisplay() const {
return text_;
}
diff --git a/chromium/components/toolbar/test_toolbar_model.h b/chromium/components/toolbar/test_toolbar_model.h
index 0484b074248..639332dd381 100644
--- a/chromium/components/toolbar/test_toolbar_model.h
+++ b/chromium/components/toolbar/test_toolbar_model.h
@@ -23,7 +23,8 @@ class TestToolbarModel : public ToolbarModel {
public:
TestToolbarModel();
~TestToolbarModel() override;
- base::string16 GetFormattedURL(size_t* prefix_end) const override;
+ base::string16 GetFormattedFullURL() const override;
+ base::string16 GetURLForDisplay() const override;
GURL GetURL() const override;
security_state::SecurityLevel GetSecurityLevel(
bool ignore_editing) const override;
diff --git a/chromium/components/toolbar/toolbar_field_trial.cc b/chromium/components/toolbar/toolbar_field_trial.cc
new file mode 100644
index 00000000000..3a2e1394f8c
--- /dev/null
+++ b/chromium/components/toolbar/toolbar_field_trial.cc
@@ -0,0 +1,21 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/toolbar/toolbar_field_trial.h"
+
+#include "base/feature_list.h"
+
+namespace toolbar {
+namespace features {
+
+// Features used for EV UI removal experiment (https://crbug.com/803501).
+const base::Feature kSimplifyHttpsIndicator{"SimplifyHttpsIndicator",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+const char kSimplifyHttpsIndicatorParameterName[] = "treatment";
+const char kSimplifyHttpsIndicatorParameterEvToSecure[] = "ev-to-secure";
+const char kSimplifyHttpsIndicatorParameterSecureToLock[] = "secure-to-lock";
+const char kSimplifyHttpsIndicatorParameterBothToLock[] = "both-to-lock";
+
+} // namespace features
+} // namespace toolbar
diff --git a/chromium/components/toolbar/toolbar_field_trial.h b/chromium/components/toolbar/toolbar_field_trial.h
new file mode 100644
index 00000000000..d7ac1971e2a
--- /dev/null
+++ b/chromium/components/toolbar/toolbar_field_trial.h
@@ -0,0 +1,32 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_TOOLBAR_TOOLBAR_FIELD_TRIAL_H_
+#define COMPONENTS_TOOLBAR_TOOLBAR_FIELD_TRIAL_H_
+
+#include "base/feature_list.h"
+
+namespace toolbar {
+namespace features {
+
+// This feature simplifies the security indiciator UI for https:// pages. The
+// exact UI treatment is dependent on the parameter 'treatment' which can have
+// the following value:
+// - 'ev-to-secure': Show the "Secure" chip for pages with an EV certificate.
+// - 'secure-to-lock': Show only the lock icon for non-EV https:// pages.
+// - 'both-to-lock': Show only the lock icon for all https:// pages.
+extern const base::Feature kSimplifyHttpsIndicator;
+
+// The parameter name which controls the UI treatment.
+extern const char kSimplifyHttpsIndicatorParameterName[];
+
+// The different parameter values, described above.
+extern const char kSimplifyHttpsIndicatorParameterEvToSecure[];
+extern const char kSimplifyHttpsIndicatorParameterSecureToLock[];
+extern const char kSimplifyHttpsIndicatorParameterBothToLock[];
+
+} // namespace features
+} // namespace toolbar
+
+#endif // COMPONENTS_TOOLBAR_TOOLBAR_FIELD_TRIAL_H_
diff --git a/chromium/components/toolbar/toolbar_model.h b/chromium/components/toolbar/toolbar_model.h
index 05648825ce8..299a910d57e 100644
--- a/chromium/components/toolbar/toolbar_model.h
+++ b/chromium/components/toolbar/toolbar_model.h
@@ -25,13 +25,18 @@ class ToolbarModel {
public:
virtual ~ToolbarModel() = default;
- // Returns a formatted URL for display in the toolbar. The formatting
- // includes:
+ // Returns the formatted full URL for the toolbar. The formatting includes:
// - Some characters may be unescaped.
// - The scheme and/or trailing slash may be dropped.
- // If |prefix_end| is non-NULL, it is set to the length of the pre-hostname
- // portion of the resulting URL.
- virtual base::string16 GetFormattedURL(size_t* prefix_end) const = 0;
+ // This method specifically keeps the URL suitable for editing by not
+ // applying any elisions that change the meaning of the URL.
+ virtual base::string16 GetFormattedFullURL() const = 0;
+
+ // Returns a simplified URL for display (but not editing) on the toolbar.
+ // This formatting is generally a superset of GetFormattedFullURL, and may
+ // include some destructive elisions that change the meaning of the URL.
+ // The returned string is not suitable for editing, and is for display only.
+ virtual base::string16 GetURLForDisplay() const = 0;
// Returns the URL of the current navigation entry.
virtual GURL GetURL() const = 0;
diff --git a/chromium/components/toolbar/toolbar_model_impl.cc b/chromium/components/toolbar/toolbar_model_impl.cc
index 1d42c347998..2d23c24defe 100644
--- a/chromium/components/toolbar/toolbar_model_impl.cc
+++ b/chromium/components/toolbar/toolbar_model_impl.cc
@@ -4,7 +4,9 @@
#include "components/toolbar/toolbar_model_impl.h"
+#include "base/feature_list.h"
#include "base/logging.h"
+#include "base/metrics/field_trial_params.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -12,6 +14,7 @@
#include "components/security_state/core/security_state.h"
#include "components/strings/grit/components_strings.h"
#include "components/toolbar/features.h"
+#include "components/toolbar/toolbar_field_trial.h"
#include "components/toolbar/toolbar_model_delegate.h"
#include "components/url_formatter/elide_url.h"
#include "components/url_formatter/url_formatter.h"
@@ -37,7 +40,7 @@ ToolbarModelImpl::~ToolbarModelImpl() {
}
// ToolbarModelImpl Implementation.
-base::string16 ToolbarModelImpl::GetFormattedURL(size_t* prefix_end) const {
+base::string16 ToolbarModelImpl::GetFormattedFullURL() const {
GURL url(GetURL());
// Note that we can't unescape spaces here, because if the user copies this
// and pastes it into another program, that program may think the URL ends at
@@ -46,18 +49,28 @@ base::string16 ToolbarModelImpl::GetFormattedURL(size_t* prefix_end) const {
delegate_->FormattedStringWithEquivalentMeaning(
url, url_formatter::FormatUrl(
url, url_formatter::kFormatUrlOmitDefaults,
- net::UnescapeRule::NORMAL, nullptr, prefix_end, nullptr));
- if (formatted_text.length() <= max_url_display_chars_)
- return formatted_text;
+ net::UnescapeRule::NORMAL, nullptr, nullptr, nullptr));
// Truncating the URL breaks editing and then pressing enter, but hopefully
// people won't try to do much with such enormous URLs anyway. If this becomes
// a real problem, we could perhaps try to keep some sort of different "elided
// visible URL" where editing affects and reloads the "real underlying URL",
// but this seems very tricky for little gain.
- return gfx::TruncateString(formatted_text, max_url_display_chars_ - 1,
- gfx::CHARACTER_BREAK) +
- gfx::kEllipsisUTF16;
+ return gfx::TruncateString(formatted_text, max_url_display_chars_,
+ gfx::CHARACTER_BREAK);
+}
+
+base::string16 ToolbarModelImpl::GetURLForDisplay() const {
+ url_formatter::FormatUrlTypes format_types =
+ url_formatter::kFormatUrlOmitDefaults |
+ url_formatter::kFormatUrlOmitHTTPS |
+ url_formatter::kFormatUrlOmitTrivialSubdomains;
+ base::string16 result = url_formatter::FormatUrl(GetURL(), format_types,
+ net::UnescapeRule::NORMAL,
+ nullptr, nullptr, nullptr);
+
+ return gfx::TruncateString(result, max_url_display_chars_,
+ gfx::CHARACTER_BREAK);
}
GURL ToolbarModelImpl::GetURL() const {
@@ -127,10 +140,33 @@ base::string16 ToolbarModelImpl::GetSecureVerboseText() const {
if (IsOfflinePage())
return l10n_util::GetStringUTF16(IDS_OFFLINE_VERBOSE_STATE);
+ // Security UI study (https://crbug.com/803501): Change EV/Secure text.
+ const std::string parameter =
+ base::FeatureList::IsEnabled(toolbar::features::kSimplifyHttpsIndicator)
+ ? base::GetFieldTrialParamValueByFeature(
+ toolbar::features::kSimplifyHttpsIndicator,
+ toolbar::features::kSimplifyHttpsIndicatorParameterName)
+ : std::string();
switch (GetSecurityLevel(false)) {
case security_state::HTTP_SHOW_WARNING:
return l10n_util::GetStringUTF16(IDS_NOT_SECURE_VERBOSE_STATE);
+ case security_state::EV_SECURE:
+ if (parameter ==
+ toolbar::features::kSimplifyHttpsIndicatorParameterEvToSecure) {
+ return l10n_util::GetStringUTF16(IDS_SECURE_VERBOSE_STATE);
+ }
+ if (parameter ==
+ toolbar::features::kSimplifyHttpsIndicatorParameterBothToLock) {
+ return base::string16();
+ }
+ return GetEVCertName();
case security_state::SECURE:
+ if (parameter ==
+ toolbar::features::kSimplifyHttpsIndicatorParameterSecureToLock ||
+ parameter ==
+ toolbar::features::kSimplifyHttpsIndicatorParameterBothToLock) {
+ return base::string16();
+ }
return l10n_util::GetStringUTF16(IDS_SECURE_VERBOSE_STATE);
case security_state::DANGEROUS:
return l10n_util::GetStringUTF16(delegate_->FailsMalwareCheck()
diff --git a/chromium/components/toolbar/toolbar_model_impl.h b/chromium/components/toolbar/toolbar_model_impl.h
index 6bbf45af108..2e2a74407af 100644
--- a/chromium/components/toolbar/toolbar_model_impl.h
+++ b/chromium/components/toolbar/toolbar_model_impl.h
@@ -28,7 +28,8 @@ class ToolbarModelImpl : public ToolbarModel {
private:
// ToolbarModel:
- base::string16 GetFormattedURL(size_t* prefix_end) const override;
+ base::string16 GetFormattedFullURL() const override;
+ base::string16 GetURLForDisplay() const override;
GURL GetURL() const override;
security_state::SecurityLevel GetSecurityLevel(
bool ignore_editing) const override;
diff --git a/chromium/components/toolbar/vector_icons/OWNERS b/chromium/components/toolbar/vector_icons/OWNERS
new file mode 100644
index 00000000000..d7ec991d34a
--- /dev/null
+++ b/chromium/components/toolbar/vector_icons/OWNERS
@@ -0,0 +1 @@
+file://components/vector_icons/OWNERS
diff --git a/chromium/components/toolbar/vector_icons/vector_icons.cc.template b/chromium/components/toolbar/vector_icons/vector_icons.cc.template
index 6120c7c84e5..dc4a46f02da 100644
--- a/chromium/components/toolbar/vector_icons/vector_icons.cc.template
+++ b/chromium/components/toolbar/vector_icons/vector_icons.cc.template
@@ -10,11 +10,7 @@
#include "base/logging.h"
#include "ui/gfx/vector_icon_types.h"
-#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
-static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
-
-#define VECTOR_ICON_TEMPLATE(icon_name, path_name, path_name_1x) \
-const gfx::VectorIcon icon_name = { path_name , path_name_1x };
+#include "components/vector_icons/cc_macros.h"
namespace toolbar {
diff --git a/chromium/components/tracing/common/trace_config_file.h b/chromium/components/tracing/common/trace_config_file.h
index 31adcef508c..fab9eeb1a23 100644
--- a/chromium/components/tracing/common/trace_config_file.h
+++ b/chromium/components/tracing/common/trace_config_file.h
@@ -65,6 +65,10 @@ namespace tracing {
// /data/local/chrome-trace-config.json
// If this file exists, Chrome will start tracing according to the configuration
// specified in the file, otherwise, Chrome will not start tracing.
+// In order for Chrome to read this file on Android M+, SE Linux mode must be
+// set to 0. Run "adb shell setenforce 0".
+// Note that on Android, the output path is ignored, and the result is emitted
+// to a location generated by TracingControllerAndroid::GenerateTracingFilePath.
class TRACING_EXPORT TraceConfigFile {
public:
static TraceConfigFile* GetInstance();
diff --git a/chromium/components/translate/content/common/BUILD.gn b/chromium/components/translate/content/common/BUILD.gn
index 7e782e1d0bb..b9b11ebe959 100644
--- a/chromium/components/translate/content/common/BUILD.gn
+++ b/chromium/components/translate/content/common/BUILD.gn
@@ -11,6 +11,6 @@ mojom("common") {
public_deps = [
"//mojo/common:common_custom_types",
- "//url/mojo:url_mojom_gurl",
+ "//url/mojom:url_mojom_gurl",
]
}
diff --git a/chromium/components/translate/content/common/translate.mojom b/chromium/components/translate/content/common/translate.mojom
index 9df5ce09fbb..0cfb34a3c53 100644
--- a/chromium/components/translate/content/common/translate.mojom
+++ b/chromium/components/translate/content/common/translate.mojom
@@ -5,7 +5,8 @@
module translate.mojom;
import "mojo/common/time.mojom";
-import "url/mojo/url.mojom";
+import "mojo/public/mojom/base/string16.mojom";
+import "url/mojom/url.mojom";
enum TranslateError {
NONE,
@@ -31,7 +32,7 @@ struct LanguageDetectionDetails {
bool has_notranslate;
string html_root_language;
string adopted_language;
- string contents;
+ mojo_base.mojom.String16 contents;
};
interface Page {
diff --git a/chromium/components/translate/core/browser/BUILD.gn b/chromium/components/translate/core/browser/BUILD.gn
index e1b185f46cc..d4a3cbe9b9c 100644
--- a/chromium/components/translate/core/browser/BUILD.gn
+++ b/chromium/components/translate/core/browser/BUILD.gn
@@ -50,6 +50,7 @@ static_library("browser") {
"//components/data_use_measurement/core",
"//components/keyed_service/core",
"//components/language/core/browser",
+ "//components/language/core/common",
"//components/language_usage_metrics",
"//components/metrics",
"//components/pref_registry",
diff --git a/chromium/components/translate/core/common/BUILD.gn b/chromium/components/translate/core/common/BUILD.gn
index 6e59b894d6d..94491e26e26 100644
--- a/chromium/components/translate/core/common/BUILD.gn
+++ b/chromium/components/translate/core/common/BUILD.gn
@@ -23,6 +23,7 @@ static_library("common") {
deps = [
"//base",
+ "//components/language/core/common",
"//components/sync/protocol",
"//third_party/metrics_proto",
"//url",
diff --git a/chromium/components/ui_devtools/devtools_server.cc b/chromium/components/ui_devtools/devtools_server.cc
index a901f937e98..fab9ade6c18 100644
--- a/chromium/components/ui_devtools/devtools_server.cc
+++ b/chromium/components/ui_devtools/devtools_server.cc
@@ -4,11 +4,12 @@
#include "components/ui_devtools/devtools_server.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/format_macros.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
@@ -44,6 +45,27 @@ int GetUiDevToolsPort() {
return port;
}
+constexpr net::NetworkTrafficAnnotationTag kUIDevtoolsServer =
+ net::DefineNetworkTrafficAnnotation("ui_devtools_server", R"(
+ semantics {
+ sender: "UI Devtools Server"
+ description:
+ "Backend for UI DevTools, to inspect Aura/Views UI."
+ trigger:
+ "Run with '--enable-ui-devtools' switch."
+ data: "Debugging data, including any data on the open pages."
+ destination: OTHER
+ destination_other: "The data can be sent to any destination."
+ }
+ policy {
+ cookies_allowed: NO
+ setting:
+ "This request cannot be disabled in settings. However it will never "
+ "be made if user does not run with '--enable-ui-devtools' switch."
+ policy_exception_justification:
+ "Not implemented, only used in Devtools and is behind a switch."
+ })");
+
} // namespace
UiDevToolsServer* UiDevToolsServer::devtools_server_ = nullptr;
@@ -108,9 +130,9 @@ void UiDevToolsServer::AttachClient(std::unique_ptr<UiDevToolsClient> client) {
void UiDevToolsServer::SendOverWebSocket(int connection_id,
const String& message) {
io_thread_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&net::HttpServer::SendOverWebSocket,
- base::Unretained(server_.get()), connection_id, message));
+ FROM_HERE, base::Bind(&net::HttpServer::SendOverWebSocket,
+ base::Unretained(server_.get()), connection_id,
+ message, kUIDevtoolsServer));
}
void UiDevToolsServer::Start(const std::string& address_string, uint16_t port) {
@@ -128,7 +150,7 @@ void UiDevToolsServer::StartServer(const std::string& address_string,
if (socket->ListenWithAddressAndPort(address_string, port, kBacklog) !=
net::OK)
return;
- server_ = base::MakeUnique<net::HttpServer>(std::move(socket), this);
+ server_ = std::make_unique<net::HttpServer>(std::move(socket), this);
}
// HttpServer::Delegate Implementation
@@ -157,9 +179,9 @@ void UiDevToolsServer::OnWebSocketRequest(
client->set_connection_id(connection_id);
connections_[connection_id] = client;
io_thread_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&net::HttpServer::AcceptWebSocket,
- base::Unretained(server_.get()), connection_id, info));
+ FROM_HERE, base::Bind(&net::HttpServer::AcceptWebSocket,
+ base::Unretained(server_.get()), connection_id,
+ info, kUIDevtoolsServer));
}
void UiDevToolsServer::OnWebSocketMessage(int connection_id,
diff --git a/chromium/components/ui_devtools/views/BUILD.gn b/chromium/components/ui_devtools/views/BUILD.gn
index ba256a9ddcc..2b0fc8e8148 100644
--- a/chromium/components/ui_devtools/views/BUILD.gn
+++ b/chromium/components/ui_devtools/views/BUILD.gn
@@ -17,6 +17,8 @@ source_set("views") {
"dom_agent.h",
"overlay_agent.cc",
"overlay_agent.h",
+ "root_element.cc",
+ "root_element.h",
"ui_element.cc",
"ui_element.h",
"ui_element_delegate.h",
diff --git a/chromium/components/ui_devtools/views/css_agent.cc b/chromium/components/ui_devtools/views/css_agent.cc
index 487324d7916..4bc0fbd6f17 100644
--- a/chromium/components/ui_devtools/views/css_agent.cc
+++ b/chromium/components/ui_devtools/views/css_agent.cc
@@ -70,10 +70,10 @@ std::unique_ptr<CSS::CSSStyle> BuildCSSStyle(UIElement* ui_element) {
std::unique_ptr<Array<CSS::CSSProperty>> css_properties(
BuildCSSPropertyArray(bounds, visible));
- const std::vector<std::pair<std::string, std::string>> attributes(
- ui_element->GetCustomAttributes());
+ const std::vector<std::pair<std::string, std::string>> properties(
+ ui_element->GetCustomProperties());
- for (const auto& it : attributes)
+ for (const auto& it : properties)
css_properties->addItem(BuildCSSProperty(it.first, it.second));
return CSS::CSSStyle::create()
diff --git a/chromium/components/ui_devtools/views/dom_agent.cc b/chromium/components/ui_devtools/views/dom_agent.cc
index 39fe80daf2b..e87d0d0685b 100644
--- a/chromium/components/ui_devtools/views/dom_agent.cc
+++ b/chromium/components/ui_devtools/views/dom_agent.cc
@@ -4,10 +4,12 @@
#include "components/ui_devtools/views/dom_agent.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "base/strings/utf_string_conversions.h"
#include "components/ui_devtools/devtools_server.h"
#include "components/ui_devtools/views/overlay_agent.h"
+#include "components/ui_devtools/views/root_element.h"
#include "components/ui_devtools/views/ui_element.h"
#include "components/ui_devtools/views/view_element.h"
#include "components/ui_devtools/views/widget_element.h"
@@ -53,41 +55,7 @@ std::unique_ptr<DOM::Node> BuildNode(
return node;
}
-// TODO(thanhph): Move this function to UIElement::GetAttributes().
-std::unique_ptr<Array<std::string>> GetAttributes(UIElement* ui_element) {
- std::unique_ptr<Array<std::string>> attributes = Array<std::string>::create();
- attributes->addItem("name");
- switch (ui_element->type()) {
- case UIElementType::WINDOW: {
- aura::Window* window =
- UIElement::GetBackingElement<aura::Window, WindowElement>(ui_element);
- attributes->addItem(window->GetName());
- attributes->addItem("active");
- attributes->addItem(::wm::IsActiveWindow(window) ? "true" : "false");
- break;
- }
- case UIElementType::WIDGET: {
- views::Widget* widget =
- UIElement::GetBackingElement<views::Widget, WidgetElement>(
- ui_element);
- attributes->addItem(widget->GetName());
- attributes->addItem("active");
- attributes->addItem(widget->IsActive() ? "true" : "false");
- break;
- }
- case UIElementType::VIEW: {
- attributes->addItem(
- UIElement::GetBackingElement<views::View, ViewElement>(ui_element)
- ->GetClassName());
- break;
- }
- default:
- DCHECK(false);
- }
- return attributes;
-}
-
-views::Widget* GetWidgetFromWindow(aura::Window* window) {
+views::Widget* GetWidgetFromWindow(gfx::NativeWindow window) {
return views::Widget::GetWidgetForNativeView(window);
}
@@ -96,7 +64,7 @@ std::unique_ptr<DOM::Node> BuildDomNodeFromUIElement(UIElement* root) {
for (auto* it : root->children())
children->addItem(BuildDomNodeFromUIElement(it));
- return BuildNode(root->GetTypeName(), GetAttributes(root),
+ return BuildNode(root->GetTypeName(), root->GetAttributes(),
std::move(children), root->node_id());
}
@@ -540,10 +508,10 @@ Response DOMAgent::HighlightNode(int node_id, bool show_size) {
layer_for_highlighting_->set_delegate(this);
layer_for_highlighting_->SetFillsBoundsOpaquely(false);
}
- std::pair<aura::Window*, gfx::Rect> window_and_bounds =
+ std::pair<gfx::NativeWindow, gfx::Rect> window_and_bounds =
node_id_to_ui_element_.count(node_id)
? node_id_to_ui_element_[node_id]->GetNodeWindowAndBounds()
- : std::make_pair<aura::Window*, gfx::Rect>(nullptr, gfx::Rect());
+ : std::make_pair<gfx::NativeWindow, gfx::Rect>(nullptr, gfx::Rect());
if (!window_and_bounds.first)
return Response::Error("No node found with that id");
@@ -558,36 +526,43 @@ Response DOMAgent::HighlightNode(int node_id, bool show_size) {
return Response::OK();
}
-int DOMAgent::FindElementIdTargetedByPoint(const gfx::Point& p,
- aura::Window* root_window) const {
- aura::Window* targeted_window = root_window->GetEventHandlerForPoint(p);
+int DOMAgent::FindElementIdTargetedByPoint(
+ const gfx::Point& p,
+ gfx::NativeWindow root_window) const {
+ gfx::NativeWindow targeted_window = root_window->GetEventHandlerForPoint(p);
if (!targeted_window)
return 0;
views::Widget* targeted_widget =
views::Widget::GetWidgetForNativeWindow(targeted_window);
if (!targeted_widget) {
- return window_element_root_->FindUIElementIdForBackendElement<aura::Window>(
+#if defined(USE_AURA)
+ return element_root_->FindUIElementIdForBackendElement<aura::Window>(
targeted_window);
+#else
+ return 0;
+#endif // defined(USE_AURA)
}
views::View* root_view = targeted_widget->GetRootView();
DCHECK(root_view);
gfx::Point point_in_targeted_window(p);
+#if defined(USE_AURA)
aura::Window::ConvertPointToTarget(root_window, targeted_window,
&point_in_targeted_window);
+#endif // defined(USE_AURA)
views::View* targeted_view =
root_view->GetEventHandlerForPoint(point_in_targeted_window);
DCHECK(targeted_view);
- return window_element_root_->FindUIElementIdForBackendElement<views::View>(
+ return element_root_->FindUIElementIdForBackendElement<views::View>(
targeted_view);
}
void DOMAgent::ShowDistancesInHighlightOverlay(int pinned_id, int element_id) {
- const std::pair<aura::Window*, gfx::Rect> pair_r2(
+ const std::pair<gfx::NativeWindow, gfx::Rect> pair_r2(
node_id_to_ui_element_[element_id]->GetNodeWindowAndBounds());
- const std::pair<aura::Window*, gfx::Rect> pair_r1(
+ const std::pair<gfx::NativeWindow, gfx::Rect> pair_r1(
node_id_to_ui_element_[pinned_id]->GetNodeWindowAndBounds());
gfx::Rect r2(pair_r2.second);
gfx::Rect r1(pair_r1.second);
@@ -633,7 +608,7 @@ void DOMAgent::ShowDistancesInHighlightOverlay(int pinned_id, int element_id) {
int DOMAgent::GetParentIdOfNodeId(int node_id) const {
DCHECK(node_id_to_ui_element_.count(node_id));
const UIElement* element = node_id_to_ui_element_.at(node_id);
- if (element->parent() && element->parent() != window_element_root_.get())
+ if (element->parent() && element->parent() != element_root_.get())
return element->parent()->node_id();
return 0;
}
@@ -790,20 +765,17 @@ std::unique_ptr<DOM::Node> DOMAgent::BuildInitialTree() {
is_building_tree_ = true;
std::unique_ptr<Array<DOM::Node>> children = Array<DOM::Node>::create();
- // TODO(thanhph): Root of UIElement tree shoudn't be WindowElement
- // but maybe a new different element type.
- window_element_root_ =
- base::MakeUnique<WindowElement>(nullptr, this, nullptr);
+ element_root_ = std::make_unique<RootElement>(this);
for (aura::Window* window : root_windows()) {
UIElement* window_element =
- new WindowElement(window, this, window_element_root_.get());
+ new WindowElement(window, this, element_root_.get());
children->addItem(BuildTreeForUIElement(window_element));
- window_element_root_->AddChild(window_element);
+ element_root_->AddChild(window_element);
}
- std::unique_ptr<DOM::Node> root_node = BuildNode(
- "root", nullptr, std::move(children), window_element_root_->node_id());
+ std::unique_ptr<DOM::Node> root_node =
+ BuildNode("root", nullptr, std::move(children), element_root_->node_id());
is_building_tree_ = false;
return root_node;
}
@@ -846,7 +818,7 @@ std::unique_ptr<DOM::Node> DOMAgent::BuildTreeForWindow(
window_element_root->AddChild(window_element);
}
std::unique_ptr<DOM::Node> node =
- BuildNode("Window", GetAttributes(window_element_root),
+ BuildNode("Window", window_element_root->GetAttributes(),
std::move(children), window_element_root->node_id());
return node;
}
@@ -863,7 +835,7 @@ std::unique_ptr<DOM::Node> DOMAgent::BuildTreeForRootWidget(
widget_element->AddChild(view_element);
std::unique_ptr<DOM::Node> node =
- BuildNode("Widget", GetAttributes(widget_element), std::move(children),
+ BuildNode("Widget", widget_element->GetAttributes(), std::move(children),
widget_element->node_id());
return node;
}
@@ -879,7 +851,7 @@ std::unique_ptr<DOM::Node> DOMAgent::BuildTreeForView(UIElement* view_element,
view_element->AddChild(view_element_child);
}
std::unique_ptr<DOM::Node> node =
- BuildNode("View", GetAttributes(view_element), std::move(children),
+ BuildNode("View", view_element->GetAttributes(), std::move(children),
view_element->node_id());
return node;
}
@@ -895,17 +867,17 @@ void DOMAgent::Reset() {
is_building_tree_ = false;
render_text_.reset();
layer_for_highlighting_.reset();
- window_element_root_.reset();
+ element_root_.reset();
node_id_to_ui_element_.clear();
observers_.Clear();
}
void DOMAgent::UpdateHighlight(
- const std::pair<aura::Window*, gfx::Rect>& window_and_bounds) {
+ const std::pair<gfx::NativeWindow, gfx::Rect>& window_and_bounds) {
display::Display display =
display::Screen::GetScreen()->GetDisplayNearestWindow(
window_and_bounds.first);
- aura::Window* root = window_and_bounds.first->GetRootWindow();
+ gfx::NativeWindow root = window_and_bounds.first->GetRootWindow();
layer_for_highlighting_->SetBounds(root->bounds());
layer_for_highlighting_->SchedulePaint(root->bounds());
diff --git a/chromium/components/ui_devtools/views/dom_agent.h b/chromium/components/ui_devtools/views/dom_agent.h
index 440f7b9d268..4906b04995c 100644
--- a/chromium/components/ui_devtools/views/dom_agent.h
+++ b/chromium/components/ui_devtools/views/dom_agent.h
@@ -10,6 +10,7 @@
#include "components/ui_devtools/views/ui_element_delegate.h"
#include "ui/aura/env_observer.h"
#include "ui/compositor/layer_delegate.h"
+#include "ui/gfx/native_widget_types.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
@@ -69,8 +70,8 @@ class DOMAgent : public UiDevToolsBaseAgent<protocol::DOM::Metainfo>,
void AddObserver(DOMAgentObserver* observer);
void RemoveObserver(DOMAgentObserver* observer);
UIElement* GetElementFromNodeId(int node_id);
- UIElement* window_element_root() const { return window_element_root_.get(); };
- const std::vector<aura::Window*>& root_windows() const {
+ UIElement* element_root() const { return element_root_.get(); };
+ const std::vector<gfx::NativeWindow>& root_windows() const {
return root_windows_;
};
HighlightRectsConfiguration highlight_rect_config() const {
@@ -84,7 +85,7 @@ class DOMAgent : public UiDevToolsBaseAgent<protocol::DOM::Metainfo>,
// exists), then the targeted view (if one exists). Return 0 if no valid
// target is found.
int FindElementIdTargetedByPoint(const gfx::Point& p,
- aura::Window* root_window) const;
+ gfx::NativeWindow root_window) const;
// Shows the distances between the nodes identified by |pinned_id| and
// |element_id| in the highlight overlay.
@@ -119,14 +120,14 @@ class DOMAgent : public UiDevToolsBaseAgent<protocol::DOM::Metainfo>,
void RemoveDomNode(UIElement* ui_element);
void Reset();
void UpdateHighlight(
- const std::pair<aura::Window*, gfx::Rect>& window_and_bounds);
+ const std::pair<gfx::NativeWindow, gfx::Rect>& window_and_bounds);
std::unique_ptr<gfx::RenderText> render_text_;
bool is_building_tree_;
bool show_size_on_canvas_ = false;
HighlightRectsConfiguration highlight_rect_config_;
bool is_swap_ = false;
- std::unique_ptr<UIElement> window_element_root_;
+ std::unique_ptr<UIElement> element_root_;
std::unordered_map<int, UIElement*> node_id_to_ui_element_;
// TODO(thanhph): |layer_for_highlighting_| should be owned by the overlay
diff --git a/chromium/components/ui_devtools/views/overlay_agent.cc b/chromium/components/ui_devtools/views/overlay_agent.cc
index 9057ef3effc..3cf4c8628ad 100644
--- a/chromium/components/ui_devtools/views/overlay_agent.cc
+++ b/chromium/components/ui_devtools/views/overlay_agent.cc
@@ -45,7 +45,7 @@ protocol::Response OverlayAgent::hideHighlight() {
void OverlayAgent::OnMouseEvent(ui::MouseEvent* event) {
// Make sure the element tree has been populated before processing
// mouse events.
- if (!dom_agent_->window_element_root())
+ if (!dom_agent_->element_root())
return;
// Show parent of the pinned element with id |pinned_id_| when mouse scrolls
@@ -92,7 +92,7 @@ void OverlayAgent::OnMouseEvent(ui::MouseEvent* event) {
}
void OverlayAgent::OnKeyEvent(ui::KeyEvent* event) {
- if (!dom_agent_->window_element_root())
+ if (!dom_agent_->element_root())
return;
// Exit inspect mode by pressing ESC key.
diff --git a/chromium/components/ui_devtools/views/root_element.cc b/chromium/components/ui_devtools/views/root_element.cc
new file mode 100644
index 00000000000..93824e94bbc
--- /dev/null
+++ b/chromium/components/ui_devtools/views/root_element.cc
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/ui_devtools/views/root_element.h"
+
+#include "components/ui_devtools/Protocol.h"
+#include "components/ui_devtools/views/ui_element_delegate.h"
+
+namespace ui_devtools {
+
+RootElement::RootElement(UIElementDelegate* ui_element_delegate)
+ : UIElement(UIElementType::ROOT, ui_element_delegate, nullptr) {}
+
+RootElement::~RootElement() {}
+
+std::vector<std::pair<std::string, std::string>>
+RootElement::GetCustomProperties() const {
+ NOTREACHED();
+ return {};
+}
+
+void RootElement::GetBounds(gfx::Rect* bounds) const {
+ NOTREACHED();
+}
+
+void RootElement::SetBounds(const gfx::Rect& bounds) {
+ NOTREACHED();
+}
+
+void RootElement::GetVisible(bool* visible) const {
+ NOTREACHED();
+}
+
+void RootElement::SetVisible(bool visible) {
+ NOTREACHED();
+}
+std::unique_ptr<protocol::Array<std::string>> RootElement::GetAttributes()
+ const {
+ NOTREACHED();
+ return nullptr;
+}
+
+std::pair<gfx::NativeWindow, gfx::Rect> RootElement::GetNodeWindowAndBounds()
+ const {
+ NOTREACHED();
+ return {};
+}
+
+} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/root_element.h b/chromium/components/ui_devtools/views/root_element.h
new file mode 100644
index 00000000000..f58137be75c
--- /dev/null
+++ b/chromium/components/ui_devtools/views/root_element.h
@@ -0,0 +1,34 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_UI_DEVTOOLS_VIEWS_ROOT_ELEMENT_H_
+#define COMPONENTS_UI_DEVTOOLS_VIEWS_ROOT_ELEMENT_H_
+
+#include "base/macros.h"
+#include "components/ui_devtools/views/ui_element.h"
+
+namespace ui_devtools {
+
+class RootElement : public UIElement {
+ public:
+ explicit RootElement(UIElementDelegate* ui_element_delegate);
+ ~RootElement() override;
+
+ // UIElement:
+ std::vector<std::pair<std::string, std::string>> GetCustomProperties()
+ 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;
+ std::unique_ptr<protocol::Array<std::string>> GetAttributes() const override;
+ std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndBounds()
+ const override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RootElement);
+};
+} // namespace ui_devtools
+
+#endif // COMPONENTS_UI_DEVTOOLS_VIEWS_ROOT_ELEMENT_H_
diff --git a/chromium/components/ui_devtools/views/ui_devtools_unittest.cc b/chromium/components/ui_devtools/views/ui_devtools_unittest.cc
index a942b35871d..d6693e97227 100644
--- a/chromium/components/ui_devtools/views/ui_devtools_unittest.cc
+++ b/chromium/components/ui_devtools/views/ui_devtools_unittest.cc
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "components/ui_devtools/views/css_agent.h"
@@ -212,7 +213,7 @@ class UIDevToolsTest : public views::ViewsTestBase {
aura::Window* parent,
aura::client::WindowType type = aura::client::WINDOW_TYPE_NORMAL) {
std::unique_ptr<aura::Window> window =
- base::MakeUnique<aura::Window>(nullptr, type);
+ std::make_unique<aura::Window>(nullptr, type);
window->Init(ui::LAYER_NOT_DRAWN);
window->SetBounds(gfx::Rect());
parent->AddChild(window.get());
@@ -221,15 +222,15 @@ class UIDevToolsTest : public views::ViewsTestBase {
}
void SetUp() override {
- fake_frontend_channel_ = base::MakeUnique<FakeFrontendChannel>();
+ fake_frontend_channel_ = std::make_unique<FakeFrontendChannel>();
uber_dispatcher_ =
- base::MakeUnique<UberDispatcher>(fake_frontend_channel_.get());
- dom_agent_ = base::MakeUnique<DOMAgent>();
+ std::make_unique<UberDispatcher>(fake_frontend_channel_.get());
+ dom_agent_ = std::make_unique<DOMAgent>();
dom_agent_->Init(uber_dispatcher_.get());
- css_agent_ = base::MakeUnique<CSSAgent>(dom_agent_.get());
+ css_agent_ = std::make_unique<CSSAgent>(dom_agent_.get());
css_agent_->Init(uber_dispatcher_.get());
css_agent_->enable();
- overlay_agent_ = base::MakeUnique<OverlayAgent>(dom_agent_.get());
+ overlay_agent_ = std::make_unique<OverlayAgent>(dom_agent_.get());
overlay_agent_->Init(uber_dispatcher_.get());
overlay_agent_->enable();
@@ -965,7 +966,7 @@ TEST_F(UIDevToolsTest, ViewRemoved) {
CreateTestWidget(gfx::Rect(1, 1, 1, 1)));
// Need to store |view| in unique_ptr because it is removed from the widget
// and needs to be destroyed independently
- std::unique_ptr<views::View> child_view = base::MakeUnique<views::View>();
+ std::unique_ptr<views::View> child_view = std::make_unique<views::View>();
aura::Window* window = widget->GetNativeWindow();
widget->Show();
views::View* root_view = widget->GetRootView();
diff --git a/chromium/components/ui_devtools/views/ui_element.cc b/chromium/components/ui_devtools/views/ui_element.cc
index 30f32c839f8..1a48248a010 100644
--- a/chromium/components/ui_devtools/views/ui_element.cc
+++ b/chromium/components/ui_devtools/views/ui_element.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "components/ui_devtools/Protocol.h"
#include "components/ui_devtools/views/ui_element_delegate.h"
#include "components/ui_devtools/views/view_element.h"
#include "components/ui_devtools/views/widget_element.h"
@@ -26,6 +27,8 @@ UIElement::~UIElement() {
std::string UIElement::GetTypeName() const {
switch (type_) {
+ case UIElementType::ROOT:
+ return "Root";
case UIElementType::WINDOW:
return "Window";
case UIElementType::WIDGET:
diff --git a/chromium/components/ui_devtools/views/ui_element.h b/chromium/components/ui_devtools/views/ui_element.h
index 1df61821190..dcb5827928c 100644
--- a/chromium/components/ui_devtools/views/ui_element.h
+++ b/chromium/components/ui_devtools/views/ui_element.h
@@ -8,16 +8,21 @@
#include <vector>
#include "base/macros.h"
-#include "ui/aura/window.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/native_widget_types.h"
#include "ui/views/view.h"
namespace ui_devtools {
class UIElementDelegate;
+namespace protocol {
+template <typename T>
+class Array;
+}
+
// UIElement type.
-enum UIElementType { WINDOW, WIDGET, VIEW };
+enum UIElementType { WINDOW, WIDGET, VIEW, ROOT };
class UIElement {
public:
@@ -43,8 +48,8 @@ class UIElement {
template <class T>
int FindUIElementIdForBackendElement(T* element) const;
- // Return a vector of pairs of attributes' names and values.
- virtual std::vector<std::pair<std::string, std::string>> GetCustomAttributes()
+ // Return a vector of pairs of properties' names and values.
+ virtual std::vector<std::pair<std::string, std::string>> GetCustomProperties()
const = 0;
virtual void GetBounds(gfx::Rect* bounds) const = 0;
virtual void SetBounds(const gfx::Rect& bounds) = 0;
@@ -53,7 +58,11 @@ class UIElement {
// If element exists, return its associated native window and its bounds.
// Otherwise, return null and empty bounds.
- virtual std::pair<aura::Window*, gfx::Rect> GetNodeWindowAndBounds()
+ virtual std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndBounds()
+ const = 0;
+ // Get a list of interleaved keys and values of attributes to be displayed
+ // on the element in the dev tools hierarchy view.
+ virtual std::unique_ptr<protocol::Array<std::string>> GetAttributes()
const = 0;
template <typename BackingT, typename T>
diff --git a/chromium/components/ui_devtools/views/view_element.cc b/chromium/components/ui_devtools/views/view_element.cc
index 3c7e50c709e..33bae48d06a 100644
--- a/chromium/components/ui_devtools/views/view_element.cc
+++ b/chromium/components/ui_devtools/views/view_element.cc
@@ -5,6 +5,7 @@
#include "components/ui_devtools/views/view_element.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/ui_devtools/Protocol.h"
#include "components/ui_devtools/views/ui_element_delegate.h"
#include "ui/views/widget/widget.h"
@@ -58,7 +59,7 @@ void ViewElement::OnViewBoundsChanged(views::View* view) {
}
std::vector<std::pair<std::string, std::string>>
-ViewElement::GetCustomAttributes() const {
+ViewElement::GetCustomProperties() const {
base::string16 description;
if (view_->GetTooltipText(gfx::Point(), &description)) {
return {std::make_pair<std::string, std::string>(
@@ -83,7 +84,16 @@ void ViewElement::SetVisible(bool visible) {
view_->SetVisible(visible);
}
-std::pair<aura::Window*, gfx::Rect> ViewElement::GetNodeWindowAndBounds()
+std::unique_ptr<protocol::Array<std::string>> ViewElement::GetAttributes()
+ const {
+ auto attributes = protocol::Array<std::string>::create();
+ // TODO(lgrey): Change name to class after updating tests.
+ attributes->addItem("name");
+ attributes->addItem(view_->GetClassName());
+ return attributes;
+}
+
+std::pair<gfx::NativeWindow, gfx::Rect> ViewElement::GetNodeWindowAndBounds()
const {
return std::make_pair(view_->GetWidget()->GetNativeWindow(),
view_->GetBoundsInScreen());
diff --git a/chromium/components/ui_devtools/views/view_element.h b/chromium/components/ui_devtools/views/view_element.h
index 6576069daa6..651b34381c4 100644
--- a/chromium/components/ui_devtools/views/view_element.h
+++ b/chromium/components/ui_devtools/views/view_element.h
@@ -7,8 +7,8 @@
#include "base/macros.h"
#include "components/ui_devtools/views/ui_element.h"
-#include "ui/aura/window.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/native_widget_types.h"
#include "ui/views/view.h"
#include "ui/views/view_observer.h"
@@ -31,13 +31,15 @@ class ViewElement : public views::ViewObserver, public UIElement {
void OnViewBoundsChanged(views::View* view) override;
// UIElement:
- std::vector<std::pair<std::string, std::string>> GetCustomAttributes()
+ std::vector<std::pair<std::string, std::string>> GetCustomProperties()
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;
- std::pair<aura::Window*, gfx::Rect> GetNodeWindowAndBounds() const override;
+ std::unique_ptr<protocol::Array<std::string>> GetAttributes() const override;
+ std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndBounds()
+ const override;
static views::View* From(const UIElement* element);
private:
diff --git a/chromium/components/ui_devtools/views/widget_element.cc b/chromium/components/ui_devtools/views/widget_element.cc
index fd5fa7efcd1..df6ac3e26a6 100644
--- a/chromium/components/ui_devtools/views/widget_element.cc
+++ b/chromium/components/ui_devtools/views/widget_element.cc
@@ -4,6 +4,7 @@
#include "components/ui_devtools/views/widget_element.h"
+#include "components/ui_devtools/Protocol.h"
#include "components/ui_devtools/views/ui_element_delegate.h"
namespace ui_devtools {
@@ -36,7 +37,7 @@ void WidgetElement::OnWidgetBoundsChanged(views::Widget* widget,
}
std::vector<std::pair<std::string, std::string>>
-WidgetElement::GetCustomAttributes() const {
+WidgetElement::GetCustomProperties() const {
return {};
}
@@ -61,7 +62,17 @@ void WidgetElement::SetVisible(bool visible) {
widget_->Hide();
}
-std::pair<aura::Window*, gfx::Rect> WidgetElement::GetNodeWindowAndBounds()
+std::unique_ptr<protocol::Array<std::string>> WidgetElement::GetAttributes()
+ const {
+ auto attributes = protocol::Array<std::string>::create();
+ attributes->addItem("name");
+ attributes->addItem(widget_->GetName());
+ attributes->addItem("active");
+ attributes->addItem(widget_->IsActive() ? "true" : "false");
+ return attributes;
+}
+
+std::pair<gfx::NativeWindow, gfx::Rect> WidgetElement::GetNodeWindowAndBounds()
const {
return std::make_pair(widget_->GetNativeWindow(),
widget_->GetWindowBoundsInScreen());
diff --git a/chromium/components/ui_devtools/views/widget_element.h b/chromium/components/ui_devtools/views/widget_element.h
index 56aa0cf4406..0fca29814e7 100644
--- a/chromium/components/ui_devtools/views/widget_element.h
+++ b/chromium/components/ui_devtools/views/widget_element.h
@@ -7,8 +7,8 @@
#include "base/macros.h"
#include "components/ui_devtools/views/ui_element.h"
-#include "ui/aura/window.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/native_widget_types.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
#include "ui/views/widget/widget_removals_observer.h"
@@ -35,13 +35,15 @@ class WidgetElement : public views::WidgetRemovalsObserver,
const gfx::Rect& new_bounds) override;
// UIElement:
- std::vector<std::pair<std::string, std::string>> GetCustomAttributes()
+ std::vector<std::pair<std::string, std::string>> GetCustomProperties()
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;
- std::pair<aura::Window*, gfx::Rect> GetNodeWindowAndBounds() const override;
+ std::unique_ptr<protocol::Array<std::string>> GetAttributes() const override;
+ std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndBounds()
+ const override;
static views::Widget* From(const UIElement* element);
diff --git a/chromium/components/ui_devtools/views/window_element.cc b/chromium/components/ui_devtools/views/window_element.cc
index 2213ffb445f..bb5fabef0b0 100644
--- a/chromium/components/ui_devtools/views/window_element.cc
+++ b/chromium/components/ui_devtools/views/window_element.cc
@@ -4,8 +4,10 @@
#include "components/ui_devtools/views/window_element.h"
+#include "components/ui_devtools/Protocol.h"
#include "components/ui_devtools/views/ui_element_delegate.h"
#include "ui/aura/window.h"
+#include "ui/wm/core/window_util.h"
namespace ui_devtools {
namespace {
@@ -65,7 +67,7 @@ void WindowElement::OnWindowBoundsChanged(aura::Window* window,
}
std::vector<std::pair<std::string, std::string>>
-WindowElement::GetCustomAttributes() const {
+WindowElement::GetCustomProperties() const {
return {};
}
@@ -88,9 +90,20 @@ void WindowElement::SetVisible(bool visible) {
window_->Hide();
}
-std::pair<aura::Window*, gfx::Rect> WindowElement::GetNodeWindowAndBounds()
+std::unique_ptr<protocol::Array<std::string>> WindowElement::GetAttributes()
const {
- return std::make_pair(window_, window_->GetBoundsInScreen());
+ auto attributes = protocol::Array<std::string>::create();
+ attributes->addItem("name");
+ attributes->addItem(window_->GetName());
+ attributes->addItem("active");
+ attributes->addItem(::wm::IsActiveWindow(window_) ? "true" : "false");
+ return attributes;
+}
+
+std::pair<gfx::NativeWindow, gfx::Rect> WindowElement::GetNodeWindowAndBounds()
+ const {
+ return std::make_pair(static_cast<aura::Window*>(window_),
+ window_->GetBoundsInScreen());
}
// static
diff --git a/chromium/components/ui_devtools/views/window_element.h b/chromium/components/ui_devtools/views/window_element.h
index 06130ed872c..fe176cc2897 100644
--- a/chromium/components/ui_devtools/views/window_element.h
+++ b/chromium/components/ui_devtools/views/window_element.h
@@ -10,6 +10,7 @@
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/native_widget_types.h"
namespace ui_devtools {
@@ -33,13 +34,15 @@ class WindowElement : public aura::WindowObserver, public UIElement {
ui::PropertyChangeReason reason) override;
// UIElement:
- std::vector<std::pair<std::string, std::string>> GetCustomAttributes()
+ std::vector<std::pair<std::string, std::string>> GetCustomProperties()
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;
- std::pair<aura::Window*, gfx::Rect> GetNodeWindowAndBounds() const override;
+ std::unique_ptr<protocol::Array<std::string>> GetAttributes() const override;
+ std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndBounds()
+ const override;
static aura::Window* From(const UIElement* element);
diff --git a/chromium/components/ukm/BUILD.gn b/chromium/components/ukm/BUILD.gn
index 3705109962a..2367f2eb497 100644
--- a/chromium/components/ukm/BUILD.gn
+++ b/chromium/components/ukm/BUILD.gn
@@ -27,7 +27,7 @@ static_library("ukm") {
public_deps = [
"//services/metrics/public/cpp:metrics_cpp",
- "//services/metrics/public/interfaces",
+ "//services/metrics/public/mojom",
"//third_party/metrics_proto",
]
diff --git a/chromium/components/ukm/content/BUILD.gn b/chromium/components/ukm/content/BUILD.gn
index 1d306f9affb..8708c14296a 100644
--- a/chromium/components/ukm/content/BUILD.gn
+++ b/chromium/components/ukm/content/BUILD.gn
@@ -11,7 +11,7 @@ static_library("content") {
"//base",
"//content/public/browser",
"//services/metrics/public/cpp:metrics_cpp",
- "//services/metrics/public/interfaces",
+ "//services/metrics/public/mojom",
"//url",
]
}
diff --git a/chromium/components/ukm/debug_page/BUILD.gn b/chromium/components/ukm/content/debug_page/BUILD.gn
index ffbaa4fa776..a22951e1498 100644
--- a/chromium/components/ukm/debug_page/BUILD.gn
+++ b/chromium/components/ukm/content/debug_page/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
+# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -11,8 +11,8 @@ static_library("debug_page") {
deps = [
"//base",
"//components/ukm",
+ "//components/ukm/debug:util",
"//content/public/browser",
- "//services/metrics/public/cpp:ukm_builders",
"//url",
]
}
diff --git a/chromium/components/ukm/content/debug_page/debug_page.cc b/chromium/components/ukm/content/debug_page/debug_page.cc
new file mode 100644
index 00000000000..0b2ff6f80e7
--- /dev/null
+++ b/chromium/components/ukm/content/debug_page/debug_page.cc
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/ukm/content/debug_page/debug_page.h"
+
+#include "base/memory/ref_counted_memory.h"
+#include "components/ukm/debug/ukm_debug_data_extractor.h"
+
+namespace ukm {
+namespace debug {
+
+DebugPage::DebugPage(ServiceGetter service_getter)
+ : service_getter_(service_getter) {}
+
+DebugPage::~DebugPage() {}
+
+std::string DebugPage::GetSource() const {
+ return "ukm";
+}
+
+std::string DebugPage::GetMimeType(const std::string& path) const {
+ return "text/html";
+}
+
+void DebugPage::StartDataRequest(
+ const std::string& path,
+ const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+ const content::URLDataSource::GotDataCallback& callback) {
+ std::string data = UkmDebugDataExtractor::GetHTMLData(service_getter_.Run());
+ callback.Run(base::RefCountedString::TakeString(&data));
+}
+
+bool DebugPage::AllowCaching() const {
+ return false;
+}
+
+} // namespace debug
+} // namespace ukm
diff --git a/chromium/components/ukm/debug_page/debug_page.h b/chromium/components/ukm/content/debug_page/debug_page.h
index 52ae7a167af..e693b1bfd35 100644
--- a/chromium/components/ukm/debug_page/debug_page.h
+++ b/chromium/components/ukm/content/debug_page/debug_page.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -20,7 +20,7 @@ namespace debug {
// Implements the chrome://ukm page for debugging UKM state.
class DebugPage : public content::URLDataSource {
public:
- typedef base::Callback<UkmService*()> ServiceGetter;
+ typedef base::RepeatingCallback<UkmService*()> ServiceGetter;
explicit DebugPage(ServiceGetter service_getter);
diff --git a/chromium/components/ukm/content/source_url_recorder.cc b/chromium/components/ukm/content/source_url_recorder.cc
index fb8dc18b943..bfc762f6cfe 100644
--- a/chromium/components/ukm/content/source_url_recorder.cc
+++ b/chromium/components/ukm/content/source_url_recorder.cc
@@ -39,7 +39,7 @@ class SourceUrlRecorderWebContentsObserver
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
- ukm::SourceId GetLastCommittedSourceId();
+ ukm::SourceId GetLastCommittedSourceId() const;
private:
explicit SourceUrlRecorderWebContentsObserver(
@@ -107,7 +107,8 @@ void SourceUrlRecorderWebContentsObserver::DidFinishNavigation(
MaybeRecordUrl(navigation_handle, initial_url);
}
-ukm::SourceId SourceUrlRecorderWebContentsObserver::GetLastCommittedSourceId() {
+ukm::SourceId SourceUrlRecorderWebContentsObserver::GetLastCommittedSourceId()
+ const {
return last_committed_source_id_;
}
@@ -149,8 +150,9 @@ void InitializeSourceUrlRecorderForWebContents(
web_contents);
}
-SourceId GetSourceIdForWebContentsDocument(content::WebContents* web_contents) {
- internal::SourceUrlRecorderWebContentsObserver* obs =
+SourceId GetSourceIdForWebContentsDocument(
+ const content::WebContents* web_contents) {
+ const internal::SourceUrlRecorderWebContentsObserver* obs =
internal::SourceUrlRecorderWebContentsObserver::FromWebContents(
web_contents);
return obs ? obs->GetLastCommittedSourceId() : kInvalidSourceId;
diff --git a/chromium/components/ukm/content/source_url_recorder.h b/chromium/components/ukm/content/source_url_recorder.h
index eff51240c18..64f704d22b7 100644
--- a/chromium/components/ukm/content/source_url_recorder.h
+++ b/chromium/components/ukm/content/source_url_recorder.h
@@ -19,7 +19,8 @@ void InitializeSourceUrlRecorderForWebContents(
// Get a UKM SourceId for the currently committed document of web contents.
// Returns kInvalidSourceId if no commit has been observed.
-SourceId GetSourceIdForWebContentsDocument(content::WebContents* web_contents);
+SourceId GetSourceIdForWebContentsDocument(
+ const content::WebContents* web_contents);
} // namespace ukm
diff --git a/chromium/components/ukm/content/source_url_recorder_browsertest.cc b/chromium/components/ukm/content/source_url_recorder_browsertest.cc
index 82d3425380c..bb37e781e78 100644
--- a/chromium/components/ukm/content/source_url_recorder_browsertest.cc
+++ b/chromium/components/ukm/content/source_url_recorder_browsertest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
+
#include "base/files/scoped_temp_dir.h"
#include "base/test/scoped_feature_list.h"
#include "components/ukm/content/source_url_recorder.h"
@@ -29,7 +31,7 @@ class SourceUrlRecorderWebContentsObserverBrowserTest
ASSERT_TRUE(embedded_test_server()->Start());
- test_ukm_recorder_ = base::MakeUnique<ukm::TestAutoSetUkmRecorder>();
+ test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
ukm::InitializeSourceUrlRecorderForWebContents(shell()->web_contents());
}
diff --git a/chromium/components/ukm/debug/BUILD.gn b/chromium/components/ukm/debug/BUILD.gn
new file mode 100644
index 00000000000..f40504a34d7
--- /dev/null
+++ b/chromium/components/ukm/debug/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("util") {
+ sources = [
+ "ukm_debug_data_extractor.cc",
+ "ukm_debug_data_extractor.h",
+ ]
+ deps = [
+ "//base",
+ "//components/ukm",
+ "//services/metrics/public/cpp:ukm_builders",
+ ]
+}
diff --git a/chromium/components/ukm/debug_page/debug_page.cc b/chromium/components/ukm/debug/ukm_debug_data_extractor.cc
index 1bc33a5f3c3..5377eeeec9c 100644
--- a/chromium/components/ukm/debug_page/debug_page.cc
+++ b/chromium/components/ukm/debug/ukm_debug_data_extractor.cc
@@ -1,12 +1,11 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/ukm/debug_page/debug_page.h"
+#include "components/ukm/debug/ukm_debug_data_extractor.h"
#include <inttypes.h>
-#include "base/memory/ref_counted_memory.h"
#include "base/strings/stringprintf.h"
#include "components/ukm/ukm_service.h"
#include "components/ukm/ukm_source.h"
@@ -31,25 +30,14 @@ std::string GetName(ukm::builders::DecodeMap& decode_map, uint64_t hash) {
} // namespace
-DebugPage::DebugPage(ServiceGetter service_getter)
- : service_getter_(service_getter) {}
+UkmDebugDataExtractor::UkmDebugDataExtractor() = default;
-DebugPage::~DebugPage() {}
+UkmDebugDataExtractor::~UkmDebugDataExtractor() = default;
-std::string DebugPage::GetSource() const {
- return "ukm";
-}
-
-std::string DebugPage::GetMimeType(const std::string& path) const {
- return "text/html";
-}
-
-void DebugPage::StartDataRequest(
- const std::string& path,
- const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
- const content::URLDataSource::GotDataCallback& callback) {
- std::string data;
- data.append(R"""(<!DOCTYPE html>
+// static
+std::string UkmDebugDataExtractor::GetHTMLData(UkmService* ukm_service) {
+ std::string output;
+ output.append(R"""(<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy"
@@ -59,15 +47,16 @@ void DebugPage::StartDataRequest(
<body>
<h1>UKM Debug page</h1>
)""");
- UkmService* ukm_service = service_getter_.Run();
+
if (ukm_service) {
- data.append(
+ output.append(
// 'id' attribute set so tests can extract this element.
base::StringPrintf("<p>IsEnabled:<span id='state'>%s</span></p>",
ukm_service->recording_enabled_ ? "True" : "False"));
- data.append(base::StringPrintf("<p>ClientId:%" PRIu64 "</p>",
- ukm_service->client_id_));
- data.append(
+ output.append(base::StringPrintf("<p>ClientId:<span id='clientid'>%" PRIu64
+ "</span></p>",
+ ukm_service->client_id_));
+ output.append(
base::StringPrintf("<p>SessionId:%d</p>", ukm_service->session_id_));
auto decode_map = ::ukm::builders::CreateDecodeMap();
@@ -80,21 +69,21 @@ void DebugPage::StartDataRequest(
source_data[v.get()->source_id].entries.push_back(v.get());
}
- data.append("<h2>Sources</h2>");
+ output.append("<h2>Sources</h2>");
for (const auto& kv : source_data) {
const auto* src = kv.second.source;
if (src) {
- data.append(base::StringPrintf("<h3>Id:%" PRId64 " Url:%s</h3>",
- src->id(), src->url().spec().c_str()));
+ output.append(base::StringPrintf("<h3>Id:%" PRId64 " Url:%s</h3>",
+ src->id(), src->url().spec().c_str()));
} else {
- data.append(base::StringPrintf("<h3>Id:%" PRId64 "</h3>", kv.first));
+ output.append(base::StringPrintf("<h3>Id:%" PRId64 "</h3>", kv.first));
}
for (auto* entry : kv.second.entries) {
- data.append(
+ output.append(
base::StringPrintf("<h4>Entry:%s</h4>",
GetName(decode_map, entry->event_hash).c_str()));
for (const auto& metric : entry->metrics) {
- data.append(base::StringPrintf(
+ output.append(base::StringPrintf(
"<h5>Metric:%s Value:%" PRId64 "</h5>",
GetName(decode_map, metric->metric_hash).c_str(), metric->value));
}
@@ -102,16 +91,12 @@ void DebugPage::StartDataRequest(
}
}
- data.append(R"""(
+ output.append(R"""(
</body>
</html>
)""");
- callback.Run(base::RefCountedString::TakeString(&data));
-}
-
-bool DebugPage::AllowCaching() const {
- return false;
+ return output;
}
} // namespace debug
diff --git a/chromium/components/ukm/debug/ukm_debug_data_extractor.h b/chromium/components/ukm/debug/ukm_debug_data_extractor.h
new file mode 100644
index 00000000000..42d953c0022
--- /dev/null
+++ b/chromium/components/ukm/debug/ukm_debug_data_extractor.h
@@ -0,0 +1,34 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_UKM_DEBUG_UKM_DEBUG_DATA_EXTRACTOR_H_
+#define COMPONENTS_UKM_DEBUG_UKM_DEBUG_DATA_EXTRACTOR_H_
+
+#include <string>
+
+#include "base/macros.h"
+
+namespace ukm {
+
+class UkmService;
+
+namespace debug {
+
+// Extracts UKM data as an HTML page for debugging purposes.
+class UkmDebugDataExtractor {
+ public:
+ UkmDebugDataExtractor();
+ ~UkmDebugDataExtractor();
+
+ // Returns UKM data as an HTML page.
+ static std::string GetHTMLData(UkmService* ukm_service);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(UkmDebugDataExtractor);
+};
+
+} // namespace debug
+} // namespace ukm
+
+#endif // COMPONENTS_UKM_DEBUG_UKM_DEBUG_DATA_EXTRACTOR_H_
diff --git a/chromium/components/ukm/debug_page/DEPS b/chromium/components/ukm/debug_page/DEPS
deleted file mode 100644
index fe7bb13183f..00000000000
--- a/chromium/components/ukm/debug_page/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+content/public",
-]
diff --git a/chromium/components/ukm/observers/sync_disable_observer.cc b/chromium/components/ukm/observers/sync_disable_observer.cc
index 7609b7a0ce2..c7b5f34d138 100644
--- a/chromium/components/ukm/observers/sync_disable_observer.cc
+++ b/chromium/components/ukm/observers/sync_disable_observer.cc
@@ -9,20 +9,24 @@
namespace ukm {
SyncDisableObserver::SyncDisableObserver()
- : sync_observer_(this), all_profiles_enabled_(false) {}
+ : sync_observer_(this),
+ all_histories_enabled_(false),
+ all_extensions_enabled_(false) {}
SyncDisableObserver::~SyncDisableObserver() {}
// static
SyncDisableObserver::SyncState SyncDisableObserver::GetSyncState(
syncer::SyncService* sync_service) {
- const bool initialized = sync_service->IsEngineInitialized();
- return SyncDisableObserver::SyncState{
- sync_service->GetPreferredDataTypes().Has(
- syncer::HISTORY_DELETE_DIRECTIVES),
- initialized,
- initialized ? sync_service->IsUsingSecondaryPassphrase() : false,
- };
+ SyncState state;
+ state.history_enabled = sync_service->GetPreferredDataTypes().Has(
+ syncer::HISTORY_DELETE_DIRECTIVES);
+ state.extensions_enabled =
+ sync_service->GetPreferredDataTypes().Has(syncer::EXTENSIONS);
+ state.initialized = sync_service->IsEngineInitialized();
+ state.passphrase_protected =
+ state.initialized && sync_service->IsUsingSecondaryPassphrase();
+ return state;
}
void SyncDisableObserver::ObserveServiceForSyncDisables(
@@ -33,14 +37,20 @@ void SyncDisableObserver::ObserveServiceForSyncDisables(
}
void SyncDisableObserver::UpdateAllProfileEnabled(bool must_purge) {
- bool all_enabled = AreAllProfilesEnabled();
- if (must_purge || (all_enabled != all_profiles_enabled_)) {
- all_profiles_enabled_ = all_enabled;
+ bool all_enabled = CheckHistorySyncOnAllProfiles();
+ bool all_extensions_enabled =
+ all_enabled && CheckExtensionSyncOnAllProfiles();
+ // Any change in sync settings needs to call OnSyncPrefsChanged so that the
+ // new settings take effect.
+ if (must_purge || (all_enabled != all_histories_enabled_) ||
+ (all_extensions_enabled != all_extensions_enabled_)) {
+ all_histories_enabled_ = all_enabled;
+ all_extensions_enabled_ = all_extensions_enabled;
OnSyncPrefsChanged(must_purge);
}
}
-bool SyncDisableObserver::AreAllProfilesEnabled() {
+bool SyncDisableObserver::CheckHistorySyncOnAllProfiles() {
if (previous_states_.empty())
return false;
for (const auto& kv : previous_states_) {
@@ -52,6 +62,17 @@ bool SyncDisableObserver::AreAllProfilesEnabled() {
return true;
}
+bool SyncDisableObserver::CheckExtensionSyncOnAllProfiles() {
+ if (previous_states_.empty())
+ return false;
+ for (const auto& kv : previous_states_) {
+ const SyncDisableObserver::SyncState& state = kv.second;
+ if (!state.extensions_enabled)
+ return false;
+ }
+ return true;
+}
+
void SyncDisableObserver::OnStateChanged(syncer::SyncService* sync) {
DCHECK(base::ContainsKey(previous_states_, sync));
SyncDisableObserver::SyncState state = GetSyncState(sync);
@@ -78,7 +99,11 @@ void SyncDisableObserver::OnSyncShutdown(syncer::SyncService* sync) {
}
bool SyncDisableObserver::IsHistorySyncEnabledOnAllProfiles() {
- return all_profiles_enabled_;
+ return all_histories_enabled_;
+}
+
+bool SyncDisableObserver::IsExtensionSyncEnabledOnAllProfiles() {
+ return all_extensions_enabled_;
}
} // namespace ukm
diff --git a/chromium/components/ukm/observers/sync_disable_observer.h b/chromium/components/ukm/observers/sync_disable_observer.h
index 931e5ba6cd9..f336cc3b5eb 100644
--- a/chromium/components/ukm/observers/sync_disable_observer.h
+++ b/chromium/components/ukm/observers/sync_disable_observer.h
@@ -28,6 +28,9 @@ class SyncDisableObserver : public syncer::SyncServiceObserver {
// Returns if history sync is enabled on all active profiles.
virtual bool IsHistorySyncEnabledOnAllProfiles();
+ // Returns if history sync is enabled on all active profiles.
+ virtual bool IsExtensionSyncEnabledOnAllProfiles();
+
protected:
// Called after state changes and some profile has sync disabled.
// If |must_purge| is true, sync was disabled for some profile, and
@@ -42,9 +45,13 @@ class SyncDisableObserver : public syncer::SyncServiceObserver {
// Recomputes all_profiles_enabled_ state from previous_states_;
void UpdateAllProfileEnabled(bool must_purge);
- // Returns true iff all profiles are enabled in previous_states_.
+ // Returns true iff all profile histories are enabled in previous_states_.
// If there are no profiles being observed, this returns false.
- bool AreAllProfilesEnabled();
+ bool CheckHistorySyncOnAllProfiles();
+
+ // Returns true iff all profile extensions are enabled in previous_states_.
+ // If there are no profiles being observed, this returns false.
+ bool CheckExtensionSyncOnAllProfiles();
// Tracks observed history services, for cleanup.
ScopedObserver<syncer::SyncService, syncer::SyncServiceObserver>
@@ -53,12 +60,14 @@ class SyncDisableObserver : public syncer::SyncServiceObserver {
// State data about sync services that we need to remember.
struct SyncState {
// If the user has history sync enabled.
- bool history_enabled;
+ bool history_enabled = false;
+ // If the user has extension sync enabled.
+ bool extensions_enabled = false;
// Whether the sync service has been initialized.
- bool initialized;
+ bool initialized = false;
// Whether user data is hidden by a secondary passphrase.
// This is not valid if the state is not initialized.
- bool passphrase_protected;
+ bool passphrase_protected = false;
};
// Gets the current state of a SyncService.
@@ -67,8 +76,13 @@ class SyncDisableObserver : public syncer::SyncServiceObserver {
// The list of services that had sync enabled when we last checked.
std::map<syncer::SyncService*, SyncState> previous_states_;
- // Tracks if sync was enabled on all profiles after the last state change.
- bool all_profiles_enabled_;
+ // Tracks if history sync was enabled on all profiles after the last state
+ // change.
+ bool all_histories_enabled_;
+
+ // Tracks if extension sync was enabled on all profiles after the last state
+ // change.
+ bool all_extensions_enabled_;
DISALLOW_COPY_AND_ASSIGN(SyncDisableObserver);
};
diff --git a/chromium/components/ukm/test_ukm_recorder.cc b/chromium/components/ukm/test_ukm_recorder.cc
index 5a9139585d9..954cba46287 100644
--- a/chromium/components/ukm/test_ukm_recorder.cc
+++ b/chromium/components/ukm/test_ukm_recorder.cc
@@ -60,7 +60,7 @@ std::vector<int64_t> GetValuesForMetric(const mojom::UkmEntry* entry,
} // namespace
TestUkmRecorder::TestUkmRecorder() {
- EnableRecording();
+ EnableRecording(/*extensions=*/true);
}
TestUkmRecorder::~TestUkmRecorder() {
diff --git a/chromium/components/ukm/test_ukm_recorder.h b/chromium/components/ukm/test_ukm_recorder.h
index e2ec2ffe84e..d540b43873b 100644
--- a/chromium/components/ukm/test_ukm_recorder.h
+++ b/chromium/components/ukm/test_ukm_recorder.h
@@ -17,7 +17,7 @@
#include "base/memory/weak_ptr.h"
#include "components/ukm/ukm_recorder_impl.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
-#include "services/metrics/public/interfaces/ukm_interface.mojom.h"
+#include "services/metrics/public/mojom/ukm_interface.mojom.h"
#include "url/gurl.h"
namespace ukm {
@@ -36,38 +36,39 @@ class TestUkmRecorder : public UkmRecorderImpl {
using UkmRecorderImpl::UpdateSourceURL;
- // Get all recorded UkmSource data.
+ // Gets all recorded UkmSource data.
const std::map<ukm::SourceId, std::unique_ptr<UkmSource>>& GetSources()
const {
return sources();
}
- // Get UkmSource data for a single SourceId.
+ // Gets UkmSource data for a single SourceId.
const UkmSource* GetSourceForSourceId(ukm::SourceId source_id) const;
- // Get all of the entries recorded for entry name.
+ // Gets all of the entries recorded for entry name.
std::vector<const mojom::UkmEntry*> GetEntriesByName(
base::StringPiece entry_name) const;
- // Get the data for all entries with given entry name, merged to one entry
+ // Gets the data for all entries with given entry name, merged to one entry
// for each source id. Intended for singular="true" metrics.
std::map<ukm::SourceId, mojom::UkmEntryPtr> GetMergedEntriesByName(
base::StringPiece entry_name) const;
- // Check if an entry is associated with a url.
+ // Checks if an entry is associated with a url.
void ExpectEntrySourceHasUrl(const mojom::UkmEntry* entry,
const GURL& url) const;
- // Expect the value of a metric from an entry.
+ // Expects the value of a metric from an entry.
static void ExpectEntryMetric(const mojom::UkmEntry* entry,
base::StringPiece metric_name,
int64_t expected_value);
- // Check if an entry contains a specific metric.
+ // Checks if an entry contains a specific metric.
static bool EntryHasMetric(const mojom::UkmEntry* entry,
base::StringPiece metric_name);
- // Expect the value of a metric from an entry.
+ // Gets the value of a metric from an entry. Returns nullptr if the metric is
+ // not found.
static const int64_t* GetEntryMetric(const mojom::UkmEntry* entry,
base::StringPiece metric_name);
diff --git a/chromium/components/ukm/ukm_recorder_impl.cc b/chromium/components/ukm/ukm_recorder_impl.cc
index 7f431a86841..2c52d74cc7f 100644
--- a/chromium/components/ukm/ukm_recorder_impl.cc
+++ b/chromium/components/ukm/ukm_recorder_impl.cc
@@ -4,14 +4,18 @@
#include "components/ukm/ukm_recorder_impl.h"
+#include <limits>
#include <memory>
#include <string>
#include <utility>
+#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/metrics_hashes.h"
+#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "components/ukm/ukm_source.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
@@ -24,7 +28,16 @@ namespace ukm {
namespace {
-// Gets the list of whitelisted Entries as string. Format is a comma seperated
+// Note: kChromeUIScheme is defined in content, which this code can't
+// depend on - since it's used by iOS too. kExtensionScheme is defined
+// in extensions which also isn't always available here.
+const char kChromeUIScheme[] = "chrome";
+const char kExtensionScheme[] = "chrome-extension";
+
+const base::Feature kUkmSamplingRateFeature{"UkmSamplingRate",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Gets the list of whitelisted Entries as string. Format is a comma separated
// list of Entry names (as strings).
std::string GetWhitelistEntries() {
return base::GetFieldTrialParamValueByFeature(kUkmFeature,
@@ -43,7 +56,7 @@ size_t GetMaxSources() {
kUkmFeature, "MaxSources", kDefaultMaxSources));
}
-// Gets the maximum number of unferenced Sources kept after purging sources
+// Gets the maximum number of unreferenced Sources kept after purging sources
// that were added to the log.
size_t GetMaxKeptSources() {
constexpr size_t kDefaultMaxKeptSources = 100;
@@ -61,14 +74,10 @@ size_t GetMaxEntries() {
// Returns whether |url| has one of the schemes supported for logging to UKM.
// URLs with other schemes will not be logged.
-// Note: This currently excludes chrome-extension:// URLs as in order to log
-// them, UKM needs to take into account extension-sync consent, which is not
-// yet done.
bool HasSupportedScheme(const GURL& url) {
- // Note: kChromeUIScheme is defined in content, which this code can't
- // depend on - since it's used by iOS too. So "chrome" is hardcoded here.
return url.SchemeIsHTTPOrHTTPS() || url.SchemeIs(url::kFtpScheme) ||
- url.SchemeIs(url::kAboutScheme) || url.SchemeIs("chrome");
+ url.SchemeIs(url::kAboutScheme) || url.SchemeIs(kChromeUIScheme) ||
+ url.SchemeIs(kExtensionScheme);
}
// True if we should record the initial_url field of the UKM Source proto.
@@ -83,6 +92,9 @@ enum class DroppedDataReason {
MAX_HIT = 2,
NOT_WHITELISTED = 3,
UNSUPPORTED_URL_SCHEME = 4,
+ SAMPLED_OUT = 5,
+ EXTENSION_URLS_DISABLED = 6,
+ EXTENSION_NOT_SYNCED = 7,
NUM_DROPPED_DATA_REASONS
};
@@ -128,14 +140,16 @@ GURL SanitizeURL(const GURL& url) {
UkmRecorderImpl::UkmRecorderImpl() : recording_enabled_(false) {}
UkmRecorderImpl::~UkmRecorderImpl() = default;
-void UkmRecorderImpl::EnableRecording() {
- DVLOG(1) << "UkmRecorderImpl::EnableRecording";
+void UkmRecorderImpl::EnableRecording(bool extensions) {
+ DVLOG(1) << "UkmRecorderImpl::EnableRecording, extensions=" << extensions;
recording_enabled_ = true;
+ extensions_enabled_ = extensions;
}
void UkmRecorderImpl::DisableRecording() {
DVLOG(1) << "UkmRecorderImpl::DisableRecording";
recording_enabled_ = false;
+ extensions_enabled_ = false;
}
void UkmRecorderImpl::Purge() {
@@ -144,6 +158,11 @@ void UkmRecorderImpl::Purge() {
entries_.clear();
}
+void UkmRecorderImpl::SetIsWebstoreExtensionCallback(
+ const IsWebstoreExtensionCallback& callback) {
+ is_webstore_extension_callback_ = callback;
+}
+
void UkmRecorderImpl::StoreRecordingsInReport(Report* report) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -170,10 +189,43 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) {
if (!ShouldRecordInitialUrl())
proto_source->clear_initial_url();
}
+ for (const auto& event_and_aggregate : event_aggregations_) {
+ if (event_and_aggregate.second.metrics.empty())
+ continue;
+ const EventAggregate& event_aggregate = event_and_aggregate.second;
+ Aggregate* proto_aggregate = report->add_aggregates();
+ proto_aggregate->set_source_id(0); // Across all sources.
+ proto_aggregate->set_event_hash(event_and_aggregate.first);
+ proto_aggregate->set_total_count(event_aggregate.total_count);
+ proto_aggregate->set_dropped_due_to_limits(
+ event_aggregate.dropped_due_to_limits);
+ proto_aggregate->set_dropped_due_to_sampling(
+ event_aggregate.dropped_due_to_sampling);
+ for (const auto& metric_and_aggregate : event_aggregate.metrics) {
+ const MetricAggregate& aggregate = metric_and_aggregate.second;
+ Aggregate::Metric* proto_metric = proto_aggregate->add_metrics();
+ proto_metric->set_metric_hash(metric_and_aggregate.first);
+ proto_metric->set_value_sum(aggregate.value_sum);
+ proto_metric->set_value_square_sum(aggregate.value_square_sum);
+ if (aggregate.total_count != event_aggregate.total_count) {
+ proto_metric->set_total_count(aggregate.total_count);
+ }
+ if (aggregate.dropped_due_to_limits !=
+ event_aggregate.dropped_due_to_limits) {
+ proto_metric->set_dropped_due_to_limits(
+ aggregate.dropped_due_to_limits);
+ }
+ if (aggregate.dropped_due_to_sampling !=
+ event_aggregate.dropped_due_to_sampling) {
+ proto_metric->set_dropped_due_to_sampling(
+ aggregate.dropped_due_to_sampling);
+ }
+ }
+ }
UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.SerializedCount",
sources_.size() - unsent_sources.size());
- UMA_HISTOGRAM_COUNTS_1000("UKM.Entries.SerializedCount", entries_.size());
+ UMA_HISTOGRAM_COUNTS_100000("UKM.Entries.SerializedCount2", entries_.size());
UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.UnsentSourcesCount",
unsent_sources.size());
sources_.clear();
@@ -204,6 +256,9 @@ bool UkmRecorderImpl::ShouldRestrictToWhitelistedSourceIds() const {
kUkmFeature, "RestrictToWhitelistedSourceIds", false);
}
+UkmRecorderImpl::EventAggregate::EventAggregate() = default;
+UkmRecorderImpl::EventAggregate::~EventAggregate() = default;
+
void UkmRecorderImpl::UpdateSourceURL(SourceId source_id,
const GURL& unsanitized_url) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -226,6 +281,19 @@ void UkmRecorderImpl::UpdateSourceURL(SourceId source_id,
return;
}
+ // Extension URLs need to be specifically enabled and the extension synced.
+ if (url.SchemeIs(kExtensionScheme)) {
+ if (!extensions_enabled_) {
+ RecordDroppedSource(DroppedDataReason::EXTENSION_URLS_DISABLED);
+ return;
+ }
+ if (!is_webstore_extension_callback_ ||
+ !is_webstore_extension_callback_.Run(url.host_piece())) {
+ RecordDroppedSource(DroppedDataReason::EXTENSION_NOT_SYNCED);
+ return;
+ }
+ }
+
// Update the pre-existing source if there is any. This happens when the
// initial URL is different from the committed URL for the same source, e.g.,
// when there is redirection.
@@ -238,7 +306,7 @@ void UkmRecorderImpl::UpdateSourceURL(SourceId source_id,
RecordDroppedSource(DroppedDataReason::MAX_HIT);
return;
}
- sources_.emplace(source_id, base::MakeUnique<UkmSource>(source_id, url));
+ sources_.emplace(source_id, std::make_unique<UkmSource>(source_id, url));
}
void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) {
@@ -248,10 +316,6 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) {
RecordDroppedEntry(DroppedDataReason::RECORDING_DISABLED);
return;
}
- if (entries_.size() >= GetMaxEntries()) {
- RecordDroppedEntry(DroppedDataReason::MAX_HIT);
- return;
- }
if (!whitelisted_entry_hashes_.empty() &&
!base::ContainsKey(whitelisted_entry_hashes_, entry->event_hash)) {
@@ -259,9 +323,78 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) {
return;
}
+ if (default_sampling_rate_ == 0)
+ LoadExperimentSamplingInfo();
+
+ EventAggregate& event_aggregate = event_aggregations_[entry->event_hash];
+ event_aggregate.total_count++;
+ for (const auto& metric : entry->metrics) {
+ MetricAggregate& aggregate = event_aggregate.metrics[metric->metric_hash];
+ double value = metric->value;
+ aggregate.total_count++;
+ aggregate.value_sum += value;
+ aggregate.value_square_sum += value * value;
+ }
+
+ auto found = event_sampling_rates_.find(entry->event_hash);
+ int sampling_rate = (found != event_sampling_rates_.end())
+ ? found->second
+ : default_sampling_rate_;
+ if (sampling_rate == 0 ||
+ (sampling_rate > 1 && base::RandInt(1, sampling_rate) != 1)) {
+ RecordDroppedEntry(DroppedDataReason::SAMPLED_OUT);
+ event_aggregate.dropped_due_to_sampling++;
+ for (auto& metric : entry->metrics)
+ event_aggregate.metrics[metric->metric_hash].dropped_due_to_sampling++;
+ return;
+ }
+
+ if (entries_.size() >= GetMaxEntries()) {
+ RecordDroppedEntry(DroppedDataReason::MAX_HIT);
+ event_aggregate.dropped_due_to_limits++;
+ for (auto& metric : entry->metrics)
+ event_aggregate.metrics[metric->metric_hash].dropped_due_to_limits++;
+ return;
+ }
+
entries_.push_back(std::move(entry));
}
+void UkmRecorderImpl::LoadExperimentSamplingInfo() {
+ DCHECK_EQ(0, default_sampling_rate_);
+ std::map<std::string, std::string> params;
+
+ if (base::FeatureList::IsEnabled(kUkmSamplingRateFeature)) {
+ // Enabled may have various parameters to control sampling.
+ if (base::GetFieldTrialParamsByFeature(kUkmSamplingRateFeature, &params)) {
+ for (const auto& kv : params) {
+ const std::string& key = kv.first;
+ if (key.length() == 0)
+ continue;
+
+ // Keys starting with an underscore are global configuration.
+ if (key.at(0) == '_') {
+ if (key == "_default_sampling") {
+ int sampling;
+ if (base::StringToInt(kv.second, &sampling) && sampling >= 0)
+ default_sampling_rate_ = sampling;
+ }
+ continue;
+ }
+
+ // Anything else is an event name.
+ int sampling;
+ if (base::StringToInt(kv.second, &sampling) && sampling >= 0)
+ event_sampling_rates_[base::HashMetricName(key)] = sampling;
+ }
+ }
+ }
+
+ // Default rate must be >0 to indicate that load is complete.
+ if (default_sampling_rate_ == 0)
+ default_sampling_rate_ = 1;
+}
+
void UkmRecorderImpl::StoreWhitelistedEntries() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const auto entries =
diff --git a/chromium/components/ukm/ukm_recorder_impl.h b/chromium/components/ukm/ukm_recorder_impl.h
index a24820aabde..bd9670a48b1 100644
--- a/chromium/components/ukm/ukm_recorder_impl.h
+++ b/chromium/components/ukm/ukm_recorder_impl.h
@@ -9,9 +9,12 @@
#include <set>
#include <vector>
+#include "base/callback_forward.h"
+#include "base/containers/flat_map.h"
#include "base/sequence_checker.h"
+#include "base/strings/string_piece.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
-#include "services/metrics/public/interfaces/ukm_interface.mojom.h"
+#include "services/metrics/public/mojom/ukm_interface.mojom.h"
namespace metrics {
class UkmBrowserTest;
@@ -24,21 +27,30 @@ class UkmSource;
class Report;
namespace debug {
-class DebugPage;
+class UkmDebugDataExtractor;
}
class UkmRecorderImpl : public UkmRecorder {
+ using IsWebstoreExtensionCallback =
+ base::RepeatingCallback<bool(base::StringPiece id)>;
+
public:
UkmRecorderImpl();
~UkmRecorderImpl() override;
- // Enables/disables recording control if data is allowed to be collected.
- void EnableRecording();
+ // Enables/disables recording control if data is allowed to be collected. The
+ // |extensions| flag separately controls recording of chrome-extension://
+ // URLs; this flag should reflect the "sync extensions" user setting.
+ void EnableRecording(bool extensions);
void DisableRecording();
// Deletes stored recordings.
void Purge();
+ // Sets a callback for determining if an extension URL can be recorded.
+ void SetIsWebstoreExtensionCallback(
+ const IsWebstoreExtensionCallback& callback);
+
protected:
// Cache the list of whitelisted entries from the field trial parameter.
void StoreWhitelistedEntries();
@@ -60,12 +72,41 @@ class UkmRecorderImpl : public UkmRecorder {
private:
friend ::metrics::UkmBrowserTest;
friend ::metrics::UkmEGTestHelper;
- friend ::ukm::debug::DebugPage;
+ friend ::ukm::debug::UkmDebugDataExtractor;
+
+ struct MetricAggregate {
+ uint64_t total_count = 0;
+ double value_sum = 0;
+ double value_square_sum = 0.0;
+ uint64_t dropped_due_to_limits = 0;
+ uint64_t dropped_due_to_sampling = 0;
+ };
+
+ struct EventAggregate {
+ EventAggregate();
+ ~EventAggregate();
+
+ base::flat_map<uint64_t, MetricAggregate> metrics;
+ uint64_t total_count = 0;
+ uint64_t dropped_due_to_limits = 0;
+ uint64_t dropped_due_to_sampling = 0;
+ };
+
+ using MetricAggregateMap = std::map<uint64_t, MetricAggregate>;
void AddEntry(mojom::UkmEntryPtr entry) override;
+ // Load sampling configurations from field-trial information.
+ void LoadExperimentSamplingInfo();
+
// Whether recording new data is currently allowed.
- bool recording_enabled_;
+ bool recording_enabled_ = false;
+
+ // Indicates whether recording is enabled for extensions.
+ bool extensions_enabled_ = false;
+
+ // Callback for checking extension IDs.
+ IsWebstoreExtensionCallback is_webstore_extension_callback_;
// Contains newly added sources and entries of UKM metrics which periodically
// get serialized and cleared by StoreRecordingsInReport().
@@ -75,6 +116,13 @@ class UkmRecorderImpl : public UkmRecorder {
// Whitelisted Entry hashes, only the ones in this set will be recorded.
std::set<uint64_t> whitelisted_entry_hashes_;
+ // Sampling configurations, loaded from a field-trial.
+ int default_sampling_rate_ = 0;
+ base::flat_map<uint64_t, int> event_sampling_rates_;
+
+ // Aggregate information for collected event metrics.
+ std::map<uint64_t, EventAggregate> event_aggregations_;
+
SEQUENCE_CHECKER(sequence_checker_);
};
diff --git a/chromium/components/ukm/ukm_reporting_service.cc b/chromium/components/ukm/ukm_reporting_service.cc
index 2ff266d6d9c..70bb4fc0fc6 100644
--- a/chromium/components/ukm/ukm_reporting_service.cc
+++ b/chromium/components/ukm/ukm_reporting_service.cc
@@ -6,6 +6,8 @@
#include "components/ukm/ukm_reporting_service.h"
+#include <memory>
+
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
@@ -59,7 +61,7 @@ void UkmReportingService::RegisterPrefs(PrefRegistrySimple* registry) {
UkmReportingService::UkmReportingService(metrics::MetricsServiceClient* client,
PrefService* local_state)
: ReportingService(client, local_state, kMaxLogRetransmitSize),
- persisted_logs_(base::MakeUnique<ukm::PersistedLogsMetricsImpl>(),
+ persisted_logs_(std::make_unique<ukm::PersistedLogsMetricsImpl>(),
local_state,
prefs::kUkmPersistedLogs,
kMinPersistedLogs,
diff --git a/chromium/components/ukm/ukm_service.h b/chromium/components/ukm/ukm_service.h
index 5c70a84256b..4c5b6807fc5 100644
--- a/chromium/components/ukm/ukm_service.h
+++ b/chromium/components/ukm/ukm_service.h
@@ -31,7 +31,7 @@ class UkmEGTestHelper;
namespace ukm {
namespace debug {
-class DebugPage;
+class UkmDebugDataExtractor;
}
// The URL-Keyed Metrics (UKM) service is responsible for gathering and
@@ -76,10 +76,12 @@ class UkmService : public UkmRecorderImpl {
// the provided PrefRegistry.
static void RegisterPrefs(PrefRegistrySimple* registry);
+ int32_t report_count() const { return report_count_; }
+
private:
friend ::metrics::UkmBrowserTest;
friend ::metrics::UkmEGTestHelper;
- friend ::ukm::debug::DebugPage;
+ friend ::ukm::debug::UkmDebugDataExtractor;
FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, AddEntryWithEmptyMetrics);
FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, EntryBuilderAndSerialization);
diff --git a/chromium/components/ukm/ukm_service_unittest.cc b/chromium/components/ukm/ukm_service_unittest.cc
index 2e507b8b6b8..6e92eb640fb 100644
--- a/chromium/components/ukm/ukm_service_unittest.cc
+++ b/chromium/components/ukm/ukm_service_unittest.cc
@@ -5,12 +5,15 @@
#include "components/ukm/ukm_service.h"
#include <map>
+#include <memory>
#include <string>
#include <utility>
+#include "base/bind.h"
#include "base/hash.h"
#include "base/metrics/metrics_hashes.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_simple_task_runner.h"
@@ -55,6 +58,10 @@ class TestRecordingHelper {
namespace {
+bool TestIsWebstoreExtension(base::StringPiece id) {
+ return (id == "bhcnanendmgjjeghamaccjnochlnhcgj");
+}
+
// TODO(rkaplow): consider making this a generic testing class in
// components/variations.
class ScopedUkmFeatureParams {
@@ -124,7 +131,7 @@ class UkmServiceTest : public testing::Test {
Report GetPersistedReport() {
EXPECT_GE(GetPersistedLogCount(), 1);
metrics::PersistedLogs result_persisted_logs(
- base::MakeUnique<ukm::PersistedLogsMetricsImpl>(), &prefs_,
+ std::make_unique<ukm::PersistedLogsMetricsImpl>(), &prefs_,
prefs::kUkmPersistedLogs,
3, // log count limit
1000, // byte limit
@@ -168,7 +175,7 @@ TEST_F(UkmServiceTest, EnableDisableSchedule) {
EXPECT_FALSE(task_runner_->HasPendingTask());
service.Initialize();
EXPECT_FALSE(task_runner_->HasPendingTask());
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
EXPECT_TRUE(task_runner_->HasPendingTask());
service.DisableReporting();
@@ -182,7 +189,7 @@ TEST_F(UkmServiceTest, PersistAndPurge) {
EXPECT_EQ(GetPersistedLogCount(), 0);
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
SourceId id = GetWhitelistedSourceId(0);
@@ -208,7 +215,7 @@ TEST_F(UkmServiceTest, SourceSerialization) {
EXPECT_EQ(GetPersistedLogCount(), 0);
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
ukm::SourceId id = GetWhitelistedSourceId(0);
@@ -235,7 +242,7 @@ TEST_F(UkmServiceTest, EntryBuilderAndSerialization) {
EXPECT_EQ(0, GetPersistedLogCount());
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
ukm::SourceId id = GetWhitelistedSourceId(0);
@@ -299,7 +306,7 @@ TEST_F(UkmServiceTest, AddEntryWithEmptyMetrics) {
EXPECT_EQ(0, GetPersistedLogCount());
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
ukm::SourceId id = GetWhitelistedSourceId(0);
@@ -326,7 +333,7 @@ TEST_F(UkmServiceTest, MetricsProviderTest) {
EXPECT_FALSE(provider->provide_system_profile_metrics_called());
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
ukm::SourceId id = GetWhitelistedSourceId(0);
@@ -347,13 +354,53 @@ TEST_F(UkmServiceTest, MetricsProviderTest) {
EXPECT_TRUE(provider->provide_system_profile_metrics_called());
}
+TEST_F(UkmServiceTest, LogsRotation) {
+ UkmService service(&prefs_, &client_);
+ TestRecordingHelper recorder(&service);
+ EXPECT_EQ(GetPersistedLogCount(), 0);
+ service.Initialize();
+ task_runner_->RunUntilIdle();
+ service.EnableRecording(/*extensions=*/false);
+ service.EnableReporting();
+
+ EXPECT_EQ(0, service.report_count());
+
+ // Log rotation should generate a log.
+ const ukm::SourceId id = GetWhitelistedSourceId(0);
+ recorder.UpdateSourceURL(id, GURL("https://google.com/foobar"));
+ task_runner_->RunPendingTasks();
+ EXPECT_EQ(1, service.report_count());
+ EXPECT_TRUE(client_.uploader()->is_uploading());
+
+ // Rotation shouldn't generate a log due to one being pending.
+ recorder.UpdateSourceURL(id, GURL("https://google.com/foobar"));
+ task_runner_->RunPendingTasks();
+ EXPECT_EQ(1, service.report_count());
+ EXPECT_TRUE(client_.uploader()->is_uploading());
+
+ // Completing the upload should clear pending log, then log rotation should
+ // generate another log.
+ client_.uploader()->CompleteUpload(200);
+ task_runner_->RunPendingTasks();
+ EXPECT_EQ(2, service.report_count());
+
+ // Check that rotations keep working.
+ for (int i = 3; i < 6; i++) {
+ task_runner_->RunPendingTasks();
+ client_.uploader()->CompleteUpload(200);
+ recorder.UpdateSourceURL(id, GURL("https://google.com/foobar"));
+ task_runner_->RunPendingTasks();
+ EXPECT_EQ(i, service.report_count());
+ }
+}
+
TEST_F(UkmServiceTest, LogsUploadedOnlyWhenHavingSourcesOrEntries) {
UkmService service(&prefs_, &client_);
TestRecordingHelper recorder(&service);
EXPECT_EQ(GetPersistedLogCount(), 0);
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
EXPECT_TRUE(task_runner_->HasPendingTask());
@@ -414,7 +461,7 @@ TEST_F(UkmServiceTest, RecordInitialUrl) {
EXPECT_EQ(GetPersistedLogCount(), 0);
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
ukm::SourceId id = GetWhitelistedSourceId(0);
@@ -453,7 +500,7 @@ TEST_F(UkmServiceTest, RestrictToWhitelistedSourceIds) {
EXPECT_EQ(GetPersistedLogCount(), 0);
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
ukm::SourceId id1 = GetWhitelistedSourceId(0);
@@ -495,7 +542,7 @@ TEST_F(UkmServiceTest, RecordSessionId) {
EXPECT_EQ(0, GetPersistedLogCount());
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
auto id = GetWhitelistedSourceId(0);
@@ -521,7 +568,7 @@ TEST_F(UkmServiceTest, SourceSize) {
EXPECT_EQ(0, GetPersistedLogCount());
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
auto id = GetWhitelistedSourceId(0);
@@ -546,7 +593,7 @@ TEST_F(UkmServiceTest, PurgeMidUpload) {
EXPECT_EQ(GetPersistedLogCount(), 0);
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
auto id = GetWhitelistedSourceId(0);
recorder.UpdateSourceURL(id, GURL("https://google.com/foobar1"));
@@ -573,7 +620,7 @@ TEST_F(UkmServiceTest, WhitelistEntryTest) {
EXPECT_EQ(0, GetPersistedLogCount());
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
auto id = GetWhitelistedSourceId(0);
@@ -619,7 +666,7 @@ TEST_F(UkmServiceTest, SourceURLLength) {
EXPECT_EQ(0, GetPersistedLogCount());
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
auto id = GetWhitelistedSourceId(0);
@@ -654,7 +701,7 @@ TEST_F(UkmServiceTest, UnreferencedNonWhitelistedSources) {
EXPECT_EQ(0, GetPersistedLogCount());
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
std::vector<SourceId> ids;
@@ -720,7 +767,65 @@ TEST_F(UkmServiceTest, UnreferencedNonWhitelistedSources) {
}
}
-TEST_F(UkmServiceTest, UnsupportedSchemes) {
+TEST_F(UkmServiceTest, SupportedSchemes) {
+ struct {
+ const char* url;
+ bool expected_kept;
+ } test_cases[] = {
+ {"http://google.ca/", true},
+ {"https://google.ca/", true},
+ {"ftp://google.ca/", true},
+ {"about:blank", true},
+ {"chrome://version/", true},
+ // chrome-extension are controlled by TestIsWebstoreExtension, above.
+ {"chrome-extension://bhcnanendmgjjeghamaccjnochlnhcgj/", true},
+ {"chrome-extension://abcdefghijklmnopqrstuvwxyzabcdef/", false},
+ {"file:///tmp/", false},
+ {"abc://google.ca/", false},
+ {"www.google.ca/", false},
+ };
+
+ base::FieldTrialList field_trial_list(nullptr /* entropy_provider */);
+ ScopedUkmFeatureParams params(base::FeatureList::OVERRIDE_ENABLE_FEATURE, {});
+ UkmService service(&prefs_, &client_);
+ TestRecordingHelper recorder(&service);
+ service.SetIsWebstoreExtensionCallback(
+ base::BindRepeating(&TestIsWebstoreExtension));
+
+ EXPECT_EQ(GetPersistedLogCount(), 0);
+ service.Initialize();
+ task_runner_->RunUntilIdle();
+ service.EnableRecording(/*extensions=*/true);
+ service.EnableReporting();
+
+ int64_t id_counter = 1;
+ int expected_kept_count = 0;
+ for (const auto& test : test_cases) {
+ auto source_id = GetWhitelistedSourceId(id_counter++);
+ recorder.UpdateSourceURL(source_id, GURL(test.url));
+ recorder.GetEntryBuilder(source_id, "FakeEntry");
+ if (test.expected_kept)
+ ++expected_kept_count;
+ }
+
+ service.Flush();
+ EXPECT_EQ(GetPersistedLogCount(), 1);
+ Report proto_report = GetPersistedReport();
+
+ EXPECT_EQ(expected_kept_count, proto_report.sources_size());
+ for (const auto& test : test_cases) {
+ bool found = false;
+ for (int i = 0; i < proto_report.sources_size(); ++i) {
+ if (proto_report.sources(i).url() == test.url) {
+ found = true;
+ break;
+ }
+ }
+ EXPECT_EQ(test.expected_kept, found) << test.url;
+ }
+}
+
+TEST_F(UkmServiceTest, SupportedSchemesNoExtensions) {
struct {
const char* url;
bool expected_kept;
@@ -730,8 +835,9 @@ TEST_F(UkmServiceTest, UnsupportedSchemes) {
{"ftp://google.ca/", true},
{"about:blank", true},
{"chrome://version/", true},
+ {"chrome-extension://bhcnanendmgjjeghamaccjnochlnhcgj/", false},
+ {"chrome-extension://abcdefghijklmnopqrstuvwxyzabcdef/", false},
{"file:///tmp/", false},
- {"chrome-extension://bhcnanendmgjjeghamaccjnochlnhcgj", false},
{"abc://google.ca/", false},
{"www.google.ca/", false},
};
@@ -744,7 +850,7 @@ TEST_F(UkmServiceTest, UnsupportedSchemes) {
EXPECT_EQ(GetPersistedLogCount(), 0);
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
int64_t id_counter = 1;
@@ -780,7 +886,7 @@ TEST_F(UkmServiceTest, SanitizeUrlAuthParams) {
EXPECT_EQ(0, GetPersistedLogCount());
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
auto id = GetWhitelistedSourceId(0);
@@ -816,7 +922,7 @@ TEST_F(UkmServiceTest, SanitizeChromeUrlParams) {
EXPECT_EQ(0, GetPersistedLogCount());
service.Initialize();
task_runner_->RunUntilIdle();
- service.EnableRecording();
+ service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
auto id = GetWhitelistedSourceId(0);
diff --git a/chromium/components/undo/undo_manager_test.cc b/chromium/components/undo/undo_manager_test.cc
index 70e50f08dfa..deaf4632ad9 100644
--- a/chromium/components/undo/undo_manager_test.cc
+++ b/chromium/components/undo/undo_manager_test.cc
@@ -4,9 +4,10 @@
#include "components/undo/undo_manager.h"
+#include <memory>
+
#include "base/auto_reset.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "components/undo/undo_manager_observer.h"
#include "components/undo/undo_operation.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -138,7 +139,7 @@ void TestUndoService::Redo() {
}
void TestUndoService::TriggerOperation() {
- undo_manager_.AddUndoOperation(base::MakeUnique<TestUndoOperation>(this));
+ undo_manager_.AddUndoOperation(std::make_unique<TestUndoOperation>(this));
}
void TestUndoService::RecordUndoCall() {
diff --git a/chromium/components/unzip_service/BUILD.gn b/chromium/components/unzip_service/BUILD.gn
new file mode 100644
index 00000000000..ea7e53fdc81
--- /dev/null
+++ b/chromium/components/unzip_service/BUILD.gn
@@ -0,0 +1,32 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//services/service_manager/public/cpp/service.gni")
+import("//services/service_manager/public/service_manifest.gni")
+
+source_set("lib") {
+ sources = [
+ "unzip_service.cc",
+ "unzip_service.h",
+ "unzipper_impl.cc",
+ "unzipper_impl.h",
+ ]
+
+ deps = [
+ "//base",
+ "//mojo/public/cpp/bindings",
+ "//third_party/zlib/google:zip",
+ ]
+
+ public_deps = [
+ "//components/filesystem/public/interfaces",
+ "//components/unzip_service/public/interfaces",
+ "//services/service_manager/public/cpp",
+ ]
+}
+
+service_manifest("manifest") {
+ name = "unzip_service"
+ source = "manifest.json"
+}
diff --git a/chromium/components/unzip_service/DEPS b/chromium/components/unzip_service/DEPS
new file mode 100644
index 00000000000..116747aae75
--- /dev/null
+++ b/chromium/components/unzip_service/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+ "+components/filesystem",
+ "+mojo/public",
+ "+services/service_manager/public",
+ "+third_party/zlib/google",
+]
diff --git a/chromium/components/unzip_service/OWNERS b/chromium/components/unzip_service/OWNERS
new file mode 100644
index 00000000000..bd74fe691c3
--- /dev/null
+++ b/chromium/components/unzip_service/OWNERS
@@ -0,0 +1,4 @@
+sorin@chromium.org
+waffles@chromium.org
+per-file manifest.json=set noparent
+per-file manifest.json=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/unzip_service/manifest.json b/chromium/components/unzip_service/manifest.json
new file mode 100644
index 00000000000..b21cb3767e7
--- /dev/null
+++ b/chromium/components/unzip_service/manifest.json
@@ -0,0 +1,15 @@
+{
+ "name": "unzip_service",
+ "display_name": "Unzip Service",
+ "sandbox_type": "utility",
+ "interface_provider_specs": {
+ "service_manager:connector": {
+ "provides": {
+ "unzip_file": [ "unzip::mojom::Unzipper" ]
+ },
+ "requires": {
+ "service_manager": [ "service_manager:all_users" ]
+ }
+ }
+ }
+}
diff --git a/chromium/components/unzip_service/public/cpp/BUILD.gn b/chromium/components/unzip_service/public/cpp/BUILD.gn
new file mode 100644
index 00000000000..83bc8ae5d06
--- /dev/null
+++ b/chromium/components/unzip_service/public/cpp/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+source_set("cpp") {
+ sources = [
+ "unzip.cc",
+ "unzip.h",
+ ]
+
+ public_deps = [
+ "//components/filesystem:lib",
+ "//components/unzip_service/public/interfaces",
+ "//services/service_manager/public/cpp",
+ ]
+}
diff --git a/chromium/components/unzip_service/public/cpp/unzip.cc b/chromium/components/unzip_service/public/cpp/unzip.cc
new file mode 100644
index 00000000000..f30e8c6a54b
--- /dev/null
+++ b/chromium/components/unzip_service/public/cpp/unzip.cc
@@ -0,0 +1,94 @@
+// 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/unzip_service/public/cpp/unzip.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/string16.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/filesystem/directory_impl.h"
+#include "components/filesystem/lock_table.h"
+#include "components/unzip_service/public/interfaces/constants.mojom.h"
+#include "components/unzip_service/public/interfaces/unzipper.mojom.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace unzip {
+
+namespace {
+
+class UnzipParams : public base::RefCounted<UnzipParams> {
+ public:
+ UnzipParams(mojom::UnzipperPtr unzipper, UnzipCallback callback)
+ : unzipper_(std::move(unzipper)), callback_(std::move(callback)) {}
+
+ mojom::UnzipperPtr* unzipper() { return &unzipper_; }
+
+ UnzipCallback TakeCallback() { return std::move(callback_); }
+
+ private:
+ friend class base::RefCounted<UnzipParams>;
+
+ ~UnzipParams() = default;
+
+ // The UnzipperPtr is stored so it does not get deleted before the callback
+ // runs.
+ mojom::UnzipperPtr unzipper_;
+
+ UnzipCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(UnzipParams);
+};
+
+void UnzipDone(scoped_refptr<UnzipParams> params, bool success) {
+ UnzipCallback cb = params->TakeCallback();
+ if (!cb.is_null())
+ std::move(cb).Run(success);
+}
+
+} // namespace
+
+void Unzip(service_manager::Connector* connector,
+ const base::FilePath& zip_path,
+ const base::FilePath& output_dir,
+ UnzipCallback callback) {
+ DCHECK(!callback.is_null());
+
+ base::File zip_file(zip_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+
+ if (!zip_file.IsValid()) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), false));
+ return;
+ }
+
+ filesystem::mojom::DirectoryPtr directory_ptr;
+ mojo::MakeStrongBinding(
+ std::make_unique<filesystem::DirectoryImpl>(output_dir, nullptr, nullptr),
+ mojo::MakeRequest(&directory_ptr));
+
+ mojom::UnzipperPtr unzipper;
+ connector->BindInterface(mojom::kServiceName, mojo::MakeRequest(&unzipper));
+
+ // |callback| is shared between the connection error handler and the Unzip
+ // call using a refcounted UnzipParams object that owns |callback|.
+ auto unzip_params = base::MakeRefCounted<UnzipParams>(std::move(unzipper),
+ std::move(callback));
+
+ unzip_params->unzipper()->set_connection_error_handler(
+ base::BindRepeating(&UnzipDone, unzip_params, false));
+ (*unzip_params->unzipper())
+ ->Unzip(std::move(zip_file), std::move(directory_ptr),
+ base::BindOnce(&UnzipDone, unzip_params));
+}
+
+} // namespace unzip
diff --git a/chromium/components/unzip_service/public/cpp/unzip.h b/chromium/components/unzip_service/public/cpp/unzip.h
new file mode 100644
index 00000000000..14b4b1f0d51
--- /dev/null
+++ b/chromium/components/unzip_service/public/cpp/unzip.h
@@ -0,0 +1,30 @@
+// 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_UNZIP_SERVICE_PUBLIC_CPP_UNZIP_H_
+#define COMPONENTS_UNZIP_SERVICE_PUBLIC_CPP_UNZIP_H_
+
+#include "base/callback_forward.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace service_manager {
+class Connector;
+}
+
+namespace unzip {
+
+// Unzips |zip_file| into |output_dir|.
+using UnzipCallback = base::OnceCallback<void(bool result)>;
+// TODO(waffles): Unzip can only be called on blockable threads (never UI).
+void Unzip(service_manager::Connector* connector,
+ const base::FilePath& zip_file,
+ const base::FilePath& output_dir,
+ UnzipCallback result_callback);
+
+} // namespace unzip
+
+#endif // COMPONENTS_UNZIP_SERVICE_PUBLIC_CPP_UNZIP_H_
diff --git a/chromium/components/unzip_service/public/interfaces/BUILD.gn b/chromium/components/unzip_service/public/interfaces/BUILD.gn
new file mode 100644
index 00000000000..d048a5895e8
--- /dev/null
+++ b/chromium/components/unzip_service/public/interfaces/BUILD.gn
@@ -0,0 +1,23 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("interfaces") {
+ sources = [
+ "unzipper.mojom",
+ ]
+
+ public_deps = [
+ ":constants",
+ "//components/filesystem/public/interfaces",
+ "//mojo/common:common_custom_types",
+ ]
+}
+
+mojom("constants") {
+ sources = [
+ "constants.mojom",
+ ]
+}
diff --git a/chromium/components/unzip_service/public/interfaces/OWNERS b/chromium/components/unzip_service/public/interfaces/OWNERS
new file mode 100644
index 00000000000..08850f42120
--- /dev/null
+++ b/chromium/components/unzip_service/public/interfaces/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/unzip_service/public/interfaces/README.md b/chromium/components/unzip_service/public/interfaces/README.md
new file mode 100644
index 00000000000..2c3d6a091ba
--- /dev/null
+++ b/chromium/components/unzip_service/public/interfaces/README.md
@@ -0,0 +1 @@
+Mojo service that exposes an interface that can be used to unzip ZIP files.
diff --git a/chromium/components/unzip_service/public/interfaces/constants.mojom b/chromium/components/unzip_service/public/interfaces/constants.mojom
new file mode 100644
index 00000000000..6cf09d156b6
--- /dev/null
+++ b/chromium/components/unzip_service/public/interfaces/constants.mojom
@@ -0,0 +1,7 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module unzip.mojom;
+
+const string kServiceName = "unzip_service";
diff --git a/chromium/components/unzip_service/public/interfaces/unzipper.mojom b/chromium/components/unzip_service/public/interfaces/unzipper.mojom
new file mode 100644
index 00000000000..19e21533567
--- /dev/null
+++ b/chromium/components/unzip_service/public/interfaces/unzipper.mojom
@@ -0,0 +1,15 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module unzip.mojom;
+
+import "mojo/common/file.mojom";
+import "components/filesystem/public/interfaces/directory.mojom";
+
+interface Unzipper {
+ // Unzip |zip_file| into |output_dir|.
+ // Returns true on success, false otherwise.
+ Unzip(mojo.common.mojom.File zip_file, filesystem.mojom.Directory output_dir)
+ => (bool result);
+};
diff --git a/chromium/components/unzip_service/unzip_service.cc b/chromium/components/unzip_service/unzip_service.cc
new file mode 100644
index 00000000000..dc38d52fc42
--- /dev/null
+++ b/chromium/components/unzip_service/unzip_service.cc
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/unzip_service/unzip_service.h"
+
+#include "build/build_config.h"
+#include "components/unzip_service/unzipper_impl.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace unzip {
+
+namespace {
+
+void OnUnzipRequest(service_manager::ServiceContextRefFactory* ref_factory,
+ unzip::mojom::UnzipperRequest request) {
+ mojo::MakeStrongBinding(
+ std::make_unique<UnzipperImpl>(ref_factory->CreateRef()),
+ std::move(request));
+}
+
+} // namespace
+
+UnzipService::UnzipService() = default;
+
+UnzipService::~UnzipService() = default;
+
+std::unique_ptr<service_manager::Service> UnzipService::CreateService() {
+ return std::make_unique<UnzipService>();
+}
+
+void UnzipService::OnStart() {
+ ref_factory_ = std::make_unique<service_manager::ServiceContextRefFactory>(
+ context()->CreateQuitClosure());
+ registry_.AddInterface(
+ base::BindRepeating(&OnUnzipRequest, ref_factory_.get()));
+}
+
+void UnzipService::OnBindInterface(
+ const service_manager::BindSourceInfo& source_info,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle interface_pipe) {
+ registry_.BindInterface(interface_name, std::move(interface_pipe));
+}
+
+} // namespace unzip
diff --git a/chromium/components/unzip_service/unzip_service.h b/chromium/components/unzip_service/unzip_service.h
new file mode 100644
index 00000000000..bca9f89ad95
--- /dev/null
+++ b/chromium/components/unzip_service/unzip_service.h
@@ -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.
+
+#ifndef COMPONENTS_UNZIP_SERVICE_UNZIP_SERVICE_H_
+#define COMPONENTS_UNZIP_SERVICE_UNZIP_SERVICE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+#include "services/service_manager/public/cpp/service_context.h"
+#include "services/service_manager/public/cpp/service_context_ref.h"
+
+namespace unzip {
+
+class UnzipService : public service_manager::Service {
+ public:
+ UnzipService();
+ ~UnzipService() override;
+ // Factory method for creating the service.
+ static std::unique_ptr<service_manager::Service> CreateService();
+ // Lifescycle events that occur after the service has started to spinup.
+ void OnStart() override;
+ void OnBindInterface(const service_manager::BindSourceInfo& source_info,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle interface_pipe) override;
+
+ private:
+ // State needed to manage service lifecycle and lifecycle of bound clients.
+ std::unique_ptr<service_manager::ServiceContextRefFactory> ref_factory_;
+ service_manager::BinderRegistry registry_;
+ DISALLOW_COPY_AND_ASSIGN(UnzipService);
+};
+
+} // namespace unzip
+
+#endif // COMPONENTS_UNZIP_SERVICE_UNZIP_SERVICE_H_
diff --git a/chromium/components/unzip_service/unzipper_impl.cc b/chromium/components/unzip_service/unzipper_impl.cc
new file mode 100644
index 00000000000..09001109643
--- /dev/null
+++ b/chromium/components/unzip_service/unzipper_impl.cc
@@ -0,0 +1,107 @@
+// 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/unzip_service/unzipper_impl.h"
+
+#include "base/compiler_specific.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "third_party/zlib/google/zip.h"
+#include "third_party/zlib/google/zip_reader.h"
+
+namespace unzip {
+
+namespace {
+
+// A writer delegate that reports errors instead of writing.
+class DudWriterDelegate : public zip::WriterDelegate {
+ public:
+ DudWriterDelegate() {}
+ ~DudWriterDelegate() override {}
+
+ // WriterDelegate methods:
+ bool PrepareOutput() override { return false; }
+ bool WriteBytes(const char* data, int num_bytes) override { return false; }
+ void SetTimeModified(const base::Time& time) override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DudWriterDelegate);
+};
+
+std::string PathToMojoString(const base::FilePath& path) {
+#if defined(OS_WIN)
+ return base::WideToUTF8(path.value());
+#else
+ return path.value();
+#endif
+}
+
+// Modifies output_dir to point to the final directory.
+bool CreateDirectory(filesystem::mojom::DirectoryPtr* output_dir,
+ const base::FilePath& path) {
+ filesystem::mojom::FileError err = filesystem::mojom::FileError::OK;
+ return (*output_dir)
+ ->OpenDirectory(PathToMojoString(path), nullptr,
+ filesystem::mojom::kFlagOpenAlways, &err) &&
+ err == filesystem::mojom::FileError::OK;
+}
+
+std::unique_ptr<zip::WriterDelegate> MakeFileWriterDelegateNoParent(
+ filesystem::mojom::DirectoryPtr* output_dir,
+ const base::FilePath& path) {
+ auto file = std::make_unique<base::File>();
+ filesystem::mojom::FileError err;
+ if (!(*output_dir)
+ ->OpenFileHandle(PathToMojoString(path),
+ filesystem::mojom::kFlagCreate |
+ filesystem::mojom::kFlagWrite |
+ filesystem::mojom::kFlagWriteAttributes,
+ &err, file.get()) ||
+ err != filesystem::mojom::FileError::OK) {
+ return std::make_unique<DudWriterDelegate>();
+ }
+ return std::make_unique<zip::FileWriterDelegate>(std::move(file));
+}
+
+std::unique_ptr<zip::WriterDelegate> MakeFileWriterDelegate(
+ filesystem::mojom::DirectoryPtr* output_dir,
+ const base::FilePath& path) {
+ if (path == path.BaseName())
+ return MakeFileWriterDelegateNoParent(output_dir, path);
+ filesystem::mojom::DirectoryPtr parent;
+ filesystem::mojom::FileError err;
+ if (!(*output_dir)
+ ->OpenDirectory(PathToMojoString(path.DirName()),
+ mojo::MakeRequest(&parent),
+ filesystem::mojom::kFlagOpenAlways, &err) ||
+ err != filesystem::mojom::FileError::OK) {
+ return std::make_unique<DudWriterDelegate>();
+ }
+ return MakeFileWriterDelegateNoParent(&parent, path.BaseName());
+}
+
+bool FilterNoFiles(const base::FilePath& unused) {
+ return true;
+}
+
+} // namespace
+
+UnzipperImpl::UnzipperImpl(
+ std::unique_ptr<service_manager::ServiceContextRef> service_ref)
+ : service_ref_(std::move(service_ref)) {}
+
+UnzipperImpl::~UnzipperImpl() = default;
+
+void UnzipperImpl::Unzip(base::File zip_file,
+ filesystem::mojom::DirectoryPtr output_dir,
+ UnzipCallback callback) {
+ DCHECK(zip_file.IsValid());
+ std::move(callback).Run(zip::UnzipWithFilterAndWriters(
+ zip_file.GetPlatformFile(),
+ base::BindRepeating(&MakeFileWriterDelegate, &output_dir),
+ base::BindRepeating(&CreateDirectory, &output_dir),
+ base::BindRepeating(&FilterNoFiles), false));
+}
+
+} // namespace unzip
diff --git a/chromium/components/unzip_service/unzipper_impl.h b/chromium/components/unzip_service/unzipper_impl.h
new file mode 100644
index 00000000000..6bb6d342112
--- /dev/null
+++ b/chromium/components/unzip_service/unzipper_impl.h
@@ -0,0 +1,36 @@
+// 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_UNZIP_SERVICE_UNZIPPER_IMPL_H_
+#define COMPONENTS_UNZIP_SERVICE_UNZIPPER_IMPL_H_
+
+#include <memory>
+
+#include "base/files/file.h"
+#include "base/macros.h"
+#include "components/unzip_service/public/interfaces/unzipper.mojom.h"
+#include "services/service_manager/public/cpp/service_context_ref.h"
+
+namespace unzip {
+
+class UnzipperImpl : public mojom::Unzipper {
+ public:
+ explicit UnzipperImpl(
+ std::unique_ptr<service_manager::ServiceContextRef> service_ref);
+ ~UnzipperImpl() override;
+
+ private:
+ // unzip::mojom::Unzipper:
+ void Unzip(base::File zip_file,
+ filesystem::mojom::DirectoryPtr output_dir,
+ UnzipCallback callback) override;
+
+ const std::unique_ptr<service_manager::ServiceContextRef> service_ref_;
+
+ DISALLOW_COPY_AND_ASSIGN(UnzipperImpl);
+};
+
+} // namespace unzip
+
+#endif // COMPONENTS_UNZIP_SERVICE_UNZIPPER_IMPL_H_
diff --git a/chromium/components/update_client/BUILD.gn b/chromium/components/update_client/BUILD.gn
index 675c7be083c..b162617473d 100644
--- a/chromium/components/update_client/BUILD.gn
+++ b/chromium/components/update_client/BUILD.gn
@@ -69,12 +69,12 @@ static_library("update_client") {
"//components/data_use_measurement/core",
"//components/patch_service/public/cpp",
"//components/prefs",
+ "//components/unzip_service/public/cpp",
"//components/version_info:version_info",
"//courgette:courgette_lib",
"//crypto",
"//net",
"//third_party/libxml",
- "//third_party/zlib/google:zip",
"//url",
]
libs = []
@@ -97,12 +97,17 @@ static_library("test_support") {
public_deps = [
":update_client",
]
+
deps = [
"//base",
"//components/patch_service:lib",
"//components/prefs",
+ "//components/unzip_service:lib",
+ "//mojo/public/cpp/bindings",
"//net:test_support",
+ "//services/service_manager/public/cpp",
"//services/service_manager/public/cpp/test:test_support",
+ "//services/service_manager/public/mojom",
"//testing/gmock",
"//testing/gtest",
"//url",
diff --git a/chromium/components/update_client/DEPS b/chromium/components/update_client/DEPS
index 30e7de9951f..64005e1a2da 100644
--- a/chromium/components/update_client/DEPS
+++ b/chromium/components/update_client/DEPS
@@ -4,10 +4,12 @@ include_rules = [
"+components/data_use_measurement/core",
"+components/patch_service",
"+components/prefs",
+ "+components/unzip_service",
"+components/version_info",
"+courgette",
"+crypto",
"+libxml",
+ "+mojo",
"+net",
"+services/service_manager/public",
"+third_party/libxml",
diff --git a/chromium/components/update_client/action_runner.cc b/chromium/components/update_client/action_runner.cc
index e357a115c6b..ded657e532f 100644
--- a/chromium/components/update_client/action_runner.cc
+++ b/chromium/components/update_client/action_runner.cc
@@ -14,10 +14,12 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/task_scheduler/post_task.h"
+#include "build/build_config.h"
#include "components/update_client/component.h"
#include "components/update_client/configurator.h"
#include "components/update_client/task_traits.h"
#include "components/update_client/update_client.h"
+#include "components/update_client/update_engine.h"
namespace update_client {
@@ -35,11 +37,14 @@ void ActionRunner::Run(Callback run_complete) {
run_complete_ = std::move(run_complete);
base::CreateSequencedTaskRunnerWithTraits(kTaskTraits)
- ->PostTask(FROM_HERE,
- base::BindOnce(&ActionRunner::Unpack, base::Unretained(this)));
+ ->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ActionRunner::Unpack, base::Unretained(this),
+ component_.config()->CreateServiceManagerConnector()));
}
-void ActionRunner::Unpack() {
+void ActionRunner::Unpack(
+ std::unique_ptr<service_manager::Connector> connector) {
const auto& installer = component_.crx_component().installer;
base::FilePath file_path;
@@ -47,8 +52,8 @@ void ActionRunner::Unpack() {
// Contains the key hash of the CRX this object is allowed to run.
const auto key_hash = component_.config()->GetRunActionKeyHash();
- auto unpacker = base::MakeRefCounted<ComponentUnpacker>(key_hash, file_path,
- installer, nullptr);
+ auto unpacker = base::MakeRefCounted<ComponentUnpacker>(
+ key_hash, file_path, installer, std::move(connector));
unpacker->Unpack(
base::BindOnce(&ActionRunner::UnpackComplete, base::Unretained(this)));
}
diff --git a/chromium/components/update_client/action_runner.h b/chromium/components/update_client/action_runner.h
index 877d9c245f1..b63571c3174 100644
--- a/chromium/components/update_client/action_runner.h
+++ b/chromium/components/update_client/action_runner.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <memory>
#include <utility>
#include <vector>
@@ -38,7 +39,7 @@ class ActionRunner {
void Run(Callback run_complete);
private:
- void Unpack();
+ void Unpack(std::unique_ptr<service_manager::Connector> connector);
void UnpackComplete(const ComponentUnpacker::Result& result);
void RunCommand(const base::CommandLine& cmdline);
diff --git a/chromium/components/update_client/component.cc b/chromium/components/update_client/component.cc
index e6fb57109c9..dfe50d2c322 100644
--- a/chromium/components/update_client/component.cc
+++ b/chromium/components/update_client/component.cc
@@ -66,15 +66,14 @@ using InstallOnBlockingTaskRunnerCompleteCallback = base::OnceCallback<
void(int error_category, int error_code, int extra_code1)>;
void InstallComplete(
- const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
InstallOnBlockingTaskRunnerCompleteCallback callback,
const base::FilePath& unpack_path,
const CrxInstaller::Result& result) {
base::PostTaskWithTraits(
FROM_HERE, {base::TaskPriority::BACKGROUND, base::MayBlock()},
base::BindOnce(
- [](const scoped_refptr<base::SingleThreadTaskRunner>&
- main_task_runner,
+ [](scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
InstallOnBlockingTaskRunnerCompleteCallback callback,
const base::FilePath& unpack_path,
const CrxInstaller::Result& result) {
@@ -92,11 +91,11 @@ void InstallComplete(
}
void InstallOnBlockingTaskRunner(
- const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
const base::FilePath& unpack_path,
const std::string& public_key,
const std::string& fingerprint,
- const scoped_refptr<CrxInstaller>& installer,
+ scoped_refptr<CrxInstaller> installer,
InstallOnBlockingTaskRunnerCompleteCallback callback) {
DCHECK(base::DirectoryExists(unpack_path));
@@ -124,10 +123,10 @@ void InstallOnBlockingTaskRunner(
}
void UnpackCompleteOnBlockingTaskRunner(
- const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
const base::FilePath& crx_path,
const std::string& fingerprint,
- const scoped_refptr<CrxInstaller>& installer,
+ scoped_refptr<CrxInstaller> installer,
InstallOnBlockingTaskRunnerCompleteCallback callback,
const ComponentUnpacker::Result& result) {
update_client::DeleteFileAndEmptyParentDirectory(crx_path);
@@ -149,11 +148,11 @@ void UnpackCompleteOnBlockingTaskRunner(
}
void StartInstallOnBlockingTaskRunner(
- const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
const std::vector<uint8_t>& pk_hash,
const base::FilePath& crx_path,
const std::string& fingerprint,
- const scoped_refptr<CrxInstaller>& installer,
+ scoped_refptr<CrxInstaller> installer,
std::unique_ptr<service_manager::Connector> connector,
InstallOnBlockingTaskRunnerCompleteCallback callback) {
auto unpacker = base::MakeRefCounted<ComponentUnpacker>(
@@ -177,6 +176,10 @@ scoped_refptr<Configurator> Component::config() const {
return update_context_.config;
}
+std::string Component::session_id() const {
+ return update_context_.session_id;
+}
+
void Component::Handle(CallbackHandleComplete callback) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(state_);
@@ -311,8 +314,7 @@ void Component::State::TransitionState(std::unique_ptr<State> next_state) {
is_final_ = true;
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(callback_), base::Passed(&next_state)));
+ FROM_HERE, base::BindOnce(std::move(callback_), std::move(next_state)));
}
Component::StateNew::StateNew(Component* component)
@@ -393,7 +395,7 @@ void Component::StateUpdateError::DoHandle() {
component.AppendEvent(BuildUpdateCompleteEventElement(component));
TransitionState(nullptr);
- component.NotifyObservers(Events::COMPONENT_NOT_UPDATED);
+ component.NotifyObservers(Events::COMPONENT_UPDATE_ERROR);
}
Component::StateCanUpdate::StateCanUpdate(Component* component)
@@ -615,7 +617,7 @@ void Component::StateUpdatingDiff::DoHandle() {
base::ThreadTaskRunnerHandle::Get(),
component.crx_component_.pk_hash, component.crx_path_,
component.next_fp_, component.crx_component_.installer,
- base::Passed(&connector),
+ std::move(connector),
base::BindOnce(&Component::StateUpdatingDiff::InstallComplete,
base::Unretained(this))));
}
@@ -678,7 +680,7 @@ void Component::StateUpdating::DoHandle() {
base::ThreadTaskRunnerHandle::Get(),
component.crx_component_.pk_hash, component.crx_path_,
component.next_fp_, component.crx_component_.installer,
- base::Passed(&connector),
+ std::move(connector),
base::BindOnce(&Component::StateUpdating::InstallComplete,
base::Unretained(this))));
}
diff --git a/chromium/components/update_client/component.h b/chromium/components/update_client/component.h
index e577a8e7bc9..d44e39a7833 100644
--- a/chromium/components/update_client/component.h
+++ b/chromium/components/update_client/component.h
@@ -122,6 +122,8 @@ class Component {
scoped_refptr<Configurator> config() const;
+ std::string session_id() const;
+
private:
friend class FakePingManagerImpl;
friend class UpdateCheckerTest;
diff --git a/chromium/components/update_client/component_patcher_operation.cc b/chromium/components/update_client/component_patcher_operation.cc
index 99906e495ad..cc36bb36ea6 100644
--- a/chromium/components/update_client/component_patcher_operation.cc
+++ b/chromium/components/update_client/component_patcher_operation.cc
@@ -62,7 +62,7 @@ DeltaUpdateOp::~DeltaUpdateOp() {
void DeltaUpdateOp::Run(const base::DictionaryValue* command_args,
const base::FilePath& input_dir,
const base::FilePath& unpack_dir,
- const scoped_refptr<CrxInstaller>& installer,
+ scoped_refptr<CrxInstaller> installer,
ComponentPatcher::Callback callback) {
callback_ = std::move(callback);
std::string output_rel_path;
@@ -117,7 +117,7 @@ DeltaUpdateOpCopy::~DeltaUpdateOpCopy() {
UnpackerError DeltaUpdateOpCopy::DoParseArguments(
const base::DictionaryValue* command_args,
const base::FilePath& input_dir,
- const scoped_refptr<CrxInstaller>& installer) {
+ scoped_refptr<CrxInstaller> installer) {
std::string input_rel_path;
if (!command_args->GetString(kInput, &input_rel_path))
return UnpackerError::kDeltaBadCommands;
@@ -144,7 +144,7 @@ DeltaUpdateOpCreate::~DeltaUpdateOpCreate() {
UnpackerError DeltaUpdateOpCreate::DoParseArguments(
const base::DictionaryValue* command_args,
const base::FilePath& input_dir,
- const scoped_refptr<CrxInstaller>& installer) {
+ scoped_refptr<CrxInstaller> installer) {
std::string patch_rel_path;
if (!command_args->GetString(kPatch, &patch_rel_path))
return UnpackerError::kDeltaBadCommands;
@@ -174,7 +174,7 @@ DeltaUpdateOpPatch::~DeltaUpdateOpPatch() {
UnpackerError DeltaUpdateOpPatch::DoParseArguments(
const base::DictionaryValue* command_args,
const base::FilePath& input_dir,
- const scoped_refptr<CrxInstaller>& installer) {
+ scoped_refptr<CrxInstaller> installer) {
std::string patch_rel_path;
std::string input_rel_path;
if (!command_args->GetString(kPatch, &patch_rel_path) ||
@@ -193,8 +193,8 @@ UnpackerError DeltaUpdateOpPatch::DoParseArguments(
void DeltaUpdateOpPatch::DoRun(ComponentPatcher::Callback callback) {
patch::Patch(connector_, operation_, input_abs_path_, patch_abs_path_,
output_abs_path_,
- base::Bind(&DeltaUpdateOpPatch::DonePatching, this,
- base::Passed(&callback)));
+ base::BindOnce(&DeltaUpdateOpPatch::DonePatching, this,
+ std::move(callback)));
}
void DeltaUpdateOpPatch::DonePatching(ComponentPatcher::Callback callback,
diff --git a/chromium/components/update_client/component_patcher_operation.h b/chromium/components/update_client/component_patcher_operation.h
index 1f99ca17228..61fd40f3df6 100644
--- a/chromium/components/update_client/component_patcher_operation.h
+++ b/chromium/components/update_client/component_patcher_operation.h
@@ -42,7 +42,7 @@ class DeltaUpdateOp : public base::RefCountedThreadSafe<DeltaUpdateOp> {
void Run(const base::DictionaryValue* command_args,
const base::FilePath& input_dir,
const base::FilePath& unpack_dir,
- const scoped_refptr<CrxInstaller>& installer,
+ scoped_refptr<CrxInstaller> installer,
ComponentPatcher::Callback callback);
protected:
@@ -62,7 +62,7 @@ class DeltaUpdateOp : public base::RefCountedThreadSafe<DeltaUpdateOp> {
virtual UnpackerError DoParseArguments(
const base::DictionaryValue* command_args,
const base::FilePath& input_dir,
- const scoped_refptr<CrxInstaller>& installer) = 0;
+ scoped_refptr<CrxInstaller> installer) = 0;
// Subclasses must override DoRun to actually perform the patching operation.
// They must call the provided callback when they have completed their
@@ -93,7 +93,7 @@ class DeltaUpdateOpCopy : public DeltaUpdateOp {
UnpackerError DoParseArguments(
const base::DictionaryValue* command_args,
const base::FilePath& input_dir,
- const scoped_refptr<CrxInstaller>& installer) override;
+ scoped_refptr<CrxInstaller> installer) override;
void DoRun(ComponentPatcher::Callback callback) override;
@@ -117,7 +117,7 @@ class DeltaUpdateOpCreate : public DeltaUpdateOp {
UnpackerError DoParseArguments(
const base::DictionaryValue* command_args,
const base::FilePath& input_dir,
- const scoped_refptr<CrxInstaller>& installer) override;
+ scoped_refptr<CrxInstaller> installer) override;
void DoRun(ComponentPatcher::Callback callback) override;
@@ -142,7 +142,7 @@ class DeltaUpdateOpPatch : public DeltaUpdateOp {
UnpackerError DoParseArguments(
const base::DictionaryValue* command_args,
const base::FilePath& input_dir,
- const scoped_refptr<CrxInstaller>& installer) override;
+ scoped_refptr<CrxInstaller> installer) override;
void DoRun(ComponentPatcher::Callback callback) override;
diff --git a/chromium/components/update_client/component_unpacker.cc b/chromium/components/update_client/component_unpacker.cc
index c642af3ed7c..9e27a11e5b0 100644
--- a/chromium/components/update_client/component_unpacker.cc
+++ b/chromium/components/update_client/component_unpacker.cc
@@ -21,10 +21,10 @@
#include "base/strings/stringprintf.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/crx_file/crx_verifier.h"
+#include "components/unzip_service/public/cpp/unzip.h"
#include "components/update_client/component_patcher.h"
#include "components/update_client/update_client.h"
#include "components/update_client/update_client_errors.h"
-#include "third_party/zlib/google/zip.h"
namespace update_client {
@@ -33,7 +33,7 @@ ComponentUnpacker::Result::Result() {}
ComponentUnpacker::ComponentUnpacker(
const std::vector<uint8_t>& pk_hash,
const base::FilePath& path,
- const scoped_refptr<CrxInstaller>& installer,
+ scoped_refptr<CrxInstaller> installer,
std::unique_ptr<service_manager::Connector> connector)
: pk_hash_(pk_hash),
path_(path),
@@ -45,13 +45,9 @@ ComponentUnpacker::ComponentUnpacker(
ComponentUnpacker::~ComponentUnpacker() {}
-bool ComponentUnpacker::UnpackInternal() {
- return Verify() && Unzip() && BeginPatching();
-}
-
void ComponentUnpacker::Unpack(Callback callback) {
callback_ = std::move(callback);
- if (!UnpackInternal())
+ if (!Verify() || !BeginUnzipping())
EndUnpacking();
}
@@ -76,7 +72,7 @@ bool ComponentUnpacker::Verify() {
return true;
}
-bool ComponentUnpacker::Unzip() {
+bool ComponentUnpacker::BeginUnzipping() {
// Mind the reference to non-const type, passed as an argument below.
base::FilePath& destination = is_delta_ ? unpack_diff_path_ : unpack_path_;
if (!base::CreateNewTempDirectory(base::FilePath::StringType(),
@@ -86,13 +82,20 @@ bool ComponentUnpacker::Unzip() {
return false;
}
VLOG(1) << "Unpacking in: " << destination.value();
- if (!zip::Unzip(path_, destination)) {
+ unzip::Unzip(connector_.get(), path_, destination,
+ base::BindOnce(&ComponentUnpacker::EndUnzipping, this));
+ return true;
+}
+
+void ComponentUnpacker::EndUnzipping(bool result) {
+ if (!result) {
VLOG(1) << "Unzipping failed.";
error_ = UnpackerError::kUnzipFailed;
- return false;
+ EndUnpacking();
+ return;
}
VLOG(1) << "Unpacked successfully";
- return true;
+ BeginPatching();
}
bool ComponentUnpacker::BeginPatching() {
diff --git a/chromium/components/update_client/component_unpacker.h b/chromium/components/update_client/component_unpacker.h
index 7a6fc76a550..0fe5bcc927b 100644
--- a/chromium/components/update_client/component_unpacker.h
+++ b/chromium/components/update_client/component_unpacker.h
@@ -83,7 +83,7 @@ class ComponentUnpacker : public base::RefCountedThreadSafe<ComponentUnpacker> {
// location of the CRX.
ComponentUnpacker(const std::vector<uint8_t>& pk_hash,
const base::FilePath& path,
- const scoped_refptr<CrxInstaller>& installer,
+ scoped_refptr<CrxInstaller> installer,
std::unique_ptr<service_manager::Connector> connector);
// Begins the actual unpacking of the files. May invoke a patcher and the
@@ -96,16 +96,15 @@ class ComponentUnpacker : public base::RefCountedThreadSafe<ComponentUnpacker> {
virtual ~ComponentUnpacker();
- bool UnpackInternal();
-
// The first step of unpacking is to verify the file. Returns false if an
// error is encountered, the file is malformed, or the file is incorrectly
// signed.
bool Verify();
- // The second step of unpacking is to unzip. Returns false if an error
- // occurs as part of unzipping.
- bool Unzip();
+ // The second step of unpacking is to unzip. Returns false if an early error
+ // is encountered.
+ bool BeginUnzipping();
+ void EndUnzipping(bool error);
// The third step is to optionally patch files - this is a no-op for full
// (non-differential) updates. This step is asynchronous. Returns false if an
diff --git a/chromium/components/update_client/component_unpacker_unittest.cc b/chromium/components/update_client/component_unpacker_unittest.cc
index 3ba343c8b91..636ff68462e 100644
--- a/chromium/components/update_client/component_unpacker_unittest.cc
+++ b/chromium/components/update_client/component_unpacker_unittest.cc
@@ -100,10 +100,12 @@ void ComponentUnpackerTest::UnpackComplete(
}
TEST_F(ComponentUnpackerTest, UnpackFullCrx) {
+ auto config = base::MakeRefCounted<TestConfigurator>();
scoped_refptr<ComponentUnpacker> component_unpacker =
base::MakeRefCounted<ComponentUnpacker>(
std::vector<uint8_t>(std::begin(jebg_hash), std::end(jebg_hash)),
- test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"), nullptr, nullptr);
+ test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"), nullptr,
+ config->CreateServiceManagerConnector());
component_unpacker->Unpack(base::BindOnce(
&ComponentUnpackerTest::UnpackComplete, base::Unretained(this)));
RunThreads();
diff --git a/chromium/components/update_client/configurator.h b/chromium/components/update_client/configurator.h
index fd29c79c801..2d08795d590 100644
--- a/chromium/components/update_client/configurator.h
+++ b/chromium/components/update_client/configurator.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/memory/ref_counted.h"
+#include "net/url_request/url_request_context_getter.h"
class GURL;
class PrefService;
@@ -18,10 +19,6 @@ namespace base {
class Version;
}
-namespace net {
-class URLRequestContextGetter;
-}
-
namespace service_manager {
class Connector;
}
@@ -96,7 +93,8 @@ class Configurator : public base::RefCountedThreadSafe<Configurator> {
virtual std::string GetDownloadPreference() const = 0;
// The source of contexts for all the url requests.
- virtual net::URLRequestContextGetter* RequestContext() const = 0;
+ virtual scoped_refptr<net::URLRequestContextGetter> RequestContext()
+ const = 0;
// Returns a new connector to the service manager. That connector is not bound
// to any thread yet.
diff --git a/chromium/components/update_client/crx_downloader.cc b/chromium/components/update_client/crx_downloader.cc
index 02d898c377c..806b90f246c 100644
--- a/chromium/components/update_client/crx_downloader.cc
+++ b/chromium/components/update_client/crx_downloader.cc
@@ -22,6 +22,7 @@
#include "components/update_client/update_client_errors.h"
#include "components/update_client/url_fetcher_downloader.h"
#include "components/update_client/utils.h"
+#include "net/url_request/url_request_context_getter.h"
namespace update_client {
@@ -41,7 +42,7 @@ CrxDownloader::DownloadMetrics::DownloadMetrics()
// which uses the BITS service.
std::unique_ptr<CrxDownloader> CrxDownloader::Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
std::unique_ptr<CrxDownloader> url_fetcher_downloader =
std::make_unique<UrlFetcherDownloader>(nullptr, context_getter);
diff --git a/chromium/components/update_client/crx_downloader.h b/chromium/components/update_client/crx_downloader.h
index 544a91514d1..eab67413e91 100644
--- a/chromium/components/update_client/crx_downloader.h
+++ b/chromium/components/update_client/crx_downloader.h
@@ -86,8 +86,9 @@ class CrxDownloader {
// bytes is not guaranteed to monotonically increment over time.
using ProgressCallback = base::Callback<void(const Result& result)>;
- using Factory =
- std::unique_ptr<CrxDownloader> (*)(bool, net::URLRequestContextGetter*);
+ using Factory = std::unique_ptr<CrxDownloader> (*)(
+ bool,
+ scoped_refptr<net::URLRequestContextGetter>);
// Factory method to create an instance of this class and build the
// chain of responsibility. |is_background_download| specifies that a
@@ -96,7 +97,7 @@ class CrxDownloader {
// code such as file IO operations.
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter);
+ scoped_refptr<net::URLRequestContextGetter> context_getter);
virtual ~CrxDownloader();
void set_progress_callback(const ProgressCallback& progress_callback);
diff --git a/chromium/components/update_client/crx_downloader_unittest.cc b/chromium/components/update_client/crx_downloader_unittest.cc
index b87257d5378..8b53e2285d7 100644
--- a/chromium/components/update_client/crx_downloader_unittest.cc
+++ b/chromium/components/update_client/crx_downloader_unittest.cc
@@ -266,13 +266,7 @@ TEST_F(CrxDownloaderTest, OneUrlBadHash) {
// Tests that specifying two urls has no side effects. Expect a successful
// download, and only one download request be made.
-// This test is flaky on Android. crbug.com/329883
-#if defined(OS_ANDROID)
-#define MAYBE_TwoUrls DISABLED_TwoUrls
-#else
-#define MAYBE_TwoUrls TwoUrls
-#endif
-TEST_F(CrxDownloaderTest, MAYBE_TwoUrls) {
+TEST_F(CrxDownloaderTest, TwoUrls) {
const GURL expected_crx_url =
GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
@@ -304,72 +298,27 @@ TEST_F(CrxDownloaderTest, MAYBE_TwoUrls) {
EXPECT_EQ(1843, download_progress_result_.total_bytes);
}
-// Tests that an invalid host results in a download error.
-TEST_F(CrxDownloaderTest, OneUrl_InvalidHost) {
- const GURL expected_crx_url =
- GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
-
- const base::FilePath test_file(MakeTestFilePath(kTestFileName));
- get_interceptor_->SetResponse(expected_crx_url, test_file);
-
- crx_downloader_->StartDownloadFromUrl(
- GURL("http://no.such.host"
- "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"),
- std::string(hash_jebg), std::move(callback_));
- RunThreads();
-
- EXPECT_EQ(0, get_interceptor_->GetHitCount());
-
- EXPECT_EQ(1, num_download_complete_calls_);
- EXPECT_EQ(kExpectedContext, crx_context_);
- EXPECT_NE(0, download_complete_result_.error);
- EXPECT_TRUE(download_complete_result_.response.empty());
-}
-
-// Tests that an invalid path results in a download error.
-TEST_F(CrxDownloaderTest, OneUrl_InvalidPath) {
- const GURL expected_crx_url =
- GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
-
- const base::FilePath test_file(MakeTestFilePath(kTestFileName));
- get_interceptor_->SetResponse(expected_crx_url, test_file);
-
- crx_downloader_->StartDownloadFromUrl(GURL("http://localhost/no/such/file"),
- std::string(hash_jebg),
- std::move(callback_));
- RunThreads();
-
- EXPECT_EQ(0, get_interceptor_->GetHitCount());
-
- EXPECT_EQ(1, num_download_complete_calls_);
- EXPECT_EQ(kExpectedContext, crx_context_);
- EXPECT_NE(0, download_complete_result_.error);
- EXPECT_TRUE(download_complete_result_.response.empty());
-}
-
// Tests that the fallback to a valid url is successful.
-// This test is flaky on Android. crbug.com/329883
-#if defined(OS_ANDROID)
-#define MAYBE_TwoUrls_FirstInvalid DISABLED_TwoUrls_FirstInvalid
-#else
-#define MAYBE_TwoUrls_FirstInvalid TwoUrls_FirstInvalid
-#endif
-TEST_F(CrxDownloaderTest, MAYBE_TwoUrls_FirstInvalid) {
+TEST_F(CrxDownloaderTest, TwoUrls_FirstInvalid) {
const GURL expected_crx_url =
GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
+ const GURL no_file_url =
+ GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc.crx");
const base::FilePath test_file(MakeTestFilePath(kTestFileName));
get_interceptor_->SetResponse(expected_crx_url, test_file);
+ get_interceptor_->SetResponse(no_file_url,
+ base::FilePath(FILE_PATH_LITERAL("no-file")));
std::vector<GURL> urls;
- urls.push_back(GURL("http://localhost/no/such/file"));
+ urls.push_back(no_file_url);
urls.push_back(expected_crx_url);
crx_downloader_->StartDownload(urls, std::string(hash_jebg),
std::move(callback_));
RunThreads();
- EXPECT_EQ(1, get_interceptor_->GetHitCount());
+ EXPECT_EQ(2, get_interceptor_->GetHitCount());
EXPECT_EQ(1, num_download_complete_calls_);
EXPECT_EQ(kExpectedContext, crx_context_);
@@ -381,9 +330,21 @@ TEST_F(CrxDownloaderTest, MAYBE_TwoUrls_FirstInvalid) {
EXPECT_TRUE(
DeleteFileAndEmptyParentDirectory(download_complete_result_.response));
+ // Expect at least some progress reported by the fetcher.
EXPECT_LE(1, num_progress_calls_);
EXPECT_EQ(1843, download_progress_result_.downloaded_bytes);
EXPECT_EQ(1843, download_progress_result_.total_bytes);
+
+ const auto download_metrics = crx_downloader_->download_metrics();
+ ASSERT_EQ(2u, download_metrics.size());
+ EXPECT_EQ(no_file_url, download_metrics[0].url);
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, download_metrics[0].error);
+ EXPECT_EQ(-1, download_metrics[0].downloaded_bytes);
+ EXPECT_EQ(-1, download_metrics[0].total_bytes);
+ EXPECT_EQ(expected_crx_url, download_metrics[1].url);
+ EXPECT_EQ(0, download_metrics[1].error);
+ EXPECT_EQ(1843, download_metrics[1].downloaded_bytes);
+ EXPECT_EQ(1843, download_metrics[1].total_bytes);
}
// Tests that the download succeeds if the first url is correct and the
@@ -391,13 +352,17 @@ TEST_F(CrxDownloaderTest, MAYBE_TwoUrls_FirstInvalid) {
TEST_F(CrxDownloaderTest, TwoUrls_SecondInvalid) {
const GURL expected_crx_url =
GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
+ const GURL no_file_url =
+ GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc.crx");
const base::FilePath test_file(MakeTestFilePath(kTestFileName));
get_interceptor_->SetResponse(expected_crx_url, test_file);
+ get_interceptor_->SetResponse(no_file_url,
+ base::FilePath(FILE_PATH_LITERAL("no-file")));
std::vector<GURL> urls;
urls.push_back(expected_crx_url);
- urls.push_back(GURL("http://localhost/no/such/file"));
+ urls.push_back(no_file_url);
crx_downloader_->StartDownload(urls, std::string(hash_jebg),
std::move(callback_));
@@ -418,32 +383,43 @@ TEST_F(CrxDownloaderTest, TwoUrls_SecondInvalid) {
EXPECT_LE(1, num_progress_calls_);
EXPECT_EQ(1843, download_progress_result_.downloaded_bytes);
EXPECT_EQ(1843, download_progress_result_.total_bytes);
+
+ EXPECT_EQ(1u, crx_downloader_->download_metrics().size());
}
-// Tests that the download fails if both urls are bad.
+// Tests that the download fails if both urls don't serve content.
TEST_F(CrxDownloaderTest, TwoUrls_BothInvalid) {
const GURL expected_crx_url =
GURL("http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx");
- const base::FilePath test_file(MakeTestFilePath(kTestFileName));
- get_interceptor_->SetResponse(expected_crx_url, test_file);
+ get_interceptor_->SetResponse(expected_crx_url,
+ base::FilePath(FILE_PATH_LITERAL("no-file")));
std::vector<GURL> urls;
- urls.push_back(GURL("http://localhost/no/such/file"));
- urls.push_back(GURL(
- "http://no.such.host/"
- "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"));
+ urls.push_back(expected_crx_url);
+ urls.push_back(expected_crx_url);
crx_downloader_->StartDownload(urls, std::string(hash_jebg),
std::move(callback_));
RunThreads();
- EXPECT_EQ(0, get_interceptor_->GetHitCount());
+ EXPECT_EQ(2, get_interceptor_->GetHitCount());
EXPECT_EQ(1, num_download_complete_calls_);
EXPECT_EQ(kExpectedContext, crx_context_);
EXPECT_NE(0, download_complete_result_.error);
EXPECT_TRUE(download_complete_result_.response.empty());
+
+ const auto download_metrics = crx_downloader_->download_metrics();
+ ASSERT_EQ(2u, download_metrics.size());
+ EXPECT_EQ(expected_crx_url, download_metrics[0].url);
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, download_metrics[0].error);
+ EXPECT_EQ(-1, download_metrics[0].downloaded_bytes);
+ EXPECT_EQ(-1, download_metrics[0].total_bytes);
+ EXPECT_EQ(expected_crx_url, download_metrics[1].url);
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, download_metrics[1].error);
+ EXPECT_EQ(-1, download_metrics[1].downloaded_bytes);
+ EXPECT_EQ(-1, download_metrics[1].total_bytes);
}
} // namespace update_client
diff --git a/chromium/components/update_client/ping_manager.cc b/chromium/components/update_client/ping_manager.cc
index f974cd4b6d1..e6d3d544fe9 100644
--- a/chromium/components/update_client/ping_manager.cc
+++ b/chromium/components/update_client/ping_manager.cc
@@ -8,6 +8,7 @@
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -15,6 +16,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "components/update_client/configurator.h"
#include "components/update_client/protocol_builder.h"
#include "components/update_client/request_sender.h"
@@ -26,81 +28,88 @@ namespace update_client {
namespace {
-// Sends a fire and forget ping. The instances of this class have no
-// ownership and they self-delete upon completion. One instance of this class
-// can send only one ping.
-class PingSender {
+const int kErrorNoEvents = -1;
+const int kErrorNoUrl = -2;
+
+// An instance of this class can send only one ping.
+class PingSender : public base::RefCountedThreadSafe<PingSender> {
public:
- explicit PingSender(const scoped_refptr<Configurator>& config);
- ~PingSender();
+ using Callback = PingManager::Callback;
+ explicit PingSender(scoped_refptr<Configurator> config);
+ void SendPing(const Component& component, Callback callback);
- bool SendPing(const Component& component);
+ protected:
+ virtual ~PingSender();
private:
- void OnRequestSenderComplete(int error,
- const std::string& response,
- int retry_after_sec);
+ friend class base::RefCountedThreadSafe<PingSender>;
+ void SendPingComplete(int error,
+ const std::string& response,
+ int retry_after_sec);
+
+ THREAD_CHECKER(thread_checker_);
const scoped_refptr<Configurator> config_;
+ Callback callback_;
std::unique_ptr<RequestSender> request_sender_;
- base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(PingSender);
};
-PingSender::PingSender(const scoped_refptr<Configurator>& config)
- : config_(config) {}
+PingSender::PingSender(scoped_refptr<Configurator> config) : config_(config) {}
PingSender::~PingSender() {
- DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-void PingSender::OnRequestSenderComplete(int error,
- const std::string& response,
- int retry_after_sec) {
- DCHECK(thread_checker_.CalledOnValidThread());
- delete this;
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
-bool PingSender::SendPing(const Component& component) {
- DCHECK(thread_checker_.CalledOnValidThread());
+void PingSender::SendPing(const Component& component, Callback callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (component.events().empty())
- return false;
+ if (component.events().empty()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), kErrorNoEvents, ""));
+ return;
+ }
auto urls(config_->PingUrl());
if (component.crx_component().requires_network_encryption)
RemoveUnsecureUrls(&urls);
- if (urls.empty())
- return false;
+ if (urls.empty()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), kErrorNoUrl, ""));
+ return;
+ }
+
+ callback_ = std::move(callback);
request_sender_ = std::make_unique<RequestSender>(config_);
- request_sender_->Send(false, BuildEventPingRequest(*config_, component), urls,
- base::BindOnce(&PingSender::OnRequestSenderComplete,
- base::Unretained(this)));
- return true;
+ request_sender_->Send(urls, {}, BuildEventPingRequest(*config_, component),
+ false,
+ base::BindOnce(&PingSender::SendPingComplete, this));
+}
+
+void PingSender::SendPingComplete(int error,
+ const std::string& response,
+ int retry_after_sec) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ std::move(callback_).Run(error, response);
}
} // namespace
-PingManager::PingManager(const scoped_refptr<Configurator>& config)
+PingManager::PingManager(scoped_refptr<Configurator> config)
: config_(config) {}
PingManager::~PingManager() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
-bool PingManager::SendPing(const Component& component) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- auto ping_sender = std::make_unique<PingSender>(config_);
- if (!ping_sender->SendPing(component))
- return false;
+void PingManager::SendPing(const Component& component, Callback callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- // The ping sender object self-deletes after sending the ping asynchrously.
- ping_sender.release();
- return true;
+ auto ping_sender = base::MakeRefCounted<PingSender>(config_);
+ ping_sender->SendPing(component, std::move(callback));
}
} // namespace update_client
diff --git a/chromium/components/update_client/ping_manager.h b/chromium/components/update_client/ping_manager.h
index 3021a8b7bfa..24040e640e2 100644
--- a/chromium/components/update_client/ping_manager.h
+++ b/chromium/components/update_client/ping_manager.h
@@ -5,6 +5,9 @@
#ifndef COMPONENTS_UPDATE_CLIENT_PING_MANAGER_H_
#define COMPONENTS_UPDATE_CLIENT_PING_MANAGER_H_
+#include <string>
+
+#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
@@ -14,21 +17,27 @@ namespace update_client {
class Configurator;
class Component;
-// Sends fire-and-forget pings.
-class PingManager {
+class PingManager : public base::RefCountedThreadSafe<PingManager> {
public:
- explicit PingManager(const scoped_refptr<Configurator>& config);
- virtual ~PingManager();
+ // |error| is 0 if the ping was sent successfully, otherwise |error| contains
+ // a value with no particular meaning for the caller.
+ using Callback =
+ base::OnceCallback<void(int error, const std::string& response)>;
+
+ explicit PingManager(scoped_refptr<Configurator> config);
- // Sends a fire and forget ping for the |item|. Returns true if the
- // ping is queued up and may be sent in the future, or false, if an error
- // occurs right away. The ping itself is not persisted and it will be
- // discarded if it can't be sent for any reason.
- virtual bool SendPing(const Component& component);
+ // Sends a ping for the |item|. |callback| is invoked after the ping is sent
+ // or an error has occured. The ping itself is not persisted and it will
+ // be discarded if it has not been sent for any reason.
+ virtual void SendPing(const Component& component, Callback callback);
+
+ protected:
+ virtual ~PingManager();
private:
- base::ThreadChecker thread_checker_;
+ friend class base::RefCountedThreadSafe<PingManager>;
+ THREAD_CHECKER(thread_checker_);
const scoped_refptr<Configurator> config_;
DISALLOW_COPY_AND_ASSIGN(PingManager);
diff --git a/chromium/components/update_client/ping_manager_unittest.cc b/chromium/components/update_client/ping_manager_unittest.cc
index f7ce932334b..ecc919d2e40 100644
--- a/chromium/components/update_client/ping_manager_unittest.cc
+++ b/chromium/components/update_client/ping_manager_unittest.cc
@@ -6,11 +6,14 @@
#include <memory>
#include <string>
+#include <utility>
#include <vector>
+#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/version.h"
#include "components/update_client/component.h"
@@ -30,36 +33,67 @@ class PingManagerTest : public testing::Test {
PingManagerTest();
~PingManagerTest() override {}
- void RunThreadsUntilIdle();
-
+ PingManager::Callback MakePingCallback();
std::unique_ptr<UpdateContext> MakeFakeUpdateContext() const;
// Overrides from testing::Test.
void SetUp() override;
void TearDown() override;
+ void PingSentCallback(int error, const std::string& response);
+
protected:
+ void Quit();
+ void RunThreads();
+
scoped_refptr<TestConfigurator> config_;
- std::unique_ptr<PingManager> ping_manager_;
+ scoped_refptr<PingManager> ping_manager_;
+
+ int error_ = -1;
+ std::string response_;
private:
- base::MessageLoopForIO loop_;
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::OnceClosure quit_closure_;
};
-PingManagerTest::PingManagerTest() {}
+PingManagerTest::PingManagerTest()
+ : scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::IO) {
+ config_ = base::MakeRefCounted<TestConfigurator>();
+}
void PingManagerTest::SetUp() {
- config_ = base::MakeRefCounted<TestConfigurator>();
- ping_manager_ = std::make_unique<PingManager>(config_);
+ ping_manager_ = base::MakeRefCounted<PingManager>(config_);
}
void PingManagerTest::TearDown() {
- ping_manager_.reset();
- config_ = nullptr;
+ // Run the threads until they are idle to allow the clean up
+ // of the network interceptors on the IO thread.
+ scoped_task_environment_.RunUntilIdle();
+ ping_manager_ = nullptr;
+}
+
+void PingManagerTest::RunThreads() {
+ base::RunLoop runloop;
+ quit_closure_ = runloop.QuitClosure();
+ runloop.Run();
+}
+
+void PingManagerTest::Quit() {
+ if (!quit_closure_.is_null())
+ std::move(quit_closure_).Run();
+}
+
+PingManager::Callback PingManagerTest::MakePingCallback() {
+ return base::BindOnce(&PingManagerTest::PingSentCallback,
+ base::Unretained(this));
}
-void PingManagerTest::RunThreadsUntilIdle() {
- base::RunLoop().RunUntilIdle();
+void PingManagerTest::PingSentCallback(int error, const std::string& response) {
+ error_ = error;
+ response_ = response;
+ Quit();
}
std::unique_ptr<UpdateContext> PingManagerTest::MakeFakeUpdateContext() const {
@@ -70,10 +104,9 @@ std::unique_ptr<UpdateContext> PingManagerTest::MakeFakeUpdateContext() const {
}
TEST_F(PingManagerTest, SendPing) {
- std::unique_ptr<InterceptorFactory> interceptor_factory(
- new InterceptorFactory(base::ThreadTaskRunnerHandle::Get()));
- URLRequestPostInterceptor* interceptor =
- interceptor_factory->CreateInterceptor();
+ auto interceptor_factory =
+ std::make_unique<InterceptorFactory>(base::ThreadTaskRunnerHandle::Get());
+ auto* interceptor = interceptor_factory->CreateInterceptor();
EXPECT_TRUE(interceptor);
// Test eventresult="1" is sent for successful updates.
@@ -87,16 +120,27 @@ TEST_F(PingManagerTest, SendPing) {
component.next_version_ = base::Version("2.0");
component.AppendEvent(BuildUpdateCompleteEventElement(component));
- ping_manager_->SendPing(component);
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(interceptor->ExpectRequest(new AnyMatch));
+ ping_manager_->SendPing(component, MakePingCallback());
+ RunThreads();
EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString();
EXPECT_NE(string::npos,
- interceptor->GetRequests()[0].find(
+ interceptor->GetRequestBody(0).find(
"<app appid=\"abc\">"
"<event eventtype=\"3\" eventresult=\"1\" "
"previousversion=\"1.0\" nextversion=\"2.0\"/></app>"))
<< interceptor->GetRequestsAsString();
+ EXPECT_NE(string::npos, interceptor->GetRequestBody(0).find(" sessionid="));
+
+ // Check the ping request does not carry the specific extra request headers.
+ EXPECT_FALSE(interceptor->GetRequests()[0].second.HasHeader(
+ "X-GoogleUpdate-Interactivity"));
+ EXPECT_FALSE(interceptor->GetRequests()[0].second.HasHeader(
+ "X-GoogleUpdate-Updater"));
+ EXPECT_FALSE(
+ interceptor->GetRequests()[0].second.HasHeader("X-GoogleUpdate-AppId"));
+
interceptor->Reset();
}
@@ -109,12 +153,13 @@ TEST_F(PingManagerTest, SendPing) {
component.next_version_ = base::Version("2.0");
component.AppendEvent(BuildUpdateCompleteEventElement(component));
- ping_manager_->SendPing(component);
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(interceptor->ExpectRequest(new AnyMatch));
+ ping_manager_->SendPing(component, MakePingCallback());
+ RunThreads();
EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString();
EXPECT_NE(string::npos,
- interceptor->GetRequests()[0].find(
+ interceptor->GetRequestBody(0).find(
"<app appid=\"abc\">"
"<event eventtype=\"3\" eventresult=\"0\" "
"previousversion=\"1.0\" nextversion=\"2.0\"/></app>"))
@@ -140,12 +185,13 @@ TEST_F(PingManagerTest, SendPing) {
component.crx_diffurls_.push_back(GURL("http://host/path"));
component.AppendEvent(BuildUpdateCompleteEventElement(component));
- ping_manager_->SendPing(component);
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(interceptor->ExpectRequest(new AnyMatch));
+ ping_manager_->SendPing(component, MakePingCallback());
+ RunThreads();
EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString();
EXPECT_NE(string::npos,
- interceptor->GetRequests()[0].find(
+ interceptor->GetRequestBody(0).find(
"<app appid=\"abc\">"
"<event eventtype=\"3\" eventresult=\"0\" errorcat=\"1\" "
"errorcode=\"2\" extracode1=\"-1\" diffresult=\"0\" "
@@ -166,12 +212,13 @@ TEST_F(PingManagerTest, SendPing) {
component.AppendEvent(BuildUpdateCompleteEventElement(component));
- ping_manager_->SendPing(component);
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(interceptor->ExpectRequest(new AnyMatch));
+ ping_manager_->SendPing(component, MakePingCallback());
+ RunThreads();
EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString();
EXPECT_NE(string::npos,
- interceptor->GetRequests()[0].find(
+ interceptor->GetRequestBody(0).find(
"<app appid=\"abc\"><event eventtype=\"3\" eventresult=\"0\" "
"previousversion=\"1.0\"/></app>"))
<< interceptor->GetRequestsAsString();
@@ -185,12 +232,13 @@ TEST_F(PingManagerTest, SendPing) {
component.Uninstall(base::Version("1.2.3.4"), 0);
component.AppendEvent(BuildUninstalledEventElement(component));
- ping_manager_->SendPing(component);
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(interceptor->ExpectRequest(new AnyMatch));
+ ping_manager_->SendPing(component, MakePingCallback());
+ RunThreads();
EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString();
EXPECT_NE(string::npos,
- interceptor->GetRequests()[0].find(
+ interceptor->GetRequestBody(0).find(
"<app appid=\"abc\">"
"<event eventtype=\"4\" eventresult=\"1\" "
"previousversion=\"1.2.3.4\" nextversion=\"0\"/></app>"))
@@ -226,13 +274,14 @@ TEST_F(PingManagerTest, SendPing) {
component.AppendEvent(
BuildDownloadCompleteEventElement(component, download_metrics));
- ping_manager_->SendPing(component);
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(interceptor->ExpectRequest(new AnyMatch));
+ ping_manager_->SendPing(component, MakePingCallback());
+ RunThreads();
EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString();
EXPECT_NE(
string::npos,
- interceptor->GetRequests()[0].find(
+ interceptor->GetRequestBody(0).find(
"<app appid=\"abc\">"
"<event eventtype=\"3\" eventresult=\"1\" previousversion=\"1.0\" "
"nextversion=\"2.0\"/>"
@@ -247,9 +296,6 @@ TEST_F(PingManagerTest, SendPing) {
<< interceptor->GetRequestsAsString();
interceptor->Reset();
}
-
- interceptor_factory.reset();
- base::RunLoop().RunUntilIdle();
}
// Tests that sending the ping fails when the component requires encryption but
@@ -259,18 +305,20 @@ TEST_F(PingManagerTest, RequiresEncryption) {
const auto update_context = MakeFakeUpdateContext();
- {
- Component component(*update_context, "abc");
- component.crx_component_.requires_network_encryption = true;
+ Component component(*update_context, "abc");
- EXPECT_FALSE(ping_manager_->SendPing(component));
- }
+ // The default value for |requires_network_encryption| is true.
+ EXPECT_TRUE(component.crx_component_.requires_network_encryption);
- {
- // Tests that the default for |requires_network_encryption| is true.
- Component component(*update_context, "abc");
- EXPECT_FALSE(ping_manager_->SendPing(component));
- }
+ component.state_ = std::make_unique<Component::StateUpdated>(&component);
+ component.previous_version_ = base::Version("1.0");
+ component.next_version_ = base::Version("2.0");
+ component.AppendEvent(BuildUpdateCompleteEventElement(component));
+
+ ping_manager_->SendPing(component, MakePingCallback());
+ RunThreads();
+
+ EXPECT_EQ(-2, error_);
}
} // namespace update_client
diff --git a/chromium/components/update_client/protocol_builder.cc b/chromium/components/update_client/protocol_builder.cc
index b7e98e8c07f..6d4bbebc74a 100644
--- a/chromium/components/update_client/protocol_builder.cc
+++ b/chromium/components/update_client/protocol_builder.cc
@@ -202,6 +202,7 @@ std::string BuildActionRunEventElement(bool succeeded,
}
std::string BuildProtocolRequest(
+ const std::string& session_id,
const std::string& prod_id,
const std::string& browser_version,
const std::string& channel,
@@ -222,22 +223,27 @@ std::string BuildProtocolRequest(
// Constant information for this updater.
base::StringAppendF(&request, "dedup=\"cr\" acceptformat=\"crx2,crx3\" ");
+ // Sesssion id and request id
+ DCHECK(!session_id.empty());
+ DCHECK(!base::StartsWith(session_id, "{", base::CompareCase::SENSITIVE));
+ DCHECK(!base::EndsWith(session_id, "}", base::CompareCase::SENSITIVE));
+ base::StringAppendF(&request, "sessionid=\"{%s}\" requestid=\"{%s}\" ",
+ session_id.c_str(), base::GenerateGUID().c_str());
+
// Chrome version and platform information.
- base::StringAppendF(
- &request,
- "version=\"%s-%s\" prodversion=\"%s\" "
- "requestid=\"{%s}\" lang=\"%s\" updaterchannel=\"%s\" prodchannel=\"%s\" "
- "os=\"%s\" arch=\"%s\" nacl_arch=\"%s\"",
- prod_id.c_str(), // "version" is prefixed by prod_id.
- browser_version.c_str(),
- browser_version.c_str(), // "prodversion"
- base::GenerateGUID().c_str(), // "requestid"
- lang.c_str(), // "lang"
- channel.c_str(), // "updaterchannel"
- channel.c_str(), // "prodchannel"
- UpdateQueryParams::GetOS(), // "os"
- UpdateQueryParams::GetArch(), // "arch"
- UpdateQueryParams::GetNaclArch()); // "nacl_arch"
+ base::StringAppendF(&request,
+ "version=\"%s-%s\" prodversion=\"%s\" "
+ "lang=\"%s\" updaterchannel=\"%s\" prodchannel=\"%s\" "
+ "os=\"%s\" arch=\"%s\" nacl_arch=\"%s\"",
+ prod_id.c_str(), // "version" is prefixed by prod_id.
+ browser_version.c_str(),
+ browser_version.c_str(), // "prodversion"
+ lang.c_str(), // "lang"
+ channel.c_str(), // "updaterchannel"
+ channel.c_str(), // "prodchannel"
+ UpdateQueryParams::GetOS(), // "os"
+ UpdateQueryParams::GetArch(), // "arch"
+ UpdateQueryParams::GetNaclArch()); // "nacl_arch"
#if defined(OS_WIN)
const bool is_wow64(base::win::OSInfo::GetInstance()->wow64_status() ==
base::win::OSInfo::WOW64_ENABLED);
@@ -296,6 +302,7 @@ std::string BuildProtocolRequest(
std::string BuildUpdateCheckRequest(
const Configurator& config,
+ const std::string& session_id,
const std::vector<std::string>& ids_checked,
const IdToComponentPtrMap& components,
PersistedData* metadata,
@@ -386,7 +393,7 @@ std::string BuildUpdateCheckRequest(
// Include the updater state in the update check request.
return BuildProtocolRequest(
- config.GetProdId(), config.GetBrowserVersion().GetString(),
+ session_id, config.GetProdId(), config.GetBrowserVersion().GetString(),
config.GetChannel(), config.GetLang(), config.GetOSLongName(),
config.GetDownloadPreference(), app_elements, additional_attributes,
updater_state_attributes);
@@ -405,10 +412,31 @@ std::string BuildEventPingRequest(const Configurator& config,
app.append("</app>");
// The ping request does not include any updater state.
- return BuildProtocolRequest(
- config.GetProdId(), config.GetBrowserVersion().GetString(),
- config.GetChannel(), config.GetLang(), config.GetOSLongName(),
- config.GetDownloadPreference(), app, "", nullptr);
+ return BuildProtocolRequest(component.session_id(), config.GetProdId(),
+ config.GetBrowserVersion().GetString(),
+ config.GetChannel(), config.GetLang(),
+ config.GetOSLongName(),
+ config.GetDownloadPreference(), app, "", nullptr);
+}
+
+std::map<std::string, std::string> BuildUpdateCheckExtraRequestHeaders(
+ scoped_refptr<Configurator> config,
+ const std::vector<std::string>& ids,
+ bool is_foreground) {
+ // This number of extension ids result in an HTTP header length of about 1KB.
+ constexpr size_t maxExtensionCount = 30;
+ const std::vector<std::string>& app_ids =
+ ids.size() <= maxExtensionCount
+ ? ids
+ : std::vector<std::string>(ids.cbegin(),
+ ids.cbegin() + maxExtensionCount);
+ return std::map<std::string, std::string>{
+ {"X-GoogleUpdate-Updater",
+ base::StringPrintf("%s-%s", config->GetProdId().c_str(),
+ config->GetBrowserVersion().GetString().c_str())},
+ {"X-GoogleUpdate-Interactivity", is_foreground ? "fg" : "bg"},
+ {"X-GoogleUpdate-AppId", base::JoinString(app_ids, ",")},
+ };
}
} // namespace update_client
diff --git a/chromium/components/update_client/protocol_builder.h b/chromium/components/update_client/protocol_builder.h
index 969126ed72b..340693e7e68 100644
--- a/chromium/components/update_client/protocol_builder.h
+++ b/chromium/components/update_client/protocol_builder.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_UPDATE_CLIENT_PROTOCOL_BUILDER_H_
#define COMPONENTS_UPDATE_CLIENT_PROTOCOL_BUILDER_H_
+#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -35,6 +36,7 @@ class PersistedData;
// </request>
std::string BuildUpdateCheckRequest(
const Configurator& config,
+ const std::string& session_id,
const std::vector<std::string>& ids_checked,
const IdToComponentPtrMap& components,
PersistedData* metadata,
@@ -82,7 +84,8 @@ std::string BuildActionRunEventElement(bool succeeded,
// For example:
//
// <?xml version="1.0" encoding="UTF-8"?>
-// <request protocol="3.0" version="chrome-32.0.1.0" prodversion="32.0.1.0"
+// <request protocol="3.0" sessionid="{D505492F-95FE-4F90-8253-AEA75772DCC4}"
+// version="chrome-32.0.1.0" prodversion="32.0.1.0"
// requestid="{7383396D-B4DD-46E1-9104-AAC6B918E792}"
// updaterchannel="canary" arch="x86" nacl_arch="x86-64"
// ADDITIONAL ATTRIBUTES>
@@ -101,6 +104,7 @@ std::string BuildActionRunEventElement(bool succeeded,
// parameter specifying that an <updater> element is serialized as part of
// the request.
std::string BuildProtocolRequest(
+ const std::string& session_id,
const std::string& prod_id,
const std::string& browser_version,
const std::string& channel,
@@ -111,6 +115,14 @@ std::string BuildProtocolRequest(
const std::string& additional_attributes,
const std::unique_ptr<UpdaterState::Attributes>& updater_state_attributes);
+// Creates the values for the DDOS extra request headers sent with the update
+// check. These headers include "X-GoogleUpdate-Updater",
+// "X-GoogleUpdate-AppId", and "X-GoogleUpdate-Interactivity".
+std::map<std::string, std::string> BuildUpdateCheckExtraRequestHeaders(
+ scoped_refptr<Configurator> config,
+ const std::vector<std::string>& ids,
+ bool is_foreground);
+
} // namespace update_client
#endif // COMPONENTS_UPDATE_CLIENT_PROTOCOL_BUILDER_H_
diff --git a/chromium/components/update_client/protocol_builder_unittest.cc b/chromium/components/update_client/protocol_builder_unittest.cc
index cc2a665f589..68cc8da707f 100644
--- a/chromium/components/update_client/protocol_builder_unittest.cc
+++ b/chromium/components/update_client/protocol_builder_unittest.cc
@@ -5,9 +5,13 @@
#include <string>
#include "base/files/file_path.h"
+#include "base/memory/scoped_refptr.h"
#include "base/path_service.h"
+#include "base/strings/string_util.h"
+#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
#include "components/update_client/protocol_builder.h"
+#include "components/update_client/test_configurator.h"
#include "components/update_client/updater_state.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -15,34 +19,41 @@ using std::string;
namespace update_client {
-TEST(UpdateClientUtils, BuildProtocolRequest_ProdIdVersion) {
- // Verifies that |prod_id| and |version| are serialized.
- const string request = BuildProtocolRequest("some_prod_id", "1.0", "", "", "",
- "", "", "", nullptr);
- EXPECT_NE(string::npos, request.find(" version=\"some_prod_id-1.0\" "));
+TEST(BuildProtocolRequest, SessionIdProdIdVersion) {
+ // Verifies that |session_id|, |prod_id| and |version| are serialized.
+ const string request = BuildProtocolRequest(
+ "15160585-8ADE-4D3C-839B-1281A6035D1F", "some_prod_id", "1.0", "", "", "",
+ "", "", "", nullptr);
+ EXPECT_NE(
+ string::npos,
+ request.find(" sessionid=\"{15160585-8ADE-4D3C-839B-1281A6035D1F}\" "));
+ EXPECT_NE(string::npos,
+ request.find(" version=\"some_prod_id-1.0\" prodversion=\"1.0\" "));
}
-TEST(UpdateClientUtils, BuildProtocolRequest_DownloadPreference) {
+TEST(BuildProtocolRequest, DownloadPreference) {
// Verifies that an empty |download_preference| is not serialized.
const string request_no_dlpref =
- BuildProtocolRequest("", "", "", "", "", "", "", "", nullptr);
+ BuildProtocolRequest("1", "", "", "", "", "", "", "", "", nullptr);
EXPECT_EQ(string::npos, request_no_dlpref.find(" dlpref="));
// Verifies that |download_preference| is serialized.
- const string request_with_dlpref =
- BuildProtocolRequest("", "", "", "", "", "some pref", "", "", nullptr);
+ const string request_with_dlpref = BuildProtocolRequest(
+ "1", "", "", "", "", "", "some pref", "", "", nullptr);
EXPECT_NE(string::npos, request_with_dlpref.find(" dlpref=\"some pref\""));
}
-TEST(UpdateClientUtils, BuildProtocolRequestUpdaterStateAttributes) {
+TEST(BuildProtocolRequest, UpdaterStateAttributes) {
// When no updater state is provided, then check that the elements and
// attributes related to the updater state are not serialized.
std::string request =
- BuildProtocolRequest("", "", "", "", "", "", "", "", nullptr).c_str();
+ BuildProtocolRequest("1", "", "", "", "", "", "", "", "", nullptr)
+ .c_str();
EXPECT_EQ(std::string::npos, request.find(" domainjoined"));
EXPECT_EQ(std::string::npos, request.find("<updater"));
UpdaterState::Attributes attributes;
+ attributes["ismachine"] = "1";
attributes["domainjoined"] = "1";
attributes["name"] = "Omaha";
attributes["version"] = "1.2.3.4";
@@ -51,11 +62,11 @@ TEST(UpdateClientUtils, BuildProtocolRequestUpdaterStateAttributes) {
attributes["autoupdatecheckenabled"] = "0";
attributes["updatepolicy"] = "-1";
request = BuildProtocolRequest(
- "", "", "", "", "", "", "", "",
+ "1", "", "", "", "", "", "", "", "",
std::make_unique<UpdaterState::Attributes>(attributes));
EXPECT_NE(std::string::npos, request.find(" domainjoined=\"1\""));
const std::string updater_element =
- "<updater autoupdatecheckenabled=\"0\" "
+ "<updater autoupdatecheckenabled=\"0\" ismachine=\"1\" "
"lastchecked=\"2\" laststarted=\"1\" name=\"Omaha\" "
"updatepolicy=\"-1\" version=\"1.2.3.4\"/>";
#if defined(GOOGLE_CHROME_BUILD)
@@ -65,4 +76,45 @@ TEST(UpdateClientUtils, BuildProtocolRequestUpdaterStateAttributes) {
#endif // GOOGLE_CHROME_BUILD
}
+TEST(BuildProtocolRequest, BuildUpdateCheckExtraRequestHeaders) {
+ base::test::ScopedTaskEnvironment scoped_task_environment;
+ auto config = base::MakeRefCounted<TestConfigurator>();
+
+ auto headers = BuildUpdateCheckExtraRequestHeaders(config, {}, true);
+ EXPECT_STREQ("fake_prodid-30.0", headers["X-GoogleUpdate-Updater"].c_str());
+ EXPECT_STREQ("fg", headers["X-GoogleUpdate-Interactivity"].c_str());
+ EXPECT_EQ("", headers["X-GoogleUpdate-AppId"]);
+
+ headers = BuildUpdateCheckExtraRequestHeaders(config, {}, false);
+ EXPECT_STREQ("fake_prodid-30.0", headers["X-GoogleUpdate-Updater"].c_str());
+ EXPECT_STREQ("bg", headers["X-GoogleUpdate-Interactivity"].c_str());
+ EXPECT_EQ("", headers["X-GoogleUpdate-AppId"]);
+
+ headers = BuildUpdateCheckExtraRequestHeaders(
+ config, {"jebgalgnebhfojomionfpkfelancnnkf"}, true);
+ EXPECT_STREQ("fake_prodid-30.0", headers["X-GoogleUpdate-Updater"].c_str());
+ EXPECT_STREQ("fg", headers["X-GoogleUpdate-Interactivity"].c_str());
+ EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf",
+ headers["X-GoogleUpdate-AppId"].c_str());
+
+ headers = BuildUpdateCheckExtraRequestHeaders(
+ config,
+ {"jebgalgnebhfojomionfpkfelancnnkf", "ihfokbkgjpifbbojhneepfflplebdkc"},
+ true);
+ EXPECT_STREQ("fake_prodid-30.0", headers["X-GoogleUpdate-Updater"].c_str());
+ EXPECT_STREQ("fg", headers["X-GoogleUpdate-Interactivity"].c_str());
+ EXPECT_STREQ(
+ "jebgalgnebhfojomionfpkfelancnnkf,ihfokbkgjpifbbojhneepfflplebdkc",
+ headers["X-GoogleUpdate-AppId"].c_str());
+
+ headers = BuildUpdateCheckExtraRequestHeaders(
+ config, std::vector<std::string>(40, "jebgalgnebhfojomionfpkfelancnnkf"),
+ true);
+ EXPECT_STREQ(
+ base::JoinString(
+ std::vector<std::string>(30, "jebgalgnebhfojomionfpkfelancnnkf"), ",")
+ .c_str(),
+ headers["X-GoogleUpdate-AppId"].c_str());
+}
+
} // namespace update_client
diff --git a/chromium/components/update_client/request_sender.cc b/chromium/components/update_client/request_sender.cc
index a1d46ea8095..eebe4f2f4a3 100644
--- a/chromium/components/update_client/request_sender.cc
+++ b/chromium/components/update_client/request_sender.cc
@@ -52,22 +52,25 @@ constexpr int64_t kMaxRetryAfterSec = 24 * 60 * 60;
} // namespace
-RequestSender::RequestSender(const scoped_refptr<Configurator>& config)
+RequestSender::RequestSender(scoped_refptr<Configurator> config)
: config_(config), use_signing_(false) {}
RequestSender::~RequestSender() {
DCHECK(thread_checker_.CalledOnValidThread());
}
-void RequestSender::Send(bool use_signing,
- const std::string& request_body,
- const std::vector<GURL>& urls,
- RequestSenderCallback request_sender_callback) {
+void RequestSender::Send(
+ const std::vector<GURL>& urls,
+ const std::map<std::string, std::string>& request_extra_headers,
+ const std::string& request_body,
+ bool use_signing,
+ RequestSenderCallback request_sender_callback) {
DCHECK(thread_checker_.CalledOnValidThread());
- use_signing_ = use_signing;
- request_body_ = request_body;
urls_ = urls;
+ request_extra_headers_ = request_extra_headers;
+ request_body_ = request_body;
+ use_signing_ = use_signing;
request_sender_callback_ = std::move(request_sender_callback);
if (urls_.empty()) {
@@ -101,8 +104,8 @@ void RequestSender::SendInternal() {
url = BuildUpdateUrl(url, request_query_string);
}
- url_fetcher_ =
- SendProtocolRequest(url, request_body_, this, config_->RequestContext());
+ url_fetcher_ = SendProtocolRequest(url, request_extra_headers_, request_body_,
+ this, config_->RequestContext());
if (!url_fetcher_.get())
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&RequestSender::SendInternalComplete,
diff --git a/chromium/components/update_client/request_sender.h b/chromium/components/update_client/request_sender.h
index bbba898682b..91a83c9e536 100644
--- a/chromium/components/update_client/request_sender.h
+++ b/chromium/components/update_client/request_sender.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -51,14 +52,19 @@ class RequestSender : public net::URLFetcherDelegate {
// avoiding collisions with known network errors is desirable.
enum : int { kErrorResponseNotTrusted = -10000 };
- explicit RequestSender(const scoped_refptr<Configurator>& config);
+ explicit RequestSender(scoped_refptr<Configurator> config);
~RequestSender() override;
// |use_signing| enables CUP signing of protocol messages exchanged using
- // this class.
- void Send(bool use_signing,
+ // this class. |is_foreground| controls the presence and the value for the
+ // X-GoogleUpdate-Interactvity header serialized in the protocol request.
+ // If this optional parameter is set, the values of "fg" or "bg" are sent
+ // for true or false values of this parameter. Otherwise the header is not
+ // sent at all.
+ void Send(const std::vector<GURL>& urls,
+ const std::map<std::string, std::string>& request_extra_headers,
const std::string& request_body,
- const std::vector<GURL>& urls,
+ bool use_signing,
RequestSenderCallback request_sender_callback);
private:
@@ -97,9 +103,11 @@ class RequestSender : public net::URLFetcherDelegate {
base::ThreadChecker thread_checker_;
const scoped_refptr<Configurator> config_;
- bool use_signing_; // True if CUP signing is used.
+
std::vector<GURL> urls_;
+ std::map<std::string, std::string> request_extra_headers_;
std::string request_body_;
+ bool use_signing_; // True if CUP signing is used.
RequestSenderCallback request_sender_callback_;
std::string public_key_;
diff --git a/chromium/components/update_client/request_sender_unittest.cc b/chromium/components/update_client/request_sender_unittest.cc
index 8310e7b3ed4..4807afef5b0 100644
--- a/chromium/components/update_client/request_sender_unittest.cc
+++ b/chromium/components/update_client/request_sender_unittest.cc
@@ -41,7 +41,8 @@ base::FilePath test_file(const char* file) {
} // namespace
-class RequestSenderTest : public testing::Test {
+class RequestSenderTest : public testing::Test,
+ public ::testing::WithParamInterface<bool> {
public:
RequestSenderTest();
~RequestSenderTest() override;
@@ -77,6 +78,8 @@ class RequestSenderTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(RequestSenderTest);
};
+INSTANTIATE_TEST_CASE_P(IsForeground, RequestSenderTest, ::testing::Bool());
+
RequestSenderTest::RequestSenderTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
@@ -133,14 +136,16 @@ void RequestSenderTest::RequestSenderComplete(int error,
// Tests that when a request to the first url succeeds, the subsequent urls are
// not tried.
-TEST_F(RequestSenderTest, RequestSendSuccess) {
+TEST_P(RequestSenderTest, RequestSendSuccess) {
EXPECT_TRUE(post_interceptor_1_->ExpectRequest(
new PartialMatch("test"), test_file("updatecheck_reply_1.xml")));
const std::vector<GURL> urls = {GURL(kUrl1), GURL(kUrl2)};
+ const bool is_foreground = GetParam();
request_sender_ = std::make_unique<RequestSender>(config_);
request_sender_->Send(
- false, "test", urls,
+ urls, {{"X-GoogleUpdate-Interactivity", is_foreground ? "fg" : "bg"}},
+ "test", false,
base::BindOnce(&RequestSenderTest::RequestSenderComplete,
base::Unretained(this)));
RunThreads();
@@ -156,7 +161,7 @@ TEST_F(RequestSenderTest, RequestSendSuccess) {
<< post_interceptor_2_->GetRequestsAsString();
// Sanity check the request.
- EXPECT_STREQ("test", post_interceptor_1_->GetRequests()[0].c_str());
+ EXPECT_STREQ("test", post_interceptor_1_->GetRequestBody(0).c_str());
// Check the response post conditions.
EXPECT_EQ(0, error_);
@@ -165,6 +170,14 @@ TEST_F(RequestSenderTest, RequestSendSuccess) {
base::CompareCase::SENSITIVE));
EXPECT_EQ(505ul, response_.size());
+ // Check the interactivity header value.
+ const auto extra_request_headers =
+ post_interceptor_1_->GetRequests()[0].second;
+ EXPECT_TRUE(extra_request_headers.HasHeader("X-GoogleUpdate-Interactivity"));
+ std::string header;
+ extra_request_headers.GetHeader("X-GoogleUpdate-Interactivity", &header);
+ EXPECT_STREQ(is_foreground ? "fg" : "bg", header.c_str());
+
interceptor_factory_ = nullptr;
}
@@ -178,7 +191,7 @@ TEST_F(RequestSenderTest, RequestSendSuccessWithFallback) {
const std::vector<GURL> urls = {GURL(kUrl1), GURL(kUrl2)};
request_sender_ = std::make_unique<RequestSender>(config_);
request_sender_->Send(
- false, "test", urls,
+ urls, {}, "test", false,
base::BindOnce(&RequestSenderTest::RequestSenderComplete,
base::Unretained(this)));
RunThreads();
@@ -192,8 +205,8 @@ TEST_F(RequestSenderTest, RequestSendSuccessWithFallback) {
EXPECT_EQ(1, post_interceptor_2_->GetCount())
<< post_interceptor_2_->GetRequestsAsString();
- EXPECT_STREQ("test", post_interceptor_1_->GetRequests()[0].c_str());
- EXPECT_STREQ("test", post_interceptor_2_->GetRequests()[0].c_str());
+ EXPECT_STREQ("test", post_interceptor_1_->GetRequestBody(0).c_str());
+ EXPECT_STREQ("test", post_interceptor_2_->GetRequestBody(0).c_str());
EXPECT_EQ(0, error_);
}
@@ -207,7 +220,7 @@ TEST_F(RequestSenderTest, RequestSendFailed) {
const std::vector<GURL> urls = {GURL(kUrl1), GURL(kUrl2)};
request_sender_ = std::make_unique<RequestSender>(config_);
request_sender_->Send(
- false, "test", urls,
+ urls, {}, "test", false,
base::BindOnce(&RequestSenderTest::RequestSenderComplete,
base::Unretained(this)));
RunThreads();
@@ -221,8 +234,8 @@ TEST_F(RequestSenderTest, RequestSendFailed) {
EXPECT_EQ(1, post_interceptor_2_->GetCount())
<< post_interceptor_2_->GetRequestsAsString();
- EXPECT_STREQ("test", post_interceptor_1_->GetRequests()[0].c_str());
- EXPECT_STREQ("test", post_interceptor_2_->GetRequests()[0].c_str());
+ EXPECT_STREQ("test", post_interceptor_1_->GetRequestBody(0).c_str());
+ EXPECT_STREQ("test", post_interceptor_2_->GetRequestBody(0).c_str());
EXPECT_EQ(403, error_);
}
@@ -231,7 +244,7 @@ TEST_F(RequestSenderTest, RequestSendFailedNoUrls) {
std::vector<GURL> urls;
request_sender_ = std::make_unique<RequestSender>(config_);
request_sender_->Send(
- false, "test", urls,
+ urls, std::map<std::string, std::string>(), "test", false,
base::BindOnce(&RequestSenderTest::RequestSenderComplete,
base::Unretained(this)));
RunThreads();
@@ -247,7 +260,7 @@ TEST_F(RequestSenderTest, RequestSendCupError) {
const std::vector<GURL> urls = {GURL(kUrl1)};
request_sender_ = std::make_unique<RequestSender>(config_);
request_sender_->Send(
- true, "test", urls,
+ urls, {}, "test", true,
base::BindOnce(&RequestSenderTest::RequestSenderComplete,
base::Unretained(this)));
RunThreads();
@@ -257,7 +270,7 @@ TEST_F(RequestSenderTest, RequestSendCupError) {
EXPECT_EQ(1, post_interceptor_1_->GetCount())
<< post_interceptor_1_->GetRequestsAsString();
- EXPECT_STREQ("test", post_interceptor_1_->GetRequests()[0].c_str());
+ EXPECT_STREQ("test", post_interceptor_1_->GetRequestBody(0).c_str());
EXPECT_EQ(RequestSender::kErrorResponseNotTrusted, error_);
EXPECT_TRUE(response_.empty());
}
diff --git a/chromium/components/update_client/test_configurator.cc b/chromium/components/update_client/test_configurator.cc
index 2543c156cb2..243a2a47b7d 100644
--- a/chromium/components/update_client/test_configurator.cc
+++ b/chromium/components/update_client/test_configurator.cc
@@ -8,13 +8,14 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/version.h"
-#include "components/patch_service/file_patcher_impl.h"
#include "components/patch_service/patch_service.h"
-#include "components/patch_service/public/interfaces/file_patcher.mojom.h"
#include "components/prefs/pref_service.h"
+#include "components/unzip_service/unzip_service.h"
#include "components/update_client/activity_data_service.h"
#include "net/url_request/url_request_test_util.h"
#include "services/service_manager/public/cpp/connector.h"
+#include "services/service_manager/public/cpp/service.h"
+#include "services/service_manager/public/cpp/test/test_connector_factory.h"
#include "url/gurl.h"
namespace update_client {
@@ -36,12 +37,17 @@ TestConfigurator::TestConfigurator()
ondemand_time_(0),
enabled_cup_signing_(false),
enabled_component_updates_(true),
- connector_factory_(
- service_manager::TestConnectorFactory::CreateForUniqueService(
- std::make_unique<patch::PatchService>())),
- connector_(connector_factory_->CreateConnector()),
context_(base::MakeRefCounted<net::TestURLRequestContextGetter>(
- base::ThreadTaskRunnerHandle::Get())) {}
+ base::ThreadTaskRunnerHandle::Get())) {
+ service_manager::TestConnectorFactory::NameToServiceMap services;
+ services.insert(
+ std::make_pair("patch_service", std::make_unique<patch::PatchService>()));
+ services.insert(
+ std::make_pair("unzip_service", std::make_unique<unzip::UnzipService>()));
+ connector_factory_ = service_manager::TestConnectorFactory::CreateForServices(
+ std::move(services));
+ connector_ = connector_factory_->CreateConnector();
+}
TestConfigurator::~TestConfigurator() {
}
@@ -109,8 +115,9 @@ std::string TestConfigurator::GetDownloadPreference() const {
return download_preference_;
}
-net::URLRequestContextGetter* TestConfigurator::RequestContext() const {
- return context_.get();
+scoped_refptr<net::URLRequestContextGetter> TestConfigurator::RequestContext()
+ const {
+ return context_;
}
std::unique_ptr<service_manager::Connector>
diff --git a/chromium/components/update_client/test_configurator.h b/chromium/components/update_client/test_configurator.h
index f911b5b98de..60ba6579c06 100644
--- a/chromium/components/update_client/test_configurator.h
+++ b/chromium/components/update_client/test_configurator.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -14,7 +15,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "components/update_client/configurator.h"
-#include "services/service_manager/public/cpp/test/test_connector_factory.h"
#include "url/gurl.h"
class PrefService;
@@ -26,7 +26,8 @@ class URLRequestContextGetter;
namespace service_manager {
class Connector;
-}
+class TestConnectorFactory;
+} // namespace service_manager
namespace update_client {
@@ -43,7 +44,7 @@ const uint8_t jebg_hash[] = {0x94, 0x16, 0x0b, 0x6d, 0x41, 0x75, 0xe9, 0xec,
0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47, 0xf6, 0xc4,
0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40};
// component 1 public key (base64 encoded):
-const std::string jebg_public_key =
+const char jebg_public_key[] =
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68bW8i/RzSaeXOcNLuBw0SP9+1bdo5ysLqH"
"qfLqZs6XyJWEyL0U6f1axPR6LwViku21kgdc6PI524eb8Cr+a/iXGgZ8SdvZTcfQ/g/ukwlblF"
"mtqYfDoVpz03U8rDQ9b6DxeJBF4r48TNlFORggrAiNR26qbf1i178Au12AzWtwIDAQAB";
@@ -85,7 +86,7 @@ class TestConfigurator : public Configurator {
std::string GetOSLongName() const override;
std::string ExtraRequestParams() const override;
std::string GetDownloadPreference() const override;
- net::URLRequestContextGetter* RequestContext() const override;
+ scoped_refptr<net::URLRequestContextGetter> RequestContext() const override;
std::unique_ptr<service_manager::Connector> CreateServiceManagerConnector()
const override;
bool EnabledDeltas() const override;
diff --git a/chromium/components/update_client/update_checker.cc b/chromium/components/update_client/update_checker.cc
index 8f9de17bda9..051c7e483cf 100644
--- a/chromium/components/update_client/update_checker.cc
+++ b/chromium/components/update_client/update_checker.cc
@@ -20,6 +20,7 @@
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
#include "components/update_client/component.h"
#include "components/update_client/configurator.h"
#include "components/update_client/persisted_data.h"
@@ -49,22 +50,26 @@ bool IsEncryptionRequired(const IdToComponentPtrMap& components) {
class UpdateCheckerImpl : public UpdateChecker {
public:
- UpdateCheckerImpl(const scoped_refptr<Configurator>& config,
+ UpdateCheckerImpl(scoped_refptr<Configurator> config,
PersistedData* metadata);
~UpdateCheckerImpl() override;
// Overrides for UpdateChecker.
- void CheckForUpdates(const std::vector<std::string>& ids_checked,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_checked,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override;
private:
void ReadUpdaterStateAttributes();
- void CheckForUpdatesHelper(const IdToComponentPtrMap& components,
+ void CheckForUpdatesHelper(const std::string& session_id,
+ const IdToComponentPtrMap& components,
const std::string& additional_attributes,
- bool enabled_component_updates);
+ bool enabled_component_updates,
+ bool is_foreground);
void OnRequestSenderComplete(const IdToComponentPtrMap& components,
int error,
const std::string& response,
@@ -88,7 +93,7 @@ class UpdateCheckerImpl : public UpdateChecker {
DISALLOW_COPY_AND_ASSIGN(UpdateCheckerImpl);
};
-UpdateCheckerImpl::UpdateCheckerImpl(const scoped_refptr<Configurator>& config,
+UpdateCheckerImpl::UpdateCheckerImpl(scoped_refptr<Configurator> config,
PersistedData* metadata)
: config_(config), metadata_(metadata) {}
@@ -97,10 +102,12 @@ UpdateCheckerImpl::~UpdateCheckerImpl() {
}
void UpdateCheckerImpl::CheckForUpdates(
+ const std::string& session_id,
const std::vector<std::string>& ids_checked,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -112,20 +119,31 @@ void UpdateCheckerImpl::CheckForUpdates(
base::BindOnce(&UpdateCheckerImpl::ReadUpdaterStateAttributes,
base::Unretained(this)),
base::BindOnce(&UpdateCheckerImpl::CheckForUpdatesHelper,
- base::Unretained(this), base::ConstRef(components),
- additional_attributes, enabled_component_updates));
+ base::Unretained(this), session_id,
+ base::ConstRef(components), additional_attributes,
+ enabled_component_updates, is_foreground));
}
// This function runs on the blocking pool task runner.
void UpdateCheckerImpl::ReadUpdaterStateAttributes() {
- const bool is_machine_install = !config_->IsPerUserInstall();
- updater_state_attributes_ = UpdaterState::GetState(is_machine_install);
+#if defined(OS_WIN)
+ // On Windows, the Chrome and the updater install modes are matched by design.
+ updater_state_attributes_ =
+ UpdaterState::GetState(!config_->IsPerUserInstall());
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+ // MacOS ignores this value in the current implementation but this may change.
+ updater_state_attributes_ = UpdaterState::GetState(false);
+#else
+// Other platforms don't have updaters.
+#endif // OS_WIN
}
void UpdateCheckerImpl::CheckForUpdatesHelper(
+ const std::string& session_id,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
- bool enabled_component_updates) {
+ bool enabled_component_updates,
+ bool is_foreground) {
DCHECK(thread_checker_.CalledOnValidThread());
auto urls(config_->UpdateUrl());
@@ -134,11 +152,13 @@ void UpdateCheckerImpl::CheckForUpdatesHelper(
request_sender_ = std::make_unique<RequestSender>(config_);
request_sender_->Send(
- config_->EnabledCupSigning(),
- BuildUpdateCheckRequest(*config_, ids_checked_, components, metadata_,
- additional_attributes, enabled_component_updates,
- updater_state_attributes_),
urls,
+ BuildUpdateCheckExtraRequestHeaders(config_, ids_checked_, is_foreground),
+ BuildUpdateCheckRequest(*config_, session_id, ids_checked_, components,
+ metadata_, additional_attributes,
+ enabled_component_updates,
+ updater_state_attributes_),
+ config_->EnabledCupSigning(),
base::BindOnce(&UpdateCheckerImpl::OnRequestSenderComplete,
base::Unretained(this), base::ConstRef(components)));
}
@@ -221,7 +241,7 @@ void UpdateCheckerImpl::UpdateCheckFailed(const IdToComponentPtrMap& components,
} // namespace
std::unique_ptr<UpdateChecker> UpdateChecker::Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* persistent) {
return std::make_unique<UpdateCheckerImpl>(config, persistent);
}
diff --git a/chromium/components/update_client/update_checker.h b/chromium/components/update_client/update_checker.h
index 0f2cb3edfab..24e224ac879 100644
--- a/chromium/components/update_client/update_checker.h
+++ b/chromium/components/update_client/update_checker.h
@@ -25,9 +25,9 @@ class UpdateChecker {
using UpdateCheckCallback =
base::OnceCallback<void(int error, int retry_after_sec)>;
- using Factory = std::unique_ptr<UpdateChecker> (*)(
- const scoped_refptr<Configurator>& config,
- PersistedData* persistent);
+ using Factory =
+ std::unique_ptr<UpdateChecker> (*)(scoped_refptr<Configurator> config,
+ PersistedData* persistent);
virtual ~UpdateChecker() = default;
@@ -35,16 +35,20 @@ class UpdateChecker {
// |additional_attributes| provides a way to customize the <request> element.
// This value is inserted as-is, therefore it must be well-formed as an
// XML attribute string.
+ // |is_foreground| controls the value of "X-GoogleUpdate-Interactivity"
+ // header which is sent with the update check.
// On completion, the state of |components| is mutated as required by the
// server response received.
- virtual void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ virtual void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) = 0;
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* persistent);
protected:
diff --git a/chromium/components/update_client/update_checker_unittest.cc b/chromium/components/update_client/update_checker_unittest.cc
index 23a03fd3b95..76186725d53 100644
--- a/chromium/components/update_client/update_checker_unittest.cc
+++ b/chromium/components/update_client/update_checker_unittest.cc
@@ -104,7 +104,8 @@ void ActivityDataServiceTest::SetDaysSinceLastRollCall(const std::string& id,
} // namespace
-class UpdateCheckerTest : public testing::Test {
+class UpdateCheckerTest : public testing::Test,
+ public ::testing::WithParamInterface<bool> {
public:
UpdateCheckerTest();
~UpdateCheckerTest() override;
@@ -146,6 +147,8 @@ class UpdateCheckerTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(UpdateCheckerTest);
};
+INSTANTIATE_TEST_CASE_P(IsForeground, UpdateCheckerTest, ::testing::Bool());
+
UpdateCheckerTest::UpdateCheckerTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
@@ -189,12 +192,6 @@ void UpdateCheckerTest::RunThreads() {
base::RunLoop runloop;
quit_closure_ = runloop.QuitClosure();
runloop.Run();
-
- // Since some tests need to drain currently enqueued tasks such as network
- // intercepts on the IO thread, run the threads until they are
- // idle. The component updater service won't loop again until the loop count
- // is set and the service is started.
- scoped_task_environment_.RunUntilIdle();
}
void UpdateCheckerTest::Quit() {
@@ -231,7 +228,7 @@ std::unique_ptr<Component> UpdateCheckerTest::MakeComponent() const {
return component;
}
-TEST_F(UpdateCheckerTest, UpdateCheckSuccess) {
+TEST_P(UpdateCheckerTest, UpdateCheckSuccess) {
EXPECT_TRUE(post_interceptor_->ExpectRequest(
new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
@@ -243,9 +240,10 @@ TEST_F(UpdateCheckerTest, UpdateCheckSuccess) {
auto& component = components[kUpdateItemId];
component->crx_component_.installer_attributes["ap"] = "some_ap";
+ const bool is_foreground = GetParam();
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
- true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "extra=\"params\"", true, is_foreground,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
@@ -256,9 +254,9 @@ TEST_F(UpdateCheckerTest, UpdateCheckSuccess) {
<< post_interceptor_->GetRequestsAsString();
// Sanity check the request.
- const auto request = post_interceptor_->GetRequests()[0];
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
- "request protocol=\"3.1\" extra=\"params\""));
+ const auto request = post_interceptor_->GetRequestBody(0);
+ EXPECT_NE(string::npos,
+ request.find("request protocol=\"3.1\" extra=\"params\""));
// The request must not contain any "dlpref" in the default case.
EXPECT_EQ(string::npos, request.find(" dlpref=\""));
EXPECT_NE(string::npos,
@@ -276,6 +274,9 @@ TEST_F(UpdateCheckerTest, UpdateCheckSuccess) {
string::npos,
request.find(" version=\"fake_prodid-30.0\" prodversion=\"30.0\" "));
+ // Tests that there is a sessionid attribute.
+ EXPECT_NE(string::npos, request.find(" sessionid="));
+
// Sanity check the arguments of the callback after parsing.
EXPECT_EQ(0, error_);
@@ -295,6 +296,17 @@ TEST_F(UpdateCheckerTest, UpdateCheckSuccess) {
EXPECT_NE(string::npos, request.find(" name=\"Omaha\" "));
#endif // GOOGLE_CHROME_BUILD
#endif // OS_WINDOWS
+
+ // Check the interactivity header value.
+ const auto extra_request_headers = post_interceptor_->GetRequests()[0].second;
+ EXPECT_TRUE(extra_request_headers.HasHeader("X-GoogleUpdate-Interactivity"));
+ std::string header;
+ extra_request_headers.GetHeader("X-GoogleUpdate-Interactivity", &header);
+ EXPECT_STREQ(is_foreground ? "fg" : "bg", header.c_str());
+ extra_request_headers.GetHeader("X-GoogleUpdate-Updater", &header);
+ EXPECT_STREQ("fake_prodid-30.0", header.c_str());
+ extra_request_headers.GetHeader("X-GoogleUpdate-AppId", &header);
+ EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", header.c_str());
}
// Tests that an invalid "ap" is not serialized.
@@ -312,19 +324,20 @@ TEST_F(UpdateCheckerTest, UpdateCheckInvalidAp) {
component->crx_component_.installer_attributes["ap"] = std::string(257, 'a');
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
- std::string("app appid=\"") + kUpdateItemId +
- "\" version=\"0.9\" brand=\"TEST\" enabled=\"1\">"
- "<updatecheck/><ping r=\"-2\" "));
+ const auto request = post_interceptor_->GetRequestBody(0);
+ EXPECT_NE(string::npos,
+ request.find(std::string("app appid=\"") + kUpdateItemId +
+ "\" version=\"0.9\" brand=\"TEST\" enabled=\"1\">"
+ "<updatecheck/><ping r=\"-2\" "));
EXPECT_NE(string::npos,
- post_interceptor_->GetRequests()[0].find(
- "<packages><package fp=\"fp1\"/></packages></app>"));
+ request.find("<packages><package fp=\"fp1\"/></packages></app>"));
}
TEST_F(UpdateCheckerTest, UpdateCheckSuccessNoBrand) {
@@ -338,19 +351,20 @@ TEST_F(UpdateCheckerTest, UpdateCheckSuccessNoBrand) {
components[kUpdateItemId] = MakeComponent();
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
- std::string("<app appid=\"") + kUpdateItemId +
- "\" version=\"0.9\" enabled=\"1\">"
- "<updatecheck/><ping r=\"-2\" "));
+ const auto request = post_interceptor_->GetRequestBody(0);
EXPECT_NE(string::npos,
- post_interceptor_->GetRequests()[0].find(
- "<packages><package fp=\"fp1\"/></packages></app>"));
+ request.find(std::string("<app appid=\"") + kUpdateItemId +
+ "\" version=\"0.9\" enabled=\"1\">"
+ "<updatecheck/><ping r=\"-2\" "));
+ EXPECT_NE(string::npos,
+ request.find("<packages><package fp=\"fp1\"/></packages></app>"));
}
// Simulates a 403 server response error.
@@ -366,7 +380,8 @@ TEST_F(UpdateCheckerTest, UpdateCheckError) {
auto& component = components[kUpdateItemId];
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
@@ -392,16 +407,16 @@ TEST_F(UpdateCheckerTest, UpdateCheckDownloadPreference) {
components[kUpdateItemId] = MakeComponent();
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
- true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "extra=\"params\"", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
// The request must contain dlpref="cacheable".
- EXPECT_NE(string::npos,
- post_interceptor_->GetRequests()[0].find(" dlpref=\"cacheable\""));
+ const auto request = post_interceptor_->GetRequestBody(0);
+ EXPECT_NE(string::npos, request.find(" dlpref=\"cacheable\""));
}
// This test is checking that an update check signed with CUP fails, since there
@@ -420,7 +435,8 @@ TEST_F(UpdateCheckerTest, UpdateCheckCupError) {
const auto& component = components[kUpdateItemId];
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
@@ -432,14 +448,14 @@ TEST_F(UpdateCheckerTest, UpdateCheckCupError) {
<< post_interceptor_->GetRequestsAsString();
// Sanity check the request.
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
- std::string("<app appid=\"") + kUpdateItemId +
- "\" version=\"0.9\" "
- "brand=\"TEST\" enabled=\"1\">"
- "<updatecheck/><ping r=\"-2\" "));
+ const auto request = post_interceptor_->GetRequestBody(0);
+ EXPECT_NE(string::npos,
+ request.find(std::string("<app appid=\"") + kUpdateItemId +
+ "\" version=\"0.9\" "
+ "brand=\"TEST\" enabled=\"1\">"
+ "<updatecheck/><ping r=\"-2\" "));
EXPECT_NE(string::npos,
- post_interceptor_->GetRequests()[0].find(
- "<packages><package fp=\"fp1\"/></packages></app>"));
+ request.find("<packages><package fp=\"fp1\"/></packages></app>"));
// Expect an error since the response is not trusted.
EXPECT_EQ(-10000, error_);
@@ -460,7 +476,8 @@ TEST_F(UpdateCheckerTest, UpdateCheckRequiresEncryptionError) {
component->crx_component_.requires_network_encryption = true;
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
@@ -485,16 +502,16 @@ TEST_F(UpdateCheckerTest, UpdateCheckLastRollCall) {
// Do two update-checks.
activity_data_service_->SetDaysSinceLastRollCall(kUpdateItemId, 5);
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
- true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "extra=\"params\"", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
- true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "extra=\"params\"", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
@@ -503,9 +520,9 @@ TEST_F(UpdateCheckerTest, UpdateCheckLastRollCall) {
<< post_interceptor_->GetRequestsAsString();
ASSERT_EQ(2, post_interceptor_->GetCount())
<< post_interceptor_->GetRequestsAsString();
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(0).find(
"<ping r=\"5\" ping_freshness="));
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(1).find(
"<ping rd=\"3383\" ping_freshness="));
}
@@ -525,8 +542,8 @@ TEST_F(UpdateCheckerTest, UpdateCheckLastActive) {
activity_data_service_->SetActiveBit(kUpdateItemId, true);
activity_data_service_->SetDaysSinceLastActive(kUpdateItemId, 10);
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
- true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "extra=\"params\"", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
@@ -537,8 +554,8 @@ TEST_F(UpdateCheckerTest, UpdateCheckLastActive) {
activity_data_service_->SetActiveBit(kUpdateItemId, true);
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
- true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "extra=\"params\"", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
@@ -548,8 +565,8 @@ TEST_F(UpdateCheckerTest, UpdateCheckLastActive) {
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "extra=\"params\"",
- true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "extra=\"params\"", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
@@ -560,18 +577,15 @@ TEST_F(UpdateCheckerTest, UpdateCheckLastActive) {
<< post_interceptor_->GetRequestsAsString();
ASSERT_EQ(3, post_interceptor_->GetCount())
<< post_interceptor_->GetRequestsAsString();
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(0).find(
"<ping a=\"10\" r=\"-2\" ping_freshness="));
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(1).find(
"<ping ad=\"3383\" rd=\"3383\" ping_freshness="));
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(2).find(
"<ping rd=\"3383\" ping_freshness="));
}
TEST_F(UpdateCheckerTest, UpdateCheckInstallSource) {
- EXPECT_TRUE(post_interceptor_->ExpectRequest(
- new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
-
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
IdToComponentPtrMap components;
@@ -580,52 +594,61 @@ TEST_F(UpdateCheckerTest, UpdateCheckInstallSource) {
auto& component = components[kUpdateItemId];
auto& crx_component = const_cast<CrxComponent&>(component->crx_component());
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", false,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", false, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
EXPECT_EQ(string::npos,
- post_interceptor_->GetRequests()[0].find("intallsource="));
+ post_interceptor_->GetRequestBody(0).find("installsource="));
component->set_on_demand(true);
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", false,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", false, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(1).find(
"installsource=\"ondemand\""));
component->set_on_demand(false);
crx_component.install_source = "webstore";
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", false,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", false, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(2).find(
"installsource=\"webstore\""));
component->set_on_demand(true);
crx_component.install_source = "sideload";
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", false,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", false, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(3).find(
"installsource=\"sideload\""));
}
TEST_F(UpdateCheckerTest, ComponentDisabled) {
- EXPECT_TRUE(post_interceptor_->ExpectRequest(
- new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
-
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
IdToComponentPtrMap components;
@@ -634,90 +657,105 @@ TEST_F(UpdateCheckerTest, ComponentDisabled) {
auto& component = components[kUpdateItemId];
auto& crx_component = const_cast<CrxComponent&>(component->crx_component());
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", false,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", false, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
EXPECT_NE(string::npos,
- post_interceptor_->GetRequests()[0].find("enabled=\"1\""));
+ post_interceptor_->GetRequestBody(0).find("enabled=\"1\""));
EXPECT_EQ(string::npos,
- post_interceptor_->GetRequests()[0].find("<disabled"));
+ post_interceptor_->GetRequestBody(0).find("<disabled"));
crx_component.disabled_reasons = std::vector<int>();
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", false,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", false, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
EXPECT_NE(string::npos,
- post_interceptor_->GetRequests()[1].find("enabled=\"1\""));
+ post_interceptor_->GetRequestBody(1).find("enabled=\"1\""));
EXPECT_EQ(string::npos,
- post_interceptor_->GetRequests()[1].find("<disabled"));
+ post_interceptor_->GetRequestBody(1).find("<disabled"));
crx_component.disabled_reasons = std::vector<int>({0});
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", false,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", false, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
EXPECT_NE(string::npos,
- post_interceptor_->GetRequests()[2].find("enabled=\"0\""));
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
+ post_interceptor_->GetRequestBody(2).find("enabled=\"0\""));
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(2).find(
"<disabled reason=\"0\"/>"));
crx_component.disabled_reasons = std::vector<int>({1});
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", false,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", false, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
EXPECT_NE(string::npos,
- post_interceptor_->GetRequests()[3].find("enabled=\"0\""));
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find(
+ post_interceptor_->GetRequestBody(3).find("enabled=\"0\""));
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(3).find(
"<disabled reason=\"1\"/>"));
crx_component.disabled_reasons = std::vector<int>({4, 8, 16});
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", false,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", false, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
EXPECT_NE(string::npos,
- post_interceptor_->GetRequests()[4].find("enabled=\"0\""));
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[4].find(
+ post_interceptor_->GetRequestBody(4).find("enabled=\"0\""));
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(4).find(
"<disabled reason=\"4\"/>"));
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[4].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(4).find(
"<disabled reason=\"8\"/>"));
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[4].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(4).find(
"<disabled reason=\"16\"/>"));
crx_component.disabled_reasons = std::vector<int>({0, 4, 8, 16});
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", false,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", false, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
EXPECT_NE(string::npos,
- post_interceptor_->GetRequests()[5].find("enabled=\"0\""));
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[5].find(
+ post_interceptor_->GetRequestBody(5).find("enabled=\"0\""));
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(5).find(
"<disabled reason=\"0\"/>"));
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[5].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(5).find(
"<disabled reason=\"4\"/>"));
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[5].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(5).find(
"<disabled reason=\"8\"/>"));
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[5].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(5).find(
"<disabled reason=\"16\"/>"));
}
TEST_F(UpdateCheckerTest, UpdateCheckUpdateDisabled) {
- EXPECT_TRUE(post_interceptor_->ExpectRequest(
- new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
-
config_->SetBrand("");
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
@@ -734,12 +772,15 @@ TEST_F(UpdateCheckerTest, UpdateCheckUpdateDisabled) {
EXPECT_FALSE(
component->crx_component_.supports_group_policy_enable_component_updates);
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", false,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", false, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(0).find(
std::string("<app appid=\"") + kUpdateItemId +
"\" version=\"0.9\" enabled=\"1\">"
"<updatecheck/>"));
@@ -751,12 +792,15 @@ TEST_F(UpdateCheckerTest, UpdateCheckUpdateDisabled) {
component->crx_component_.supports_group_policy_enable_component_updates =
true;
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", false,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", false, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(1).find(
std::string("<app appid=\"") + kUpdateItemId +
"\" version=\"0.9\" enabled=\"1\">"
"<updatecheck updatedisabled=\"true\"/>"));
@@ -768,12 +812,15 @@ TEST_F(UpdateCheckerTest, UpdateCheckUpdateDisabled) {
component->crx_component_.supports_group_policy_enable_component_updates =
false;
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(2).find(
std::string("<app appid=\"") + kUpdateItemId +
"\" version=\"0.9\" enabled=\"1\">"
"<updatecheck/>"));
@@ -785,12 +832,15 @@ TEST_F(UpdateCheckerTest, UpdateCheckUpdateDisabled) {
component->crx_component_.supports_group_policy_enable_component_updates =
true;
update_checker_ = UpdateChecker::Create(config_, metadata_.get());
+ EXPECT_TRUE(post_interceptor_->ExpectRequest(
+ new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml")));
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
- EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find(
+ EXPECT_NE(string::npos, post_interceptor_->GetRequestBody(3).find(
std::string("<app appid=\"") + kUpdateItemId +
"\" version=\"0.9\" enabled=\"1\">"
"<updatecheck/>"));
@@ -809,7 +859,8 @@ TEST_F(UpdateCheckerTest, NoUpdateActionRun) {
auto& component = components[kUpdateItemId];
update_checker_->CheckForUpdates(
- std::vector<std::string>{kUpdateItemId}, components, "", true,
+ update_context_->session_id, std::vector<std::string>{kUpdateItemId},
+ components, "", true, true,
base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
base::Unretained(this)));
RunThreads();
diff --git a/chromium/components/update_client/update_client.cc b/chromium/components/update_client/update_client.cc
index 8ea68cbcd58..c6035ed3e45 100644
--- a/chromium/components/update_client/update_client.cc
+++ b/chromium/components/update_client/update_client.cc
@@ -17,7 +17,6 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/observer_list.h"
-#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/prefs/pref_registry_simple.h"
@@ -61,13 +60,13 @@ CrxComponent::~CrxComponent() {
// the UpdateClient instance exceeds the life time of its inner members,
// including any thread objects that might execute callbacks bound to it.
UpdateClientImpl::UpdateClientImpl(
- const scoped_refptr<Configurator>& config,
- std::unique_ptr<PingManager> ping_manager,
+ scoped_refptr<Configurator> config,
+ scoped_refptr<PingManager> ping_manager,
UpdateChecker::Factory update_checker_factory,
CrxDownloader::Factory crx_downloader_factory)
: is_stopped_(false),
config_(config),
- ping_manager_(std::move(ping_manager)),
+ ping_manager_(ping_manager),
update_engine_(std::make_unique<UpdateEngine>(
config,
update_checker_factory,
@@ -240,9 +239,9 @@ void UpdateClientImpl::SendUninstallPing(const std::string& id,
}
scoped_refptr<UpdateClient> UpdateClientFactory(
- const scoped_refptr<Configurator>& config) {
+ scoped_refptr<Configurator> config) {
return base::MakeRefCounted<UpdateClientImpl>(
- config, std::make_unique<PingManager>(config), &UpdateChecker::Create,
+ config, base::MakeRefCounted<PingManager>(config), &UpdateChecker::Create,
&CrxDownloader::Create);
}
diff --git a/chromium/components/update_client/update_client.h b/chromium/components/update_client/update_client.h
index a806057ffe9..3b883b8ac67 100644
--- a/chromium/components/update_client/update_client.h
+++ b/chromium/components/update_client/update_client.h
@@ -299,10 +299,15 @@ class UpdateClient : public base::RefCounted<UpdateClient> {
// Sent when a CRX has been successfully updated.
COMPONENT_UPDATED,
- // Sent when a CRX has not been updated following an update check:
- // either there was no update available, or the update failed.
+ // Sent when a CRX has not been updated because there was no update
+ // available for this component.
COMPONENT_NOT_UPDATED,
+ // Sent when an error ocurred during an update for any reason, including
+ // the update check itself failed, or the download of the update payload
+ // failed, or applying the update failed.
+ COMPONENT_UPDATE_ERROR,
+
// Sent when CRX bytes are being downloaded.
COMPONENT_UPDATE_DOWNLOADING,
};
@@ -382,7 +387,7 @@ class UpdateClient : public base::RefCounted<UpdateClient> {
// Creates an instance of the update client.
scoped_refptr<UpdateClient> UpdateClientFactory(
- const scoped_refptr<Configurator>& config);
+ scoped_refptr<Configurator> config);
// This must be called prior to the construction of any Configurator that
// contains a PrefService.
diff --git a/chromium/components/update_client/update_client_internal.h b/chromium/components/update_client/update_client_internal.h
index 6684b7eebca..d0127e6606a 100644
--- a/chromium/components/update_client/update_client_internal.h
+++ b/chromium/components/update_client/update_client_internal.h
@@ -29,8 +29,8 @@ enum class Error;
class UpdateClientImpl : public UpdateClient {
public:
- UpdateClientImpl(const scoped_refptr<Configurator>& config,
- std::unique_ptr<PingManager> ping_manager,
+ UpdateClientImpl(scoped_refptr<Configurator> config,
+ scoped_refptr<PingManager> ping_manager,
UpdateChecker::Factory update_checker_factory,
CrxDownloader::Factory crx_downloader_factory);
@@ -81,7 +81,7 @@ class UpdateClientImpl : public UpdateClient {
std::set<Task*> tasks_;
// TODO(sorin): try to make the ping manager an observer of the service.
- std::unique_ptr<PingManager> ping_manager_;
+ scoped_refptr<PingManager> ping_manager_;
std::unique_ptr<UpdateEngine> update_engine_;
base::ObserverList<Observer> observer_list_;
diff --git a/chromium/components/update_client/update_client_unittest.cc b/chromium/components/update_client/update_client_unittest.cc
index 3c23319cf4f..e4215b2cc6a 100644
--- a/chromium/components/update_client/update_client_unittest.cc
+++ b/chromium/components/update_client/update_client_unittest.cc
@@ -21,6 +21,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "base/version.h"
+#include "build/build_config.h"
#include "components/prefs/testing_pref_service.h"
#include "components/update_client/component_unpacker.h"
#include "components/update_client/crx_update_item.h"
@@ -101,29 +102,31 @@ class FakePingManagerImpl : public PingManager {
bool diff_update_failed = false;
};
- explicit FakePingManagerImpl(const scoped_refptr<Configurator>& config);
- ~FakePingManagerImpl() override;
+ explicit FakePingManagerImpl(scoped_refptr<Configurator> config);
- bool SendPing(const Component& component) override;
+ void SendPing(const Component& component, Callback callback) override;
const std::vector<PingData>& ping_data() const;
const std::vector<std::string>& events() const;
+ protected:
+ ~FakePingManagerImpl() override;
+
private:
std::vector<PingData> ping_data_;
std::vector<std::string> events_;
DISALLOW_COPY_AND_ASSIGN(FakePingManagerImpl);
};
-FakePingManagerImpl::FakePingManagerImpl(
- const scoped_refptr<Configurator>& config)
+FakePingManagerImpl::FakePingManagerImpl(scoped_refptr<Configurator> config)
: PingManager(config) {}
FakePingManagerImpl::~FakePingManagerImpl() {
}
-bool FakePingManagerImpl::SendPing(const Component& component) {
+void FakePingManagerImpl::SendPing(const Component& component,
+ Callback callback) {
PingData ping_data;
ping_data.id = component.id_;
ping_data.previous_version = component.previous_version_;
@@ -139,7 +142,7 @@ bool FakePingManagerImpl::SendPing(const Component& component) {
const auto& events = component.events();
events_.insert(events_.end(), events.begin(), events.end());
- return true;
+ std::move(callback).Run(0, "");
}
const std::vector<FakePingManagerImpl::PingData>&
@@ -234,16 +237,19 @@ TEST_F(UpdateClientTest, OneCrxNoUpdate) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
+ EXPECT_FALSE(session_id.empty());
EXPECT_TRUE(enabled_component_updates);
EXPECT_EQ(1u, ids_to_check.size());
const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
@@ -268,7 +274,7 @@ TEST_F(UpdateClientTest, OneCrxNoUpdate) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -280,14 +286,16 @@ TEST_F(UpdateClientTest, OneCrxNoUpdate) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override { EXPECT_TRUE(ping_data().empty()); }
};
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -344,15 +352,17 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
/*
Fake the following response:
@@ -375,7 +385,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
</app>
</response>
*/
-
+ EXPECT_FALSE(session_id.empty());
EXPECT_TRUE(enabled_component_updates);
EXPECT_EQ(2u, ids_to_check.size());
@@ -427,7 +437,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -466,8 +476,10 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override {
const auto ping_data = FakePingManagerImpl::ping_data();
EXPECT_EQ(1u, ping_data.size());
@@ -481,7 +493,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -554,15 +566,17 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
/*
Fake the following response:
@@ -599,6 +613,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) {
</app>
</response>
*/
+ EXPECT_FALSE(session_id.empty());
EXPECT_TRUE(enabled_component_updates);
EXPECT_EQ(2u, ids_to_check.size());
@@ -659,7 +674,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -718,8 +733,10 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override {
const auto ping_data = FakePingManagerImpl::ping_data();
EXPECT_EQ(2u, ping_data.size());
@@ -738,7 +755,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdate) {
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -822,15 +839,17 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
/*
Fake the following response:
@@ -868,6 +887,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
</response>
*/
+ EXPECT_FALSE(session_id.empty());
EXPECT_TRUE(enabled_component_updates);
EXPECT_EQ(2u, ids_to_check.size());
@@ -924,7 +944,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -980,8 +1000,10 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override {
const auto ping_data = FakePingManagerImpl::ping_data();
EXPECT_EQ(2u, ping_data.size());
@@ -1000,7 +1022,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -1013,8 +1035,9 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
"jebgalgnebhfojomionfpkfelancnnkf"))
.Times(AtLeast(1));
- EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
- "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
+ EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
+ "jebgalgnebhfojomionfpkfelancnnkf"))
+ .Times(1);
}
{
InSequence seq;
@@ -1088,16 +1111,20 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
+ EXPECT_FALSE(session_id.empty());
+
static int num_call = 0;
++num_call;
@@ -1206,7 +1233,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -1265,8 +1292,10 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override {
const auto ping_data = FakePingManagerImpl::ping_data();
EXPECT_EQ(2u, ping_data.size());
@@ -1288,7 +1317,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -1414,15 +1443,17 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
/*
Fake the following response:
@@ -1445,6 +1476,8 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
</app>
</response>
*/
+ EXPECT_FALSE(session_id.empty());
+
const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
EXPECT_EQ(id, ids_to_check[0]);
EXPECT_EQ(1u, components.count(id));
@@ -1474,7 +1507,7 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -1513,8 +1546,10 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override {
const auto ping_data = FakePingManagerImpl::ping_data();
EXPECT_EQ(1u, ping_data.size());
@@ -1528,7 +1563,7 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -1543,8 +1578,9 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
.Times(AtLeast(1));
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY,
"jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
- EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
- "jebgalgnebhfojomionfpkfelancnnkf")).Times(1);
+ EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
+ "jebgalgnebhfojomionfpkfelancnnkf"))
+ .Times(1);
}
update_client->AddObserver(&observer);
@@ -1600,16 +1636,20 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
+ EXPECT_FALSE(session_id.empty());
+
static int num_call = 0;
++num_call;
@@ -1720,7 +1760,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -1791,8 +1831,10 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override {
const auto ping_data = FakePingManagerImpl::ping_data();
EXPECT_EQ(2u, ping_data.size());
@@ -1814,7 +1856,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -1901,16 +1943,19 @@ TEST_F(UpdateClientTest, OneCrxNoUpdateQueuedCall) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
+ EXPECT_FALSE(session_id.empty());
EXPECT_TRUE(enabled_component_updates);
EXPECT_EQ(1u, ids_to_check.size());
const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
@@ -1935,7 +1980,7 @@ TEST_F(UpdateClientTest, OneCrxNoUpdateQueuedCall) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -1947,16 +1992,16 @@ TEST_F(UpdateClientTest, OneCrxNoUpdateQueuedCall) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override { EXPECT_TRUE(ping_data().empty()); }
};
- std::unique_ptr<PingManager> ping_manager =
- std::make_unique<FakePingManager>(config());
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -2012,15 +2057,17 @@ TEST_F(UpdateClientTest, OneCrxInstall) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
/*
Fake the following response:
@@ -2043,6 +2090,7 @@ TEST_F(UpdateClientTest, OneCrxInstall) {
</app>
</response>
*/
+ EXPECT_FALSE(session_id.empty());
EXPECT_TRUE(enabled_component_updates);
EXPECT_EQ(1u, ids_to_check.size());
@@ -2078,7 +2126,7 @@ TEST_F(UpdateClientTest, OneCrxInstall) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -2121,8 +2169,10 @@ TEST_F(UpdateClientTest, OneCrxInstall) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override {
const auto ping_data = FakePingManagerImpl::ping_data();
EXPECT_EQ(1u, ping_data.size());
@@ -2136,7 +2186,7 @@ TEST_F(UpdateClientTest, OneCrxInstall) {
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -2203,16 +2253,19 @@ TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
+ EXPECT_FALSE(session_id.empty());
EXPECT_TRUE(enabled_component_updates);
EXPECT_EQ(1u, ids_to_check.size());
const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
@@ -2238,7 +2291,7 @@ TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -2250,16 +2303,16 @@ TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override { EXPECT_TRUE(ping_data().empty()); }
};
- std::unique_ptr<FakePingManager> ping_manager =
- std::make_unique<FakePingManager>(config());
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -2307,23 +2360,27 @@ TEST_F(UpdateClientTest, EmptyIdList) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
- UpdateCheckCallback update_check_callback) override {}
+ bool is_foreground,
+ UpdateCheckCallback update_check_callback) override {
+ NOTREACHED();
+ }
};
class FakeCrxDownloader : public CrxDownloader {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -2333,9 +2390,18 @@ TEST_F(UpdateClientTest, EmptyIdList) {
void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
};
+ class FakePingManager : public FakePingManagerImpl {
+ public:
+ explicit FakePingManager(scoped_refptr<Configurator> config)
+ : FakePingManagerImpl(config) {}
+
+ protected:
+ ~FakePingManager() override { EXPECT_TRUE(ping_data().empty()); }
+ };
+
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManagerImpl>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
const std::vector<std::string> empty_id_list;
@@ -2356,23 +2422,27 @@ TEST_F(UpdateClientTest, SendUninstallPing) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return nullptr;
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
- UpdateCheckCallback update_check_callback) override {}
+ bool is_foreground,
+ UpdateCheckCallback update_check_callback) override {
+ NOTREACHED();
+ }
};
class FakeCrxDownloader : public CrxDownloader {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return nullptr;
}
@@ -2385,8 +2455,10 @@ TEST_F(UpdateClientTest, SendUninstallPing) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override {
const auto ping_data = FakePingManagerImpl::ping_data();
EXPECT_EQ(1u, ping_data.size());
@@ -2399,7 +2471,7 @@ TEST_F(UpdateClientTest, SendUninstallPing) {
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
update_client->SendUninstallPing(
@@ -2454,16 +2526,20 @@ TEST_F(UpdateClientTest, RetryAfter) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
+ EXPECT_FALSE(session_id.empty());
+
static int num_call = 0;
++num_call;
@@ -2497,7 +2573,7 @@ TEST_F(UpdateClientTest, RetryAfter) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -2509,14 +2585,16 @@ TEST_F(UpdateClientTest, RetryAfter) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override { EXPECT_TRUE(ping_data().empty()); }
};
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -2627,15 +2705,17 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
/*
Fake the following response:
@@ -2677,8 +2757,8 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
// configurator instance, persists its value in the corresponding
// update context, and propagates it down to each of the update actions,
// and further down to the UpdateChecker instance.
+ EXPECT_FALSE(session_id.empty());
EXPECT_FALSE(enabled_component_updates);
-
EXPECT_EQ(2u, ids_to_check.size());
{
@@ -2734,7 +2814,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -2777,8 +2857,10 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override {
const auto ping_data = FakePingManagerImpl::ping_data();
EXPECT_EQ(2u, ping_data.size());
@@ -2799,7 +2881,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
config()->SetEnabledComponentUpdates(false);
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -2811,7 +2893,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND,
"jebgalgnebhfojomionfpkfelancnnkf"))
.Times(1);
- EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
+ EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
"jebgalgnebhfojomionfpkfelancnnkf"))
.Times(1);
}
@@ -2873,16 +2955,19 @@ TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
+ EXPECT_FALSE(session_id.empty());
EXPECT_TRUE(enabled_component_updates);
EXPECT_EQ(1u, ids_to_check.size());
const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
@@ -2898,7 +2983,7 @@ TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -2910,14 +2995,16 @@ TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override { EXPECT_TRUE(ping_data().empty()); }
};
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
MockObserver observer;
@@ -2925,7 +3012,7 @@ TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) {
EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
"jebgalgnebhfojomionfpkfelancnnkf"))
.Times(1);
- EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED,
+ EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
"jebgalgnebhfojomionfpkfelancnnkf"))
.Times(1)
.WillOnce(Invoke([&update_client](Events event, const std::string& id) {
@@ -2953,15 +3040,17 @@ TEST_F(UpdateClientTest, ActionRun_Install) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
/*
Fake the following response:
@@ -2986,6 +3075,7 @@ TEST_F(UpdateClientTest, ActionRun_Install) {
</app>
</response>
*/
+ EXPECT_FALSE(session_id.empty());
EXPECT_TRUE(enabled_component_updates);
EXPECT_EQ(1u, ids_to_check.size());
@@ -3019,7 +3109,7 @@ TEST_F(UpdateClientTest, ActionRun_Install) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -3058,8 +3148,10 @@ TEST_F(UpdateClientTest, ActionRun_Install) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override {
const auto& events = FakePingManagerImpl::events();
EXPECT_EQ(3u, events.size());
@@ -3083,7 +3175,7 @@ TEST_F(UpdateClientTest, ActionRun_Install) {
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
// The action is a program which returns 1877345072 as a hardcoded value.
@@ -3114,15 +3206,17 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
class FakeUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
PersistedData* metadata) {
return std::make_unique<FakeUpdateChecker>();
}
- void CheckForUpdates(const std::vector<std::string>& ids_to_check,
+ void CheckForUpdates(const std::string& session_id,
+ const std::vector<std::string>& ids_to_check,
const IdToComponentPtrMap& components,
const std::string& additional_attributes,
bool enabled_component_updates,
+ bool is_foreground,
UpdateCheckCallback update_check_callback) override {
/*
Fake the following response:
@@ -3138,6 +3232,7 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
</app>
</response>
*/
+ EXPECT_FALSE(session_id.empty());
EXPECT_EQ(1u, ids_to_check.size());
const std::string id = "gjpmebpgbhcamgdgjcmnjfhggjpgcimm";
EXPECT_EQ(id, ids_to_check[0]);
@@ -3161,7 +3256,7 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
public:
static std::unique_ptr<CrxDownloader> Create(
bool is_background_download,
- net::URLRequestContextGetter* context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> context_getter) {
return std::make_unique<FakeCrxDownloader>();
}
@@ -3173,8 +3268,10 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
class FakePingManager : public FakePingManagerImpl {
public:
- explicit FakePingManager(const scoped_refptr<Configurator>& config)
+ explicit FakePingManager(scoped_refptr<Configurator> config)
: FakePingManagerImpl(config) {}
+
+ protected:
~FakePingManager() override {
const auto& events = FakePingManagerImpl::events();
EXPECT_EQ(1u, events.size());
@@ -3192,9 +3289,11 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
base::RunLoop runloop;
base::OnceClosure quit_closure = runloop.QuitClosure();
+ auto config = base::MakeRefCounted<TestConfigurator>();
scoped_refptr<ComponentUnpacker> component_unpacker = new ComponentUnpacker(
std::vector<uint8_t>(std::begin(gjpm_hash), std::end(gjpm_hash)),
- TestFilePath("runaction_test_win.crx3"), nullptr, nullptr);
+ TestFilePath("runaction_test_win.crx3"), nullptr,
+ config->CreateServiceManagerConnector());
component_unpacker->Unpack(base::BindOnce(
[](base::FilePath* unpack_path, base::OnceClosure quit_closure,
@@ -3221,7 +3320,7 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
scoped_refptr<UpdateClient> update_client =
base::MakeRefCounted<UpdateClientImpl>(
- config(), std::make_unique<FakePingManager>(config()),
+ config(), base::MakeRefCounted<FakePingManager>(config()),
&FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
// The action is a program which returns 1877345072 as a hardcoded value.
diff --git a/chromium/components/update_client/update_engine.cc b/chromium/components/update_client/update_engine.cc
index e30cedd74c7..a32285c9d9f 100644
--- a/chromium/components/update_client/update_engine.cc
+++ b/chromium/components/update_client/update_engine.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/guid.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/stl_util.h"
@@ -25,7 +26,7 @@
namespace update_client {
UpdateContext::UpdateContext(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
bool is_foreground,
const std::vector<std::string>& ids,
UpdateClient::CrxDataCallback crx_data_callback,
@@ -39,7 +40,8 @@ UpdateContext::UpdateContext(
crx_data_callback(std::move(crx_data_callback)),
notify_observers_callback(notify_observers_callback),
callback(std::move(callback)),
- crx_downloader_factory(crx_downloader_factory) {
+ crx_downloader_factory(crx_downloader_factory),
+ session_id(base::GenerateGUID()) {
for (const auto& id : ids)
components.insert(
std::make_pair(id, std::make_unique<Component>(*this, id)));
@@ -48,10 +50,10 @@ UpdateContext::UpdateContext(
UpdateContext::~UpdateContext() {}
UpdateEngine::UpdateEngine(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
UpdateChecker::Factory update_checker_factory,
CrxDownloader::Factory crx_downloader_factory,
- PingManager* ping_manager,
+ scoped_refptr<PingManager> ping_manager,
const NotifyObserversCallback& notify_observers_callback)
: config_(config),
update_checker_factory_(update_checker_factory),
@@ -72,6 +74,13 @@ void UpdateEngine::Update(bool is_foreground,
Callback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
+ if (ids.empty()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback), Error::INVALID_ARGUMENT));
+ return;
+ }
+
if (IsThrottled(is_foreground)) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), Error::RETRY_LATER));
@@ -157,8 +166,9 @@ void UpdateEngine::DoUpdateCheck(const UpdateContextIterator it) {
update_checker_factory_(config_, metadata_.get());
update_context->update_checker->CheckForUpdates(
- update_context->ids, update_context->components,
- config_->ExtraRequestParams(), update_context->enabled_component_updates,
+ update_context->session_id, update_context->ids,
+ update_context->components, config_->ExtraRequestParams(),
+ update_context->enabled_component_updates, update_context->is_foreground,
base::BindOnce(&UpdateEngine::UpdateCheckDone, base::Unretained(this),
it));
}
@@ -288,7 +298,8 @@ void UpdateEngine::HandleComponentComplete(const UpdateContextIterator it) {
update_context->next_update_delay = component->GetUpdateDuration();
if (!component->events().empty()) {
- ping_manager_->SendPing(*component);
+ ping_manager_->SendPing(*component,
+ base::BindOnce([](int, const std::string&) {}));
}
queue.pop();
diff --git a/chromium/components/update_client/update_engine.h b/chromium/components/update_client/update_engine.h
index 9e3789259eb..5ac3024cf45 100644
--- a/chromium/components/update_client/update_engine.h
+++ b/chromium/components/update_client/update_engine.h
@@ -46,10 +46,10 @@ class UpdateEngine {
const std::string& id)>;
using CrxDataCallback = UpdateClient::CrxDataCallback;
- UpdateEngine(const scoped_refptr<Configurator>& config,
+ UpdateEngine(scoped_refptr<Configurator> config,
UpdateChecker::Factory update_checker_factory,
CrxDownloader::Factory crx_downloader_factory,
- PingManager* ping_manager,
+ scoped_refptr<PingManager> ping_manager,
const NotifyObserversCallback& notify_observers_callback);
~UpdateEngine();
@@ -88,18 +88,11 @@ class UpdateEngine {
// occurs too soon.
bool IsThrottled(bool is_foreground) const;
- // base::TimeDelta GetNextUpdateDelay(const Component& component) const;
-
base::ThreadChecker thread_checker_;
-
scoped_refptr<Configurator> config_;
-
UpdateChecker::Factory update_checker_factory_;
CrxDownloader::Factory crx_downloader_factory_;
-
- // TODO(sorin): refactor as a ref counted class.
- PingManager* ping_manager_; // Not owned by this class.
-
+ scoped_refptr<PingManager> ping_manager_;
std::unique_ptr<PersistedData> metadata_;
// Called when CRX state changes occur.
@@ -118,9 +111,10 @@ class UpdateEngine {
};
// TODO(sorin): consider making this a ref counted type.
+// Describes a group of components which are installed or updated together.
struct UpdateContext {
UpdateContext(
- const scoped_refptr<Configurator>& config,
+ scoped_refptr<Configurator> config,
bool is_foreground,
const std::vector<std::string>& ids,
UpdateClient::CrxDataCallback crx_data_callback,
@@ -173,6 +167,9 @@ struct UpdateContext {
// is handling the next component in the queue.
base::TimeDelta next_update_delay;
+ // The session id this context is associated with.
+ const std::string session_id;
+
private:
DISALLOW_COPY_AND_ASSIGN(UpdateContext);
};
diff --git a/chromium/components/update_client/updater_state.cc b/chromium/components/update_client/updater_state.cc
index b8102535ef7..c9bd83c19d4 100644
--- a/chromium/components/update_client/updater_state.cc
+++ b/chromium/components/update_client/updater_state.cc
@@ -53,6 +53,10 @@ void UpdaterState::ReadState() {
UpdaterState::Attributes UpdaterState::BuildAttributes() const {
Attributes attributes;
+#if defined(OS_WIN)
+ // Only Windows implements this attribute in a meaningful way.
+ attributes["ismachine"] = is_machine_ ? "1" : "0";
+#endif // OS_WIN
attributes[kIsEnterpriseManaged] = is_enterprise_managed_ ? "1" : "0";
attributes["name"] = updater_name_;
diff --git a/chromium/components/update_client/updater_state.h b/chromium/components/update_client/updater_state.h
index ea8b64e0e22..7b6d3a4be65 100644
--- a/chromium/components/update_client/updater_state.h
+++ b/chromium/components/update_client/updater_state.h
@@ -23,7 +23,8 @@ class UpdaterState {
// Returns a map of items representing the state of an updater. These items
// can be serialized as XML attributes in the request building.
- // |is_machine| is true for per-system installs of Chrome. Returns nullptr on
+ // If |is_machine| is true, this indicates that the updater state corresponds
+ // to the machine instance of the updater. Returns nullptr on
// the platforms and builds where this feature is not supported.
static std::unique_ptr<Attributes> GetState(bool is_machine);
@@ -52,7 +53,10 @@ class UpdaterState {
static std::string NormalizeTimeDelta(const base::TimeDelta& delta);
- bool is_machine_ = false;
+ // True if the Omaha updater is installed per-machine.
+ // The MacOS implementation ignores the value of this member but this may
+ // change in the future.
+ bool is_machine_;
std::string updater_name_;
base::Version updater_version_;
base::Time last_autoupdate_started_;
diff --git a/chromium/components/update_client/updater_state_unittest.cc b/chromium/components/update_client/updater_state_unittest.cc
index 86ad660a3d7..20fa0f711ec 100644
--- a/chromium/components/update_client/updater_state_unittest.cc
+++ b/chromium/components/update_client/updater_state_unittest.cc
@@ -43,12 +43,19 @@ TEST_F(UpdaterStateTest, Serialize) {
EXPECT_STREQ("1", attributes.at("updatepolicy").c_str());
#if defined(GOOGLE_CHROME_BUILD)
- #if defined(OS_WIN)
- // The name of the Windows updater for Chrome.
- EXPECT_STREQ("Omaha", UpdaterState::GetState(false)->at("name").c_str());
+#if defined(OS_WIN)
+ // The value of "ismachine".
+ EXPECT_STREQ("0", UpdaterState::GetState(false)->at("ismachine").c_str());
+ EXPECT_STREQ("1", UpdaterState::GetState(true)->at("ismachine").c_str());
+
+ // The name of the Windows updater for Chrome.
+ EXPECT_STREQ("Omaha", UpdaterState::GetState(false)->at("name").c_str());
#elif defined(OS_MACOSX) && !defined(OS_IOS)
+ // MacOS does not serialize "ismachine".
+ EXPECT_EQ(0UL, UpdaterState::GetState(false)->count("ismachine"));
+ EXPECT_EQ(0UL, UpdaterState::GetState(true)->count("ismachine"));
EXPECT_STREQ("Keystone", UpdaterState::GetState(false)->at("name").c_str());
-#endif
+#endif // OS_WIN
#endif // GOOGLE_CHROME_BUILD
// Tests some of the remaining values.
diff --git a/chromium/components/update_client/updater_state_win.cc b/chromium/components/update_client/updater_state_win.cc
index 9b811830e3c..13e5dd683dc 100644
--- a/chromium/components/update_client/updater_state_win.cc
+++ b/chromium/components/update_client/updater_state_win.cc
@@ -4,6 +4,8 @@
#include "components/update_client/updater_state.h"
+#include <windows.h>
+
#include <string>
#include <utility>
@@ -15,8 +17,6 @@
#include "base/win/registry.h"
#include "base/win/win_util.h"
-#include <windows.h>
-
// TODO(sorin): implement this in terms of
// chrome/installer/util/google_update_settings (crbug.com/615187).
diff --git a/chromium/components/update_client/url_fetcher_downloader.cc b/chromium/components/update_client/url_fetcher_downloader.cc
index 77dd764b09a..2d0d4d14537 100644
--- a/chromium/components/update_client/url_fetcher_downloader.cc
+++ b/chromium/components/update_client/url_fetcher_downloader.cc
@@ -20,6 +20,7 @@
#include "net/base/load_flags.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_request_context_getter.h"
#include "url/gurl.h"
namespace {
@@ -54,7 +55,7 @@ void UrlFetcherDownloader::URLFetcherDelegate::OnURLFetchDownloadProgress(
UrlFetcherDownloader::UrlFetcherDownloader(
std::unique_ptr<CrxDownloader> successor,
- net::URLRequestContextGetter* context_getter)
+ scoped_refptr<net::URLRequestContextGetter> context_getter)
: CrxDownloader(std::move(successor)),
delegate_(std::make_unique<URLFetcherDelegate>(this)),
context_getter_(context_getter) {}
@@ -137,7 +138,7 @@ void UrlFetcherDownloader::StartURLFetch(const GURL& url) {
url_fetcher_ = net::URLFetcher::Create(0, url, net::URLFetcher::GET,
delegate_.get(), traffic_annotation);
- url_fetcher_->SetRequestContext(context_getter_);
+ url_fetcher_->SetRequestContext(context_getter_.get());
url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DISABLE_CACHE);
diff --git a/chromium/components/update_client/url_fetcher_downloader.h b/chromium/components/update_client/url_fetcher_downloader.h
index 2241adc8fe1..442cbf2c339 100644
--- a/chromium/components/update_client/url_fetcher_downloader.h
+++ b/chromium/components/update_client/url_fetcher_downloader.h
@@ -27,8 +27,9 @@ namespace update_client {
// Implements a CRX downloader in top of the URLFetcher.
class UrlFetcherDownloader : public CrxDownloader {
public:
- UrlFetcherDownloader(std::unique_ptr<CrxDownloader> successor,
- net::URLRequestContextGetter* context_getter);
+ UrlFetcherDownloader(
+ std::unique_ptr<CrxDownloader> successor,
+ scoped_refptr<net::URLRequestContextGetter> context_getter);
~UrlFetcherDownloader() override;
private:
@@ -65,7 +66,7 @@ class UrlFetcherDownloader : public CrxDownloader {
std::unique_ptr<URLFetcherDelegate> delegate_;
std::unique_ptr<net::URLFetcher> url_fetcher_;
- net::URLRequestContextGetter* context_getter_ = nullptr;
+ scoped_refptr<net::URLRequestContextGetter> context_getter_;
// Contains a temporary download directory for the downloaded file.
base::FilePath download_dir_;
diff --git a/chromium/components/update_client/url_request_post_interceptor.cc b/chromium/components/update_client/url_request_post_interceptor.cc
index ac2cdb5431f..9c051341f5b 100644
--- a/chromium/components/update_client/url_request_post_interceptor.cc
+++ b/chromium/components/update_client/url_request_post_interceptor.cc
@@ -62,9 +62,8 @@ class URLRequestMockJob : public net::URLRequestSimpleJob {
URLRequestPostInterceptor::URLRequestPostInterceptor(
const GURL& url,
- const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
- : url_(url), io_task_runner_(io_task_runner), hit_count_(0) {
-}
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner)
+ : url_(url), io_task_runner_(io_task_runner), hit_count_(0) {}
URLRequestPostInterceptor::~URLRequestPostInterceptor() {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
@@ -120,21 +119,25 @@ int URLRequestPostInterceptor::GetCount() const {
return static_cast<int>(requests_.size());
}
-std::vector<std::string> URLRequestPostInterceptor::GetRequests() const {
+std::vector<URLRequestPostInterceptor::InterceptedRequest>
+URLRequestPostInterceptor::GetRequests() const {
base::AutoLock auto_lock(interceptor_lock_);
return requests_;
}
+std::string URLRequestPostInterceptor::GetRequestBody(size_t n) const {
+ base::AutoLock auto_lock(interceptor_lock_);
+ return requests_[n].first;
+}
+
std::string URLRequestPostInterceptor::GetRequestsAsString() const {
- std::vector<std::string> requests(GetRequests());
+ const std::vector<InterceptedRequest> requests = GetRequests();
std::string s = "Requests are:";
int i = 0;
- for (std::vector<std::string>::const_iterator it = requests.begin();
- it != requests.end(); ++it) {
- s.append(base::StringPrintf("\n (%d): %s", ++i, it->c_str()));
- }
+ for (auto it = requests.cbegin(); it != requests.cend(); ++it)
+ s.append(base::StringPrintf("\n [%d]: %s", ++i, it->first.c_str()));
return s;
}
@@ -150,7 +153,7 @@ class URLRequestPostInterceptor::Delegate : public net::URLRequestInterceptor {
public:
Delegate(const std::string& scheme,
const std::string& hostname,
- const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner)
: scheme_(scheme), hostname_(hostname), io_task_runner_(io_task_runner) {}
void Register() {
@@ -213,7 +216,8 @@ class URLRequestPostInterceptor::Delegate : public net::URLRequestInterceptor {
{
base::AutoLock auto_lock(interceptor->interceptor_lock_);
- interceptor->requests_.push_back(request_body);
+ interceptor->requests_.push_back(
+ {request_body, request->extra_request_headers()});
if (interceptor->expectations_.empty())
return nullptr;
const URLRequestPostInterceptor::Expectation& expectation(
@@ -246,7 +250,7 @@ class URLRequestPostInterceptor::Delegate : public net::URLRequestInterceptor {
URLRequestPostInterceptorFactory::URLRequestPostInterceptorFactory(
const std::string& scheme,
const std::string& hostname,
- const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner)
: scheme_(scheme),
hostname_(hostname),
io_task_runner_(io_task_runner),
@@ -289,12 +293,15 @@ bool PartialMatch::Match(const std::string& actual) const {
return actual.find(expected_) != std::string::npos;
}
+bool AnyMatch::Match(const std::string&) const {
+ return true;
+}
+
InterceptorFactory::InterceptorFactory(
- const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner)
: URLRequestPostInterceptorFactory(POST_INTERCEPT_SCHEME,
POST_INTERCEPT_HOSTNAME,
- io_task_runner) {
-}
+ io_task_runner) {}
InterceptorFactory::~InterceptorFactory() {
}
diff --git a/chromium/components/update_client/url_request_post_interceptor.h b/chromium/components/update_client/url_request_post_interceptor.h
index 87631935c48..be47caf2bb7 100644
--- a/chromium/components/update_client/url_request_post_interceptor.h
+++ b/chromium/components/update_client/url_request_post_interceptor.h
@@ -22,15 +22,20 @@ class FilePath;
class SequencedTaskRunner;
}
+namespace net {
+class HttpRequestHeaders;
+}
+
namespace update_client {
// Intercepts requests to a file path, counts them, and captures the body of
// the requests. Optionally, for each request, it can return a canned response
// from a given file. The class maintains a queue of expectations, and returns
-// one and only one response for each request that matches and it is
-// intercepted.
+// one and only one response for each request that matches the expectation.
+// Then, the expectation is removed from the queue.
class URLRequestPostInterceptor {
public:
+ using InterceptedRequest = std::pair<std::string, net::HttpRequestHeaders>;
// Allows a generic string maching interface when setting up expectations.
class RequestMatcher {
public:
@@ -61,9 +66,12 @@ class URLRequestPostInterceptor {
int GetCount() const;
// Returns all requests that have been intercepted, matched or not.
- std::vector<std::string> GetRequests() const;
+ std::vector<InterceptedRequest> GetRequests() const;
+
+ // Return the body of the n-th request, zero-based.
+ std::string GetRequestBody(size_t n) const;
- // Returns all requests as a string for debugging purposes.
+ // Returns the joined bodies of all requests for debugging purposes.
std::string GetRequestsAsString() const;
// Resets the state of the interceptor so that new expectations can be set.
@@ -86,7 +94,7 @@ class URLRequestPostInterceptor {
URLRequestPostInterceptor(
const GURL& url,
- const scoped_refptr<base::SequencedTaskRunner>& io_task_runner);
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner);
~URLRequestPostInterceptor();
void ClearExpectations();
@@ -95,9 +103,16 @@ class URLRequestPostInterceptor {
scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
mutable base::Lock interceptor_lock_;
- mutable int hit_count_;
- mutable std::vector<std::string> requests_;
- mutable base::queue<Expectation> expectations_;
+
+ // Contains the count of the request matching expectations.
+ int hit_count_;
+
+ // Contains the request body and the extra headers of the intercepted
+ // requests.
+ std::vector<InterceptedRequest> requests_;
+
+ // Contains the expectations which this interceptor tries to match.
+ base::queue<Expectation> expectations_;
DISALLOW_COPY_AND_ASSIGN(URLRequestPostInterceptor);
};
@@ -107,7 +122,7 @@ class URLRequestPostInterceptorFactory {
URLRequestPostInterceptorFactory(
const std::string& scheme,
const std::string& hostname,
- const scoped_refptr<base::SequencedTaskRunner>& io_task_runner);
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner);
~URLRequestPostInterceptorFactory();
// Creates an interceptor object for the specified url path. Returns NULL
@@ -132,7 +147,7 @@ class URLRequestPostInterceptorFactory {
class InterceptorFactory : public URLRequestPostInterceptorFactory {
public:
explicit InterceptorFactory(
- const scoped_refptr<base::SequencedTaskRunner>& io_task_runner);
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner);
~InterceptorFactory();
// Creates an interceptor for the url path defined by POST_INTERCEPT_PATH.
@@ -156,6 +171,15 @@ class PartialMatch : public URLRequestPostInterceptor::RequestMatcher {
DISALLOW_COPY_AND_ASSIGN(PartialMatch);
};
+class AnyMatch : public URLRequestPostInterceptor::RequestMatcher {
+ public:
+ AnyMatch() = default;
+ bool Match(const std::string& actual) const override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AnyMatch);
+};
+
} // namespace update_client
#endif // COMPONENTS_UPDATE_CLIENT_URL_REQUEST_POST_INTERCEPTOR_H_
diff --git a/chromium/components/update_client/utils.cc b/chromium/components/update_client/utils.cc
index c200deff0be..19b93a09688 100644
--- a/chromium/components/update_client/utils.cc
+++ b/chromium/components/update_client/utils.cc
@@ -20,6 +20,7 @@
#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 "base/values.h"
#include "components/crx_file/id_util.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
@@ -40,9 +41,10 @@ namespace update_client {
std::unique_ptr<net::URLFetcher> SendProtocolRequest(
const GURL& url,
+ const std::map<std::string, std::string>& protocol_request_extra_headers,
const std::string& protocol_request,
net::URLFetcherDelegate* url_fetcher_delegate,
- net::URLRequestContextGetter* url_request_context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("component_updater_utils", R"(
semantics {
@@ -79,13 +81,16 @@ std::unique_ptr<net::URLFetcher> SendProtocolRequest(
data_use_measurement::DataUseUserData::AttachToFetcher(
url_fetcher.get(), data_use_measurement::DataUseUserData::UPDATE_CLIENT);
url_fetcher->SetUploadData("application/xml", protocol_request);
- url_fetcher->SetRequestContext(url_request_context_getter);
+ url_fetcher->SetRequestContext(url_request_context_getter.get());
url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DISABLE_CACHE);
url_fetcher->SetAutomaticallyRetryOn5xx(false);
- url_fetcher->Start();
+ for (const auto& header : protocol_request_extra_headers)
+ url_fetcher->AddExtraRequestHeader(base::StringPrintf(
+ "%s: %s", header.first.c_str(), header.second.c_str()));
+ url_fetcher->Start();
return url_fetcher;
}
diff --git a/chromium/components/update_client/utils.h b/chromium/components/update_client/utils.h
index 30f6edd82d7..54eb873a774 100644
--- a/chromium/components/update_client/utils.h
+++ b/chromium/components/update_client/utils.h
@@ -5,12 +5,14 @@
#ifndef COMPONENTS_UPDATE_CLIENT_UTILS_H_
#define COMPONENTS_UPDATE_CLIENT_UTILS_H_
+#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/callback_forward.h"
+#include "base/memory/ref_counted.h"
#include "components/update_client/update_client.h"
class GURL;
@@ -41,9 +43,10 @@ using InstallerAttribute = std::pair<std::string, std::string>;
// expected to contain XML data. The caller owns the returned object.
std::unique_ptr<net::URLFetcher> SendProtocolRequest(
const GURL& url,
+ const std::map<std::string, std::string>& protocol_request_extra_headers,
const std::string& protocol_request,
net::URLFetcherDelegate* url_fetcher_delegate,
- net::URLRequestContextGetter* url_request_context_getter);
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
// Returns true if the url request of |fetcher| was succesful.
bool FetchSuccess(const net::URLFetcher& fetcher);
diff --git a/chromium/components/url_formatter/OWNERS b/chromium/components/url_formatter/OWNERS
index 3336b55a8b5..0e9305e7620 100644
--- a/chromium/components/url_formatter/OWNERS
+++ b/chromium/components/url_formatter/OWNERS
@@ -1,9 +1,6 @@
pkasting@chromium.org
tommycli@chromium.org
-# Backup reviewer
-brettw@chromium.org
-
# Changes to FormatUrlForSecurityDisplay and FormatOriginForSecurityDisplay
# require a security review to avoid introducing security bugs.
per-file elide_url.*=palmer@chromium.org
diff --git a/chromium/components/url_formatter/elide_url.cc b/chromium/components/url_formatter/elide_url.cc
index 38d987006f2..77cd4dd0a99 100644
--- a/chromium/components/url_formatter/elide_url.cc
+++ b/chromium/components/url_formatter/elide_url.cc
@@ -63,7 +63,8 @@ base::string16 ElideComponentizedPath(
const base::string16& url_filename,
const base::string16& url_query,
const gfx::FontList& font_list,
- float available_pixel_width) {
+ float available_pixel_width,
+ gfx::Typesetter typesetter) {
const size_t url_path_number_of_elements = url_path_elements.size();
CHECK(url_path_number_of_elements);
@@ -71,10 +72,9 @@ base::string16 ElideComponentizedPath(
base::string16 elided_path = BuildPathFromComponents(
url_path_prefix, url_path_elements, url_filename, i);
if (available_pixel_width >=
- gfx::GetStringWidthF(elided_path, font_list, gfx::Typesetter::BROWSER))
+ gfx::GetStringWidthF(elided_path, font_list, typesetter))
return gfx::ElideText(elided_path + url_query, font_list,
- available_pixel_width, gfx::ELIDE_TAIL,
- gfx::Typesetter::BROWSER);
+ available_pixel_width, gfx::ELIDE_TAIL, typesetter);
}
return base::string16();
@@ -142,82 +142,6 @@ base::string16 HostForDisplay(base::StringPiece host_in_puny) {
base::ASCIIToUTF16(host_in_puny) : host;
}
-// Adjust the components of |parsed| to describe a portion of a previous URL.
-// |offset| and |length| describe the substring range. Components that fall
-// completely outside the specified range are invalidated, while others are
-// clamped to fit. If |offset| is non-zero, the start positions of all valid
-// components are reduced by this offset.
-void AdjustParsed(int length, int offset, url::Parsed* parsed) {
- DCHECK_GE(length, 0);
- DCHECK_GE(offset, 0);
-
- const std::vector<url::Component*> components = {
- &(parsed->scheme), &(parsed->username), &(parsed->password),
- &(parsed->host), &(parsed->port), &(parsed->path),
- &(parsed->query), &(parsed->ref),
- };
-
- for (auto* component : components) {
- if (!component->is_valid())
- continue;
- int begin = base::ClampToRange(component->begin - offset, 0, length);
- int end = base::ClampToRange(component->end() - offset, 0, length);
- component->begin = begin;
- component->len = end - begin;
- if (component->len == 0)
- component->reset();
- }
-}
-
-// Elide a URL string with ellipsis at either the head or tail end, and adjust
-// |parsed| accordingly. This allows a formatted URL to be elided while
-// maintaining a Parsed description of the result.
-base::string16 ElideParsedUrlString(const base::string16& original,
- const gfx::FontList& font_list,
- float available_pixel_width,
- gfx::ElideBehavior behavior,
- url::Parsed* parsed) {
- DCHECK(behavior == gfx::ELIDE_TAIL || behavior == gfx::ELIDE_HEAD);
-
- base::string16 elided =
- gfx::ElideText(original, font_list, available_pixel_width, behavior,
- gfx::Typesetter::BROWSER);
- if (elided == original)
- return elided;
-
- // If elision reduced the string to a tiny remaining fragment, standardize it.
- if (elided == (base::string16(gfx::kEllipsisUTF16) + gfx::kEllipsisUTF16))
- elided = base::string16(gfx::kEllipsisUTF16);
-
- int offset =
- (behavior == gfx::ELIDE_HEAD) ? original.size() - elided.size() : 0;
- AdjustParsed(elided.size(), offset, parsed);
- return elided;
-}
-
-// Elide the path and onward components of a URL string to fit a specified
-// width, if possible. If trimming these components allows the URL to fit,
-// |url_string| and |parsed| are updated and the function returns true.
-// Otherwise, inputs are untouched and the function returns false.
-bool ElideAfterHost(base::string16* url_string,
- const gfx::FontList& font_list,
- float available_pixel_width,
- url::Parsed* parsed) {
- DCHECK(parsed->host.is_nonempty());
- DCHECK(parsed->path.is_nonempty() || parsed->query.is_nonempty() ||
- parsed->ref.is_nonempty());
-
- const base::string16 shortest = url_string->substr(0, parsed->host.end()) +
- gfx::kForwardSlash +
- base::string16(gfx::kEllipsisUTF16);
- if (available_pixel_width >= gfx::GetStringWidthF(shortest, font_list)) {
- *url_string = ElideParsedUrlString(
- *url_string, font_list, available_pixel_width, gfx::ELIDE_TAIL, parsed);
- return true;
- }
- return false;
-}
-
} // namespace
namespace url_formatter {
@@ -230,7 +154,8 @@ namespace url_formatter {
// suspect it could be made simpler.
base::string16 ElideUrl(const GURL& url,
const gfx::FontList& font_list,
- float available_pixel_width) {
+ float available_pixel_width,
+ gfx::Typesetter typesetter) {
// Get a formatted string and corresponding parsing of the url.
url::Parsed parsed;
const base::string16 url_string = url_formatter::FormatUrl(
@@ -241,13 +166,13 @@ base::string16 ElideUrl(const GURL& url,
if (!url.IsStandard()) {
return gfx::ElideText(url_string, font_list, available_pixel_width,
- gfx::ELIDE_TAIL, gfx::Typesetter::BROWSER);
+ gfx::ELIDE_TAIL, typesetter);
}
// Now start eliding url_string to fit within available pixel width.
// Fist pass - check to see whether entire url_string fits.
const float pixel_width_url_string =
- gfx::GetStringWidthF(url_string, font_list, gfx::Typesetter::BROWSER);
+ gfx::GetStringWidthF(url_string, font_list, typesetter);
if (available_pixel_width >= pixel_width_url_string)
return url_string;
@@ -264,10 +189,10 @@ base::string16 ElideUrl(const GURL& url,
// Return general elided text if url minus the query fits.
const base::string16 url_minus_query =
url_string.substr(0, path_start_index + path_len);
- if (available_pixel_width >= gfx::GetStringWidthF(url_minus_query, font_list,
- gfx::Typesetter::BROWSER)) {
+ if (available_pixel_width >=
+ gfx::GetStringWidthF(url_minus_query, font_list, typesetter)) {
return gfx::ElideText(url_string, font_list, available_pixel_width,
- gfx::ELIDE_TAIL, gfx::Typesetter::BROWSER);
+ gfx::ELIDE_TAIL, typesetter);
}
base::string16 url_host;
@@ -295,17 +220,17 @@ base::string16 ElideUrl(const GURL& url,
// Second Pass - remove scheme - the rest fits.
const float pixel_width_url_host =
- gfx::GetStringWidthF(url_host, font_list, gfx::Typesetter::BROWSER);
- const float pixel_width_url_path = gfx::GetStringWidthF(
- url_path_query_etc, font_list, gfx::Typesetter::BROWSER);
+ gfx::GetStringWidthF(url_host, font_list, typesetter);
+ const float pixel_width_url_path =
+ gfx::GetStringWidthF(url_path_query_etc, font_list, typesetter);
if (available_pixel_width >= pixel_width_url_host + pixel_width_url_path)
return url_host + url_path_query_etc;
// Third Pass: Subdomain, domain and entire path fits.
const float pixel_width_url_domain =
- gfx::GetStringWidthF(url_domain, font_list, gfx::Typesetter::BROWSER);
+ gfx::GetStringWidthF(url_domain, font_list, typesetter);
const float pixel_width_url_subdomain =
- gfx::GetStringWidthF(url_subdomain, font_list, gfx::Typesetter::BROWSER);
+ gfx::GetStringWidthF(url_subdomain, font_list, typesetter);
if (available_pixel_width >=
pixel_width_url_subdomain + pixel_width_url_domain + pixel_width_url_path)
return url_subdomain + url_domain + url_path_query_etc;
@@ -313,17 +238,16 @@ base::string16 ElideUrl(const GURL& url,
// Query element.
base::string16 url_query;
const float kPixelWidthDotsTrailer = gfx::GetStringWidthF(
- base::string16(gfx::kEllipsisUTF16), font_list, gfx::Typesetter::BROWSER);
+ base::string16(gfx::kEllipsisUTF16), font_list, typesetter);
if (parsed.query.is_nonempty()) {
url_query = base::UTF8ToUTF16("?") + url_string.substr(parsed.query.begin);
if (available_pixel_width >=
(pixel_width_url_subdomain + pixel_width_url_domain +
pixel_width_url_path -
- gfx::GetStringWidthF(url_query, font_list,
- gfx::Typesetter::BROWSER))) {
+ gfx::GetStringWidthF(url_query, font_list, typesetter))) {
return gfx::ElideText(url_subdomain + url_domain + url_path_query_etc,
font_list, available_pixel_width, gfx::ELIDE_TAIL,
- gfx::Typesetter::BROWSER);
+ typesetter);
}
}
@@ -354,20 +278,20 @@ base::string16 ElideUrl(const GURL& url,
// chop off the TLD. https://crbug.com/739975.
return gfx::ElideText(url_subdomain + url_domain + url_path_query_etc,
font_list, available_pixel_width, gfx::ELIDE_TAIL,
- gfx::Typesetter::BROWSER);
+ typesetter);
}
// Start eliding the path and replacing elements by ".../".
const base::string16 kEllipsisAndSlash =
base::string16(gfx::kEllipsisUTF16) + gfx::kForwardSlash;
- const float pixel_width_ellipsis_slash = gfx::GetStringWidthF(
- kEllipsisAndSlash, font_list, gfx::Typesetter::BROWSER);
+ const float pixel_width_ellipsis_slash =
+ gfx::GetStringWidthF(kEllipsisAndSlash, font_list, typesetter);
// Check with both subdomain and domain.
if (url_path_number_of_elements > 0) {
base::string16 elided_path = ElideComponentizedPath(
url_subdomain + url_domain, url_path_elements, url_filename, url_query,
- font_list, available_pixel_width);
+ font_list, available_pixel_width, typesetter);
if (!elided_path.empty())
return elided_path;
}
@@ -387,7 +311,7 @@ base::string16 ElideUrl(const GURL& url,
if (url_path_number_of_elements > 0) {
base::string16 elided_path = ElideComponentizedPath(
url_elided_domain, url_path_elements, url_filename, url_query,
- font_list, available_pixel_width);
+ font_list, available_pixel_width, typesetter);
if (!elided_path.empty())
return elided_path;
}
@@ -395,15 +319,15 @@ base::string16 ElideUrl(const GURL& url,
// Return elided domain/.../filename anyway.
base::string16 final_elided_url_string(url_elided_domain);
- const float url_elided_domain_width = gfx::GetStringWidthF(
- url_elided_domain, font_list, gfx::Typesetter::BROWSER);
+ const float url_elided_domain_width =
+ gfx::GetStringWidthF(url_elided_domain, font_list, typesetter);
// A hack to prevent trailing ".../...".
if (url_path_number_of_elements > 0 &&
url_elided_domain_width + pixel_width_ellipsis_slash +
kPixelWidthDotsTrailer +
gfx::GetStringWidthF(base::ASCIIToUTF16("UV"), font_list,
- gfx::Typesetter::BROWSER) <
+ typesetter) <
available_pixel_width) {
final_elided_url_string += BuildPathFromComponents(
base::string16(), url_path_elements, url_filename, 1);
@@ -412,8 +336,7 @@ base::string16 ElideUrl(const GURL& url,
}
return gfx::ElideText(final_elided_url_string, font_list,
- available_pixel_width, gfx::ELIDE_TAIL,
- gfx::Typesetter::BROWSER);
+ available_pixel_width, gfx::ELIDE_TAIL, typesetter);
}
base::string16 ElideHost(const GURL& url,
@@ -425,7 +348,8 @@ base::string16 ElideHost(const GURL& url,
base::string16 url_subdomain;
SplitHost(url, &url_host, &url_domain, &url_subdomain);
- const float pixel_width_url_host = gfx::GetStringWidthF(url_host, font_list);
+ const float pixel_width_url_host =
+ gfx::GetStringWidthF(url_host, font_list, typesetter);
if (available_pixel_width >= pixel_width_url_host)
return url_host;
@@ -513,56 +437,4 @@ base::string16 FormatOriginForSecurityDisplay(
return result;
}
-base::string16 ElideUrlSimple(const GURL& url,
- const base::string16& unelided_url_string,
- const gfx::FontList& font_list,
- float available_pixel_width,
- url::Parsed* parsed) {
- DCHECK_NE(parsed, nullptr);
- base::string16 url_string = unelided_url_string;
-
- if (available_pixel_width <= 0 ||
- available_pixel_width >= gfx::GetStringWidthF(url_string, font_list)) {
- return url_string;
- }
-
- // If non-standard, a file, or there is no host, simply elide from the right.
- if (!url.IsStandard() || url.SchemeIsFile() || !parsed->host.is_nonempty()) {
- return ElideParsedUrlString(url_string, font_list, available_pixel_width,
- gfx::ELIDE_TAIL, parsed);
- }
-
- bool has_path_ref_query = parsed->path.is_nonempty() ||
- parsed->query.is_nonempty() ||
- parsed->ref.is_nonempty();
-
- // Try fitting the host with scheme preserved.
- if (has_path_ref_query &&
- ElideAfterHost(&url_string, font_list, available_pixel_width, parsed)) {
- return url_string;
- }
-
- // Remove the scheme and try fitting the host again.
- if (parsed->host.begin > 0) {
- url_string.erase(0, parsed->host.begin);
- AdjustParsed(url_string.size(), parsed->host.begin, parsed);
-
- if (has_path_ref_query &&
- ElideAfterHost(&url_string, font_list, available_pixel_width, parsed)) {
- return url_string;
- }
- }
-
- // Fully elide everything after the host, as none of it can fit.
- if (has_path_ref_query) {
- url_string = url_string.substr(0, parsed->host.end()) + gfx::kForwardSlash +
- base::string16(gfx::kEllipsisUTF16);
- AdjustParsed(url_string.size(), 0, parsed);
- }
-
- // Only host remains, so elide from the left.
- return ElideParsedUrlString(url_string, font_list, available_pixel_width,
- gfx::ELIDE_HEAD, parsed);
-}
-
} // namespace url_formatter
diff --git a/chromium/components/url_formatter/elide_url.h b/chromium/components/url_formatter/elide_url.h
index cc86db34ecc..297186625ac 100644
--- a/chromium/components/url_formatter/elide_url.h
+++ b/chromium/components/url_formatter/elide_url.h
@@ -21,7 +21,6 @@ class FontList;
namespace url {
class Origin;
-struct Parsed;
}
namespace url_formatter {
@@ -42,7 +41,8 @@ namespace url_formatter {
// http://crbug.com/6487 for more information.
base::string16 ElideUrl(const GURL& url,
const gfx::FontList& font_list,
- float available_pixel_width);
+ float available_pixel_width,
+ gfx::Typesetter typesetter = gfx::Typesetter::DEFAULT);
// This function takes a GURL object and elides the host to fit within
// the given width. The function will never elide past the TLD+1 point,
@@ -55,30 +55,6 @@ base::string16 ElideHost(const GURL& host_url,
gfx::Typesetter typesetter = gfx::Typesetter::DEFAULT);
#endif // !defined(OS_ANDROID)
-// Similar to ElideUrl, this function shortens a URL to fit a specified width,
-// but does so according to the origin presentation guidance at:
-// https://www.chromium.org/Home/chromium-security/enamel
-//
-// This method differs from ElideUrl in that:
-// - The method accepts a pre-formatted URL string, allowing arbitrary
-// formatting of the URL.
-// - |parsed| is accepted and modified, allowing regions of the elided URL to be
-// colored or styled. For example, if a path is completely elided to an
-// ellipsis, the path component will describe the ellipsis. The input must be
-// the Parsed structure originally generated during formatting.
-// - When necessary, the host portion is elided from the left, to preserve the
-// TLD as long as possible. Subdomain is not treated specially.
-// - The path is elided from the right, with no special handling of the last
-// path element, to avoid potentially long runtimes.
-//
-// This function should be merged with ElideUrl to have a single elision method.
-// See http://crbug.com/772476.
-base::string16 ElideUrlSimple(const GURL& url,
- const base::string16& url_string,
- const gfx::FontList& font_list,
- float available_pixel_width,
- url::Parsed* parsed);
-
enum class SchemeDisplay {
SHOW,
OMIT_HTTP_AND_HTTPS,
diff --git a/chromium/components/url_formatter/elide_url_unittest.cc b/chromium/components/url_formatter/elide_url_unittest.cc
index 5e66ef75bdd..e2fc4410b3d 100644
--- a/chromium/components/url_formatter/elide_url_unittest.cc
+++ b/chromium/components/url_formatter/elide_url_unittest.cc
@@ -22,11 +22,6 @@
namespace {
-enum ElisionMethod {
- kMethodOriginal,
- kMethodSimple,
-};
-
struct Testcase {
const std::string input;
const std::string output;
@@ -49,59 +44,18 @@ struct ParsingTestcase {
const std::vector<UrlComponent> components;
};
-base::string16 FormatAndElideUrlSimple(const GURL& url,
- const gfx::FontList& font_list,
- float available_pixel_width,
- url::Parsed* parsed) {
- const base::string16 url_string = url_formatter::FormatUrl(
- url, url_formatter::kFormatUrlOmitDefaults, net::UnescapeRule::SPACES,
- parsed, nullptr, nullptr);
- return url_formatter::ElideUrlSimple(url, url_string, font_list,
- available_pixel_width, parsed);
-}
-
-base::string16 Elide(const GURL& url,
- const gfx::FontList& font_list,
- float available_width,
- ElisionMethod method) {
- switch (method) {
- case kMethodSimple: {
- url::Parsed parsed;
- return FormatAndElideUrlSimple(url, font_list, available_width, &parsed);
- }
#if !defined(OS_ANDROID)
- case kMethodOriginal:
- return url_formatter::ElideUrl(url, font_list, available_width);
-#endif
- default:
- NOTREACHED();
- return base::string16();
- }
-}
-url::Component* GetComponent(url::Parsed* parsed,
- url::Parsed::ComponentType type) {
- switch (type) {
- case url::Parsed::SCHEME:
- return &parsed->scheme;
- case url::Parsed::USERNAME:
- return &parsed->username;
- case url::Parsed::PASSWORD:
- return &parsed->password;
- case url::Parsed::HOST:
- return &parsed->host;
- case url::Parsed::PORT:
- return &parsed->port;
- case url::Parsed::PATH:
- return &parsed->path;
- case url::Parsed::QUERY:
- return &parsed->query;
- case url::Parsed::REF:
- return &parsed->ref;
- default:
- NOTREACHED();
- return nullptr;
- }
+// Returns the width of a utf8 or utf16 string using the BROWSER typesetter and
+// default UI font, or the provided |font_list|.
+float GetWidth(const std::string& utf8,
+ const gfx::FontList& font_list = gfx::FontList()) {
+ return gfx::GetStringWidthF(base::UTF8ToUTF16(utf8), font_list,
+ gfx::Typesetter::BROWSER);
+}
+float GetWidth(const base::string16& utf16,
+ const gfx::FontList& font_list = gfx::FontList()) {
+ return gfx::GetStringWidthF(utf16, font_list, gfx::Typesetter::BROWSER);
}
// Verify that one or more URLs passes through an explicit sequence of elided
@@ -120,8 +74,7 @@ url::Component* GetComponent(url::Parsed* parsed,
// google.com/in... <- Must match.
//
void RunProgressiveElisionTest(
- const std::vector<ProgressiveTestcase>& testcases,
- ElisionMethod method) {
+ const std::vector<ProgressiveTestcase>& testcases) {
const gfx::FontList font_list;
for (const auto& testcase : testcases) {
SCOPED_TRACE("Eliding " + testcase.input);
@@ -130,10 +83,8 @@ void RunProgressiveElisionTest(
// Occasionally, a parsed URL can grow in length before elision, such as
// when parsing a Windows file path with missing slashes.
ASSERT_FALSE(testcase.output.empty());
- float width = std::max(
- gfx::GetStringWidthF(base::UTF8ToUTF16(testcase.input), font_list),
- gfx::GetStringWidthF(base::UTF8ToUTF16(testcase.output.front()),
- font_list));
+ float width = std::max(GetWidth(testcase.input, font_list),
+ GetWidth(testcase.output.front(), font_list));
// Ideally, this test would iterate through all available field widths on a
// per-pixel basis, but this is slow. Instead, compute the next input field
@@ -146,7 +97,8 @@ void RunProgressiveElisionTest(
for (size_t i = 0; i < testcase.output.size(); i++) {
const auto& expected = testcase.output[i];
base::string16 expected_utf16 = base::UTF8ToUTF16(expected);
- base::string16 elided = Elide(url, font_list, width, method);
+ base::string16 elided = url_formatter::ElideUrl(url, font_list, width,
+ gfx::Typesetter::BROWSER);
if (expected_utf16 != elided) {
if (i > 0 && i < testcase.output.size() - 1 &&
mismatches < kMaxConsecutiveMismatches) {
@@ -157,7 +109,7 @@ void RunProgressiveElisionTest(
break;
}
mismatches = 0;
- float new_width = gfx::GetStringWidthF(elided, font_list);
+ float new_width = GetWidth(elided, font_list);
// Elision rounds fractional available widths up.
EXPECT_LE(new_width, std::ceil(width)) << " at " << elided;
width = new_width - 1.0f;
@@ -165,28 +117,20 @@ void RunProgressiveElisionTest(
}
}
-#if !defined(OS_ANDROID)
-
void RunElisionTest(const std::vector<Testcase>& testcases) {
const gfx::FontList font_list;
for (const auto& testcase : testcases) {
SCOPED_TRACE("Eliding " + testcase.input);
const GURL url(testcase.input);
- const float available_width =
- gfx::GetStringWidthF(base::UTF8ToUTF16(testcase.output), font_list);
+ const float available_width = GetWidth(testcase.output, font_list);
EXPECT_EQ(base::UTF8ToUTF16(testcase.output),
- url_formatter::ElideUrl(url, font_list, available_width));
+ url_formatter::ElideUrl(url, font_list, available_width,
+ gfx::Typesetter::BROWSER));
}
}
// Test eliding of commonplace URLs.
-// Disabled on Mac for the typesetter migration. http://crbug.com/803354.
-#if defined(OS_MACOSX)
-#define MAYBE_TestGeneralEliding DISABLED_TestGeneralEliding
-#else
-#define MAYBE_TestGeneralEliding TestGeneralEliding
-#endif
-TEST(TextEliderTest, MAYBE_TestGeneralEliding) {
+TEST(TextEliderTest, TestGeneralEliding) {
const std::string kEllipsisStr(gfx::kEllipsis);
const std::vector<ProgressiveTestcase> progressive_testcases = {
// Elide a non-www URL (www URLs are handled differently). In this first
@@ -270,7 +214,7 @@ TEST(TextEliderTest, MAYBE_TestGeneralEliding) {
/* clang-format on */
}},
};
- RunProgressiveElisionTest(progressive_testcases, kMethodOriginal);
+ RunProgressiveElisionTest(progressive_testcases);
}
// When there is very little space available, the elision code will shorten
@@ -283,34 +227,32 @@ TEST(TextEliderTest, TestTrailingEllipsisSlashEllipsisHack) {
// Very little space, would cause double ellipsis.
gfx::FontList font_list;
GURL url("http://battersbox.com/directory/foo/peter_paul_and_mary.html");
- float available_width = gfx::GetStringWidthF(
- base::UTF8ToUTF16("battersbox.com/" + kEllipsisStr + "/" + kEllipsisStr),
- font_list);
+ float available_width = GetWidth(
+ "battersbox.com/" + kEllipsisStr + "/" + kEllipsisStr, font_list);
// Create the expected string, after elision. Depending on font size, the
// directory might become /dir... or /di... or/d... - it never should be
// shorter than that. (If it is, the font considers d... to be longer
// than .../... - that should never happen).
- ASSERT_GT(
- gfx::GetStringWidthF(base::UTF8ToUTF16(kEllipsisStr + "/" + kEllipsisStr),
- font_list),
- gfx::GetStringWidthF(base::UTF8ToUTF16("d" + kEllipsisStr), font_list));
+ ASSERT_GT(GetWidth(kEllipsisStr + "/" + kEllipsisStr, font_list),
+ GetWidth("d" + kEllipsisStr, font_list));
GURL long_url("http://battersbox.com/directorynameisreallylongtoforcetrunc");
base::string16 expected = url_formatter::ElideUrl(
- long_url, font_list, available_width);
+ long_url, font_list, available_width, gfx::Typesetter::BROWSER);
// Ensure that the expected result still contains part of the directory name.
ASSERT_GT(expected.length(), std::string("battersbox.com/d").length());
- EXPECT_EQ(expected, url_formatter::ElideUrl(url, font_list, available_width));
+ EXPECT_EQ(expected, url_formatter::ElideUrl(url, font_list, available_width,
+ gfx::Typesetter::BROWSER));
// Regression test for https://crbug.com/756717. An empty path, eliding to a
// width in between the full domain ("www.angelfire.lycos.com") and a bit
// longer than the ETLD+1 ("…lycos.com…/…UV"). This previously crashed due to
// the path being empty.
url = GURL("http://www.angelfire.lycos.com/");
- available_width = gfx::GetStringWidthF(
- base::UTF8ToUTF16(kEllipsisStr + "angelfire.lycos.com"), font_list);
+ available_width = GetWidth(kEllipsisStr + "angelfire.lycos.com", font_list);
EXPECT_EQ(base::UTF8ToUTF16(kEllipsisStr + "lycos.com"),
- url_formatter::ElideUrl(url, font_list, available_width));
+ url_formatter::ElideUrl(url, font_list, available_width,
+ gfx::Typesetter::BROWSER));
// More space available - elide directories, partially elide filename.
const std::vector<Testcase> testcases = {
@@ -369,13 +311,7 @@ TEST(TextEliderTest, TestElisionSpecialCases) {
}
// Test eliding of file: URLs.
-// Disabled on Mac for the typesetter migration. http://crbug.com/803354.
-#if defined(OS_MACOSX)
-#define MAYBE_TestFileURLEliding DISABLED_TestFileURLEliding
-#else
-#define MAYBE_TestFileURLEliding TestFileURLEliding
-#endif
-TEST(TextEliderTest, MAYBE_TestFileURLEliding) {
+TEST(TextEliderTest, TestFileURLEliding) {
const std::string kEllipsisStr(gfx::kEllipsis);
const std::vector<ProgressiveTestcase> progressive_testcases = {
{"file:///C:/path1/path2/path3/filename",
@@ -416,7 +352,7 @@ TEST(TextEliderTest, MAYBE_TestFileURLEliding) {
}},
};
- RunProgressiveElisionTest(progressive_testcases, kMethodOriginal);
+ RunProgressiveElisionTest(progressive_testcases);
const std::vector<Testcase> testcases = {
// Eliding file URLs with nothing after the ':' shouldn't crash.
@@ -446,6 +382,8 @@ TEST(TextEliderTest, TestHostEliding) {
};
for (size_t i = 0; i < arraysize(testcases); ++i) {
+ // Note this does not use GetWidth(), so typesetting will be done with
+ // gfx::Typesetter::DEFAULT. ElideHost() supports either typesetter on Mac.
const float available_width = gfx::GetStringWidthF(
base::UTF8ToUTF16(testcases[i].output), gfx::FontList());
EXPECT_EQ(base::UTF8ToUTF16(testcases[i].output),
@@ -755,167 +693,4 @@ TEST(TextEliderTest, FormatOriginForSecurityDisplay) {
<< "Explicitly test the url::Origin which takes an empty, invalid URL";
}
-// Disabled on Mac for the typesetter migration. http://crbug.com/803354.
-#if defined(OS_MACOSX)
-#define MAYBE_TestSimpleElisionMethod DISABLED_TestSimpleElisionMethod
-#else
-#define MAYBE_TestSimpleElisionMethod TestSimpleElisionMethod
-#endif
-TEST(TextEliderTest, MAYBE_TestSimpleElisionMethod) {
- const std::string kEllipsisStr(gfx::kEllipsis);
- const std::vector<ProgressiveTestcase> testcases = {
- {"https://www.abc.com/def/",
- {
- /* clang-format off */
- {"https://www.abc.com/def/"},
- {"https://www.abc.com/d" + kEllipsisStr},
- {"https://www.abc.com/" + kEllipsisStr},
- {"www.abc.com/def/"},
- {"www.abc.com/d" + kEllipsisStr},
- {"www.abc.com/" + kEllipsisStr},
- {kEllipsisStr + "ww.abc.com/" + kEllipsisStr},
- {kEllipsisStr + "w.abc.com/" + kEllipsisStr},
- {kEllipsisStr + ".abc.com/" + kEllipsisStr},
- {kEllipsisStr + "abc.com/" + kEllipsisStr},
- {kEllipsisStr + "bc.com/" + kEllipsisStr},
- {kEllipsisStr + "c.com/" + kEllipsisStr},
- {kEllipsisStr + ".com/" + kEllipsisStr},
- {kEllipsisStr + "com/" + kEllipsisStr},
- {kEllipsisStr + "om/" + kEllipsisStr},
- {kEllipsisStr + "m/" + kEllipsisStr},
- {kEllipsisStr + "/" + kEllipsisStr},
- {kEllipsisStr},
- {""},
- /* clang-format on */
- }},
- {"file://fs/file",
- {
- /* clang-format off */
- "file://fs/file",
- "file://fs/fi" + kEllipsisStr,
- "file://fs/f" + kEllipsisStr,
- "file://fs/" + kEllipsisStr,
- "file://fs" + kEllipsisStr,
- "file://f" + kEllipsisStr,
- "file://" + kEllipsisStr,
- "file:/" + kEllipsisStr,
- "file:" + kEllipsisStr,
- "file" + kEllipsisStr,
- "fil" + kEllipsisStr,
- "fi" + kEllipsisStr,
- "f" + kEllipsisStr,
- kEllipsisStr,
- "",
- /* clang-format on */
- }},
- };
- RunProgressiveElisionTest(testcases, kMethodSimple);
-}
-
-// Verify that the secure elision method returns URL component data that
-// correctly represents the elided URL.
-void RunElisionParsingTest(const std::vector<ParsingTestcase>& testcases) {
- const gfx::FontList font_list;
- for (const auto& testcase : testcases) {
- SCOPED_TRACE(testcase.input + " to " + testcase.output);
-
- const GURL url(testcase.input);
- const float available_width =
- gfx::GetStringWidthF(base::UTF8ToUTF16(testcase.output), font_list);
-
- url::Parsed parsed;
- auto elided =
- FormatAndElideUrlSimple(url, font_list, available_width, &parsed);
- EXPECT_EQ(base::UTF8ToUTF16(testcase.output), elided);
-
- // Build an expected Parsed struct from the sparse test expectations.
- url::Parsed expected;
- for (const auto& expectation : testcase.components) {
- url::Component* component = GetComponent(&expected, expectation.type);
- component->begin = expectation.begin;
- component->len = expectation.len;
- }
-
- const std::vector<url::Parsed::ComponentType> kComponents = {
- url::Parsed::SCHEME, url::Parsed::USERNAME, url::Parsed::PASSWORD,
- url::Parsed::HOST, url::Parsed::PORT, url::Parsed::PATH,
- url::Parsed::QUERY, url::Parsed::REF,
- };
- for (const auto& type : kComponents) {
- EXPECT_EQ(GetComponent(&expected, type)->begin,
- GetComponent(&parsed, type)->begin)
- << " in component " << type;
- EXPECT_EQ(GetComponent(&expected, type)->len,
- GetComponent(&parsed, type)->len)
- << " in component " << type;
- }
- }
-}
-
-// Verify that during elision, the parsed URL components are properly modified.
-// Disabled on Mac for the typesetter migration. http://crbug.com/803354.
-#if defined(OS_MACOSX)
-#define MAYBE_TestElisionParsingAdjustments \
- DISABLED_TestElisionParsingAdjustments
-#else
-#define MAYBE_TestElisionParsingAdjustments TestElisionParsingAdjustments
-#endif
-TEST(TextEliderTest, MAYBE_TestElisionParsingAdjustments) {
- const std::string kEllipsisStr(gfx::kEllipsis);
- const std::vector<ParsingTestcase> testcases = {
- // HTTPS with path.
- {"https://www.google.com/intl/en/ads/",
- "https://www.google.com/intl/en/ads/",
- {{url::Parsed::ComponentType::SCHEME, 0, 5},
- {url::Parsed::ComponentType::HOST, 8, 14},
- {url::Parsed::ComponentType::PATH, 22, 13}}},
- {"https://www.google.com/intl/en/ads/",
- "https://www.google.com/intl/en/a" + kEllipsisStr,
- {{url::Parsed::ComponentType::SCHEME, 0, 5},
- {url::Parsed::ComponentType::HOST, 8, 14},
- {url::Parsed::ComponentType::PATH, 22, 11}}},
- {"https://www.google.com/intl/en/ads/",
- "https://www.google.com/" + kEllipsisStr,
- {{url::Parsed::ComponentType::SCHEME, 0, 5},
- {url::Parsed::ComponentType::HOST, 8, 14},
- {url::Parsed::ComponentType::PATH, 22, 2}}},
- {"https://www.google.com/intl/en/ads/",
- kEllipsisStr + "google.com/" + kEllipsisStr,
- {{url::Parsed::ComponentType::HOST, 0, 11},
- {url::Parsed::ComponentType::PATH, 11, 2}}},
- {"https://www.google.com/intl/en/ads/",
- kEllipsisStr,
- {{url::Parsed::ComponentType::PATH, 0, 1}}},
- // HTTPS with no path.
- {"https://www.google.com/",
- "www.google.com",
- {{url::Parsed::ComponentType::HOST, 0, 14}}},
- {"https://www.google.com/",
- kEllipsisStr,
- {{url::Parsed::ComponentType::HOST, 0, 1}}},
- // HTTP with no path.
- {"http://www.google.com/",
- "www.google.com",
- {{url::Parsed::ComponentType::HOST, 0, 14}}},
- // File URLs.
- {"file:///C:/path1/path2",
- "file:///C:/path1/" + kEllipsisStr,
- {{url::Parsed::ComponentType::SCHEME, 0, 4},
- {url::Parsed::ComponentType::PATH, 7, 11}}},
- {"file:///C:/path1/path2",
- "fi" + kEllipsisStr,
- {{url::Parsed::ComponentType::SCHEME, 0, 3}}},
- {"file:///C:/path1/path2",
- kEllipsisStr,
- {{url::Parsed::ComponentType::SCHEME, 0, 1}}},
- // RTL URL.
- {"http://127.0.0.1/ا/http://attack.com‬",
- kEllipsisStr + "7.0.0.1/" + kEllipsisStr,
- {{url::Parsed::ComponentType::HOST, 0, 8},
- {url::Parsed::ComponentType::PATH, 8, 2}}},
- };
-
- RunElisionParsingTest(testcases);
-}
-
} // namespace
diff --git a/chromium/components/url_formatter/idn_spoof_checker.cc b/chromium/components/url_formatter/idn_spoof_checker.cc
index ef400a5747d..66b7cf6d925 100644
--- a/chromium/components/url_formatter/idn_spoof_checker.cc
+++ b/chromium/components/url_formatter/idn_spoof_checker.cc
@@ -4,6 +4,7 @@
#include "components/url_formatter/idn_spoof_checker.h"
+#include "base/no_destructor.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
@@ -20,12 +21,17 @@
namespace url_formatter {
namespace {
-base::ThreadLocalStorage::StaticSlot tls_index = TLS_INITIALIZER;
void OnThreadTermination(void* regex_matcher) {
delete reinterpret_cast<icu::RegexMatcher*>(regex_matcher);
}
+base::ThreadLocalStorage::Slot& DangerousPatternTLS() {
+ static base::NoDestructor<base::ThreadLocalStorage::Slot>
+ dangerous_pattern_tls(&OnThreadTermination);
+ return *dangerous_pattern_tls;
+}
+
#include "components/url_formatter/top_domains/alexa_skeletons-inc.cc"
// All the domains in the above file have 3 or fewer labels.
const size_t kNumberOfLabelsToCheck = 3;
@@ -149,37 +155,40 @@ IDNSpoofChecker::IDNSpoofChecker() {
// Supplement the Unicode confusable list by the following mapping.
// - {U+00FE (þ), U+03FC (ϼ), U+048F (ҏ)} => p
// - {U+0127 (ħ), U+043D (н), U+045B (ћ), U+04A3 (ң), U+04A5 (ҥ),
- // U+04C8 (ӈ), U+0527 (ԧ), U+0529 (ԩ)} => h
+ // U+04C8 (ӈ), U+04CA (ӊ), U+050B (ԋ), U+0527 (ԧ), U+0529 (ԩ)} => h
// - {U+0138 (ĸ), U+03BA (κ), U+043A (к), U+049B (қ), U+049D (ҝ),
// U+049F (ҟ), U+04A1(ҡ), U+04C4 (ӄ), U+051F (ԟ)} => k
- // - {U+0167 (ŧ), U+0442 (т), U+04AD (ҭ)} => t
+ // - {U+014B (ŋ), U+043F (п)} => n
+ // - {U+0167 (ŧ), U+0442 (т), U+04AD (ҭ), U+050F (ԏ)} => t
// - {U+0185 (ƅ), U+044C (ь), U+048D (ҍ), U+0432 (в)} => b
- // - {U+03C9 (ω), U+0448 (ш), U+0449 (щ)} => w
+ // - {U+03C9 (ω), U+0448 (ш), U+0449 (щ), U+0E1F (ฟ)} => w
// - {U+043C (м), U+04CE (ӎ)} => m
- // - U+043F(п) => n
+ // - {U+0454 (є), U+04BD (ҽ), U+04BF (ҿ), U+1054 (ၔ)} => e
// - U+0491 (ґ) => r
- // - U+0493 (ғ) => f
- // - U+04AB (ҫ) => c
+ // - {U+0493 (ғ), U+04FB (ӻ)} => f
+ // - {U+04AB (ҫ), U+1004 (င)} => c
// - U+04B1 (ұ) => y
// - U+03C7 (χ), U+04B3 (ҳ), U+04FD (ӽ), U+04FF (ӿ) => x
- // - U+04BD (ҽ), U+04BF (ҿ) => e
// - U+04CF (ӏ) => i (on Windows), l (elsewhere)
// - U+0503 (ԃ) => d
- // - U+050D (ԍ) => g
- // - U+0D1F (ട) => s
+ // - {U+050D (ԍ), U+100c (ဌ)} => g
+ // - {U+0D1F (ട), U+0E23 (ร)} => s
+ // - U+1042 (၂) => j
+ // - {U+0437 (з), U+04E1 (ӡ)} => 3
extra_confusable_mapper_.reset(icu::Transliterator::createFromRules(
UNICODE_STRING_SIMPLE("ExtraConf"),
- icu::UnicodeString::fromUTF8("[þϼҏ] > p; [ħнћңҥӈԧԩ] > h;"
- "[ĸκкқҝҟҡӄԟ] > k; [ŧтҭ] > t;"
- "[ƅьҍв] > b; [ωшщ] > w; [мӎ] > m;"
- "п > n; ћ > h; ґ > r; ғ > f; ҫ > c;"
- "ұ > y; [χҳӽӿ] > x; [ҽҿ] > e;"
+ icu::UnicodeString::fromUTF8("[þϼҏ] > p; [ħнћңҥӈӊԋԧԩ] > h;"
+ "[ĸκкқҝҟҡӄԟ] > k; [ŋп] > n; [ŧтҭԏ] > t;"
+ "[ƅьҍв] > b; [ωшщฟ] > w; [мӎ] > m;"
+ "[єҽҿၔ] > e; ґ > r; [ғӻ] > f; [ҫင] > c;"
+ "ұ > y; [χҳӽӿ] > x;"
#if defined(OS_WIN)
"ӏ > i;"
#else
"ӏ > l;"
#endif
- "ԃ > d; ԍ > g; ട > s"),
+ "ԃ > d; [ԍဌ] > g; [ടร] > s; ၂ > j;"
+ "[зӡ] > 3"),
UTRANS_FORWARD, parse_error, status));
DCHECK(U_SUCCESS(status))
<< "Spoofchecker initalization failed due to an error: "
@@ -248,10 +257,8 @@ bool IDNSpoofChecker::SafeToDisplayAsUnicode(base::StringPiece16 label,
!lgc_letters_n_ascii_.containsAll(label_string))
return false;
- if (!tls_index.initialized())
- tls_index.Initialize(&OnThreadTermination);
icu::RegexMatcher* dangerous_pattern =
- reinterpret_cast<icu::RegexMatcher*>(tls_index.Get());
+ reinterpret_cast<icu::RegexMatcher*>(DangerousPatternTLS().Get());
if (!dangerous_pattern) {
// Disallow the katakana no, so, zo, or n, as they may be mistaken for
// slashes when they're surrounded by non-Japanese scripts (i.e. scripts
@@ -294,7 +301,7 @@ bool IDNSpoofChecker::SafeToDisplayAsUnicode(base::StringPiece16 label,
R"([ijl]\u0307)",
-1, US_INV),
0, status);
- tls_index.Set(dangerous_pattern);
+ DangerousPatternTLS().Set(dangerous_pattern);
}
dangerous_pattern->reset(label_string);
return !dangerous_pattern->find();
diff --git a/chromium/components/url_formatter/top_domains/test_domains.list b/chromium/components/url_formatter/top_domains/test_domains.list
index a67dd54564b..1ed11e45ff6 100644
--- a/chromium/components/url_formatter/top_domains/test_domains.list
+++ b/chromium/components/url_formatter/top_domains/test_domains.list
@@ -12,3 +12,6 @@ rf.com
cyxe.com
ldg.com
idg.com
+cegjo.com
+wsws.com
+1234567890.com
diff --git a/chromium/components/url_formatter/top_domains/test_skeletons.gperf b/chromium/components/url_formatter/top_domains/test_skeletons.gperf
index d705a7610f7..f0f24c5770c 100644
--- a/chromium/components/url_formatter/top_domains/test_skeletons.gperf
+++ b/chromium/components/url_formatter/top_domains/test_skeletons.gperf
@@ -22,4 +22,7 @@ rf.corn, 1
cyxe.corn, 1
ldg.corn, 1
idg.corn, 1
+cegjo.corn, 1
+wsws.corn, 1
+l23456789O.corn, 1
%%
diff --git a/chromium/components/url_formatter/url_fixer.cc b/chromium/components/url_formatter/url_fixer.cc
index 4335b3955de..47c04997ac0 100644
--- a/chromium/components/url_formatter/url_fixer.cc
+++ b/chromium/components/url_formatter/url_fixer.cc
@@ -434,12 +434,9 @@ std::string SegmentURLInternal(std::string* text, url::Parsed* parts) {
(*text)[semicolon] = ';';
}
if (!found_scheme) {
- // Couldn't determine the scheme, so just pick one.
+ // Couldn't determine the scheme, so just default to http.
parts->scheme.reset();
- scheme =
- base::StartsWith(*text, "ftp.", base::CompareCase::INSENSITIVE_ASCII)
- ? url::kFtpScheme
- : url::kHttpScheme;
+ scheme = url::kHttpScheme;
}
}
diff --git a/chromium/components/url_formatter/url_fixer_unittest.cc b/chromium/components/url_formatter/url_fixer_unittest.cc
index 48ad0e6666e..79d641d1c47 100644
--- a/chromium/components/url_formatter/url_fixer_unittest.cc
+++ b/chromium/components/url_formatter/url_fixer_unittest.cc
@@ -277,12 +277,6 @@ struct FixupCase {
// a clean way to guess this isn't the new-and-exciting "user" scheme.
{"user:passwd@www.google.com:8080/", "user:passwd@www.google.com:8080/"},
// {"file:///c:/foo/bar%20baz.txt", "file:///C:/foo/bar%20baz.txt"},
- {"ftp.google.com", "ftp://ftp.google.com/"},
- {" ftp.google.com", "ftp://ftp.google.com/"},
- {"FTP.GooGle.com", "ftp://ftp.google.com/"},
- {"ftpblah.google.com", "http://ftpblah.google.com/"},
- {"ftp", "http://ftp/"},
- {"google.ftp.com", "http://google.ftp.com/"},
// URLs which end with 0x85 (NEL in ISO-8859).
{"http://foo.com/s?q=\xd0\x85", "http://foo.com/s?q=%D0%85"},
{"http://foo.com/s?q=\xec\x97\x85", "http://foo.com/s?q=%EC%97%85"},
diff --git a/chromium/components/url_formatter/url_formatter_unittest.cc b/chromium/components/url_formatter/url_formatter_unittest.cc
index 9e6dc0d2c71..600a4b5e0d7 100644
--- a/chromium/components/url_formatter/url_formatter_unittest.cc
+++ b/chromium/components/url_formatter/url_formatter_unittest.cc
@@ -423,6 +423,12 @@ const IDNTestCase idn_cases[] = {
{"xn--l1acpzs.com", L"\x0449\x043c\x043d\x0442\x044c.com", false},
// шмнтв.com
{"xn--b1atdu1a.com", L"\x0448\x043c\x043d\x0442\x0432.com", false},
+ // шмԋтв.com
+ {"xn--b1atsw09g.com", L"\x0448\x043c\x050b\x0442\x0432.com", false},
+ // шмԧтв.com
+ {"xn--b1atsw03i.com", L"\x0448\x043c\x0527\x0442\x0432.com", false},
+ // шмԋԏв.com
+ {"xn--b1at9a12dua.com", L"\x0448\x043c\x050b\x050f\x0432.com", false},
// ഠട345.com
{"xn--345-jtke.com",
L"\x0d20\x0d1f"
@@ -478,6 +484,10 @@ const IDNTestCase idn_cases[] = {
{"xn--m1a4ne5jry.com", L"\x048f\x043d\x051f\x04ad\x048d.com", false},
// ҏнԟҭв.com
{"xn--b1av9v8dry.com", L"\x048f\x043d\x051f\x04ad\x0432.com", false},
+ // ҏӊԟҭв.com
+ {"xn--b1a9p8c1e8r.com", L"\x048f\x04ca\x051f\x04ad\x0432.com", false},
+ // wmŋr.com
+ {"xn--wmr-jxa.com", L"wm\x014br.com", false},
// шмпґ.com
{"xn--l1agz80a.com", L"\x0448\x043c\x043f\x0491.com", false},
// щмпґ.com
@@ -486,6 +496,8 @@ const IDNTestCase idn_cases[] = {
{"xn--o1at1tsi.com", L"\x0449\x04ce\x043f\x0491.com", false},
// ґғ.com
{"xn--03ae.com", L"\x0491\x0493.com", false},
+ // ґӻ.com
+ {"xn--03a6s.com", L"\x0491\x04fb.com", false},
// ҫұҳҽ.com
{"xn--r4amg4b.com", L"\x04ab\x04b1\x04b3\x04bd.com", false},
// ҫұӽҽ.com
@@ -494,9 +506,36 @@ const IDNTestCase idn_cases[] = {
{"xn--r4am0b3s.com", L"\x04ab\x04b1\x04ff\x04bd.com", false},
// ҫұӿҿ.com
{"xn--r4am6b4p.com", L"\x04ab\x04b1\x04ff\x04bf.com", false},
+ // ҫұӿє.com
+ {"xn--91a7osa62a.com", L"\x04ab\x04b1\x04ff\x0454.com", false},
// ӏԃԍ.com
{"xn--s5a8h4a.com", L"\x04cf\x0503\x050d.com", false},
+ // ꓲ2345б7890.com
+ {"xn--23457890-e7g93622b.com", L"\xa4f2" L"2345\x0431" L"7890.com", false},
+ // 1ᒿ345б7890.com
+ {"xn--13457890-e7g0943b.com", L"1\x14bf" L"345\x0431" L"7890.com", false},
+ // 12з4567890.com
+ {"xn--124567890-10h.com", L"12\x0437" L"4567890.com", false},
+ // 12ӡ4567890.com
+ {"xn--124567890-mfj.com", L"12\x04e1" L"4567890.com", false},
+ // 123Ꮞ567890.com
+ {"xn--123567890-dm4b.com", L"123\x13ce" L"567890.com", false},
+ // 12345б7890.com
+ {"xn--123457890-fzh.com", L"12345\x0431" L"7890.com", false},
+ // 1234567ȣ90.com
+ {"xn--123456790-6od.com", L"1234567\x0223" L"90.com", false},
+ // 12345678୨0.com
+ {"xn--123456780-71w.com", L"12345678\x0b68" L"0.com", false},
+ // 123456789ꓳ.com
+ {"xn--123456789-tx75a.com", L"123456789\xa4f3.com", false},
+
+ // ငၔဌ၂ဝ.com (entirely made of Myanmar characters)
+ {"xn--ridq5c9hnd.com", L"\x1004\x1054\x100c" L"\x1042\x101d.com", false},
+
+ // ฟรฟร.com (made of two Thai characters)
+ {"xn--w3calb.com", L"\x0e1f\x0e23\x0e1f\x0e23.com", false},
+
// At one point the skeleton of 'w' was 'vv', ensure that
// that it's treated as 'w'.
{"xn--wder-qqa.com",
diff --git a/chromium/components/url_matcher/regex_set_matcher.cc b/chromium/components/url_matcher/regex_set_matcher.cc
index ae0eb595f31..ce110293c83 100644
--- a/chromium/components/url_matcher/regex_set_matcher.cc
+++ b/chromium/components/url_matcher/regex_set_matcher.cc
@@ -6,8 +6,9 @@
#include <stddef.h>
+#include <memory>
+
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "components/url_matcher/substring_set_matcher.h"
#include "third_party/re2/src/re2/filtered_re2.h"
@@ -102,7 +103,7 @@ void RegexSetMatcher::RebuildMatcher() {
// SubstringSetMatcher doesn't own its strings.
for (size_t i = 0; i < strings_to_match.size(); ++i) {
substring_patterns_.push_back(
- base::MakeUnique<StringPattern>(strings_to_match[i], i));
+ std::make_unique<StringPattern>(strings_to_match[i], i));
}
std::vector<const StringPattern*> patterns;
for (const auto& pattern : substring_patterns_)
diff --git a/chromium/components/url_matcher/url_matcher_factory.cc b/chromium/components/url_matcher/url_matcher_factory.cc
index 87cbfecd2e2..50c85e716f0 100644
--- a/chromium/components/url_matcher/url_matcher_factory.cc
+++ b/chromium/components/url_matcher/url_matcher_factory.cc
@@ -6,12 +6,12 @@
#include <algorithm>
#include <cctype>
+#include <memory>
#include <utility>
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "components/url_matcher/url_matcher_constants.h"
@@ -234,7 +234,7 @@ URLMatcherFactory::CreateURLMatcherScheme(const base::Value* value,
return nullptr;
}
}
- return base::MakeUnique<URLMatcherSchemeFilter>(schemas);
+ return std::make_unique<URLMatcherSchemeFilter>(schemas);
}
// static
@@ -268,7 +268,7 @@ std::unique_ptr<URLMatcherPortFilter> URLMatcherFactory::CreateURLMatcherPorts(
}
}
- return base::MakeUnique<URLMatcherPortFilter>(ranges);
+ return std::make_unique<URLMatcherPortFilter>(ranges);
}
} // namespace url_matcher
diff --git a/chromium/components/url_matcher/url_matcher_factory_unittest.cc b/chromium/components/url_matcher/url_matcher_factory_unittest.cc
index 347bea4f2ae..65db5ae431a 100644
--- a/chromium/components/url_matcher/url_matcher_factory_unittest.cc
+++ b/chromium/components/url_matcher/url_matcher_factory_unittest.cc
@@ -11,7 +11,6 @@
#include "base/format_macros.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "components/url_matcher/url_matcher_constants.h"
@@ -35,7 +34,7 @@ TEST(URLMatcherFactoryTest, CreateFromURLFilterDictionary) {
// Invalid value type: {"hostSuffix": []}
base::DictionaryValue invalid_condition2;
invalid_condition2.Set(keys::kHostSuffixKey,
- base::MakeUnique<base::ListValue>());
+ std::make_unique<base::ListValue>());
// Invalid regex value: {"urlMatches": "*"}
base::DictionaryValue invalid_condition3;
@@ -54,14 +53,14 @@ TEST(URLMatcherFactoryTest, CreateFromURLFilterDictionary) {
// }
// Port range: Allow 80;1000-1010.
- auto port_range = base::MakeUnique<base::ListValue>();
+ auto port_range = std::make_unique<base::ListValue>();
port_range->AppendInteger(1000);
port_range->AppendInteger(1010);
- auto port_ranges = base::MakeUnique<base::ListValue>();
+ auto port_ranges = std::make_unique<base::ListValue>();
port_ranges->AppendInteger(80);
port_ranges->Append(std::move(port_range));
- auto scheme_list = base::MakeUnique<base::ListValue>();
+ auto scheme_list = std::make_unique<base::ListValue>();
scheme_list->AppendString("http");
base::DictionaryValue valid_condition;
@@ -143,7 +142,7 @@ TEST(URLMatcherFactoryTest, UpperCase) {
invalid_condition4.SetString(keys::kHostEqualsKey, "WWW.example.Com");
// {"scheme": ["HTTP"]}
- auto scheme_list = base::MakeUnique<base::ListValue>();
+ auto scheme_list = std::make_unique<base::ListValue>();
scheme_list->AppendString("HTTP");
base::DictionaryValue invalid_condition5;
invalid_condition5.Set(keys::kSchemesKey, std::move(scheme_list));
@@ -236,7 +235,7 @@ void UrlConditionCaseTest::CheckCondition(
UrlConditionCaseTest::ResultType expected_result) const {
base::DictionaryValue condition;
if (use_list_of_strings_) {
- auto list = base::MakeUnique<base::ListValue>();
+ auto list = std::make_unique<base::ListValue>();
list->AppendString(value);
condition.SetWithoutPathExpansion(condition_key_, std::move(list));
} else {
diff --git a/chromium/components/url_pattern_index/BUILD.gn b/chromium/components/url_pattern_index/BUILD.gn
index 410252b0dec..50ae1131a6d 100644
--- a/chromium/components/url_pattern_index/BUILD.gn
+++ b/chromium/components/url_pattern_index/BUILD.gn
@@ -48,6 +48,17 @@ static_library("test_support") {
]
}
+static_library("util") {
+ sources = [
+ "url_rule_util.cc",
+ "url_rule_util.h",
+ ]
+ deps = [
+ ":url_pattern_index",
+ "//base",
+ ]
+}
+
source_set("unit_tests") {
testonly = true
sources = [
@@ -58,10 +69,12 @@ source_set("unit_tests") {
"unindexed_ruleset_unittest.cc",
"url_pattern_index_unittest.cc",
"url_pattern_unittest.cc",
+ "url_rule_util_unittest.cc",
]
deps = [
":test_support",
":url_pattern_index",
+ ":util",
"//base",
"//testing/gtest",
"//third_party/protobuf:protobuf_lite",
diff --git a/chromium/components/url_pattern_index/url_pattern.cc b/chromium/components/url_pattern_index/url_pattern.cc
index 83584d4fd2e..aea8321191b 100644
--- a/chromium/components/url_pattern_index/url_pattern.cc
+++ b/chromium/components/url_pattern_index/url_pattern.cc
@@ -20,6 +20,7 @@
#include <ostream>
#include "base/logging.h"
+#include "base/numerics/checked_math.h"
#include "components/url_pattern_index/flat/url_pattern_index_generated.h"
#include "components/url_pattern_index/fuzzy_pattern_matching.h"
#include "components/url_pattern_index/string_splitter.h"
@@ -101,13 +102,38 @@ size_t FindSubdomainAnchoredSubpattern(base::StringPiece url,
const bool is_fuzzy =
(subpattern.find(kSeparatorPlaceholder) != base::StringPiece::npos);
- for (size_t position = 0; position <= url.size(); ++position) {
- position = is_fuzzy ? FindFuzzy(url, subpattern, position)
- : url.find(subpattern, position);
+ // Any match found after the end of the host will be discarded, so just
+ // avoid searching there for the subpattern to begin with.
+ //
+ // Check for overflow.
+ size_t max_match_end = 0;
+ if (!base::CheckAdd(host.end(), subpattern.length())
+ .AssignIfValid(&max_match_end)) {
+ return base::StringPiece::npos;
+ }
+ const base::StringPiece url_match_candidate = url.substr(0, max_match_end);
+ const base::StringPiece url_host = url.substr(0, host.end());
+
+ for (size_t position = static_cast<size_t>(host.begin);
+ position <= static_cast<size_t>(host.end()); ++position) {
+ // Enforce as a loop precondition that we are always anchored at a
+ // sub-domain before calling find. This is to reduce the number of potential
+ // searches for |subpattern|.
+ DCHECK(IsSubdomainAnchored(url, host, position));
+
+ position = is_fuzzy ? FindFuzzy(url_match_candidate, subpattern, position)
+ : url_match_candidate.find(subpattern, position);
if (position == base::StringPiece::npos ||
IsSubdomainAnchored(url, host, position)) {
return position;
}
+
+ // Enforce the loop precondition. This skips |position| to the next '.',
+ // within the host, which the loop itself increments to the anchored
+ // sub-domain.
+ position = url_host.find('.', position);
+ if (position == base::StringPiece::npos)
+ break;
}
return base::StringPiece::npos;
}
@@ -235,12 +261,13 @@ bool UrlPattern::MatchesUrl(const GURL& url) const {
}
std::ostream& operator<<(std::ostream& out, const UrlPattern& pattern) {
- // Note: Each fall-through in this switch is intentional.
switch (pattern.anchor_left()) {
case proto::ANCHOR_TYPE_SUBDOMAIN:
out << '|';
+ FALLTHROUGH;
case proto::ANCHOR_TYPE_BOUNDARY:
out << '|';
+ FALLTHROUGH;
default:
break;
}
diff --git a/chromium/components/url_pattern_index/url_pattern_index.cc b/chromium/components/url_pattern_index/url_pattern_index.cc
index 6f2a32d9e35..cc591ab924d 100644
--- a/chromium/components/url_pattern_index/url_pattern_index.cc
+++ b/chromium/components/url_pattern_index/url_pattern_index.cc
@@ -18,6 +18,7 @@
#include "components/url_pattern_index/url_pattern.h"
#include "url/gurl.h"
#include "url/origin.h"
+#include "url/url_constants.h"
namespace url_pattern_index {
@@ -229,7 +230,7 @@ class UrlRuleFlatBufferConverter {
switch (rule_.source_type()) {
case proto::SOURCE_TYPE_ANY:
options_ |= flat::OptionFlag_APPLIES_TO_THIRD_PARTY;
- // Note: fall through here intentionally.
+ FALLTHROUGH;
case proto::SOURCE_TYPE_FIRST_PARTY:
options_ |= flat::OptionFlag_APPLIES_TO_FIRST_PARTY;
break;
@@ -714,8 +715,13 @@ const flat::UrlRule* UrlPatternIndexMatcher::FindMatch(
bool is_third_party,
bool disable_generic_rules,
FindRuleStrategy strategy) const {
- if (!flat_index_ || !url.is_valid())
+ // 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.
+ if (!flat_index_ || !url.is_valid() ||
+ url.spec().length() > url::kMaxURLChars) {
return nullptr;
+ }
if ((element_type == flat::ElementType_NONE) ==
(activation_type == flat::ActivationType_NONE)) {
return nullptr;
diff --git a/chromium/components/url_pattern_index/url_pattern_index.h b/chromium/components/url_pattern_index/url_pattern_index.h
index 3199ac155d5..142a2865de4 100644
--- a/chromium/components/url_pattern_index/url_pattern_index.h
+++ b/chromium/components/url_pattern_index/url_pattern_index.h
@@ -119,7 +119,11 @@ class UrlPatternIndexMatcher {
// one of them, depending on the |strategy|. Otherwise, returns nullptr.
//
// Notes on parameters:
- // - |url| should be valid, otherwise the return value is nullptr.
+ // - |url| should be valid and not longer than url::kMaxURLChars, otherwise
+ // the return value is nullptr. The length limit is chosen due to
+ // performance implications of matching giant URLs, along with the fact
+ // that in many places in Chrome (e.g. at the IPC layer), URLs longer than
+ // this are dropped already.
// - Exactly one of |element_type| and |activation_type| should be specified,
// i.e., not equal to *_UNSPECIFIED, otherwise the return value is nullptr.
// - |is_third_party| should be pre-computed by the caller, e.g. using the
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 7826a198f12..b773c06c0ab 100644
--- a/chromium/components/url_pattern_index/url_pattern_index_unittest.cc
+++ b/chromium/components/url_pattern_index/url_pattern_index_unittest.cc
@@ -772,4 +772,22 @@ TEST_F(UrlPatternIndexTest, FindMatchHighestPriority) {
FindHighestPriorityMatch(pattern_for_number(kNumPatternTypes + 1)));
}
+TEST_F(UrlPatternIndexTest, LongUrl_NoMatch) {
+ std::string pattern = "http://example.com";
+ ASSERT_TRUE(AddUrlRule(MakeUrlRule(UrlPattern(pattern, kSubstring))));
+ Finish();
+
+ std::string url = "http://example.com/";
+ url.append(url::kMaxURLChars - url.size(), 'x');
+ EXPECT_EQ(url::kMaxURLChars, url.size());
+ EXPECT_TRUE(FindMatch(url));
+
+ // Add a single extra character, which should push this over the max URL
+ // limit. At this point, URL pattern matching should just give up since the
+ // URL load will be disallowed elsewhere in the stack.
+ url += "x";
+ EXPECT_GT(url.size(), url::kMaxURLChars);
+ EXPECT_FALSE(FindMatch(url));
+}
+
} // namespace url_pattern_index
diff --git a/chromium/components/url_pattern_index/url_pattern_unittest.cc b/chromium/components/url_pattern_index/url_pattern_unittest.cc
index 09434567eb8..3f85fa63d87 100644
--- a/chromium/components/url_pattern_index/url_pattern_unittest.cc
+++ b/chromium/components/url_pattern_index/url_pattern_unittest.cc
@@ -100,6 +100,7 @@ TEST(SubresourceFilterUrlPatternTest, MatchesUrl) {
{{"examp", kSubdomain, kAnchorNone}, "http://test.example.com/", true},
{{"t.examp", kSubdomain, kAnchorNone}, "http://test.example.com/", false},
{{"com^", kSubdomain, kAnchorNone}, "http://test.example.com/", true},
+ {{"com^x", kSubdomain, kBoundary}, "http://a.com/x", true},
{{"x.com", kSubdomain, kAnchorNone}, "http://ex.com/?url=x.com", false},
{{"ex.com/", kSubdomain, kBoundary}, "http://ex.com/", true},
{{"ex.com^", kSubdomain, kBoundary}, "http://ex.com/", true},
@@ -110,6 +111,17 @@ TEST(SubresourceFilterUrlPatternTest, MatchesUrl) {
{{"http", kSubdomain, kAnchorNone}, "http://http.com/", true},
{{"/example.com", kSubdomain, kBoundary}, "http://example.com/", false},
{{"/example.com/", kSubdomain, kBoundary}, "http://example.com/", false},
+ {{".", kSubdomain, kAnchorNone}, "http://a..com/", true},
+ {{"^", kSubdomain, kAnchorNone}, "http://a..com/", false},
+ {{".", kSubdomain, kAnchorNone}, "http://a.com./", false},
+ {{"^", kSubdomain, kAnchorNone}, "http://a.com./", true},
+ {{".", kSubdomain, kAnchorNone}, "http://a.com../", true},
+ {{"^", kSubdomain, kAnchorNone}, "http://a.com../", true},
+ {{"/path", kSubdomain, kAnchorNone}, "http://a.com./path/to/x", true},
+ {{"^path", kSubdomain, kAnchorNone}, "http://a.com./path/to/x", true},
+ {{"/path", kSubdomain, kBoundary}, "http://a.com./path", true},
+ {{"^path", kSubdomain, kBoundary}, "http://a.com./path", true},
+ {{"path", kSubdomain, kBoundary}, "http://a.com./path", false},
};
for (const auto& test_case : kTestCases) {
diff --git a/chromium/components/url_pattern_index/url_rule_util.cc b/chromium/components/url_pattern_index/url_rule_util.cc
new file mode 100644
index 00000000000..5dbf3490638
--- /dev/null
+++ b/chromium/components/url_pattern_index/url_rule_util.cc
@@ -0,0 +1,183 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/url_pattern_index/url_rule_util.h"
+
+#include "base/macros.h"
+#include "base/strings/string_util.h"
+#include "components/url_pattern_index/flat/url_pattern_index_generated.h"
+
+namespace url_pattern_index {
+
+namespace {
+
+std::string AnchorToString(url_pattern_index::flat::AnchorType anchor_type) {
+ switch (anchor_type) {
+ case url_pattern_index::flat::AnchorType_NONE:
+ return std::string();
+ case url_pattern_index::flat::AnchorType_SUBDOMAIN:
+ return "||";
+ case url_pattern_index::flat::AnchorType_BOUNDARY:
+ return "|";
+ }
+ NOTREACHED();
+ return std::string();
+}
+
+// Class that aids in appending options to a pretty-printed rule.
+class OptionsPrinter {
+ public:
+ OptionsPrinter() = default;
+
+ // If this is the first printed option for the rule, add a $ separator,
+ // otherwise a comma.
+ std::string PrintOption(const std::string& option) {
+ std::string out = printed_options_ ? "," : "$";
+ printed_options_ = true;
+ return out + option;
+ }
+
+ private:
+ bool printed_options_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(OptionsPrinter);
+};
+
+std::string PartyOptionsToString(
+ OptionsPrinter* options_printer,
+ const url_pattern_index::flat::UrlRule* flat_rule) {
+ std::string out;
+ bool third_party = flat_rule->options() &
+ url_pattern_index::flat::OptionFlag_APPLIES_TO_THIRD_PARTY;
+ bool first_party = flat_rule->options() &
+ url_pattern_index::flat::OptionFlag_APPLIES_TO_FIRST_PARTY;
+ if (first_party ^ third_party) {
+ if (first_party)
+ out += options_printer->PrintOption("~third-party");
+ else
+ out += options_printer->PrintOption("third-party");
+ }
+ return out;
+}
+
+std::string TypeOptionsToString(
+ OptionsPrinter* options_printer,
+ const url_pattern_index::flat::UrlRule* flat_rule) {
+ std::string out;
+
+ if (flat_rule->activation_types() &
+ url_pattern_index::flat::ActivationType_DOCUMENT) {
+ out += options_printer->PrintOption("document");
+ }
+
+ if (flat_rule->activation_types() &
+ url_pattern_index::flat::ActivationType_GENERIC_BLOCK) {
+ out += options_printer->PrintOption("genericblock");
+ }
+
+ uint16_t types = flat_rule->element_types();
+
+ if (types == url_pattern_index::flat::ElementType_ANY)
+ return out;
+
+ if (types & url_pattern_index::flat::ElementType_OTHER)
+ out += options_printer->PrintOption("other");
+ if (types & url_pattern_index::flat::ElementType_SCRIPT)
+ out += options_printer->PrintOption("script");
+ if (types & url_pattern_index::flat::ElementType_IMAGE)
+ out += options_printer->PrintOption("image");
+ if (types & url_pattern_index::flat::ElementType_STYLESHEET)
+ out += options_printer->PrintOption("stylesheet");
+ if (types & url_pattern_index::flat::ElementType_OBJECT)
+ out += options_printer->PrintOption("object");
+ if (types & url_pattern_index::flat::ElementType_XMLHTTPREQUEST)
+ out += options_printer->PrintOption("xmlhttprequest");
+ if (types & url_pattern_index::flat::ElementType_OBJECT_SUBREQUEST)
+ out += options_printer->PrintOption("object-subrequest");
+ if (types & url_pattern_index::flat::ElementType_SUBDOCUMENT)
+ out += options_printer->PrintOption("subdocument");
+ if (types & url_pattern_index::flat::ElementType_PING)
+ out += options_printer->PrintOption("ping");
+ if (types & url_pattern_index::flat::ElementType_MEDIA)
+ out += options_printer->PrintOption("media");
+ if (types & url_pattern_index::flat::ElementType_FONT)
+ out += options_printer->PrintOption("font");
+ if (types & url_pattern_index::flat::ElementType_WEBSOCKET)
+ out += options_printer->PrintOption("websocket");
+
+ return out;
+}
+
+std::string ConvertFlatString(const flatbuffers::String* string) {
+ return string ? std::string(string->data(), string->size()) : "";
+}
+
+std::string DomainOptionsToString(
+ OptionsPrinter* options_printer,
+ const url_pattern_index::flat::UrlRule* flat_rule) {
+ std::string out;
+ if (!flat_rule->domains_included() && !flat_rule->domains_excluded())
+ return "";
+
+ out += options_printer->PrintOption("domain=");
+
+ bool first = true;
+ if (flat_rule->domains_included()) {
+ for (auto* domain : *flat_rule->domains_included()) {
+ if (!first)
+ out += "|";
+ first = false;
+ out += ConvertFlatString(domain);
+ }
+ }
+ if (flat_rule->domains_excluded()) {
+ for (auto* domain : *flat_rule->domains_excluded()) {
+ if (!first)
+ out += "|";
+ first = false;
+ out += "~" + ConvertFlatString(domain);
+ }
+ }
+ return out;
+}
+
+} // namespace
+
+std::string FlatUrlRuleToString(const flat::UrlRule* flat_rule) {
+ std::string out;
+
+ if (flat_rule->options() & url_pattern_index::flat::OptionFlag_IS_WHITELIST)
+ out += "@@";
+
+ out += AnchorToString(flat_rule->anchor_left());
+
+ std::string pattern = ConvertFlatString(flat_rule->url_pattern());
+
+ // Add a wildcard to pattern if necessary to differentiate it from a regex.
+ // E.g., /foo/ should be /foo/*.
+ if (flat_rule->url_pattern_type() !=
+ url_pattern_index::flat::UrlPatternType_REGEXP &&
+ pattern.size() >= 2 && pattern[0] == '/' &&
+ pattern[pattern.size() - 1] == '/') {
+ pattern += "*";
+ }
+ out += pattern;
+
+ out += AnchorToString(flat_rule->anchor_right());
+
+ OptionsPrinter options_printer;
+
+ out += PartyOptionsToString(&options_printer, flat_rule);
+
+ if (flat_rule->options() & url_pattern_index::flat::OptionFlag_IS_MATCH_CASE)
+ out += options_printer.PrintOption("match-case");
+
+ out += TypeOptionsToString(&options_printer, flat_rule);
+
+ out += DomainOptionsToString(&options_printer, flat_rule);
+
+ return out;
+}
+
+} // namespace url_pattern_index
diff --git a/chromium/components/url_pattern_index/url_rule_util.h b/chromium/components/url_pattern_index/url_rule_util.h
new file mode 100644
index 00000000000..a91c3306b57
--- /dev/null
+++ b/chromium/components/url_pattern_index/url_rule_util.h
@@ -0,0 +1,21 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_URL_PATTERN_INDEX_URL_RULE_UTIL_H_
+#define COMPONENTS_URL_PATTERN_INDEX_URL_RULE_UTIL_H_
+
+#include <string>
+
+namespace url_pattern_index {
+
+namespace flat {
+struct UrlRule;
+}
+
+// Prints a UrlRule in string form.
+std::string FlatUrlRuleToString(const flat::UrlRule* flat_rule);
+
+} // namespace url_pattern_index
+
+#endif // COMPONENTS_URL_PATTERN_INDEX_URL_RULE_UTIL_H_
diff --git a/chromium/components/url_pattern_index/url_rule_util_unittest.cc b/chromium/components/url_pattern_index/url_rule_util_unittest.cc
new file mode 100644
index 00000000000..ee6c1bae9a8
--- /dev/null
+++ b/chromium/components/url_pattern_index/url_rule_util_unittest.cc
@@ -0,0 +1,230 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/url_pattern_index/url_rule_util.h"
+
+#include <cmath>
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "components/url_pattern_index/url_pattern.h"
+#include "components/url_pattern_index/url_pattern_index.h"
+#include "components/url_pattern_index/url_rule_test_support.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace url_pattern_index {
+
+namespace {
+
+proto::UrlRule MakeProtoRule(proto::RuleSemantics semantics,
+ const UrlPattern& url_pattern,
+ proto::SourceType source_type,
+ proto::ElementType types,
+ const std::vector<std::string>& domains) {
+ proto::UrlRule rule;
+
+ rule.set_semantics(semantics);
+ rule.set_source_type(source_type);
+ rule.set_element_types(types);
+
+ rule.set_url_pattern_type(url_pattern.type());
+ 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());
+
+ testing::AddDomains(domains, &rule);
+
+ return rule;
+}
+
+struct RuleTest {
+ const char* rule_string;
+ const char* match_string;
+};
+
+class UrlRuleUtilTest : public ::testing::Test {
+ protected:
+ UrlRuleUtilTest() = default;
+
+ const flat::UrlRule* MakeFlatRule(const proto::UrlRule& rule) {
+ auto offset = url_pattern_index::SerializeUrlRule(rule, &flat_builder_);
+ return flatbuffers::GetTemporaryPointer(flat_builder_, offset);
+ }
+
+ flatbuffers::FlatBufferBuilder flat_builder_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(UrlRuleUtilTest);
+};
+
+TEST_F(UrlRuleUtilTest, Blacklist) {
+ const flat::UrlRule* flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("example.com/", FlatUrlRuleToString(flat_rule));
+}
+
+TEST_F(UrlRuleUtilTest, Whitelist) {
+ const flat::UrlRule* flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_WHITELIST, UrlPattern("example.com/"),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("@@example.com/", FlatUrlRuleToString(flat_rule));
+}
+
+TEST_F(UrlRuleUtilTest, LeftAnchor) {
+ const flat::UrlRule* flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST,
+ UrlPattern("example.com/", proto::ANCHOR_TYPE_NONE,
+ proto::ANCHOR_TYPE_NONE),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("example.com/", FlatUrlRuleToString(flat_rule));
+
+ flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST,
+ UrlPattern("example.com/", proto::ANCHOR_TYPE_BOUNDARY,
+ proto::ANCHOR_TYPE_NONE),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("|example.com/", FlatUrlRuleToString(flat_rule));
+
+ flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST,
+ UrlPattern("example.com/", proto::ANCHOR_TYPE_SUBDOMAIN,
+ proto::ANCHOR_TYPE_NONE),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("||example.com/", FlatUrlRuleToString(flat_rule));
+}
+
+TEST_F(UrlRuleUtilTest, RightAnchor) {
+ const flat::UrlRule* flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST,
+ UrlPattern("example.com", proto::ANCHOR_TYPE_NONE,
+ proto::ANCHOR_TYPE_NONE),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("example.com", FlatUrlRuleToString(flat_rule));
+
+ flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST,
+ UrlPattern("example.com", proto::ANCHOR_TYPE_NONE,
+ proto::ANCHOR_TYPE_BOUNDARY),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("example.com|", FlatUrlRuleToString(flat_rule));
+}
+
+TEST_F(UrlRuleUtilTest, BothSidesAnchored) {
+ const flat::UrlRule* flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST,
+ UrlPattern("example.com", proto::ANCHOR_TYPE_SUBDOMAIN,
+ proto::ANCHOR_TYPE_BOUNDARY),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("||example.com|", FlatUrlRuleToString(flat_rule));
+}
+
+TEST_F(UrlRuleUtilTest, NonRegex) {
+ const flat::UrlRule* flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("/foo/"),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("/foo/*", FlatUrlRuleToString(flat_rule));
+
+ // Show that whitelist rules work too.
+ flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_WHITELIST, UrlPattern("/foo/"),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("@@/foo/*", FlatUrlRuleToString(flat_rule));
+
+ // TODO(jkarlin): If regex support is added to UrlRule, verify that regex
+ // rules don't get the '*' appended.
+}
+
+TEST_F(UrlRuleUtilTest, Party) {
+ const flat::UrlRule* flat_rule = MakeFlatRule(MakeProtoRule(
+ proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+ proto::SOURCE_TYPE_THIRD_PARTY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("example.com/$third-party", FlatUrlRuleToString(flat_rule));
+
+ flat_rule = MakeFlatRule(MakeProtoRule(
+ proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+ proto::SOURCE_TYPE_FIRST_PARTY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("example.com/$~third-party", FlatUrlRuleToString(flat_rule));
+}
+
+TEST_F(UrlRuleUtilTest, MultipleOptions) {
+ const flat::UrlRule* flat_rule = MakeFlatRule(MakeProtoRule(
+ proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+ proto::SOURCE_TYPE_THIRD_PARTY, proto::ELEMENT_TYPE_SCRIPT, {}));
+ EXPECT_EQ("example.com/$third-party,script", FlatUrlRuleToString(flat_rule));
+}
+
+TEST_F(UrlRuleUtilTest, ElementType) {
+ // Test a single type.
+ const flat::UrlRule* flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_SCRIPT, {}));
+ EXPECT_EQ("example.com/$script", FlatUrlRuleToString(flat_rule));
+
+ // Test blocking every type.
+ flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("example.com/", FlatUrlRuleToString(flat_rule));
+
+ // Block everything except other. This test will need to be updated as
+ // proto::ElementType is changed.
+ flat_rule = MakeFlatRule(MakeProtoRule(
+ proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+ proto::SOURCE_TYPE_ANY,
+ static_cast<proto::ElementType>(proto::ELEMENT_TYPE_ALL - 1), {}));
+ std::string expected =
+ "example.com/"
+ "$script,image,stylesheet,object,xmlhttprequest,object-subrequest,"
+ "subdocument,ping,media,font,websocket";
+
+ EXPECT_EQ(expected, FlatUrlRuleToString(flat_rule));
+}
+
+TEST_F(UrlRuleUtilTest, ActivationType) {
+ // Test with no activiation type.
+ const flat::UrlRule* flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("example.com/", FlatUrlRuleToString(flat_rule));
+
+ // Test with a document activation type.
+ auto proto_rule =
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {});
+ proto_rule.set_activation_types(proto::ACTIVATION_TYPE_DOCUMENT);
+ flat_rule = MakeFlatRule(proto_rule);
+ EXPECT_EQ("example.com/$document", FlatUrlRuleToString(flat_rule));
+
+ // Test with Document & Generic block types.
+ proto_rule.set_activation_types(proto::ACTIVATION_TYPE_DOCUMENT |
+ proto::ACTIVATION_TYPE_GENERICBLOCK);
+ flat_rule = MakeFlatRule(proto_rule);
+ EXPECT_EQ("example.com/$document,genericblock",
+ FlatUrlRuleToString(flat_rule));
+}
+
+TEST_F(UrlRuleUtilTest, DomainList) {
+ // Test with no domains set.
+ const flat::UrlRule* flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
+ EXPECT_EQ("example.com/", FlatUrlRuleToString(flat_rule));
+
+ // Test with domains set.
+ flat_rule = MakeFlatRule(
+ MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+ proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL,
+ {"foo.example.com", "~bar.example.com"}));
+ EXPECT_EQ("example.com/$domain=foo.example.com|~bar.example.com",
+ FlatUrlRuleToString(flat_rule));
+}
+
+} // namespace
+
+} // namespace url_pattern_index
diff --git a/chromium/components/user_manager/fake_user_manager.cc b/chromium/components/user_manager/fake_user_manager.cc
index 4e16a3d491e..fce3279b09d 100644
--- a/chromium/components/user_manager/fake_user_manager.cc
+++ b/chromium/components/user_manager/fake_user_manager.cc
@@ -5,6 +5,7 @@
#include "components/user_manager/fake_user_manager.h"
#include <algorithm>
+#include <utility>
#include "base/callback.h"
#include "base/command_line.h"
@@ -366,7 +367,7 @@ base::string16 FakeUserManager::GetResourceStringUTF16(int string_id) const {
void FakeUserManager::ScheduleResolveLocale(
const std::string& locale,
- const base::Closure& on_resolved_callback,
+ base::OnceClosure on_resolved_callback,
std::string* out_resolved_locale) const {
NOTIMPLEMENTED();
return;
diff --git a/chromium/components/user_manager/fake_user_manager.h b/chromium/components/user_manager/fake_user_manager.h
index 249e092a9c7..f3554992c17 100644
--- a/chromium/components/user_manager/fake_user_manager.h
+++ b/chromium/components/user_manager/fake_user_manager.h
@@ -113,7 +113,7 @@ class USER_MANAGER_EXPORT FakeUserManager : public UserManagerBase {
const gfx::ImageSkia& GetResourceImagekiaNamed(int id) const override;
base::string16 GetResourceStringUTF16(int string_id) const override;
void ScheduleResolveLocale(const std::string& locale,
- const base::Closure& on_resolved_callback,
+ base::OnceClosure on_resolved_callback,
std::string* out_resolved_locale) const override;
bool IsValidDefaultUserImageId(int image_index) const override;
diff --git a/chromium/components/user_manager/known_user.cc b/chromium/components/user_manager/known_user.cc
index 8763f42b989..b218adb2d77 100644
--- a/chromium/components/user_manager/known_user.cc
+++ b/chromium/components/user_manager/known_user.cc
@@ -61,6 +61,9 @@ const char kProfileEverInitialized[] = "profile_ever_initialized";
// attempted.
const char kMinimalMigrationAttempted[] = "minimal_migration_attempted";
+// Key of the boolean flag telling if user session requires policy.
+const char kProfileRequiresPolicy[] = "profile_requires_policy";
+
PrefService* GetLocalState() {
if (!UserManager::IsInitialized())
return nullptr;
@@ -480,6 +483,22 @@ void SetProfileEverInitialized(const AccountId& account_id, bool initialized) {
SetBooleanPref(account_id, kProfileEverInitialized, initialized);
}
+void 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) {
+ bool requires_policy;
+ if (GetBooleanPref(account_id, kProfileRequiresPolicy, &requires_policy)) {
+ return requires_policy ? ProfileRequiresPolicy::kPolicyRequired
+ : ProfileRequiresPolicy::kNoPolicyRequired;
+ }
+ return ProfileRequiresPolicy::kUnknown;
+}
+
void UpdateReauthReason(const AccountId& account_id, const int reauth_reason) {
SetIntegerPref(account_id, kReauthReasonKey, reauth_reason);
}
diff --git a/chromium/components/user_manager/known_user.h b/chromium/components/user_manager/known_user.h
index 3c3473d991c..38fed5ee1c9 100644
--- a/chromium/components/user_manager/known_user.h
+++ b/chromium/components/user_manager/known_user.h
@@ -138,6 +138,26 @@ bool USER_MANAGER_EXPORT WasProfileEverInitialized(const AccountId& account_id);
void USER_MANAGER_EXPORT SetProfileEverInitialized(const AccountId& account_id,
bool initialized);
+// 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).
+ProfileRequiresPolicy USER_MANAGER_EXPORT
+GetProfileRequiresPolicy(const AccountId& account_id);
+
+// Sets whether the profile requires policy or not.
+void USER_MANAGER_EXPORT
+SetProfileRequiresPolicy(const AccountId& account_id,
+ ProfileRequiresPolicy policy_required);
+
// Saves why the user has to go through re-auth flow.
void USER_MANAGER_EXPORT UpdateReauthReason(const AccountId& account_id,
const int reauth_reason);
diff --git a/chromium/components/user_manager/user.cc b/chromium/components/user_manager/user.cc
index 5d013286150..4448702eae0 100644
--- a/chromium/components/user_manager/user.cc
+++ b/chromium/components/user_manager/user.cc
@@ -9,6 +9,7 @@
#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"
@@ -20,6 +21,20 @@ namespace user_manager {
namespace {
+// Must be in sync with histogram enum UserTypeChanged in enums.xml.
+// The values must never be changed (only new ones can be added) as they
+// are stored in UMA logs.
+enum class UserTypeChangeHistogram {
+ UNKNOWN_FATAL = 0,
+ REGULAR_TO_CHILD = 1,
+ CHILD_TO_REGULAR = 2,
+ COUNT, // Not a value, just a count of other values.
+};
+void UMAUserTypeChanged(const UserTypeChangeHistogram value) {
+ UMA_HISTOGRAM_ENUMERATION("UserManager.UserTypeChanged", value,
+ UserTypeChangeHistogram::COUNT);
+}
+
// Returns account name portion of an email.
std::string GetUserName(const std::string& email) {
std::string::size_type i = email.find('@');
@@ -45,6 +60,7 @@ class RegularUser : public User {
// Overridden from User:
UserType GetType() const override;
+ void UpdateType(UserType user_type) override;
bool CanSyncImage() const override;
private:
@@ -166,6 +182,12 @@ const AccountId& User::GetAccountId() const {
return account_id_;
}
+void User::UpdateType(UserType user_type) {
+ UMAUserTypeChanged(UserTypeChangeHistogram::UNKNOWN_FATAL);
+ LOG(FATAL) << "Unsupported user type change " << GetType() << "=>"
+ << user_type;
+}
+
bool User::HasGaiaAccount() const {
return TypeHasGaiaAccount(GetType());
}
@@ -323,6 +345,30 @@ UserType RegularUser::GetType() const {
user_manager::USER_TYPE_REGULAR;
}
+void RegularUser::UpdateType(UserType user_type) {
+ const UserType current_type = GetType();
+ // Can only change between regular and child.
+ if ((user_type == user_manager::USER_TYPE_CHILD ||
+ user_type == user_manager::USER_TYPE_REGULAR) &&
+ (current_type == user_manager::USER_TYPE_CHILD ||
+ current_type == user_manager::USER_TYPE_REGULAR)) {
+ // We want all the other type changes to crash, that is why this check is
+ // not at the top level.
+ if (user_type == current_type)
+ return;
+ const bool old_is_child = is_child_;
+ is_child_ = user_type == user_manager::USER_TYPE_CHILD;
+ LOG(WARNING) << "User type has changed: " << current_type
+ << " (is_child=" << old_is_child << ") => " << user_type
+ << " (is_child=" << is_child_ << ")";
+ UMAUserTypeChanged(is_child_ ? UserTypeChangeHistogram::REGULAR_TO_CHILD
+ : UserTypeChangeHistogram::CHILD_TO_REGULAR);
+ return;
+ }
+ // Fail with LOG(FATAL).
+ User::UpdateType(user_type);
+}
+
bool RegularUser::CanSyncImage() const {
return true;
}
diff --git a/chromium/components/user_manager/user.h b/chromium/components/user_manager/user.h
index 1d8fa680b7c..074691bd0d4 100644
--- a/chromium/components/user_manager/user.h
+++ b/chromium/components/user_manager/user.h
@@ -87,6 +87,9 @@ class USER_MANAGER_EXPORT User : public UserInfo {
// Returns the user type.
virtual UserType GetType() const = 0;
+ // Will LOG(FATAL) unless overridden.
+ virtual void UpdateType(UserType user_type);
+
// Returns true if user has gaia account. True for users of types
// USER_TYPE_REGULAR and USER_TYPE_CHILD.
virtual bool HasGaiaAccount() const;
@@ -158,6 +161,11 @@ class USER_MANAGER_EXPORT User : public UserInfo {
// Whether the user's session has completed initialization yet.
bool profile_ever_initialized() const { return profile_ever_initialized_; }
+ // Public so it can be called via tests.
+ void set_profile_ever_initialized(bool profile_ever_initialized) {
+ profile_ever_initialized_ = profile_ever_initialized;
+ }
+
// True if the user's session can be locked (i.e. the user has a password with
// which to unlock the session).
bool can_lock() const;
@@ -178,6 +186,12 @@ class USER_MANAGER_EXPORT User : public UserInfo {
return CreatePublicAccountUser(account_id);
}
+ static User* CreateRegularUserForTesting(const AccountId& account_id) {
+ User* user = CreateRegularUser(account_id, USER_TYPE_REGULAR);
+ user->SetImage(std::unique_ptr<UserImage>(new UserImage), 0);
+ return user;
+ }
+
void AddProfileCreatedObserver(base::OnceClosure on_profile_created);
protected:
@@ -245,10 +259,6 @@ class USER_MANAGER_EXPORT User : public UserInfo {
force_online_signin_ = force_online_signin;
}
- void set_profile_ever_initialized(bool profile_ever_initialized) {
- profile_ever_initialized_ = profile_ever_initialized;
- }
-
void set_username_hash(const std::string& username_hash) {
username_hash_ = username_hash;
}
diff --git a/chromium/components/user_manager/user_manager.cc b/chromium/components/user_manager/user_manager.cc
index 060a7c8911f..374eeea1ba3 100644
--- a/chromium/components/user_manager/user_manager.cc
+++ b/chromium/components/user_manager/user_manager.cc
@@ -109,8 +109,17 @@ UserType UserManager::CalculateUserType(const AccountId& account_id,
if (user) {
// This branch works for any other user type, including PUBLIC_ACCOUNT.
const UserType user_type = user->GetType();
- if (is_child && user_type != USER_TYPE_CHILD)
+ if (user_type == USER_TYPE_CHILD || user_type == USER_TYPE_REGULAR) {
+ const UserType new_user_type =
+ is_child ? USER_TYPE_CHILD : USER_TYPE_REGULAR;
+ if (new_user_type != user_type) {
+ LOG(WARNING) << "Child user type has changed: " << user_type << " => "
+ << new_user_type;
+ }
+ return new_user_type;
+ } else if (is_child) {
LOG(FATAL) << "Incorrect child user type " << user_type;
+ }
// TODO (rsorokin): Check for reverse: account_id AD type should imply
// AD user type.
diff --git a/chromium/components/user_manager/user_manager.h b/chromium/components/user_manager/user_manager.h
index 149cfe9c757..4d68eea050d 100644
--- a/chromium/components/user_manager/user_manager.h
+++ b/chromium/components/user_manager/user_manager.h
@@ -392,7 +392,7 @@ class USER_MANAGER_EXPORT UserManager {
// |on_resolved_callback| as reply callback.
virtual void ScheduleResolveLocale(
const std::string& locale,
- const base::Closure& on_resolved_callback,
+ base::OnceClosure on_resolved_callback,
std::string* out_resolved_locale) const = 0;
// Returns true if |image_index| is a valid default user image index.
diff --git a/chromium/components/user_manager/user_manager_base.cc b/chromium/components/user_manager/user_manager_base.cc
index dd80c6a5984..d5072b3bc30 100644
--- a/chromium/components/user_manager/user_manager_base.cc
+++ b/chromium/components/user_manager/user_manager_base.cc
@@ -4,6 +4,7 @@
#include "components/user_manager/user_manager_base.h"
+#include <memory>
#include <stddef.h>
#include <set>
#include <utility>
@@ -16,7 +17,6 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -178,6 +178,7 @@ void UserManagerBase::UserLoggedIn(const AccountId& account_id,
} else {
switch (user_type) {
case USER_TYPE_REGULAR: // fallthrough
+ case USER_TYPE_CHILD: // fallthrough
case USER_TYPE_ACTIVE_DIRECTORY:
if (account_id != GetOwnerAccountId() && !user &&
(AreEphemeralUsersEnabled() || browser_restart)) {
@@ -204,10 +205,6 @@ void UserManagerBase::UserLoggedIn(const AccountId& account_id,
KioskAppLoggedIn(user);
break;
- case USER_TYPE_CHILD:
- RegularUserLoggedIn(account_id, USER_TYPE_CHILD);
- break;
-
case USER_TYPE_ARC_KIOSK_APP:
ArcKioskAppLoggedIn(user);
break;
@@ -345,7 +342,8 @@ void UserManagerBase::RemoveUserFromList(const AccountId& account_id) {
DCHECK(!task_runner_ || task_runner_->RunsTasksInCurrentSequence());
RemoveNonCryptohomeData(account_id);
if (user_loading_stage_ == STAGE_LOADED) {
- DeleteUser(RemoveRegularOrSupervisedUserFromList(account_id));
+ DeleteUser(
+ RemoveRegularOrSupervisedUserFromList(account_id, true /* notify */));
} else if (user_loading_stage_ == STAGE_LOADING) {
DCHECK(IsSupervisedAccountId(account_id));
// Special case, removing partially-constructed supervised user during user
@@ -907,14 +905,18 @@ void UserManagerBase::AddUserRecord(User* user) {
// Add the user to the front of the user list.
ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers);
prefs_users_update->Insert(
- 0, base::MakeUnique<base::Value>(user->GetAccountId().GetUserEmail()));
+ 0, std::make_unique<base::Value>(user->GetAccountId().GetUserEmail()));
users_.insert(users_.begin(), user);
}
void UserManagerBase::RegularUserLoggedIn(const AccountId& account_id,
const UserType user_type) {
// Remove the user from the user list.
- active_user_ = RemoveRegularOrSupervisedUserFromList(account_id);
+ active_user_ =
+ RemoveRegularOrSupervisedUserFromList(account_id, false /* notify */);
+
+ if (active_user_ && active_user_->GetType() != user_type)
+ active_user_->UpdateType(user_type);
// If the user was not found on the user list, create a new user.
SetIsCurrentUserNew(!active_user_);
@@ -1017,7 +1019,8 @@ void UserManagerBase::RemoveNonCryptohomeData(const AccountId& account_id) {
}
User* UserManagerBase::RemoveRegularOrSupervisedUserFromList(
- const AccountId& account_id) {
+ const AccountId& account_id,
+ bool notify) {
ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers);
prefs_users_update->Clear();
User* user = nullptr;
@@ -1034,7 +1037,8 @@ User* UserManagerBase::RemoveRegularOrSupervisedUserFromList(
++it;
}
}
- OnUserRemoved(account_id);
+ if (notify)
+ OnUserRemoved(account_id);
return user;
}
@@ -1113,14 +1117,15 @@ void UserManagerBase::UpdateUserAccountLocale(const AccountId& account_id,
const std::string& locale) {
std::unique_ptr<std::string> resolved_locale(new std::string());
if (!locale.empty() && locale != GetApplicationLocale()) {
- // base::Passed will nullptr out |resolved_locale|, so cache the underlying
+ // std::move will nullptr out |resolved_locale|, so cache the underlying
// ptr.
std::string* raw_resolved_locale = resolved_locale.get();
- ScheduleResolveLocale(locale,
- base::Bind(&UserManagerBase::DoUpdateAccountLocale,
- weak_factory_.GetWeakPtr(), account_id,
- base::Passed(&resolved_locale)),
- raw_resolved_locale);
+ ScheduleResolveLocale(
+ locale,
+ base::BindOnce(&UserManagerBase::DoUpdateAccountLocale,
+ weak_factory_.GetWeakPtr(), account_id,
+ std::move(resolved_locale)),
+ raw_resolved_locale);
} else {
resolved_locale.reset(new std::string(locale));
DoUpdateAccountLocale(account_id, std::move(resolved_locale));
diff --git a/chromium/components/user_manager/user_manager_base.h b/chromium/components/user_manager/user_manager_base.h
index 5c2d8d2b934..006af52d3a7 100644
--- a/chromium/components/user_manager/user_manager_base.h
+++ b/chromium/components/user_manager/user_manager_base.h
@@ -195,7 +195,10 @@ class USER_MANAGER_EXPORT UserManagerBase : public UserManager {
// Removes a regular or supervised user from the user list.
// Returns the user if found or NULL otherwise.
// Also removes the user from the persistent user list.
- User* RemoveRegularOrSupervisedUserFromList(const AccountId& account_id);
+ // |notify| is true when OnUserRemoved() should be triggered,
+ // meaning that the user won't be added after the removal.
+ User* RemoveRegularOrSupervisedUserFromList(const AccountId& account_id,
+ bool notify);
// Implementation for RemoveUser method. This is an asynchronous part of the
// method, that verifies that owner will not get deleted, and calls
diff --git a/chromium/components/variations/BUILD.gn b/chromium/components/variations/BUILD.gn
index 991ea3f41c9..bd2a7fbb775 100644
--- a/chromium/components/variations/BUILD.gn
+++ b/chromium/components/variations/BUILD.gn
@@ -25,10 +25,10 @@ static_library("variations") {
"entropy_provider.h",
"experiment_labels.cc",
"experiment_labels.h",
+ "hashing.cc",
+ "hashing.h",
"metrics.cc",
"metrics.h",
- "metrics_util.cc",
- "metrics_util.h",
"platform_field_trials.h",
"pref_names.cc",
"pref_names.h",
@@ -83,7 +83,6 @@ static_library("variations") {
"//components/crash/core/common:crash_key",
"//components/prefs",
"//crypto",
- "//third_party/mt19937ar",
"//third_party/protobuf:protobuf_lite",
"//third_party/zlib/google:compression_utils",
]
@@ -128,7 +127,8 @@ source_set("unit_tests") {
"child_process_field_trial_syncer_unittest.cc",
"entropy_provider_unittest.cc",
"experiment_labels_unittest.cc",
- "metrics_util_unittest.cc",
+ "hashing_unittest.cc",
+ "net/variations_command_line_unittest.cc",
"net/variations_http_headers_unittest.cc",
"study_filtering_unittest.cc",
"synthetic_trial_registry_unittest.cc",
@@ -151,7 +151,8 @@ source_set("unit_tests") {
"proto",
"//base/test:test_support",
"//components/prefs:test_support",
- "//components/variations/field_trial_config:unit_tests",
+ "//components/variations/field_trial_config:field_trial_config",
+ "//testing/gmock",
"//testing/gtest",
"//third_party/zlib/google:compression_utils",
]
@@ -165,6 +166,7 @@ test("variations_unittests") {
deps = [
":unit_tests",
"//components/test:test_support",
+ "//components/variations/field_trial_config:unit_tests",
"//components/variations/service:unit_tests",
]
}
diff --git a/chromium/components/variations/DEPS b/chromium/components/variations/DEPS
index 720e034fc7f..9f3a04369f5 100644
--- a/chromium/components/variations/DEPS
+++ b/chromium/components/variations/DEPS
@@ -8,7 +8,6 @@ include_rules = [
"+components/variations",
"+crypto",
"-net",
- "+third_party/mt19937ar",
"+third_party/protobuf",
"+third_party/zlib/google",
]
diff --git a/chromium/components/variations/active_field_trials.cc b/chromium/components/variations/active_field_trials.cc
index d71d6e6b39a..f18dfe13bbe 100644
--- a/chromium/components/variations/active_field_trials.cc
+++ b/chromium/components/variations/active_field_trials.cc
@@ -10,7 +10,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "components/variations/metrics_util.h"
+#include "components/variations/hashing.h"
#include "components/variations/synthetic_trials_active_group_id_provider.h"
namespace variations {
@@ -45,8 +45,8 @@ void AppendActiveGroupIdsAsStrings(
ActiveGroupId MakeActiveGroupId(base::StringPiece trial_name,
base::StringPiece group_name) {
ActiveGroupId id;
- id.name = metrics::HashName(trial_name);
- id.group = metrics::HashName(group_name);
+ id.name = HashName(trial_name);
+ id.group = HashName(group_name);
return id;
}
diff --git a/chromium/components/variations/active_field_trials_unittest.cc b/chromium/components/variations/active_field_trials_unittest.cc
index 40909e37f49..b9345176de9 100644
--- a/chromium/components/variations/active_field_trials_unittest.cc
+++ b/chromium/components/variations/active_field_trials_unittest.cc
@@ -7,7 +7,7 @@
#include <stddef.h>
#include "base/strings/string_piece.h"
-#include "components/variations/metrics_util.h"
+#include "components/variations/hashing.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace variations {
@@ -32,11 +32,11 @@ TEST(ActiveFieldTrialsTest, GetFieldTrialActiveGroups) {
// Create our expected groups of IDs.
ActiveGroupIdSet expected_groups;
ActiveGroupId name_group_id;
- name_group_id.name = metrics::HashName(trial_one);
- name_group_id.group = metrics::HashName(group_one);
+ name_group_id.name = HashName(trial_one);
+ name_group_id.group = HashName(group_one);
expected_groups.insert(name_group_id);
- name_group_id.name = metrics::HashName(trial_two);
- name_group_id.group = metrics::HashName(group_two);
+ name_group_id.name = HashName(trial_two);
+ name_group_id.group = HashName(group_two);
expected_groups.insert(name_group_id);
std::vector<ActiveGroupId> active_group_ids;
@@ -68,8 +68,8 @@ TEST(ActiveFieldTrialsTest, GetFieldTrialActiveGroupsWithSuffix) {
&active_group_ids);
EXPECT_EQ(1U, active_group_ids.size());
- uint32_t expected_name = metrics::HashName("trial onesome_suffix");
- uint32_t expected_group = metrics::HashName("group onesome_suffix");
+ uint32_t expected_name = HashName("trial onesome_suffix");
+ uint32_t expected_group = HashName("group onesome_suffix");
EXPECT_EQ(expected_name, active_group_ids[0].name);
EXPECT_EQ(expected_group, active_group_ids[0].group);
}
diff --git a/chromium/components/variations/android/BUILD.gn b/chromium/components/variations/android/BUILD.gn
index 40e0b133653..7e6bc741e15 100644
--- a/chromium/components/variations/android/BUILD.gn
+++ b/chromium/components/variations/android/BUILD.gn
@@ -22,6 +22,7 @@ junit_binary("components_variations_junit_tests") {
":variations_java",
"//base:base_java",
"//base:base_java_test_support",
+ "//base:base_junit_test_support",
"//third_party/hamcrest:hamcrest_java",
]
}
diff --git a/chromium/components/variations/caching_permuted_entropy_provider.cc b/chromium/components/variations/caching_permuted_entropy_provider.cc
index d1788c40a6c..48f6b111143 100644
--- a/chromium/components/variations/caching_permuted_entropy_provider.cc
+++ b/chromium/components/variations/caching_permuted_entropy_provider.cc
@@ -12,7 +12,7 @@
#include "components/prefs/pref_service.h"
#include "components/variations/pref_names.h"
-namespace metrics {
+namespace variations {
CachingPermutedEntropyProvider::CachingPermutedEntropyProvider(
PrefService* local_state,
@@ -105,4 +105,4 @@ bool CachingPermutedEntropyProvider::FindValue(uint32_t randomization_seed,
return false;
}
-} // namespace metrics
+} // namespace variations
diff --git a/chromium/components/variations/caching_permuted_entropy_provider.h b/chromium/components/variations/caching_permuted_entropy_provider.h
index ce76449606d..141e001cef9 100644
--- a/chromium/components/variations/caching_permuted_entropy_provider.h
+++ b/chromium/components/variations/caching_permuted_entropy_provider.h
@@ -17,7 +17,7 @@
class PrefService;
class PrefRegistrySimple;
-namespace metrics {
+namespace variations {
// CachingPermutedEntropyProvider is an entropy provider that uses the same
// algorithm as the PermutedEntropyProvider, but caches the results in Local
@@ -63,6 +63,6 @@ class CachingPermutedEntropyProvider : public PermutedEntropyProvider {
DISALLOW_COPY_AND_ASSIGN(CachingPermutedEntropyProvider);
};
-} // namespace metrics
+} // namespace variations
#endif // COMPONENTS_VARIATIONS_CACHING_PERMUTED_ENTROPY_PROVIDER_H_
diff --git a/chromium/components/variations/caching_permuted_entropy_provider_unittest.cc b/chromium/components/variations/caching_permuted_entropy_provider_unittest.cc
index c7139d8e1e2..5d55e109c7a 100644
--- a/chromium/components/variations/caching_permuted_entropy_provider_unittest.cc
+++ b/chromium/components/variations/caching_permuted_entropy_provider_unittest.cc
@@ -12,7 +12,7 @@
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace metrics {
+namespace variations {
// Size of the low entropy source to use for the permuted entropy provider
// in tests.
@@ -51,4 +51,4 @@ TEST(CachingPermutedEntropyProviderTest, HasConsistentResults) {
}
}
-} // namespace metrics
+} // namespace variations
diff --git a/chromium/components/variations/entropy_provider.cc b/chromium/components/variations/entropy_provider.cc
index 64c3cfc85da..897b4fa693d 100644
--- a/chromium/components/variations/entropy_provider.cc
+++ b/chromium/components/variations/entropy_provider.cc
@@ -13,15 +13,14 @@
#include "base/sha1.h"
#include "base/strings/string_number_conversions.h"
#include "base/sys_byteorder.h"
-#include "components/variations/metrics_util.h"
+#include "components/variations/hashing.h"
-namespace metrics {
+namespace variations {
namespace internal {
-SeededRandGenerator::SeededRandGenerator(uint32_t seed) {
- mersenne_twister_.init_genrand(seed);
-}
+SeededRandGenerator::SeededRandGenerator(uint32_t seed)
+ : mersenne_twister_(seed) {}
SeededRandGenerator::~SeededRandGenerator() {
}
@@ -39,7 +38,7 @@ uint32_t SeededRandGenerator::operator()(uint32_t range) {
uint32_t value;
do {
- value = mersenne_twister_.genrand_int32();
+ value = mersenne_twister_();
} while (value > max_acceptable_value);
return value % range;
@@ -133,4 +132,4 @@ uint16_t PermutedEntropyProvider::GetPermutedValue(
return mapping[low_entropy_source_];
}
-} // namespace metrics
+} // namespace variations
diff --git a/chromium/components/variations/entropy_provider.h b/chromium/components/variations/entropy_provider.h
index 41276019bf1..29001f140fe 100644
--- a/chromium/components/variations/entropy_provider.h
+++ b/chromium/components/variations/entropy_provider.h
@@ -9,15 +9,15 @@
#include <stdint.h>
#include <functional>
+#include <random>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
-#include "third_party/mt19937ar/mt19937ar.h"
-namespace metrics {
+namespace variations {
// Internals of entropy_provider.cc exposed for testing.
namespace internal {
@@ -31,7 +31,7 @@ struct SeededRandGenerator {
// Returns a random number in range [0, range).
uint32_t operator()(uint32_t range);
- MersenneTwister mersenne_twister_;
+ std::mt19937 mersenne_twister_;
};
// Fills |mapping| to create a bijection of values in the range of
@@ -92,6 +92,6 @@ class PermutedEntropyProvider : public base::FieldTrial::EntropyProvider {
DISALLOW_COPY_AND_ASSIGN(PermutedEntropyProvider);
};
-} // namespace metrics
+} // namespace variations
#endif // COMPONENTS_VARIATIONS_ENTROPY_PROVIDER_H_
diff --git a/chromium/components/variations/entropy_provider_unittest.cc b/chromium/components/variations/entropy_provider_unittest.cc
index 6d032a9b2de..79439eb6dfe 100644
--- a/chromium/components/variations/entropy_provider_unittest.cc
+++ b/chromium/components/variations/entropy_provider_unittest.cc
@@ -16,10 +16,10 @@
#include "base/macros.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
-#include "components/variations/metrics_util.h"
+#include "components/variations/hashing.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace metrics {
+namespace variations {
namespace {
@@ -396,4 +396,4 @@ TEST(EntropyProviderTest, SeededRandGeneratorIsUniform) {
}
}
-} // namespace metrics
+} // namespace variations
diff --git a/chromium/components/variations/metrics_util.cc b/chromium/components/variations/hashing.cc
index e6e713c4c6f..3383201f83c 100644
--- a/chromium/components/variations/metrics_util.cc
+++ b/chromium/components/variations/hashing.cc
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/variations/metrics_util.h"
+#include "components/variations/hashing.h"
#include <string.h>
#include "base/sha1.h"
#include "base/sys_byteorder.h"
-namespace metrics {
+namespace variations {
uint32_t HashName(base::StringPiece name) {
// SHA-1 is designed to produce a uniformly random spread in its output space,
@@ -25,4 +25,4 @@ uint32_t HashName(base::StringPiece name) {
return base::ByteSwapToLE32(bits);
}
-} // namespace metrics
+} // namespace variations
diff --git a/chromium/components/variations/metrics_util.h b/chromium/components/variations/hashing.h
index 76254d45810..149813f9f6a 100644
--- a/chromium/components/variations/metrics_util.h
+++ b/chromium/components/variations/hashing.h
@@ -2,20 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_VARIATIONS_METRICS_UTIL_H_
-#define COMPONENTS_VARIATIONS_METRICS_UTIL_H_
+#ifndef COMPONENTS_VARIATIONS_HASHING_H_
+#define COMPONENTS_VARIATIONS_HASHING_H_
#include <stdint.h>
#include "base/strings/string_piece.h"
-// TODO(rkaplow): Move to variations namespace and rename file hashing.h.
-namespace metrics {
+namespace variations {
// Computes a uint32_t hash of a given string based on its SHA1 hash. Suitable
// for uniquely identifying field trial names and group names.
uint32_t HashName(base::StringPiece name);
-} // namespace metrics
+} // namespace variations
-#endif // COMPONENTS_VARIATIONS_METRICS_UTIL_H_
+#endif // COMPONENTS_VARIATIONS_HASHING_H_
diff --git a/chromium/components/variations/hashing_unittest.cc b/chromium/components/variations/hashing_unittest.cc
new file mode 100644
index 00000000000..58592dfe5bc
--- /dev/null
+++ b/chromium/components/variations/hashing_unittest.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/variations/hashing.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace variations {
+
+TEST(HashingTest, HashName) {
+ // Checks that hashing is stable on all platforms.
+ struct {
+ const char* name;
+ uint32_t hash_value;
+ } known_hashes[] = {{"a", 937752454u},
+ {"1", 723085877u},
+ {"Trial Name", 2713117220u},
+ {"Group Name", 3201815843u},
+ {"My Favorite Experiment", 3722155194u},
+ {"My Awesome Group Name", 4109503236u},
+ {"abcdefghijklmonpqrstuvwxyz", 787728696u},
+ {"0123456789ABCDEF", 348858318U}};
+
+ for (size_t i = 0; i < arraysize(known_hashes); ++i) {
+ EXPECT_EQ(known_hashes[i].hash_value, HashName(known_hashes[i].name));
+ }
+}
+
+} // namespace variations
diff --git a/chromium/components/variations/metrics.cc b/chromium/components/variations/metrics.cc
index a59d3d6920e..05cd56a3b17 100644
--- a/chromium/components/variations/metrics.cc
+++ b/chromium/components/variations/metrics.cc
@@ -20,6 +20,11 @@ void RecordLoadSeedResult(LoadSeedResult state) {
LoadSeedResult::ENUM_SIZE);
}
+void RecordLoadSafeSeedResult(LoadSeedResult state) {
+ UMA_HISTOGRAM_ENUMERATION("Variations.SafeMode.LoadSafeSeed.Result", state,
+ LoadSeedResult::ENUM_SIZE);
+}
+
void RecordStoreSeedResult(StoreSeedResult result) {
UMA_HISTOGRAM_ENUMERATION("Variations.SeedStoreResult", result,
StoreSeedResult::ENUM_SIZE);
diff --git a/chromium/components/variations/metrics.h b/chromium/components/variations/metrics.h
index 28e846da512..832f39ba83a 100644
--- a/chromium/components/variations/metrics.h
+++ b/chromium/components/variations/metrics.h
@@ -83,9 +83,13 @@ enum class VerifySignatureResult {
void RecordFirstRunSeedImportResult(FirstRunSeedImportResult result);
#endif // OS_ANDROID
-// Records the result of attempting to load a variations seed on startup.
+// Records the result of attempting to load the latest variations seed on
+// startup.
void RecordLoadSeedResult(LoadSeedResult state);
+// Records the result of attempting to load the safe variations seed on startup.
+void RecordLoadSafeSeedResult(LoadSeedResult state);
+
// Records the result of attempting to store a variations seed received from the
// server.
void RecordStoreSeedResult(StoreSeedResult result);
diff --git a/chromium/components/variations/metrics_util_unittest.cc b/chromium/components/variations/metrics_util_unittest.cc
deleted file mode 100644
index 953e1390d0e..00000000000
--- a/chromium/components/variations/metrics_util_unittest.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/variations/metrics_util.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace metrics {
-
-TEST(MetricsUtilTest, HashName) {
- // Checks that hashing is stable on all platforms.
- struct {
- const char* name;
- uint32_t hash_value;
- } known_hashes[] = {
- {"a", 937752454u},
- {"1", 723085877u},
- {"Trial Name", 2713117220u},
- {"Group Name", 3201815843u},
- {"My Favorite Experiment", 3722155194u},
- {"My Awesome Group Name", 4109503236u},
- {"abcdefghijklmonpqrstuvwxyz", 787728696u},
- {"0123456789ABCDEF", 348858318U}
- };
-
- for (size_t i = 0; i < arraysize(known_hashes); ++i)
- EXPECT_EQ(known_hashes[i].hash_value, HashName(known_hashes[i].name));
-}
-
-} // namespace metrics
diff --git a/chromium/components/variations/net/BUILD.gn b/chromium/components/variations/net/BUILD.gn
index 148bf79a12d..dc870aa1557 100644
--- a/chromium/components/variations/net/BUILD.gn
+++ b/chromium/components/variations/net/BUILD.gn
@@ -4,6 +4,8 @@
static_library("net") {
sources = [
+ "variations_command_line.cc",
+ "variations_command_line.h",
"variations_http_headers.cc",
"variations_http_headers.h",
]
@@ -17,6 +19,7 @@ static_library("net") {
"//base",
"//components/google/core/browser",
"//components/metrics",
+ "//components/variations/field_trial_config",
"//components/variations/proto",
]
}
diff --git a/chromium/components/variations/net/variations_command_line.cc b/chromium/components/variations/net/variations_command_line.cc
new file mode 100644
index 00000000000..b515f16cd43
--- /dev/null
+++ b/chromium/components/variations/net/variations_command_line.cc
@@ -0,0 +1,51 @@
+// Copyright 2018 The Chromium Authors. All 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/net/variations_command_line.h"
+
+#include "base/base_switches.h"
+#include "base/feature_list.h"
+#include "base/metrics/field_trial.h"
+#include "components/variations/field_trial_config/field_trial_util.h"
+#include "components/variations/variations_switches.h"
+#include "net/base/escape.h"
+
+namespace variations {
+
+namespace {
+
+// Format the provided |param_key| and |param_value| as commandline input.
+std::string GenerateParam(const std::string& param_key,
+ const std::string& param_value) {
+ if (!param_value.empty())
+ return " --" + param_key + "=\"" + param_value + "\"";
+
+ return "";
+}
+
+} // namespace
+
+std::string GetVariationsCommandLine() {
+ std::string field_trial_states;
+ base::FieldTrialList::AllStatesToString(&field_trial_states, true);
+
+ std::string field_trial_params =
+ base::FieldTrialList::AllParamsToString(true, &EscapeValue);
+
+ std::string enable_features;
+ std::string disable_features;
+ base::FeatureList::GetInstance()->GetFeatureOverrides(&enable_features,
+ &disable_features);
+
+ std::string output;
+ output.append(
+ GenerateParam(::switches::kForceFieldTrials, field_trial_states));
+ output.append(
+ GenerateParam(switches::kForceFieldTrialParams, field_trial_params));
+ output.append(GenerateParam(::switches::kEnableFeatures, enable_features));
+ output.append(GenerateParam(::switches::kDisableFeatures, disable_features));
+ return output;
+}
+
+} // namespace variations
diff --git a/chromium/components/variations/net/variations_command_line.h b/chromium/components/variations/net/variations_command_line.h
new file mode 100644
index 00000000000..fb15b3e5a1c
--- /dev/null
+++ b/chromium/components/variations/net/variations_command_line.h
@@ -0,0 +1,19 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VARIATIONS_NET_VARIATIONS_COMMAND_LINE_H_
+#define COMPONENTS_VARIATIONS_NET_VARIATIONS_COMMAND_LINE_H_
+
+#include <string>
+
+namespace variations {
+
+// Generates a string containing the complete state of variations (including all
+// the registered trials with corresponding groups, params and features) for the
+// client in command-line format.
+std::string GetVariationsCommandLine();
+
+} // namespace variations
+
+#endif // COMPONENTS_VARIATIONS_NET_VARIATIONS_COMMAND_LINE_H_ \ No newline at end of file
diff --git a/chromium/components/variations/net/variations_command_line_unittest.cc b/chromium/components/variations/net/variations_command_line_unittest.cc
new file mode 100644
index 00000000000..0c26abf3fb5
--- /dev/null
+++ b/chromium/components/variations/net/variations_command_line_unittest.cc
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/variations/net/variations_command_line.h"
+
+#include <stddef.h>
+
+#include "base/macros.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/variations/field_trial_config/field_trial_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace variations {
+
+TEST(VariationsCommandLineTest, TestGetVariationsCommandLine) {
+ std::string trial_list = "trial1/group1/*trial2/group2/";
+ std::string param_list = "trial1.group1:p1/v1/p2/2";
+ std::string enable_feature_list = "feature1<trial1";
+ std::string disable_feature_list = "feature2<trial2";
+
+ base::FieldTrialList field_trial_list(nullptr);
+ AssociateParamsFromString(param_list);
+ base::FieldTrialList::CreateTrialsFromString(trial_list,
+ std::set<std::string>());
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitFromCommandLine(enable_feature_list,
+ disable_feature_list);
+
+ std::string output = GetVariationsCommandLine();
+ EXPECT_NE(output.find(trial_list), std::string::npos);
+ EXPECT_NE(output.find(param_list), std::string::npos);
+ EXPECT_NE(output.find(enable_feature_list), std::string::npos);
+ EXPECT_NE(output.find(disable_feature_list), std::string::npos);
+}
+
+} // namespace variations \ No newline at end of file
diff --git a/chromium/components/variations/pref_names.cc b/chromium/components/variations/pref_names.cc
index dd4fdea56d4..6e01e80c696 100644
--- a/chromium/components/variations/pref_names.cc
+++ b/chromium/components/variations/pref_names.cc
@@ -24,7 +24,7 @@ const char kVariationsFailedToFetchSeedStreak[] =
"variations_failed_to_fetch_seed_streak";
// The serialized base::Time from the last successful seed fetch (i.e. when the
-// Variations server responds with 200 or 304).
+// Variations server responds with 200 or 304). This is a client timestamp.
const char kVariationsLastFetchTime[] = "variations_last_fetch_time";
// Pair of <Chrome version string, country code string> representing the country
@@ -49,11 +49,22 @@ const char kVariationsRestrictParameter[] = "variations_restrict_parameter";
// https://docs.google.com/document/d/17UN2pLSa5JZqk8f3LeYZIftXewxqcITotgalTrJvGSY
const char kVariationsSafeCompressedSeed[] = "variations_safe_compressed_seed";
-// The serialized base::Time at which the last known "safe" seed was received.
-// An empty/default-constructed base::Time time if there is no known "safe"
-// 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.
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
+// 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
+// data.
+const char kVariationsSafeSeedFetchTime[] = "variations_safe_seed_fetch_time";
+
// The active client locale that was successfully used in association with the
// last known "safe" seed.
const char kVariationsSafeSeedLocale[] = "variations_safe_seed_locale";
@@ -74,11 +85,12 @@ const char kVariationsSafeSeedSessionConsistencyCountry[] =
// base64-encoded. Empty if there is no known "safe" seed.
const char kVariationsSafeSeedSignature[] = "variations_safe_seed_signature";
-// The serialized base::Time from the last seed received.
+// The serialized base::Time from the last seed received. This is a
+// server-provided timestamp.
const char kVariationsSeedDate[] = "variations_seed_date";
// Digital signature of the binary variations seed data, base64-encoded.
const char kVariationsSeedSignature[] = "variations_seed_signature";
} // namespace prefs
-} // namespace metrics
+} // namespace variations
diff --git a/chromium/components/variations/pref_names.h b/chromium/components/variations/pref_names.h
index c9d18c5d322..a058a544387 100644
--- a/chromium/components/variations/pref_names.h
+++ b/chromium/components/variations/pref_names.h
@@ -21,6 +21,7 @@ extern const char kVariationsPermutedEntropyCache[];
extern const char kVariationsRestrictParameter[];
extern const char kVariationsSafeCompressedSeed[];
extern const char kVariationsSafeSeedDate[];
+extern const char kVariationsSafeSeedFetchTime[];
extern const char kVariationsSafeSeedLocale[];
extern const char kVariationsSafeSeedPermanentConsistencyCountry[];
extern const char kVariationsSafeSeedSessionConsistencyCountry[];
@@ -29,6 +30,6 @@ extern const char kVariationsSeedDate[];
extern const char kVariationsSeedSignature[];
} // namespace prefs
-} // namespace metrics
+} // namespace variations
#endif // COMPONENTS_VARIATIONS_PREF_NAMES_H_
diff --git a/chromium/components/variations/processed_study.cc b/chromium/components/variations/processed_study.cc
index 493154388ab..8af4c593910 100644
--- a/chromium/components/variations/processed_study.cc
+++ b/chromium/components/variations/processed_study.cc
@@ -20,7 +20,7 @@ bool ValidateStudyAndComputeTotalProbability(
const Study& study,
base::FieldTrial::Probability* total_probability,
bool* all_assignments_to_one_group,
- std::string* single_feature_name) {
+ std::vector<std::string>* associated_features) {
if (study.filter().has_min_version() &&
!base::Version::IsValidWildcardString(study.filter().min_version())) {
DVLOG(1) << study.name() << " has invalid min version: "
@@ -97,10 +97,19 @@ bool ValidateStudyAndComputeTotalProbability(
return false;
}
- if (!has_multiple_features && !single_feature_name_seen.empty())
- single_feature_name->swap(single_feature_name_seen);
- else
- single_feature_name->clear();
+ // Check if this study enables/disables a single feature and uses explicit
+ // activation (i.e. the trial should be activated when queried). If so, ensure
+ // that groups that don't explicitly enable/disable that feature are still
+ // associated with it (i.e. so "Default" group gets reported).
+ //
+ // Note: This checks for ACTIVATION_EXPLICIT, since there is no reason to
+ // have this association with ACTIVATION_AUTO (where the trial starts active),
+ // as well as allowing flexibility to disable this behavior in the future from
+ // the server by introducing a new activation type.
+ if (!has_multiple_features && !single_feature_name_seen.empty() &&
+ study.activation_type() == Study_ActivationType_ACTIVATION_EXPLICIT) {
+ associated_features->push_back(single_feature_name_seen);
+ }
*total_probability = divisor;
*all_assignments_to_one_group = !multiple_assigned_groups;
@@ -114,11 +123,9 @@ bool ValidateStudyAndComputeTotalProbability(
const char ProcessedStudy::kGenericDefaultExperimentName[] =
"VariationsDefaultExperiment";
-ProcessedStudy::ProcessedStudy()
- : study_(nullptr),
- total_probability_(0),
- all_assignments_to_one_group_(false),
- is_expired_(false) {}
+ProcessedStudy::ProcessedStudy() {}
+
+ProcessedStudy::ProcessedStudy(const ProcessedStudy& other) = default;
ProcessedStudy::~ProcessedStudy() {
}
@@ -126,10 +133,10 @@ ProcessedStudy::~ProcessedStudy() {
bool ProcessedStudy::Init(const Study* study, bool is_expired) {
base::FieldTrial::Probability total_probability = 0;
bool all_assignments_to_one_group = false;
- std::string single_feature_name;
+ std::vector<std::string> associated_features;
if (!ValidateStudyAndComputeTotalProbability(*study, &total_probability,
&all_assignments_to_one_group,
- &single_feature_name)) {
+ &associated_features)) {
return false;
}
@@ -137,7 +144,7 @@ bool ProcessedStudy::Init(const Study* study, bool is_expired) {
is_expired_ = is_expired;
total_probability_ = total_probability;
all_assignments_to_one_group_ = all_assignments_to_one_group;
- single_feature_name_.swap(single_feature_name);
+ associated_features_.swap(associated_features);
return true;
}
diff --git a/chromium/components/variations/processed_study.h b/chromium/components/variations/processed_study.h
index e7807f5cf77..504b5f4ddc2 100644
--- a/chromium/components/variations/processed_study.h
+++ b/chromium/components/variations/processed_study.h
@@ -23,6 +23,7 @@ class ProcessedStudy {
static const char kGenericDefaultExperimentName[];
ProcessedStudy();
+ ProcessedStudy(const ProcessedStudy& other);
~ProcessedStudy();
bool Init(const Study* study, bool is_expired);
@@ -39,8 +40,8 @@ class ProcessedStudy {
bool is_expired() const { return is_expired_; }
- const std::string& single_feature_name() const {
- return single_feature_name_;
+ const std::vector<std::string>& associated_features() const {
+ return associated_features_;
}
// Gets the index of the experiment with the given |name|. Returns -1 if no
@@ -58,20 +59,22 @@ class ProcessedStudy {
private:
// Corresponding Study object. Weak reference.
- const Study* study_;
+ const Study* study_ = nullptr;
// Computed total group probability for the study.
- base::FieldTrial::Probability total_probability_;
+ base::FieldTrial::Probability total_probability_ = 0;
// Whether all assignments are to a single group.
- bool all_assignments_to_one_group_;
+ bool all_assignments_to_one_group_ = false;
// Whether the study is expired.
- bool is_expired_;
+ bool is_expired_ = false;
- // If the study has groups that enable/disable a single feature, the name of
- // that feature.
- std::string single_feature_name_;
+ // A list of feature names associated with this study by default. Studies
+ // might have groups that do not specify any feature associations – this is
+ // often the case for a default group, for example. The features listed here
+ // will be associated with all such groups.
+ std::vector<std::string> associated_features_;
};
} // namespace variations
diff --git a/chromium/components/variations/proto/permuted_entropy_cache.proto b/chromium/components/variations/proto/permuted_entropy_cache.proto
index fb78a06ef07..5bba6d164db 100644
--- a/chromium/components/variations/proto/permuted_entropy_cache.proto
+++ b/chromium/components/variations/proto/permuted_entropy_cache.proto
@@ -6,7 +6,7 @@ syntax = "proto2";
option optimize_for = LITE_RUNTIME;
-package metrics;
+package variations;
// Represents a cache of permuted entropy mappings, where each entry maps from
// a |randomization_seed| to a |value|.
diff --git a/chromium/components/variations/service/safe_seed_manager.cc b/chromium/components/variations/service/safe_seed_manager.cc
index d22b8133db8..e82dd986713 100644
--- a/chromium/components/variations/service/safe_seed_manager.cc
+++ b/chromium/components/variations/service/safe_seed_manager.cc
@@ -17,6 +17,53 @@
namespace variations {
+// As of the time of this writing, January 2018, users at the 99.5th percentile,
+// across all platforms, tend to experience fewer than 3 consecutive crashes:
+// [1], [2], [3], [4]. Note, however, that this is less true for the less-stable
+// channels on some platforms.
+// [1] All platforms, stable channel (consistently stable):
+// https://uma.googleplex.com/timeline_v2?sid=90ac80f4573249fb341a8e49501bfcfd
+// [2] Most platforms, all channels (consistently stable other than occasional
+// spikes on Canary):
+// https://uma.googleplex.com/timeline_v2?sid=7af5ba1969db76689a401f982a1db539
+// [3] A less stable platform, all channels:
+// https://uma.googleplex.com/timeline_v2?sid=07dbc8e4fa9f08e332fb609309a21882
+// [4] Another less stable platform, all channels:
+// https://uma.googleplex.com/timeline_v2?sid=a7b529ef5d52863fae2d216e963c4cbc
+// Overall, the only {platform, channel} combinations that spike above 3
+// consecutive crashes are ones with very few users, plus Canary. It's probably
+// not realistic to avoid false positives for these less-stable configurations.
+constexpr int kCrashStreakThreshold = 3;
+
+// Consecutive seed fetch failures are, unfortunately, a bit more common. As of
+// January 2018, users at the 99.5th percentile tend to see fewer than 4
+// consecutive fetch failures on mobile platforms; and users at the 99th
+// percentile tend to see fewer than 5 or 6 consecutive failures on desktop
+// platforms. It makes sense that the characteristics differ on mobile
+// vs. desktop platforms, given that the two use different scheduling algorithms
+// for the fetches. Graphs:
+// [1] Android, all channels (consistently connected):
+// https://uma.googleplex.com/timeline_v2?sid=99d1d4c2490c60bcbde7afeb77c12a28
+// [2] High-connectivity platforms, Stable and Beta channel (consistently
+// connected):
+// https://uma.googleplex.com/timeline_v2?sid=2db5b7278dad41cbf349f5f2cb30efd9
+// [3] Other platforms, Stable and Beta channel (slightly less connected):
+// https://uma.googleplex.com/timeline_v2?sid=d4ba2f3751d211898f8e69214147c2ec
+// [4] All platforms, Dev (even less connected):
+// https://uma.googleplex.com/timeline_v2?sid=5740fb22b17faa823822adfd8e00ec1a
+// [5] All platforms, Canary (actually fairly well-connected!):
+// https://uma.googleplex.com/timeline_v2?sid=3e14d3e4887792bb614db9f3f2c1d48c
+// Note the all of the graphs show a spike on a particular day, presumably due
+// to server-side instability. Moreover, the Dev channel on desktop is an
+// outlier – users on the Dev channel can experience just shy of 9 consecutive
+// failures on some platforms.
+// Decision: There is not an obvious threshold that both achieves a low
+// false-positive rate and provides good coverage for true positives. For now,
+// set a threshold that should minimize false-positives.
+// TODO(isherman): Check in with the networking team about their thoughts on how
+// to find a better balance here.
+constexpr int kFetchFailureStreakThreshold = 25;
+
SafeSeedManager::SafeSeedManager(bool did_previous_session_exit_cleanly,
PrefService* local_state)
: local_state_(local_state) {
@@ -31,25 +78,12 @@ SafeSeedManager::SafeSeedManager(bool did_previous_session_exit_cleanly,
local_state->SetInteger(prefs::kVariationsCrashStreak, num_crashes);
}
- // After three failures in a row -- either consistent crashes or consistent
- // failures to fetch the seed -- assume that the current seed is bad, and fall
- // back to the safe seed. However, ignore any number of failures if the
- // --force-fieldtrials flag is set, as this flag is only used by developers,
- // and there's no need to make the development process flakier.
- const int kMaxFailuresBeforeRevertingToSafeSeed = 3;
- int num_failures_to_fetch =
+ int num_failed_fetches =
local_state->GetInteger(prefs::kVariationsFailedToFetchSeedStreak);
- bool fall_back_to_safe_mode =
- (num_crashes >= kMaxFailuresBeforeRevertingToSafeSeed ||
- num_failures_to_fetch >= kMaxFailuresBeforeRevertingToSafeSeed) &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- ::switches::kForceFieldTrials);
- UMA_HISTOGRAM_BOOLEAN("Variations.SafeMode.FellBackToSafeMode",
- fall_back_to_safe_mode);
base::UmaHistogramSparse("Variations.SafeMode.Streak.Crashes",
base::ClampToRange(num_crashes, 0, 100));
base::UmaHistogramSparse("Variations.SafeMode.Streak.FetchFailures",
- base::ClampToRange(num_failures_to_fetch, 0, 100));
+ base::ClampToRange(num_failed_fetches, 0, 100));
}
SafeSeedManager::~SafeSeedManager() = default;
@@ -61,15 +95,33 @@ void SafeSeedManager::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterIntegerPref(prefs::kVariationsFailedToFetchSeedStreak, 0);
}
+bool SafeSeedManager::ShouldRunInSafeMode() const {
+ // Ignore any number of failures if the --force-fieldtrials flag is set. This
+ // flag is only used by developers, and there's no need to make the
+ // development process flakier.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ ::switches::kForceFieldTrials)) {
+ return false;
+ }
+
+ int num_crashes = local_state_->GetInteger(prefs::kVariationsCrashStreak);
+ int num_failed_fetches =
+ local_state_->GetInteger(prefs::kVariationsFailedToFetchSeedStreak);
+ return num_crashes >= kCrashStreakThreshold ||
+ num_failed_fetches >= kFetchFailureStreakThreshold;
+}
+
void SafeSeedManager::SetActiveSeedState(
const std::string& seed_data,
const std::string& base64_seed_signature,
- std::unique_ptr<ClientFilterableState> client_filterable_state) {
+ std::unique_ptr<ClientFilterableState> client_filterable_state,
+ base::Time seed_fetch_time) {
DCHECK(!has_set_active_seed_state_);
has_set_active_seed_state_ = true;
active_seed_state_ = std::make_unique<ActiveSeedState>(
- seed_data, base64_seed_signature, std::move(client_filterable_state));
+ seed_data, base64_seed_signature, std::move(client_filterable_state),
+ seed_fetch_time);
}
void SafeSeedManager::RecordFetchStarted() {
@@ -89,11 +141,10 @@ void SafeSeedManager::RecordSuccessfulFetch(VariationsSeedStore* seed_store) {
// even if running in safe mode, as the saved seed in that case will just be
// the existing safe seed.
if (active_seed_state_) {
- // TODO(isherman): As an optimization, skip writing the seed if we're
- // already running in safe mode.
seed_store->StoreSafeSeed(active_seed_state_->seed_data,
active_seed_state_->base64_seed_signature,
- *active_seed_state_->client_filterable_state);
+ *active_seed_state_->client_filterable_state,
+ active_seed_state_->seed_fetch_time);
// The active seed state is only needed for the first time this code path is
// reached, so free up its memory once the data is no longer needed.
@@ -111,10 +162,12 @@ void SafeSeedManager::RecordSuccessfulFetch(VariationsSeedStore* seed_store) {
SafeSeedManager::ActiveSeedState::ActiveSeedState(
const std::string& seed_data,
const std::string& base64_seed_signature,
- std::unique_ptr<ClientFilterableState> client_filterable_state)
+ std::unique_ptr<ClientFilterableState> client_filterable_state,
+ base::Time seed_fetch_time)
: seed_data(seed_data),
base64_seed_signature(base64_seed_signature),
- client_filterable_state(std::move(client_filterable_state)) {}
+ client_filterable_state(std::move(client_filterable_state)),
+ seed_fetch_time(seed_fetch_time) {}
SafeSeedManager::ActiveSeedState::~ActiveSeedState() = default;
diff --git a/chromium/components/variations/service/safe_seed_manager.h b/chromium/components/variations/service/safe_seed_manager.h
index e1e76da0fb5..5855f7a07f2 100644
--- a/chromium/components/variations/service/safe_seed_manager.h
+++ b/chromium/components/variations/service/safe_seed_manager.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/macros.h"
+#include "base/time/time.h"
class PrefRegistrySimple;
class PrefService;
@@ -30,13 +31,19 @@ class SafeSeedManager {
// Register safe mode prefs in Local State.
static void RegisterPrefs(PrefRegistrySimple* registry);
+ // Returns true iff the client should use the safe seed for variations state.
+ // Virtual for testing.
+ virtual bool ShouldRunInSafeMode() const;
+
// Stores the combined server and client state that control the active
// variations state. Must be called at most once per launch of the Chrome app.
+ // As an optimization, should not be called when running in safe mode.
// Virtual for testing.
virtual void SetActiveSeedState(
const std::string& seed_data,
const std::string& base64_seed_signature,
- std::unique_ptr<ClientFilterableState> client_filterable_state);
+ std::unique_ptr<ClientFilterableState> client_filterable_state,
+ base::Time seed_fetch_time);
// Records that a fetch has started: pessimistically increments the
// corresponding failure streak for safe mode.
@@ -49,12 +56,13 @@ class SafeSeedManager {
private:
// The combined server and client state needed to save an active seed as a
- // safe seed.
+ // safe seed. Not set when running in safe mode.
struct ActiveSeedState {
ActiveSeedState(
const std::string& seed_data,
const std::string& base64_seed_signature,
- std::unique_ptr<ClientFilterableState> client_filterable_state);
+ std::unique_ptr<ClientFilterableState> client_filterable_state,
+ base::Time seed_fetch_time);
~ActiveSeedState();
// The serialized variations seed data.
@@ -65,6 +73,10 @@ class SafeSeedManager {
// The client state which is used for filtering studies.
const std::unique_ptr<ClientFilterableState> client_filterable_state;
+
+ // The latest timestamp at which this seed was fetched. This is always a
+ // client-side timestamp, never a server-provided timestamp.
+ const base::Time seed_fetch_time;
};
std::unique_ptr<ActiveSeedState> active_seed_state_;
diff --git a/chromium/components/variations/service/safe_seed_manager_unittest.cc b/chromium/components/variations/service/safe_seed_manager_unittest.cc
index 289de528741..0ae6b5c6e3f 100644
--- a/chromium/components/variations/service/safe_seed_manager_unittest.cc
+++ b/chromium/components/variations/service/safe_seed_manager_unittest.cc
@@ -7,10 +7,14 @@
#include <memory>
#include <string>
+#include "base/base_switches.h"
+#include "base/command_line.h"
#include "base/macros.h"
+#include "base/test/histogram_tester.h"
#include "base/time/time.h"
#include "components/prefs/testing_pref_service.h"
#include "components/variations/client_filterable_state.h"
+#include "components/variations/pref_names.h"
#include "components/variations/variations_seed_store.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -23,26 +27,31 @@ const char kTestLocale[] = "en-US";
const char kTestPermanentConsistencyCountry[] = "US";
const char kTestSessionConsistencyCountry[] = "CA";
+base::Time GetTestFetchTime() {
+ return base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromDays(123));
+}
+
// A simple fake data store.
class FakeSeedStore : public VariationsSeedStore {
public:
- FakeSeedStore() : VariationsSeedStore(nullptr) {}
+ explicit FakeSeedStore(PrefService* local_state)
+ : VariationsSeedStore(local_state) {}
~FakeSeedStore() override = default;
bool StoreSafeSeed(const std::string& seed_data,
const std::string& base64_seed_signature,
- const ClientFilterableState& client_state) override {
+ const ClientFilterableState& client_state,
+ base::Time seed_fetch_time) override {
seed_data_ = seed_data;
signature_ = base64_seed_signature;
date_ = client_state.reference_date;
locale_ = client_state.locale;
permanent_consistency_country_ = client_state.permanent_consistency_country;
session_consistency_country_ = client_state.session_consistency_country;
+ fetch_time_ = seed_fetch_time;
return true;
}
- // TODO(isherman): Replace these with a LoadSafeSeed() function once that's
- // implemented on the seed store.
const std::string& seed_data() const { return seed_data_; }
const std::string& signature() const { return signature_; }
const base::Time& date() const { return date_; }
@@ -53,6 +62,7 @@ class FakeSeedStore : public VariationsSeedStore {
const std::string& session_consistency_country() const {
return session_consistency_country_;
}
+ const base::Time& fetch_time() const { return fetch_time_; }
private:
// The stored data.
@@ -62,6 +72,7 @@ class FakeSeedStore : public VariationsSeedStore {
std::string locale_;
std::string permanent_consistency_country_;
std::string session_consistency_country_;
+ base::Time fetch_time_;
DISALLOW_COPY_AND_ASSIGN(FakeSeedStore);
};
@@ -77,8 +88,8 @@ void SetDefaultActiveState(SafeSeedManager* safe_seed_manager) {
client_state->session_consistency_country = kTestSessionConsistencyCountry;
client_state->reference_date = base::Time::UnixEpoch();
- safe_seed_manager->SetActiveSeedState(kTestSeed, kTestSignature,
- std::move(client_state));
+ safe_seed_manager->SetActiveSeedState(
+ kTestSeed, kTestSignature, std::move(client_state), GetTestFetchTime());
}
// Verifies that the default test values were written to the seed store.
@@ -91,6 +102,7 @@ void ExpectDefaultActiveState(const FakeSeedStore& seed_store) {
EXPECT_EQ(kTestSessionConsistencyCountry,
seed_store.session_consistency_country());
EXPECT_EQ(base::Time::UnixEpoch(), seed_store.date());
+ EXPECT_EQ(GetTestFetchTime(), seed_store.fetch_time());
}
} // namespace
@@ -108,7 +120,7 @@ TEST_F(SafeSeedManagerTest, RecordSuccessfulFetch_FirstCallSavesSafeSeed) {
SafeSeedManager safe_seed_manager(true, &prefs_);
SetDefaultActiveState(&safe_seed_manager);
- FakeSeedStore seed_store;
+ FakeSeedStore seed_store(&prefs_);
safe_seed_manager.RecordSuccessfulFetch(&seed_store);
ExpectDefaultActiveState(seed_store);
@@ -118,7 +130,7 @@ TEST_F(SafeSeedManagerTest, RecordSuccessfulFetch_RepeatedCallsRetainSafeSeed) {
SafeSeedManager safe_seed_manager(true, &prefs_);
SetDefaultActiveState(&safe_seed_manager);
- FakeSeedStore seed_store;
+ FakeSeedStore seed_store(&prefs_);
safe_seed_manager.RecordSuccessfulFetch(&seed_store);
safe_seed_manager.RecordSuccessfulFetch(&seed_store);
safe_seed_manager.RecordSuccessfulFetch(&seed_store);
@@ -131,7 +143,7 @@ TEST_F(SafeSeedManagerTest,
SafeSeedManager safe_seed_manager(true, &prefs_);
// Omit setting any active state.
- FakeSeedStore seed_store;
+ FakeSeedStore seed_store(&prefs_);
safe_seed_manager.RecordSuccessfulFetch(&seed_store);
EXPECT_EQ(std::string(), seed_store.seed_data());
@@ -140,6 +152,118 @@ TEST_F(SafeSeedManagerTest,
EXPECT_EQ(std::string(), seed_store.permanent_consistency_country());
EXPECT_EQ(std::string(), seed_store.session_consistency_country());
EXPECT_EQ(base::Time(), seed_store.date());
+ EXPECT_EQ(base::Time(), seed_store.fetch_time());
+}
+
+TEST_F(SafeSeedManagerTest, StreakMetrics_NoPrefs) {
+ base::HistogramTester histogram_tester;
+ SafeSeedManager safe_seed_manager(true, &prefs_);
+ histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 0,
+ 1);
+ histogram_tester.ExpectUniqueSample(
+ "Variations.SafeMode.Streak.FetchFailures", 0, 1);
+}
+
+TEST_F(SafeSeedManagerTest, StreakMetrics_NoCrashes_NoFetchFailures) {
+ prefs_.SetInteger(prefs::kVariationsCrashStreak, 0);
+ prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 0);
+
+ base::HistogramTester histogram_tester;
+ SafeSeedManager safe_seed_manager(true, &prefs_);
+ histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 0,
+ 1);
+ histogram_tester.ExpectUniqueSample(
+ "Variations.SafeMode.Streak.FetchFailures", 0, 1);
+}
+
+TEST_F(SafeSeedManagerTest, StreakMetrics_SomeCrashes_SomeFetchFailures) {
+ prefs_.SetInteger(prefs::kVariationsCrashStreak, 1);
+ prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 2);
+
+ base::HistogramTester histogram_tester;
+ SafeSeedManager safe_seed_manager(true, &prefs_);
+ histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 1,
+ 1);
+ 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);
+ prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 100);
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ ::switches::kForceFieldTrials, "SomeFieldTrial");
+
+ SafeSeedManager safe_seed_manager(true, &prefs_);
+ EXPECT_FALSE(safe_seed_manager.ShouldRunInSafeMode());
+}
+
+TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_NoCrashes_NoFetchFailures) {
+ prefs_.SetInteger(prefs::kVariationsCrashStreak, 0);
+ prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 0);
+
+ SafeSeedManager safe_seed_manager(true, &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_);
+ EXPECT_FALSE(safe_seed_manager.ShouldRunInSafeMode());
+}
+
+TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_FewCrashes_FewFetchFailures) {
+ prefs_.SetInteger(prefs::kVariationsCrashStreak, 2);
+ prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 2);
+
+ SafeSeedManager safe_seed_manager(true, &prefs_);
+ EXPECT_FALSE(safe_seed_manager.ShouldRunInSafeMode());
+}
+
+TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_ManyCrashes_NoFetchFailures) {
+ prefs_.SetInteger(prefs::kVariationsCrashStreak, 3);
+ prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 0);
+
+ SafeSeedManager safe_seed_manager(true, &prefs_);
+ EXPECT_TRUE(safe_seed_manager.ShouldRunInSafeMode());
+}
+
+TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_NoCrashes_ManyFetchFailures) {
+ prefs_.SetInteger(prefs::kVariationsCrashStreak, 0);
+ prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 50);
+
+ SafeSeedManager safe_seed_manager(true, &prefs_);
+ EXPECT_TRUE(safe_seed_manager.ShouldRunInSafeMode());
+}
+
+TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_ManyCrashes_ManyFetchFailures) {
+ prefs_.SetInteger(prefs::kVariationsCrashStreak, 3);
+ prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 50);
+
+ SafeSeedManager safe_seed_manager(true, &prefs_);
+ EXPECT_TRUE(safe_seed_manager.ShouldRunInSafeMode());
}
} // 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 0962bf1e7fa..c7845c22aae 100644
--- a/chromium/components/variations/service/variations_field_trial_creator.cc
+++ b/chromium/components/variations/service/variations_field_trial_creator.cc
@@ -6,8 +6,11 @@
#include <stddef.h>
#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <memory>
+#include <set>
#include <utility>
#include <vector>
@@ -16,6 +19,7 @@
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
+#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
#include "base/trace_event/trace_event.h"
#include "base/version.h"
@@ -33,6 +37,7 @@
#include "ui/base/device_form_factor.h"
namespace variations {
+namespace {
// Maximum age permitted for a variations seed, in days.
const int kMaxVariationsSeedAgeDays = 30;
@@ -76,15 +81,6 @@ Study::FormFactor GetCurrentFormFactor() {
return Study::DESKTOP;
}
-// Gets the hardware class and returns it as a string. This returns an empty
-// string if the client is not ChromeOS.
-std::string GetHardwareClass() {
-#if defined(OS_CHROMEOS)
- return base::SysInfo::GetLsbReleaseBoard();
-#endif // OS_CHROMEOS
- return std::string();
-}
-
// Returns the date that should be used by the VariationsSeedProcessor to do
// expiry and start date checks.
base::Time GetReferenceDateForExpiryChecks(PrefService* local_state) {
@@ -99,11 +95,25 @@ base::Time GetReferenceDateForExpiryChecks(PrefService* local_state) {
}
// Wrapper around channel checking, used to enable channel mocking for
-// testing. If the current browser channel is not UNKNOWN, this will return
-// that channel value. Otherwise, if the fake channel flag is provided, this
-// will return the fake channel. Failing that, this will return the UNKNOWN
-// channel.
+// testing. If a fake channel flag is provided, it will take precedence.
+// Otherwise, this will return the current browser channel (which could be
+// UNKNOWN).
Study::Channel GetChannelForVariations(version_info::Channel product_channel) {
+ const std::string forced_channel =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kFakeVariationsChannel);
+ if (!forced_channel.empty()) {
+ if (forced_channel == "stable")
+ return Study::STABLE;
+ if (forced_channel == "beta")
+ return Study::BETA;
+ if (forced_channel == "dev")
+ return Study::DEV;
+ if (forced_channel == "canary")
+ return Study::CANARY;
+ DVLOG(1) << "Invalid channel provided: " << forced_channel;
+ }
+
switch (product_channel) {
case version_info::Channel::CANARY:
return Study::CANARY;
@@ -114,20 +124,9 @@ Study::Channel GetChannelForVariations(version_info::Channel product_channel) {
case version_info::Channel::STABLE:
return Study::STABLE;
case version_info::Channel::UNKNOWN:
- break;
+ return Study::UNKNOWN;
}
- const std::string forced_channel =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kFakeVariationsChannel);
- if (forced_channel == "stable")
- return Study::STABLE;
- if (forced_channel == "beta")
- return Study::BETA;
- if (forced_channel == "dev")
- return Study::DEV;
- if (forced_channel == "canary")
- return Study::CANARY;
- DVLOG(1) << "Invalid channel provided: " << forced_channel;
+ NOTREACHED();
return Study::UNKNOWN;
}
@@ -138,6 +137,22 @@ void RecordCreateTrialsSeedExpiry(VariationsSeedExpiry expiry_check_result) {
VARIATIONS_SEED_EXPIRY_ENUM_SIZE);
}
+// Records the loaded seed's age to an UMA histogram.
+void RecordSeedFreshness(base::TimeDelta seed_age) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Variations.SeedFreshness", seed_age.InMinutes(),
+ 1, base::TimeDelta::FromDays(30).InMinutes(), 50);
+}
+
+// If an invalid command-line to force field trials was specified, exit the
+// browser with a helpful error message, so that the user can correct their
+// mistake.
+void ExitWithMessage(const std::string& message) {
+ puts(message.c_str());
+ exit(1);
+}
+
+} // namespace
+
VariationsFieldTrialCreator::VariationsFieldTrialCreator(
PrefService* local_state,
VariationsServiceClient* client,
@@ -179,11 +194,17 @@ bool VariationsFieldTrialCreator::CreateTrialsFromSeed(
GetClientFilterableStateForVersion(current_version);
VariationsSeed seed;
+ bool run_in_safe_mode = safe_seed_manager->ShouldRunInSafeMode() &&
+ LoadSafeSeed(&seed, client_filterable_state.get());
+
std::string seed_data;
std::string base64_seed_signature;
- if (!LoadSeed(&seed, &seed_data, &base64_seed_signature))
+ if (!run_in_safe_mode && !LoadSeed(&seed, &seed_data, &base64_seed_signature))
return false;
+ UMA_HISTOGRAM_BOOLEAN("Variations.SafeMode.FellBackToSafeMode2",
+ run_in_safe_mode);
+
// Note that passing |&ui_string_overrider_| via base::Unretained below is
// safe because the callback is executed synchronously. It is not possible to
// pass UIStringOverrider directly to VariationSeedProcessor as the variations
@@ -195,9 +216,14 @@ bool VariationsFieldTrialCreator::CreateTrialsFromSeed(
low_entropy_provider.get(), feature_list);
// Store into the |safe_seed_manager| the combined server and client data used
- // to create the field trials.
- safe_seed_manager->SetActiveSeedState(seed_data, base64_seed_signature,
- std::move(client_filterable_state));
+ // 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());
+ }
UMA_HISTOGRAM_TIMES("Variations.SeedProcessingTime",
base::TimeTicks::Now() - start_time);
@@ -217,7 +243,7 @@ VariationsFieldTrialCreator::GetClientFilterableStateForVersion(
state->platform = (has_platform_override_)
? platform_override_
: ClientFilterableState::GetCurrentPlatform();
- state->hardware_class = GetHardwareClass();
+ state->hardware_class = GetShortHardwareClass();
#if defined(OS_ANDROID)
// This is set on Android only currently, because the IsLowEndDevice() API
// on other platforms has no intrinsic meaning outside of a field trial that
@@ -316,30 +342,39 @@ void VariationsFieldTrialCreator::StorePermanentCountry(
new_list_value);
}
-void VariationsFieldTrialCreator::RecordLastFetchTime() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- local_state()->SetTime(prefs::kVariationsLastFetchTime, base::Time::Now());
-}
-
void VariationsFieldTrialCreator::OverrideVariationsPlatform(
Study::Platform platform_override) {
has_platform_override_ = true;
platform_override_ = platform_override;
}
+// static
+std::string VariationsFieldTrialCreator::GetShortHardwareClass() {
+#if defined(OS_CHROMEOS)
+ std::string board = base::SysInfo::GetLsbReleaseBoard();
+ // GetLsbReleaseBoard() may be suffixed with a "-signed-" and other extra
+ // info. Strip it.
+ const size_t index = board.find("-signed-");
+ if (index != std::string::npos)
+ board.resize(index);
+
+ return base::ToLowerASCII(board);
+#else
+ return std::string();
+#endif // OS_CHROMEOS
+}
+
bool VariationsFieldTrialCreator::LoadSeed(VariationsSeed* seed,
std::string* seed_data,
std::string* base64_signature) {
- if (!LoadSeedFromStore(seed, seed_data, base64_signature))
+ if (!GetSeedStore()->LoadSeed(seed, seed_data, base64_signature))
return false;
- const base::Time last_fetch_time =
- local_state()->GetTime(prefs::kVariationsLastFetchTime);
+ const base::Time last_fetch_time = seed_store_.GetLastFetchTime();
if (last_fetch_time.is_null()) {
// If the last fetch time is missing and we have a seed, then this must be
// the first run of Chrome. Store the current time as the last fetch time.
- RecordLastFetchTime();
+ seed_store_.RecordLastFetchTime();
RecordCreateTrialsSeedExpiry(VARIATIONS_SEED_EXPIRY_FETCH_TIME_MISSING);
return true;
}
@@ -353,16 +388,25 @@ bool VariationsFieldTrialCreator::LoadSeed(VariationsSeed* seed,
// Record that a suitably fresh seed was loaded.
RecordCreateTrialsSeedExpiry(VARIATIONS_SEED_EXPIRY_NOT_EXPIRED);
- UMA_HISTOGRAM_CUSTOM_COUNTS("Variations.SeedFreshness", seed_age.InMinutes(),
- 1, base::TimeDelta::FromDays(30).InMinutes(), 50);
+ RecordSeedFreshness(seed_age);
return true;
}
-bool VariationsFieldTrialCreator::LoadSeedFromStore(
+bool VariationsFieldTrialCreator::LoadSafeSeed(
VariationsSeed* seed,
- std::string* seed_data,
- std::string* base64_signature) {
- return seed_store_.LoadSeed(seed, seed_data, base64_signature);
+ ClientFilterableState* client_state) {
+ base::Time safe_seed_fetch_time;
+ if (!GetSeedStore()->LoadSafeSeed(seed, client_state, &safe_seed_fetch_time))
+ return false;
+
+ // Record the safe seed's age. Note, however, that the safe seed fetch time
+ // pref was added about a milestone later than most of the other safe seed
+ // prefs, so it might be absent. If it's absent, don't attempt to guess what
+ // value to record; just skip recording the metric.
+ if (!safe_seed_fetch_time.is_null())
+ RecordSeedFreshness(base::Time::Now() - safe_seed_fetch_time);
+
+ return true;
}
bool VariationsFieldTrialCreator::SetupFieldTrials(
@@ -370,10 +414,10 @@ bool VariationsFieldTrialCreator::SetupFieldTrials(
const char* kEnableFeatures,
const char* kDisableFeatures,
const std::set<std::string>& unforceable_field_trials,
+ const std::vector<std::string>& variation_ids,
std::unique_ptr<const base::FieldTrial::EntropyProvider>
low_entropy_provider,
std::unique_ptr<base::FeatureList> feature_list,
- std::vector<std::string>* variation_ids,
PlatformFieldTrials* platform_field_trials,
SafeSeedManager* safe_seed_manager) {
const base::CommandLine* command_line =
@@ -386,8 +430,10 @@ bool VariationsFieldTrialCreator::SetupFieldTrials(
if (command_line->HasSwitch(switches::kForceFieldTrialParams)) {
bool result = AssociateParamsFromString(
command_line->GetSwitchValueASCII(switches::kForceFieldTrialParams));
- CHECK(result) << "Invalid --" << switches::kForceFieldTrialParams
- << " list specified.";
+ if (!result) {
+ ExitWithMessage(base::StringPrintf("Invalid --%s list specified.",
+ switches::kForceFieldTrialParams));
+ }
}
// Ensure any field trials specified on the command line are initialized.
@@ -397,19 +443,32 @@ bool VariationsFieldTrialCreator::SetupFieldTrials(
bool result = base::FieldTrialList::CreateTrialsFromString(
command_line->GetSwitchValueASCII(::switches::kForceFieldTrials),
unforceable_field_trials);
- CHECK(result) << "Invalid --" << ::switches::kForceFieldTrials
- << " list specified.";
+ if (!result) {
+ ExitWithMessage(base::StringPrintf("Invalid --%s list specified.",
+ ::switches::kForceFieldTrials));
+ }
}
VariationsHttpHeaderProvider* http_header_provider =
VariationsHttpHeaderProvider::GetInstance();
// Force the variation ids selected in chrome://flags and/or specified using
// the command-line flag.
- bool result = http_header_provider->ForceVariationIds(
- command_line->GetSwitchValueASCII(switches::kForceVariationIds),
- variation_ids);
- CHECK(result) << "Invalid list of variation ids specified (either in --"
- << switches::kForceVariationIds << " or in chrome://flags)";
+ auto result = http_header_provider->ForceVariationIds(
+ variation_ids,
+ command_line->GetSwitchValueASCII(switches::kForceVariationIds));
+ switch (result) {
+ case VariationsHttpHeaderProvider::ForceIdsResult::INVALID_SWITCH_ENTRY:
+ ExitWithMessage(base::StringPrintf("Invalid --%s list specified.",
+ switches::kForceVariationIds));
+ break;
+ case VariationsHttpHeaderProvider::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 VariationsHttpHeaderProvider::ForceIdsResult::SUCCESS:
+ break;
+ }
feature_list->InitializeFromCommandLine(
command_line->GetSwitchValueASCII(kEnableFeatures),
@@ -437,4 +496,8 @@ bool VariationsFieldTrialCreator::SetupFieldTrials(
return has_seed;
}
+VariationsSeedStore* VariationsFieldTrialCreator::GetSeedStore() {
+ return &seed_store_;
+}
+
} // namespace variations
diff --git a/chromium/components/variations/service/variations_field_trial_creator.h b/chromium/components/variations/service/variations_field_trial_creator.h
index 5cf2b624544..7043454b937 100644
--- a/chromium/components/variations/service/variations_field_trial_creator.h
+++ b/chromium/components/variations/service/variations_field_trial_creator.h
@@ -2,10 +2,13 @@
// 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_CREATOR_H_
-#define COMPONENTS_VARIATIONS_FIELD_TRIAL_CREATOR_H_
+#ifndef COMPONENTS_VARIATIONS_SERVICE_VARIATIONS_FIELD_TRIAL_CREATOR_H_
+#define COMPONENTS_VARIATIONS_SERVICE_VARIATIONS_FIELD_TRIAL_CREATOR_H_
+#include <memory>
+#include <set>
#include <string>
+#include <vector>
#include "base/compiler_specific.h"
#include "base/macros.h"
@@ -42,10 +45,10 @@ class VariationsFieldTrialCreator {
// feature controlling flags not directly accesible from variations.
// |unforcable_field_trials| contains the list of trials that can not be
// overridden.
- // |low_entropy_provider| allows for field trial randomization.
- // |feature_list| contains the list of all active features for this client.
// |variation_ids| allows for forcing ids selected in chrome://flags and/or
// specified using the command-line flag.
+ // |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
// for Chrome.
// |safe_seed_manager| should be notified of the combined server and client
@@ -55,10 +58,10 @@ class VariationsFieldTrialCreator {
const char* kEnableFeatures,
const char* kDisableFeatures,
const std::set<std::string>& unforceable_field_trials,
+ const std::vector<std::string>& variation_ids,
std::unique_ptr<const base::FieldTrial::EntropyProvider>
low_entropy_provider,
std::unique_ptr<base::FeatureList> feature_list,
- std::vector<std::string>* variation_ids,
PlatformFieldTrials* platform_field_trials,
SafeSeedManager* safe_seed_manager);
@@ -87,6 +90,11 @@ class VariationsFieldTrialCreator {
// overridden.
void OverrideVariationsPlatform(Study::Platform platform_override);
+ // Returns the short hardware class value used to evaluate variations hardware
+ // class filters. Only implemented on CrOS - returns empty string on other
+ // platforms.
+ static std::string GetShortHardwareClass();
+
private:
// Loads the seed from the variations store into |seed|, and records metrics
// about the loaded seed. Returns true on success, in which case |seed| will
@@ -94,15 +102,13 @@ class VariationsFieldTrialCreator {
// contain the raw pref values.
bool LoadSeed(VariationsSeed* seed,
std::string* seed_data,
- std::string* base64_signature);
+ std::string* base64_signature) WARN_UNUSED_RESULT;
- // Loads the seed from the variations store into |seed|. Returns true on
- // success, in which case |seed| will contain the loaded data, and |seed_data|
- // and |base64_signature| will contain the raw pref values. Virtual for
- // testing.
- virtual bool LoadSeedFromStore(VariationsSeed* seed,
- std::string* seed_data,
- std::string* base64_signature);
+ // Loads the safe seed from the variations store into |seed| and updates any
+ // relevant fields in |client_state|. If the load succeeds, records metrics
+ // about the loaded seed. Returns whether the load succeeded.
+ bool LoadSafeSeed(VariationsSeed* seed,
+ ClientFilterableState* client_state) WARN_UNUSED_RESULT;
// Creates field trials based on the variations seed loaded from local state.
// If there is a problem loading the seed data, all trials specified by the
@@ -117,6 +123,9 @@ class VariationsFieldTrialCreator {
base::FeatureList* feature_list,
SafeSeedManager* safe_seed_manager);
+ // Returns the seed store. Virtual for testing.
+ virtual VariationsSeedStore* GetSeedStore();
+
PrefService* local_state() { return seed_store_.local_state(); }
const PrefService* local_state() const { return seed_store_.local_state(); }
@@ -145,4 +154,4 @@ class VariationsFieldTrialCreator {
} // namespace variations
-#endif // COMPONENTS_VARIATIONS_FIELD_TRIAL_CREATOR_H_
+#endif // COMPONENTS_VARIATIONS_SERVICE_VARIATIONS_FIELD_TRIAL_CREATOR_H_
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 560642c1abd..b61078e0ebb 100644
--- a/chromium/components/variations/service/variations_field_trial_creator_unittest.cc
+++ b/chromium/components/variations/service/variations_field_trial_creator_unittest.cc
@@ -9,7 +9,10 @@
#include "base/feature_list.h"
#include "base/macros.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/histogram_tester.h"
#include "base/version.h"
+#include "build/build_config.h"
#include "components/prefs/testing_pref_service.h"
#include "components/variations/platform_field_trials.h"
#include "components/variations/pref_names.h"
@@ -20,14 +23,21 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_ANDROID)
+#include "components/variations/android/variations_seed_bridge.h"
+#endif // OS_ANDROID
+
using testing::_;
+using testing::Ge;
+using testing::Return;
namespace variations {
namespace {
-// Constants used to create the test seed.
+// Constants used to create the test seeds.
const char kTestSeedStudyName[] = "test";
const char kTestSeedExperimentName[] = "abc";
+const char kTestSafeSeedExperimentName[] = "abc.safe";
const int kTestSeedExperimentProbability = 100;
const char kTestSeedSerialNumber[] = "123";
@@ -37,8 +47,7 @@ const char kTestSeedSignature[] = "a totally valid signature, I swear!";
// 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. |seed|'s study field will be cleared before adding
-// the new study.
+// probability weight 100.
VariationsSeed CreateTestSeed() {
VariationsSeed seed;
Study* study = seed.add_study();
@@ -51,6 +60,51 @@ VariationsSeed CreateTestSeed() {
return seed;
}
+// Returns a seed containing simple test data. The resulting seed will contain
+// one study called "test", which contains one experiment called "abc.safe" with
+// probability weight 100. This is intended to be used whenever a "safe" seed is
+// called for, so that test expectations can distinguish between a "safe" seed
+// and a "latest" seed.
+VariationsSeed CreateTestSafeSeed() {
+ VariationsSeed seed = CreateTestSeed();
+ Study* study = seed.mutable_study(0);
+ study->set_default_experiment_name(kTestSafeSeedExperimentName);
+ study->mutable_experiment(0)->set_name(kTestSafeSeedExperimentName);
+ return seed;
+}
+
+#if defined(OS_ANDROID)
+const char kTestSeedCountry[] = "in";
+
+// Populates |seed| with simple test data, targetting only users in a specific
+// country. The resulting seed will contain one study called "test", which
+// contains one experiment called "abc" with probability weight 100, restricted
+// just to users in |kTestSeedCountry|.
+VariationsSeed CreateTestSeedWithCountryFilter() {
+ VariationsSeed seed = CreateTestSeed();
+ Study* study = seed.mutable_study(0);
+ Study::Filter* filter = study->mutable_filter();
+ filter->add_country(kTestSeedCountry);
+ return seed;
+}
+
+// Serializes |seed| to protobuf binary format.
+std::string SerializeSeed(const VariationsSeed& seed) {
+ std::string serialized_seed;
+ seed.SerializeToString(&serialized_seed);
+ return serialized_seed;
+}
+
+// Returns the |time| formatted as a UTC string.
+std::string ToUTCString(base::Time time) {
+ base::Time::Exploded exploded;
+ time.UTCExplode(&exploded);
+ return base::StringPrintf("%d-%d-%d %d:%d:%d UTC", exploded.year,
+ exploded.month, exploded.day_of_month,
+ exploded.hour, exploded.minute, exploded.second);
+}
+#endif // OS_ANDROID
+
class TestPlatformFieldTrials : public PlatformFieldTrials {
public:
TestPlatformFieldTrials() = default;
@@ -61,6 +115,9 @@ class TestPlatformFieldTrials : public PlatformFieldTrials {
void SetupFeatureControllingFieldTrials(
bool has_seed,
base::FeatureList* feature_list) override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestPlatformFieldTrials);
};
class MockSafeSeedManager : public SafeSeedManager {
@@ -69,17 +126,20 @@ class MockSafeSeedManager : public SafeSeedManager {
: SafeSeedManager(true, local_state) {}
~MockSafeSeedManager() override = default;
- MOCK_METHOD3(DoSetActiveSeedState,
+ MOCK_CONST_METHOD0(ShouldRunInSafeMode, bool());
+ MOCK_METHOD4(DoSetActiveSeedState,
void(const std::string& seed_data,
const std::string& base64_seed_signature,
- ClientFilterableState* client_filterable_state));
+ ClientFilterableState* client_filterable_state,
+ base::Time seed_fetch_time));
void SetActiveSeedState(
const std::string& seed_data,
const std::string& base64_seed_signature,
- std::unique_ptr<ClientFilterableState> client_filterable_state) override {
+ std::unique_ptr<ClientFilterableState> client_filterable_state,
+ base::Time seed_fetch_time) override {
DoSetActiveSeedState(seed_data, base64_seed_signature,
- client_filterable_state.get());
+ client_filterable_state.get(), seed_fetch_time);
}
private:
@@ -123,12 +183,53 @@ class TestVariationsServiceClient : public VariationsServiceClient {
DISALLOW_COPY_AND_ASSIGN(TestVariationsServiceClient);
};
+class TestVariationsSeedStore : public VariationsSeedStore {
+ public:
+ TestVariationsSeedStore(PrefService* local_state)
+ : VariationsSeedStore(local_state), local_state_(local_state) {}
+ ~TestVariationsSeedStore() override = default;
+
+ bool LoadSeed(VariationsSeed* seed,
+ std::string* seed_data,
+ std::string* base64_signature) override {
+ *seed = CreateTestSeed();
+ *seed_data = kTestSeedData;
+ *base64_signature = kTestSeedSignature;
+ return true;
+ }
+
+ bool LoadSafeSeed(VariationsSeed* seed,
+ ClientFilterableState* client_state,
+ base::Time* seed_fetch_time) override {
+ if (has_corrupted_safe_seed_)
+ return false;
+
+ *seed = CreateTestSafeSeed();
+ *seed_fetch_time =
+ local_state_->GetTime(prefs::kVariationsSafeSeedFetchTime);
+ return true;
+ }
+
+ void set_has_corrupted_safe_seed(bool is_corrupted) {
+ has_corrupted_safe_seed_ = is_corrupted;
+ }
+
+ private:
+ // Whether to simulate having a corrupted safe seed.
+ bool has_corrupted_safe_seed_ = false;
+
+ PrefService* local_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestVariationsSeedStore);
+};
+
class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
public:
TestVariationsFieldTrialCreator(PrefService* local_state,
TestVariationsServiceClient* client,
SafeSeedManager* safe_seed_manager)
: VariationsFieldTrialCreator(local_state, client, UIStringOverrider()),
+ seed_store_(local_state),
safe_seed_manager_(safe_seed_manager) {}
~TestVariationsFieldTrialCreator() override = default;
@@ -136,24 +237,19 @@ class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
// A convenience wrapper around SetupFieldTrials() which passes default values
// for uninteresting params.
bool SetupFieldTrials() {
- std::vector<std::string> variation_ids;
TestPlatformFieldTrials platform_field_trials;
return VariationsFieldTrialCreator::SetupFieldTrials(
- "", "", "", std::set<std::string>(), nullptr,
- std::make_unique<base::FeatureList>(), &variation_ids,
- &platform_field_trials, safe_seed_manager_);
+ "", "", "", std::set<std::string>(), std::vector<std::string>(),
+ nullptr, std::make_unique<base::FeatureList>(), &platform_field_trials,
+ safe_seed_manager_);
}
+ TestVariationsSeedStore* seed_store() { return &seed_store_; }
+
private:
- bool LoadSeedFromStore(VariationsSeed* seed,
- std::string* seed_data,
- std::string* base64_signature) override {
- *seed = CreateTestSeed();
- *seed_data = kTestSeedData;
- *base64_signature = kTestSeedSignature;
- return true;
- }
+ VariationsSeedStore* GetSeedStore() override { return &seed_store_; }
+ TestVariationsSeedStore seed_store_;
SafeSeedManager* const safe_seed_manager_;
DISALLOW_COPY_AND_ASSIGN(TestVariationsFieldTrialCreator);
@@ -192,9 +288,14 @@ class FieldTrialCreatorTest : public ::testing::Test {
TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSeed) {
// With a valid seed, the safe seed manager should be informed of the active
// seed state.
+ const base::Time now = base::Time::Now();
+ const base::Time recent_time = now - base::TimeDelta::FromMinutes(17);
testing::NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
- EXPECT_CALL(safe_seed_manager,
- DoSetActiveSeedState(kTestSeedData, kTestSeedSignature, _))
+ ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
+ .WillByDefault(Return(false));
+ EXPECT_CALL(
+ safe_seed_manager,
+ DoSetActiveSeedState(kTestSeedData, kTestSeedSignature, _, recent_time))
.Times(1);
TestVariationsServiceClient variations_service_client;
@@ -202,21 +303,32 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSeed) {
&prefs_, &variations_service_client, &safe_seed_manager);
// Simulate a seed having been stored recently.
- prefs_.SetTime(prefs::kVariationsLastFetchTime, base::Time::Now());
+ prefs_.SetTime(prefs::kVariationsLastFetchTime, recent_time);
// Check that field trials are created from the seed. Since the test study has
// only 1 experiment with 100% probability weight, we must be part of it.
+ base::HistogramTester histogram_tester;
EXPECT_TRUE(field_trial_creator.SetupFieldTrials());
EXPECT_EQ(kTestSeedExperimentName,
base::FieldTrialList::FindFullName(kTestSeedStudyName));
+
+ // Verify metrics.
+ histogram_tester.ExpectUniqueSample("Variations.SeedFreshness", 17, 1);
+ histogram_tester.ExpectUniqueSample("Variations.SafeMode.FellBackToSafeMode2",
+ false, 1);
}
TEST_F(FieldTrialCreatorTest, SetupFieldTrials_NoLastFetchTime) {
// With a valid seed on first run, the safe seed manager should be informed of
- // the active seed state.
+ // the active seed state. The last fetch time in this case is expected to be
+ // inferred to be recent.
testing::NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
+ ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
+ .WillByDefault(Return(false));
+ const base::Time start_time = base::Time::Now();
EXPECT_CALL(safe_seed_manager,
- DoSetActiveSeedState(kTestSeedData, kTestSeedSignature, _))
+ DoSetActiveSeedState(kTestSeedData, kTestSeedSignature, _,
+ Ge(start_time)))
.Times(1);
TestVariationsServiceClient variations_service_client;
@@ -228,16 +340,25 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_NoLastFetchTime) {
// Check that field trials are created from the seed. Since the test study has
// only 1 experiment with 100% probability weight, we must be part of it.
+ base::HistogramTester histogram_tester;
EXPECT_TRUE(field_trial_creator.SetupFieldTrials());
EXPECT_EQ(base::FieldTrialList::FindFullName(kTestSeedStudyName),
kTestSeedExperimentName);
+
+ // Verify metrics. The seed freshness metric should not be recorded on first
+ // run.
+ histogram_tester.ExpectTotalCount("Variations.SeedFreshness", 0);
+ histogram_tester.ExpectUniqueSample("Variations.SafeMode.FellBackToSafeMode2",
+ false, 1);
}
TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ExpiredSeed) {
// With an expired seed, there should be no field trials created, and hence no
// active state should be passed to the safe seed manager.
testing::NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
- EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _)).Times(0);
+ ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
+ .WillByDefault(Return(false));
+ EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _)).Times(0);
TestVariationsServiceClient variations_service_client;
TestVariationsFieldTrialCreator field_trial_creator(
@@ -249,8 +370,122 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ExpiredSeed) {
prefs_.SetTime(prefs::kVariationsLastFetchTime, seed_date);
// Check that field trials are not created from the expired seed.
+ base::HistogramTester histogram_tester;
EXPECT_FALSE(field_trial_creator.SetupFieldTrials());
EXPECT_TRUE(base::FieldTrialList::FindFullName(kTestSeedStudyName).empty());
+
+ // Verify metrics. The seed freshness metric should not be recorded for an
+ // expired seed.
+ histogram_tester.ExpectTotalCount("Variations.SeedFreshness", 0);
+ histogram_tester.ExpectTotalCount("Variations.SafeMode.FellBackToSafeMode2",
+ 0);
+}
+
+TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSafeSeed) {
+ // With a valid safe seed, the safe seed manager should *not* be informed of
+ // the active seed state. This is an optimization to avoid saving a safe seed
+ // when already running in safe mode.
+ testing::NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
+ ON_CALL(safe_seed_manager, ShouldRunInSafeMode()).WillByDefault(Return(true));
+ EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _)).Times(0);
+
+ const base::Time now = base::Time::Now();
+ const base::Time earlier = now - base::TimeDelta::FromMinutes(17);
+ TestVariationsServiceClient variations_service_client;
+ TestVariationsFieldTrialCreator field_trial_creator(
+ &prefs_, &variations_service_client, &safe_seed_manager);
+ prefs_.SetTime(prefs::kVariationsLastFetchTime, now);
+ prefs_.SetTime(prefs::kVariationsSafeSeedFetchTime, earlier);
+
+ // Check that field trials are created from the safe seed. Since the test
+ // study has only 1 experiment with 100% probability weight, we must be part
+ // of it.
+ base::HistogramTester histogram_tester;
+ EXPECT_TRUE(field_trial_creator.SetupFieldTrials());
+ EXPECT_EQ(kTestSafeSeedExperimentName,
+ base::FieldTrialList::FindFullName(kTestSeedStudyName));
+
+ // Verify metrics.
+ histogram_tester.ExpectUniqueSample("Variations.SeedFreshness", 17, 1);
+ histogram_tester.ExpectUniqueSample("Variations.SafeMode.FellBackToSafeMode2",
+ true, 1);
+}
+
+TEST_F(FieldTrialCreatorTest,
+ SetupFieldTrials_CorruptedSafeSeed_FallsBackToLatestSeed) {
+ // With a corrupted safe seed, the field trial creator should fall back to the
+ // latest seed. Hence, the safe seed manager *should* be informed of the
+ // active seed state.
+ const base::Time now = base::Time::Now();
+ const base::Time recent_time = now - base::TimeDelta::FromMinutes(17);
+ testing::NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
+ ON_CALL(safe_seed_manager, ShouldRunInSafeMode()).WillByDefault(Return(true));
+ EXPECT_CALL(
+ safe_seed_manager,
+ DoSetActiveSeedState(kTestSeedData, kTestSeedSignature, _, recent_time))
+ .Times(1);
+
+ TestVariationsServiceClient variations_service_client;
+ TestVariationsFieldTrialCreator field_trial_creator(
+ &prefs_, &variations_service_client, &safe_seed_manager);
+ field_trial_creator.seed_store()->set_has_corrupted_safe_seed(true);
+ prefs_.SetTime(prefs::kVariationsLastFetchTime, recent_time);
+ prefs_.SetTime(prefs::kVariationsSafeSeedFetchTime,
+ now - base::TimeDelta::FromDays(4));
+
+ // Check that field trials are created from the latest seed. Since the test
+ // study has only 1 experiment with 100% probability weight, we must be part
+ // of it.
+ base::HistogramTester histogram_tester;
+ EXPECT_TRUE(field_trial_creator.SetupFieldTrials());
+ EXPECT_EQ(kTestSeedExperimentName,
+ base::FieldTrialList::FindFullName(kTestSeedStudyName));
+
+ // Verify metrics.
+ histogram_tester.ExpectUniqueSample("Variations.SeedFreshness", 17, 1);
+ histogram_tester.ExpectUniqueSample("Variations.SafeMode.FellBackToSafeMode2",
+ false, 1);
+}
+
+#if defined(OS_ANDROID)
+// This is a regression test for https://crbug.com/829527
+TEST_F(FieldTrialCreatorTest, SetupFieldTrials_LoadsCountryOnFirstRun) {
+ // Simulate having received a seed in Java during First Run.
+ const base::Time one_day_ago =
+ base::Time::Now() - base::TimeDelta::FromDays(1);
+ const std::string test_seed_data =
+ SerializeSeed(CreateTestSeedWithCountryFilter());
+ const std::string test_seed_signature = kTestSeedSignature;
+ const std::string test_seed_country = kTestSeedCountry;
+ const std::string test_response_date = ToUTCString(one_day_ago);
+ const bool test_is_gzip_compressed = false;
+ android::SetJavaFirstRunPrefsForTesting(test_seed_data, test_seed_signature,
+ test_seed_country, test_response_date,
+ test_is_gzip_compressed);
+
+ TestVariationsServiceClient variations_service_client;
+ TestPlatformFieldTrials platform_field_trials;
+ testing::NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
+ ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
+ .WillByDefault(Return(false));
+
+ // Note: Unlike other tests, this test does not mock out the seed store, since
+ // the interaction between these two classes is what's being tested.
+ VariationsFieldTrialCreator field_trial_creator(
+ &prefs_, &variations_service_client, UIStringOverrider());
+
+ // 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 the
+ // First Run prefs included the country code for India, this study should be
+ // active.
+ EXPECT_TRUE(field_trial_creator.SetupFieldTrials(
+ "", "", "", std::set<std::string>(), std::vector<std::string>(), nullptr,
+ std::make_unique<base::FeatureList>(), &platform_field_trials,
+ &safe_seed_manager));
+
+ EXPECT_EQ(kTestSeedExperimentName,
+ base::FieldTrialList::FindFullName(kTestSeedStudyName));
}
+#endif // OS_ANDROID
} // namespace variations
diff --git a/chromium/components/variations/service/variations_service.cc b/chromium/components/variations/service/variations_service.cc
index 58dde005f45..8c4ea981e39 100644
--- a/chromium/components/variations/service/variations_service.cc
+++ b/chromium/components/variations/service/variations_service.cc
@@ -22,7 +22,6 @@
#include "base/sys_info.h"
#include "base/task_runner_util.h"
#include "base/task_scheduler/post_task.h"
-#include "base/threading/sequenced_worker_pool.h"
#include "base/timer/elapsed_timer.h"
#include "base/values.h"
#include "base/version.h"
@@ -256,8 +255,6 @@ VariationsService::VariationsService(
weak_ptr_factory_(this) {
DCHECK(client_.get());
DCHECK(resource_request_allowed_notifier_.get());
-
- resource_request_allowed_notifier_->Init(this);
}
VariationsService::~VariationsService() {
@@ -266,6 +263,8 @@ VariationsService::~VariationsService() {
void VariationsService::PerformPreMainMessageLoopStartup() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ InitResourceRequestedAllowedNotifier();
+
if (!IsFetchingEnabled())
return;
@@ -377,7 +376,6 @@ void VariationsService::RegisterPrefs(PrefRegistrySimple* registry) {
SafeSeedManager::RegisterPrefs(registry);
VariationsSeedStore::RegisterPrefs(registry);
- registry->RegisterTimePref(prefs::kVariationsLastFetchTime, base::Time());
// This preference will only be written by the policy service, which will fill
// it according to a value stored in the User Policy.
registry->RegisterStringPref(prefs::kVariationsRestrictParameter,
@@ -418,7 +416,7 @@ void VariationsService::EnableForTesting() {
}
void VariationsService::DoActualFetch() {
- DoFetchFromURL(variations_server_url_);
+ DoFetchFromURL(variations_server_url_, false);
}
bool VariationsService::StoreSeed(const std::string& seed_data,
@@ -453,7 +451,15 @@ VariationsService::CreateLowEntropyProvider() {
return state_manager_->CreateLowEntropyProvider();
}
-bool VariationsService::DoFetchFromURL(const GURL& url) {
+void VariationsService::InitResourceRequestedAllowedNotifier() {
+ // ResourceRequestAllowedNotifier does not install an observer if there is no
+ // NetworkChangeNotifier, which results in never being notified of changes to
+ // network status.
+ DCHECK(net::NetworkChangeNotifier::HasNetworkChangeNotifier());
+ resource_request_allowed_notifier_->Init(this);
+}
+
+bool VariationsService::DoFetchFromURL(const GURL& url, bool is_http_retry) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(IsFetchingEnabled());
@@ -501,9 +507,8 @@ bool VariationsService::DoFetchFromURL(const GURL& url) {
// Tell the server that delta-compressed seeds are supported.
enable_deltas = true;
// Get the seed only if its serial number doesn't match what we have.
- // If the fetch is being done over HTTP, encrypt the If-None-Match header.
- if (!url.SchemeIs(url::kHttpsScheme) &&
- base::FeatureList::IsEnabled(kHttpRetryFeature)) {
+ // If the fetch is an HTTP retry, encrypt the If-None-Match header.
+ if (is_http_retry) {
if (!EncryptString(serial_number, &serial_number)) {
pending_seed_request_.reset();
return false;
@@ -616,7 +621,7 @@ void VariationsService::OnURLFetchComplete(const net::URLFetcher* source) {
if (was_https && !insecure_variations_server_url_.is_empty()) {
// When re-trying via HTTP, return immediately. OnURLFetchComplete() will
// be called with the result of that retry.
- if (DoFetchFromURL(insecure_variations_server_url_))
+ if (DoFetchFromURL(insecure_variations_server_url_, true))
return;
}
// It's common for the very first fetch attempt to fail (e.g. the network
@@ -739,7 +744,7 @@ void VariationsService::PerformSimulationWithVersion(
}
void VariationsService::RecordSuccessfulFetch() {
- field_trial_creator_.RecordLastFetchTime();
+ field_trial_creator_.seed_store()->RecordLastFetchTime();
safe_seed_manager_.RecordSuccessfulFetch(field_trial_creator_.seed_store());
}
@@ -760,14 +765,13 @@ bool VariationsService::SetupFieldTrials(
const char* kEnableFeatures,
const char* kDisableFeatures,
const std::set<std::string>& unforceable_field_trials,
+ const std::vector<std::string>& variation_ids,
std::unique_ptr<base::FeatureList> feature_list,
- std::vector<std::string>* variation_ids,
variations::PlatformFieldTrials* platform_field_trials) {
return field_trial_creator_.SetupFieldTrials(
kEnableGpuBenchmarking, kEnableFeatures, kDisableFeatures,
- unforceable_field_trials, CreateLowEntropyProvider(),
- std::move(feature_list), variation_ids, platform_field_trials,
- &safe_seed_manager_);
+ unforceable_field_trials, variation_ids, CreateLowEntropyProvider(),
+ std::move(feature_list), platform_field_trials, &safe_seed_manager_);
}
std::string VariationsService::GetStoredPermanentCountry() {
diff --git a/chromium/components/variations/service/variations_service.h b/chromium/components/variations/service/variations_service.h
index f3062e5dcd8..15dac3dc639 100644
--- a/chromium/components/variations/service/variations_service.h
+++ b/chromium/components/variations/service/variations_service.h
@@ -6,7 +6,9 @@
#define COMPONENTS_VARIATIONS_SERVICE_VARIATIONS_SERVICE_H_
#include <memory>
+#include <set>
#include <string>
+#include <vector>
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
@@ -163,8 +165,8 @@ class VariationsService
const char* kEnableFeatures,
const char* kDisableFeatures,
const std::set<std::string>& unforceable_field_trials,
+ const std::vector<std::string>& variation_ids,
std::unique_ptr<base::FeatureList> feature_list,
- std::vector<std::string>* variation_ids,
variations::PlatformFieldTrials* platform_field_trials);
protected:
@@ -241,9 +243,12 @@ class VariationsService
LOAD_COUNTRY_MAX,
};
+ void InitResourceRequestedAllowedNotifier();
+
// Attempts a seed fetch from the set |url|. Returns true if the fetch was
- // started successfully, false otherwise.
- bool DoFetchFromURL(const GURL& url);
+ // started successfully, false otherwise. |is_http_retry| should be true if
+ // this is a retry over HTTP, false otherwise.
+ bool DoFetchFromURL(const GURL& url, bool is_http_retry);
// Calls FetchVariationsSeed once and repeats this periodically. See
// implementation for details on the period.
diff --git a/chromium/components/variations/service/variations_service_unittest.cc b/chromium/components/variations/service/variations_service_unittest.cc
index 73211a1dc85..a902e2ca486 100644
--- a/chromium/components/variations/service/variations_service_unittest.cc
+++ b/chromium/components/variations/service/variations_service_unittest.cc
@@ -11,8 +11,6 @@
#include <vector>
#include "base/base64.h"
-#include "base/base_switches.h"
-#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/json/json_string_value_serializer.h"
#include "base/macros.h"
@@ -34,6 +32,7 @@
#include "components/variations/proto/study.pb.h"
#include "components/variations/proto/variations_seed.pb.h"
#include "components/web_resource/resource_request_allowed_notifier_test_util.h"
+#include "net/base/mock_network_change_notifier.h"
#include "net/base/url_util.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
@@ -384,6 +383,7 @@ TEST_F(VariationsServiceTest, VariationsURLHasParams) {
}
TEST_F(VariationsServiceTest, RequestsInitiallyNotAllowed) {
+ net::test::MockNetworkChangeNotifier network_change_notifier;
// Pass ownership to TestVariationsService, but keep a weak pointer to
// manipulate it for this test.
std::unique_ptr<web_resource::TestRequestAllowedNotifier> test_notifier =
@@ -391,6 +391,7 @@ TEST_F(VariationsServiceTest, RequestsInitiallyNotAllowed) {
web_resource::TestRequestAllowedNotifier* raw_notifier = test_notifier.get();
TestVariationsService test_service(std::move(test_notifier), &prefs_,
GetMetricsStateManager(), true);
+ test_service.InitResourceRequestedAllowedNotifier();
// Force the notifier to initially disallow requests.
raw_notifier->SetRequestsAllowedOverride(false);
@@ -746,137 +747,6 @@ TEST_F(VariationsServiceTest, OverrideStoredPermanentCountry) {
}
}
-TEST_F(VariationsServiceTest, SafeMode_NoPrefs) {
- // Create a variations service.
- base::HistogramTester histogram_tester;
- TestVariationsService service(
- std::make_unique<web_resource::TestRequestAllowedNotifier>(&prefs_),
- &prefs_, GetMetricsStateManager(), true);
-
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.FellBackToSafeMode",
- false, 1);
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 0,
- 1);
- histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.Streak.FetchFailures", 0, 1);
-}
-
-TEST_F(VariationsServiceTest, SafeMode_NoCrashes_NoFetchFailures) {
- prefs_.SetInteger(prefs::kVariationsCrashStreak, 0);
- prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 0);
-
- // Create a variations service.
- base::HistogramTester histogram_tester;
- TestVariationsService service(
- std::make_unique<web_resource::TestRequestAllowedNotifier>(&prefs_),
- &prefs_, GetMetricsStateManager(), true);
-
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.FellBackToSafeMode",
- false, 1);
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 0,
- 1);
- histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.Streak.FetchFailures", 0, 1);
-}
-
-TEST_F(VariationsServiceTest, SafeMode_SomeCrashes_SomeFetchFailures) {
- prefs_.SetInteger(prefs::kVariationsCrashStreak, 1);
- prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 2);
-
- // Create a variations service.
- base::HistogramTester histogram_tester;
- TestVariationsService service(
- std::make_unique<web_resource::TestRequestAllowedNotifier>(&prefs_),
- &prefs_, GetMetricsStateManager(), true);
-
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.FellBackToSafeMode",
- false, 1);
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 1,
- 1);
- histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.Streak.FetchFailures", 2, 1);
-}
-
-TEST_F(VariationsServiceTest, SafeMode_NoCrashes_ManyFetchFailures) {
- prefs_.SetInteger(prefs::kVariationsCrashStreak, 0);
- prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 3);
-
- // Create a variations service.
- base::HistogramTester histogram_tester;
- TestVariationsService service(
- std::make_unique<web_resource::TestRequestAllowedNotifier>(&prefs_),
- &prefs_, GetMetricsStateManager(), true);
-
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.FellBackToSafeMode",
- true, 1);
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 0,
- 1);
- histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.Streak.FetchFailures", 3, 1);
-}
-
-TEST_F(VariationsServiceTest, SafeMode_ManyCrashes_NoFetchFailures) {
- prefs_.SetInteger(prefs::kVariationsCrashStreak, 3);
- prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 0);
-
- // Create a variations service.
- base::HistogramTester histogram_tester;
- TestVariationsService service(
- std::make_unique<web_resource::TestRequestAllowedNotifier>(&prefs_),
- &prefs_, GetMetricsStateManager(), true);
-
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.FellBackToSafeMode",
- true, 1);
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 3,
- 1);
- histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.Streak.FetchFailures", 0, 1);
-}
-
-TEST_F(VariationsServiceTest, SafeMode_OverriddenByCommandlineFlag) {
- prefs_.SetInteger(prefs::kVariationsCrashStreak, 3);
- prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 3);
- base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- ::switches::kForceFieldTrials, "SomeFieldTrial");
-
- // Create a variations service.
- base::HistogramTester histogram_tester;
- TestVariationsService service(
- std::make_unique<web_resource::TestRequestAllowedNotifier>(&prefs_),
- &prefs_, GetMetricsStateManager(), true);
-
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.FellBackToSafeMode",
- false, 1);
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 3,
- 1);
- histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.Streak.FetchFailures", 3, 1);
-}
-
-TEST_F(VariationsServiceTest, SafeMode_CrashIncrementsCrashStreak) {
- prefs_.SetInteger(prefs::kVariationsCrashStreak, 1);
- prefs_.SetBoolean(metrics::prefs::kStabilityExitedCleanly, false);
-
- // Create a variations service.
- TestVariationsService service(
- std::make_unique<web_resource::TestRequestAllowedNotifier>(&prefs_),
- &prefs_, GetMetricsStateManager(), true);
-
- EXPECT_EQ(2, prefs_.GetInteger(prefs::kVariationsCrashStreak));
-}
-
-TEST_F(VariationsServiceTest, SafeMode_NoCrashPreservesCrashStreak) {
- prefs_.SetInteger(prefs::kVariationsCrashStreak, 1);
- prefs_.SetBoolean(metrics::prefs::kStabilityExitedCleanly, true);
-
- // Create a variations service.
- TestVariationsService service(
- std::make_unique<web_resource::TestRequestAllowedNotifier>(&prefs_),
- &prefs_, GetMetricsStateManager(), true);
-
- EXPECT_EQ(1, prefs_.GetInteger(prefs::kVariationsCrashStreak));
-}
-
TEST_F(VariationsServiceTest, SafeMode_StartingRequestIncrementsFetchFailures) {
prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 1);
@@ -895,6 +765,8 @@ TEST_F(VariationsServiceTest, SafeMode_SuccessfulFetchClearsFailureStreaks) {
prefs_.SetInteger(prefs::kVariationsCrashStreak, 2);
prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 1);
+ net::test::MockNetworkChangeNotifier network_change_notifier;
+
// Create a variations service and perform a successful fetch.
VariationsService service(
std::make_unique<TestVariationsServiceClient>(),
diff --git a/chromium/components/variations/study_filtering.cc b/chromium/components/variations/study_filtering.cc
index 97d43905d8b..92896580816 100644
--- a/chromium/components/variations/study_filtering.cc
+++ b/chromium/components/variations/study_filtering.cc
@@ -62,31 +62,18 @@ bool CheckStudyHardwareClass(const Study::Filter& filter,
return true;
}
+ // Note: This logic changed in M66. Prior to M66, this used substring
+ // comparison logic to match hardware classes. In M66, it was made consistent
+ // with other filters.
+
// Checks if we are supposed to filter for a specified set of
// hardware_classes. Note that this means this overrides the
// exclude_hardware_class in case that ever occurs (which it shouldn't).
- if (filter.hardware_class_size() > 0) {
- for (int i = 0; i < filter.hardware_class_size(); ++i) {
- // Check if the entry is a substring of |hardware_class|.
- size_t position = hardware_class.find(filter.hardware_class(i));
- if (position != std::string::npos)
- return true;
- }
- // None of the requested hardware_classes match.
- return false;
- }
+ if (filter.hardware_class_size() > 0)
+ return base::ContainsValue(filter.hardware_class(), hardware_class);
- // Omit if matches any of the exclude entries.
- for (int i = 0; i < filter.exclude_hardware_class_size(); ++i) {
- // Check if the entry is a substring of |hardware_class|.
- size_t position = hardware_class.find(
- filter.exclude_hardware_class(i));
- if (position != std::string::npos)
- return false;
- }
-
- // None of the exclusions match, so this accepts.
- return true;
+ // Omit if we match the blacklist.
+ return !base::ContainsValue(filter.exclude_hardware_class(), hardware_class);
}
bool CheckStudyLocale(const Study::Filter& filter, const std::string& locale) {
diff --git a/chromium/components/variations/study_filtering_unittest.cc b/chromium/components/variations/study_filtering_unittest.cc
index acf097ae239..cbaf37e3e11 100644
--- a/chromium/components/variations/study_filtering_unittest.cc
+++ b/chromium/components/variations/study_filtering_unittest.cc
@@ -35,6 +35,11 @@ Study::Experiment* AddExperiment(const std::string& name,
return experiment;
}
+std::vector<std::string> SplitFilterString(const std::string& input) {
+ return base::SplitString(input, ",", base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_ALL);
+}
+
} // namespace
TEST(VariationsStudyFilteringTest, CheckStudyChannel) {
@@ -191,22 +196,16 @@ TEST(VariationsStudyFilteringTest, CheckStudyLocale) {
{"", "fr-CA", true, true, true},
};
- for (size_t i = 0; i < arraysize(test_cases); ++i) {
+ for (const auto& test : test_cases) {
Study::Filter filter;
- for (const std::string& locale : base::SplitString(
- test_cases[i].filter_locales, ",",
- base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL))
+ for (const std::string& locale : SplitFilterString(test.filter_locales))
filter.add_locale(locale);
- for (const std::string& exclude_locale :
- base::SplitString(test_cases[i].exclude_locales, ",",
- base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL))
- filter.add_exclude_locale(exclude_locale);
- EXPECT_EQ(test_cases[i].en_us_result,
- internal::CheckStudyLocale(filter, "en-US"));
- EXPECT_EQ(test_cases[i].en_ca_result,
- internal::CheckStudyLocale(filter, "en-CA"));
- EXPECT_EQ(test_cases[i].fr_result,
- internal::CheckStudyLocale(filter, "fr"));
+ for (const std::string& locale : SplitFilterString(test.exclude_locales))
+ filter.add_exclude_locale(locale);
+
+ EXPECT_EQ(test.en_us_result, internal::CheckStudyLocale(filter, "en-US"));
+ EXPECT_EQ(test.en_ca_result, internal::CheckStudyLocale(filter, "en-CA"));
+ EXPECT_EQ(test.fr_result, internal::CheckStudyLocale(filter, "fr"));
}
}
@@ -412,54 +411,45 @@ TEST(VariationsStudyFilteringTest, CheckStudyHardwareClass) {
const char* actual_hardware_class;
bool expected_result;
} test_cases[] = {
- // Neither filtered nor excluded set:
- // True since empty is always a match.
- {"", "", "fancy INTEL pear device", true},
- {"", "", "", true},
-
- // Filtered set:
- {"apple,pear,orange", "", "apple", true},
- {"apple,pear,orange", "", "fancy INTEL pear device", true},
- {"apple,pear,orange", "", "fancy INTEL GRAPE device", false},
- // Somehow tagged as both, but still valid.
- {"apple,pear,orange", "", "fancy INTEL pear GRAPE device", true},
- // Substring, so still valid.
- {"apple,pear,orange", "", "fancy INTEL SNapple device", true},
- // No issues with doubling.
- {"apple,pear,orange", "", "fancy orange orange device", true},
- // Empty, which is what would happen for non ChromeOS platforms.
- {"apple,pear,orange", "", "", false},
-
- // Excluded set:
- {"", "apple,pear,orange", "apple", false},
- {"", "apple,pear,orange", "fancy INTEL pear device", false},
- {"", "apple,pear,orange", "fancy INTEL GRAPE device", true},
- // Somehow tagged as both. Very excluded!
- {"", "apple,pear,orange", "fancy INTEL pear GRAPE device", false},
- // Substring, so still invalid.
- {"", "apple,pear,orange", "fancy INTEL SNapple device", false},
- // Empty.
- {"", "apple,pear,orange", "", true},
-
- // Not testing when both are set as it should never occur and should be
- // considered undefined.
+ // Neither filtered nor excluded set:
+ // True since empty is always a match.
+ {"", "", "fancy INTEL pear device", true},
+ {"", "", "", true},
+
+ // Filtered set:
+ {"apple,pear,orange", "", "apple", true},
+ {"apple,pear,orange", "", "fancy INTEL pear device", false},
+ {"apple,pear,orange", "", "fancy INTEL GRAPE device", false},
+ // Somehow tagged as both, but still valid.
+ {"apple,pear,orange", "", "fancy INTEL pear GRAPE device", false},
+ // Substring, which should not match.
+ {"apple,pear,orange", "", "fancy INTEL SNapple device", false},
+ // Empty, which is what would happen for non ChromeOS platforms.
+ {"apple,pear,orange", "", "", false},
+
+ // Excluded set:
+ {"", "apple,pear,orange", "apple", false},
+ {"", "apple,pear,orange", "fancy INTEL pear device", true},
+ {"", "apple,pear,orange", "fancy INTEL GRAPE device", true},
+ // Empty.
+ {"", "apple,pear,orange", "", true},
+
+ // Not testing when both are set as it should never occur and should be
+ // considered undefined.
};
- for (size_t i = 0; i < arraysize(test_cases); ++i) {
+ for (const auto& test : test_cases) {
Study::Filter filter;
- for (const std::string& cur : base::SplitString(
- test_cases[i].hardware_class, ",",
- base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL))
- filter.add_hardware_class(cur);
-
- for (const std::string& cur : base::SplitString(
- test_cases[i].exclude_hardware_class, ",",
- base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL))
- filter.add_exclude_hardware_class(cur);
-
- EXPECT_EQ(test_cases[i].expected_result,
- internal::CheckStudyHardwareClass(
- filter, test_cases[i].actual_hardware_class));
+ for (const auto& hw_class : SplitFilterString(test.hardware_class))
+ filter.add_hardware_class(hw_class);
+ for (const auto& hw_class : SplitFilterString(test.exclude_hardware_class))
+ filter.add_exclude_hardware_class(hw_class);
+
+ EXPECT_EQ(test.expected_result, internal::CheckStudyHardwareClass(
+ filter, test.actual_hardware_class))
+ << "hardware_class=" << test.hardware_class << " "
+ << "exclude_hardware_class=" << test.exclude_hardware_class << " "
+ << "actual_hardware_class=" << test.actual_hardware_class;
}
}
@@ -497,14 +487,10 @@ TEST(VariationsStudyFilteringTest, CheckStudyCountry) {
for (const auto& test : test_cases) {
Study::Filter filter;
- for (const std::string& country : base::SplitString(
- test.country, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL))
+ for (const std::string& country : SplitFilterString(test.country))
filter.add_country(country);
-
- for (const std::string& exclude_country : base::SplitString(
- test.exclude_country, ",",
- base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL))
- filter.add_exclude_country(exclude_country);
+ for (const std::string& country : SplitFilterString(test.exclude_country))
+ filter.add_exclude_country(country);
EXPECT_EQ(test.expected_result,
internal::CheckStudyCountry(filter, test.actual_country));
diff --git a/chromium/components/variations/synthetic_trial_registry_unittest.cc b/chromium/components/variations/synthetic_trial_registry_unittest.cc
index 632aa3f95b9..e7ef847cd91 100644
--- a/chromium/components/variations/synthetic_trial_registry_unittest.cc
+++ b/chromium/components/variations/synthetic_trial_registry_unittest.cc
@@ -6,7 +6,7 @@
#include "base/strings/stringprintf.h"
#include "components/variations/active_field_trials.h"
-#include "components/variations/metrics_util.h"
+#include "components/variations/hashing.h"
#include "components/variations/synthetic_trials_active_group_id_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -21,8 +21,8 @@ class SyntheticTrialRegistryTest : public ::testing::Test {
bool HasSyntheticTrial(const std::vector<ActiveGroupId>& synthetic_trials,
const std::string& trial_name,
const std::string& trial_group) {
- uint32_t trial_name_hash = metrics::HashName(trial_name);
- uint32_t trial_group_hash = metrics::HashName(trial_group);
+ uint32_t trial_name_hash = HashName(trial_name);
+ uint32_t trial_group_hash = HashName(trial_group);
for (const ActiveGroupId& trial : synthetic_trials) {
if (trial.name == trial_name_hash && trial.group == trial_group_hash)
return true;
@@ -45,12 +45,10 @@ TEST_F(SyntheticTrialRegistryTest, RegisterSyntheticTrial) {
SyntheticTrialRegistry registry;
// Add two synthetic trials and confirm that they show up in the list.
- SyntheticTrialGroup trial1(metrics::HashName("TestTrial1"),
- metrics::HashName("Group1"));
+ SyntheticTrialGroup trial1(HashName("TestTrial1"), HashName("Group1"));
registry.RegisterSyntheticFieldTrial(trial1);
- SyntheticTrialGroup trial2(metrics::HashName("TestTrial2"),
- metrics::HashName("Group2"));
+ SyntheticTrialGroup trial2(HashName("TestTrial2"), HashName("Group2"));
registry.RegisterSyntheticFieldTrial(trial2);
// Ensure that time has advanced by at least a tick before proceeding.
WaitUntilTimeChanges(base::TimeTicks::Now());
@@ -71,16 +69,14 @@ TEST_F(SyntheticTrialRegistryTest, RegisterSyntheticTrial) {
WaitUntilTimeChanges(begin_log_time);
// Change the group for the first trial after the log started.
- SyntheticTrialGroup trial3(metrics::HashName("TestTrial1"),
- metrics::HashName("Group2"));
+ SyntheticTrialGroup trial3(HashName("TestTrial1"), HashName("Group2"));
registry.RegisterSyntheticFieldTrial(trial3);
registry.GetSyntheticFieldTrialsOlderThan(begin_log_time, &synthetic_trials);
EXPECT_EQ(1U, synthetic_trials.size());
EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
// Add a new trial after the log started and confirm that it doesn't show up.
- SyntheticTrialGroup trial4(metrics::HashName("TestTrial3"),
- metrics::HashName("Group3"));
+ SyntheticTrialGroup trial4(HashName("TestTrial3"), HashName("Group3"));
registry.RegisterSyntheticFieldTrial(trial4);
registry.GetSyntheticFieldTrialsOlderThan(begin_log_time, &synthetic_trials);
EXPECT_EQ(1U, synthetic_trials.size());
@@ -102,9 +98,8 @@ TEST_F(SyntheticTrialRegistryTest, RegisterSyntheticMultiGroupFieldTrial) {
SyntheticTrialRegistry registry;
// Register a synthetic trial TestTrial1 with groups A and B.
- uint32_t trial_name_hash = metrics::HashName("TestTrial1");
- std::vector<uint32_t> group_name_hashes = {metrics::HashName("A"),
- metrics::HashName("B")};
+ uint32_t trial_name_hash = HashName("TestTrial1");
+ std::vector<uint32_t> group_name_hashes = {HashName("A"), HashName("B")};
registry.RegisterSyntheticMultiGroupFieldTrial(trial_name_hash,
group_name_hashes);
// Ensure that time has advanced by at least a tick before proceeding.
@@ -118,7 +113,7 @@ TEST_F(SyntheticTrialRegistryTest, RegisterSyntheticMultiGroupFieldTrial) {
EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "B"));
// Change the group for the trial to a single group.
- group_name_hashes = {metrics::HashName("X")};
+ group_name_hashes = {HashName("X")};
registry.RegisterSyntheticMultiGroupFieldTrial(trial_name_hash,
group_name_hashes);
// Ensure that time has advanced by at least a tick before proceeding.
@@ -149,12 +144,10 @@ TEST_F(SyntheticTrialRegistryTest, GetSyntheticFieldTrialActiveGroups) {
SyntheticTrialsActiveGroupIdProvider::GetInstance());
// Add two synthetic trials and confirm that they show up in the list.
- SyntheticTrialGroup trial1(metrics::HashName("TestTrial1"),
- metrics::HashName("Group1"));
+ SyntheticTrialGroup trial1(HashName("TestTrial1"), HashName("Group1"));
registry.RegisterSyntheticFieldTrial(trial1);
- SyntheticTrialGroup trial2(metrics::HashName("TestTrial2"),
- metrics::HashName("Group2"));
+ SyntheticTrialGroup trial2(HashName("TestTrial2"), HashName("Group2"));
registry.RegisterSyntheticFieldTrial(trial2);
// Ensure that time has advanced by at least a tick before proceeding.
diff --git a/chromium/components/variations/variations_http_header_provider.cc b/chromium/components/variations/variations_http_header_provider.cc
index e23f5581a14..a473a40e288 100644
--- a/chromium/components/variations/variations_http_header_provider.cc
+++ b/chromium/components/variations/variations_http_header_provider.cc
@@ -61,49 +61,23 @@ std::string VariationsHttpHeaderProvider::GetVariationsString() {
return ids_string;
}
-bool VariationsHttpHeaderProvider::ForceVariationIds(
- const std::string& command_line_variation_ids,
- std::vector<std::string>* variation_ids) {
+VariationsHttpHeaderProvider::ForceIdsResult
+VariationsHttpHeaderProvider::ForceVariationIds(
+ const std::vector<std::string>& variation_ids,
+ const std::string& command_line_variation_ids) {
+ default_variation_ids_set_.clear();
+
+ if (!AddDefaultVariationIds(variation_ids))
+ return ForceIdsResult::INVALID_VECTOR_ENTRY;
+
if (!command_line_variation_ids.empty()) {
- // Combine |variation_ids| with |command_line_variation_ids|.
- std::vector<std::string> variation_ids_flags =
+ std::vector<std::string> variation_ids_from_command_line =
base::SplitString(command_line_variation_ids, ",",
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- variation_ids->insert(variation_ids->end(), variation_ids_flags.begin(),
- variation_ids_flags.end());
+ if (!AddDefaultVariationIds(variation_ids_from_command_line))
+ return ForceIdsResult::INVALID_SWITCH_ENTRY;
}
-
- if (!variation_ids->empty()) {
- // Create default variation ids which will always be included in the
- // X-Client-Data request header.
- return SetDefaultVariationIds(*variation_ids);
- }
- return true;
-}
-
-bool VariationsHttpHeaderProvider::SetDefaultVariationIds(
- const std::vector<std::string>& variation_ids) {
- default_variation_ids_set_.clear();
- for (const std::string& entry : variation_ids) {
- if (entry.empty()) {
- default_variation_ids_set_.clear();
- return false;
- }
- bool trigger_id =
- base::StartsWith(entry, "t", base::CompareCase::SENSITIVE);
- // Remove the "t" prefix if it's there.
- std::string trimmed_entry = trigger_id ? entry.substr(1) : entry;
-
- int variation_id = 0;
- if (!base::StringToInt(trimmed_entry, &variation_id)) {
- default_variation_ids_set_.clear();
- return false;
- }
- default_variation_ids_set_.insert(VariationIDEntry(
- variation_id,
- trigger_id ? GOOGLE_WEB_PROPERTIES_TRIGGER : GOOGLE_WEB_PROPERTIES));
- }
- return true;
+ return ForceIdsResult::SUCCESS;
}
void VariationsHttpHeaderProvider::ResetForTesting() {
@@ -260,6 +234,30 @@ std::string VariationsHttpHeaderProvider::GenerateBase64EncodedProto(
return hashed;
}
+bool VariationsHttpHeaderProvider::AddDefaultVariationIds(
+ const std::vector<std::string>& variation_ids) {
+ for (const std::string& entry : variation_ids) {
+ if (entry.empty()) {
+ default_variation_ids_set_.clear();
+ return false;
+ }
+ bool trigger_id =
+ base::StartsWith(entry, "t", base::CompareCase::SENSITIVE);
+ // Remove the "t" prefix if it's there.
+ std::string trimmed_entry = trigger_id ? entry.substr(1) : entry;
+
+ int variation_id = 0;
+ if (!base::StringToInt(trimmed_entry, &variation_id)) {
+ default_variation_ids_set_.clear();
+ return false;
+ }
+ default_variation_ids_set_.insert(VariationIDEntry(
+ variation_id,
+ trigger_id ? GOOGLE_WEB_PROPERTIES_TRIGGER : GOOGLE_WEB_PROPERTIES));
+ }
+ return true;
+}
+
std::set<VariationsHttpHeaderProvider::VariationIDEntry>
VariationsHttpHeaderProvider::GetAllVariationIds() {
lock_.AssertAcquired();
diff --git a/chromium/components/variations/variations_http_header_provider.h b/chromium/components/variations/variations_http_header_provider.h
index 184766d6352..8bf60c29275 100644
--- a/chromium/components/variations/variations_http_header_provider.h
+++ b/chromium/components/variations/variations_http_header_provider.h
@@ -45,19 +45,21 @@ class VariationsHttpHeaderProvider : public base::FieldTrialList::Observer,
// a leading and trailing space, e.g. " 123 234 345 ".
std::string GetVariationsString();
- // Forces the list of |variation_ids| (which will be modified by adding the
- // comma-separated |command_line_variation_ids|). This is a wrapper function
- // around SetDefaultVariationIds.
- bool ForceVariationIds(
- const std::string& command_line_variation_ids,
- std::vector<std::string>* variation_ids);
+ // Result of ForceVariationIds() call.
+ enum class ForceIdsResult {
+ SUCCESS,
+ INVALID_VECTOR_ENTRY, // Invalid entry in |variation_ids|.
+ INVALID_SWITCH_ENTRY, // Invalid entry in |command_line_variation_ids|.
+ };
// Sets *additional* variation ids and trigger variation ids to be encoded in
// the X-Client-Data request header. This is intended for development use to
// force a server side experiment id. |variation_ids| should be a list of
- // strings of numeric experiment ids. If an id is prefixed with "t" it will
- // be treated as a trigger experiment id.
- bool SetDefaultVariationIds(const std::vector<std::string>& variation_ids);
+ // strings of numeric experiment ids. Ids explicitly passed in |variation_ids|
+ // and those in the comma-separated |command_line_variation_ids| are added.
+ ForceIdsResult ForceVariationIds(
+ const std::vector<std::string>& variation_ids,
+ const std::string& command_line_variation_ids);
// Resets any cached state for tests.
void ResetForTesting();
@@ -68,9 +70,11 @@ class VariationsHttpHeaderProvider : public base::FieldTrialList::Observer,
typedef std::pair<VariationID, IDCollectionKey> VariationIDEntry;
FRIEND_TEST_ALL_PREFIXES(VariationsHttpHeaderProviderTest,
- SetDefaultVariationIds_Valid);
+ ForceVariationIds_Valid);
FRIEND_TEST_ALL_PREFIXES(VariationsHttpHeaderProviderTest,
- SetDefaultVariationIds_Invalid);
+ ForceVariationIds_ValidCommandLine);
+ FRIEND_TEST_ALL_PREFIXES(VariationsHttpHeaderProviderTest,
+ ForceVariationIds_Invalid);
FRIEND_TEST_ALL_PREFIXES(VariationsHttpHeaderProviderTest,
OnFieldTrialGroupFinalized);
FRIEND_TEST_ALL_PREFIXES(VariationsHttpHeaderProviderTest,
@@ -109,6 +113,10 @@ class VariationsHttpHeaderProvider : public base::FieldTrialList::Observer,
// |is_signed_in| state.
std::string GenerateBase64EncodedProto(bool is_signed_in);
+ // Adds *additional* variation ids and trigger variation ids to be encoded in
+ // the X-Client-Data request header.
+ bool AddDefaultVariationIds(const std::vector<std::string>& variation_ids);
+
// Returns the currently active set of variation ids, which includes any
// default values, synthetic variations and actual field trial variations.
std::set<VariationIDEntry> GetAllVariationIds();
diff --git a/chromium/components/variations/variations_http_header_provider_unittest.cc b/chromium/components/variations/variations_http_header_provider_unittest.cc
index 394310aa18f..4fad592fff3 100644
--- a/chromium/components/variations/variations_http_header_provider_unittest.cc
+++ b/chromium/components/variations/variations_http_header_provider_unittest.cc
@@ -60,12 +60,13 @@ class VariationsHttpHeaderProviderTest : public ::testing::Test {
void TearDown() override { testing::ClearAllVariationIDs(); }
};
-TEST_F(VariationsHttpHeaderProviderTest, SetDefaultVariationIds_Valid) {
+TEST_F(VariationsHttpHeaderProviderTest, ForceVariationIds_Valid) {
base::MessageLoop loop;
VariationsHttpHeaderProvider provider;
// Valid experiment ids.
- EXPECT_TRUE(provider.SetDefaultVariationIds({"12", "456", "t789"}));
+ EXPECT_EQ(VariationsHttpHeaderProvider::ForceIdsResult::SUCCESS,
+ provider.ForceVariationIds({"12", "456", "t789"}, ""));
provider.InitVariationIDsCacheIfNeeded();
std::string variations = provider.GetClientDataHeader(false);
EXPECT_FALSE(variations.empty());
@@ -78,19 +79,44 @@ TEST_F(VariationsHttpHeaderProviderTest, SetDefaultVariationIds_Valid) {
EXPECT_FALSE(variation_ids.find(789) != variation_ids.end());
}
-TEST_F(VariationsHttpHeaderProviderTest, SetDefaultVariationIds_Invalid) {
+TEST_F(VariationsHttpHeaderProviderTest, ForceVariationIds_ValidCommandLine) {
+ base::MessageLoop loop;
+ VariationsHttpHeaderProvider provider;
+
+ // Valid experiment ids.
+ EXPECT_EQ(VariationsHttpHeaderProvider::ForceIdsResult::SUCCESS,
+ provider.ForceVariationIds({"12"}, "456,t789"));
+ provider.InitVariationIDsCacheIfNeeded();
+ std::string variations = provider.GetClientDataHeader(false);
+ EXPECT_FALSE(variations.empty());
+ std::set<VariationID> variation_ids;
+ std::set<VariationID> trigger_ids;
+ ASSERT_TRUE(ExtractVariationIds(variations, &variation_ids, &trigger_ids));
+ EXPECT_TRUE(variation_ids.find(12) != variation_ids.end());
+ EXPECT_TRUE(variation_ids.find(456) != variation_ids.end());
+ EXPECT_TRUE(trigger_ids.find(789) != trigger_ids.end());
+ EXPECT_FALSE(variation_ids.find(789) != variation_ids.end());
+}
+
+TEST_F(VariationsHttpHeaderProviderTest, ForceVariationIds_Invalid) {
base::MessageLoop loop;
VariationsHttpHeaderProvider provider;
// Invalid experiment ids.
- EXPECT_FALSE(provider.SetDefaultVariationIds(
- std::vector<std::string>{"abcd12", "456"}));
+ EXPECT_EQ(VariationsHttpHeaderProvider::ForceIdsResult::INVALID_VECTOR_ENTRY,
+ provider.ForceVariationIds({"abcd12", "456"}, ""));
provider.InitVariationIDsCacheIfNeeded();
EXPECT_TRUE(provider.GetClientDataHeader(false).empty());
// Invalid trigger experiment id
- EXPECT_FALSE(provider.SetDefaultVariationIds(
- std::vector<std::string>{"12", "tabc456"}));
+ EXPECT_EQ(VariationsHttpHeaderProvider::ForceIdsResult::INVALID_VECTOR_ENTRY,
+ provider.ForceVariationIds({"12", "tabc456"}, ""));
+ provider.InitVariationIDsCacheIfNeeded();
+ EXPECT_TRUE(provider.GetClientDataHeader(false).empty());
+
+ // Invalid command-line ids.
+ EXPECT_EQ(VariationsHttpHeaderProvider::ForceIdsResult::INVALID_SWITCH_ENTRY,
+ provider.ForceVariationIds({"12", "50"}, "tabc456"));
provider.InitVariationIDsCacheIfNeeded();
EXPECT_TRUE(provider.GetClientDataHeader(false).empty());
}
@@ -154,10 +180,7 @@ TEST_F(VariationsHttpHeaderProviderTest, GetVariationsString) {
CreateTrialAndAssociateId("t3", "g3", GOOGLE_WEB_PROPERTIES_SIGNED_IN, 125);
VariationsHttpHeaderProvider provider;
- std::vector<std::string> ids;
- ids.push_back("100");
- ids.push_back("200");
- provider.SetDefaultVariationIds(ids);
+ provider.ForceVariationIds({"100", "200"}, "");
EXPECT_EQ(" 100 123 124 200 ", provider.GetVariationsString());
}
diff --git a/chromium/components/variations/variations_request_scheduler_unittest.cc b/chromium/components/variations/variations_request_scheduler_unittest.cc
index 822c17b2d43..ca5d6fa3f84 100644
--- a/chromium/components/variations/variations_request_scheduler_unittest.cc
+++ b/chromium/components/variations/variations_request_scheduler_unittest.cc
@@ -14,7 +14,7 @@ namespace variations {
TEST(VariationsRequestSchedulerTest, ScheduleFetchShortly) {
base::MessageLoopForUI message_loop_;
- const base::Closure task = base::Bind(&base::DoNothing);
+ const base::Closure task = base::DoNothing();
VariationsRequestScheduler scheduler(task);
EXPECT_FALSE(scheduler.one_shot_timer_.IsRunning());
diff --git a/chromium/components/variations/variations_seed_processor.cc b/chromium/components/variations/variations_seed_processor.cc
index 947bf53cd67..7fff151c3f3 100644
--- a/chromium/components/variations/variations_seed_processor.cc
+++ b/chromium/components/variations/variations_seed_processor.cc
@@ -125,21 +125,13 @@ void RegisterFeatureOverrides(const ProcessedStudy& processed_study,
base::FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
}
- // Check if this study enables/disables a single feature and uses explicit
- // activation (i.e. the trial should be activated when queried). If so, ensure
- // that groups that don't explicitly enable/disable that feature are still
- // associated with it (i.e. so "Default" group gets reported).
- //
- // Note: This checks for ACTIVATION_EXPLICIT, since there is no reason to
- // have this association with ACTIVATION_AUTO (where the trial starts active),
- // as well as allowing flexibility to disable this behavior in the future from
- // the server by introducing a new activation type.
- if (!processed_study.single_feature_name().empty() &&
- study.activation_type() == Study_ActivationType_ACTIVATION_EXPLICIT &&
- !experiment.has_feature_association()) {
- feature_list->RegisterFieldTrialOverride(
- processed_study.single_feature_name(),
- base::FeatureList::OVERRIDE_USE_DEFAULT, trial);
+ // Associate features for groups that do not specify them manually (e.g.
+ // "Default" group), so that such groups are reported.
+ if (!experiment.has_feature_association()) {
+ for (const auto& feature_name : processed_study.associated_features()) {
+ feature_list->RegisterFieldTrialOverride(
+ feature_name, base::FeatureList::OVERRIDE_USE_DEFAULT, trial);
+ }
}
}
diff --git a/chromium/components/variations/variations_seed_processor_unittest.cc b/chromium/components/variations/variations_seed_processor_unittest.cc
index 79793795a0e..b1c4d25d259 100644
--- a/chromium/components/variations/variations_seed_processor_unittest.cc
+++ b/chromium/components/variations/variations_seed_processor_unittest.cc
@@ -26,8 +26,12 @@
#include "components/variations/processed_study.h"
#include "components/variations/study_filtering.h"
#include "components/variations/variations_associated_data.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using testing::ElementsAre;
+using testing::IsEmpty;
+
namespace variations {
namespace {
@@ -412,35 +416,37 @@ TEST_F(VariationsSeedProcessorTest, ValidateStudySingleFeature) {
EXPECT_TRUE(processed_study.Init(&study, false));
EXPECT_EQ(400, processed_study.total_probability());
- EXPECT_EQ(std::string(), processed_study.single_feature_name());
+ EXPECT_THAT(processed_study.associated_features(), IsEmpty());
const char kFeature1Name[] = "Feature1";
const char kFeature2Name[] = "Feature2";
exp1->mutable_feature_association()->add_enable_feature(kFeature1Name);
EXPECT_TRUE(processed_study.Init(&study, false));
- EXPECT_EQ(kFeature1Name, processed_study.single_feature_name());
+ EXPECT_THAT(processed_study.associated_features(),
+ ElementsAre(kFeature1Name));
exp1->clear_feature_association();
exp1->mutable_feature_association()->add_enable_feature(kFeature1Name);
exp1->mutable_feature_association()->add_enable_feature(kFeature2Name);
EXPECT_TRUE(processed_study.Init(&study, false));
- // Since there's multiple different features, |single_feature_name| should be
+ // Since there's multiple different features, |associated_features| should be
// unset.
- EXPECT_EQ(std::string(), processed_study.single_feature_name());
+ EXPECT_THAT(processed_study.associated_features(), IsEmpty());
exp1->clear_feature_association();
exp1->mutable_feature_association()->add_enable_feature(kFeature1Name);
exp2->mutable_feature_association()->add_enable_feature(kFeature1Name);
exp3->mutable_feature_association()->add_disable_feature(kFeature1Name);
EXPECT_TRUE(processed_study.Init(&study, false));
- EXPECT_EQ(kFeature1Name, processed_study.single_feature_name());
+ EXPECT_THAT(processed_study.associated_features(),
+ ElementsAre(kFeature1Name));
- // Setting a different feature name on exp2 should cause |single_feature_name|
+ // Setting a different feature name on exp2 should cause |associated_features|
// to be not set.
exp2->mutable_feature_association()->set_enable_feature(0, kFeature2Name);
EXPECT_TRUE(processed_study.Init(&study, false));
- EXPECT_EQ(std::string(), processed_study.single_feature_name());
+ EXPECT_THAT(processed_study.associated_features(), IsEmpty());
}
TEST_F(VariationsSeedProcessorTest, ProcessedStudyAllAssignmentsToOneGroup) {
diff --git a/chromium/components/variations/variations_seed_store.cc b/chromium/components/variations/variations_seed_store.cc
index d0b7e7ce04d..6c5aea0c7e0 100644
--- a/chromium/components/variations/variations_seed_store.cc
+++ b/chromium/components/variations/variations_seed_store.cc
@@ -26,7 +26,6 @@
#endif // OS_ANDROID
namespace variations {
-
namespace {
// The ECDSA public key of the variations server for verifying variations seed
@@ -41,6 +40,11 @@ const uint8_t kPublicKey[] = {
0x2b, 0xff, 0x82, 0x4d, 0xd3, 0xfe, 0xc5, 0xef, 0x20, 0xc6, 0xa3, 0x10, 0xbf,
};
+// A sentinel value that may be stored as the latest variations seed value in
+// prefs to indicate that the latest seed is identical to the safe seed. Used to
+// avoid duplicating storage space.
+constexpr char kIdenticalToSafeSeedSentinel[] = "safe_seed_content";
+
// Verifies a variations seed (the serialized proto bytes) with the specified
// base-64 encoded signature that was received from the server and returns the
// result. The signature is assumed to be an "ECDSA with SHA-256" signature
@@ -107,7 +111,16 @@ UpdateSeedDateResult GetSeedDateChangeState(
} // namespace
VariationsSeedStore::VariationsSeedStore(PrefService* local_state)
- : local_state_(local_state) {}
+ : local_state_(local_state) {
+#if defined(OS_ANDROID)
+ // If there is a first run seed to import, do so as soon as possible. This is
+ // especially important because some clients query the seed store prefs
+ // directly rather than accessing them via the seed store API:
+ // https://crbug.com/829527
+ if (!local_state_->HasPrefPath(prefs::kVariationsSeedSignature))
+ ImportFirstRunJavaSeed();
+#endif // OS_ANDROID
+}
VariationsSeedStore::~VariationsSeedStore() {
}
@@ -115,39 +128,13 @@ VariationsSeedStore::~VariationsSeedStore() {
bool VariationsSeedStore::LoadSeed(VariationsSeed* seed,
std::string* seed_data,
std::string* base64_seed_signature) {
-#if defined(OS_ANDROID)
- if (!local_state_->HasPrefPath(prefs::kVariationsSeedSignature))
- ImportFirstRunJavaSeed();
-#endif // OS_ANDROID
-
- LoadSeedResult read_result = ReadSeedData(seed_data);
- if (read_result != LoadSeedResult::SUCCESS) {
- RecordLoadSeedResult(read_result);
- return false;
- }
-
- *base64_seed_signature =
- local_state_->GetString(prefs::kVariationsSeedSignature);
- if (SignatureVerificationEnabled()) {
- const VerifySignatureResult result =
- VerifySeedSignature(*seed_data, *base64_seed_signature);
- UMA_HISTOGRAM_ENUMERATION("Variations.LoadSeedSignature", result,
- VerifySignatureResult::ENUM_SIZE);
- if (result != VerifySignatureResult::VALID_SIGNATURE) {
- ClearPrefs();
- RecordLoadSeedResult(LoadSeedResult::INVALID_SIGNATURE);
- return false;
- }
- }
-
- if (!seed->ParseFromString(*seed_data)) {
- ClearPrefs();
- RecordLoadSeedResult(LoadSeedResult::CORRUPT_PROTOBUF);
+ LoadSeedResult result =
+ LoadSeedImpl(SeedType::LATEST, seed, seed_data, base64_seed_signature);
+ RecordLoadSeedResult(result);
+ if (result != LoadSeedResult::SUCCESS)
return false;
- }
latest_serial_number_ = seed->serial_number();
- RecordLoadSeedResult(LoadSeedResult::SUCCESS);
return true;
}
@@ -201,7 +188,8 @@ bool VariationsSeedStore::StoreSeedData(
std::string existing_seed_data;
std::string updated_seed_data;
- LoadSeedResult read_result = ReadSeedData(&existing_seed_data);
+ LoadSeedResult read_result =
+ ReadSeedData(SeedType::LATEST, &existing_seed_data);
if (read_result != LoadSeedResult::SUCCESS) {
RecordStoreSeedResult(StoreSeedResult::FAILED_DELTA_READ_SEED);
return false;
@@ -229,10 +217,34 @@ bool VariationsSeedStore::StoreSeedData(
return result;
}
+bool VariationsSeedStore::LoadSafeSeed(VariationsSeed* seed,
+ ClientFilterableState* client_state,
+ base::Time* seed_fetch_time) {
+ std::string unused_seed_data;
+ std::string unused_base64_seed_signature;
+ LoadSeedResult result = LoadSeedImpl(SeedType::SAFE, seed, &unused_seed_data,
+ &unused_base64_seed_signature);
+ RecordLoadSafeSeedResult(result);
+ if (result != LoadSeedResult::SUCCESS)
+ return false;
+
+ client_state->reference_date =
+ local_state_->GetTime(prefs::kVariationsSafeSeedDate);
+ client_state->locale =
+ local_state_->GetString(prefs::kVariationsSafeSeedLocale);
+ client_state->permanent_consistency_country = local_state_->GetString(
+ prefs::kVariationsSafeSeedPermanentConsistencyCountry);
+ client_state->session_consistency_country = local_state_->GetString(
+ prefs::kVariationsSafeSeedSessionConsistencyCountry);
+ *seed_fetch_time = local_state_->GetTime(prefs::kVariationsSafeSeedFetchTime);
+ return true;
+}
+
bool VariationsSeedStore::StoreSafeSeed(
const std::string& seed_data,
const std::string& base64_seed_signature,
- const ClientFilterableState& client_state) {
+ const ClientFilterableState& client_state,
+ base::Time seed_fetch_time) {
std::string base64_seed_data;
StoreSeedResult result = VerifyAndCompressSeedData(
seed_data, base64_seed_signature, false /* fetched_insecurely */,
@@ -242,11 +254,43 @@ bool VariationsSeedStore::StoreSafeSeed(
if (result != StoreSeedResult::SUCCESS)
return false;
- local_state_->SetString(prefs::kVariationsSafeCompressedSeed,
- base64_seed_data);
+ // The sentinel value should only ever be saved in place of the latest seed --
+ // it should never be saved in place of the safe seed.
+ DCHECK_NE(base64_seed_data, kIdenticalToSafeSeedSentinel);
+
+ // As a performance optimization, avoid an expensive no-op of overwriting the
+ // previous safe seed with an identical copy.
+ std::string previous_safe_seed =
+ local_state_->GetString(prefs::kVariationsSafeCompressedSeed);
+ if (base64_seed_data != previous_safe_seed) {
+ // It's theoretically possible to overwrite an existing safe seed value,
+ // which was identical to the latest seed, with a new value. This could
+ // happen, for example, if:
+ // (1) Seed A is received from the server and saved as both the safe and
+ // latest seed value.
+ // (2) Seed B is received from the server and saved as the latest seed
+ // value.
+ // (3) The user restarts Chrome, which is now running with the
+ // configuration from seed B.
+ // (4) Seed A is received again from the server, perhaps due to a
+ // rollback.
+ // In this situation, seed A should be saved as the latest seed, while seed
+ // B should be saved as the safe seed, i.e. the previously saved values
+ // should be swapped. Indeed, it is guaranteed that the latest seed value
+ // should be overwritten in this case, as a seed should not be considered
+ // safe unless a new seed can be both received *and saved* from the server.
+ std::string latest_seed =
+ local_state_->GetString(prefs::kVariationsCompressedSeed);
+ if (latest_seed == kIdenticalToSafeSeedSentinel) {
+ local_state_->SetString(prefs::kVariationsCompressedSeed,
+ previous_safe_seed);
+ }
+ local_state_->SetString(prefs::kVariationsSafeCompressedSeed,
+ base64_seed_data);
+ }
+
local_state_->SetString(prefs::kVariationsSafeSeedSignature,
base64_seed_signature);
-
local_state_->SetTime(prefs::kVariationsSafeSeedDate,
client_state.reference_date);
local_state_->SetString(prefs::kVariationsSafeSeedLocale,
@@ -255,9 +299,39 @@ bool VariationsSeedStore::StoreSafeSeed(
client_state.permanent_consistency_country);
local_state_->SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry,
client_state.session_consistency_country);
+
+ // As a space optimization, overwrite the stored latest seed data with an
+ // alias to the safe seed, if they are identical.
+ if (base64_seed_data ==
+ local_state_->GetString(prefs::kVariationsCompressedSeed)) {
+ local_state_->SetString(prefs::kVariationsCompressedSeed,
+ kIdenticalToSafeSeedSentinel);
+
+ // Moreover, in this case, the last fetch time for the safe seed should
+ // match the latest seed's.
+ seed_fetch_time = GetLastFetchTime();
+ }
+ local_state_->SetTime(prefs::kVariationsSafeSeedFetchTime, seed_fetch_time);
+
return true;
}
+base::Time VariationsSeedStore::GetLastFetchTime() const {
+ return local_state_->GetTime(prefs::kVariationsLastFetchTime);
+}
+
+void VariationsSeedStore::RecordLastFetchTime() {
+ base::Time now = base::Time::Now();
+ local_state_->SetTime(prefs::kVariationsLastFetchTime, now);
+
+ // If the latest and safe seeds are identical, update the fetch time for the
+ // safe seed as well.
+ if (local_state_->GetString(prefs::kVariationsCompressedSeed) ==
+ kIdenticalToSafeSeedSentinel) {
+ local_state_->SetTime(prefs::kVariationsSafeSeedFetchTime, now);
+ }
+}
+
void VariationsSeedStore::UpdateSeedDateAndLogDayChange(
const base::Time& server_date_fetched) {
UpdateSeedDateResult result = UpdateSeedDateResult::NO_OLD_DATE;
@@ -284,7 +358,7 @@ const std::string& VariationsSeedStore::GetLatestSerialNumber() {
// when running in safe mode.
std::string seed_data;
VariationsSeed seed;
- if (ReadSeedData(&seed_data) == LoadSeedResult::SUCCESS &&
+ if (ReadSeedData(SeedType::LATEST, &seed_data) == LoadSeedResult::SUCCESS &&
seed.ParseFromString(seed_data)) {
latest_serial_number_ = seed.serial_number();
}
@@ -296,6 +370,7 @@ const std::string& VariationsSeedStore::GetLatestSerialNumber() {
void VariationsSeedStore::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterStringPref(prefs::kVariationsCompressedSeed, std::string());
registry->RegisterStringPref(prefs::kVariationsCountry, std::string());
+ registry->RegisterTimePref(prefs::kVariationsLastFetchTime, base::Time());
registry->RegisterTimePref(prefs::kVariationsSeedDate, base::Time());
registry->RegisterStringPref(prefs::kVariationsSeedSignature, std::string());
@@ -303,6 +378,7 @@ void VariationsSeedStore::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterStringPref(prefs::kVariationsSafeCompressedSeed,
std::string());
registry->RegisterTimePref(prefs::kVariationsSafeSeedDate, base::Time());
+ registry->RegisterTimePref(prefs::kVariationsSafeSeedFetchTime, base::Time());
registry->RegisterStringPref(prefs::kVariationsSafeSeedLocale, std::string());
registry->RegisterStringPref(
prefs::kVariationsSafeSeedPermanentConsistencyCountry, std::string());
@@ -323,10 +399,24 @@ bool VariationsSeedStore::SignatureVerificationEnabled() {
#endif
}
-void VariationsSeedStore::ClearPrefs() {
- local_state_->ClearPref(prefs::kVariationsCompressedSeed);
- local_state_->ClearPref(prefs::kVariationsSeedDate);
- local_state_->ClearPref(prefs::kVariationsSeedSignature);
+void VariationsSeedStore::ClearPrefs(SeedType seed_type) {
+ if (seed_type == SeedType::LATEST) {
+ local_state_->ClearPref(prefs::kVariationsCompressedSeed);
+ local_state_->ClearPref(prefs::kVariationsLastFetchTime);
+ local_state_->ClearPref(prefs::kVariationsSeedDate);
+ local_state_->ClearPref(prefs::kVariationsSeedSignature);
+ return;
+ }
+
+ DCHECK_EQ(seed_type, SeedType::SAFE);
+ local_state_->ClearPref(prefs::kVariationsSafeCompressedSeed);
+ local_state_->ClearPref(prefs::kVariationsSafeSeedDate);
+ local_state_->ClearPref(prefs::kVariationsSafeSeedFetchTime);
+ local_state_->ClearPref(prefs::kVariationsSafeSeedLocale);
+ local_state_->ClearPref(
+ prefs::kVariationsSafeSeedPermanentConsistencyCountry);
+ local_state_->ClearPref(prefs::kVariationsSafeSeedSessionConsistencyCountry);
+ local_state_->ClearPref(prefs::kVariationsSafeSeedSignature);
}
#if defined(OS_ANDROID)
@@ -365,21 +455,67 @@ void VariationsSeedStore::ImportFirstRunJavaSeed() {
}
#endif // OS_ANDROID
-LoadSeedResult VariationsSeedStore::ReadSeedData(std::string* seed_data) {
- std::string base64_seed_data =
- local_state_->GetString(prefs::kVariationsCompressedSeed);
+LoadSeedResult VariationsSeedStore::LoadSeedImpl(
+ SeedType seed_type,
+ VariationsSeed* seed,
+ std::string* seed_data,
+ std::string* base64_seed_signature) {
+ LoadSeedResult read_result = ReadSeedData(seed_type, seed_data);
+ if (read_result != LoadSeedResult::SUCCESS)
+ return read_result;
+
+ *base64_seed_signature = local_state_->GetString(
+ seed_type == SeedType::LATEST ? prefs::kVariationsSeedSignature
+ : prefs::kVariationsSafeSeedSignature);
+ if (SignatureVerificationEnabled()) {
+ const VerifySignatureResult result =
+ VerifySeedSignature(*seed_data, *base64_seed_signature);
+ if (seed_type == SeedType::LATEST) {
+ UMA_HISTOGRAM_ENUMERATION("Variations.LoadSeedSignature", result,
+ VerifySignatureResult::ENUM_SIZE);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Variations.SafeMode.LoadSafeSeed.SignatureValidity", result,
+ VerifySignatureResult::ENUM_SIZE);
+ }
+ if (result != VerifySignatureResult::VALID_SIGNATURE) {
+ ClearPrefs(seed_type);
+ return LoadSeedResult::INVALID_SIGNATURE;
+ }
+ }
+
+ if (!seed->ParseFromString(*seed_data)) {
+ ClearPrefs(seed_type);
+ return LoadSeedResult::CORRUPT_PROTOBUF;
+ }
+
+ return LoadSeedResult::SUCCESS;
+}
+
+LoadSeedResult VariationsSeedStore::ReadSeedData(SeedType seed_type,
+ std::string* seed_data) {
+ std::string base64_seed_data = local_state_->GetString(
+ seed_type == SeedType::LATEST ? prefs::kVariationsCompressedSeed
+ : prefs::kVariationsSafeCompressedSeed);
if (base64_seed_data.empty())
return LoadSeedResult::EMPTY;
+ // As a space optimization, the latest seed might not be stored directly, but
+ // rather aliased to the safe seed.
+ if (seed_type == SeedType::LATEST &&
+ base64_seed_data == kIdenticalToSafeSeedSentinel) {
+ return ReadSeedData(SeedType::SAFE, seed_data);
+ }
+
// If the decode process fails, assume the pref value is corrupt and clear it.
std::string decoded_data;
if (!base::Base64Decode(base64_seed_data, &decoded_data)) {
- ClearPrefs();
+ ClearPrefs(seed_type);
return LoadSeedResult::CORRUPT_BASE64;
}
if (!compression::GzipUncompress(decoded_data, seed_data)) {
- ClearPrefs();
+ ClearPrefs(seed_type);
return LoadSeedResult::CORRUPT_GZIP;
}
@@ -417,6 +553,13 @@ bool VariationsSeedStore::StoreSeedDataNoDelta(
if (!country_code.empty())
local_state_->SetString(prefs::kVariationsCountry, country_code);
+ // As a space optimization, store an alias to the safe seed if the contents
+ // are identical.
+ if (base64_seed_data ==
+ local_state_->GetString(prefs::kVariationsSafeCompressedSeed)) {
+ base64_seed_data = kIdenticalToSafeSeedSentinel;
+ }
+
local_state_->SetString(prefs::kVariationsCompressedSeed, base64_seed_data);
UpdateSeedDateAndLogDayChange(date_fetched);
local_state_->SetString(prefs::kVariationsSeedSignature,
diff --git a/chromium/components/variations/variations_seed_store.h b/chromium/components/variations/variations_seed_store.h
index 2af9b8d0d56..56bd21da90e 100644
--- a/chromium/components/variations/variations_seed_store.h
+++ b/chromium/components/variations/variations_seed_store.h
@@ -33,9 +33,10 @@ class VariationsSeedStore {
// raw pref values into |seed_data| and |base64_signature|. If there is a
// problem with loading, clears the seed pref value and returns false. If
// successful, fills the the outparams with the loaded data and returns true.
- bool LoadSeed(VariationsSeed* seed,
- std::string* seed_data,
- std::string* base64_seed_signature) WARN_UNUSED_RESULT;
+ // Virtual for testing.
+ virtual bool LoadSeed(VariationsSeed* seed,
+ std::string* seed_data,
+ std::string* base64_seed_signature) WARN_UNUSED_RESULT;
// Stores the given seed |data| (serialized protobuf) to local state, along
// with a base64-encoded digital signature for seed and the date when it was
@@ -57,6 +58,18 @@ class VariationsSeedStore {
bool fetched_insecurely,
VariationsSeed* parsed_seed) WARN_UNUSED_RESULT;
+ // Loads the safe variations seed data from local state into |seed| and
+ // updates any relevant fields in |client_state| and stores the
+ // |seed_fetch_time|. Returns true iff the safe seed was read successfully
+ // from prefs. If the safe seed could not be loaded, it is guaranteed that no
+ // fields in |client_state| are modified.
+ // Side-effect: Upon any failure to read or validate the safe seed, clears all
+ // of the safe seed pref values. This occurs iff the method returns false.
+ // Virtual for testing.
+ virtual bool LoadSafeSeed(VariationsSeed* seed,
+ ClientFilterableState* client_state,
+ base::Time* seed_fetch_time) WARN_UNUSED_RESULT;
+
// Stores the given |seed_data| (a serialized protobuf) to local state as a
// safe seed, along with a base64-encoded digital signature for seed and any
// additional client metadata relevant to the safe seed. Returns true on
@@ -64,7 +77,17 @@ class VariationsSeedStore {
// Virtual for testing.
virtual bool StoreSafeSeed(const std::string& seed_data,
const std::string& base64_seed_signature,
- const ClientFilterableState& client_state);
+ const ClientFilterableState& client_state,
+ base::Time seed_fetch_time);
+
+ // Loads the last fetch time (for the latest seed) that was persisted to the
+ // store.
+ base::Time GetLastFetchTime() const;
+
+ // Records the current time as the last time at which a seed was fetched
+ // successfully. Also updates the safe seed's fetch time if the latest and
+ // safe seeds are identical.
+ void RecordLastFetchTime();
// Updates |kVariationsSeedDate| and logs when previous date was from a
// different day.
@@ -85,7 +108,6 @@ class VariationsSeedStore {
static void RegisterPrefs(PrefRegistrySimple* registry);
PrefService* local_state() { return local_state_; }
-
const PrefService* local_state() const { return local_state_; }
protected:
@@ -108,8 +130,9 @@ class VariationsSeedStore {
SAFE,
};
- // Clears all prefs related to variations seed storage.
- void ClearPrefs();
+ // Clears all prefs related to variations seed storage for the specified seed
+ // type.
+ void ClearPrefs(SeedType seed_type);
#if defined(OS_ANDROID)
// Imports the variations seed data from Java side during the first
@@ -117,11 +140,25 @@ class VariationsSeedStore {
void ImportFirstRunJavaSeed();
#endif // OS_ANDROID
+ // Loads the variations seed data from local state into |seed|, as well as the
+ // raw pref values into |seed_data| and |base64_signature|. Loads either the
+ // safe seed or the latest seed, according to the |seed_type|. Returns whether
+ // loading the seed was successful.
+ // Side-effect: Upon any failure to read or validate the safe seed, clears all
+ // of the pref values for the seed. This occurs iff the method returns false.
+ LoadSeedResult LoadSeedImpl(SeedType seed_type,
+ VariationsSeed* seed,
+ std::string* seed_data,
+ std::string* base64_seed_signature)
+ WARN_UNUSED_RESULT;
+
// Reads the variations seed data from prefs into |seed_data|, and returns the
// result of the load. The value stored into |seed_data| should only be used
- // if the result is SUCCESS.
+ // if the result is SUCCESS. Reads either the latest or the safe seed,
+ // according to the specified |seed_type|.
// Side-effect: If the read fails, clears the prefs associated with the seed.
- LoadSeedResult ReadSeedData(std::string* seed_data) WARN_UNUSED_RESULT;
+ LoadSeedResult ReadSeedData(SeedType seed_type,
+ std::string* seed_data) WARN_UNUSED_RESULT;
// Internal version of |StoreSeedData()| that assumes |seed_data| is not delta
// compressed.
diff --git a/chromium/components/variations/variations_seed_store_unittest.cc b/chromium/components/variations/variations_seed_store_unittest.cc
index f401c99fcbe..8173ec6650d 100644
--- a/chromium/components/variations/variations_seed_store_unittest.cc
+++ b/chromium/components/variations/variations_seed_store_unittest.cc
@@ -4,9 +4,14 @@
#include "components/variations/variations_seed_store.h"
+#include <memory>
+#include <utility>
+
#include "base/base64.h"
#include "base/macros.h"
#include "base/test/histogram_tester.h"
+#include "base/time/time.h"
+#include "base/version.h"
#include "build/build_config.h"
#include "components/prefs/testing_pref_service.h"
#include "components/variations/client_filterable_state.h"
@@ -35,6 +40,14 @@ const char kBase64SeedSignature[] =
"MEQCIDD1IVxjzWYncun+9IGzqYjZvqxxujQEayJULTlbTGA/AiAr0oVmEgVUQZBYq5VLOSvy"
"96JkMYgzTkHPwbv7K/CmgA==";
+// The sentinel value that may be stored as the latest variations seed value in
+// prefs to indicate that the latest seed is identical to the safe seed.
+// Note: This constant is intentionally duplicated in the test because it is
+// persisted to disk. In order to maintain backward-compatibility, it's
+// important that code continue to correctly handle this specific constant, even
+// if the constant used internally in the implementation changes.
+constexpr char kIdenticalToSafeSeedSentinel[] = "safe_seed_content";
+
class TestVariationsSeedStore : public VariationsSeedStore {
public:
explicit TestVariationsSeedStore(PrefService* local_state)
@@ -67,6 +80,14 @@ class SignatureVerifyingVariationsSeedStore : public VariationsSeedStore {
DISALLOW_COPY_AND_ASSIGN(SignatureVerifyingVariationsSeedStore);
};
+// Creates a base::Time object from the corresponding raw value. The specific
+// implementation is not important; it's only important that distinct inputs map
+// to distinct outputs.
+base::Time WrapTime(int64_t time) {
+ return base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(time));
+}
+
// 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. |seed|'s study field will be cleared before adding
@@ -83,6 +104,24 @@ VariationsSeed CreateTestSeed() {
return seed;
}
+// Returns a ClientFilterableState with all fields set to "interesting" values
+// for testing.
+std::unique_ptr<ClientFilterableState> CreateTestClientFilterableState() {
+ std::unique_ptr<ClientFilterableState> client_state =
+ std::make_unique<ClientFilterableState>();
+ client_state->locale = "es-MX";
+ client_state->reference_date = WrapTime(1234554321);
+ client_state->version = base::Version("1.2.3.4");
+ client_state->channel = Study::CANARY;
+ client_state->form_factor = Study::PHONE;
+ client_state->platform = Study::PLATFORM_MAC;
+ client_state->hardware_class = "mario";
+ client_state->is_low_end_device = true;
+ client_state->session_consistency_country = "mx";
+ client_state->permanent_consistency_country = "br";
+ return client_state;
+}
+
// Serializes |seed| to protobuf binary format.
std::string SerializeSeed(const VariationsSeed& seed) {
std::string serialized_seed;
@@ -106,6 +145,23 @@ std::string SerializeSeedBase64(const VariationsSeed& seed) {
return base64_serialized_seed;
}
+// Sets all seed-related prefs to non-default values. Used to verify whether
+// pref values were cleared.
+void SetAllSeedPrefsToNonDefaultValues(PrefService* prefs) {
+ prefs->SetString(prefs::kVariationsCompressedSeed, "a");
+ prefs->SetString(prefs::kVariationsSafeCompressedSeed, "b");
+ prefs->SetString(prefs::kVariationsSafeSeedLocale, "c");
+ prefs->SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry, "d");
+ prefs->SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry, "e");
+ prefs->SetString(prefs::kVariationsSafeSeedSignature, "f");
+ prefs->SetString(prefs::kVariationsSeedSignature, "g");
+ const base::Time now = base::Time::Now();
+ const base::TimeDelta delta = base::TimeDelta::FromDays(1);
+ prefs->SetTime(prefs::kVariationsSafeSeedDate, now - delta);
+ prefs->SetTime(prefs::kVariationsSafeSeedFetchTime, now - delta * 2);
+ prefs->SetTime(prefs::kVariationsSeedDate, now - delta * 3);
+}
+
// Checks whether the pref with name |pref_name| is at its default value in
// |prefs|.
bool PrefHasDefaultValue(const TestingPrefServiceSimple& prefs,
@@ -115,11 +171,11 @@ bool PrefHasDefaultValue(const TestingPrefServiceSimple& prefs,
} // namespace
-TEST(VariationsSeedStoreTest, LoadSeed) {
+TEST(VariationsSeedStoreTest, LoadSeed_ValidSeed) {
// Store good seed data to test if loading from prefs works.
const VariationsSeed seed = CreateTestSeed();
const std::string base64_seed = SerializeSeedBase64(seed);
- const std::string base64_seed_signature = "a test signature, clearly forged.";
+ const std::string base64_seed_signature = "a test signature, ignored.";
TestingPrefServiceSimple prefs;
VariationsSeedStore::RegisterPrefs(prefs.registry());
@@ -142,20 +198,116 @@ TEST(VariationsSeedStoreTest, LoadSeed) {
// Make sure the pref hasn't been changed.
EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed));
EXPECT_EQ(base64_seed, prefs.GetString(prefs::kVariationsCompressedSeed));
+}
- // Check that loading a bad seed returns false and clears the pref.
+TEST(VariationsSeedStoreTest, LoadSeed_InvalidSeed) {
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+ SetAllSeedPrefsToNonDefaultValues(&prefs);
prefs.SetString(prefs::kVariationsCompressedSeed, "this should fail");
- EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed));
+
+ // Loading an invalid seed should return false and clear all associated prefs.
+ TestVariationsSeedStore seed_store(&prefs);
+ VariationsSeed loaded_seed;
+ std::string loaded_seed_data;
+ std::string loaded_base64_seed_signature;
EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed, &loaded_seed_data,
&loaded_base64_seed_signature));
EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed));
EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate));
EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature));
- // Check that having no seed in prefs results in a return value of false.
- prefs.ClearPref(prefs::kVariationsCompressedSeed);
+ // However, only the latest seed prefs should be cleared; the safe seed prefs
+ // should not be modified.
+ EXPECT_FALSE(
+ PrefHasDefaultValue(prefs, prefs::kVariationsSafeCompressedSeed));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedDate));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedFetchTime));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedLocale));
+ EXPECT_FALSE(PrefHasDefaultValue(
+ prefs, prefs::kVariationsSafeSeedPermanentConsistencyCountry));
+ EXPECT_FALSE(PrefHasDefaultValue(
+ prefs, prefs::kVariationsSafeSeedSessionConsistencyCountry));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedSignature));
+}
+
+TEST(VariationsSeedStoreTest, LoadSeed_InvalidSignature) {
+ const VariationsSeed seed = CreateTestSeed();
+ const std::string base64_seed = SerializeSeedBase64(seed);
+ const std::string base64_seed_signature = "a deeply compromised signature.";
+
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+ SetAllSeedPrefsToNonDefaultValues(&prefs);
+ prefs.SetString(prefs::kVariationsCompressedSeed, base64_seed);
+ prefs.SetString(prefs::kVariationsSeedSignature, base64_seed_signature);
+
+ // Loading a valid seed with an invalid signature should return false and
+ // clear all associated prefs when signature verification is enabled.
+ SignatureVerifyingVariationsSeedStore seed_store(&prefs);
+ VariationsSeed loaded_seed;
+ std::string loaded_seed_data;
+ std::string loaded_base64_seed_signature;
EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed, &loaded_seed_data,
&loaded_base64_seed_signature));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature));
+
+ // However, only the latest seed prefs should be cleared; the safe seed prefs
+ // should not be modified.
+ EXPECT_FALSE(
+ PrefHasDefaultValue(prefs, prefs::kVariationsSafeCompressedSeed));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedDate));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedFetchTime));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedLocale));
+ EXPECT_FALSE(PrefHasDefaultValue(
+ prefs, prefs::kVariationsSafeSeedPermanentConsistencyCountry));
+ EXPECT_FALSE(PrefHasDefaultValue(
+ prefs, prefs::kVariationsSafeSeedSessionConsistencyCountry));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedSignature));
+}
+
+TEST(VariationsSeedStoreTest, LoadSeed_EmptySeed) {
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+
+ // Loading an empty seed should return false.
+ TestVariationsSeedStore seed_store(&prefs);
+ VariationsSeed loaded_seed;
+ std::string loaded_seed_data;
+ std::string loaded_base64_seed_signature;
+ EXPECT_FALSE(seed_store.LoadSeed(&loaded_seed, &loaded_seed_data,
+ &loaded_base64_seed_signature));
+}
+
+TEST(VariationsSeedStoreTest, LoadSeed_IdenticalToSafeSeed) {
+ // Store good seed data to the safe seed prefs, and store a sentinel value to
+ // the latest seed pref, to verify that loading via the alias works.
+ const VariationsSeed seed = CreateTestSeed();
+ const std::string base64_seed = SerializeSeedBase64(seed);
+ const std::string base64_seed_signature = "a test signature, ignored.";
+
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+ prefs.SetString(prefs::kVariationsCompressedSeed,
+ kIdenticalToSafeSeedSentinel);
+ prefs.SetString(prefs::kVariationsSafeCompressedSeed, base64_seed);
+ prefs.SetString(prefs::kVariationsSeedSignature, base64_seed_signature);
+
+ TestVariationsSeedStore seed_store(&prefs);
+
+ VariationsSeed loaded_seed;
+ std::string loaded_seed_data;
+ std::string loaded_base64_seed_signature;
+ // Check that loading the seed works correctly.
+ EXPECT_TRUE(seed_store.LoadSeed(&loaded_seed, &loaded_seed_data,
+ &loaded_base64_seed_signature));
+
+ // Check that the loaded data is the same as the original.
+ EXPECT_EQ(SerializeSeed(seed), SerializeSeed(loaded_seed));
+ EXPECT_EQ(SerializeSeed(seed), loaded_seed_data);
+ EXPECT_EQ(base64_seed_signature, loaded_base64_seed_signature);
}
TEST(VariationsSeedStoreTest, StoreSeedData) {
@@ -236,24 +388,210 @@ TEST(VariationsSeedStoreTest, StoreSeedData_GzippedSeed) {
EXPECT_EQ(serialized_seed, SerializeSeed(parsed_seed));
}
+TEST(VariationsSeedStoreTest, StoreSeedData_IdenticalToSafeSeed) {
+ const VariationsSeed seed = CreateTestSeed();
+ const std::string serialized_seed = SerializeSeed(seed);
+ const std::string base64_seed = SerializeSeedBase64(seed);
+
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+ prefs.SetString(prefs::kVariationsSafeCompressedSeed, base64_seed);
+
+ TestVariationsSeedStore seed_store(&prefs);
+ EXPECT_TRUE(seed_store.StoreSeedForTesting(serialized_seed));
+
+ // Verify that the pref has a sentinel value, rather than the full string.
+ EXPECT_EQ(kIdenticalToSafeSeedSentinel,
+ prefs.GetString(prefs::kVariationsCompressedSeed));
+
+ // Verify that loading the stored seed returns the original seed value.
+ VariationsSeed loaded_seed;
+ std::string loaded_seed_data;
+ std::string unused_loaded_base64_seed_signature;
+ EXPECT_TRUE(seed_store.LoadSeed(&loaded_seed, &loaded_seed_data,
+ &unused_loaded_base64_seed_signature));
+
+ EXPECT_EQ(SerializeSeed(seed), SerializeSeed(loaded_seed));
+ EXPECT_EQ(SerializeSeed(seed), loaded_seed_data);
+}
+
+TEST(VariationsSeedStoreTest, LoadSafeSeed_ValidSeed) {
+ // Store good seed data to test if loading from prefs works.
+ const VariationsSeed seed = CreateTestSeed();
+ const std::string base64_seed = SerializeSeedBase64(seed);
+ const std::string base64_seed_signature = "a test signature, ignored.";
+ const base::Time reference_date = base::Time::Now();
+ const base::Time fetch_time = reference_date - base::TimeDelta::FromDays(3);
+ const std::string locale = "en-US";
+ const std::string permanent_consistency_country = "us";
+ const std::string session_consistency_country = "ca";
+
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+ prefs.SetString(prefs::kVariationsSafeCompressedSeed, base64_seed);
+ prefs.SetString(prefs::kVariationsSafeSeedSignature, base64_seed_signature);
+ prefs.SetTime(prefs::kVariationsSafeSeedDate, reference_date);
+ prefs.SetTime(prefs::kVariationsSafeSeedFetchTime, fetch_time);
+ prefs.SetString(prefs::kVariationsSafeSeedLocale, locale);
+ prefs.SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry,
+ permanent_consistency_country);
+ prefs.SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry,
+ session_consistency_country);
+
+ TestVariationsSeedStore seed_store(&prefs);
+ VariationsSeed loaded_seed;
+ std::unique_ptr<ClientFilterableState> client_state =
+ CreateTestClientFilterableState();
+ base::Time loaded_fetch_time;
+ EXPECT_TRUE(seed_store.LoadSafeSeed(&loaded_seed, client_state.get(),
+ &loaded_fetch_time));
+
+ // Check that the loaded data is the same as the original.
+ EXPECT_EQ(SerializeSeed(seed), SerializeSeed(loaded_seed));
+ EXPECT_EQ(locale, client_state->locale);
+ EXPECT_EQ(reference_date, client_state->reference_date);
+ EXPECT_EQ(permanent_consistency_country,
+ client_state->permanent_consistency_country);
+ EXPECT_EQ(session_consistency_country,
+ client_state->session_consistency_country);
+ EXPECT_EQ(fetch_time, loaded_fetch_time);
+
+ // Make sure that other data in the |client_state| hasn't been changed.
+ std::unique_ptr<ClientFilterableState> original_state =
+ CreateTestClientFilterableState();
+ EXPECT_EQ(original_state->version, client_state->version);
+ EXPECT_EQ(original_state->channel, client_state->channel);
+ EXPECT_EQ(original_state->form_factor, client_state->form_factor);
+ EXPECT_EQ(original_state->platform, client_state->platform);
+ EXPECT_EQ(original_state->hardware_class, client_state->hardware_class);
+ EXPECT_EQ(original_state->is_low_end_device, client_state->is_low_end_device);
+
+ // Make sure the pref hasn't been changed.
+ EXPECT_FALSE(
+ PrefHasDefaultValue(prefs, prefs::kVariationsSafeCompressedSeed));
+ EXPECT_EQ(base64_seed, prefs.GetString(prefs::kVariationsSafeCompressedSeed));
+}
+
+TEST(VariationsSeedStoreTest, LoadSafeSeed_InvalidSeed) {
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+ SetAllSeedPrefsToNonDefaultValues(&prefs);
+ prefs.SetString(prefs::kVariationsSafeCompressedSeed, "this should fail");
+
+ // Loading an invalid seed should return false and clear all associated prefs.
+ TestVariationsSeedStore seed_store(&prefs);
+ VariationsSeed loaded_seed;
+ std::unique_ptr<ClientFilterableState> client_state =
+ CreateTestClientFilterableState();
+ base::Time fetch_time;
+ EXPECT_FALSE(
+ seed_store.LoadSafeSeed(&loaded_seed, client_state.get(), &fetch_time));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeCompressedSeed));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedDate));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedFetchTime));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedLocale));
+ EXPECT_TRUE(PrefHasDefaultValue(
+ prefs, prefs::kVariationsSafeSeedPermanentConsistencyCountry));
+ EXPECT_TRUE(PrefHasDefaultValue(
+ prefs, prefs::kVariationsSafeSeedSessionConsistencyCountry));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedSignature));
+
+ // However, only the safe seed prefs should be cleared; the latest seed prefs
+ // should not be modified.
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature));
+
+ // Moreover, loading an invalid seed should leave the |client_state|
+ // unmodified.
+ std::unique_ptr<ClientFilterableState> original_state =
+ CreateTestClientFilterableState();
+ EXPECT_EQ(original_state->locale, client_state->locale);
+ EXPECT_EQ(original_state->reference_date, client_state->reference_date);
+ EXPECT_EQ(original_state->session_consistency_country,
+ client_state->session_consistency_country);
+ EXPECT_EQ(original_state->permanent_consistency_country,
+ client_state->permanent_consistency_country);
+}
+
+TEST(VariationsSeedStoreTest, LoadSafeSeed_InvalidSignature) {
+ const VariationsSeed seed = CreateTestSeed();
+ const std::string base64_seed = SerializeSeedBase64(seed);
+ const std::string base64_seed_signature = "a deeply compromised signature.";
+
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+ SetAllSeedPrefsToNonDefaultValues(&prefs);
+ prefs.SetString(prefs::kVariationsSafeCompressedSeed, base64_seed);
+ prefs.SetString(prefs::kVariationsSafeSeedSignature, base64_seed_signature);
+
+ // Loading a valid seed with an invalid signature should return false and
+ // clear all associated prefs when signature verification is enabled.
+ SignatureVerifyingVariationsSeedStore seed_store(&prefs);
+ VariationsSeed loaded_seed;
+ std::unique_ptr<ClientFilterableState> client_state =
+ CreateTestClientFilterableState();
+ base::Time fetch_time;
+ EXPECT_FALSE(
+ seed_store.LoadSafeSeed(&loaded_seed, client_state.get(), &fetch_time));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeCompressedSeed));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedDate));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedFetchTime));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedLocale));
+ EXPECT_TRUE(PrefHasDefaultValue(
+ prefs, prefs::kVariationsSafeSeedPermanentConsistencyCountry));
+ EXPECT_TRUE(PrefHasDefaultValue(
+ prefs, prefs::kVariationsSafeSeedSessionConsistencyCountry));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedSignature));
+
+ // However, only the safe seed prefs should be cleared; the latest seed prefs
+ // should not be modified.
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature));
+
+ // Moreover, the passed-in |client_state| should remain unmodified.
+ std::unique_ptr<ClientFilterableState> original_state =
+ CreateTestClientFilterableState();
+ EXPECT_EQ(original_state->locale, client_state->locale);
+ EXPECT_EQ(original_state->reference_date, client_state->reference_date);
+ EXPECT_EQ(original_state->session_consistency_country,
+ client_state->session_consistency_country);
+ EXPECT_EQ(original_state->permanent_consistency_country,
+ client_state->permanent_consistency_country);
+}
+
+TEST(VariationsSeedStoreTest, LoadSafeSeed_EmptySeed) {
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+
+ // Loading an empty seed should return false.
+ TestVariationsSeedStore seed_store(&prefs);
+ VariationsSeed loaded_seed;
+ ClientFilterableState client_state;
+ base::Time fetch_time;
+ EXPECT_FALSE(
+ seed_store.LoadSafeSeed(&loaded_seed, &client_state, &fetch_time));
+}
+
TEST(VariationsSeedStoreTest, StoreSafeSeed_ValidSeed) {
const VariationsSeed seed = CreateTestSeed();
const std::string serialized_seed = SerializeSeed(seed);
const std::string signature = "a completely ignored signature";
ClientFilterableState client_state;
client_state.locale = "en-US";
- client_state.reference_date =
- base::Time() + base::TimeDelta::FromMicroseconds(12345);
+ client_state.reference_date = WrapTime(12345);
client_state.session_consistency_country = "US";
client_state.permanent_consistency_country = "CA";
+ const base::Time fetch_time = WrapTime(99999);
TestingPrefServiceSimple prefs;
VariationsSeedStore::RegisterPrefs(prefs.registry());
TestVariationsSeedStore seed_store(&prefs);
base::HistogramTester histogram_tester;
- EXPECT_TRUE(
- seed_store.StoreSafeSeed(serialized_seed, signature, client_state));
+ EXPECT_TRUE(seed_store.StoreSafeSeed(serialized_seed, signature, client_state,
+ fetch_time));
// Verify the stored data.
std::string loaded_compressed_seed =
@@ -264,7 +602,9 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_ValidSeed) {
EXPECT_EQ(Compress(serialized_seed), decoded_compressed_seed);
EXPECT_EQ(signature, prefs.GetString(prefs::kVariationsSafeSeedSignature));
EXPECT_EQ("en-US", prefs.GetString(prefs::kVariationsSafeSeedLocale));
- EXPECT_EQ(12345, prefs.GetInt64(prefs::kVariationsSafeSeedDate));
+ EXPECT_EQ(WrapTime(12345), prefs.GetTime(prefs::kVariationsSafeSeedDate));
+ EXPECT_EQ(WrapTime(99999),
+ prefs.GetTime(prefs::kVariationsSafeSeedFetchTime));
EXPECT_EQ("US", prefs.GetString(
prefs::kVariationsSafeSeedSessionConsistencyCountry));
EXPECT_EQ("CA", prefs.GetString(
@@ -280,10 +620,10 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_EmptySeed) {
const std::string signature = "a completely ignored signature";
ClientFilterableState client_state;
client_state.locale = "en-US";
- client_state.reference_date =
- base::Time() + base::TimeDelta::FromMicroseconds(12345);
+ client_state.reference_date = WrapTime(54321);
client_state.session_consistency_country = "US";
client_state.permanent_consistency_country = "CA";
+ base::Time fetch_time = WrapTime(99999);
TestingPrefServiceSimple prefs;
VariationsSeedStore::RegisterPrefs(prefs.registry());
@@ -292,13 +632,14 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_EmptySeed) {
prefs.SetString(prefs::kVariationsSafeSeedLocale, "en-US");
prefs.SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry, "CA");
prefs.SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry, "US");
- prefs.SetInt64(prefs::kVariationsSafeSeedDate, 12345);
+ prefs.SetTime(prefs::kVariationsSafeSeedDate, WrapTime(12345));
+ prefs.SetTime(prefs::kVariationsSafeSeedFetchTime, WrapTime(34567));
TestVariationsSeedStore seed_store(&prefs);
base::HistogramTester histogram_tester;
- EXPECT_FALSE(
- seed_store.StoreSafeSeed(serialized_seed, signature, client_state));
+ EXPECT_FALSE(seed_store.StoreSafeSeed(serialized_seed, signature,
+ client_state, fetch_time));
// Verify that none of the prefs were overwritten.
EXPECT_EQ("a seed", prefs.GetString(prefs::kVariationsSafeCompressedSeed));
@@ -309,7 +650,9 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_EmptySeed) {
prefs::kVariationsSafeSeedPermanentConsistencyCountry));
EXPECT_EQ("US", prefs.GetString(
prefs::kVariationsSafeSeedSessionConsistencyCountry));
- EXPECT_EQ(12345, prefs.GetInt64(prefs::kVariationsSafeSeedDate));
+ EXPECT_EQ(WrapTime(12345), prefs.GetTime(prefs::kVariationsSafeSeedDate));
+ EXPECT_EQ(WrapTime(34567),
+ prefs.GetTime(prefs::kVariationsSafeSeedFetchTime));
// Verify metrics.
histogram_tester.ExpectUniqueSample(
@@ -322,10 +665,10 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_InvalidSeed) {
const std::string signature = "a completely ignored signature";
ClientFilterableState client_state;
client_state.locale = "en-US";
- client_state.reference_date =
- base::Time() + base::TimeDelta::FromMicroseconds(12345);
+ client_state.reference_date = WrapTime(12345);
client_state.session_consistency_country = "US";
client_state.permanent_consistency_country = "CA";
+ base::Time fetch_time = WrapTime(54321);
TestingPrefServiceSimple prefs;
VariationsSeedStore::RegisterPrefs(prefs.registry());
@@ -334,13 +677,14 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_InvalidSeed) {
prefs.SetString(prefs::kVariationsSafeSeedLocale, "en-CA");
prefs.SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry, "IN");
prefs.SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry, "MX");
- prefs.SetInt64(prefs::kVariationsSafeSeedDate, 67890);
+ prefs.SetTime(prefs::kVariationsSafeSeedDate, WrapTime(67890));
+ prefs.SetTime(prefs::kVariationsSafeSeedFetchTime, WrapTime(13579));
SignatureVerifyingVariationsSeedStore seed_store(&prefs);
base::HistogramTester histogram_tester;
- EXPECT_FALSE(
- seed_store.StoreSafeSeed(serialized_seed, signature, client_state));
+ EXPECT_FALSE(seed_store.StoreSafeSeed(serialized_seed, signature,
+ client_state, fetch_time));
// Verify that none of the prefs were overwritten.
EXPECT_EQ("a previous seed",
@@ -352,7 +696,9 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_InvalidSeed) {
prefs::kVariationsSafeSeedPermanentConsistencyCountry));
EXPECT_EQ("MX", prefs.GetString(
prefs::kVariationsSafeSeedSessionConsistencyCountry));
- EXPECT_EQ(67890, prefs.GetInt64(prefs::kVariationsSafeSeedDate));
+ EXPECT_EQ(WrapTime(67890), prefs.GetTime(prefs::kVariationsSafeSeedDate));
+ EXPECT_EQ(WrapTime(13579),
+ prefs.GetTime(prefs::kVariationsSafeSeedFetchTime));
// Verify metrics.
histogram_tester.ExpectUniqueSample(
@@ -367,10 +713,10 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_InvalidSignature) {
const std::string signature = kBase64SeedSignature;
ClientFilterableState client_state;
client_state.locale = "en-US";
- client_state.reference_date =
- base::Time() + base::TimeDelta::FromMicroseconds(12345);
+ client_state.reference_date = WrapTime(12345);
client_state.session_consistency_country = "US";
client_state.permanent_consistency_country = "CA";
+ const base::Time fetch_time = WrapTime(34567);
TestingPrefServiceSimple prefs;
VariationsSeedStore::RegisterPrefs(prefs.registry());
@@ -379,13 +725,14 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_InvalidSignature) {
prefs.SetString(prefs::kVariationsSafeSeedLocale, "en-CA");
prefs.SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry, "IN");
prefs.SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry, "MX");
- prefs.SetInt64(prefs::kVariationsSafeSeedDate, 67890);
+ prefs.SetTime(prefs::kVariationsSafeSeedDate, WrapTime(67890));
+ prefs.SetTime(prefs::kVariationsSafeSeedFetchTime, WrapTime(24680));
SignatureVerifyingVariationsSeedStore seed_store(&prefs);
base::HistogramTester histogram_tester;
- EXPECT_FALSE(
- seed_store.StoreSafeSeed(serialized_seed, signature, client_state));
+ EXPECT_FALSE(seed_store.StoreSafeSeed(serialized_seed, signature,
+ client_state, fetch_time));
// Verify that none of the prefs were overwritten.
EXPECT_EQ("a previous seed",
@@ -397,7 +744,9 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_InvalidSignature) {
prefs::kVariationsSafeSeedPermanentConsistencyCountry));
EXPECT_EQ("MX", prefs.GetString(
prefs::kVariationsSafeSeedSessionConsistencyCountry));
- EXPECT_EQ(67890, prefs.GetInt64(prefs::kVariationsSafeSeedDate));
+ EXPECT_EQ(WrapTime(67890), prefs.GetTime(prefs::kVariationsSafeSeedDate));
+ EXPECT_EQ(WrapTime(24680),
+ prefs.GetTime(prefs::kVariationsSafeSeedFetchTime));
// Verify metrics.
histogram_tester.ExpectUniqueSample(
@@ -415,18 +764,18 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_ValidSignature) {
const std::string signature = kBase64SeedSignature;
ClientFilterableState client_state;
client_state.locale = "en-US";
- client_state.reference_date =
- base::Time() + base::TimeDelta::FromMicroseconds(12345);
+ client_state.reference_date = WrapTime(12345);
client_state.session_consistency_country = "US";
client_state.permanent_consistency_country = "CA";
+ const base::Time fetch_time = WrapTime(34567);
TestingPrefServiceSimple prefs;
VariationsSeedStore::RegisterPrefs(prefs.registry());
SignatureVerifyingVariationsSeedStore seed_store(&prefs);
base::HistogramTester histogram_tester;
- EXPECT_TRUE(
- seed_store.StoreSafeSeed(serialized_seed, signature, client_state));
+ EXPECT_TRUE(seed_store.StoreSafeSeed(serialized_seed, signature, client_state,
+ fetch_time));
// Verify the stored data.
std::string loaded_compressed_seed =
@@ -437,7 +786,9 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_ValidSignature) {
EXPECT_EQ(Compress(serialized_seed), decoded_compressed_seed);
EXPECT_EQ(signature, prefs.GetString(prefs::kVariationsSafeSeedSignature));
EXPECT_EQ("en-US", prefs.GetString(prefs::kVariationsSafeSeedLocale));
- EXPECT_EQ(12345, prefs.GetInt64(prefs::kVariationsSafeSeedDate));
+ EXPECT_EQ(WrapTime(12345), prefs.GetTime(prefs::kVariationsSafeSeedDate));
+ EXPECT_EQ(WrapTime(34567),
+ prefs.GetTime(prefs::kVariationsSafeSeedFetchTime));
EXPECT_EQ("US", prefs.GetString(
prefs::kVariationsSafeSeedSessionConsistencyCountry));
EXPECT_EQ("CA", prefs.GetString(
@@ -451,6 +802,112 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_ValidSignature) {
VerifySignatureResult::VALID_SIGNATURE, 1);
}
+TEST(VariationsSeedStoreTest, StoreSafeSeed_IdenticalToLatestSeed) {
+ const VariationsSeed seed = CreateTestSeed();
+ const std::string serialized_seed = SerializeSeed(seed);
+ const std::string base64_seed = SerializeSeedBase64(seed);
+ const std::string signature = "a completely ignored signature";
+ ClientFilterableState unused_client_state;
+ const base::Time fetch_time = WrapTime(12345);
+
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+ prefs.SetString(prefs::kVariationsCompressedSeed, base64_seed);
+ prefs.SetTime(prefs::kVariationsLastFetchTime, WrapTime(99999));
+
+ TestVariationsSeedStore seed_store(&prefs);
+ base::HistogramTester histogram_tester;
+ EXPECT_TRUE(seed_store.StoreSafeSeed(serialized_seed, signature,
+ unused_client_state, fetch_time));
+
+ // Verify the latest seed value was migrated to a sentinel value, rather than
+ // the full string.
+ EXPECT_EQ(kIdenticalToSafeSeedSentinel,
+ prefs.GetString(prefs::kVariationsCompressedSeed));
+
+ // Verify that loading the stored seed returns the original seed value.
+ VariationsSeed loaded_seed;
+ std::string loaded_seed_data;
+ std::string unused_loaded_base64_seed_signature;
+ EXPECT_TRUE(seed_store.LoadSeed(&loaded_seed, &loaded_seed_data,
+ &unused_loaded_base64_seed_signature));
+
+ EXPECT_EQ(SerializeSeed(seed), SerializeSeed(loaded_seed));
+ EXPECT_EQ(SerializeSeed(seed), loaded_seed_data);
+
+ // Verify that the safe seed prefs indeed contain the serialized seed value
+ // and that the last fetch time was copied from the latest seed.
+ EXPECT_EQ(base64_seed, prefs.GetString(prefs::kVariationsSafeCompressedSeed));
+ VariationsSeed loaded_safe_seed;
+ base::Time loaded_fetch_time;
+ EXPECT_TRUE(seed_store.LoadSafeSeed(&loaded_safe_seed, &unused_client_state,
+ &loaded_fetch_time));
+ EXPECT_EQ(SerializeSeed(seed), SerializeSeed(loaded_safe_seed));
+ EXPECT_EQ(WrapTime(99999), loaded_fetch_time);
+
+ // Verify metrics.
+ histogram_tester.ExpectUniqueSample(
+ "Variations.SafeMode.StoreSafeSeed.Result", StoreSeedResult::SUCCESS, 1);
+}
+
+TEST(VariationsSeedStoreTest, StoreSafeSeed_PreviouslyIdenticalToLatestSeed) {
+ // Create two distinct seeds: an old one saved as both the safe and the latest
+ // seed value, and a new one that should overwrite only the stored safe seed
+ // value.
+ const VariationsSeed old_seed = CreateTestSeed();
+ VariationsSeed new_seed = CreateTestSeed();
+ new_seed.set_serial_number("12345678");
+ ASSERT_NE(SerializeSeed(old_seed), SerializeSeed(new_seed));
+
+ const std::string serialized_old_seed = SerializeSeed(old_seed);
+ const std::string base64_old_seed = SerializeSeedBase64(old_seed);
+ const std::string serialized_new_seed = SerializeSeed(new_seed);
+ const std::string base64_new_seed = SerializeSeedBase64(new_seed);
+ const std::string signature = "a completely ignored signature";
+ const base::Time fetch_time = WrapTime(12345);
+ ClientFilterableState unused_client_state;
+
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+ prefs.SetString(prefs::kVariationsSafeCompressedSeed, base64_old_seed);
+ prefs.SetString(prefs::kVariationsCompressedSeed,
+ kIdenticalToSafeSeedSentinel);
+
+ TestVariationsSeedStore seed_store(&prefs);
+ base::HistogramTester histogram_tester;
+ EXPECT_TRUE(seed_store.StoreSafeSeed(serialized_new_seed, signature,
+ unused_client_state, fetch_time));
+
+ // Verify the latest seed value was copied before the safe seed was
+ // overwritten.
+ EXPECT_EQ(base64_old_seed, prefs.GetString(prefs::kVariationsCompressedSeed));
+
+ // Verify that loading the stored seed returns the old seed value.
+ VariationsSeed loaded_seed;
+ std::string loaded_seed_data;
+ std::string unused_loaded_base64_seed_signature;
+ EXPECT_TRUE(seed_store.LoadSeed(&loaded_seed, &loaded_seed_data,
+ &unused_loaded_base64_seed_signature));
+
+ EXPECT_EQ(SerializeSeed(old_seed), SerializeSeed(loaded_seed));
+ EXPECT_EQ(SerializeSeed(old_seed), loaded_seed_data);
+
+ // Verify that the safe seed prefs indeed contain the new seed's serialized
+ // value.
+ EXPECT_EQ(base64_new_seed,
+ prefs.GetString(prefs::kVariationsSafeCompressedSeed));
+ VariationsSeed loaded_safe_seed;
+ base::Time loaded_fetch_time;
+ EXPECT_TRUE(seed_store.LoadSafeSeed(&loaded_safe_seed, &unused_client_state,
+ &loaded_fetch_time));
+ EXPECT_EQ(SerializeSeed(new_seed), SerializeSeed(loaded_safe_seed));
+ EXPECT_EQ(fetch_time, loaded_fetch_time);
+
+ // Verify metrics.
+ histogram_tester.ExpectUniqueSample(
+ "Variations.SafeMode.StoreSafeSeed.Result", StoreSeedResult::SUCCESS, 1);
+}
+
TEST(VariationsSeedStoreTest, StoreSeedData_GzippedEmptySeed) {
std::string empty_seed;
std::string compressed_seed;
@@ -620,6 +1077,52 @@ TEST(VariationsSeedStoreTest, ApplyDeltaPatch) {
EXPECT_EQ(after_seed_data, output);
}
+TEST(VariationsSeedStoreTest, LastFetchTime_DistinctSeeds) {
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+ prefs.SetString(prefs::kVariationsCompressedSeed, "one");
+ prefs.SetString(prefs::kVariationsSafeCompressedSeed, "not one");
+ prefs.SetTime(prefs::kVariationsLastFetchTime, WrapTime(1));
+ prefs.SetTime(prefs::kVariationsSafeSeedFetchTime, WrapTime(0));
+
+ base::Time start_time = base::Time::Now();
+ TestVariationsSeedStore seed_store(&prefs);
+ seed_store.RecordLastFetchTime();
+
+ // Verify that the last fetch time was updated.
+ const base::Time last_fetch_time =
+ prefs.GetTime(prefs::kVariationsLastFetchTime);
+ EXPECT_NE(WrapTime(1), last_fetch_time);
+ EXPECT_GE(last_fetch_time, start_time);
+
+ // Verify that the safe seed's fetch time was *not* updated.
+ EXPECT_EQ(WrapTime(0), prefs.GetTime(prefs::kVariationsSafeSeedFetchTime));
+}
+
+TEST(VariationsSeedStoreTest, LastFetchTime_IdenticalSeeds) {
+ TestingPrefServiceSimple prefs;
+ VariationsSeedStore::RegisterPrefs(prefs.registry());
+ prefs.SetString(prefs::kVariationsSafeCompressedSeed, "some seed");
+ prefs.SetString(prefs::kVariationsCompressedSeed,
+ kIdenticalToSafeSeedSentinel);
+ prefs.SetTime(prefs::kVariationsLastFetchTime, WrapTime(1));
+ prefs.SetTime(prefs::kVariationsSafeSeedFetchTime, WrapTime(0));
+
+ base::Time start_time = base::Time::Now();
+ TestVariationsSeedStore seed_store(&prefs);
+ seed_store.RecordLastFetchTime();
+
+ // Verify that the last fetch time was updated.
+ const base::Time last_fetch_time =
+ prefs.GetTime(prefs::kVariationsLastFetchTime);
+ EXPECT_NE(WrapTime(1), last_fetch_time);
+ EXPECT_GE(last_fetch_time, start_time);
+
+ // Verify that the safe seed's fetch time *was* also updated.
+ EXPECT_EQ(last_fetch_time,
+ prefs.GetTime(prefs::kVariationsSafeSeedFetchTime));
+}
+
TEST(VariationsSeedStoreTest, GetLatestSerialNumber_LoadsInitialValue) {
// Store good seed data to test if loading from prefs works.
const VariationsSeed seed = CreateTestSeed();
diff --git a/chromium/components/vector_icons/README.md b/chromium/components/vector_icons/README.md
index e8922c4161a..2fc3b3d5bae 100644
--- a/chromium/components/vector_icons/README.md
+++ b/chromium/components/vector_icons/README.md
@@ -14,10 +14,14 @@ Some of the icons have **.1x.icon** variants which are used when the device scal
[This tool](http://evanstade.github.io/skiafy/) generates .icon file output from SVGs. (If you want to contribute improvements, [here's the project](https://github.com/evanstade/skiafy).)
-It handles only a small subset of SVG (paths, circles, etc.) and it's finicky about what it expects as the format, but with a minor amount of manual intervention beforehand, it mostly spits out usable .icon output. It will often work better if you run the SVG through SVGO first, which is a separate project (an SVG minifier). [Jake Archibald's SVGOMG](https://jakearchibald.github.io/svgomg/) is a web interface to SVGO. If any manual adjustments need to be made to the output, the [SVG Path spec](https://www.w3.org/TR/SVG/paths.html) is a helpful reference.
+It handles only a small subset of SVG (paths, circles, etc.) and it's finicky about what it expects as the format, but with a minor amount of manual intervention beforehand, it mostly spits out usable .icon output. It will often work better if you run the SVG through SVGO first, which is a separate project (an SVG minifier). [Jake Archibald's SVGOMG](https://jakearchibald.github.io/svgomg/) is a web interface to SVGO. If any manual adjustments need to be made to the output, the [SVG Path spec](https://www.w3.org/TR/SVG/paths.html) is a helpful reference; compare with the relevant [Chromium drawing commands](https://cs.chromium.org/chromium/src/ui/gfx/vector_icon_types.h?rcl=b9bf332694f083c6767416b69d0f8539d1c44707&l=22).
Some SVGs are already pretty minimal, like the ones at [the Material Design Icon repository](https://material.io/icons/) so they don't require much if any adjustment, but some SVG editing tools like Sketch leave a lot of random cruft so SVGOMG helps a lot. Take the output and insert into a .icon file.
+### Troubleshooting icon generation
+
++ **My colors are inverted!** There is probably a surplus square path encompassing your icon. For example, `<path d="M0 0h16v16H0z"/>`. Delete this and try again.
+
## Using .icon files
Once you have created an .icon file, place it in an appropriate vector_icon subdirectory and add the filename to the corresponding BUILD.gn. A constant is automatically generated so that the icon can be referenced at runtime. The icon file foo_bar.icon is mapped to the constant name of kFooBarIcon ('k' + camel-cased filename + 'Icon') and a sample call site to create this icon looks something like:
diff --git a/chromium/components/vector_icons/aggregate_vector_icons.py b/chromium/components/vector_icons/aggregate_vector_icons.py
index 87aa1bea0f6..c48a34932e2 100644
--- a/chromium/components/vector_icons/aggregate_vector_icons.py
+++ b/chromium/components/vector_icons/aggregate_vector_icons.py
@@ -124,10 +124,13 @@ def AggregateVectorIcons(working_directory, file_list, output_cc, output_h):
CamelCase(icon_name, "Path1x"), vector_commands_1x))
# Define the value of kFooBarIcon.
- third_arg = "nullptr" if vector_commands_1x is None else CamelCase(
- icon_name, "Path1x")
- output_cc.write("VECTOR_ICON_TEMPLATE({}, {}, {})\n".format(CamelCase(
- icon_name, "Icon"), CamelCase(icon_name, "Path"), third_arg))
+ if vector_commands_1x is None:
+ output_cc.write("VECTOR_ICON_TEMPLATE({}, {})\n".format(CamelCase(
+ icon_name, "Icon"), CamelCase(icon_name, "Path")))
+ else:
+ output_cc.write("VECTOR_ICON_TEMPLATE2({}, {}, {})\n".format(CamelCase(
+ icon_name, "Icon"), CamelCase(icon_name, "Path"), CamelCase(
+ icon_name, "Path1x")))
output_cc.close()
diff --git a/chromium/components/vector_icons/cc_macros.h b/chromium/components/vector_icons/cc_macros.h
new file mode 100644
index 00000000000..6ba0c245a44
--- /dev/null
+++ b/chromium/components/vector_icons/cc_macros.h
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VECTOR_ICONS_CC_MACROS_H_
+#define COMPONENTS_VECTOR_ICONS_CC_MACROS_H_
+
+// This file holds macros that are common to each vector icon target's
+// vector_icons.cc.template file.
+
+// The prefix is used to help make sure the string IDs are unique. Typically,
+// matching the namespace of the icons should ensure that is the case. If the
+// vector_icons.cc.template file doesn't define a prefix, we'll go without one.
+#ifndef VECTOR_ICON_ID_PREFIX
+#define VECTOR_ICON_ID_PREFIX ""
+#endif
+
+#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
+ static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
+
+// The VectorIcon will be called kMyIcon, and the identifier for the icon might
+// be "my_namespace::kMyIconId".
+#define VECTOR_ICON_TEMPLATE(icon_name, path_name) \
+ const char icon_name##Id[] = VECTOR_ICON_ID_PREFIX #icon_name; \
+ const gfx::VectorIcon icon_name = {path_name, arraysize(path_name), nullptr, \
+ 0u, icon_name##Id};
+
+#define VECTOR_ICON_TEMPLATE2(icon_name, path_name, path_name_1x) \
+ const char icon_name##Id[] = VECTOR_ICON_ID_PREFIX #icon_name; \
+ const gfx::VectorIcon icon_name = {path_name, arraysize(path_name), \
+ path_name_1x, arraysize(path_name_1x), \
+ icon_name##Id};
+
+#else // !COMPONENTS_VECTOR_ICONS_CC_MACROS_H_
+#error This file should only be included once.
+#endif // COMPONENTS_VECTOR_ICONS_CC_MACROS_H_
diff --git a/chromium/components/vector_icons/vector_icons.cc.template b/chromium/components/vector_icons/vector_icons.cc.template
index 4a965b1c219..7cb101277d7 100644
--- a/chromium/components/vector_icons/vector_icons.cc.template
+++ b/chromium/components/vector_icons/vector_icons.cc.template
@@ -10,11 +10,7 @@
#include "base/logging.h"
#include "ui/gfx/vector_icon_types.h"
-#define PATH_ELEMENT_TEMPLATE(path_name, ...) \
-static constexpr gfx::PathElement path_name[] = {__VA_ARGS__};
-
-#define VECTOR_ICON_TEMPLATE(icon_name, path_name, path_name_1x) \
-const gfx::VectorIcon icon_name = { path_name , path_name_1x };
+#include "components/vector_icons/cc_macros.h"
namespace vector_icons {
diff --git a/chromium/components/vector_icons/vector_icons.gni b/chromium/components/vector_icons/vector_icons.gni
index e1a36481074..b8ba375a6c4 100644
--- a/chromium/components/vector_icons/vector_icons.gni
+++ b/chromium/components/vector_icons/vector_icons.gni
@@ -40,7 +40,9 @@ template("aggregate_vector_icons") {
"vector_icons.cc.template",
"vector_icons.h.template",
]
- inputs = rebase_path(templates + invoker.icons, ".", invoker.icon_directory)
+ inputs =
+ rebase_path(templates + invoker.icons, ".", invoker.icon_directory) +
+ [ "//components/vector_icons/aggregate_vector_icons.py" ]
outputs = [
output_cc,
diff --git a/chromium/components/version_info/BUILD.gn b/chromium/components/version_info/BUILD.gn
index 17b24f412ae..8fbad36091b 100644
--- a/chromium/components/version_info/BUILD.gn
+++ b/chromium/components/version_info/BUILD.gn
@@ -47,8 +47,6 @@ static_library("version_string") {
source_set("channel") {
sources = [
"channel.h",
- "channel_android.cc",
- "channel_android.h",
]
}
diff --git a/chromium/components/version_info/DEPS b/chromium/components/version_info/DEPS
index 060155c2707..96b3c130b00 100644
--- a/chromium/components/version_info/DEPS
+++ b/chromium/components/version_info/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+components/strings/grit/components_strings.h",
+ "+jni",
"+ui/base",
# version_info is used on iOS and thus cannot depend on //content.
diff --git a/chromium/components/version_info/android/BUILD.gn b/chromium/components/version_info/android/BUILD.gn
new file mode 100644
index 00000000000..3d5ee8479e4
--- /dev/null
+++ b/chromium/components/version_info/android/BUILD.gn
@@ -0,0 +1,73 @@
+# Copyright 2018 The Chromium 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/rules.gni")
+import("//build/config/zip.gni")
+import("//build/util/process_version.gni")
+import("//chrome/android/channel.gni")
+
+# Depend on this on the Java side to get org.components.version_info.Channel and
+# org.components.version_info.VersionConstants.
+android_library("version_constants_java") {
+ java_files = [
+ "java/src/org/chromium/components/version_info/VersionConstantsBridge.java",
+ ]
+ deps = [
+ "//base:base_java",
+ ]
+ srcjar_deps = [
+ ":channel_enum_srcjar",
+ ":version_constants_srcjar",
+ ]
+}
+
+# Depend on this on the native side to get version_info::GetChannel. It requires
+# version_constants_java for its JNI call.
+static_library("channel_getter") {
+ sources = [
+ "channel_getter.cc",
+ "channel_getter.h",
+ ]
+ deps = [
+ ":version_constants_bridge_jni",
+ "..:channel",
+ ]
+}
+
+java_cpp_enum("channel_enum_srcjar") {
+ sources = [
+ "../channel.h",
+ ]
+}
+
+version_constants_java_file = "$target_gen_dir/java/org/chromium/components/version_info/VersionConstants.java"
+zip("version_constants_srcjar") {
+ inputs = [
+ version_constants_java_file,
+ ]
+ output = "$target_gen_dir/$target_name.srcjar"
+ base_dir = "$target_gen_dir/java"
+ deps = [
+ ":generate_version_constants_java",
+ ]
+}
+
+process_version("generate_version_constants_java") {
+ template_file = "java/VersionConstants.java.version"
+ output = version_constants_java_file
+ sources = [
+ "//chrome/VERSION",
+ ]
+ extra_args = [
+ "-e",
+ "CHANNEL=str.upper('$android_channel')",
+ ]
+}
+
+generate_jni("version_constants_bridge_jni") {
+ sources = [
+ "java/src/org/chromium/components/version_info/VersionConstantsBridge.java",
+ ]
+ jni_package = "version_constants_bridge"
+}
diff --git a/chromium/components/version_info/android/OWNERS b/chromium/components/version_info/android/OWNERS
new file mode 100644
index 00000000000..ed649bee395
--- /dev/null
+++ b/chromium/components/version_info/android/OWNERS
@@ -0,0 +1,2 @@
+paulmiller@chromium.org
+torne@chromium.org
diff --git a/chromium/components/version_info/android/channel_getter.cc b/chromium/components/version_info/android/channel_getter.cc
new file mode 100644
index 00000000000..56241077d41
--- /dev/null
+++ b/chromium/components/version_info/android/channel_getter.cc
@@ -0,0 +1,16 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/version_info/android/channel_getter.h"
+
+#include "jni/VersionConstantsBridge_jni.h"
+
+namespace version_info {
+
+Channel GetChannel() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ return static_cast<Channel>(Java_VersionConstantsBridge_getChannel(env));
+}
+
+} // namespace version_info
diff --git a/chromium/components/version_info/android/channel_getter.h b/chromium/components/version_info/android/channel_getter.h
new file mode 100644
index 00000000000..1345dedd539
--- /dev/null
+++ b/chromium/components/version_info/android/channel_getter.h
@@ -0,0 +1,16 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VERSION_INFO_ANDROID_CHANNEL_GETTER_H_
+#define COMPONENTS_VERSION_INFO_ANDROID_CHANNEL_GETTER_H_
+
+#include "components/version_info/channel.h"
+
+namespace version_info {
+
+Channel GetChannel();
+
+}
+
+#endif // COMPONENTS_VERSION_INFO_ANDROID_CHANNEL_GETTER_H_
diff --git a/chromium/components/version_info/android/java/VersionConstants.java.version b/chromium/components/version_info/android/java/VersionConstants.java.version
new file mode 100644
index 00000000000..6bbce43c534
--- /dev/null
+++ b/chromium/components/version_info/android/java/VersionConstants.java.version
@@ -0,0 +1,17 @@
+// Copyright 2018 The Chromium 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.version_info;
+
+// Constants shared by Android Chrome and WebView. Chrome specific constants are
+// in ChromeVersionConstants.
+public class VersionConstants {
+ public static final String PRODUCT_VERSION = "@MAJOR@.@MINOR@.@BUILD@.@PATCH@";
+ @SuppressWarnings({"ComplexBooleanConstant", "IdentityBinaryExpression"})
+ public static final boolean IS_OFFICIAL_BUILD = @OFFICIAL_BUILD@ == 1;
+
+ public static final int PRODUCT_MAJOR_VERSION = @MAJOR@;
+
+ public static final int CHANNEL = Channel.@CHANNEL@;
+}
diff --git a/chromium/components/version_info/channel.h b/chromium/components/version_info/channel.h
index d3c48840d51..8df5ef93ec9 100644
--- a/chromium/components/version_info/channel.h
+++ b/chromium/components/version_info/channel.h
@@ -8,7 +8,17 @@
namespace version_info {
// The possible channels for an installation, from most fun to most stable.
-enum class Channel { UNKNOWN = 0, CANARY, DEV, BETA, STABLE };
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.version_info
+enum class Channel {
+ UNKNOWN = 0,
+ // DEFAULT is an alias for UNKNOWN because the build files use DEFAULT but the
+ // code uses UNKNOWN. TODO(paulmiller): Combine DEFAULT & UNKNOWN.
+ DEFAULT = UNKNOWN,
+ CANARY = 1,
+ DEV = 2,
+ BETA = 3,
+ STABLE = 4,
+};
} // namespace version_info
diff --git a/chromium/components/version_info/channel_android.cc b/chromium/components/version_info/channel_android.cc
deleted file mode 100644
index 4e1cd4700d7..00000000000
--- a/chromium/components/version_info/channel_android.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/version_info/channel_android.h"
-
-#include <cstring>
-
-namespace version_info {
-
-Channel ChannelFromPackageName(const char* package_name) {
- if (!strcmp(package_name, "com.android.chrome"))
- return Channel::STABLE;
- if (!strcmp(package_name, "com.chrome.beta"))
- return Channel::BETA;
- if (!strcmp(package_name, "com.chrome.dev"))
- return Channel::DEV;
- if (!strcmp(package_name, "com.chrome.canary"))
- return Channel::CANARY;
-
- return Channel::UNKNOWN;
-}
-
-} // namespace version_info
diff --git a/chromium/components/version_info/channel_android.h b/chromium/components/version_info/channel_android.h
deleted file mode 100644
index d4e5cf2002f..00000000000
--- a/chromium/components/version_info/channel_android.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VERSION_INFO_CHANNEL_ANDROID_H_
-#define COMPONENTS_VERSION_INFO_CHANNEL_ANDROID_H_
-
-#include "components/version_info/channel.h"
-
-namespace version_info {
-
-// Determine channel based on Chrome's package name.
-Channel ChannelFromPackageName(const char* package_name);
-
-} // namespace version_info
-
-#endif // COMPONENTS_VERSION_INFO_CHANNEL_ANDROID_H_
diff --git a/chromium/components/version_ui/BUILD.gn b/chromium/components/version_ui/BUILD.gn
index 91b80b27a72..84b0b00a366 100644
--- a/chromium/components/version_ui/BUILD.gn
+++ b/chromium/components/version_ui/BUILD.gn
@@ -13,5 +13,6 @@ static_library("version_ui") {
deps = [
"//base",
"//components/variations",
+ "//components/variations/net",
]
}
diff --git a/chromium/components/version_ui/resources/about_version.css b/chromium/components/version_ui/resources/about_version.css
index 6ac70ed9037..2e744ed596d 100644
--- a/chromium/components/version_ui/resources/about_version.css
+++ b/chromium/components/version_ui/resources/about_version.css
@@ -13,7 +13,8 @@ body {
margin-left: auto;
margin-right: auto;
margin-top: 10px;
- width: 800px;
+ min-width: 800px;
+ width: 60%;
}
#inner {
@@ -61,3 +62,10 @@ body {
padding-left: 5px;
vertical-align: bottom;
}
+
+.version-wide {
+ font-family: monospace;
+ max-width: auto;
+ padding-left: 5px;
+ vertical-align: bottom;
+}
diff --git a/chromium/components/version_ui/resources/about_version.html b/chromium/components/version_ui/resources/about_version.html
index c19c5f87a04..b4fcf4cb9ba 100644
--- a/chromium/components/version_ui/resources/about_version.html
+++ b/chromium/components/version_ui/resources/about_version.html
@@ -136,6 +136,10 @@ about:version template page
<td class="label">$i18n{variations_name}</td>
<td class="version" id="variations-list"></td>
</tr>
+ <tr id="variations-cmd-section" hidden>
+ <td class="label">$i18n{variations_cmd_name}</td>
+ <td class="version-wide" id="variations-cmd"></td>
+ </tr>
<if expr="is_win">
<tr id="compiler-section">
<td class="label">Compiler</td>
diff --git a/chromium/components/version_ui/resources/about_version.js b/chromium/components/version_ui/resources/about_version.js
index ca2076f31e6..54b6b0089ca 100644
--- a/chromium/components/version_ui/resources/about_version.js
+++ b/chromium/components/version_ui/resources/about_version.js
@@ -15,6 +15,17 @@ function returnVariationInfo(variationsList) {
}
/**
+ * Callback from the backend with the variations formatted as command line
+ * input. This call will build the variations-cmd section of the version page
+ * if needed.
+ * @param {string} variationsCmd The variations info in command line format.
+ */
+function returnVariationCmd(variationsCmd) {
+ $('variations-cmd-section').hidden = !variationsCmd;
+ $('variations-cmd').textContent = variationsCmd;
+}
+
+/**
* Callback from the backend with the executable and profile paths to display.
* @param {string} execPath The executable path to display.
* @param {string} profilePath The profile path to display.
diff --git a/chromium/components/version_ui/resources/about_version_mobile.css b/chromium/components/version_ui/resources/about_version_mobile.css
index b084d149c29..8a8083cc8c6 100644
--- a/chromium/components/version_ui/resources/about_version_mobile.css
+++ b/chromium/components/version_ui/resources/about_version_mobile.css
@@ -3,6 +3,7 @@
* found in the LICENSE file. */
#outer {
+ min-width: 0; /* Wrap content to screen on mobile. */
text-align: left;
width: 90%;
}
diff --git a/chromium/components/version_ui/version_handler_helper.cc b/chromium/components/version_ui/version_handler_helper.cc
index 6bdc949bf61..0f62928ae16 100644
--- a/chromium/components/version_ui/version_handler_helper.cc
+++ b/chromium/components/version_ui/version_handler_helper.cc
@@ -7,11 +7,13 @@
#include <utility>
#include <vector>
+#include "base/base_switches.h"
#include "base/metrics/field_trial.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "components/variations/active_field_trials.h"
+#include "components/variations/net/variations_command_line.h"
namespace version_ui {
@@ -44,4 +46,8 @@ std::unique_ptr<base::Value> GetVariationsList() {
return std::move(variations_list);
}
+base::Value GetVariationsCommandLineAsValue() {
+ return base::Value(variations::GetVariationsCommandLine());
+}
+
} // namespace version_ui
diff --git a/chromium/components/version_ui/version_handler_helper.h b/chromium/components/version_ui/version_handler_helper.h
index 697049ecd92..aa19132ada0 100644
--- a/chromium/components/version_ui/version_handler_helper.h
+++ b/chromium/components/version_ui/version_handler_helper.h
@@ -16,6 +16,10 @@ namespace version_ui {
// Returns the list of variations to be displayed on the chrome:://version page.
std::unique_ptr<base::Value> GetVariationsList();
+// Returns the variations information in command line format to be displayed on
+// the chrome:://version page.
+base::Value GetVariationsCommandLineAsValue();
+
} // namespace version_ui
#endif // COMPONENTS_VERSION_UI_VERSION_HANDLER_HELPER_H_
diff --git a/chromium/components/version_ui/version_ui_constants.cc b/chromium/components/version_ui/version_ui_constants.cc
index f482a465c36..b11022ac3f6 100644
--- a/chromium/components/version_ui/version_ui_constants.cc
+++ b/chromium/components/version_ui/version_ui_constants.cc
@@ -15,6 +15,7 @@ const char kRequestVersionInfo[] = "requestVersionInfo";
const char kReturnFilePaths[] = "returnFilePaths";
const char kReturnFlashVersion[] = "returnFlashVersion";
const char kReturnVariationInfo[] = "returnVariationInfo";
+const char kReturnVariationCmd[] = "returnVariationCmd";
// Strings.
const char kApplicationLabel[] = "application_label";
@@ -69,7 +70,9 @@ const char kRevision[] = "revision";
const char kTitle[] = "title";
const char kUserAgent[] = "useragent";
const char kUserAgentName[] = "user_agent_name";
+const char kVariationsCmdName[] = "variations_cmd_name";
const char kVariationsName[] = "variations_name";
+const char kVariationsShowCmdQuery[] = "show-variations-cmd";
const char kVersion[] = "version";
const char kVersionBitSize[] = "version_bitsize";
const char kVersionModifier[] = "version_modifier";
diff --git a/chromium/components/version_ui/version_ui_constants.h b/chromium/components/version_ui/version_ui_constants.h
index 186ba51e65e..fea46c006a4 100644
--- a/chromium/components/version_ui/version_ui_constants.h
+++ b/chromium/components/version_ui/version_ui_constants.h
@@ -20,6 +20,7 @@ extern const char kRequestVersionInfo[];
extern const char kReturnFilePaths[];
extern const char kReturnFlashVersion[];
extern const char kReturnVariationInfo[];
+extern const char kReturnVariationCmd[];
// Strings.
// Must match the constants used in the resource files.
@@ -75,7 +76,9 @@ extern const char kRevision[];
extern const char kTitle[];
extern const char kUserAgent[];
extern const char kUserAgentName[];
+extern const char kVariationsCmdName[];
extern const char kVariationsName[];
+extern const char kVariationsShowCmdQuery[];
extern const char kVersion[];
extern const char kVersionBitSize[];
extern const char kVersionModifier[];
diff --git a/chromium/components/version_ui_strings.grdp b/chromium/components/version_ui_strings.grdp
index 72925ab1291..6278a8a380d 100644
--- a/chromium/components/version_ui_strings.grdp
+++ b/chromium/components/version_ui_strings.grdp
@@ -55,6 +55,9 @@
<message name="IDS_VERSION_UI_VARIATIONS" desc="label for the variations list on the about:version page">
Variations
</message>
+ <message name="IDS_VERSION_UI_VARIATIONS_CMD" desc="label for the variations information in command-line format on the about:version page">
+ Command-line variations
+ </message>
<if expr="is_win">
<message translateable="false" name="IDS_VERSION_UI_COHORT_NAME" desc="Update cohort substring included in the version number line on the about:version page.">
(cohort: <ph name="UPDATE_COHORT_NAME">$1<ex>Stable</ex></ph>)
diff --git a/chromium/components/visitedlink/browser/visitedlink_master.cc b/chromium/components/visitedlink/browser/visitedlink_master.cc
index 1ce0342a236..74158129599 100644
--- a/chromium/components/visitedlink/browser/visitedlink_master.cc
+++ b/chromium/components/visitedlink/browser/visitedlink_master.cc
@@ -9,6 +9,8 @@
#include <algorithm>
#include <utility>
+#include <memory>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/containers/stack_container.h"
@@ -16,7 +18,6 @@
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/rand_util.h"
#include "base/strings/string_util.h"
@@ -226,10 +227,9 @@ VisitedLinkMaster::VisitedLinkMaster(content::BrowserContext* browser_context,
bool persist_to_disk)
: browser_context_(browser_context),
delegate_(delegate),
- listener_(base::MakeUnique<VisitedLinkEventListener>(browser_context)),
+ listener_(std::make_unique<VisitedLinkEventListener>(browser_context)),
persist_to_disk_(persist_to_disk),
- weak_ptr_factory_(this) {
-}
+ weak_ptr_factory_(this) {}
VisitedLinkMaster::VisitedLinkMaster(Listener* listener,
VisitedLinkDelegate* delegate,
diff --git a/chromium/components/viz/DEPS b/chromium/components/viz/DEPS
index ecdd1168819..eba179ee3b2 100644
--- a/chromium/components/viz/DEPS
+++ b/chromium/components/viz/DEPS
@@ -1,3 +1,5 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"-components/viz",
"+components/viz/common",
diff --git a/chromium/components/viz/OWNERS b/chromium/components/viz/OWNERS
index bb27a38c7dc..2abbeb1df57 100644
--- a/chromium/components/viz/OWNERS
+++ b/chromium/components/viz/OWNERS
@@ -24,6 +24,7 @@ sadrul@chromium.org
enne@chromium.org
fsamuel@chromium.org
kylechar@chromium.org
+samans@chromium.org
# gpu
danakj@chromium.org
diff --git a/chromium/components/viz/README.md b/chromium/components/viz/README.md
index c73a9ba2227..946f2fecb7c 100644
--- a/chromium/components/viz/README.md
+++ b/chromium/components/viz/README.md
@@ -120,9 +120,13 @@ Code here supports presentation of the backing store drawn by the display
compositor (typically thought of as SwapBuffers), as well as the use of
overlays.
-| Can depend on: |
-|:---------------|
-| viz/common/* |
+| Can depend on: |
+|:--------------------------------------|
+| viz/common/* |
+| viz/service/display/<some_interfaces> |
+
+Dependencies onto viz/service/display should generally only be for interfaces
+that the embedder must provide to the display.
#### service/frame_sinks
**Frame sinks**: This component implements the Mojo interfaces to send frames,
@@ -130,11 +134,13 @@ resources, and other data types from ``viz/common/`` for display to the
compositing service. It receives and organizes relationships between what should
be composited.
-| Can depend on: |
-|:----------------------|
-| viz/common/* |
-| viz/service/display/ |
-| viz/service/surfaces/ |
+| Can depend on: |
+|:------------------------------|
+| viz/common/* |
+| viz/service/display/ |
+| viz/service/display_embedder/ |
+| viz/service/hit_test/ |
+| viz/service/surfaces/ |
#### service/gl
**GL**: This component implements the Mojo interfaces for allocating (and
diff --git a/chromium/components/viz/client/BUILD.gn b/chromium/components/viz/client/BUILD.gn
index f104219b2dc..4137fa5e2cc 100644
--- a/chromium/components/viz/client/BUILD.gn
+++ b/chromium/components/viz/client/BUILD.gn
@@ -15,6 +15,8 @@ viz_component("client") {
"frame_evictor.cc",
"frame_evictor.h",
"hit_test_data_provider.h",
+ "hit_test_data_provider_draw_quad.cc",
+ "hit_test_data_provider_draw_quad.h",
"local_surface_id_provider.cc",
"local_surface_id_provider.h",
]
@@ -34,6 +36,7 @@ viz_source_set("unit_tests") {
testonly = true
sources = [
"client_layer_tree_frame_sink_unittest.cc",
+ "hit_test_data_provider_draw_quad_unittest.cc",
]
deps = [
diff --git a/chromium/components/viz/client/DEPS b/chromium/components/viz/client/DEPS
index 7e48a4ae4eb..2fa7a11d9d7 100644
--- a/chromium/components/viz/client/DEPS
+++ b/chromium/components/viz/client/DEPS
@@ -1,7 +1,10 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+cc",
"-cc/blink",
"-cc/test",
+ "-components/viz/common/features.h",
"-components/viz/common/switches.h",
"+components/viz/client",
"+mojo/public/cpp/bindings",
diff --git a/chromium/components/viz/client/client_layer_tree_frame_sink.cc b/chromium/components/viz/client/client_layer_tree_frame_sink.cc
index a0e74830534..6640d1d8d89 100644
--- a/chromium/components/viz/client/client_layer_tree_frame_sink.cc
+++ b/chromium/components/viz/client/client_layer_tree_frame_sink.cc
@@ -55,29 +55,8 @@ ClientLayerTreeFrameSink::ClientLayerTreeFrameSink(
DETACH_FROM_THREAD(thread_checker_);
}
-ClientLayerTreeFrameSink::ClientLayerTreeFrameSink(
- scoped_refptr<VulkanContextProvider> vulkan_context_provider,
- InitParams* params)
- : cc::LayerTreeFrameSink(std::move(vulkan_context_provider)),
- hit_test_data_provider_(std::move(params->hit_test_data_provider)),
- local_surface_id_provider_(std::move(params->local_surface_id_provider)),
- synthetic_begin_frame_source_(
- std::move(params->synthetic_begin_frame_source)),
- pipes_(std::move(params->pipes)),
- client_binding_(this),
- enable_surface_synchronization_(params->enable_surface_synchronization),
- wants_animate_only_begin_frames_(params->wants_animate_only_begin_frames),
- weak_factory_(this) {
- DETACH_FROM_THREAD(thread_checker_);
-}
-
ClientLayerTreeFrameSink::~ClientLayerTreeFrameSink() {}
-base::WeakPtr<ClientLayerTreeFrameSink> ClientLayerTreeFrameSink::GetWeakPtr() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- return weak_factory_.GetWeakPtr();
-}
-
bool ClientLayerTreeFrameSink::BindToClient(
cc::LayerTreeFrameSinkClient* client) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -100,7 +79,8 @@ bool ClientLayerTreeFrameSink::BindToClient(
weak_factory_.GetWeakPtr()));
compositor_frame_sink_ptr_ = compositor_frame_sink_associated_.get();
}
- client_binding_.Bind(std::move(pipes_.client_request));
+ client_binding_.Bind(std::move(pipes_.client_request),
+ compositor_task_runner_);
if (synthetic_begin_frame_source_) {
client->SetBeginFrameSource(synthetic_begin_frame_source_.get());
@@ -156,7 +136,7 @@ void ClientLayerTreeFrameSink::SubmitCompositorFrame(CompositorFrame frame) {
mojom::HitTestRegionListPtr hit_test_region_list;
if (hit_test_data_provider_)
- hit_test_region_list = hit_test_data_provider_->GetHitTestData();
+ hit_test_region_list = hit_test_data_provider_->GetHitTestData(frame);
compositor_frame_sink_ptr_->SubmitCompositorFrame(
local_surface_id_, std::move(frame), std::move(hit_test_region_list),
@@ -171,6 +151,18 @@ void ClientLayerTreeFrameSink::DidNotProduceFrame(const BeginFrameAck& ack) {
compositor_frame_sink_ptr_->DidNotProduceFrame(ack);
}
+void ClientLayerTreeFrameSink::DidAllocateSharedBitmap(
+ mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) {
+ DCHECK(compositor_frame_sink_ptr_);
+ compositor_frame_sink_ptr_->DidAllocateSharedBitmap(std::move(buffer), id);
+}
+
+void ClientLayerTreeFrameSink::DidDeleteSharedBitmap(const SharedBitmapId& id) {
+ DCHECK(compositor_frame_sink_ptr_);
+ compositor_frame_sink_ptr_->DidDeleteSharedBitmap(id);
+}
+
void ClientLayerTreeFrameSink::DidReceiveCompositorFrameAck(
const std::vector<ReturnedResource>& resources) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/chromium/components/viz/client/client_layer_tree_frame_sink.h b/chromium/components/viz/client/client_layer_tree_frame_sink.h
index 88a2ed80bf4..701c3496183 100644
--- a/chromium/components/viz/client/client_layer_tree_frame_sink.h
+++ b/chromium/components/viz/client/client_layer_tree_frame_sink.h
@@ -66,13 +66,8 @@ class VIZ_CLIENT_EXPORT ClientLayerTreeFrameSink
scoped_refptr<RasterContextProvider> worker_context_provider,
InitParams* params);
- ClientLayerTreeFrameSink(
- scoped_refptr<VulkanContextProvider> vulkan_context_provider,
- InitParams* params);
-
~ClientLayerTreeFrameSink() override;
- base::WeakPtr<ClientLayerTreeFrameSink> GetWeakPtr();
const HitTestDataProvider* hit_test_data_provider() const {
return hit_test_data_provider_.get();
}
@@ -85,6 +80,9 @@ class VIZ_CLIENT_EXPORT ClientLayerTreeFrameSink
void SetLocalSurfaceId(const LocalSurfaceId& local_surface_id) override;
void SubmitCompositorFrame(CompositorFrame frame) override;
void DidNotProduceFrame(const BeginFrameAck& ack) override;
+ void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) override;
+ void DidDeleteSharedBitmap(const SharedBitmapId& id) override;
private:
// mojom::CompositorFrameSinkClient implementation:
diff --git a/chromium/components/viz/client/client_layer_tree_frame_sink_unittest.cc b/chromium/components/viz/client/client_layer_tree_frame_sink_unittest.cc
index 9f8d9601753..a554f5c8ae9 100644
--- a/chromium/components/viz/client/client_layer_tree_frame_sink_unittest.cc
+++ b/chromium/components/viz/client/client_layer_tree_frame_sink_unittest.cc
@@ -12,8 +12,8 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "cc/test/fake_layer_tree_frame_sink_client.h"
-#include "cc/test/test_context_provider.h"
#include "components/viz/client/local_surface_id_provider.h"
+#include "components/viz/test/test_context_provider.h"
#include "components/viz/test/test_gpu_memory_buffer_manager.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
@@ -53,8 +53,7 @@ TEST(ClientLayerTreeFrameSinkTest,
base::Thread bg_thread("BG Thread");
bg_thread.Start();
- scoped_refptr<cc::TestContextProvider> provider =
- cc::TestContextProvider::Create();
+ scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
TestGpuMemoryBufferManager test_gpu_memory_buffer_manager;
mojom::CompositorFrameSinkPtrInfo sink_info;
diff --git a/chromium/components/viz/client/client_shared_bitmap_manager.cc b/chromium/components/viz/client/client_shared_bitmap_manager.cc
index e03df4f64be..e2cae716e7d 100644
--- a/chromium/components/viz/client/client_shared_bitmap_manager.cc
+++ b/chromium/components/viz/client/client_shared_bitmap_manager.cc
@@ -149,6 +149,20 @@ std::unique_ptr<SharedBitmap> ClientSharedBitmapManager::GetSharedBitmapFromId(
return nullptr;
}
+bool ClientSharedBitmapManager::ChildAllocatedSharedBitmap(
+ mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) {
+ // Display compositor only.
+ NOTREACHED();
+ return false;
+}
+
+void ClientSharedBitmapManager::ChildDeletedSharedBitmap(
+ const SharedBitmapId& id) {
+ // Display compositor only.
+ NOTREACHED();
+}
+
std::unique_ptr<SharedBitmap>
ClientSharedBitmapManager::GetBitmapForSharedMemory(base::SharedMemory* mem) {
SharedBitmapId id = SharedBitmap::GenerateId();
diff --git a/chromium/components/viz/client/client_shared_bitmap_manager.h b/chromium/components/viz/client/client_shared_bitmap_manager.h
index 4df7ffe8bfe..e36f8dd9189 100644
--- a/chromium/components/viz/client/client_shared_bitmap_manager.h
+++ b/chromium/components/viz/client/client_shared_bitmap_manager.h
@@ -36,6 +36,9 @@ class VIZ_CLIENT_EXPORT ClientSharedBitmapManager : public SharedBitmapManager {
std::unique_ptr<SharedBitmap> GetSharedBitmapFromId(
const gfx::Size&,
const SharedBitmapId&) override;
+ bool ChildAllocatedSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) override;
+ void ChildDeletedSharedBitmap(const SharedBitmapId& id) override;
std::unique_ptr<SharedBitmap> GetBitmapForSharedMemory(
base::SharedMemory* mem);
diff --git a/chromium/components/viz/client/hit_test_data_provider.h b/chromium/components/viz/client/hit_test_data_provider.h
index 809dab2007c..3c7e1777bc1 100644
--- a/chromium/components/viz/client/hit_test_data_provider.h
+++ b/chromium/components/viz/client/hit_test_data_provider.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "components/viz/client/viz_client_export.h"
+#include "components/viz/common/quads/compositor_frame.h"
#include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
namespace viz {
@@ -21,7 +22,8 @@ class VIZ_CLIENT_EXPORT HitTestDataProvider {
// Returns an array of hit-test regions. May return nullptr to disable
// hit-testing.
- virtual mojom::HitTestRegionListPtr GetHitTestData() const = 0;
+ virtual mojom::HitTestRegionListPtr GetHitTestData(
+ const CompositorFrame& compositor_frame) const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(HitTestDataProvider);
diff --git a/chromium/components/viz/client/hit_test_data_provider_draw_quad.cc b/chromium/components/viz/client/hit_test_data_provider_draw_quad.cc
new file mode 100644
index 00000000000..a44809b0fcb
--- /dev/null
+++ b/chromium/components/viz/client/hit_test_data_provider_draw_quad.cc
@@ -0,0 +1,56 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/client/hit_test_data_provider_draw_quad.h"
+
+#include "components/viz/common/quads/surface_draw_quad.h"
+
+namespace viz {
+
+HitTestDataProviderDrawQuad::HitTestDataProviderDrawQuad(
+ bool should_ask_for_child_region)
+ : should_ask_for_child_region_(should_ask_for_child_region) {}
+
+HitTestDataProviderDrawQuad::~HitTestDataProviderDrawQuad() = default;
+
+mojom::HitTestRegionListPtr HitTestDataProviderDrawQuad::GetHitTestData(
+ const CompositorFrame& compositor_frame) const {
+ // Derive hit test regions from information in the CompositorFrame.
+ auto hit_test_region_list = mojom::HitTestRegionList::New();
+ hit_test_region_list->flags =
+ mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestMine;
+ hit_test_region_list->bounds.set_size(compositor_frame.size_in_pixels());
+
+ for (const auto& render_pass : compositor_frame.render_pass_list) {
+ for (const DrawQuad* quad : render_pass->quad_list) {
+ if (quad->material == DrawQuad::SURFACE_CONTENT) {
+ // Skip the quad if the transform is not invertible (i.e. it will not
+ // be able to receive events).
+ gfx::Transform target_to_quad_transform;
+ if (!quad->shared_quad_state->quad_to_target_transform.GetInverse(
+ &target_to_quad_transform)) {
+ continue;
+ }
+
+ const SurfaceDrawQuad* surface_quad =
+ SurfaceDrawQuad::MaterialCast(quad);
+ auto hit_test_region = mojom::HitTestRegion::New();
+ const SurfaceId& surface_id = surface_quad->primary_surface_id;
+ hit_test_region->frame_sink_id = surface_id.frame_sink_id();
+ hit_test_region->local_surface_id = surface_id.local_surface_id();
+ hit_test_region->flags = mojom::kHitTestMouse | mojom::kHitTestTouch |
+ mojom::kHitTestChildSurface;
+ if (should_ask_for_child_region_)
+ hit_test_region->flags |= mojom::kHitTestAsk;
+ hit_test_region->rect = surface_quad->rect;
+ hit_test_region->transform = target_to_quad_transform;
+ hit_test_region_list->regions.push_back(std::move(hit_test_region));
+ }
+ }
+ }
+
+ return hit_test_region_list;
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/client/hit_test_data_provider_draw_quad.h b/chromium/components/viz/client/hit_test_data_provider_draw_quad.h
new file mode 100644
index 00000000000..f3195d1eb7a
--- /dev/null
+++ b/chromium/components/viz/client/hit_test_data_provider_draw_quad.h
@@ -0,0 +1,31 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_CLIENT_HIT_TEST_DATA_PROVIDER_DRAW_QUAD_H_
+#define COMPONENTS_VIZ_CLIENT_HIT_TEST_DATA_PROVIDER_DRAW_QUAD_H_
+
+#include "components/viz/client/hit_test_data_provider.h"
+
+namespace viz {
+
+// HitTestDataProviderDrawQuad is used to extract hit test data from DrawQuads
+// in the CompositorFrame.
+class VIZ_CLIENT_EXPORT HitTestDataProviderDrawQuad
+ : public HitTestDataProvider {
+ public:
+ explicit HitTestDataProviderDrawQuad(bool should_ask_for_child_region);
+ ~HitTestDataProviderDrawQuad() override;
+
+ mojom::HitTestRegionListPtr GetHitTestData(
+ const CompositorFrame& compositor_frame) const override;
+
+ private:
+ const bool should_ask_for_child_region_;
+
+ DISALLOW_COPY_AND_ASSIGN(HitTestDataProviderDrawQuad);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_CLIENT_HIT_TEST_DATA_PROVIDER_DRAW_QUAD_H_
diff --git a/chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc b/chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
new file mode 100644
index 00000000000..85eea7f56ed
--- /dev/null
+++ b/chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
@@ -0,0 +1,100 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/client/hit_test_data_provider_draw_quad.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread.h"
+#include "cc/test/fake_layer_tree_frame_sink_client.h"
+#include "components/viz/client/local_surface_id_provider.h"
+#include "components/viz/common/quads/surface_draw_quad.h"
+#include "components/viz/test/compositor_frame_helpers.h"
+#include "components/viz/test/test_context_provider.h"
+#include "components/viz/test/test_gpu_memory_buffer_manager.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace viz {
+
+namespace {
+
+CompositorFrame MakeCompositorFrameWithChildSurface(
+ const SurfaceId& child_surface_id,
+ const gfx::Rect& rect,
+ const gfx::Rect& child_rect,
+ const gfx::Transform& transform) {
+ auto pass = RenderPass::Create();
+ pass->SetNew(1, rect, rect, gfx::Transform());
+
+ auto* shared_state = pass->CreateAndAppendSharedQuadState();
+ shared_state->SetAll(transform, rect, rect, rect, false, false, 1,
+ SkBlendMode::kSrcOver, 0);
+
+ auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
+ surface_quad->SetNew(pass->shared_quad_state_list.back(), child_rect,
+ child_rect, child_surface_id, base::nullopt,
+ SK_ColorWHITE, false);
+
+ return CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
+}
+
+} // namespace
+
+// Test to ensure that hit test data is created correctly from CompositorFrame
+// and its RenderPassList. kHitTestAsk is only set for OOPIFs.
+TEST(HitTestDataProviderDrawQuad, HitTestDataRenderer) {
+ std::unique_ptr<HitTestDataProvider> hit_test_data_provider =
+ std::make_unique<HitTestDataProviderDrawQuad>(
+ true /* should_ask_for_child_region */);
+
+ constexpr gfx::Rect kFrameRect(0, 0, 1024, 768);
+
+ // Ensure that a CompositorFrame without a child surface sets kHitTestMine.
+ CompositorFrame compositor_frame =
+ CompositorFrameBuilder().AddRenderPass(kFrameRect, kFrameRect).Build();
+ mojom::HitTestRegionListPtr hit_test_region_list =
+ hit_test_data_provider->GetHitTestData(compositor_frame);
+
+ EXPECT_EQ(mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestMine,
+ hit_test_region_list->flags);
+ EXPECT_EQ(kFrameRect, hit_test_region_list->bounds);
+ EXPECT_FALSE(hit_test_region_list->regions.size());
+
+ // Ensure that a CompositorFrame with a child surface only set kHitTestAsk
+ // for its child surface.
+ LocalSurfaceId child_local_surface_id(2, base::UnguessableToken::Create());
+ FrameSinkId frame_sink_id(2, 0);
+ SurfaceId child_surface_id(frame_sink_id, child_local_surface_id);
+ gfx::Rect child_rect(200, 100);
+ gfx::Transform transform;
+ transform.Translate(-200, -100);
+ compositor_frame = MakeCompositorFrameWithChildSurface(
+ child_surface_id, kFrameRect, child_rect, transform);
+ hit_test_region_list =
+ hit_test_data_provider->GetHitTestData(compositor_frame);
+
+ EXPECT_EQ(mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestMine,
+ hit_test_region_list->flags);
+ EXPECT_EQ(kFrameRect, hit_test_region_list->bounds);
+ EXPECT_EQ(1u, hit_test_region_list->regions.size());
+ EXPECT_EQ(child_surface_id.frame_sink_id(),
+ hit_test_region_list->regions[0]->frame_sink_id);
+ EXPECT_EQ(child_surface_id.local_surface_id(),
+ hit_test_region_list->regions[0]->local_surface_id);
+ EXPECT_EQ(mojom::kHitTestMouse | mojom::kHitTestTouch |
+ mojom::kHitTestChildSurface | mojom::kHitTestAsk,
+ hit_test_region_list->regions[0]->flags);
+ EXPECT_EQ(child_rect, hit_test_region_list->regions[0]->rect);
+ gfx::Transform transform_inverse;
+ EXPECT_TRUE(transform.GetInverse(&transform_inverse));
+ EXPECT_EQ(transform_inverse, hit_test_region_list->regions[0]->transform);
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/common/BUILD.gn b/chromium/components/viz/common/BUILD.gn
index b1f1c511c79..8d3a744560b 100644
--- a/chromium/components/viz/common/BUILD.gn
+++ b/chromium/components/viz/common/BUILD.gn
@@ -33,6 +33,8 @@ viz_component("common") {
defines = [ "VIZ_COMMON_IMPLEMENTATION" ]
sources = [
+ "constants.cc",
+ "constants.h",
"display/renderer_settings.cc",
"display/renderer_settings.h",
"features.cc",
@@ -64,6 +66,8 @@ viz_component("common") {
"gpu/in_process_context_provider.h",
"gpu/raster_context_provider.cc",
"gpu/raster_context_provider.h",
+ "gpu/texture_allocation.cc",
+ "gpu/texture_allocation.h",
"gpu/vulkan_context_provider.h",
"gpu/vulkan_in_process_context_provider.cc",
"gpu/vulkan_in_process_context_provider.h",
@@ -78,6 +82,7 @@ viz_component("common") {
"quads/debug_border_draw_quad.h",
"quads/draw_quad.cc",
"quads/draw_quad.h",
+ "quads/frame_deadline.h",
"quads/largest_draw_quad.cc",
"quads/largest_draw_quad.h",
"quads/picture_draw_quad.cc",
@@ -119,6 +124,8 @@ viz_component("common") {
"resources/single_release_callback.h",
"resources/transferable_resource.cc",
"resources/transferable_resource.h",
+ "surfaces/child_local_surface_id_allocator.cc",
+ "surfaces/child_local_surface_id_allocator.h",
"surfaces/frame_sink_id.cc",
"surfaces/frame_sink_id.h",
"surfaces/frame_sink_id_allocator.h",
@@ -126,18 +133,10 @@ viz_component("common") {
"surfaces/local_surface_id.h",
"surfaces/parent_local_surface_id_allocator.cc",
"surfaces/parent_local_surface_id_allocator.h",
- "surfaces/sequence_surface_reference_factory.cc",
- "surfaces/sequence_surface_reference_factory.h",
- "surfaces/stub_surface_reference_factory.cc",
- "surfaces/stub_surface_reference_factory.h",
"surfaces/surface_id.cc",
"surfaces/surface_id.h",
+ "surfaces/surface_info.cc",
"surfaces/surface_info.h",
- "surfaces/surface_reference_factory.h",
- "surfaces/surface_reference_owner.h",
- "surfaces/surface_sequence.h",
- "surfaces/surface_sequence_generator.cc",
- "surfaces/surface_sequence_generator.h",
"switches.cc",
"switches.h",
"traced_value.cc",
@@ -155,6 +154,8 @@ viz_component("common") {
"//gpu",
"//gpu/command_buffer/client:gles2_implementation",
"//gpu/command_buffer/client:gles2_interface",
+ "//gpu/command_buffer/client:raster",
+ "//gpu/command_buffer/client:raster_interface",
"//gpu/command_buffer/service",
"//gpu/ipc:gl_in_process_context",
"//gpu/skia_bindings:skia_bindings",
@@ -194,7 +195,9 @@ viz_source_set("unit_tests") {
"quads/draw_quad_unittest.cc",
"quads/render_pass_unittest.cc",
"resources/platform_color_unittest.cc",
- "surfaces/surface_sequence_generator_unittest.cc",
+ "surfaces/child_local_surface_id_allocator_unittest.cc",
+ "surfaces/local_surface_id_unittest.cc",
+ "surfaces/parent_local_surface_id_allocator_unittest.cc",
"yuv_readback_unittest.cc",
]
diff --git a/chromium/components/viz/common/DEPS b/chromium/components/viz/common/DEPS
index 04cd0928d0e..7aece4f4dd1 100644
--- a/chromium/components/viz/common/DEPS
+++ b/chromium/components/viz/common/DEPS
@@ -1,3 +1,5 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
specific_include_rules = {
# DEPS for GLHelper and friends which are in the root common/ directory.
"(yuv_readback|gl_helper).*\.(cc|h)": [
diff --git a/chromium/components/viz/common/constants.cc b/chromium/components/viz/common/constants.cc
new file mode 100644
index 00000000000..b1fdd43110c
--- /dev/null
+++ b/chromium/components/viz/common/constants.cc
@@ -0,0 +1,11 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/common/constants.h"
+
+namespace viz {
+
+const uint32_t kDefaultActivationDeadlineInFrames = 4u;
+
+} // namespace viz
diff --git a/chromium/components/viz/common/constants.h b/chromium/components/viz/common/constants.h
new file mode 100644
index 00000000000..ab09b8e30db
--- /dev/null
+++ b/chromium/components/viz/common/constants.h
@@ -0,0 +1,19 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_COMMON_CONSTANTS_H_
+#define COMPONENTS_VIZ_COMMON_CONSTANTS_H_
+
+#include <stdint.h>
+
+#include "components/viz/common/viz_common_export.h"
+
+namespace viz {
+
+// Keep list in alphabetical order.
+VIZ_COMMON_EXPORT extern const uint32_t kDefaultActivationDeadlineInFrames;
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_COMMON_CONSTANTS_H_
diff --git a/chromium/components/viz/common/display/renderer_settings.h b/chromium/components/viz/common/display/renderer_settings.h
index 870ed372ae8..f0b595f0900 100644
--- a/chromium/components/viz/common/display/renderer_settings.h
+++ b/chromium/components/viz/common/display/renderer_settings.h
@@ -7,8 +7,8 @@
#include <stddef.h>
-#include "components/viz/common/resources/resource_settings.h"
#include "components/viz/common/viz_common_export.h"
+#include "ui/gfx/geometry/size.h"
namespace viz {
@@ -18,7 +18,6 @@ class VIZ_COMMON_EXPORT RendererSettings {
RendererSettings(const RendererSettings& other);
~RendererSettings();
- ResourceSettings resource_settings;
bool allow_antialiasing = true;
bool force_antialiasing = false;
bool force_blending_with_shaders = false;
@@ -30,10 +29,14 @@ class VIZ_COMMON_EXPORT RendererSettings {
bool show_overdraw_feedback = false;
bool enable_draw_occlusion = false;
bool use_skia_renderer = false;
+ bool allow_overlays = true;
bool dont_round_texture_sizes_for_pixel_tests = false;
int highp_threshold_min = 0;
int slow_down_compositing_scale_factor = 1;
+
+ // The required minimum size for DrawQuad to apply Draw Occlusion on.
+ gfx::Size kMinimumDrawOcclusionSize = gfx::Size(60, 60);
};
} // namespace viz
diff --git a/chromium/components/viz/common/features.cc b/chromium/components/viz/common/features.cc
index b983d6f5a7a..b2364574690 100644
--- a/chromium/components/viz/common/features.cc
+++ b/chromium/components/viz/common/features.cc
@@ -5,11 +5,17 @@
#include "components/viz/common/features.h"
#include "base/command_line.h"
+#include "build/build_config.h"
#include "components/viz/common/switches.h"
namespace features {
-#if defined(USE_AURA)
+// Enables running draw occlusion algorithm to remove Draw Quads that are not
+// shown on screen from CompositorFrame.
+const base::Feature kEnableDrawOcclusion{"DrawOcclusion",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+#if defined(USE_AURA) || defined(OS_MACOSX)
const base::Feature kEnableSurfaceSynchronization{
"SurfaceSynchronization", base::FEATURE_ENABLED_BY_DEFAULT};
#else
@@ -17,12 +23,20 @@ const base::Feature kEnableSurfaceSynchronization{
"SurfaceSynchronization", base::FEATURE_DISABLED_BY_DEFAULT};
#endif
+// Enables DumpWithoutCrashing of surface invariants violations.
+const base::Feature kEnableInvariantsViolationLogging{
+ "InvariantsViolationLogging", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enables running the display compositor as part of the viz service in the GPU
// process. This is also referred to as out-of-process display compositor
// (OOP-D).
const base::Feature kVizDisplayCompositor{"VizDisplayCompositor",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables running the Viz-assisted hit-test logic.
+const base::Feature kEnableVizHitTestDrawQuad{
+ "VizHitTestDrawQuad", base::FEATURE_DISABLED_BY_DEFAULT};
+
bool IsSurfaceSynchronizationEnabled() {
auto* command_line = base::CommandLine::ForCurrentProcess();
return base::FeatureList::IsEnabled(kEnableSurfaceSynchronization) ||
@@ -30,4 +44,31 @@ bool IsSurfaceSynchronizationEnabled() {
base::FeatureList::IsEnabled(kVizDisplayCompositor);
}
+bool IsSurfaceInvariantsViolationLoggingEnabled() {
+ return IsSurfaceSynchronizationEnabled() &&
+ base::FeatureList::IsEnabled(kEnableInvariantsViolationLogging);
+}
+
+bool IsVizHitTestingDrawQuadEnabled() {
+ return base::FeatureList::IsEnabled(kEnableVizHitTestDrawQuad) ||
+ base::FeatureList::IsEnabled(kVizDisplayCompositor);
+}
+
+bool IsVizHitTestingEnabled() {
+ return IsVizHitTestingDrawQuadEnabled() ||
+ IsVizHitTestingSurfaceLayerEnabled();
+}
+
+bool IsVizHitTestingSurfaceLayerEnabled() {
+ // TODO(riajiang): Check feature flag as well. https://crbug.com/804888
+ // TODO(riajiang): Check kVizDisplayCompositor feature when it works with
+ // that config.
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseVizHitTestSurfaceLayer);
+}
+
+bool IsDrawOcclusionEnabled() {
+ return base::FeatureList::IsEnabled(kEnableDrawOcclusion);
+}
+
} // namespace features
diff --git a/chromium/components/viz/common/features.h b/chromium/components/viz/common/features.h
index cf40a471c3d..f7bffcf8faa 100644
--- a/chromium/components/viz/common/features.h
+++ b/chromium/components/viz/common/features.h
@@ -11,10 +11,18 @@
namespace features {
+VIZ_COMMON_EXPORT extern const base::Feature kEnableDrawOcclusion;
VIZ_COMMON_EXPORT extern const base::Feature kEnableSurfaceSynchronization;
+VIZ_COMMON_EXPORT extern const base::Feature kEnableInvariantsViolationLogging;
+VIZ_COMMON_EXPORT extern const base::Feature kEnableVizHitTestDrawQuad;
VIZ_COMMON_EXPORT extern const base::Feature kVizDisplayCompositor;
+VIZ_COMMON_EXPORT bool IsDrawOcclusionEnabled();
VIZ_COMMON_EXPORT bool IsSurfaceSynchronizationEnabled();
+VIZ_COMMON_EXPORT bool IsSurfaceInvariantsViolationLoggingEnabled();
+VIZ_COMMON_EXPORT bool IsVizHitTestingDrawQuadEnabled();
+VIZ_COMMON_EXPORT bool IsVizHitTestingEnabled();
+VIZ_COMMON_EXPORT bool IsVizHitTestingSurfaceLayerEnabled();
} // namespace features
diff --git a/chromium/components/viz/common/frame_sinks/DEPS b/chromium/components/viz/common/frame_sinks/DEPS
index be1960e4305..048313823cb 100644
--- a/chromium/components/viz/common/frame_sinks/DEPS
+++ b/chromium/components/viz/common/frame_sinks/DEPS
@@ -1,3 +1,5 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+gpu/command_buffer/common",
"+mojo/public/cpp/bindings",
diff --git a/chromium/components/viz/common/gl_helper_scaling.cc b/chromium/components/viz/common/gl_helper_scaling.cc
index 8fcf3332779..72d81dd3301 100644
--- a/chromium/components/viz/common/gl_helper_scaling.cc
+++ b/chromium/components/viz/common/gl_helper_scaling.cc
@@ -653,6 +653,7 @@ void GLHelperScaling::ConvertScalerOpsToScalerStages(
switch (x_ops->size()) {
case 0:
NOTREACHED();
+ break;
case 1:
if (x_ops->front().scale_factor == 3) {
current_shader = SHADER_BILINEAR3;
diff --git a/chromium/components/viz/common/gpu/DEPS b/chromium/components/viz/common/gpu/DEPS
index baee2d4e24f..1d4410875ae 100644
--- a/chromium/components/viz/common/gpu/DEPS
+++ b/chromium/components/viz/common/gpu/DEPS
@@ -1,3 +1,5 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+cc/output",
"+cc/resources",
diff --git a/chromium/components/viz/common/gpu/context_cache_controller_unittest.cc b/chromium/components/viz/common/gpu/context_cache_controller_unittest.cc
index d6eb828ef79..1c2d0222ab9 100644
--- a/chromium/components/viz/common/gpu/context_cache_controller_unittest.cc
+++ b/chromium/components/viz/common/gpu/context_cache_controller_unittest.cc
@@ -6,9 +6,7 @@
#include "base/memory/ptr_util.h"
#include "base/test/test_mock_time_task_runner.h"
-#include "cc/test/test_context_provider.h"
-#include "cc/test/test_context_support.h"
-#include "cc/test/test_web_graphics_context_3d.h"
+#include "components/viz/test/test_context_support.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -18,7 +16,7 @@ using ::testing::StrictMock;
namespace viz {
namespace {
-class MockContextSupport : public cc::TestContextSupport {
+class MockContextSupport : public TestContextSupport {
public:
MockContextSupport() {}
MOCK_METHOD1(SetAggressivelyFreeResources,
diff --git a/chromium/components/viz/common/gpu/raster_context_provider.h b/chromium/components/viz/common/gpu/raster_context_provider.h
index e46927c31de..908c01e19ff 100644
--- a/chromium/components/viz/common/gpu/raster_context_provider.h
+++ b/chromium/components/viz/common/gpu/raster_context_provider.h
@@ -27,6 +27,10 @@ namespace gpu {
class ContextSupport;
struct GpuFeatureInfo;
+namespace gles2 {
+class GLES2Interface;
+}
+
namespace raster {
class RasterInterface;
}
@@ -74,6 +78,8 @@ class VIZ_COMMON_EXPORT RasterContextProvider {
// Returns the lock that should be held if using this context from multiple
// threads. This can be called on any thread.
+ // Returns null if the context does not support locking and must be used from
+ // the same thread.
// NOTE: Helper method for ScopedContextLock. Use that instead of calling this
// directly.
virtual base::Lock* GetLock() = 0;
@@ -105,6 +111,10 @@ class VIZ_COMMON_EXPORT RasterContextProvider {
// calling this.
virtual const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const = 0;
+ // Get a GLES2 interface to the 3d context. The context provider must have
+ // been successfully bound to a thread before calling this.
+ virtual gpu::gles2::GLES2Interface* ContextGL() = 0;
+
// Get a Raster interface to the 3d context. The context provider must have
// been successfully bound to a thread before calling this.
virtual gpu::raster::RasterInterface* RasterInterface() = 0;
diff --git a/chromium/components/viz/common/gpu/texture_allocation.cc b/chromium/components/viz/common/gpu/texture_allocation.cc
new file mode 100644
index 00000000000..27778ed2df8
--- /dev/null
+++ b/chromium/components/viz/common/gpu/texture_allocation.cc
@@ -0,0 +1,112 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/common/gpu/texture_allocation.h"
+
+#include "components/viz/common/resources/resource_format_utils.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
+#include "gpu/command_buffer/common/capabilities.h"
+#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
+#include "ui/gfx/color_space.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace viz {
+
+// static
+TextureAllocation TextureAllocation::MakeTextureId(
+ gpu::gles2::GLES2Interface* gl,
+ const gpu::Capabilities& caps,
+ ResourceFormat format,
+ bool use_gpu_memory_buffer_resources,
+ bool for_framebuffer_attachment) {
+ bool overlay_textures = use_gpu_memory_buffer_resources &&
+ caps.texture_storage_image &&
+ IsGpuMemoryBufferFormatSupported(format);
+
+ uint32_t texture_target = GL_TEXTURE_2D;
+ bool overlay_candidate = false;
+ if (overlay_textures) {
+ texture_target = gpu::GetBufferTextureTarget(gfx::BufferUsage::SCANOUT,
+ BufferFormat(format), caps);
+ overlay_candidate = true;
+ }
+
+ uint32_t texture_id;
+ gl->GenTextures(1, &texture_id);
+ gl->BindTexture(texture_target, texture_id);
+ gl->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ gl->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ if (for_framebuffer_attachment && caps.texture_usage) {
+ // Set GL_FRAMEBUFFER_ATTACHMENT_ANGLE since we'll be binding these
+ // textures as a framebuffer for drawing directly to them on the gpu.
+ gl->TexParameteri(texture_target, GL_TEXTURE_USAGE_ANGLE,
+ GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+ }
+ gl->BindTexture(texture_target, 0);
+ return {texture_id, texture_target, overlay_candidate};
+}
+
+// static
+void TextureAllocation::AllocateStorage(gpu::gles2::GLES2Interface* gl,
+ const gpu::Capabilities& caps,
+ ResourceFormat format,
+ const gfx::Size& size,
+ const TextureAllocation& alloc,
+ const gfx::ColorSpace& color_space) {
+ gl->BindTexture(alloc.texture_target, alloc.texture_id);
+ // Allocate backing storage for the texture. The best choice is to use
+ // GpuMemoryBuffers if we can use the texture as an overlay and its asked
+ // for by the caller. Else we try to make the texture have immutable
+ // storage, and finally fall back to standard storage if we must.
+ if (alloc.overlay_candidate) {
+ // |overlay_candidate| was only set when these were true, and
+ // |use_gpu_memory_buffer_resources| was specified by the caller.
+ DCHECK(caps.texture_storage_image);
+ DCHECK(IsGpuMemoryBufferFormatSupported(format));
+
+ gl->TexStorage2DImageCHROMIUM(
+ alloc.texture_target, TextureStorageFormat(format), GL_SCANOUT_CHROMIUM,
+ size.width(), size.height());
+ if (color_space.IsValid()) {
+ gl->SetColorSpaceMetadataCHROMIUM(
+ alloc.texture_id, reinterpret_cast<GLColorSpace>(
+ const_cast<gfx::ColorSpace*>(&color_space)));
+ }
+ } else if (caps.texture_storage) {
+ gl->TexStorage2DEXT(alloc.texture_target, 1, TextureStorageFormat(format),
+ size.width(), size.height());
+ } else {
+ gl->TexImage2D(alloc.texture_target, 0, GLInternalFormat(format),
+ size.width(), size.height(), 0, GLDataFormat(format),
+ GLDataType(format), nullptr);
+ }
+}
+
+// static
+void TextureAllocation::AllocateStorage(gpu::raster::RasterInterface* ri,
+ const gpu::Capabilities& caps,
+ ResourceFormat format,
+ const gfx::Size& size,
+ const TextureAllocation& alloc,
+ const gfx::ColorSpace& color_space) {
+ // ETC1 resources cannot be preallocated.
+ if (format == ETC1)
+ return;
+ ri->BindTexture(alloc.texture_target, alloc.texture_id);
+ ri->TexStorageForRaster(
+ alloc.texture_target, format, size.width(), size.height(),
+ alloc.overlay_candidate ? gpu::raster::kOverlay : gpu::raster::kNone);
+ if (alloc.overlay_candidate && color_space.IsValid()) {
+ ri->SetColorSpaceMetadataCHROMIUM(
+ alloc.texture_id, reinterpret_cast<GLColorSpace>(
+ const_cast<gfx::ColorSpace*>(&color_space)));
+ }
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/common/gpu/texture_allocation.h b/chromium/components/viz/common/gpu/texture_allocation.h
new file mode 100644
index 00000000000..61b40e4fcb8
--- /dev/null
+++ b/chromium/components/viz/common/gpu/texture_allocation.h
@@ -0,0 +1,65 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_COMMON_GPU_TEXTURE_ALLOCATION_H_
+#define COMPONENTS_VIZ_COMMON_GPU_TEXTURE_ALLOCATION_H_
+
+#include "components/viz/common/resources/resource_format.h"
+#include "components/viz/common/viz_common_export.h"
+#include "third_party/khronos/GLES2/gl2.h"
+
+#include <stdint.h>
+
+namespace gfx {
+class ColorSpace;
+class Size;
+} // namespace gfx
+
+namespace gpu {
+struct Capabilities;
+namespace gles2 {
+class GLES2Interface;
+}
+namespace raster {
+class RasterInterface;
+}
+} // namespace gpu
+
+namespace viz {
+
+class VIZ_COMMON_EXPORT TextureAllocation {
+ public:
+ GLuint texture_id = 0;
+ GLenum texture_target = 0;
+ bool overlay_candidate = false;
+
+ // Generates a texture id and sets it up for use, but without any storage
+ // allocated pixels.
+ static TextureAllocation MakeTextureId(gpu::gles2::GLES2Interface* gl,
+ const gpu::Capabilities& caps,
+ ResourceFormat format,
+ bool use_gpu_memory_buffer_resources,
+ bool for_framebuffer_attachment);
+
+ // Allocates the storage for a texture id previously from MakeTextureId().
+ // Can be called on a different context, if the texture id is mapped to
+ // another context with a mailbox. The |format| should match the one given to
+ // MakeTextureId().
+ static void AllocateStorage(gpu::gles2::GLES2Interface* gl,
+ const gpu::Capabilities& caps,
+ ResourceFormat format,
+ const gfx::Size& size,
+ const TextureAllocation& alloc,
+ const gfx::ColorSpace& color_space);
+ static void AllocateStorage(gpu::raster::RasterInterface* ri,
+ const gpu::Capabilities& caps,
+ ResourceFormat format,
+ const gfx::Size& size,
+ const TextureAllocation& alloc,
+ const gfx::ColorSpace& color_space);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_COMMON_GPU_TEXTURE_ALLOCATION_H_
diff --git a/chromium/components/viz/common/quads/DEPS b/chromium/components/viz/common/quads/DEPS
index c26fd4b7c2f..8353b9ec033 100644
--- a/chromium/components/viz/common/quads/DEPS
+++ b/chromium/components/viz/common/quads/DEPS
@@ -1,3 +1,5 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
# TODO(staraz): cc/base was added because SharedQuadState includes
# cc::MathUtil. Remove it once cc/base/math_util* are moved to viz.
diff --git a/chromium/components/viz/common/quads/compositor_frame.cc b/chromium/components/viz/common/quads/compositor_frame.cc
index 17e748a7bfd..4bd8cd048b8 100644
--- a/chromium/components/viz/common/quads/compositor_frame.cc
+++ b/chromium/components/viz/common/quads/compositor_frame.cc
@@ -4,6 +4,8 @@
#include "components/viz/common/quads/compositor_frame.h"
+#include "base/containers/adapters.h"
+
namespace viz {
CompositorFrame::CompositorFrame() = default;
@@ -14,4 +16,15 @@ CompositorFrame::~CompositorFrame() = default;
CompositorFrame& CompositorFrame::operator=(CompositorFrame&& other) = default;
+bool CompositorFrame::HasCopyOutputRequests() const {
+ // Iterate the RenderPasses back-to-front, because CopyOutputRequests tend to
+ // be made on the later passes.
+ for (const auto& pass : base::Reversed(render_pass_list)) {
+ if (!pass->copy_requests.empty()) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace viz
diff --git a/chromium/components/viz/common/quads/compositor_frame.h b/chromium/components/viz/common/quads/compositor_frame.h
index de77425e1df..b4d639738e4 100644
--- a/chromium/components/viz/common/quads/compositor_frame.h
+++ b/chromium/components/viz/common/quads/compositor_frame.h
@@ -37,6 +37,8 @@ class VIZ_COMMON_EXPORT CompositorFrame {
return render_pass_list.back()->output_rect.size();
}
+ bool HasCopyOutputRequests() const;
+
CompositorFrameMetadata metadata;
std::vector<TransferableResource> resource_list;
// This list is in the order that each RenderPass will be drawn. The last one
diff --git a/chromium/components/viz/common/quads/compositor_frame_metadata.h b/chromium/components/viz/common/quads/compositor_frame_metadata.h
index efa0dd7ed06..c6033d9d5df 100644
--- a/chromium/components/viz/common/quads/compositor_frame_metadata.h
+++ b/chromium/components/viz/common/quads/compositor_frame_metadata.h
@@ -11,6 +11,7 @@
#include "base/optional.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/quads/frame_deadline.h"
#include "components/viz/common/quads/selection.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/common/viz_common_export.h"
@@ -46,7 +47,6 @@ class VIZ_COMMON_EXPORT CompositorFrameMetadata {
gfx::SizeF root_layer_size;
float min_page_scale_factor = 0.f;
float max_page_scale_factor = 0.f;
- bool root_overflow_x_hidden = false;
bool root_overflow_y_hidden = false;
bool may_contain_video = false;
@@ -99,9 +99,11 @@ class VIZ_COMMON_EXPORT CompositorFrameMetadata {
// become available or a deadline hits.
std::vector<SurfaceId> activation_dependencies;
- // This indicates a non-default deadline until this CompositorFrame should
- // be forcibly activated.
- base::Optional<uint32_t> deadline_in_frames;
+ // This specifies a deadline for this CompositorFrame to synchronize with its
+ // activation dependencies. Once this deadline passes, this CompositorFrame
+ // should be forcibly activated. This deadline may be lower-bounded by the
+ // default synchronization deadline specified by the system.
+ FrameDeadline deadline;
// This is a value that allows the browser to associate compositor frames
// with the content that they represent -- typically top-level page loads.
diff --git a/chromium/components/viz/common/quads/frame_deadline.h b/chromium/components/viz/common/quads/frame_deadline.h
new file mode 100644
index 00000000000..faa992f7565
--- /dev/null
+++ b/chromium/components/viz/common/quads/frame_deadline.h
@@ -0,0 +1,61 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_COMMON_QUADS_FRAME_DEADLINE_H_
+#define COMPONENTS_VIZ_COMMON_QUADS_FRAME_DEADLINE_H_
+
+#include "components/viz/common/viz_common_export.h"
+
+#include "base/time/time.h"
+
+namespace viz {
+
+class VIZ_COMMON_EXPORT FrameDeadline {
+ public:
+ FrameDeadline() = default;
+ FrameDeadline(base::TimeTicks frame_start_time,
+ uint32_t deadline_in_frames,
+ base::TimeDelta frame_interval,
+ bool use_default_lower_bound_deadline)
+ : frame_start_time_(frame_start_time),
+ deadline_in_frames_(deadline_in_frames),
+ frame_interval_(frame_interval),
+ use_default_lower_bound_deadline_(use_default_lower_bound_deadline) {}
+
+ FrameDeadline(const FrameDeadline& other) = default;
+
+ FrameDeadline& operator=(const FrameDeadline& other) = default;
+
+ bool operator==(const FrameDeadline& other) const {
+ return other.frame_start_time_ == frame_start_time_ &&
+ other.deadline_in_frames_ == deadline_in_frames_ &&
+ other.frame_interval_ == frame_interval_ &&
+ other.use_default_lower_bound_deadline_ ==
+ use_default_lower_bound_deadline_;
+ }
+
+ bool operator!=(const FrameDeadline& other) const {
+ return !(*this == other);
+ }
+
+ base::TimeTicks frame_start_time() const { return frame_start_time_; }
+
+ uint32_t deadline_in_frames() const { return deadline_in_frames_; }
+
+ base::TimeDelta frame_interval() const { return frame_interval_; }
+
+ bool use_default_lower_bound_deadline() const {
+ return use_default_lower_bound_deadline_;
+ }
+
+ private:
+ base::TimeTicks frame_start_time_;
+ uint32_t deadline_in_frames_ = 0u;
+ base::TimeDelta frame_interval_;
+ bool use_default_lower_bound_deadline_ = true;
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_COMMON_QUADS_FRAME_DEADLINE_H_
diff --git a/chromium/components/viz/common/quads/render_pass.h b/chromium/components/viz/common/quads/render_pass.h
index 1edfee6196a..6da9e23d8f6 100644
--- a/chromium/components/viz/common/quads/render_pass.h
+++ b/chromium/components/viz/common/quads/render_pass.h
@@ -144,8 +144,7 @@ class VIZ_COMMON_EXPORT RenderPass {
// If non-empty, the renderer should produce a copy of the render pass'
// contents as a bitmap, and give a copy of the bitmap to each callback in
- // this list. This property should not be serialized between compositors, as
- // it only makes sense in the root compositor.
+ // this list.
std::vector<std::unique_ptr<CopyOutputRequest>> copy_requests;
QuadList quad_list;
diff --git a/chromium/components/viz/common/resources/DEPS b/chromium/components/viz/common/resources/DEPS
index fe456ebd62e..d7594151d3c 100644
--- a/chromium/components/viz/common/resources/DEPS
+++ b/chromium/components/viz/common/resources/DEPS
@@ -1,6 +1,9 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+gpu/command_buffer/common",
"+gpu/GLES2",
+ "+mojo/public/cpp/system/buffer.h",
"+third_party/khronos/GLES2",
"+third_party/skia",
]
diff --git a/chromium/components/viz/common/resources/resource_format_utils.cc b/chromium/components/viz/common/resources/resource_format_utils.cc
index 93c796cf2db..57a37f19602 100644
--- a/chromium/components/viz/common/resources/resource_format_utils.cc
+++ b/chromium/components/viz/common/resources/resource_format_utils.cc
@@ -18,8 +18,9 @@ SkColorType ResourceFormatToClosestSkColorType(ResourceFormat format) {
case RGBA_4444:
return kARGB_4444_SkColorType;
case RGBA_8888:
+ return kRGBA_8888_SkColorType;
case BGRA_8888:
- return kN32_SkColorType;
+ return kBGRA_8888_SkColorType;
case ALPHA_8:
return kAlpha_8_SkColorType;
case RGB_565:
@@ -165,25 +166,6 @@ gfx::BufferFormat BufferFormat(ResourceFormat format) {
return gfx::BufferFormat::RGBA_8888;
}
-GrPixelConfig ToGrPixelConfig(ResourceFormat format) {
- switch (format) {
- case RGBA_8888:
- return kRGBA_8888_GrPixelConfig;
- case BGRA_8888:
- return kBGRA_8888_GrPixelConfig;
- case RGBA_4444:
- return kRGBA_4444_GrPixelConfig;
- case RGBA_F16:
- return kRGBA_half_GrPixelConfig;
- case ALPHA_8:
- return kAlpha_8_GrPixelConfig;
- default:
- break;
- }
- DCHECK(false) << "Unsupported resource format.";
- return kSkia8888_GrPixelConfig;
-}
-
bool IsResourceFormatCompressed(ResourceFormat format) {
return format == ETC1;
}
@@ -237,4 +219,25 @@ unsigned int TextureStorageFormat(ResourceFormat format) {
return GL_RGBA8_OES;
}
+bool IsGpuMemoryBufferFormatSupported(ResourceFormat format) {
+ switch (format) {
+ case BGRA_8888:
+ case RED_8:
+ case R16_EXT:
+ case RGBA_4444:
+ case RGBA_8888:
+ case ETC1:
+ case RGBA_F16:
+ return true;
+ // These formats have no BufferFormat equivalent.
+ case ALPHA_8:
+ case LUMINANCE_8:
+ case RGB_565:
+ case LUMINANCE_F16:
+ return false;
+ }
+ NOTREACHED();
+ return false;
+}
+
} // namespace viz
diff --git a/chromium/components/viz/common/resources/resource_format_utils.h b/chromium/components/viz/common/resources/resource_format_utils.h
index e13616d9876..1e0a6045878 100644
--- a/chromium/components/viz/common/resources/resource_format_utils.h
+++ b/chromium/components/viz/common/resources/resource_format_utils.h
@@ -35,7 +35,11 @@ VIZ_RESOURCE_FORMAT_EXPORT bool DoesResourceFormatSupportAlpha(
ResourceFormat format);
VIZ_RESOURCE_FORMAT_EXPORT unsigned int TextureStorageFormat(
ResourceFormat format);
-VIZ_RESOURCE_FORMAT_EXPORT GrPixelConfig ToGrPixelConfig(ResourceFormat format);
+
+// Returns whether the format can be used with GpuMemoryBuffer texture storage,
+// allocated through TexStorage2DImageCHROMIUM.
+VIZ_RESOURCE_FORMAT_EXPORT bool IsGpuMemoryBufferFormatSupported(
+ ResourceFormat format);
} // namespace viz
diff --git a/chromium/components/viz/common/resources/resource_settings.h b/chromium/components/viz/common/resources/resource_settings.h
index 2854205b0f0..434f9605c5a 100644
--- a/chromium/components/viz/common/resources/resource_settings.h
+++ b/chromium/components/viz/common/resources/resource_settings.h
@@ -20,7 +20,6 @@ class VIZ_COMMON_EXPORT ResourceSettings {
ResourceSettings& operator=(const ResourceSettings& other);
~ResourceSettings();
- size_t texture_id_allocation_chunk_size = 64;
bool use_gpu_memory_buffer_resources = false;
bool high_bit_for_testing = false;
// TODO(riju): Remove after r16 is used without the flag. crbug.com/759456
diff --git a/chromium/components/viz/common/resources/shared_bitmap_manager.h b/chromium/components/viz/common/resources/shared_bitmap_manager.h
index 630f0d852a0..86b77a646d7 100644
--- a/chromium/components/viz/common/resources/shared_bitmap_manager.h
+++ b/chromium/components/viz/common/resources/shared_bitmap_manager.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "components/viz/common/quads/shared_bitmap.h"
+#include "mojo/public/cpp/system/buffer.h"
#include "ui/gfx/geometry/size.h"
namespace viz {
@@ -18,11 +19,28 @@ class SharedBitmapManager {
SharedBitmapManager() {}
virtual ~SharedBitmapManager() {}
+ // Allocate a shared bitmap that can be given to the display compositor.
virtual std::unique_ptr<SharedBitmap> AllocateSharedBitmap(
const gfx::Size&) = 0;
+
+ // The following methods are only used by the display compositor, but are on
+ // the base interface in order to allow tests (or prod) to implement the
+ // display and client implementations with the same type, in lieu of having
+ // the ServerSharedBitmapManager and ClientSharedBitmapManager be separate
+ // interfaces instead of this single one.
+ // TODO(crbug.com/730660): Intent is to remove the ClientSharedBitmapManager
+ // over time, and make SharedBitmapManager a display-compositor-only concept.
+
+ // Used in the display compositor to find the bitmap associated with an id.
virtual std::unique_ptr<SharedBitmap> GetSharedBitmapFromId(
const gfx::Size&,
const SharedBitmapId&) = 0;
+ // Used in the display compositor to associate an id to a shm handle.
+ virtual bool ChildAllocatedSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) = 0;
+ // Used in the display compositor to break an association of an id to a shm
+ // handle.
+ virtual void ChildDeletedSharedBitmap(const SharedBitmapId& id) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(SharedBitmapManager);
diff --git a/chromium/components/viz/common/resources/transferable_resource.h b/chromium/components/viz/common/resources/transferable_resource.h
index 0f98bf87719..abafc4cf4b6 100644
--- a/chromium/components/viz/common/resources/transferable_resource.h
+++ b/chromium/components/viz/common/resources/transferable_resource.h
@@ -93,10 +93,15 @@ struct VIZ_COMMON_EXPORT TransferableResource {
gfx::Size size;
// The format of the pixels in the gpu mailbox/software bitmap. This should
- // almost always be RGBA_8888 for resources generted by compositor clients,
+ // almost always be RGBA_8888 for resources generated by compositor clients,
// and must be RGBA_8888 always for software resources.
ResourceFormat format = RGBA_8888;
+ // Normally derrived from the |format|, but may differ for some resource
+ // producers. This is the format of the underlying texture backing for gpu
+ // resources, needed for using the backing as an overlay.
+ gfx::BufferFormat buffer_format = gfx::BufferFormat::RGBA_8888;
+
// The |mailbox| inside here holds the gpu::Mailbox when this is a gpu
// resource, or the SharedBitmapId when it is a software resource.
// The |texture_target| and sync_token| inside here only apply for gpu
@@ -117,10 +122,9 @@ struct VIZ_COMMON_EXPORT TransferableResource {
// drawing it. Typically GL_LINEAR, or GL_NEAREST if no anti-aliasing
// during scaling is desired.
uint32_t filter = 0;
- // If a gpu resource is backed by a GpuMemoryBuffer, this specifies the
- // format of that buffer, which may not match the |format|.
- gfx::BufferFormat buffer_format = gfx::BufferFormat::RGBA_8888;
- // Whether a gpu fence needs to be used for reading a gpu resource.
+ // If a gpu resource is backed by a GpuMemoryBuffer, then it will be accessed
+ // out-of-band, and a gpu fence needs to be waited on before the resource is
+ // returned and reused.
bool read_lock_fences_enabled = false;
#if defined(OS_ANDROID)
// Indicates whether this resource may not be overlayed on Android, since
@@ -138,21 +142,20 @@ struct VIZ_COMMON_EXPORT TransferableResource {
#endif
bool operator==(const TransferableResource& o) const {
- return id == o.id && format == o.format &&
- buffer_format == o.buffer_format && filter == o.filter &&
- size == o.size &&
+ return id == o.id && is_software == o.is_software && size == o.size &&
+ format == o.format && buffer_format == o.buffer_format &&
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 &&
- read_lock_fences_enabled == o.read_lock_fences_enabled &&
- is_software == o.is_software &&
+ color_space == o.color_space &&
shared_bitmap_sequence_number == o.shared_bitmap_sequence_number &&
+ is_overlay_candidate == o.is_overlay_candidate &&
+ filter == o.filter &&
#if defined(OS_ANDROID)
is_backed_by_surface_texture == o.is_backed_by_surface_texture &&
wants_promotion_hint == o.wants_promotion_hint &&
#endif
- is_overlay_candidate == o.is_overlay_candidate &&
- color_space == o.color_space;
+ read_lock_fences_enabled == o.read_lock_fences_enabled;
}
bool operator!=(const TransferableResource& o) const { return !(*this == o); }
};
diff --git a/chromium/components/viz/common/surfaces/DEPS b/chromium/components/viz/common/surfaces/DEPS
index 16764a92a85..a04d4aa491c 100644
--- a/chromium/components/viz/common/surfaces/DEPS
+++ b/chromium/components/viz/common/surfaces/DEPS
@@ -1,3 +1,5 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+mojo/public/cpp/bindings",
]
diff --git a/chromium/components/viz/common/surfaces/child_local_surface_id_allocator.cc b/chromium/components/viz/common/surfaces/child_local_surface_id_allocator.cc
new file mode 100644
index 00000000000..b996adfe3ef
--- /dev/null
+++ b/chromium/components/viz/common/surfaces/child_local_surface_id_allocator.cc
@@ -0,0 +1,45 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/common/surfaces/child_local_surface_id_allocator.h"
+
+#include <stdint.h>
+
+#include "base/rand_util.h"
+
+namespace viz {
+
+ChildLocalSurfaceIdAllocator::ChildLocalSurfaceIdAllocator()
+ : last_known_local_surface_id_(kInvalidParentSequenceNumber,
+ kInitialChildSequenceNumber,
+ base::UnguessableToken()) {}
+
+const LocalSurfaceId& ChildLocalSurfaceIdAllocator::UpdateFromParent(
+ const LocalSurfaceId& parent_allocated_local_surface_id) {
+ DCHECK_GE(parent_allocated_local_surface_id.parent_sequence_number(),
+ last_known_local_surface_id_.parent_sequence_number());
+ // Thie verifies that we only update the nonce if the parent sequence number
+ // has changed.
+ DCHECK(parent_allocated_local_surface_id.parent_sequence_number() >
+ last_known_local_surface_id_.parent_sequence_number() ||
+ parent_allocated_local_surface_id.nonce() ==
+ last_known_local_surface_id_.nonce());
+
+ last_known_local_surface_id_.parent_sequence_number_ =
+ parent_allocated_local_surface_id.parent_sequence_number_;
+ last_known_local_surface_id_.nonce_ =
+ parent_allocated_local_surface_id.nonce_;
+ return last_known_local_surface_id_;
+}
+
+const LocalSurfaceId& ChildLocalSurfaceIdAllocator::GenerateId() {
+ // UpdateFromParent must be called before we can generate a valid ID.
+ DCHECK_NE(last_known_local_surface_id_.parent_sequence_number(),
+ kInvalidParentSequenceNumber);
+
+ ++last_known_local_surface_id_.child_sequence_number_;
+ return last_known_local_surface_id_;
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/common/surfaces/child_local_surface_id_allocator.h b/chromium/components/viz/common/surfaces/child_local_surface_id_allocator.h
new file mode 100644
index 00000000000..1f7608b7c55
--- /dev/null
+++ b/chromium/components/viz/common/surfaces/child_local_surface_id_allocator.h
@@ -0,0 +1,51 @@
+// Copyright 2018 The Chromium Authors. All 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_SURFACES_CHILD_LOCAL_SURFACE_ID_ALLOCATOR_H_
+#define COMPONENTS_VIZ_COMMON_SURFACES_CHILD_LOCAL_SURFACE_ID_ALLOCATOR_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "base/unguessable_token.h"
+#include "components/viz/common/surfaces/surface_id.h"
+#include "components/viz/common/viz_common_export.h"
+
+namespace viz {
+
+// This is a helper class for generating local surface IDs for a single
+// FrameSink. This is not threadsafe, to use from multiple threads wrap this
+// class in a mutex.
+// The parent embeds a child's surface. The child allocates a surface when it
+// changes its contents or surface parameters, for example.
+// This is that child allocator.
+class VIZ_COMMON_EXPORT ChildLocalSurfaceIdAllocator {
+ public:
+ ChildLocalSurfaceIdAllocator();
+ ChildLocalSurfaceIdAllocator(ChildLocalSurfaceIdAllocator&& other) = default;
+ ChildLocalSurfaceIdAllocator& operator=(
+ ChildLocalSurfaceIdAllocator&& other) = default;
+ ~ChildLocalSurfaceIdAllocator() = default;
+
+ // When a parent-allocated LocalSurfaceId arrives in the child, the child
+ // needs to update its understanding of the last generated message so the
+ // messages can continue to monotonically increase.
+ const LocalSurfaceId& UpdateFromParent(
+ const LocalSurfaceId& parent_allocated_local_surface_id);
+
+ const LocalSurfaceId& GenerateId();
+
+ const LocalSurfaceId& last_known_local_surface_id() const {
+ return last_known_local_surface_id_;
+ }
+
+ private:
+ LocalSurfaceId last_known_local_surface_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChildLocalSurfaceIdAllocator);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_COMMON_SURFACES_CHILD_LOCAL_SURFACE_ID_ALLOCATOR_H_
diff --git a/chromium/components/viz/common/surfaces/child_local_surface_id_allocator_unittest.cc b/chromium/components/viz/common/surfaces/child_local_surface_id_allocator_unittest.cc
new file mode 100644
index 00000000000..cda296e0f93
--- /dev/null
+++ b/chromium/components/viz/common/surfaces/child_local_surface_id_allocator_unittest.cc
@@ -0,0 +1,178 @@
+// Copyright 2018 The Chromium Authors. All 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/surfaces/child_local_surface_id_allocator.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+// ChildLocalSurfaceIdAllocator has 1 accessor which does not alter state:
+// - last_known_local_surface_id()
+//
+// For every operation which changes state we can test:
+// - the operation completed as expected,
+// - the accessors did not change, and/or
+// - the accessors changed in the way we expected.
+
+namespace viz {
+namespace {
+
+::testing::AssertionResult ParentSequenceNumberIsNotSet(
+ const LocalSurfaceId& local_surface_id);
+::testing::AssertionResult ChildSequenceNumberIsSet(
+ const LocalSurfaceId& local_surface_id);
+::testing::AssertionResult NonceIsEmpty(const LocalSurfaceId& local_surface_id);
+
+LocalSurfaceId GetFakeParentAllocatedLocalSurfaceId();
+ChildLocalSurfaceIdAllocator GetParentUpdatedAllocator();
+
+} // namespace
+
+// The default constructor should initialize its last-known LocalSurfaceId (and
+// all of its components) to an invalid state.
+TEST(ChildLocalSurfaceIdAllocatorTest,
+ DefaultConstructorShouldNotSetLocalSurfaceIdComponents) {
+ ChildLocalSurfaceIdAllocator default_constructed_child_allocator;
+
+ const LocalSurfaceId& default_local_surface_id =
+ default_constructed_child_allocator.last_known_local_surface_id();
+ EXPECT_FALSE(default_local_surface_id.is_valid());
+ EXPECT_TRUE(ParentSequenceNumberIsNotSet(default_local_surface_id));
+ EXPECT_TRUE(ChildSequenceNumberIsSet(default_local_surface_id));
+ EXPECT_TRUE(NonceIsEmpty(default_local_surface_id));
+}
+
+// The move constructor should move the last-known LocalSurfaceId.
+TEST(ChildLocalSurfaceIdAllocatorTest,
+ MoveConstructorShouldMoveLastKnownLocalSurfaceId) {
+ ChildLocalSurfaceIdAllocator moving_child_allocator =
+ GetParentUpdatedAllocator();
+ LocalSurfaceId premoved_local_surface_id =
+ moving_child_allocator.last_known_local_surface_id();
+
+ ChildLocalSurfaceIdAllocator moved_to_child_allocator =
+ std::move(moving_child_allocator);
+
+ EXPECT_EQ(premoved_local_surface_id,
+ moved_to_child_allocator.last_known_local_surface_id());
+}
+
+// The move assignment operator should move the last-known LocalSurfaceId.
+TEST(ChildLocalSurfaceIdAllocatorTest,
+ MoveAssignmentOperatorShouldMoveLastKnownLocalSurfaceId) {
+ ChildLocalSurfaceIdAllocator moving_child_allocator =
+ GetParentUpdatedAllocator();
+ LocalSurfaceId premoved_local_surface_id =
+ moving_child_allocator.last_known_local_surface_id();
+ ChildLocalSurfaceIdAllocator moved_to_child_allocator;
+ EXPECT_NE(premoved_local_surface_id,
+ moved_to_child_allocator.last_known_local_surface_id());
+
+ moved_to_child_allocator = std::move(moving_child_allocator);
+
+ EXPECT_EQ(premoved_local_surface_id,
+ moved_to_child_allocator.last_known_local_surface_id());
+}
+
+// UpdateFromParent() on a child allocator should accept the parent's sequence
+// number and nonce. But it should continue to use its own child sequence
+// number.
+TEST(ChildLocalSurfaceIdAllocatorTest,
+ UpdateFromParentOnlyUpdatesExpectedLocalSurfaceIdComponents) {
+ ChildLocalSurfaceIdAllocator parent_updated_child_allocator;
+ LocalSurfaceId preupdate_local_surface_id =
+ parent_updated_child_allocator.last_known_local_surface_id();
+ LocalSurfaceId parent_allocated_local_surface_id =
+ GetFakeParentAllocatedLocalSurfaceId();
+ EXPECT_NE(preupdate_local_surface_id.parent_sequence_number(),
+ parent_allocated_local_surface_id.parent_sequence_number());
+ EXPECT_NE(preupdate_local_surface_id.child_sequence_number(),
+ parent_allocated_local_surface_id.child_sequence_number());
+ EXPECT_NE(preupdate_local_surface_id.nonce(),
+ parent_allocated_local_surface_id.nonce());
+
+ const LocalSurfaceId& returned_local_surface_id =
+ parent_updated_child_allocator.UpdateFromParent(
+ parent_allocated_local_surface_id);
+
+ const LocalSurfaceId& postupdate_local_surface_id =
+ parent_updated_child_allocator.last_known_local_surface_id();
+ EXPECT_EQ(postupdate_local_surface_id.parent_sequence_number(),
+ parent_allocated_local_surface_id.parent_sequence_number());
+ EXPECT_NE(postupdate_local_surface_id.child_sequence_number(),
+ parent_allocated_local_surface_id.child_sequence_number());
+ EXPECT_EQ(postupdate_local_surface_id.nonce(),
+ parent_allocated_local_surface_id.nonce());
+ EXPECT_EQ(returned_local_surface_id,
+ parent_updated_child_allocator.last_known_local_surface_id());
+}
+
+// GenerateId() on a child allocator should monotonically increment the child
+// sequence number.
+TEST(ChildLocalSurfaceIdAllocatorTest,
+ GenerateIdOnlyUpdatesExpectedLocalSurfaceIdComponents) {
+ ChildLocalSurfaceIdAllocator generating_child_allocator =
+ GetParentUpdatedAllocator();
+ LocalSurfaceId pregenerateid_local_surface_id =
+ generating_child_allocator.last_known_local_surface_id();
+
+ const LocalSurfaceId& returned_local_surface_id =
+ generating_child_allocator.GenerateId();
+
+ const LocalSurfaceId& postgenerateid_local_surface_id =
+ generating_child_allocator.last_known_local_surface_id();
+ EXPECT_EQ(pregenerateid_local_surface_id.parent_sequence_number(),
+ postgenerateid_local_surface_id.parent_sequence_number());
+ EXPECT_EQ(pregenerateid_local_surface_id.child_sequence_number() + 1,
+ postgenerateid_local_surface_id.child_sequence_number());
+ EXPECT_EQ(pregenerateid_local_surface_id.nonce(),
+ postgenerateid_local_surface_id.nonce());
+ EXPECT_EQ(returned_local_surface_id,
+ generating_child_allocator.last_known_local_surface_id());
+}
+
+namespace {
+
+::testing::AssertionResult ParentSequenceNumberIsNotSet(
+ const LocalSurfaceId& local_surface_id) {
+ if (local_surface_id.parent_sequence_number() == kInvalidParentSequenceNumber)
+ return ::testing::AssertionSuccess();
+
+ return ::testing::AssertionFailure() << "parent_sequence_number() is set";
+}
+
+::testing::AssertionResult ChildSequenceNumberIsSet(
+ const LocalSurfaceId& local_surface_id) {
+ if (local_surface_id.child_sequence_number() != kInvalidChildSequenceNumber)
+ return ::testing::AssertionSuccess();
+
+ return ::testing::AssertionFailure() << "child_sequence_number() is not set";
+}
+
+::testing::AssertionResult NonceIsEmpty(
+ const LocalSurfaceId& local_surface_id) {
+ if (local_surface_id.nonce().is_empty())
+ return ::testing::AssertionSuccess();
+
+ return ::testing::AssertionFailure() << "nonce() is not empty";
+}
+
+LocalSurfaceId GetFakeParentAllocatedLocalSurfaceId() {
+ constexpr uint32_t kParentSequenceNumber = 3;
+ constexpr uint32_t kChildSequenceNumber = 2;
+ const base::UnguessableToken nonce = base::UnguessableToken::Create();
+
+ return LocalSurfaceId(kParentSequenceNumber, kChildSequenceNumber, nonce);
+}
+
+ChildLocalSurfaceIdAllocator GetParentUpdatedAllocator() {
+ ChildLocalSurfaceIdAllocator parent_updated_child_allocator;
+ LocalSurfaceId parent_allocated_local_surface_id =
+ GetFakeParentAllocatedLocalSurfaceId();
+ parent_updated_child_allocator.UpdateFromParent(
+ parent_allocated_local_surface_id);
+ return parent_updated_child_allocator;
+}
+
+} // namespace
+} // namespace viz
diff --git a/chromium/components/viz/common/surfaces/local_surface_id.cc b/chromium/components/viz/common/surfaces/local_surface_id.cc
index eea2ecebf56..97577b08022 100644
--- a/chromium/components/viz/common/surfaces/local_surface_id.cc
+++ b/chromium/components/viz/common/surfaces/local_surface_id.cc
@@ -9,9 +9,12 @@
namespace viz {
std::string LocalSurfaceId::ToString() const {
- return base::StringPrintf("LocalSurfaceId(%d, %d, %s" PRIu64 ")",
+ std::string nonce = VLOG_IS_ON(1) ? nonce_.ToString()
+ : nonce_.ToString().substr(0, 4) + "...";
+
+ return base::StringPrintf("LocalSurfaceId(%d, %d, %s)",
parent_sequence_number_, child_sequence_number_,
- nonce_.ToString().c_str());
+ nonce.c_str());
}
std::ostream& operator<<(std::ostream& out,
diff --git a/chromium/components/viz/common/surfaces/local_surface_id.h b/chromium/components/viz/common/surfaces/local_surface_id.h
index 44a884a8cf0..3d2e86f6669 100644
--- a/chromium/components/viz/common/surfaces/local_surface_id.h
+++ b/chromium/components/viz/common/surfaces/local_surface_id.h
@@ -21,10 +21,43 @@ namespace mojom {
class LocalSurfaceIdDataView;
}
+class ParentLocalSurfaceIdAllocator;
+class ChildLocalSurfaceIdAllocator;
+
+constexpr uint32_t kInvalidParentSequenceNumber = 0;
+constexpr uint32_t kInvalidChildSequenceNumber = 0;
+constexpr uint32_t kInitialChildSequenceNumber = 1;
+
+// This struct is the part of SurfaceId that can be modified by the client.
+// LocalSurfaceId uniquely identifies a surface among the surfaces created by a
+// particular client. A SurfaceId, which is FrameSinkId+LocalSurfaceId, uniquely
+// identifies a surface globally across all clients.
+//
+// LocalSurfaceId consists of:
+//
+// - parent_sequence_number: This part is incremented by the embedder of the
+// client.
+//
+// - child_sequence_number: This part is incremented by the client itself.
+//
+// - nonce: An UnguessableToken generated by the embedder. The purpose of this
+// value is to make SurfaceIds unguessable, because FrameSinkIds and
+// LocalSurfaceIds are otherwise predictable and clients might exploit this
+// fact to embed surfaces they're not allowed to. This value is generated once
+// by ParentLocalSurfaceIdAllocator and remains constant during the lifetime
+// of the allocator.
+//
+// The embedder uses ParentLocalSurfaceIdAllocator to generate LocalSurfaceIds
+// for the embedee. If Surface Synchronization is on, the embedee uses
+// ChildLocalSurfaceIdAllocator to generate LocalSurfaceIds for itself. If
+// Surface Synchronization is off, the embedee also uses
+// ParentLocalSurfaceIdAllocator, as the parent doesn't generate LocalSurfaceIds
+// for the child.
class VIZ_COMMON_EXPORT LocalSurfaceId {
public:
constexpr LocalSurfaceId()
- : parent_sequence_number_(0), child_sequence_number_(0) {}
+ : parent_sequence_number_(kInvalidParentSequenceNumber),
+ child_sequence_number_(kInvalidChildSequenceNumber) {}
constexpr LocalSurfaceId(const LocalSurfaceId& other)
: parent_sequence_number_(other.parent_sequence_number_),
@@ -34,7 +67,7 @@ class VIZ_COMMON_EXPORT LocalSurfaceId {
constexpr LocalSurfaceId(uint32_t parent_sequence_number,
const base::UnguessableToken& nonce)
: parent_sequence_number_(parent_sequence_number),
- child_sequence_number_(1),
+ child_sequence_number_(kInitialChildSequenceNumber),
nonce_(nonce) {}
constexpr LocalSurfaceId(uint32_t parent_sequence_number,
@@ -45,7 +78,8 @@ class VIZ_COMMON_EXPORT LocalSurfaceId {
nonce_(nonce) {}
constexpr bool is_valid() const {
- return parent_sequence_number_ != 0 && child_sequence_number_ != 0 &&
+ return parent_sequence_number_ != kInvalidParentSequenceNumber &&
+ child_sequence_number_ != kInvalidChildSequenceNumber &&
!nonce_.is_empty();
}
@@ -82,6 +116,8 @@ class VIZ_COMMON_EXPORT LocalSurfaceId {
private:
friend struct mojo::StructTraits<mojom::LocalSurfaceIdDataView,
LocalSurfaceId>;
+ friend class ParentLocalSurfaceIdAllocator;
+ friend class ChildLocalSurfaceIdAllocator;
friend bool operator<(const LocalSurfaceId& lhs, const LocalSurfaceId& rhs);
diff --git a/chromium/components/viz/common/surfaces/local_surface_id_unittest.cc b/chromium/components/viz/common/surfaces/local_surface_id_unittest.cc
new file mode 100644
index 00000000000..ce97c7460bb
--- /dev/null
+++ b/chromium/components/viz/common/surfaces/local_surface_id_unittest.cc
@@ -0,0 +1,58 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/common/surfaces/local_surface_id.h"
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Verifying that Local_Surface_Id::ToString() prints its corresponding
+// UnguessableToken as ABCD... if logging is not verbose and prints full
+// 16-character token otherwise.
+TEST(LocalSurfaceIdTest, VerifyToString) {
+ const base::UnguessableToken token =
+ base::UnguessableToken::Deserialize(0x111111, 0);
+ const base::UnguessableToken big_token =
+ base::UnguessableToken::Deserialize(0x123456789, 0xABCABCABC);
+ const base::UnguessableToken small_token =
+ base::UnguessableToken::Deserialize(0, 0x1);
+ const viz::LocalSurfaceId local_surface_id(11, 22, token);
+ const viz::LocalSurfaceId big_local_surface_id(11, 22, big_token);
+ const viz::LocalSurfaceId small_local_surface_id(11, 22, small_token);
+
+ const std::string verbose_expected =
+ "LocalSurfaceId(11, 22, " + token.ToString() + ")";
+ const std::string brief_expected =
+ "LocalSurfaceId(11, 22, " + token.ToString().substr(0, 4) + "...)";
+
+ const std::string big_verbose_expected =
+ "LocalSurfaceId(11, 22, " + big_token.ToString() + ")";
+ const std::string big_brief_expected =
+ "LocalSurfaceId(11, 22, " + big_token.ToString().substr(0, 4) + "...)";
+
+ const std::string small_verbose_expected =
+ "LocalSurfaceId(11, 22, " + small_token.ToString() + ")";
+ const std::string small_brief_expected =
+ "LocalSurfaceId(11, 22, " + small_token.ToString().substr(0, 4) + "...)";
+
+ int previous_log_lvl = logging::GetMinLogLevel();
+
+ // When |g_min_log_level| is set to LOG_VERBOSE we expect verbose versions
+ // of local_surface_id::ToString().
+ logging::SetMinLogLevel(logging::LOG_VERBOSE);
+ EXPECT_TRUE(VLOG_IS_ON(1));
+ EXPECT_EQ(verbose_expected, local_surface_id.ToString());
+ EXPECT_EQ(big_verbose_expected, big_local_surface_id.ToString());
+ EXPECT_EQ(small_verbose_expected, small_local_surface_id.ToString());
+
+ // When |g_min_log_level| is set to LOG_INFO we expect less verbose versions
+ // of local_surface_id::ToString().
+ logging::SetMinLogLevel(logging::LOG_INFO);
+ EXPECT_FALSE(VLOG_IS_ON(1));
+ EXPECT_EQ(brief_expected, local_surface_id.ToString());
+ EXPECT_EQ(big_brief_expected, big_local_surface_id.ToString());
+ EXPECT_EQ(small_brief_expected, small_local_surface_id.ToString());
+
+ logging::SetMinLogLevel(previous_log_lvl);
+}
diff --git a/chromium/components/viz/common/surfaces/parent_local_surface_id_allocator.cc b/chromium/components/viz/common/surfaces/parent_local_surface_id_allocator.cc
index a5a5512f3d7..3716021cc2b 100644
--- a/chromium/components/viz/common/surfaces/parent_local_surface_id_allocator.cc
+++ b/chromium/components/viz/common/surfaces/parent_local_surface_id_allocator.cc
@@ -4,21 +4,33 @@
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
-#include <stdint.h>
-
#include "base/rand_util.h"
-#include "base/unguessable_token.h"
namespace viz {
-ParentLocalSurfaceIdAllocator::ParentLocalSurfaceIdAllocator() : next_id_(1u) {}
+ParentLocalSurfaceIdAllocator::ParentLocalSurfaceIdAllocator()
+ : last_known_local_surface_id_(kInvalidParentSequenceNumber,
+ kInitialChildSequenceNumber,
+ base::UnguessableToken::Create()) {}
+
+const LocalSurfaceId& ParentLocalSurfaceIdAllocator::UpdateFromChild(
+ const LocalSurfaceId& child_allocated_local_surface_id) {
+ DCHECK_GE(child_allocated_local_surface_id.child_sequence_number(),
+ last_known_local_surface_id_.child_sequence_number());
-ParentLocalSurfaceIdAllocator::~ParentLocalSurfaceIdAllocator() {}
+ last_known_local_surface_id_.child_sequence_number_ =
+ child_allocated_local_surface_id.child_sequence_number_;
+ return last_known_local_surface_id_;
+}
+
+void ParentLocalSurfaceIdAllocator::Reset(
+ const LocalSurfaceId& local_surface_id) {
+ last_known_local_surface_id_ = local_surface_id;
+}
-LocalSurfaceId ParentLocalSurfaceIdAllocator::GenerateId() {
- LocalSurfaceId id(next_id_, base::UnguessableToken::Create());
- next_id_++;
- return id;
+const LocalSurfaceId& ParentLocalSurfaceIdAllocator::GenerateId() {
+ ++last_known_local_surface_id_.parent_sequence_number_;
+ return last_known_local_surface_id_;
}
} // namespace viz
diff --git a/chromium/components/viz/common/surfaces/parent_local_surface_id_allocator.h b/chromium/components/viz/common/surfaces/parent_local_surface_id_allocator.h
index d30d27227a4..a1b32a9883f 100644
--- a/chromium/components/viz/common/surfaces/parent_local_surface_id_allocator.h
+++ b/chromium/components/viz/common/surfaces/parent_local_surface_id_allocator.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "base/macros.h"
+#include "base/unguessable_token.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/common/viz_common_export.h"
@@ -21,12 +22,29 @@ namespace viz {
class VIZ_COMMON_EXPORT ParentLocalSurfaceIdAllocator {
public:
ParentLocalSurfaceIdAllocator();
- ~ParentLocalSurfaceIdAllocator();
+ ParentLocalSurfaceIdAllocator(ParentLocalSurfaceIdAllocator&& other) =
+ default;
+ ParentLocalSurfaceIdAllocator& operator=(
+ ParentLocalSurfaceIdAllocator&& other) = default;
+ ~ParentLocalSurfaceIdAllocator() = default;
- LocalSurfaceId GenerateId();
+ // When a child-allocated LocalSurfaceId arrives in the parent, the parent
+ // needs to update its understanding of the last generated message so the
+ // messages can continue to monotonically increase.
+ const LocalSurfaceId& UpdateFromChild(
+ const LocalSurfaceId& child_allocated_local_surface_id);
+
+ // Resets this allocator with the provided |local_surface_id| as a seed.
+ void Reset(const LocalSurfaceId& local_surface_id);
+
+ const LocalSurfaceId& GenerateId();
+
+ const LocalSurfaceId& last_known_local_surface_id() const {
+ return last_known_local_surface_id_;
+ }
private:
- uint32_t next_id_;
+ LocalSurfaceId last_known_local_surface_id_;
DISALLOW_COPY_AND_ASSIGN(ParentLocalSurfaceIdAllocator);
};
diff --git a/chromium/components/viz/common/surfaces/parent_local_surface_id_allocator_unittest.cc b/chromium/components/viz/common/surfaces/parent_local_surface_id_allocator_unittest.cc
new file mode 100644
index 00000000000..37f2acd6cef
--- /dev/null
+++ b/chromium/components/viz/common/surfaces/parent_local_surface_id_allocator_unittest.cc
@@ -0,0 +1,207 @@
+// Copyright 2018 The Chromium Authors. All 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/surfaces/parent_local_surface_id_allocator.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+// ParentLocalSurfaceIdAllocator has 1 accessor which does not alter state:
+// - last_known_local_surface_id()
+//
+// For every operation which changes state we can test:
+// - the operation completed as expected,
+// - the accessors did not change, and/or
+// - the accessors changed in the way we expected.
+
+namespace viz {
+namespace {
+
+::testing::AssertionResult ParentSequenceNumberIsNotSet(
+ const LocalSurfaceId& local_surface_id);
+::testing::AssertionResult ChildSequenceNumberIsSet(
+ const LocalSurfaceId& local_surface_id);
+::testing::AssertionResult NonceIsEmpty(const LocalSurfaceId& local_surface_id);
+
+LocalSurfaceId GetFakeChildAllocatedLocalSurfaceId();
+ParentLocalSurfaceIdAllocator GetChildUpdatedAllocator();
+
+} // namespace
+
+// The default constructor should generate a nonce and initialize the sequence
+// number of the last known LocalSurfaceId to an invalid state.
+TEST(ParentLocalSurfaceIdAllocatorTest,
+ DefaultConstructorShouldNotSetLocalSurfaceIdComponents) {
+ ParentLocalSurfaceIdAllocator default_constructed_parent_allocator;
+
+ const LocalSurfaceId& default_local_surface_id =
+ default_constructed_parent_allocator.last_known_local_surface_id();
+ EXPECT_FALSE(default_local_surface_id.is_valid());
+ EXPECT_TRUE(ParentSequenceNumberIsNotSet(default_local_surface_id));
+ EXPECT_TRUE(ChildSequenceNumberIsSet(default_local_surface_id));
+ EXPECT_FALSE(NonceIsEmpty(default_local_surface_id));
+}
+
+// The move constructor should move the last-known LocalSurfaceId.
+TEST(ParentLocalSurfaceIdAllocatorTest,
+ MoveConstructorShouldMoveLastKnownLocalSurfaceId) {
+ ParentLocalSurfaceIdAllocator moving_parent_allocator =
+ GetChildUpdatedAllocator();
+ LocalSurfaceId premoved_local_surface_id =
+ moving_parent_allocator.last_known_local_surface_id();
+
+ ParentLocalSurfaceIdAllocator moved_to_parent_allocator =
+ std::move(moving_parent_allocator);
+
+ EXPECT_EQ(premoved_local_surface_id,
+ moved_to_parent_allocator.last_known_local_surface_id());
+}
+
+// The move assignment operator should move the last-known LocalSurfaceId.
+TEST(ParentLocalSurfaceIdAllocatorTest,
+ MoveAssignmentOperatorShouldMoveLastKnownLocalSurfaceId) {
+ ParentLocalSurfaceIdAllocator moving_parent_allocator =
+ GetChildUpdatedAllocator();
+ LocalSurfaceId premoved_local_surface_id =
+ moving_parent_allocator.last_known_local_surface_id();
+ ParentLocalSurfaceIdAllocator moved_to_parent_allocator;
+ EXPECT_NE(premoved_local_surface_id,
+ moved_to_parent_allocator.last_known_local_surface_id());
+
+ moved_to_parent_allocator = std::move(moving_parent_allocator);
+
+ EXPECT_EQ(premoved_local_surface_id,
+ moved_to_parent_allocator.last_known_local_surface_id());
+}
+
+// UpdateFromChild() on a parent allocator should accept the child's sequence
+// number. But it should continue to use its own parent sequence number and
+// nonce.
+TEST(ParentLocalSurfaceIdAllocatorTest,
+ UpdateFromChildOnlyUpdatesExpectedLocalSurfaceIdComponents) {
+ ParentLocalSurfaceIdAllocator child_updated_parent_allocator;
+ LocalSurfaceId preupdate_local_surface_id =
+ child_updated_parent_allocator.last_known_local_surface_id();
+ LocalSurfaceId child_allocated_local_surface_id =
+ GetFakeChildAllocatedLocalSurfaceId();
+ EXPECT_NE(preupdate_local_surface_id.parent_sequence_number(),
+ child_allocated_local_surface_id.parent_sequence_number());
+ EXPECT_NE(preupdate_local_surface_id.child_sequence_number(),
+ child_allocated_local_surface_id.child_sequence_number());
+ EXPECT_NE(preupdate_local_surface_id.nonce(),
+ child_allocated_local_surface_id.nonce());
+
+ const LocalSurfaceId& returned_local_surface_id =
+ child_updated_parent_allocator.UpdateFromChild(
+ child_allocated_local_surface_id);
+
+ const LocalSurfaceId& postupdate_local_surface_id =
+ child_updated_parent_allocator.last_known_local_surface_id();
+ EXPECT_NE(postupdate_local_surface_id.parent_sequence_number(),
+ child_allocated_local_surface_id.parent_sequence_number());
+ EXPECT_EQ(postupdate_local_surface_id.child_sequence_number(),
+ child_allocated_local_surface_id.child_sequence_number());
+ EXPECT_NE(postupdate_local_surface_id.nonce(),
+ child_allocated_local_surface_id.nonce());
+ EXPECT_EQ(returned_local_surface_id,
+ child_updated_parent_allocator.last_known_local_surface_id());
+}
+
+// GenerateId() on a parent allocator should monotonically increment the parent
+// sequence number and use the previous nonce.
+TEST(ParentLocalSurfaceIdAllocatorTest,
+ GenerateIdOnlyUpdatesExpectedLocalSurfaceIdComponents) {
+ ParentLocalSurfaceIdAllocator generating_parent_allocator =
+ GetChildUpdatedAllocator();
+ LocalSurfaceId pregenerateid_local_surface_id =
+ generating_parent_allocator.last_known_local_surface_id();
+
+ const LocalSurfaceId& returned_local_surface_id =
+ generating_parent_allocator.GenerateId();
+
+ const LocalSurfaceId& postgenerateid_local_surface_id =
+ generating_parent_allocator.last_known_local_surface_id();
+ EXPECT_EQ(pregenerateid_local_surface_id.parent_sequence_number() + 1,
+ postgenerateid_local_surface_id.parent_sequence_number());
+ EXPECT_EQ(pregenerateid_local_surface_id.child_sequence_number(),
+ postgenerateid_local_surface_id.child_sequence_number());
+ EXPECT_EQ(pregenerateid_local_surface_id.nonce(),
+ postgenerateid_local_surface_id.nonce());
+ EXPECT_EQ(returned_local_surface_id,
+ generating_parent_allocator.last_known_local_surface_id());
+}
+
+// This test verifies that calling reset with a LocalSurfaceId updates the
+// last_known_local_surface_id and affects GenerateId.
+TEST(ParentLocalSurfaceIdAllocatorTest, ResetUpdatesComponents) {
+ ParentLocalSurfaceIdAllocator default_constructed_parent_allocator;
+
+ LocalSurfaceId default_local_surface_id =
+ default_constructed_parent_allocator.last_known_local_surface_id();
+ EXPECT_FALSE(default_local_surface_id.is_valid());
+ EXPECT_TRUE(ParentSequenceNumberIsNotSet(default_local_surface_id));
+ EXPECT_TRUE(ChildSequenceNumberIsSet(default_local_surface_id));
+ EXPECT_FALSE(NonceIsEmpty(default_local_surface_id));
+
+ LocalSurfaceId new_local_surface_id(
+ 1u, 1u, base::UnguessableToken::Deserialize(0, 1u));
+
+ default_constructed_parent_allocator.Reset(new_local_surface_id);
+ EXPECT_EQ(new_local_surface_id,
+ default_constructed_parent_allocator.last_known_local_surface_id());
+
+ LocalSurfaceId generated_id =
+ default_constructed_parent_allocator.GenerateId();
+
+ EXPECT_EQ(generated_id.nonce(), new_local_surface_id.nonce());
+ EXPECT_EQ(generated_id.child_sequence_number(),
+ new_local_surface_id.child_sequence_number());
+ EXPECT_EQ(generated_id.parent_sequence_number(),
+ new_local_surface_id.child_sequence_number() + 1);
+}
+
+namespace {
+
+::testing::AssertionResult ParentSequenceNumberIsNotSet(
+ const LocalSurfaceId& local_surface_id) {
+ if (local_surface_id.parent_sequence_number() == kInvalidParentSequenceNumber)
+ return ::testing::AssertionSuccess();
+
+ return ::testing::AssertionFailure() << "parent_sequence_number() is set";
+}
+
+::testing::AssertionResult ChildSequenceNumberIsSet(
+ const LocalSurfaceId& local_surface_id) {
+ if (local_surface_id.child_sequence_number() != kInvalidChildSequenceNumber)
+ return ::testing::AssertionSuccess();
+
+ return ::testing::AssertionFailure() << "child_sequence_number() is not set";
+}
+
+::testing::AssertionResult NonceIsEmpty(
+ const LocalSurfaceId& local_surface_id) {
+ if (local_surface_id.nonce().is_empty())
+ return ::testing::AssertionSuccess();
+
+ return ::testing::AssertionFailure() << "nonce() is not empty";
+}
+
+LocalSurfaceId GetFakeChildAllocatedLocalSurfaceId() {
+ constexpr uint32_t kParentSequenceNumber = 1;
+ constexpr uint32_t kChildSequenceNumber = 3;
+ const base::UnguessableToken nonce = base::UnguessableToken::Create();
+
+ return LocalSurfaceId(kParentSequenceNumber, kChildSequenceNumber, nonce);
+}
+
+ParentLocalSurfaceIdAllocator GetChildUpdatedAllocator() {
+ ParentLocalSurfaceIdAllocator child_updated_parent_allocator;
+ LocalSurfaceId child_allocated_local_surface_id =
+ GetFakeChildAllocatedLocalSurfaceId();
+ child_updated_parent_allocator.UpdateFromChild(
+ child_allocated_local_surface_id);
+ return child_updated_parent_allocator;
+}
+
+} // namespace
+} // namespace viz
diff --git a/chromium/components/viz/common/surfaces/sequence_surface_reference_factory.cc b/chromium/components/viz/common/surfaces/sequence_surface_reference_factory.cc
deleted file mode 100644
index 7faf30ec2ea..00000000000
--- a/chromium/components/viz/common/surfaces/sequence_surface_reference_factory.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/common/surfaces/sequence_surface_reference_factory.h"
-
-#include "base/bind.h"
-#include "base/memory/ptr_util.h"
-
-#include "components/viz/common/surfaces/surface_sequence.h"
-
-namespace viz {
-
-base::Closure SequenceSurfaceReferenceFactory::CreateReference(
- SurfaceReferenceOwner* owner,
- const SurfaceId& surface_id) const {
- auto seq = owner->GetSurfaceSequenceGenerator()->CreateSurfaceSequence();
- RequireSequence(surface_id, seq);
- return base::Bind(&SequenceSurfaceReferenceFactory::SatisfySequence, this,
- seq);
-}
-
-} // namespace viz
diff --git a/chromium/components/viz/common/surfaces/sequence_surface_reference_factory.h b/chromium/components/viz/common/surfaces/sequence_surface_reference_factory.h
deleted file mode 100644
index c3cbde918b3..00000000000
--- a/chromium/components/viz/common/surfaces/sequence_surface_reference_factory.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_COMMON_SURFACES_SEQUENCE_SURFACE_REFERENCE_FACTORY_H_
-#define COMPONENTS_VIZ_COMMON_SURFACES_SEQUENCE_SURFACE_REFERENCE_FACTORY_H_
-
-#include "components/viz/common/surfaces/surface_reference_factory.h"
-#include "components/viz/common/surfaces/surface_sequence.h"
-#include "components/viz/common/viz_common_export.h"
-
-namespace viz {
-
-// A surface reference factory that uses SurfaceSequence.
-class VIZ_COMMON_EXPORT SequenceSurfaceReferenceFactory
- : public SurfaceReferenceFactory {
- public:
- SequenceSurfaceReferenceFactory() = default;
-
- // SurfaceReferenceFactory implementation:
- base::Closure CreateReference(SurfaceReferenceOwner* owner,
- const SurfaceId& surface_id) const override;
-
- protected:
- ~SequenceSurfaceReferenceFactory() override = default;
-
- private:
- virtual void RequireSequence(const SurfaceId& surface_id,
- const SurfaceSequence& sequence) const = 0;
- virtual void SatisfySequence(const SurfaceSequence& sequence) const = 0;
-
- DISALLOW_COPY_AND_ASSIGN(SequenceSurfaceReferenceFactory);
-};
-
-} // namespace viz
-
-#endif // COMPONENTS_VIZ_COMMON_SURFACES_SEQUENCE_SURFACE_REFERENCE_FACTORY_H_
diff --git a/chromium/components/viz/common/surfaces/stub_surface_reference_factory.cc b/chromium/components/viz/common/surfaces/stub_surface_reference_factory.cc
deleted file mode 100644
index e5d2ce50a92..00000000000
--- a/chromium/components/viz/common/surfaces/stub_surface_reference_factory.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/common/surfaces/stub_surface_reference_factory.h"
-
-#include "base/callback.h"
-
-namespace viz {
-
-base::Closure StubSurfaceReferenceFactory::CreateReference(
- SurfaceReferenceOwner* owner,
- const SurfaceId& surface_id) const {
- return base::Closure();
-}
-
-} // namespace viz
diff --git a/chromium/components/viz/common/surfaces/stub_surface_reference_factory.h b/chromium/components/viz/common/surfaces/stub_surface_reference_factory.h
deleted file mode 100644
index 156809c777c..00000000000
--- a/chromium/components/viz/common/surfaces/stub_surface_reference_factory.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_COMMON_SURFACES_STUB_SURFACE_REFERENCE_FACTORY_H_
-#define COMPONENTS_VIZ_COMMON_SURFACES_STUB_SURFACE_REFERENCE_FACTORY_H_
-
-#include "base/compiler_specific.h"
-#include "components/viz/common/surfaces/surface_reference_factory.h"
-#include "components/viz/common/viz_common_export.h"
-
-namespace viz {
-
-// A stub implementation that creates a closure which does nothing.
-// TODO(kylechar): Delete this class and all usage of
-// SurfaceReferenceFactory when surface references are enabled by default.
-class VIZ_COMMON_EXPORT StubSurfaceReferenceFactory
- : public SurfaceReferenceFactory {
- public:
- StubSurfaceReferenceFactory() = default;
-
- // SurfaceReferenceFactory:
- base::Closure CreateReference(SurfaceReferenceOwner* owner,
- const SurfaceId& surface_id) const override;
-
- protected:
- ~StubSurfaceReferenceFactory() override = default;
-
- DISALLOW_COPY_AND_ASSIGN(StubSurfaceReferenceFactory);
-};
-
-} // namespace viz
-
-#endif // COMPONENTS_VIZ_COMMON_SURFACES_STUB_SURFACE_REFERENCE_FACTORY_H_
diff --git a/chromium/components/viz/common/surfaces/surface_info.cc b/chromium/components/viz/common/surfaces/surface_info.cc
new file mode 100644
index 00000000000..852899071ed
--- /dev/null
+++ b/chromium/components/viz/common/surfaces/surface_info.cc
@@ -0,0 +1,21 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/common/surfaces/surface_info.h"
+
+#include "base/strings/stringprintf.h"
+
+namespace viz {
+
+std::string SurfaceInfo::ToString() const {
+ return base::StringPrintf("SurfaceInfo(%s, DeviceScaleFactor(%f), Size(%s))",
+ id_.ToString().c_str(), device_scale_factor_,
+ size_in_pixels_.ToString().c_str());
+}
+
+std::ostream& operator<<(std::ostream& out, const SurfaceInfo& surface_info) {
+ return out << surface_info.ToString();
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/common/surfaces/surface_info.h b/chromium/components/viz/common/surfaces/surface_info.h
index b40092bcb4c..55141b09d9e 100644
--- a/chromium/components/viz/common/surfaces/surface_info.h
+++ b/chromium/components/viz/common/surfaces/surface_info.h
@@ -6,6 +6,7 @@
#define COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_INFO_H_
#include "components/viz/common/surfaces/surface_id.h"
+#include "components/viz/common/viz_common_export.h"
#include "ui/gfx/geometry/size.h"
namespace IPC {
@@ -20,7 +21,7 @@ class SurfaceInfoDataView;
} // namespace mojom
// This class contains information about the surface that is being embedded.
-class SurfaceInfo {
+class VIZ_COMMON_EXPORT SurfaceInfo {
public:
SurfaceInfo() = default;
SurfaceInfo(const SurfaceId& id,
@@ -47,6 +48,8 @@ class SurfaceInfo {
float device_scale_factor() const { return device_scale_factor_; }
const gfx::Size& size_in_pixels() const { return size_in_pixels_; }
+ std::string ToString() const;
+
private:
friend struct mojo::StructTraits<mojom::SurfaceInfoDataView, SurfaceInfo>;
friend struct IPC::ParamTraits<SurfaceInfo>;
@@ -56,6 +59,9 @@ class SurfaceInfo {
gfx::Size size_in_pixels_;
};
+VIZ_COMMON_EXPORT std::ostream& operator<<(std::ostream& out,
+ const SurfaceInfo& surface_info);
+
} // namespace viz
#endif // COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_INFO_H_
diff --git a/chromium/components/viz/common/surfaces/surface_reference_factory.h b/chromium/components/viz/common/surfaces/surface_reference_factory.h
deleted file mode 100644
index 03e5808f24e..00000000000
--- a/chromium/components/viz/common/surfaces/surface_reference_factory.h
+++ /dev/null
@@ -1,39 +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_VIZ_COMMON_SURFACES_SURFACE_REFERENCE_FACTORY_H_
-#define COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_REFERENCE_FACTORY_H_
-
-#include "base/callback_forward.h"
-#include "base/memory/ref_counted.h"
-#include "components/viz/common/surfaces/surface_id.h"
-#include "components/viz/common/surfaces/surface_reference_owner.h"
-
-namespace viz {
-
-// Confusingly, SurfaceReferenceFactory is only used to create SurfaceSequences.
-// TODO(kylechar): Delete all usage of SurfaceReferenceFactory when surface
-// references are enabled by default.
-class SurfaceReferenceFactory
- : public base::RefCountedThreadSafe<SurfaceReferenceFactory> {
- public:
- // Creates a reference to the surface with the given surface id and returns
- // a closure that must be called exactly once to remove the reference.
- virtual base::Closure CreateReference(SurfaceReferenceOwner* owner,
- const SurfaceId& surface_id) const = 0;
-
- SurfaceReferenceFactory() = default;
-
- protected:
- virtual ~SurfaceReferenceFactory() = default;
-
- private:
- friend class base::RefCountedThreadSafe<SurfaceReferenceFactory>;
-
- DISALLOW_COPY_AND_ASSIGN(SurfaceReferenceFactory);
-};
-
-} // namespace viz
-
-#endif // COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_REFERENCE_FACTORY_H_
diff --git a/chromium/components/viz/common/surfaces/surface_reference_owner.h b/chromium/components/viz/common/surfaces/surface_reference_owner.h
deleted file mode 100644
index c966fb9fad1..00000000000
--- a/chromium/components/viz/common/surfaces/surface_reference_owner.h
+++ /dev/null
@@ -1,23 +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_VIZ_COMMON_SURFACES_SURFACE_REFERENCE_OWNER_H_
-#define COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_REFERENCE_OWNER_H_
-
-#include "components/viz/common/surfaces/surface_sequence_generator.h"
-
-namespace viz {
-
-// Implementations of this interface can be passed to
-// SurfaceReferenceFactory::CreateReference as the reference owner.
-class SurfaceReferenceOwner {
- public:
- virtual ~SurfaceReferenceOwner() {}
-
- virtual SurfaceSequenceGenerator* GetSurfaceSequenceGenerator() = 0;
-};
-
-} // namespace viz
-
-#endif // COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_REFERENCE_OWNER_H_
diff --git a/chromium/components/viz/common/surfaces/surface_sequence.h b/chromium/components/viz/common/surfaces/surface_sequence.h
deleted file mode 100644
index 1b5bda93d54..00000000000
--- a/chromium/components/viz/common/surfaces/surface_sequence.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_SEQUENCE_H_
-#define COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_SEQUENCE_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <tuple>
-
-#include "base/hash.h"
-#include "components/viz/common/surfaces/frame_sink_id.h"
-
-namespace viz {
-
-// A per-surface-namespace sequence number that's used to coordinate
-// dependencies between frames. A sequence number may be satisfied once, and
-// may be depended on once.
-struct SurfaceSequence {
- SurfaceSequence() : sequence(0u) {}
- SurfaceSequence(const FrameSinkId& frame_sink_id, uint32_t sequence)
- : frame_sink_id(frame_sink_id), sequence(sequence) {}
- bool is_valid() const { return frame_sink_id.is_valid() && sequence > 0u; }
-
- FrameSinkId frame_sink_id;
- uint32_t sequence;
-};
-
-inline bool operator==(const SurfaceSequence& a, const SurfaceSequence& b) {
- return a.frame_sink_id == b.frame_sink_id && a.sequence == b.sequence;
-}
-
-inline bool operator!=(const SurfaceSequence& a, const SurfaceSequence& b) {
- return !(a == b);
-}
-
-inline bool operator<(const SurfaceSequence& a, const SurfaceSequence& b) {
- return std::tie(a.frame_sink_id, a.sequence) <
- std::tie(b.frame_sink_id, b.sequence);
-}
-
-struct SurfaceSequenceHash {
- size_t operator()(SurfaceSequence key) const {
- return base::HashInts(static_cast<uint64_t>(key.frame_sink_id.hash()),
- key.sequence);
- }
-};
-
-} // namespace viz
-
-#endif // COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_SEQUENCE_H_
diff --git a/chromium/components/viz/common/surfaces/surface_sequence_generator.cc b/chromium/components/viz/common/surfaces/surface_sequence_generator.cc
deleted file mode 100644
index f3c351e53f9..00000000000
--- a/chromium/components/viz/common/surfaces/surface_sequence_generator.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/common/surfaces/surface_sequence_generator.h"
-#include "components/viz/common/surfaces/surface_sequence.h"
-
-namespace viz {
-
-SurfaceSequenceGenerator::SurfaceSequenceGenerator()
- : next_surface_sequence_(1u) {}
-
-SurfaceSequenceGenerator::~SurfaceSequenceGenerator() = default;
-
-SurfaceSequence SurfaceSequenceGenerator::CreateSurfaceSequence() {
- return SurfaceSequence(frame_sink_id_, next_surface_sequence_++);
-}
-
-} // namespace viz
diff --git a/chromium/components/viz/common/surfaces/surface_sequence_generator.h b/chromium/components/viz/common/surfaces/surface_sequence_generator.h
deleted file mode 100644
index 1bed7d5baf7..00000000000
--- a/chromium/components/viz/common/surfaces/surface_sequence_generator.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_SEQUENCE_GENERATOR_H_
-#define COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_SEQUENCE_GENERATOR_H_
-
-#include <stdint.h>
-
-#include <tuple>
-
-#include "base/macros.h"
-
-#include "components/viz/common/surfaces/frame_sink_id.h"
-#include "components/viz/common/surfaces/surface_sequence.h"
-#include "components/viz/common/viz_common_export.h"
-
-namespace viz {
-
-// Generates unique surface sequences for a surface client id.
-class VIZ_COMMON_EXPORT SurfaceSequenceGenerator {
- public:
- SurfaceSequenceGenerator();
- ~SurfaceSequenceGenerator();
-
- void set_frame_sink_id(const FrameSinkId& frame_sink_id) {
- frame_sink_id_ = frame_sink_id;
- }
-
- SurfaceSequence CreateSurfaceSequence();
-
- private:
- FrameSinkId frame_sink_id_;
- uint32_t next_surface_sequence_;
-
- DISALLOW_COPY_AND_ASSIGN(SurfaceSequenceGenerator);
-};
-
-} // namespace viz
-
-#endif // COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_SEQUENCE_GENERATOR_H_
diff --git a/chromium/components/viz/common/surfaces/surface_sequence_generator_unittest.cc b/chromium/components/viz/common/surfaces/surface_sequence_generator_unittest.cc
deleted file mode 100644
index 5d1913cc0d4..00000000000
--- a/chromium/components/viz/common/surfaces/surface_sequence_generator_unittest.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/common/surfaces/surface_sequence_generator.h"
-
-#include "components/viz/common/surfaces/surface_sequence.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace viz {
-namespace {
-
-static constexpr FrameSinkId kArbitraryFrameSinkId(1, 1);
-
-TEST(SurfaceSequenceGeneratorTest, Basic) {
- SurfaceSequenceGenerator generator;
- generator.set_frame_sink_id(kArbitraryFrameSinkId);
- SurfaceSequence sequence1 = generator.CreateSurfaceSequence();
- SurfaceSequence sequence2 = generator.CreateSurfaceSequence();
- EXPECT_NE(sequence1, sequence2);
-}
-
-} // namespace
-} // namespace viz
diff --git a/chromium/components/viz/common/switches.cc b/chromium/components/viz/common/switches.cc
index 8eaf1ca6c9e..133fb6d1f56 100644
--- a/chromium/components/viz/common/switches.cc
+++ b/chromium/components/viz/common/switches.cc
@@ -6,40 +6,47 @@
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
+#include "components/viz/common/constants.h"
namespace switches {
-namespace {
-
-constexpr uint32_t kDefaultNumberOfFramesToDeadline = 4;
-
-} // namespace
// The default number of the BeginFrames to wait to activate a surface with
// dependencies.
const char kDeadlineToSynchronizeSurfaces[] =
"deadline-to-synchronize-surfaces";
-// Disable surface lifetime management using surface references. This enables
-// adding surface sequences and disables adding temporary references. This flag
-// is only checked on Android, other platforms always have surface references
-// enabled.
-const char kDisableSurfaceReferences[] = "disable-surface-references";
-
// Enables multi-client Surface synchronization. In practice, this indicates
// that LayerTreeHost expects to be given a valid viz::LocalSurfaceId provided
// by the parent compositor.
const char kEnableSurfaceSynchronization[] = "enable-surface-synchronization";
-uint32_t GetDeadlineToSynchronizeSurfaces() {
+// Effectively disables pipelining of compositor frame production stages by
+// waiting for each stage to finish before completing a frame.
+const char kRunAllCompositorStagesBeforeDraw[] =
+ "run-all-compositor-stages-before-draw";
+
+// Enables the viz hit-test logic (HitTestAggregator and HitTestQuery), with
+// hit-test data coming from surface layer.
+const char kUseVizHitTestSurfaceLayer[] = "use-viz-hit-test-surface-layer";
+
+base::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;
+ }
std::string deadline_to_synchronize_surfaces_string =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ command_line->GetSwitchValueASCII(
switches::kDeadlineToSynchronizeSurfaces);
- uint32_t number_of_frames_to_activation_deadline;
+ if (deadline_to_synchronize_surfaces_string.empty())
+ return viz::kDefaultActivationDeadlineInFrames;
+
+ uint32_t activation_deadline_in_frames;
if (!base::StringToUint(deadline_to_synchronize_surfaces_string,
- &number_of_frames_to_activation_deadline)) {
- return kDefaultNumberOfFramesToDeadline;
+ &activation_deadline_in_frames)) {
+ return base::nullopt;
}
- return number_of_frames_to_activation_deadline;
+ return activation_deadline_in_frames;
}
} // namespace switches
diff --git a/chromium/components/viz/common/switches.h b/chromium/components/viz/common/switches.h
index 6752c344f2f..fa604a8c85d 100644
--- a/chromium/components/viz/common/switches.h
+++ b/chromium/components/viz/common/switches.h
@@ -8,16 +8,18 @@
#include <stdint.h>
#include <string>
+#include "base/optional.h"
#include "components/viz/common/viz_common_export.h"
namespace switches {
// Keep list in alphabetical order.
VIZ_COMMON_EXPORT extern const char kDeadlineToSynchronizeSurfaces[];
-VIZ_COMMON_EXPORT extern const char kDisableSurfaceReferences[];
VIZ_COMMON_EXPORT extern const char kEnableSurfaceSynchronization[];
+VIZ_COMMON_EXPORT extern const char kRunAllCompositorStagesBeforeDraw[];
+VIZ_COMMON_EXPORT extern const char kUseVizHitTestSurfaceLayer[];
-VIZ_COMMON_EXPORT uint32_t GetDeadlineToSynchronizeSurfaces();
+VIZ_COMMON_EXPORT base::Optional<uint32_t> GetDeadlineToSynchronizeSurfaces();
} // namespace switches
diff --git a/chromium/components/viz/host/DEPS b/chromium/components/viz/host/DEPS
index a3a1c872004..6d13397fbd6 100644
--- a/chromium/components/viz/host/DEPS
+++ b/chromium/components/viz/host/DEPS
@@ -1,5 +1,8 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+cc/ipc",
+ "+components/viz/common/features.h",
"-components/viz/common/switches.h",
"+gpu/command_buffer/client",
"+gpu/command_buffer/common",
diff --git a/chromium/components/viz/host/hit_test/DEPS b/chromium/components/viz/host/hit_test/DEPS
index d4886fc180f..649497d1c62 100644
--- a/chromium/components/viz/host/hit_test/DEPS
+++ b/chromium/components/viz/host/hit_test/DEPS
@@ -1,3 +1,5 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+services/viz/public/interfaces",
]
diff --git a/chromium/components/viz/host/hit_test/hit_test_query.cc b/chromium/components/viz/host/hit_test/hit_test_query.cc
index fc514ee5b9f..092505ae802 100644
--- a/chromium/components/viz/host/hit_test/hit_test_query.cc
+++ b/chromium/components/viz/host/hit_test/hit_test_query.cc
@@ -4,7 +4,9 @@
#include "components/viz/host/hit_test/hit_test_query.h"
+#include "base/metrics/histogram_macros.h"
#include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
+#include "ui/gfx/geometry/point_conversions.h"
namespace viz {
namespace {
@@ -51,7 +53,9 @@ void HitTestQuery::SwitchActiveAggregatedHitTestRegionList(
Target HitTestQuery::FindTargetForLocation(
EventSource event_source,
- const gfx::Point& location_in_root) const {
+ const gfx::PointF& location_in_root) const {
+ SCOPED_UMA_HISTOGRAM_TIMER("Event.VizHitTest.TargetTime");
+
Target target;
if (!active_hit_test_list_size_)
return target;
@@ -61,35 +65,38 @@ Target HitTestQuery::FindTargetForLocation(
return target;
}
-gfx::Point HitTestQuery::TransformLocationForTarget(
+bool HitTestQuery::TransformLocationForTarget(
EventSource event_source,
const std::vector<FrameSinkId>& target_ancestors,
- const gfx::Point& location_in_root) const {
+ const gfx::PointF& location_in_root,
+ gfx::PointF* transformed_location) const {
+ SCOPED_UMA_HISTOGRAM_TIMER("Event.VizHitTest.TransformTime");
+
if (!active_hit_test_list_size_)
- return location_in_root;
+ return false;
+
+ if (target_ancestors.size() == 0u ||
+ target_ancestors[target_ancestors.size() - 1] !=
+ active_hit_test_list_->frame_sink_id) {
+ return false;
+ }
- gfx::Point location_in_target(location_in_root);
// TODO(riajiang): Cache the matrix product such that the transform can be
// done immediately. crbug/758062.
- DCHECK(target_ancestors.size() > 0u &&
- target_ancestors[target_ancestors.size() - 1] ==
- active_hit_test_list_->frame_sink_id);
- bool success = TransformLocationForTargetRecursively(
+ *transformed_location = location_in_root;
+ return TransformLocationForTargetRecursively(
event_source, target_ancestors, target_ancestors.size() - 1,
- active_hit_test_list_, &location_in_target);
- // Must provide a valid target.
- DCHECK(success);
- return location_in_target;
+ active_hit_test_list_, transformed_location);
}
bool HitTestQuery::FindTargetInRegionForLocation(
EventSource event_source,
- const gfx::Point& location_in_parent,
+ const gfx::PointF& location_in_parent,
AggregatedHitTestRegion* region,
Target* target) const {
- gfx::Point location_transformed(location_in_parent);
+ gfx::PointF location_transformed(location_in_parent);
region->transform.TransformPoint(&location_transformed);
- if (!region->rect.Contains(location_transformed))
+ if (!gfx::RectF(region->rect).Contains(location_transformed))
return false;
if (region->child_count < 0 ||
@@ -100,8 +107,8 @@ bool HitTestQuery::FindTargetInRegionForLocation(
AggregatedHitTestRegion* child_region = region + 1;
AggregatedHitTestRegion* child_region_end =
child_region + region->child_count;
- gfx::Point location_in_target(location_transformed);
- location_in_target.Offset(-region->rect.x(), -region->rect.y());
+ gfx::PointF location_in_target =
+ location_transformed - region->rect.OffsetFromOrigin();
while (child_region < child_region_end) {
if (FindTargetInRegionForLocation(event_source, location_in_target,
child_region, target)) {
@@ -121,16 +128,12 @@ bool HitTestQuery::FindTargetInRegionForLocation(
: (region->flags & mojom::kHitTestMouse) != 0u;
if (!match_touch_or_mouse_region)
return false;
- if (region->flags & mojom::kHitTestMine) {
+ if (region->flags & (mojom::kHitTestMine | mojom::kHitTestAsk)) {
target->frame_sink_id = region->frame_sink_id;
target->location_in_target = location_in_target;
target->flags = region->flags;
return true;
}
- if (region->flags & mojom::kHitTestAsk) {
- target->flags = region->flags;
- return true;
- }
return false;
}
@@ -139,7 +142,7 @@ bool HitTestQuery::TransformLocationForTargetRecursively(
const std::vector<FrameSinkId>& target_ancestors,
size_t target_ancestor,
AggregatedHitTestRegion* region,
- gfx::Point* location_in_target) const {
+ gfx::PointF* location_in_target) const {
bool match_touch_or_mouse_region =
ShouldUseTouchBounds(event_source)
? (region->flags & mojom::kHitTestTouch) != 0u
diff --git a/chromium/components/viz/host/hit_test/hit_test_query.h b/chromium/components/viz/host/hit_test/hit_test_query.h
index 201e6e086ab..232bfdaf004 100644
--- a/chromium/components/viz/host/hit_test/hit_test_query.h
+++ b/chromium/components/viz/host/hit_test/hit_test_query.h
@@ -11,14 +11,14 @@
#include "components/viz/common/hit_test/aggregated_hit_test_region.h"
#include "components/viz/host/viz_host_export.h"
#include "mojo/public/cpp/system/buffer.h"
-#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_f.h"
namespace viz {
struct Target {
FrameSinkId frame_sink_id;
// Coordinates in the coordinate system of the target FrameSinkId.
- gfx::Point location_in_target;
+ gfx::PointF location_in_target;
// Different flags are defined in services/viz/public/interfaces/hit_test/
// hit_test_region_list.mojom.
uint32_t flags = 0;
@@ -77,24 +77,27 @@ class VIZ_HOST_EXPORT HitTestQuery {
// transfrom-from-e-to-c and transform-from-c-to-b then we get 3 in the
// coordinate system of b.
Target FindTargetForLocation(EventSource event_source,
- const gfx::Point& location_in_root) const;
+ const gfx::PointF& location_in_root) const;
// When a target window is already known, e.g. capture/latched window, convert
- // |location_in_root| to be in the coordinate space of the target.
+ // |location_in_root| to be in the coordinate space of the target and store
+ // that in |transformed_location|. Return true if the transform is successful
+ // and false otherwise.
// |target_ancestors| contains the FrameSinkId from target to root.
// |target_ancestors.front()| is the target, and |target_ancestors.back()|
// is the root.
- gfx::Point TransformLocationForTarget(
+ bool TransformLocationForTarget(
EventSource event_source,
const std::vector<FrameSinkId>& target_ancestors,
- const gfx::Point& location_in_root) const;
+ const gfx::PointF& location_in_root,
+ gfx::PointF* transformed_location) const;
private:
// Helper function to find |target| for |location_in_parent| in the |region|,
// returns true if a target is found and false otherwise. |location_in_parent|
// is in the coordinate space of |region|'s parent.
bool FindTargetInRegionForLocation(EventSource event_source,
- const gfx::Point& location_in_parent,
+ const gfx::PointF& location_in_parent,
AggregatedHitTestRegion* region,
Target* target) const;
@@ -106,7 +109,7 @@ class VIZ_HOST_EXPORT HitTestQuery {
const std::vector<FrameSinkId>& target_ancestors,
size_t target_ancestor,
AggregatedHitTestRegion* region,
- gfx::Point* location_in_target) const;
+ gfx::PointF* location_in_target) const;
uint32_t handle_buffer_sizes_[2];
mojo::ScopedSharedBufferMapping handle_buffers_[2];
diff --git a/chromium/components/viz/host/hit_test/hit_test_query_unittest.cc b/chromium/components/viz/host/hit_test/hit_test_query_unittest.cc
index fc6f4fbcd54..85555fe031f 100644
--- a/chromium/components/viz/host/hit_test/hit_test_query_unittest.cc
+++ b/chromium/components/viz/host/hit_test/hit_test_query_unittest.cc
@@ -64,9 +64,9 @@ TEST_F(HitTestQueryTest, OneSurface) {
e_bounds, transform_e_to_e, 0); // e
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(1, 1);
- gfx::Point point2(600, 600);
- gfx::Point point3(0, 0);
+ gfx::PointF point1(1, 1);
+ gfx::PointF point2(600, 600);
+ gfx::PointF point3(0, 0);
Target target1 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
@@ -78,7 +78,7 @@ TEST_F(HitTestQueryTest, OneSurface) {
Target target2 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
EXPECT_EQ(target2.frame_sink_id, FrameSinkId());
- EXPECT_EQ(target2.location_in_target, gfx::Point());
+ EXPECT_EQ(target2.location_in_target, gfx::PointF());
EXPECT_FALSE(target2.flags);
// There's a valid Target for point3, see Rect::Contains.
@@ -121,10 +121,10 @@ TEST_F(HitTestQueryTest, OneEmbedderTwoChildren) {
c2_bounds_in_e, transform_e_to_c2, 0); // c2
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(99, 200);
- gfx::Point point2(150, 150);
- gfx::Point point3(400, 400);
- gfx::Point point4(650, 350);
+ gfx::PointF point1(99, 200);
+ gfx::PointF point2(150, 150);
+ gfx::PointF point3(400, 400);
+ gfx::PointF point4(650, 350);
Target target1 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
@@ -135,19 +135,19 @@ TEST_F(HitTestQueryTest, OneEmbedderTwoChildren) {
Target target2 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
EXPECT_EQ(target2.frame_sink_id, c1_id);
- EXPECT_EQ(target2.location_in_target, gfx::Point(50, 50));
+ EXPECT_EQ(target2.location_in_target, gfx::PointF(50, 50));
EXPECT_EQ(target2.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
Target target3 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point3);
EXPECT_EQ(target3.frame_sink_id, c2_id);
- EXPECT_EQ(target3.location_in_target, gfx::Point(100, 100));
+ EXPECT_EQ(target3.location_in_target, gfx::PointF(100, 100));
EXPECT_EQ(target3.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
Target target4 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point4);
EXPECT_EQ(target4.frame_sink_id, FrameSinkId());
- EXPECT_EQ(target4.location_in_target, gfx::Point());
+ EXPECT_EQ(target4.location_in_target, gfx::PointF());
EXPECT_FALSE(target4.flags);
}
@@ -171,8 +171,8 @@ TEST_F(HitTestQueryTest, OneEmbedderRotatedChild) {
c_bounds_in_e, transform_e_to_c, 0); // c
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(150, 120); // Point(-22, -12) after transform.
- gfx::Point point2(550, 400); // Point(185, 194) after transform.
+ gfx::PointF point1(150, 120); // Point(-22.07, -12.07) after transform.
+ gfx::PointF point2(550, 400); // Point(184.78, 194.41) after transform.
Target target1 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
@@ -183,7 +183,8 @@ TEST_F(HitTestQueryTest, OneEmbedderRotatedChild) {
Target target2 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
EXPECT_EQ(target2.frame_sink_id, c_id);
- EXPECT_EQ(target2.location_in_target, gfx::Point(185, 194));
+ EXPECT_NEAR(target2.location_in_target.x(), 185, .5);
+ EXPECT_NEAR(target2.location_in_target.y(), 194, .5);
EXPECT_EQ(target2.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
}
@@ -227,10 +228,10 @@ TEST_F(HitTestQueryTest, ClippedChildWithTabAndTransparentBackground) {
b_bounds_in_c, transform_c_to_b, 0); // b
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(1, 1);
- gfx::Point point2(202, 102);
- gfx::Point point3(403, 103);
- gfx::Point point4(202, 202);
+ gfx::PointF point1(1, 1);
+ gfx::PointF point2(202, 102);
+ gfx::PointF point3(403, 103);
+ gfx::PointF point4(202, 202);
Target target1 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
@@ -241,7 +242,7 @@ TEST_F(HitTestQueryTest, ClippedChildWithTabAndTransparentBackground) {
Target target2 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
EXPECT_EQ(target2.frame_sink_id, a_id);
- EXPECT_EQ(target2.location_in_target, gfx::Point(2, 2));
+ EXPECT_EQ(target2.location_in_target, gfx::PointF(2, 2));
EXPECT_EQ(target2.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
Target target3 =
@@ -253,7 +254,7 @@ TEST_F(HitTestQueryTest, ClippedChildWithTabAndTransparentBackground) {
Target target4 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point4);
EXPECT_EQ(target4.frame_sink_id, b_id);
- EXPECT_EQ(target4.location_in_target, gfx::Point(2, 2));
+ EXPECT_EQ(target4.location_in_target, gfx::PointF(2, 2));
EXPECT_EQ(target4.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
}
@@ -305,10 +306,10 @@ TEST_F(HitTestQueryTest, ClippedChildWithChildUnderneath) {
d_bounds_in_e, transform_e_to_d, 0); // d
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(1, 1);
- gfx::Point point2(202, 102);
- gfx::Point point3(450, 150);
- gfx::Point point4(202, 202);
+ gfx::PointF point1(1, 1);
+ gfx::PointF point2(202, 102);
+ gfx::PointF point3(450, 150);
+ gfx::PointF point4(202, 202);
Target target1 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
@@ -319,19 +320,19 @@ TEST_F(HitTestQueryTest, ClippedChildWithChildUnderneath) {
Target target2 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
EXPECT_EQ(target2.frame_sink_id, a_id);
- EXPECT_EQ(target2.location_in_target, gfx::Point(2, 2));
+ EXPECT_EQ(target2.location_in_target, gfx::PointF(2, 2));
EXPECT_EQ(target2.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
Target target3 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point3);
EXPECT_EQ(target3.frame_sink_id, d_id);
- EXPECT_EQ(target3.location_in_target, gfx::Point(50, 100));
+ EXPECT_EQ(target3.location_in_target, gfx::PointF(50, 100));
EXPECT_EQ(target3.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
Target target4 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point4);
EXPECT_EQ(target4.frame_sink_id, b_id);
- EXPECT_EQ(target4.location_in_target, gfx::Point(2, 2));
+ EXPECT_EQ(target4.location_in_target, gfx::PointF(2, 2));
EXPECT_EQ(target4.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
}
@@ -371,27 +372,28 @@ TEST_F(HitTestQueryTest, ClippedChildWithChildUnderneathTransform) {
d_bounds_in_e, transform_e_to_d, 0); // d
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(1, 1);
- gfx::Point point2(202, 102);
- gfx::Point point3(450, 150);
- gfx::Point point4(202, 202);
+ gfx::PointF point1(1, 1);
+ gfx::PointF point2(202, 102);
+ gfx::PointF point3(450, 150);
+ gfx::PointF point4(202, 202);
std::vector<FrameSinkId> target_ancestors1{e_id};
- EXPECT_EQ(hit_test_query().TransformLocationForTarget(
- EventSource::MOUSE, target_ancestors1, point1),
- point1);
+ gfx::PointF transformed_point;
+ EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
+ EventSource::MOUSE, target_ancestors1, point1, &transformed_point));
+ EXPECT_EQ(transformed_point, point1);
std::vector<FrameSinkId> target_ancestors2{a_id, c_id, e_id};
- EXPECT_EQ(hit_test_query().TransformLocationForTarget(
- EventSource::MOUSE, target_ancestors2, point2),
- gfx::Point(2, 2));
+ EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
+ EventSource::MOUSE, target_ancestors2, point2, &transformed_point));
+ EXPECT_EQ(transformed_point, gfx::PointF(2, 2));
std::vector<FrameSinkId> target_ancestors3{d_id, e_id};
- EXPECT_EQ(hit_test_query().TransformLocationForTarget(
- EventSource::MOUSE, target_ancestors3, point3),
- gfx::Point(50, 100));
+ EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
+ EventSource::MOUSE, target_ancestors3, point3, &transformed_point));
+ EXPECT_EQ(transformed_point, gfx::PointF(50, 100));
std::vector<FrameSinkId> target_ancestors4{b_id, c_id, e_id};
- EXPECT_EQ(hit_test_query().TransformLocationForTarget(
- EventSource::MOUSE, target_ancestors4, point4),
- gfx::Point(2, 2));
+ EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
+ EventSource::MOUSE, target_ancestors4, point4, &transformed_point));
+ EXPECT_EQ(transformed_point, gfx::PointF(2, 2));
}
// One embedder with two clipped children with a tab and transparent background.
@@ -459,13 +461,13 @@ TEST_F(HitTestQueryTest, ClippedChildrenWithTabAndTransparentBackground) {
h_bounds_in_c2, transform_c2_to_h, 0); // h
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(1, 1);
- gfx::Point point2(202, 102);
- gfx::Point point3(403, 103);
- gfx::Point point4(202, 202);
- gfx::Point point5(250, 750);
- gfx::Point point6(450, 750);
- gfx::Point point7(350, 1100);
+ gfx::PointF point1(1, 1);
+ gfx::PointF point2(202, 102);
+ gfx::PointF point3(403, 103);
+ gfx::PointF point4(202, 202);
+ gfx::PointF point5(250, 750);
+ gfx::PointF point6(450, 750);
+ gfx::PointF point7(350, 1100);
Target target1 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
@@ -476,7 +478,7 @@ TEST_F(HitTestQueryTest, ClippedChildrenWithTabAndTransparentBackground) {
Target target2 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
EXPECT_EQ(target2.frame_sink_id, a_id);
- EXPECT_EQ(target2.location_in_target, gfx::Point(2, 2));
+ EXPECT_EQ(target2.location_in_target, gfx::PointF(2, 2));
EXPECT_EQ(target2.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
Target target3 =
@@ -488,13 +490,13 @@ TEST_F(HitTestQueryTest, ClippedChildrenWithTabAndTransparentBackground) {
Target target4 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point4);
EXPECT_EQ(target4.frame_sink_id, b_id);
- EXPECT_EQ(target4.location_in_target, gfx::Point(2, 2));
+ EXPECT_EQ(target4.location_in_target, gfx::PointF(2, 2));
EXPECT_EQ(target4.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
Target target5 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point5);
EXPECT_EQ(target5.frame_sink_id, g_id);
- EXPECT_EQ(target5.location_in_target, gfx::Point(50, 50));
+ EXPECT_EQ(target5.location_in_target, gfx::PointF(50, 50));
EXPECT_EQ(target5.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
Target target6 =
@@ -506,7 +508,7 @@ TEST_F(HitTestQueryTest, ClippedChildrenWithTabAndTransparentBackground) {
Target target7 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point7);
EXPECT_EQ(target7.frame_sink_id, h_id);
- EXPECT_EQ(target7.location_in_target, gfx::Point(150, 300));
+ EXPECT_EQ(target7.location_in_target, gfx::PointF(150, 300));
EXPECT_EQ(target7.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
}
@@ -561,40 +563,41 @@ TEST_F(HitTestQueryTest,
h_bounds_in_c2, transform_c2_to_h, 0); // h
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(1, 1);
- gfx::Point point2(202, 102);
- gfx::Point point3(403, 103);
- gfx::Point point4(202, 202);
- gfx::Point point5(250, 750);
- gfx::Point point6(450, 750);
- gfx::Point point7(350, 1100);
+ gfx::PointF point1(1, 1);
+ gfx::PointF point2(202, 102);
+ gfx::PointF point3(403, 103);
+ gfx::PointF point4(202, 202);
+ gfx::PointF point5(250, 750);
+ gfx::PointF point6(450, 750);
+ gfx::PointF point7(350, 1100);
std::vector<FrameSinkId> target_ancestors1{e_id};
- EXPECT_EQ(hit_test_query().TransformLocationForTarget(
- EventSource::MOUSE, target_ancestors1, point1),
- point1);
+ gfx::PointF transformed_point;
+ EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
+ EventSource::MOUSE, target_ancestors1, point1, &transformed_point));
+ EXPECT_EQ(transformed_point, point1);
std::vector<FrameSinkId> target_ancestors2{a_id, c1_id, e_id};
- EXPECT_EQ(hit_test_query().TransformLocationForTarget(
- EventSource::MOUSE, target_ancestors2, point2),
- gfx::Point(2, 2));
- EXPECT_EQ(hit_test_query().TransformLocationForTarget(
- EventSource::MOUSE, target_ancestors1, point3),
- point3);
+ EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
+ EventSource::MOUSE, target_ancestors2, point2, &transformed_point));
+ EXPECT_EQ(transformed_point, gfx::PointF(2, 2));
+ EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
+ EventSource::MOUSE, target_ancestors1, point3, &transformed_point));
+ EXPECT_EQ(transformed_point, point3);
std::vector<FrameSinkId> target_ancestors3{b_id, c1_id, e_id};
- EXPECT_EQ(hit_test_query().TransformLocationForTarget(
- EventSource::MOUSE, target_ancestors3, point4),
- gfx::Point(2, 2));
+ EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
+ EventSource::MOUSE, target_ancestors3, point4, &transformed_point));
+ EXPECT_EQ(transformed_point, gfx::PointF(2, 2));
std::vector<FrameSinkId> target_ancestors4{g_id, c2_id, e_id};
- EXPECT_EQ(hit_test_query().TransformLocationForTarget(
- EventSource::MOUSE, target_ancestors4, point5),
- gfx::Point(50, 50));
- EXPECT_EQ(hit_test_query().TransformLocationForTarget(
- EventSource::MOUSE, target_ancestors1, point6),
- point6);
+ EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
+ EventSource::MOUSE, target_ancestors4, point5, &transformed_point));
+ EXPECT_EQ(transformed_point, gfx::PointF(50, 50));
+ EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
+ EventSource::MOUSE, target_ancestors1, point6, &transformed_point));
+ EXPECT_EQ(transformed_point, point6);
std::vector<FrameSinkId> target_ancestors5{h_id, c2_id, e_id};
- EXPECT_EQ(hit_test_query().TransformLocationForTarget(
- EventSource::MOUSE, target_ancestors5, point7),
- gfx::Point(150, 300));
+ EXPECT_TRUE(hit_test_query().TransformLocationForTarget(
+ EventSource::MOUSE, target_ancestors5, point7, &transformed_point));
+ EXPECT_EQ(transformed_point, gfx::PointF(150, 300));
}
// Children that are multiple layers deep.
@@ -653,10 +656,10 @@ TEST_F(HitTestQueryTest, MultipleLayerChild) {
c2_bounds_in_e, transform_e_to_c2, 0); // c2
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(1, 1);
- gfx::Point point2(300, 350);
- gfx::Point point3(550, 350);
- gfx::Point point4(900, 350);
+ gfx::PointF point1(1, 1);
+ gfx::PointF point2(300, 350);
+ gfx::PointF point3(550, 350);
+ gfx::PointF point4(900, 350);
Target target1 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
@@ -667,19 +670,19 @@ TEST_F(HitTestQueryTest, MultipleLayerChild) {
Target target2 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
EXPECT_EQ(target2.frame_sink_id, g_id);
- EXPECT_EQ(target2.location_in_target, gfx::Point(0, 20));
+ EXPECT_EQ(target2.location_in_target, gfx::PointF(0, 20));
EXPECT_EQ(target2.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
Target target3 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point3);
EXPECT_EQ(target3.frame_sink_id, b_id);
- EXPECT_EQ(target3.location_in_target, gfx::Point(400, 220));
+ EXPECT_EQ(target3.location_in_target, gfx::PointF(400, 220));
EXPECT_EQ(target3.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
Target target4 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point4);
EXPECT_EQ(target4.frame_sink_id, c2_id);
- EXPECT_EQ(target4.location_in_target, gfx::Point(500, 300));
+ EXPECT_EQ(target4.location_in_target, gfx::PointF(500, 300));
EXPECT_EQ(target4.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
}
@@ -739,10 +742,10 @@ TEST_F(HitTestQueryTest, MultipleLayerTransparentChild) {
c2_bounds_in_e, transform_e_to_c2, 0); // c2
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(1, 1);
- gfx::Point point2(300, 350);
- gfx::Point point3(450, 350);
- gfx::Point point4(900, 350);
+ gfx::PointF point1(1, 1);
+ gfx::PointF point2(300, 350);
+ gfx::PointF point3(450, 350);
+ gfx::PointF point4(900, 350);
Target target1 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
@@ -759,13 +762,13 @@ TEST_F(HitTestQueryTest, MultipleLayerTransparentChild) {
Target target3 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point3);
EXPECT_EQ(target3.frame_sink_id, c2_id);
- EXPECT_EQ(target3.location_in_target, gfx::Point(50, 300));
+ EXPECT_EQ(target3.location_in_target, gfx::PointF(50, 300));
EXPECT_TRUE(target3.flags);
Target target4 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point4);
EXPECT_EQ(target4.frame_sink_id, c2_id);
- EXPECT_EQ(target4.location_in_target, gfx::Point(500, 300));
+ EXPECT_EQ(target4.location_in_target, gfx::PointF(500, 300));
EXPECT_TRUE(target4.flags);
}
@@ -798,21 +801,21 @@ TEST_F(HitTestQueryTest, InvalidAggregatedHitTestRegionData) {
b_bounds_in_c, transform_c_to_b, 0); // b
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(1, 1);
- gfx::Point point2(202, 102);
+ gfx::PointF point1(1, 1);
+ gfx::PointF point2(202, 102);
// |child_count| is invalid, which is a security fault. For now, check to see
// if the returned Target is invalid.
Target target1 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
EXPECT_EQ(target1.frame_sink_id, FrameSinkId());
- EXPECT_EQ(target1.location_in_target, gfx::Point());
+ EXPECT_EQ(target1.location_in_target, gfx::PointF());
EXPECT_FALSE(target1.flags);
Target target2 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
EXPECT_EQ(target2.frame_sink_id, FrameSinkId());
- EXPECT_EQ(target2.location_in_target, gfx::Point());
+ EXPECT_EQ(target2.location_in_target, gfx::PointF());
EXPECT_FALSE(target2.flags);
AggregatedHitTestRegion* aggregated_hit_test_region_list_max =
@@ -833,7 +836,7 @@ TEST_F(HitTestQueryTest, InvalidAggregatedHitTestRegionData) {
Target target3 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
EXPECT_EQ(target3.frame_sink_id, FrameSinkId());
- EXPECT_EQ(target3.location_in_target, gfx::Point());
+ EXPECT_EQ(target3.location_in_target, gfx::PointF());
EXPECT_FALSE(target3.flags);
AggregatedHitTestRegion* aggregated_hit_test_region_list_bigger =
@@ -854,7 +857,7 @@ TEST_F(HitTestQueryTest, InvalidAggregatedHitTestRegionData) {
Target target4 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
EXPECT_EQ(target4.frame_sink_id, FrameSinkId());
- EXPECT_EQ(target4.location_in_target, gfx::Point());
+ EXPECT_EQ(target4.location_in_target, gfx::PointF());
EXPECT_FALSE(target4.flags);
}
@@ -882,8 +885,8 @@ TEST_F(HitTestQueryTest, MouseTouchFlags) {
c2_bounds_in_e, transform_e_to_c2, 0); // c2
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(80, 80);
- gfx::Point point2(150, 150);
+ gfx::PointF point1(80, 80);
+ gfx::PointF point2(150, 150);
Target target1 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
@@ -895,19 +898,19 @@ TEST_F(HitTestQueryTest, MouseTouchFlags) {
Target target2 =
hit_test_query().FindTargetForLocation(EventSource::TOUCH, point1);
EXPECT_EQ(target2.frame_sink_id, c2_id);
- EXPECT_EQ(target2.location_in_target, gfx::Point(5, 5));
+ EXPECT_EQ(target2.location_in_target, gfx::PointF(5, 5));
EXPECT_EQ(target2.flags, mojom::kHitTestMine | mojom::kHitTestTouch);
Target target3 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
EXPECT_EQ(target3.frame_sink_id, c1_id);
- EXPECT_EQ(target3.location_in_target, gfx::Point(50, 50));
+ EXPECT_EQ(target3.location_in_target, gfx::PointF(50, 50));
EXPECT_EQ(target3.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
Target target4 =
hit_test_query().FindTargetForLocation(EventSource::TOUCH, point2);
EXPECT_EQ(target4.frame_sink_id, c2_id);
- EXPECT_EQ(target4.location_in_target, gfx::Point(75, 75));
+ EXPECT_EQ(target4.location_in_target, gfx::PointF(75, 75));
EXPECT_EQ(target4.flags, mojom::kHitTestMine | mojom::kHitTestTouch);
}
@@ -922,21 +925,21 @@ TEST_F(HitTestQueryTest, RootHitTestAskFlag) {
e_bounds, transform_e_to_e, 0); // e
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(1, 1);
- gfx::Point point2(600, 600);
+ gfx::PointF point1(1, 1);
+ gfx::PointF point2(600, 600);
// point1 is inside e but we have to ask clients for targeting.
Target target1 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
- EXPECT_EQ(target1.frame_sink_id, FrameSinkId());
- EXPECT_EQ(target1.location_in_target, gfx::Point());
+ EXPECT_EQ(target1.frame_sink_id, e_id);
+ EXPECT_EQ(target1.location_in_target, point1);
EXPECT_EQ(target1.flags, mojom::kHitTestAsk | mojom::kHitTestMouse);
// point2 is on the bounds of e so no target found.
Target target2 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
EXPECT_EQ(target2.frame_sink_id, FrameSinkId());
- EXPECT_EQ(target2.location_in_target, gfx::Point());
+ EXPECT_EQ(target2.location_in_target, gfx::PointF());
EXPECT_FALSE(target2.flags);
}
@@ -972,9 +975,9 @@ TEST_F(HitTestQueryTest, ChildHitTestAskFlag) {
c2_bounds_in_e, transform_e_to_c2, 0); // c2
// All points are in e's coordinate system when we reach this case.
- gfx::Point point1(99, 200);
- gfx::Point point2(150, 150);
- gfx::Point point3(400, 400);
+ gfx::PointF point1(99, 200);
+ gfx::PointF point2(150, 150);
+ gfx::PointF point3(400, 400);
Target target1 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
@@ -985,15 +988,15 @@ TEST_F(HitTestQueryTest, ChildHitTestAskFlag) {
Target target2 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
EXPECT_EQ(target2.frame_sink_id, c1_id);
- EXPECT_EQ(target2.location_in_target, gfx::Point(50, 50));
+ EXPECT_EQ(target2.location_in_target, gfx::PointF(50, 50));
EXPECT_EQ(target2.flags, mojom::kHitTestMine | mojom::kHitTestMouse);
// point3 is inside c2 but we have to ask clients for targeting. Event
// shouldn't go back to e.
Target target3 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point3);
- EXPECT_EQ(target3.frame_sink_id, FrameSinkId());
- EXPECT_EQ(target3.location_in_target, gfx::Point());
+ EXPECT_EQ(target3.frame_sink_id, c2_id);
+ EXPECT_EQ(target3.location_in_target, gfx::PointF(100, 100));
EXPECT_EQ(target3.flags, mojom::kHitTestAsk | mojom::kHitTestMouse);
}
diff --git a/chromium/components/viz/host/host_frame_sink_client.h b/chromium/components/viz/host/host_frame_sink_client.h
index 9f5c6da2d18..72230418927 100644
--- a/chromium/components/viz/host/host_frame_sink_client.h
+++ b/chromium/components/viz/host/host_frame_sink_client.h
@@ -5,6 +5,8 @@
#ifndef COMPONENTS_VIZ_HOST_HOST_FRAME_SINK_CLIENT_H_
#define COMPONENTS_VIZ_HOST_HOST_FRAME_SINK_CLIENT_H_
+#include <stdint.h>
+
namespace viz {
class SurfaceInfo;
diff --git a/chromium/components/viz/host/host_frame_sink_manager.cc b/chromium/components/viz/host/host_frame_sink_manager.cc
index 1719ae8d1d6..79a38c26065 100644
--- a/chromium/components/viz/host/host_frame_sink_manager.cc
+++ b/chromium/components/viz/host/host_frame_sink_manager.cc
@@ -11,6 +11,7 @@
#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
namespace viz {
@@ -26,10 +27,6 @@ void HostFrameSinkManager::SetLocalManager(
frame_sink_manager_impl_ = frame_sink_manager_impl;
frame_sink_manager_ = frame_sink_manager_impl;
-
- // Assign temporary references if FrameSinkManagerImpl is using them.
- assign_temporary_references_ =
- frame_sink_manager_impl_->surface_manager()->using_surface_references();
}
void HostFrameSinkManager::BindAndSetManager(
@@ -76,7 +73,14 @@ void HostFrameSinkManager::InvalidateFrameSinkId(
FrameSinkData& data = frame_sink_data_map_[frame_sink_id];
DCHECK(data.IsFrameSinkRegistered());
- // This will destroy |frame_sink_id| if using mojom::CompositorFrameSink.
+ if (data.has_created_compositor_frame_sink && data.is_root) {
+ // This synchronous call ensures that the GL context/surface that draw to
+ // the platform window (eg. XWindow or HWND) get destroyed before the
+ // platform window is destroyed.
+ mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync_call;
+ frame_sink_manager_->DestroyCompositorFrameSink(frame_sink_id);
+ }
+
frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id);
data.has_created_compositor_frame_sink = false;
data.client = nullptr;
@@ -88,6 +92,19 @@ void HostFrameSinkManager::InvalidateFrameSinkId(
display_hit_test_query_.erase(frame_sink_id);
}
+void HostFrameSinkManager::EnableSynchronizationReporting(
+ const FrameSinkId& frame_sink_id,
+ const std::string& reporting_label) {
+ DCHECK(frame_sink_id.is_valid());
+
+ FrameSinkData& data = frame_sink_data_map_[frame_sink_id];
+ DCHECK(data.IsFrameSinkRegistered());
+
+ data.synchronization_reporting_label = reporting_label;
+ frame_sink_manager_->EnableSynchronizationReporting(frame_sink_id,
+ reporting_label);
+}
+
void HostFrameSinkManager::SetFrameSinkDebugLabel(
const FrameSinkId& frame_sink_id,
const std::string& debug_label) {
@@ -102,10 +119,20 @@ void HostFrameSinkManager::SetFrameSinkDebugLabel(
void HostFrameSinkManager::CreateRootCompositorFrameSink(
mojom::RootCompositorFrameSinkParamsPtr params) {
+ // Should only be used with an out-of-process display compositor.
+ DCHECK(frame_sink_manager_ptr_);
+
FrameSinkId frame_sink_id = params->frame_sink_id;
FrameSinkData& data = frame_sink_data_map_[frame_sink_id];
DCHECK(data.IsFrameSinkRegistered());
- DCHECK(!data.HasCompositorFrameSinkData());
+ DCHECK(!data.support);
+
+ // If GL context is lost a new CompositorFrameSink will be created. Destroy
+ // the old CompositorFrameSink first.
+ if (data.has_created_compositor_frame_sink) {
+ frame_sink_manager_->DestroyCompositorFrameSink(frame_sink_id,
+ base::OnceClosure());
+ }
data.is_root = true;
data.has_created_compositor_frame_sink = true;
@@ -120,7 +147,14 @@ void HostFrameSinkManager::CreateCompositorFrameSink(
mojom::CompositorFrameSinkClientPtr client) {
FrameSinkData& data = frame_sink_data_map_[frame_sink_id];
DCHECK(data.IsFrameSinkRegistered());
- DCHECK(!data.HasCompositorFrameSinkData());
+ DCHECK(!data.support);
+
+ // If GL context is lost a new CompositorFrameSink will be created. Destroy
+ // the old CompositorFrameSink first.
+ if (data.has_created_compositor_frame_sink) {
+ frame_sink_manager_->DestroyCompositorFrameSink(frame_sink_id,
+ base::OnceClosure());
+ }
data.is_root = false;
data.has_created_compositor_frame_sink = true;
@@ -209,6 +243,11 @@ void HostFrameSinkManager::CreateVideoCapturer(
frame_sink_manager_->CreateVideoCapturer(std::move(request));
}
+void HostFrameSinkManager::EvictSurfaces(
+ const std::vector<SurfaceId>& surface_ids) {
+ frame_sink_manager_->EvictSurfaces(surface_ids);
+}
+
std::unique_ptr<CompositorFrameSinkSupport>
HostFrameSinkManager::CreateCompositorFrameSinkSupport(
mojom::CompositorFrameSinkClient* client,
@@ -231,6 +270,9 @@ HostFrameSinkManager::CreateCompositorFrameSinkSupport(
data.support = support.get();
data.is_root = is_root;
+ if (is_root)
+ display_hit_test_query_[frame_sink_id] = std::make_unique<HitTestQuery>();
+
return support;
}
@@ -309,6 +351,10 @@ void HostFrameSinkManager::RegisterAfterConnectionLoss() {
FrameSinkData& data = map_entry.second;
if (data.client)
frame_sink_manager_->RegisterFrameSinkId(frame_sink_id);
+ if (!data.synchronization_reporting_label.empty()) {
+ frame_sink_manager_->EnableSynchronizationReporting(
+ frame_sink_id, data.synchronization_reporting_label);
+ }
if (!data.debug_label.empty()) {
frame_sink_manager_->SetFrameSinkDebugLabel(frame_sink_id,
data.debug_label);
diff --git a/chromium/components/viz/host/host_frame_sink_manager.h b/chromium/components/viz/host/host_frame_sink_manager.h
index 48c20290315..b86b9e993d6 100644
--- a/chromium/components/viz/host/host_frame_sink_manager.h
+++ b/chromium/components/viz/host/host_frame_sink_manager.h
@@ -6,6 +6,7 @@
#define COMPONENTS_VIZ_HOST_HOST_FRAME_SINK_MANAGER_H_
#include <memory>
+#include <string>
#include <vector>
#include "base/compiler_specific.h"
@@ -75,27 +76,41 @@ class VIZ_HOST_EXPORT HostFrameSinkManager
void RegisterFrameSinkId(const FrameSinkId& frame_sink_id,
HostFrameSinkClient* client);
- // Invalidates |frame_sink_id| which cleans up any unsatisified surface
- // sequences or dangling temporary references assigned to it. If there is a
- // CompositorFrameSink for |frame_sink_id| then it will be destroyed and the
- // message pipe to the client will be closed.
+ // Invalidates |frame_sink_id| which cleans up any dangling temporary
+ // references assigned to it. If there is a CompositorFrameSink for
+ // |frame_sink_id| then it will be destroyed and the message pipe to the
+ // client will be closed.
void InvalidateFrameSinkId(const FrameSinkId& frame_sink_id);
+ // Tells FrameSinkManger to report when a synchronization event completes via
+ // tracing and UMA and the duration of that event. A synchronization event
+ // occurs when a CompositorFrame submitted to the CompositorFrameSink
+ // specified by |frame_sink_id| activates after having been blocked by
+ // unresolved dependencies.
+ void EnableSynchronizationReporting(const FrameSinkId& frame_sink_id,
+ const std::string& reporting_label);
+
// |debug_label| is used when printing out the surface hierarchy so we know
// which clients are contributing which surfaces.
void SetFrameSinkDebugLabel(const FrameSinkId& frame_sink_id,
const std::string& debug_label);
- // Creates a connection for a display root to viz. Provides the same
+ // Creates a connection from a display root to viz. Provides the same
// interfaces as CreateCompositorFramesink() plus the priviledged
// DisplayPrivate and (if requested) ExternalBeginFrameController interfaces.
// When no longer needed, call InvalidateFrameSinkId().
+ //
+ // If there is already a CompositorFrameSink for |frame_sink_id| then calling
+ // this will destroy the existing CompositorFrameSink and create a new one.
void CreateRootCompositorFrameSink(
mojom::RootCompositorFrameSinkParamsPtr params);
- // Creates a connection between client to viz, using |request| and |client|,
+ // Creates a connection from a client to viz, using |request| and |client|,
// that allows the client to submit CompositorFrames. When no longer needed,
// call InvalidateFrameSinkId().
+ //
+ // If there is already a CompositorFrameSink for |frame_sink_id| then calling
+ // this will destroy the existing CompositorFrameSink and create a new one.
void CreateCompositorFrameSink(const FrameSinkId& frame_sink_id,
mojom::CompositorFrameSinkRequest request,
mojom::CompositorFrameSinkClientPtr client);
@@ -123,6 +138,9 @@ class VIZ_HOST_EXPORT HostFrameSinkManager
// Creates a FrameSinkVideoCapturer instance.
void CreateVideoCapturer(mojom::FrameSinkVideoCapturerRequest request);
+ // Marks the given SurfaceIds for destruction.
+ void EvictSurfaces(const std::vector<SurfaceId>& surface_ids);
+
// CompositorFrameSinkSupportManager:
std::unique_ptr<CompositorFrameSinkSupport> CreateCompositorFrameSinkSupport(
mojom::CompositorFrameSinkClient* client,
@@ -157,6 +175,10 @@ class VIZ_HOST_EXPORT HostFrameSinkManager
// The client to be notified of changes to this FrameSink.
HostFrameSinkClient* client = nullptr;
+ // The label to use whether this client would like reporting for
+ // synchronization events.
+ std::string synchronization_reporting_label;
+
// The name of the HostFrameSinkClient used for debug purposes.
std::string debug_label;
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 67cf6e47f4f..aa09b06d5ce 100644
--- a/chromium/components/viz/host/host_frame_sink_manager_unittest.cc
+++ b/chromium/components/viz/host/host_frame_sink_manager_unittest.cc
@@ -46,6 +46,27 @@ SurfaceId MakeSurfaceId(const FrameSinkId& frame_sink_id, uint32_t parent_id) {
LocalSurfaceId(parent_id, base::UnguessableToken::Deserialize(0, 1u)));
}
+// Holds the four interface objects needed to create a RootCompositorFrameSink.
+struct RootCompositorFrameSinkData {
+ mojom::RootCompositorFrameSinkParamsPtr BuildParams(
+ const FrameSinkId& frame_sink_id) {
+ auto params = mojom::RootCompositorFrameSinkParams::New();
+ params->frame_sink_id = frame_sink_id;
+ params->widget = gpu::kNullSurfaceHandle;
+ params->compositor_frame_sink = MakeRequest(&compositor_frame_sink);
+ params->compositor_frame_sink_client =
+ compositor_frame_sink_client.BindInterfacePtr().PassInterface();
+ params->display_private = MakeRequest(&display_private);
+ params->display_client = display_client.BindInterfacePtr().PassInterface();
+ return params;
+ }
+
+ mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink;
+ MockCompositorFrameSinkClient compositor_frame_sink_client;
+ mojom::DisplayPrivateAssociatedPtr display_private;
+ MockDisplayClient display_client;
+};
+
// A mock implementation of mojom::FrameSinkManager.
class MockFrameSinkManagerImpl : public FrameSinkManagerImpl {
public:
@@ -73,6 +94,14 @@ class MockFrameSinkManagerImpl : public FrameSinkManagerImpl {
}
MOCK_METHOD1(MockCreateRootCompositorFrameSink,
void(const FrameSinkId& frame_sink_id));
+ void DestroyCompositorFrameSink(
+ const FrameSinkId& frame_sink_id,
+ DestroyCompositorFrameSinkCallback callback) override {
+ MockDestroyCompositorFrameSink(frame_sink_id);
+ std::move(callback).Run();
+ }
+ MOCK_METHOD1(MockDestroyCompositorFrameSink,
+ void(const FrameSinkId& frame_sink_id));
MOCK_METHOD2(RegisterFrameSinkHierarchy,
void(const FrameSinkId& parent, const FrameSinkId& child));
MOCK_METHOD2(UnregisterFrameSinkHierarchy,
@@ -255,7 +284,7 @@ TEST_F(HostFrameSinkManagerLocalTest, CommunicateFrameToken) {
support->SubmitCompositorFrame(parent_id1.local_surface_id(),
std::move(compositor_frame));
- Surface* parent_surface = support->GetCurrentSurfaceForTesting();
+ Surface* parent_surface = support->GetLastCreatedSurfaceForTesting();
EXPECT_TRUE(parent_surface->has_deadline());
EXPECT_FALSE(parent_surface->HasActiveFrame());
EXPECT_TRUE(parent_surface->HasPendingFrame());
@@ -263,7 +292,7 @@ TEST_F(HostFrameSinkManagerLocalTest, CommunicateFrameToken) {
// HostFrameSinkClient.
EXPECT_EQ(0u, host_client_parent.last_frame_token_seen());
- parent_surface->ActivatePendingFrameForDeadline();
+ parent_surface->ActivatePendingFrameForDeadline(base::nullopt);
EXPECT_FALSE(parent_surface->has_deadline());
EXPECT_TRUE(parent_surface->HasActiveFrame());
EXPECT_FALSE(parent_surface->HasPendingFrame());
@@ -493,22 +522,22 @@ TEST_F(HostFrameSinkManagerLocalTest, DisplayRootTemporaryReference) {
GetFrameSinkManagerClient()->OnSurfaceCreated(surface_id);
}
-// Test the creation and desctruction of HitTestQuery, which is stored in
-// HostFrameSinkManager::display_hit_test_query_.
-TEST_F(HostFrameSinkManagerLocalTest, DisplayHitTestQueryMap) {
+// Test the creation and desctruction of HitTestAggregator and HitTestQuery.
+TEST_F(HostFrameSinkManagerLocalTest, HitTestAggregatorQuery) {
FakeHostFrameSinkClient client;
EXPECT_FALSE(FrameSinkDataExists(kFrameSinkChild1));
host().RegisterFrameSinkId(kFrameSinkChild1, &client);
EXPECT_TRUE(FrameSinkDataExists(kFrameSinkChild1));
EXPECT_FALSE(DisplayHitTestQueryExists(kFrameSinkChild1));
- auto params = mojom::RootCompositorFrameSinkParams::New();
- params->frame_sink_id = kFrameSinkChild1;
- params->widget = 0;
- host().CreateRootCompositorFrameSink(std::move(params));
+ auto support =
+ CreateCompositorFrameSinkSupport(kFrameSinkChild1, true /* is_root */);
+ support->SetUpHitTest();
EXPECT_TRUE(DisplayHitTestQueryExists(kFrameSinkChild1));
+ EXPECT_TRUE(support->GetHitTestAggregator());
host().InvalidateFrameSinkId(kFrameSinkChild1);
+ support.reset();
EXPECT_FALSE(FrameSinkDataExists(kFrameSinkChild1));
EXPECT_FALSE(DisplayHitTestQueryExists(kFrameSinkChild1));
}
@@ -523,6 +552,10 @@ TEST_F(HostFrameSinkManagerRemoteTest, RestartOnGpuCrash) {
host().RegisterFrameSinkId(kFrameSinkChild1, &host_client);
host().RegisterFrameSinkHierarchy(kFrameSinkParent1, kFrameSinkChild1);
+ RootCompositorFrameSinkData root_data;
+ host().CreateRootCompositorFrameSink(
+ root_data.BuildParams(kFrameSinkParent1));
+
MockCompositorFrameSinkClient compositor_frame_sink_client;
mojom::CompositorFrameSinkPtr compositor_frame_sink;
host().CreateCompositorFrameSink(
@@ -531,9 +564,14 @@ TEST_F(HostFrameSinkManagerRemoteTest, RestartOnGpuCrash) {
EXPECT_TRUE(IsBoundToFrameSinkManager());
- // Verify CompositorFrameSink was created on other end of message pipe.
+ // Verify registration and CompositorFrameSink creation happened.
{
base::RunLoop run_loop;
+ EXPECT_CALL(impl(), RegisterFrameSinkId(kFrameSinkParent1));
+ EXPECT_CALL(impl(), RegisterFrameSinkId(kFrameSinkChild1));
+ EXPECT_CALL(impl(), RegisterFrameSinkHierarchy(kFrameSinkParent1,
+ kFrameSinkChild1));
+ EXPECT_CALL(impl(), MockCreateRootCompositorFrameSink(kFrameSinkParent1));
EXPECT_CALL(impl(), MockCreateCompositorFrameSink(kFrameSinkChild1))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
@@ -573,45 +611,32 @@ TEST_F(HostFrameSinkManagerRemoteTest, DeletedHitTestQuery) {
// Register a FrameSinkId, and create a RootCompositorFrameSink, which should
// create a HitTestQuery.
- host().RegisterFrameSinkId(kFrameSinkChild1, &host_client);
- mojom::CompositorFrameSinkAssociatedPtrInfo
- compositor_frame_sink_associated_info;
- MockCompositorFrameSinkClient compositor_frame_sink_client;
- mojom::DisplayPrivateAssociatedPtr display_private;
- MockDisplayClient display_client;
-
- auto params = mojom::RootCompositorFrameSinkParams::New();
- params->frame_sink_id = kFrameSinkChild1;
- params->widget = 0;
- params->compositor_frame_sink =
- MakeRequest(&compositor_frame_sink_associated_info);
- params->compositor_frame_sink_client =
- compositor_frame_sink_client.BindInterfacePtr().PassInterface();
- params->display_private = MakeRequest(&display_private);
- params->display_client = display_client.BindInterfacePtr().PassInterface();
- host().CreateRootCompositorFrameSink(std::move(params));
+ host().RegisterFrameSinkId(kFrameSinkParent1, &host_client);
+ RootCompositorFrameSinkData root_data;
+ host().CreateRootCompositorFrameSink(
+ root_data.BuildParams(kFrameSinkParent1));
- EXPECT_TRUE(DisplayHitTestQueryExists(kFrameSinkChild1));
+ EXPECT_TRUE(DisplayHitTestQueryExists(kFrameSinkParent1));
// Verify RootCompositorFrameSink was created on other end of message pipe.
{
base::RunLoop run_loop;
- EXPECT_CALL(impl(), MockCreateRootCompositorFrameSink(kFrameSinkChild1))
+ EXPECT_CALL(impl(), MockCreateRootCompositorFrameSink(kFrameSinkParent1))
.WillOnce(InvokeClosure(run_loop.QuitClosure()));
run_loop.Run();
}
GetFrameSinkManagerClient()->SwitchActiveAggregatedHitTestRegionList(
- kFrameSinkChild1, 0);
+ kFrameSinkParent1, 0);
// Continue to send hit-test data to HitTestQuery associated with
// kFrameSinkChild1.
- host().InvalidateFrameSinkId(kFrameSinkChild1);
+ host().InvalidateFrameSinkId(kFrameSinkParent1);
// Invalidating kFrameSinkChild1 would delete the corresponding HitTestQuery,
// so further msgs to that HitTestQuery should be dropped.
- EXPECT_FALSE(DisplayHitTestQueryExists(kFrameSinkChild1));
+ EXPECT_FALSE(DisplayHitTestQueryExists(kFrameSinkParent1));
GetFrameSinkManagerClient()->SwitchActiveAggregatedHitTestRegionList(
- kFrameSinkChild1, 1);
+ kFrameSinkParent1, 1);
}
// Verify that HostFrameSinkManager assigns temporary references when connected
@@ -641,5 +666,63 @@ TEST_F(HostFrameSinkManagerRemoteTest, AssignTemporaryReference) {
run_loop.Run();
}
+// Verify that on lost context a RootCompositorFrameSink can be recreated.
+TEST_F(HostFrameSinkManagerRemoteTest, ContextLossRecreateRoot) {
+ FakeHostFrameSinkClient host_client;
+
+ // Register a FrameSinkId, and create a RootCompositorFrameSink.
+ host().RegisterFrameSinkId(kFrameSinkParent1, &host_client);
+ RootCompositorFrameSinkData root_data1;
+ host().CreateRootCompositorFrameSink(
+ root_data1.BuildParams(kFrameSinkParent1));
+
+ // Verify RootCompositorFrameSink was created on other end of message pipe.
+ EXPECT_CALL(impl(), MockCreateRootCompositorFrameSink(kFrameSinkParent1));
+ root_data1.compositor_frame_sink.FlushForTesting();
+ testing::Mock::VerifyAndClearExpectations(&impl());
+
+ // Create a new RootCompositorFrameSink and try to connect it with the same
+ // FrameSinkId. This will happen if the browser GL context is lost.
+ RootCompositorFrameSinkData root_data2;
+ host().CreateRootCompositorFrameSink(
+ root_data2.BuildParams(kFrameSinkParent1));
+
+ // Verify RootCompositorFrameSink is destroyed and then recreated.
+ EXPECT_CALL(impl(), MockDestroyCompositorFrameSink(kFrameSinkParent1));
+ EXPECT_CALL(impl(), MockCreateRootCompositorFrameSink(kFrameSinkParent1));
+ root_data2.compositor_frame_sink.FlushForTesting();
+}
+
+// Verify that on lost context a CompositorFrameSink can be recreated.
+TEST_F(HostFrameSinkManagerRemoteTest, ContextLossRecreateNonRoot) {
+ FakeHostFrameSinkClient host_client;
+
+ // Register a FrameSinkId and create a CompositorFrameSink.
+ host().RegisterFrameSinkId(kFrameSinkChild1, &host_client);
+ MockCompositorFrameSinkClient compositor_frame_sink_client1;
+ mojom::CompositorFrameSinkPtr compositor_frame_sink1;
+ host().CreateCompositorFrameSink(
+ kFrameSinkChild1, MakeRequest(&compositor_frame_sink1),
+ compositor_frame_sink_client1.BindInterfacePtr());
+
+ // Verify CompositorFrameSink was created on other end of message pipe.
+ EXPECT_CALL(impl(), MockCreateCompositorFrameSink(kFrameSinkChild1));
+ compositor_frame_sink1.FlushForTesting();
+ testing::Mock::VerifyAndClearExpectations(&impl());
+
+ // Create a new CompositorFrameSink and try to connect it with the same
+ // FrameSinkId. This will happen if the client GL context is lost.
+ MockCompositorFrameSinkClient compositor_frame_sink_client2;
+ mojom::CompositorFrameSinkPtr compositor_frame_sink2;
+ host().CreateCompositorFrameSink(
+ kFrameSinkChild1, MakeRequest(&compositor_frame_sink2),
+ compositor_frame_sink_client2.BindInterfacePtr());
+
+ // Verify CompositorFrameSink is destroyed and then recreated.
+ EXPECT_CALL(impl(), MockDestroyCompositorFrameSink(kFrameSinkChild1));
+ EXPECT_CALL(impl(), MockCreateCompositorFrameSink(kFrameSinkChild1));
+ compositor_frame_sink2.FlushForTesting();
+}
+
} // namespace test
} // namespace viz
diff --git a/chromium/components/viz/host/renderer_settings_creation.cc b/chromium/components/viz/host/renderer_settings_creation.cc
index 5413bcc8406..e0b69bf8db1 100644
--- a/chromium/components/viz/host/renderer_settings_creation.cc
+++ b/chromium/components/viz/host/renderer_settings_creation.cc
@@ -9,8 +9,13 @@
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "components/viz/common/display/renderer_settings.h"
+#include "components/viz/common/features.h"
#include "ui/base/ui_base_switches.h"
+#if defined(OS_MACOSX)
+#include "ui/base/cocoa/remote_layer_api.h"
+#endif
+
namespace viz {
namespace {
@@ -35,10 +40,6 @@ bool GetSwitchValueAsInt(const base::CommandLine* command_line,
} // namespace
-ResourceSettings CreateResourceSettings() {
- return ResourceSettings();
-}
-
RendererSettings CreateRendererSettings() {
RendererSettings renderer_settings;
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -53,12 +54,17 @@ RendererSettings CreateRendererSettings() {
command_line->HasSwitch(switches::kTintGlCompositedContent);
renderer_settings.show_overdraw_feedback =
command_line->HasSwitch(switches::kShowOverdrawFeedback);
- renderer_settings.enable_draw_occlusion =
- command_line->HasSwitch(switches::kEnableDrawOcclusion);
+ renderer_settings.enable_draw_occlusion = features::IsDrawOcclusionEnabled();
renderer_settings.allow_antialiasing =
!command_line->HasSwitch(switches::kDisableCompositedAntialiasing);
renderer_settings.use_skia_renderer =
command_line->HasSwitch(switches::kUseSkiaRenderer);
+#if defined(OS_MACOSX)
+ renderer_settings.allow_overlays =
+ ui::RemoteLayerAPISupported() &&
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableMacOverlays);
+#endif
if (command_line->HasSwitch(switches::kSlowDownCompositingScaleFactor)) {
const int kMinSlowDownScaleFactor = 1;
const int kMaxSlowDownScaleFactor = 1000;
diff --git a/chromium/components/viz/host/renderer_settings_creation.h b/chromium/components/viz/host/renderer_settings_creation.h
index 53390ea1c1c..e091be4edf2 100644
--- a/chromium/components/viz/host/renderer_settings_creation.h
+++ b/chromium/components/viz/host/renderer_settings_creation.h
@@ -11,12 +11,10 @@
namespace viz {
class RendererSettings;
-class ResourceSettings;
} // namespace viz
namespace viz {
-VIZ_HOST_EXPORT ResourceSettings CreateResourceSettings();
VIZ_HOST_EXPORT RendererSettings CreateRendererSettings();
} // namespace viz
diff --git a/chromium/components/viz/host/server_gpu_memory_buffer_manager.cc b/chromium/components/viz/host/server_gpu_memory_buffer_manager.cc
index 3a045ac94cf..630b3be00de 100644
--- a/chromium/components/viz/host/server_gpu_memory_buffer_manager.cc
+++ b/chromium/components/viz/host/server_gpu_memory_buffer_manager.cc
@@ -4,6 +4,8 @@
#include "components/viz/host/server_gpu_memory_buffer_manager.h"
+#include <utility>
+
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -60,10 +62,11 @@ void ServerGpuMemoryBufferManager::AllocateGpuMemoryBuffer(
pending_buffers_.insert(client_id);
gpu_service_->CreateGpuMemoryBuffer(
id, size, format, usage, client_id, surface_handle,
- base::Bind(&ServerGpuMemoryBufferManager::OnGpuMemoryBufferAllocated,
- weak_ptr_, client_id,
- gfx::BufferSizeForBufferFormat(size, format),
- base::Passed(std::move(callback))));
+ base::BindOnce(
+ &ServerGpuMemoryBufferManager::OnGpuMemoryBufferAllocated,
+ weak_ptr_, client_id,
+ gfx::BufferSizeForBufferFormat(size, format),
+ std::move(callback)));
return;
}
}
diff --git a/chromium/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc b/chromium/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc
index 6b65636a791..0dfe670a2d0 100644
--- a/chromium/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc
+++ b/chromium/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc
@@ -4,6 +4,8 @@
#include "components/viz/host/server_gpu_memory_buffer_manager.h"
+#include <utility>
+
#include "base/run_loop.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
@@ -313,9 +315,7 @@ TEST_F(ServerGpuMemoryBufferManagerTest,
// Destroy the buffer in a different thread.
base::Thread diff_thread("DestroyThread");
ASSERT_TRUE(diff_thread.Start());
- diff_thread.task_runner()->PostTask(
- FROM_HERE, base::Bind([](std::unique_ptr<gfx::GpuMemoryBuffer> buffer) {},
- base::Passed(&buffer)));
+ diff_thread.task_runner()->DeleteSoon(FROM_HERE, std::move(buffer));
diff_thread.Stop();
}
diff --git a/chromium/components/viz/presubmit_checks.py b/chromium/components/viz/presubmit_checks.py
index da6c89dbc10..e73bdfce58d 100644
--- a/chromium/components/viz/presubmit_checks.py
+++ b/chromium/components/viz/presubmit_checks.py
@@ -138,34 +138,6 @@ def CheckDoubleAngles(input_api, output_api, white_list,
return [output_api.PresubmitError('Use >> instead of > >:', items=errors)]
return []
-def CheckUniquePtr(input_api, output_api,
- white_list, black_list=None):
- black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST)
- source_file_filter = lambda x: input_api.FilterSourceFile(x,
- white_list,
- black_list)
- errors = []
- for f in input_api.AffectedSourceFiles(source_file_filter):
- for line_number, line in f.ChangedContents():
- # Disallow:
- # return std::unique_ptr<T>(foo);
- # bar = std::unique_ptr<T>(foo);
- # But allow:
- # return std::unique_ptr<T[]>(foo);
- # bar = std::unique_ptr<T[]>(foo);
- if re.search(r'(=|\breturn)\s*std::unique_ptr<.*?(?<!])>\([^)]+\)', line):
- errors.append(output_api.PresubmitError(
- ('%s:%d uses explicit std::unique_ptr constructor. ' +
- 'Use base::MakeUnique<T>() instead.') %
- (f.LocalPath(), line_number)))
- # Disallow:
- # std::unique_ptr<T>()
- if re.search(r'\bstd::unique_ptr<.*?>\(\)', line):
- errors.append(output_api.PresubmitError(
- '%s:%d uses std::unique_ptr<T>(). Use nullptr instead.' %
- (f.LocalPath(), line_number)))
- return errors
-
def FindUnquotedQuote(contents, pos):
match = re.search(r"(?<!\\)(?P<quote>\")", contents[pos:])
return -1 if not match else match.start("quote") + pos
@@ -331,7 +303,6 @@ def RunAllChecks(input_api, output_api, white_list):
results += CheckChangeLintsClean(input_api, output_api, white_list)
results += CheckTodos(input_api, output_api)
results += CheckDoubleAngles(input_api, output_api, white_list)
- results += CheckUniquePtr(input_api, output_api, white_list)
results += CheckNamespace(input_api, output_api)
results += CheckMojoms(input_api, output_api)
results += CheckForUseOfWrongClock(input_api, output_api, white_list)
diff --git a/chromium/components/viz/service/BUILD.gn b/chromium/components/viz/service/BUILD.gn
index a2c559832d4..f241c5e167f 100644
--- a/chromium/components/viz/service/BUILD.gn
+++ b/chromium/components/viz/service/BUILD.gn
@@ -78,6 +78,8 @@ viz_component("service") {
"display/static_geometry_binding.h",
"display/surface_aggregator.cc",
"display/surface_aggregator.h",
+ "display/sync_query_collection.cc",
+ "display/sync_query_collection.h",
"display/texture_deleter.cc",
"display/texture_deleter.h",
"display_embedder/buffer_queue.cc",
@@ -137,8 +139,6 @@ viz_component("service") {
"hit_test/hit_test_aggregator_delegate.h",
"hit_test/hit_test_manager.cc",
"hit_test/hit_test_manager.h",
- "surfaces/direct_surface_reference_factory.cc",
- "surfaces/direct_surface_reference_factory.h",
"surfaces/surface.cc",
"surfaces/surface.h",
"surfaces/surface_client.h",
@@ -175,7 +175,6 @@ viz_component("service") {
"//media",
"//media/capture:capture_lib",
"//media/gpu/ipc/service",
- "//media/mojo/common:mojo_shared_buffer_video_frame",
"//media/mojo/services",
"//services/viz/privileged/interfaces",
"//skia",
@@ -245,6 +244,8 @@ viz_component("service") {
sources += [
"display_embedder/compositor_overlay_candidate_validator_win.cc",
"display_embedder/compositor_overlay_candidate_validator_win.h",
+ "display_embedder/gl_output_surface_win.cc",
+ "display_embedder/gl_output_surface_win.h",
"display_embedder/software_output_device_win.cc",
"display_embedder/software_output_device_win.h",
]
@@ -287,6 +288,7 @@ viz_source_set("unit_tests") {
"frame_sinks/video_detector_unittest.cc",
"gl/gpu_service_impl_unittest.cc",
"hit_test/hit_test_aggregator_unittest.cc",
+ "surfaces/surface_dependency_deadline_unittest.cc",
"surfaces/surface_hittest_unittest.cc",
"surfaces/surface_unittest.cc",
]
diff --git a/chromium/components/viz/service/DEPS b/chromium/components/viz/service/DEPS
index 68254d64874..4ec6497057f 100644
--- a/chromium/components/viz/service/DEPS
+++ b/chromium/components/viz/service/DEPS
@@ -1,11 +1,16 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+cc",
+ "-components/viz/common/features.h",
"-components/viz/common/switches.h",
- "+components/viz/service",
+ "-components/viz/service",
+ "+components/viz/service/viz_service_export.h",
"+services/viz/privileged/interfaces",
"+services/viz/public/interfaces",
"+third_party/skia",
"+ui/latency",
+ "+ui/ozone/public",
]
specific_include_rules = {
diff --git a/chromium/components/viz/service/display/DEPS b/chromium/components/viz/service/display/DEPS
index 2b42f987f55..314ebb3a28c 100644
--- a/chromium/components/viz/service/display/DEPS
+++ b/chromium/components/viz/service/display/DEPS
@@ -1,3 +1,5 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+base",
"+cc/base",
@@ -5,6 +7,7 @@ include_rules = [
"+cc/output",
"+cc/resources",
"+cc/scheduler",
+ "+components/viz/service/surfaces",
"+gpu/command_buffer/client",
"+gpu/command_buffer/common",
"+gpu/GLES2",
@@ -26,6 +29,7 @@ specific_include_rules = {
],
".*_(unit|pixel|perf)test\.cc": [
"+cc/test",
+ "+components/viz/service/display_embedder",
"+components/viz/service/frame_sinks",
"+components/viz/test",
"+gpu/GLES2",
diff --git a/chromium/components/viz/service/display/bsp_tree_perftest.cc b/chromium/components/viz/service/display/bsp_tree_perftest.cc
index 697850722cc..76ea2e10eff 100644
--- a/chromium/components/viz/service/display/bsp_tree_perftest.cc
+++ b/chromium/components/viz/service/display/bsp_tree_perftest.cc
@@ -43,7 +43,7 @@ class BspTreePerfTest : public cc::LayerTreeTest {
void SetupTree() override {
gfx::Size viewport = gfx::Size(720, 1038);
- layer_tree_host()->SetViewportSize(viewport);
+ layer_tree_host()->SetViewportSizeAndScale(viewport, 1.f, LocalSurfaceId());
scoped_refptr<cc::Layer> root =
ParseTreeFromJson(json_, &content_layer_client_);
ASSERT_TRUE(root.get());
diff --git a/chromium/components/viz/service/display/direct_renderer.cc b/chromium/components/viz/service/display/direct_renderer.cc
index 9d022c6b439..70e0f88a6c9 100644
--- a/chromium/components/viz/service/display/direct_renderer.cc
+++ b/chromium/components/viz/service/display/direct_renderer.cc
@@ -17,7 +17,6 @@
#include "base/trace_event/trace_event.h"
#include "cc/base/math_util.h"
#include "cc/paint/filter_operations.h"
-#include "cc/resources/scoped_resource.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/quads/draw_quad.h"
@@ -193,8 +192,8 @@ void DirectRenderer::DecideRenderPassAllocationsForFrame(
continue;
}
}
- render_passes_in_frame[pass->id] = {RenderPassTextureSize(pass.get()),
- pass->generate_mipmap};
+ render_passes_in_frame[pass->id] = {
+ CalculateTextureSizeForRenderPass(pass.get()), pass->generate_mipmap};
}
UpdateRenderPassTextures(render_passes_in_draw_order, render_passes_in_frame);
}
@@ -203,7 +202,7 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
float device_scale_factor,
const gfx::Size& device_viewport_size) {
DCHECK(visible_);
- TRACE_EVENT0("viz", "DirectRenderer::DrawFrame");
+ TRACE_EVENT0("viz,benchmark", "DirectRenderer::DrawFrame");
UMA_HISTOGRAM_COUNTS(
"Renderer4.renderPassCount",
base::saturated_cast<int>(render_passes_in_draw_order->size()));
@@ -621,7 +620,7 @@ void DirectRenderer::UseRenderPass(const RenderPass* render_pass) {
return;
}
- gfx::Size enlarged_size = RenderPassTextureSize(render_pass);
+ gfx::Size enlarged_size = CalculateTextureSizeForRenderPass(render_pass);
enlarged_size.Enlarge(enlarge_pass_texture_amount_.width(),
enlarge_pass_texture_amount_.height());
@@ -636,7 +635,9 @@ void DirectRenderer::UseRenderPass(const RenderPass* render_pass) {
BindFramebufferToTexture(render_pass->id);
InitializeViewport(current_frame(), render_pass->output_rect,
gfx::Rect(render_pass->output_rect.size()),
- GetRenderPassTextureSize(render_pass->id));
+ // If the render pass backing is cached, we might have
+ // bigger size comparing to the size that was generated.
+ GetRenderPassBackingPixelSize(render_pass->id));
}
gfx::Rect DirectRenderer::ComputeScissorRectForRenderPass(
@@ -657,7 +658,8 @@ gfx::Rect DirectRenderer::ComputeScissorRectForRenderPass(
return render_pass->damage_rect;
}
-gfx::Size DirectRenderer::RenderPassTextureSize(const RenderPass* render_pass) {
+gfx::Size DirectRenderer::CalculateTextureSizeForRenderPass(
+ const RenderPass* render_pass) {
// Round the size of the render pass backings to a multiple of 64 pixels. This
// reduces memory fragmentation. https://crbug.com/146070. This also allows
// backings to be more easily reused during a resize operation.
diff --git a/chromium/components/viz/service/display/direct_renderer.h b/chromium/components/viz/service/display/direct_renderer.h
index ef89a16fc20..63be93b71c4 100644
--- a/chromium/components/viz/service/display/direct_renderer.h
+++ b/chromium/components/viz/service/display/direct_renderer.h
@@ -131,7 +131,7 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
const gfx::Rect& render_pass_scissor);
void SetScissorTestRectInDrawSpace(const gfx::Rect& draw_space_rect);
- gfx::Size RenderPassTextureSize(const RenderPass* render_pass);
+ gfx::Size CalculateTextureSizeForRenderPass(const RenderPass* render_pass);
void FlushPolygons(
base::circular_deque<std::unique_ptr<DrawPolygon>>* poly_list,
@@ -166,7 +166,7 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
const RenderPassRequirements& requirements) = 0;
virtual bool IsRenderPassResourceAllocated(
const RenderPassId& render_pass_id) const = 0;
- virtual gfx::Size GetRenderPassTextureSize(
+ virtual gfx::Size GetRenderPassBackingPixelSize(
const RenderPassId& render_pass_id) = 0;
virtual void BindFramebufferToOutputSurface() = 0;
virtual void BindFramebufferToTexture(const RenderPassId render_pass_id) = 0;
diff --git a/chromium/components/viz/service/display/display.cc b/chromium/components/viz/service/display/display.cc
index 5063b7c5608..5ee1877d404 100644
--- a/chromium/components/viz/service/display/display.cc
+++ b/chromium/components/viz/service/display/display.cc
@@ -564,24 +564,86 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
const SharedQuadState* last_sqs = nullptr;
cc::SimpleEnclosedRegion occlusion_in_target_space;
bool current_sqs_intersects_occlusion = false;
+ int minimum_draw_occlusion_height =
+ settings_.kMinimumDrawOcclusionSize.height() * device_scale_factor_;
+ int minimum_draw_occlusion_width =
+ settings_.kMinimumDrawOcclusionSize.width() * device_scale_factor_;
+
+ // The 160 comes from the LayerTreeSettings::minimum_occlusion_tracking_size
+ // default value, which is not accessible from here.
+ gfx::Size layer_occlusion_skip_rect_size(160 * device_scale_factor_,
+ 160 * device_scale_factor_);
+
+ // Record the total number of DrawQudas has a |visible_rect| that is smaller
+ // than minimum occlusion tracking size in layer occlusion.
+ size_t total_small_quads = 0;
+
+ // Record the total number of DrawQuads that are skipped from applying draw
+ // occlusion.
+ size_t total_quad_skipped = 0;
+
+ // Record the total number of DrawQuads that are not shown on screen so that
+ // it's removed by draw occlusion.
+ size_t total_quad_removed = 0;
+
+ // Record the total number of DrawQuads that are partially shown on screen so
+ // that its visible rect is updated by draw occlusion.
+ size_t total_quad_resized = 0;
+
+ // Record the total number of DrawQuads has non scale or translation
+ // transform.
+ size_t total_quad_with_complex_transform = 0;
+
+ // Total quad area to be drawn on screen before applying draw occlusion.
+ size_t total_quad_area_shown_wo_occlusion_px = 0;
+
+ // Total area not draw skipped by draw occlusion.
+ size_t total_area_saved_in_px = 0;
+
for (const auto& pass : frame->render_pass_list) {
// TODO(yiyix): Add filter effects to draw occlusion calculation and perform
// draw occlusion on render pass.
- if (!pass->filters.IsEmpty() || !pass->background_filters.IsEmpty())
+ if (!pass->filters.IsEmpty() || !pass->background_filters.IsEmpty()) {
+ for (auto* const quad : pass->quad_list) {
+ total_quad_area_shown_wo_occlusion_px +=
+ quad->visible_rect.height() * quad->visible_rect.width();
+ }
continue;
+ }
// TODO(yiyix): Perform draw occlusion inside the render pass with
// transparent background.
- if (pass != frame->render_pass_list.back())
+ if (pass != frame->render_pass_list.back()) {
+ for (auto* const quad : pass->quad_list) {
+ total_quad_area_shown_wo_occlusion_px +=
+ quad->visible_rect.height() * quad->visible_rect.width();
+ }
continue;
+ }
auto quad_list_end = pass->quad_list.end();
gfx::Rect occlusion_in_quad_content_space;
for (auto quad = pass->quad_list.begin(); quad != quad_list_end;) {
- // RenderPassDrawQuad is a special type of DrawQuad where the visible_rect
- // of shared quad state is not entirely covered by draw quads in it.
- if (quad->material == ContentDrawQuadBase::Material::RENDER_PASS) {
+ total_quad_area_shown_wo_occlusion_px +=
+ quad->visible_rect.height() * quad->visible_rect.width();
+ if (quad->visible_rect.width() <=
+ layer_occlusion_skip_rect_size.width() &&
+ quad->visible_rect.height() <=
+ layer_occlusion_skip_rect_size.height() &&
+ quad->visible_rect.height() >= minimum_draw_occlusion_height &&
+ quad->visible_rect.width() >= minimum_draw_occlusion_width) {
+ total_small_quads += 1;
+ }
+
+ // Skip quad if it is a RenderPassDrawQuad because RenderPassDrawQuad is a
+ // special type of DrawQuad where the visible_rect of shared quad state is
+ // not entirely covered by draw quads in it; or the DrawQuad size is
+ // smaller than the kMinimumDrawOcclusionSize.
+ if (quad->material == ContentDrawQuadBase::Material::RENDER_PASS ||
+ (quad->visible_rect.width() <= minimum_draw_occlusion_width &&
+ quad->visible_rect.height() <= minimum_draw_occlusion_height)) {
++quad;
+ total_quad_skipped += 1;
continue;
}
@@ -638,7 +700,12 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
cc::MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(
reverse_transform, occlusion_in_target_space.bounds());
} else {
+ total_quad_with_complex_transform += 1;
occlusion_in_quad_content_space = gfx::Rect();
+
+ UMA_HISTOGRAM_COUNTS_1M(
+ "Compositing.Display.Draw.Quads.With.Complex.Transform.Area",
+ quad->visible_rect.height() * quad->visible_rect.width());
}
}
@@ -651,14 +718,23 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
// Case 1: for simple transforms (scale or translation), define the
// occlusion region in the quad content space. If the |quad| is not
// shown on the screen, then remove |quad| from the compositor frame.
+ total_area_saved_in_px +=
+ quad->visible_rect.height() * quad->visible_rect.width();
quad = pass->quad_list.EraseAndInvalidateAllPointers(quad);
+ total_quad_removed += 1;
} else if (occlusion_in_quad_content_space.Intersects(
quad->visible_rect)) {
// Case 2: for simple transforms, if the quad is partially shown on
// screen and the region formed by (occlusion region - visible_rect) is
// a rect, then update visible_rect to the resulting rect.
+ gfx::Rect origin_rect = quad->visible_rect;
quad->visible_rect.Subtract(occlusion_in_quad_content_space);
+ if (origin_rect != quad->visible_rect) {
+ total_quad_resized += 1;
+ origin_rect.Subtract(quad->visible_rect);
+ total_area_saved_in_px += origin_rect.height() * origin_rect.width();
+ }
++quad;
} else if (occlusion_in_quad_content_space.IsEmpty() &&
occlusion_in_target_space.Contains(
@@ -667,12 +743,35 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
// Case 3: for non simple transforms, define the occlusion region in
// target space. If the |quad| is not shown on the screen, then remove
// |quad| from the compositor frame.
+ total_area_saved_in_px +=
+ quad->visible_rect.height() * quad->visible_rect.width();
quad = pass->quad_list.EraseAndInvalidateAllPointers(quad);
+ total_quad_removed += 1;
} else {
++quad;
}
}
}
+ UMA_HISTOGRAM_COUNTS_1000("Compositing.Display.Draw.Quads.Skipped",
+ total_quad_skipped);
+ UMA_HISTOGRAM_COUNTS_1000("Compositing.Display.Draw.Quads.Removed",
+ total_quad_removed);
+ UMA_HISTOGRAM_COUNTS_1000("Compositing.Display.Draw.Quads.Resized",
+ total_quad_resized);
+ UMA_HISTOGRAM_COUNTS_1000(
+ "Compositing.Display.Draw.Quads.With.Complex.Transform",
+ total_quad_with_complex_transform);
+ UMA_HISTOGRAM_COUNTS_1000("Compositing.Display.Draw.Quads.Smaller",
+ total_small_quads);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Compositing.Display.Draw.Occlusion.Percentage.Saved",
+ total_quad_area_shown_wo_occlusion_px == 0
+ ? 0
+ : total_area_saved_in_px * 100 /
+ total_quad_area_shown_wo_occlusion_px);
+ UMA_HISTOGRAM_COUNTS_1M(
+ "Compositing.Display.Draw.Occlusion.Drawing.Area.Saved2",
+ total_area_saved_in_px);
}
} // namespace viz
diff --git a/chromium/components/viz/service/display/display_perftest.cc b/chromium/components/viz/service/display/display_perftest.cc
index afdd4430ceb..ab7d01990c7 100644
--- a/chromium/components/viz/service/display/display_perftest.cc
+++ b/chromium/components/viz/service/display/display_perftest.cc
@@ -8,8 +8,6 @@
#include "base/test/null_task_runner.h"
#include "base/time/time.h"
#include "cc/base/lap_timer.h"
-#include "cc/test/fake_output_surface.h"
-#include "cc/test/test_context_provider.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/draw_quad.h"
@@ -21,6 +19,7 @@
#include "components/viz/service/display/display_scheduler.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
+#include "components/viz/test/fake_output_surface.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"
@@ -47,11 +46,8 @@ class RemoveOverdrawQuadPerfTest : public testing::Test {
auto scheduler = std::make_unique<DisplayScheduler>(&begin_frame_source_,
task_runner_.get(), 1);
- std::unique_ptr<cc::FakeOutputSurface> output_surface;
-
- auto provider = cc::TestContextProvider::Create();
- provider->BindToCurrentThread();
- output_surface = cc::FakeOutputSurface::Create3d(std::move(provider));
+ std::unique_ptr<FakeOutputSurface> output_surface =
+ FakeOutputSurface::Create3d();
auto display = std::make_unique<Display>(
&bitmap_manager_, RendererSettings(), frame_sink_id,
diff --git a/chromium/components/viz/service/display/display_scheduler.cc b/chromium/components/viz/service/display/display_scheduler.cc
index cb6acd51731..402eeccc064 100644
--- a/chromium/components/viz/service/display/display_scheduler.cc
+++ b/chromium/components/viz/service/display/display_scheduler.cc
@@ -70,7 +70,11 @@ void DisplayScheduler::SetVisible(bool visible) {
void DisplayScheduler::SetRootSurfaceResourcesLocked(bool locked) {
TRACE_EVENT1("viz", "DisplayScheduler::SetRootSurfaceResourcesLocked",
"locked", locked);
+ if (root_surface_resources_locked_ == locked)
+ return;
+
root_surface_resources_locked_ = locked;
+ MaybeStartObservingBeginFrames();
ScheduleBeginFrameDeadline();
}
@@ -292,7 +296,8 @@ void DisplayScheduler::StopObservingBeginFrames() {
bool DisplayScheduler::ShouldDraw() {
// Note: When any of these cases becomes true, MaybeStartObservingBeginFrames
// must be called to ensure the draw will happen.
- return needs_draw_ && !output_surface_lost_ && visible_;
+ return needs_draw_ && !output_surface_lost_ && visible_ &&
+ !root_surface_resources_locked_;
}
void DisplayScheduler::OnBeginFrameSourcePausedChanged(bool paused) {
@@ -307,7 +312,9 @@ void DisplayScheduler::OnSurfaceCreated(const SurfaceId& surface_id) {}
void DisplayScheduler::OnFirstSurfaceActivation(
const SurfaceInfo& surface_info) {}
-void DisplayScheduler::OnSurfaceActivated(const SurfaceId& surface_id) {}
+void DisplayScheduler::OnSurfaceActivated(
+ const SurfaceId& surface_id,
+ base::Optional<base::TimeDelta> duration) {}
void DisplayScheduler::OnSurfaceDestroyed(const SurfaceId& surface_id) {
auto it = surface_states_.find(surface_id);
@@ -476,7 +483,7 @@ bool DisplayScheduler::AttemptDrawAndSwap() {
begin_frame_deadline_task_time_ = base::TimeTicks();
if (ShouldDraw()) {
- if (pending_swaps_ < max_pending_swaps_ && !root_surface_resources_locked_)
+ if (pending_swaps_ < max_pending_swaps_)
return DrawAndSwap();
} else {
// We are going idle, so reset expectations.
diff --git a/chromium/components/viz/service/display/display_scheduler.h b/chromium/components/viz/service/display/display_scheduler.h
index b20b26c673f..d8af7a42468 100644
--- a/chromium/components/viz/service/display/display_scheduler.h
+++ b/chromium/components/viz/service/display/display_scheduler.h
@@ -71,7 +71,8 @@ class VIZ_SERVICE_EXPORT DisplayScheduler : public BeginFrameObserverBase,
// SurfaceObserver implementation.
void OnSurfaceCreated(const SurfaceId& surface_id) override;
void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override;
- void OnSurfaceActivated(const SurfaceId& surface_id) override;
+ void OnSurfaceActivated(const SurfaceId& surface_id,
+ base::Optional<base::TimeDelta> duration) override;
void OnSurfaceDestroyed(const SurfaceId& surface_id) override;
bool OnSurfaceDamaged(const SurfaceId& surface_id,
const BeginFrameAck& ack) override;
diff --git a/chromium/components/viz/service/display/display_scheduler_unittest.cc b/chromium/components/viz/service/display/display_scheduler_unittest.cc
index 72117520e12..a0135007266 100644
--- a/chromium/components/viz/service/display/display_scheduler_unittest.cc
+++ b/chromium/components/viz/service/display/display_scheduler_unittest.cc
@@ -123,7 +123,7 @@ class DisplaySchedulerTest : public testing::Test {
explicit DisplaySchedulerTest(bool wait_for_all_surfaces_before_draw = false)
: fake_begin_frame_source_(0.f, false),
task_runner_(new base::NullTaskRunner),
- surface_manager_(SurfaceManager::LifetimeType::REFERENCES, 4u),
+ surface_manager_(4u),
scheduler_(&fake_begin_frame_source_,
&surface_manager_,
task_runner_.get(),
@@ -629,10 +629,14 @@ TEST_F(DisplaySchedulerTest, RootSurfaceResourcesLocked) {
// Deadline triggers normally when root resources are unlocked.
AdvanceTimeAndBeginFrameForTest({sid1, root_surface_id});
- late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
+ EXPECT_FALSE(scheduler_.inside_begin_frame_deadline_interval());
SurfaceDamaged(sid1);
+
+ // The deadline is not updated because the display scheduler does not receive
+ // a BeginFrame while root resources are locked.
EXPECT_EQ(late_deadline, scheduler_.DesiredBeginFrameDeadlineTimeForTest());
scheduler_.SetRootSurfaceResourcesLocked(false);
+ EXPECT_TRUE(scheduler_.inside_begin_frame_deadline_interval());
SurfaceDamaged(root_surface_id);
EXPECT_EQ(base::TimeTicks(),
scheduler_.DesiredBeginFrameDeadlineTimeForTest());
diff --git a/chromium/components/viz/service/display/display_unittest.cc b/chromium/components/viz/service/display/display_unittest.cc
index 75e61a0b3d4..43ff2d80430 100644
--- a/chromium/components/viz/service/display/display_unittest.cc
+++ b/chromium/components/viz/service/display/display_unittest.cc
@@ -9,9 +9,7 @@
#include "base/run_loop.h"
#include "base/test/null_task_runner.h"
#include "cc/base/math_util.h"
-#include "cc/test/fake_output_surface.h"
#include "cc/test/scheduler_test_common.h"
-#include "cc/test/test_shared_bitmap_manager.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
@@ -30,7 +28,10 @@
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_manager.h"
#include "components/viz/test/compositor_frame_helpers.h"
+#include "components/viz/test/fake_output_surface.h"
#include "components/viz/test/mock_compositor_frame_sink_client.h"
+#include "components/viz/test/test_shared_bitmap_manager.h"
+#include "components/viz/test/test_web_graphics_context_3d.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -104,21 +105,21 @@ class DisplayTest : public testing::Test {
true /* needs_sync_points */)),
task_runner_(new base::NullTaskRunner) {}
- ~DisplayTest() override { support_->EvictCurrentSurface(); }
+ ~DisplayTest() override {}
void SetUpDisplay(const RendererSettings& settings,
- std::unique_ptr<cc::TestWebGraphicsContext3D> context) {
+ std::unique_ptr<TestWebGraphicsContext3D> context) {
begin_frame_source_.reset(new StubBeginFrameSource);
- std::unique_ptr<cc::FakeOutputSurface> output_surface;
+ std::unique_ptr<FakeOutputSurface> output_surface;
if (context) {
- auto provider = cc::TestContextProvider::Create(std::move(context));
+ auto provider = TestContextProvider::Create(std::move(context));
provider->BindToCurrentThread();
- output_surface = cc::FakeOutputSurface::Create3d(std::move(provider));
+ output_surface = FakeOutputSurface::Create3d(std::move(provider));
} else {
auto device = std::make_unique<TestSoftwareOutputDevice>();
software_output_device_ = device.get();
- output_surface = cc::FakeOutputSurface::CreateSoftware(std::move(device));
+ output_surface = FakeOutputSurface::CreateSoftware(std::move(device));
}
output_surface_ = output_surface.get();
auto scheduler = std::make_unique<TestDisplayScheduler>(
@@ -170,11 +171,11 @@ class DisplayTest : public testing::Test {
std::unique_ptr<CompositorFrameSinkSupport> support_;
ParentLocalSurfaceIdAllocator id_allocator_;
scoped_refptr<base::NullTaskRunner> task_runner_;
- cc::TestSharedBitmapManager shared_bitmap_manager_;
+ TestSharedBitmapManager shared_bitmap_manager_;
std::unique_ptr<BeginFrameSource> begin_frame_source_;
std::unique_ptr<Display> display_;
TestSoftwareOutputDevice* software_output_device_ = nullptr;
- cc::FakeOutputSurface* output_surface_ = nullptr;
+ FakeOutputSurface* output_surface_ = nullptr;
TestDisplayScheduler* scheduler_ = nullptr;
};
@@ -531,7 +532,7 @@ TEST_F(DisplayTest, OverLatencyInfoCap) {
LatencyInfoCapTest(true);
}
-class MockedContext : public cc::TestWebGraphicsContext3D {
+class MockedContext : public TestWebGraphicsContext3D {
public:
MOCK_METHOD0(shallowFinishCHROMIUM, void());
};
@@ -618,7 +619,7 @@ class CountLossDisplayClient : public StubDisplayClient {
};
TEST_F(DisplayTest, ContextLossInformsClient) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
CountLossDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -655,7 +656,7 @@ TEST_F(DisplayTest, CompositorFrameDamagesCorrectDisplay) {
TestDisplayScheduler* scheduler2 = scheduler_for_display2.get();
auto display2 = CreateDisplay(
settings, kAnotherFrameSinkId, std::move(scheduler_for_display2),
- cc::FakeOutputSurface::CreateSoftware(
+ FakeOutputSurface::CreateSoftware(
std::make_unique<TestSoftwareOutputDevice>()));
manager_.RegisterBeginFrameSource(begin_frame_source2.get(),
kAnotherFrameSinkId);
@@ -691,7 +692,7 @@ TEST_F(DisplayTest, CompositorFrameDamagesCorrectDisplay) {
// Check if draw occlusion does not remove any DrawQuads when no quad is being
// covered completely.
TEST_F(DisplayTest, DrawOcclusionWithNonCoveringDrawQuad) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -910,7 +911,9 @@ TEST_F(DisplayTest, DrawOcclusionWithNonCoveringDrawQuad) {
// Check if draw occlusion removes DrawQuads that are not shown on screen.
TEST_F(DisplayTest, CompositorFrameWithOverlapDrawQuad) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1037,9 +1040,197 @@ TEST_F(DisplayTest, CompositorFrameWithOverlapDrawQuad) {
TearDownDisplay();
}
+// Check if draw occlusion is not applied on DrawQuads that are smaller than
+// skip_rect size, such that DrawQuads that are smaller than the |skip_rect|
+// are drawn on the screen regardless is shown or not.
+TEST_F(DisplayTest, DrawOcclusionWithSkipRect) {
+ SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
+
+ StubDisplayClient client;
+ display_->Initialize(&client, manager_.surface_manager());
+
+ CompositorFrame frame = MakeDefaultCompositorFrame();
+ gfx::Rect more_then_minimum_size(
+ RendererSettings().kMinimumDrawOcclusionSize);
+ more_then_minimum_size.set_width(more_then_minimum_size.width() + 1);
+
+ gfx::Rect minimum_size(RendererSettings().kMinimumDrawOcclusionSize);
+
+ gfx::Rect less_than_minimum_size(
+ RendererSettings().kMinimumDrawOcclusionSize);
+ less_than_minimum_size.set_width(more_then_minimum_size.width() - 1);
+ less_than_minimum_size.set_height(more_then_minimum_size.height() - 1);
+
+ gfx::Rect rect(0, 0, 100, 100);
+
+ bool is_clipped = false;
+ bool are_contents_opaque = true;
+ float opacity = 1.f;
+ SharedQuadState* shared_quad_state =
+ frame.render_pass_list.front()->CreateAndAppendSharedQuadState();
+ auto* quad = frame.render_pass_list.front()
+ ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
+ SharedQuadState* shared_quad_state2 =
+ frame.render_pass_list.front()->CreateAndAppendSharedQuadState();
+ auto* quad2 = frame.render_pass_list.front()
+ ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
+ // A small rect is hiding behind the bigger rect (|rect|), same picture for
+ // the following 3 tests.
+ // rects structure: show on screen:
+ // +----+---+ +--------+
+ // | | | | |
+ // |----+ | | |
+ // | | | |
+ // +--------+ +--------+
+ {
+ shared_quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
+ are_contents_opaque, opacity,
+ SkBlendMode::kSrcOver, 0);
+ shared_quad_state2->SetAll(gfx::Transform(), more_then_minimum_size,
+ more_then_minimum_size, more_then_minimum_size,
+ is_clipped, are_contents_opaque, opacity,
+ SkBlendMode::kSrcOver, 0);
+ quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
+ quad2->SetNew(shared_quad_state2, more_then_minimum_size,
+ more_then_minimum_size, SK_ColorBLACK, false);
+
+ EXPECT_EQ(2u, frame.render_pass_list.front()->quad_list.size());
+ display_->RemoveOverdrawQuads(&frame);
+
+ // |more_then_minimum_size| rect is not shown on screen. Since its size is
+ // slightly larger than the skip_rect size, draw occlusion is applied on
+ // |more_then_minimum_size| and it's removed from the compositor frame.
+ EXPECT_EQ(1u, frame.render_pass_list.front()->quad_list.size());
+ EXPECT_EQ(rect.ToString(), frame.render_pass_list.front()
+ ->quad_list.ElementAt(0)
+ ->visible_rect.ToString());
+ }
+
+ {
+ shared_quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
+ are_contents_opaque, opacity,
+ SkBlendMode::kSrcOver, 0);
+ shared_quad_state2->SetAll(gfx::Transform(), minimum_size, minimum_size,
+ minimum_size, is_clipped, are_contents_opaque,
+ opacity, SkBlendMode::kSrcOver, 0);
+ quad2 = frame.render_pass_list.front()
+ ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
+ quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
+ quad2->SetNew(shared_quad_state2, minimum_size, minimum_size, SK_ColorBLACK,
+ false);
+
+ EXPECT_EQ(2u, frame.render_pass_list.front()->quad_list.size());
+ display_->RemoveOverdrawQuads(&frame);
+
+ // |minimum_size| rect is not shown on screen. Since its size is the same
+ // as skip_rect size, draw occlusion is not applied on this rect. So it is
+ // not removed from compositor frame.
+ EXPECT_EQ(2u, frame.render_pass_list.front()->quad_list.size());
+ EXPECT_EQ(rect.ToString(), frame.render_pass_list.front()
+ ->quad_list.ElementAt(0)
+ ->visible_rect.ToString());
+ EXPECT_EQ(minimum_size.ToString(), frame.render_pass_list.front()
+ ->quad_list.ElementAt(1)
+ ->visible_rect.ToString());
+ }
+
+ {
+ shared_quad_state->SetAll(gfx::Transform(), rect, rect, rect, is_clipped,
+ are_contents_opaque, opacity,
+ SkBlendMode::kSrcOver, 0);
+ shared_quad_state2->SetAll(gfx::Transform(), less_than_minimum_size,
+ less_than_minimum_size, less_than_minimum_size,
+ is_clipped, are_contents_opaque, opacity,
+ SkBlendMode::kSrcOver, 0);
+ quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
+ quad2->SetNew(shared_quad_state2, less_than_minimum_size,
+ less_than_minimum_size, SK_ColorBLACK, false);
+
+ EXPECT_EQ(2u, frame.render_pass_list.front()->quad_list.size());
+ display_->RemoveOverdrawQuads(&frame);
+
+ // |less_than_minimum_size| rect is not shown on screen. Since its size is
+ // less than skip_rect size, draw occlusion is not applied on this rect.
+ // So it is not removed from compositor frame.
+ EXPECT_EQ(2u, frame.render_pass_list.front()->quad_list.size());
+ EXPECT_EQ(rect.ToString(), frame.render_pass_list.front()
+ ->quad_list.ElementAt(0)
+ ->visible_rect.ToString());
+ EXPECT_EQ(less_than_minimum_size.ToString(), frame.render_pass_list.front()
+ ->quad_list.ElementAt(1)
+ ->visible_rect.ToString());
+ }
+
+ TearDownDisplay();
+}
+
+// Check if draw occlusion is not applied on DrawQuads that are smaller than
+// skip_rect size, such that DrawQuads that are smaller than the |skip_rect|
+// cannot occlude other quads behind it.
+TEST_F(DisplayTest, OcclusionIgnoringSkipRect) {
+ SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
+
+ StubDisplayClient client;
+ display_->Initialize(&client, manager_.surface_manager());
+
+ CompositorFrame frame = MakeDefaultCompositorFrame();
+ gfx::Rect rect1(0, 0, 50, 50);
+ gfx::Rect rect2(50, 0, 50, 50);
+ gfx::Rect rect3(0, 0, 50, 90);
+
+ bool is_clipped = false;
+ bool are_contents_opaque = true;
+ float opacity = 1.f;
+ SharedQuadState* shared_quad_state =
+ frame.render_pass_list.front()->CreateAndAppendSharedQuadState();
+ auto* quad = frame.render_pass_list.front()
+ ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
+ SharedQuadState* shared_quad_state2 =
+ frame.render_pass_list.front()->CreateAndAppendSharedQuadState();
+ auto* quad2 = frame.render_pass_list.front()
+ ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
+ SharedQuadState* shared_quad_state3 =
+ frame.render_pass_list.front()->CreateAndAppendSharedQuadState();
+ auto* quad3 = frame.render_pass_list.front()
+ ->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
+
+ shared_quad_state->SetAll(gfx::Transform(), rect1, rect1, rect1, is_clipped,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver,
+ 0);
+ shared_quad_state2->SetAll(gfx::Transform(), rect2, rect2, rect2, is_clipped,
+ are_contents_opaque, opacity,
+ SkBlendMode::kSrcOver, 0);
+ shared_quad_state3->SetAll(gfx::Transform(), rect3, rect3, rect3, is_clipped,
+ 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);
+ quad3->SetNew(shared_quad_state3, rect3, rect3, SK_ColorBLACK, false);
+
+ EXPECT_EQ(3u, frame.render_pass_list.front()->quad_list.size());
+ display_->RemoveOverdrawQuads(&frame);
+
+ // |quad3| is not shown on screen because is hiding behind the occlusion rect
+ // formed by |quad1| and |quad2|. Since the |visible_rect| in both |quad1|
+ // and |quad2| are smaller than the skip rect, they cannot be used to occlude
+ // |quad3|. So no draw quad is removed in compositor frame by draw occlusion.
+ EXPECT_EQ(3u, frame.render_pass_list.front()->quad_list.size());
+ EXPECT_EQ(rect1.ToString(), frame.render_pass_list.front()
+ ->quad_list.ElementAt(0)
+ ->visible_rect.ToString());
+ EXPECT_EQ(rect2.ToString(), frame.render_pass_list.front()
+ ->quad_list.ElementAt(1)
+ ->visible_rect.ToString());
+ EXPECT_EQ(rect3.ToString(), frame.render_pass_list.front()
+ ->quad_list.ElementAt(2)
+ ->visible_rect.ToString());
+ TearDownDisplay();
+}
// Check if draw occlusion works well with scale change transformer.
TEST_F(DisplayTest, CompositorFrameWithTransformer) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1310,7 +1501,7 @@ TEST_F(DisplayTest, CompositorFrameWithTransformer) {
// Check if draw occlusion works with transform at epsilon scale.
TEST_F(DisplayTest, CompositorFrameWithEpsilonScaleTransform) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1422,7 +1613,7 @@ TEST_F(DisplayTest, CompositorFrameWithEpsilonScaleTransform) {
// Check if draw occlusion works with transform at negative scale.
TEST_F(DisplayTest, CompositorFrameWithNegativeScaleTransform) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1545,7 +1736,9 @@ TEST_F(DisplayTest, CompositorFrameWithNegativeScaleTransform) {
// | | rotation (by 45 on y-axis) -> | | same height
// +-----+ +----+ reduced weight
TEST_F(DisplayTest, CompositorFrameWithRotation) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1672,7 +1865,9 @@ TEST_F(DisplayTest, CompositorFrameWithRotation) {
// Check if draw occlusion is handled correctly if the transform does not
// preserves 2d axis alignment.
TEST_F(DisplayTest, CompositorFrameWithPerspective) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1746,7 +1941,9 @@ TEST_F(DisplayTest, CompositorFrameWithPerspective) {
// Check if draw occlusion works with transparent DrawQuads.
TEST_F(DisplayTest, CompositorFrameWithOpacityChange) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1811,7 +2008,9 @@ TEST_F(DisplayTest, CompositorFrameWithOpacityChange) {
}
TEST_F(DisplayTest, CompositorFrameWithOpaquenessChange) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1876,7 +2075,9 @@ TEST_F(DisplayTest, CompositorFrameWithOpaquenessChange) {
}
TEST_F(DisplayTest, CompositorFrameWithTranslateTransformer) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1995,7 +2196,9 @@ TEST_F(DisplayTest, CompositorFrameWithTranslateTransformer) {
}
TEST_F(DisplayTest, CompositorFrameWithCombinedSharedQuadState) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2121,7 +2324,9 @@ TEST_F(DisplayTest, CompositorFrameWithCombinedSharedQuadState) {
}
TEST_F(DisplayTest, CompositorFrameWithMultipleRenderPass) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2195,7 +2400,7 @@ TEST_F(DisplayTest, CompositorFrameWithMultipleRenderPass) {
}
TEST_F(DisplayTest, CompositorFrameWithCoveredRenderPass) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2263,7 +2468,9 @@ TEST_F(DisplayTest, CompositorFrameWithCoveredRenderPass) {
}
TEST_F(DisplayTest, CompositorFrameWithClip) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2378,7 +2585,9 @@ TEST_F(DisplayTest, CompositorFrameWithClip) {
// Check if draw occlusion works with copy requests in root RenderPass only.
TEST_F(DisplayTest, CompositorFrameWithCopyRequest) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2424,7 +2633,9 @@ TEST_F(DisplayTest, CompositorFrameWithCopyRequest) {
}
TEST_F(DisplayTest, CompositorFrameWithRenderPass) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2602,7 +2813,9 @@ TEST_F(DisplayTest, CompositorFrameWithRenderPass) {
}
TEST_F(DisplayTest, CompositorFrameWithMultipleDrawQuadInSharedQuadState) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2777,7 +2990,9 @@ TEST_F(DisplayTest, CompositorFrameWithMultipleDrawQuadInSharedQuadState) {
}
TEST_F(DisplayTest, CompositorFrameWithNonInvertibleTransform) {
- SetUpDisplay(RendererSettings(), cc::TestWebGraphicsContext3D::Create());
+ RendererSettings settings;
+ settings.kMinimumDrawOcclusionSize.set_width(0);
+ SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2985,7 +3200,6 @@ TEST_F(DisplayTest, CompositorFrameWithPresentationToken) {
RunAllPendingInMessageLoop();
}
- sub_support->EvictCurrentSurface();
TearDownDisplay();
}
diff --git a/chromium/components/viz/service/display/gl_renderer.cc b/chromium/components/viz/service/display/gl_renderer.cc
index 345f72d6684..3db30fc6c5e 100644
--- a/chromium/components/viz/service/display/gl_renderer.cc
+++ b/chromium/components/viz/service/display/gl_renderer.cc
@@ -27,7 +27,6 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
-#include "cc/base/container_util.h"
#include "cc/base/math_util.h"
#include "cc/debug/debug_colors.h"
#include "cc/paint/render_surface_filters.h"
@@ -175,10 +174,6 @@ BlendMode BlendModeFromSkXfermode(SkBlendMode mode) {
// Smallest unit that impact anti-aliasing output. We use this to
// determine when anti-aliasing is unnecessary.
const float kAntiAliasingEpsilon = 1.0f / 1024.0f;
-
-// Block or crash if the number of pending sync queries reach this high as
-// something is seriously wrong on the service side if this happens.
-const size_t kMaxPendingSyncQueries = 16;
} // anonymous namespace
// Parameters needed to draw a RenderPassDrawQuad.
@@ -308,97 +303,6 @@ class GLRenderer::ScopedUseGrContext {
DISALLOW_COPY_AND_ASSIGN(ScopedUseGrContext);
};
-class GLRenderer::SyncQuery {
- public:
- explicit SyncQuery(gpu::gles2::GLES2Interface* gl)
- : gl_(gl), query_id_(0u), is_pending_(false), weak_ptr_factory_(this) {
- gl_->GenQueriesEXT(1, &query_id_);
- }
- virtual ~SyncQuery() { gl_->DeleteQueriesEXT(1, &query_id_); }
-
- scoped_refptr<ResourceFence> Begin() {
- DCHECK(!IsPending());
- // Invalidate weak pointer held by old fence.
- weak_ptr_factory_.InvalidateWeakPtrs();
- // Note: In case the set of drawing commands issued before End() do not
- // depend on the query, defer BeginQueryEXT call until Set() is called and
- // query is required.
- return base::MakeRefCounted<Fence>(weak_ptr_factory_.GetWeakPtr());
- }
-
- void Set() {
- if (is_pending_)
- return;
-
- // Note: BeginQueryEXT on GL_COMMANDS_COMPLETED_CHROMIUM is effectively a
- // noop relative to GL, so it doesn't matter where it happens but we still
- // make sure to issue this command when Set() is called (prior to issuing
- // any drawing commands that depend on query), in case some future extension
- // can take advantage of this.
- gl_->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query_id_);
- is_pending_ = true;
- }
-
- void End() {
- if (!is_pending_)
- return;
-
- gl_->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
- }
-
- bool IsPending() {
- if (!is_pending_)
- return false;
-
- unsigned result_available = 1;
- gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_AVAILABLE_EXT,
- &result_available);
- is_pending_ = !result_available;
- return is_pending_;
- }
-
- void Wait() {
- if (!is_pending_)
- return;
-
- unsigned result = 0;
- gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &result);
- is_pending_ = false;
- }
-
- private:
- class Fence : public ResourceFence {
- public:
- explicit Fence(base::WeakPtr<GLRenderer::SyncQuery> query)
- : query_(query) {}
-
- // ResourceFence implementation.
- void Set() override {
- DCHECK(query_);
- query_->Set();
- }
- bool HasPassed() override { return !query_ || !query_->IsPending(); }
- void Wait() override {
- if (query_)
- query_->Wait();
- }
-
- private:
- ~Fence() override {}
-
- base::WeakPtr<SyncQuery> query_;
-
- DISALLOW_COPY_AND_ASSIGN(Fence);
- };
-
- gpu::gles2::GLES2Interface* gl_;
- unsigned query_id_;
- bool is_pending_;
- base::WeakPtrFactory<SyncQuery> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(SyncQuery);
-};
-
GLRenderer::GLRenderer(
const RendererSettings* settings,
OutputSurface* output_surface,
@@ -413,6 +317,7 @@ GLRenderer::GLRenderer(
&texture_deleter_,
base::BindRepeating(&GLRenderer::MoveFromDrawToWindowSpace,
base::Unretained(this))),
+ sync_queries_(gl_),
bound_geometry_(NO_BINDING),
color_lut_cache_(gl_,
output_surface_->context_provider()
@@ -543,27 +448,7 @@ void GLRenderer::BeginDrawingFrame() {
scoped_refptr<ResourceFence> read_lock_fence;
if (use_sync_query_) {
- // Block until oldest sync query has passed if the number of pending queries
- // ever reach kMaxPendingSyncQueries.
- if (pending_sync_queries_.size() >= kMaxPendingSyncQueries) {
- LOG(ERROR) << "Reached limit of pending sync queries.";
-
- pending_sync_queries_.front()->Wait();
- DCHECK(!pending_sync_queries_.front()->IsPending());
- }
-
- while (!pending_sync_queries_.empty()) {
- if (pending_sync_queries_.front()->IsPending())
- break;
-
- available_sync_queries_.push_back(cc::PopFront(&pending_sync_queries_));
- }
-
- current_sync_query_ = available_sync_queries_.empty()
- ? std::make_unique<SyncQuery>(gl_)
- : cc::PopFront(&available_sync_queries_);
-
- read_lock_fence = current_sync_query_->Begin();
+ read_lock_fence = sync_queries_.StartNewFrame();
} else {
read_lock_fence =
base::MakeRefCounted<cc::DisplayResourceProvider::SynchronousFence>(
@@ -665,13 +550,20 @@ static sk_sp<SkImage> WrapTexture(uint32_t texture_id,
GrGLTextureInfo texture_info;
texture_info.fTarget = target;
texture_info.fID = texture_id;
+ if (kN32_SkColorType == kRGBA_8888_SkColorType) {
+ texture_info.fFormat = GL_RGBA8_OES;
+ } else {
+ DCHECK(kN32_SkColorType == kBGRA_8888_SkColorType);
+ texture_info.fFormat = GL_BGRA8_EXT;
+ }
GrBackendTexture backend_texture(size.width(), size.height(),
- kSkia8888_GrPixelConfig, texture_info);
+ GrMipMapped::kNo, texture_info);
GrSurfaceOrigin origin =
flip_texture ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
return SkImage::MakeFromTexture(context, backend_texture, origin,
- kPremul_SkAlphaType, nullptr);
+ kN32_SkColorType, kPremul_SkAlphaType,
+ nullptr);
}
static sk_sp<SkImage> ApplyImageFilter(
@@ -726,6 +618,12 @@ static sk_sp<SkImage> ApplyImageFilter(
return image;
}
+static gfx::RectF CenteredRect(const gfx::Rect& tile_rect) {
+ return gfx::RectF(
+ gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()),
+ gfx::SizeF(tile_rect.size()));
+}
+
bool GLRenderer::CanApplyBlendModeUsingBlendFunc(SkBlendMode blend_mode) {
return use_blend_equation_advanced_ || blend_mode == SkBlendMode::kSrcOver ||
blend_mode == SkBlendMode::kDstIn ||
@@ -1384,7 +1282,7 @@ void GLRenderer::UpdateRPDQTexturesForSampling(
// |params->filter_image| was populated.
params->source_needs_flip = kBottomLeft_GrSurfaceOrigin == origin;
} else if (params->contents_texture) {
- gl_->BindTexture(GL_TEXTURE_2D, params->contents_texture->id());
+ params->contents_texture->BindForSampling();
params->contents_and_bypass_color_space =
params->contents_texture->color_space();
params->source_needs_flip = params->flip_texture;
@@ -1919,22 +1817,7 @@ void GLRenderer::DrawSolidColorQuad(const SolidColorDrawQuad* quad,
// Antialising requires a normalized quad, but this could lead to floating
// point precision errors, so only normalize when antialising is on.
if (use_aa) {
- // Normalize to tile_rect.
- local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height());
-
- SetShaderQuadF(local_quad);
-
- // The transform and vertex data are used to figure out the extents that the
- // un-antialiased quad should have and which vertex this is and the float
- // quad passed in via uniform is the actual geometry that gets used to draw
- // it. This is why this centered rect is used and not the original
- // quad_rect.
- gfx::RectF centered_rect(
- gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()),
- gfx::SizeF(tile_rect.size()));
- DrawQuadGeometry(current_frame()->projection_matrix,
- quad->shared_quad_state->quad_to_target_transform,
- centered_rect);
+ DrawQuadGeometryWithAA(quad, &local_quad, tile_rect);
} else {
PrepareGeometry(SHARED_BINDING);
SetShaderQuadF(local_quad);
@@ -2081,23 +1964,10 @@ void GLRenderer::DrawContentQuadAA(const ContentDrawQuadBase* quad,
// Blending is required for antialiasing.
SetBlendEnabled(true);
-
- // Normalize to tile_rect.
- local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height());
-
SetShaderOpacity(quad);
- SetShaderQuadF(local_quad);
- // The transform and vertex data are used to figure out the extents that the
- // un-antialiased quad should have and which vertex this is and the float
- // quad passed in via uniform is the actual geometry that gets used to draw
- // it. This is why this centered rect is used and not the original quad_rect.
- gfx::RectF centered_rect(
- gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()),
- gfx::SizeF(tile_rect.size()));
- DrawQuadGeometry(current_frame()->projection_matrix,
- quad->shared_quad_state->quad_to_target_transform,
- centered_rect);
+ // Draw the quad with antialiasing.
+ DrawQuadGeometryWithAA(quad, &local_quad, tile_rect);
}
void GLRenderer::DrawContentQuadNoAA(const ContentDrawQuadBase* quad,
@@ -2638,9 +2508,7 @@ void GLRenderer::EnqueueTextureQuad(const TextureDrawQuad* quad,
void GLRenderer::FinishDrawingFrame() {
if (use_sync_query_) {
- DCHECK(current_sync_query_);
- current_sync_query_->End();
- pending_sync_queries_.push_back(std::move(current_sync_query_));
+ sync_queries_.EndCurrentFrame();
}
swap_buffer_rect_.Union(current_frame()->root_damage_rect);
@@ -2671,6 +2539,7 @@ void GLRenderer::FinishDrawingQuadList() {
void GLRenderer::GenerateMipmap() {
DCHECK(current_framebuffer_texture_);
+ current_framebuffer_texture_->set_generate_mipmap();
}
void GLRenderer::SetEnableDCLayers(bool enable) {
@@ -2828,6 +2697,24 @@ void GLRenderer::DrawQuadGeometry(const gfx::Transform& projection_matrix,
num_triangles_drawn_ += 2;
}
+void GLRenderer::DrawQuadGeometryWithAA(const DrawQuad* quad,
+ gfx::QuadF* local_quad,
+ const gfx::Rect& tile_rect) {
+ DCHECK(local_quad);
+ // Normalize to tile_rect.
+ local_quad->Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height());
+
+ SetShaderQuadF(*local_quad);
+
+ // The transform and vertex data are used to figure out the extents that the
+ // un-antialiased quad should have and which vertex this is and the float
+ // quad passed in via uniform is the actual geometry that gets used to draw
+ // it. This is why this centered rect is used and not the original quad_rect.
+ DrawQuadGeometry(current_frame()->projection_matrix,
+ quad->shared_quad_state->quad_to_target_transform,
+ CenteredRect(tile_rect));
+}
+
void GLRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) {
DCHECK(visible_);
@@ -3498,7 +3385,8 @@ void GLRenderer::CopyRenderPassDrawQuadToOverlayResource(
(*overlay_texture)->texture.target(),
(*overlay_texture)->texture.id(), 0);
DCHECK(gl_->CheckFramebufferStatus(GL_FRAMEBUFFER) ==
- GL_FRAMEBUFFER_COMPLETE);
+ GL_FRAMEBUFFER_COMPLETE ||
+ IsContextLost());
// Clear to 0 to ensure the background is transparent.
gl_->ClearColor(0, 0, 0, 0);
@@ -3806,7 +3694,7 @@ bool GLRenderer::IsRenderPassResourceAllocated(
return texture_it != render_pass_textures_.end();
}
-gfx::Size GLRenderer::GetRenderPassTextureSize(
+gfx::Size GLRenderer::GetRenderPassBackingPixelSize(
const RenderPassId& render_pass_id) {
auto texture_it = render_pass_textures_.find(render_pass_id);
DCHECK(texture_it != render_pass_textures_.end());
diff --git a/chromium/components/viz/service/display/gl_renderer.h b/chromium/components/viz/service/display/gl_renderer.h
index b3ddb34b6cd..d0e4761d39d 100644
--- a/chromium/components/viz/service/display/gl_renderer.h
+++ b/chromium/components/viz/service/display/gl_renderer.h
@@ -23,6 +23,7 @@
#include "components/viz/service/display/gl_renderer_draw_cache.h"
#include "components/viz/service/display/program_binding.h"
#include "components/viz/service/display/scoped_gpu_memory_buffer_texture.h"
+#include "components/viz/service/display/sync_query_collection.h"
#include "components/viz/service/display/texture_deleter.h"
#include "components/viz/service/viz_service_export.h"
#include "ui/gfx/geometry/quad_f.h"
@@ -104,7 +105,7 @@ class VIZ_SERVICE_EXPORT GLRenderer : public DirectRenderer {
const RenderPassRequirements& requirements) override;
bool IsRenderPassResourceAllocated(
const RenderPassId& render_pass_id) const override;
- gfx::Size GetRenderPassTextureSize(
+ gfx::Size GetRenderPassBackingPixelSize(
const RenderPassId& render_pass_id) override;
void BindFramebufferToOutputSurface() override;
void BindFramebufferToTexture(const RenderPassId render_pass_id) override;
@@ -254,6 +255,9 @@ class VIZ_SERVICE_EXPORT GLRenderer : public DirectRenderer {
void DrawQuadGeometry(const gfx::Transform& projection_matrix,
const gfx::Transform& draw_transform,
const gfx::RectF& quad_rect);
+ void DrawQuadGeometryWithAA(const DrawQuad* quad,
+ gfx::QuadF* local_quad,
+ const gfx::Rect& tile_rect);
// If |dst_color_space| is invalid, then no color conversion (apart from
// YUV to RGB conversion) is performed. This explicit argument is available
@@ -374,10 +378,7 @@ class VIZ_SERVICE_EXPORT GLRenderer : public DirectRenderer {
ScopedRenderPassTexture* current_framebuffer_texture_;
- class SyncQuery;
- base::circular_deque<std::unique_ptr<SyncQuery>> pending_sync_queries_;
- base::circular_deque<std::unique_ptr<SyncQuery>> available_sync_queries_;
- std::unique_ptr<SyncQuery> current_sync_query_;
+ SyncQueryCollection sync_queries_;
bool use_discard_framebuffer_ = false;
bool use_sync_query_ = false;
bool use_blend_equation_advanced_ = false;
diff --git a/chromium/components/viz/service/display/gl_renderer_copier.cc b/chromium/components/viz/service/display/gl_renderer_copier.cc
index 4c95b9c6eda..478b2cb9950 100644
--- a/chromium/components/viz/service/display/gl_renderer_copier.cc
+++ b/chromium/components/viz/service/display/gl_renderer_copier.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include <cstring>
+#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -426,7 +427,7 @@ void GLRendererCopier::StartReadbackFromFramebuffer(
GetOptimalReadbackFormat());
const GLuint query = workflow->query();
context_provider_->ContextSupport()->SignalQuery(
- query, base::Bind(&ReadPixelsWorkflow::Finish, base::Passed(&workflow)));
+ query, base::BindOnce(&ReadPixelsWorkflow::Finish, std::move(workflow)));
}
void GLRendererCopier::SendTextureResult(
@@ -462,8 +463,7 @@ void GLRendererCopier::SendTextureResult(
gl->DeleteTextures(1, &result_texture);
// TODO(crbug/754872): This non-null release callback wart is going away
// soon, as copy requestors won't need pool/manage textures anymore.
- release_callback = SingleReleaseCallback::Create(
- base::Bind([](const gpu::SyncToken&, bool) {}));
+ release_callback = SingleReleaseCallback::Create(base::DoNothing());
} else {
// Note: There's no need to try to pool/re-use the result texture from here,
// since only clients that are trying to re-invent video capture would see
@@ -914,9 +914,23 @@ GLRendererCopier::CacheEntry::CacheEntry() {
object_names.fill(0);
}
-GLRendererCopier::CacheEntry::CacheEntry(CacheEntry&&) = default;
+GLRendererCopier::CacheEntry::CacheEntry(CacheEntry&& other)
+ : purge_count_at_last_use(other.purge_count_at_last_use),
+ object_names(other.object_names),
+ scaler(std::move(other.scaler)),
+ i420_converter(std::move(other.i420_converter)) {
+ other.object_names.fill(0);
+}
+
GLRendererCopier::CacheEntry& GLRendererCopier::CacheEntry::operator=(
- CacheEntry&&) = default;
+ CacheEntry&& other) {
+ purge_count_at_last_use = other.purge_count_at_last_use;
+ object_names = other.object_names;
+ other.object_names.fill(0);
+ scaler = std::move(other.scaler);
+ i420_converter = std::move(other.i420_converter);
+ return *this;
+}
GLRendererCopier::CacheEntry::~CacheEntry() {
// Ensure all resources were freed by this point. Resources aren't explicity
diff --git a/chromium/components/viz/service/display/gl_renderer_copier_unittest.cc b/chromium/components/viz/service/display/gl_renderer_copier_unittest.cc
index 0522bc1221a..18bbea050d3 100644
--- a/chromium/components/viz/service/display/gl_renderer_copier_unittest.cc
+++ b/chromium/components/viz/service/display/gl_renderer_copier_unittest.cc
@@ -10,9 +10,9 @@
#include <memory>
#include "base/bind.h"
-#include "cc/test/test_context_provider.h"
-#include "cc/test/test_gles2_interface.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
+#include "components/viz/test/test_context_provider.h"
+#include "components/viz/test/test_gles2_interface.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/vector2d.h"
@@ -21,7 +21,7 @@ namespace viz {
namespace {
-class CopierTestGLES2Interface : public cc::TestGLES2Interface {
+class CopierTestGLES2Interface : public TestGLES2Interface {
public:
// Sets how GL will respond to queries regarding the implementation's internal
// read-back format.
@@ -44,7 +44,7 @@ class CopierTestGLES2Interface : public cc::TestGLES2Interface {
params[0] = type_;
break;
default:
- cc::TestGLES2Interface::GetIntegerv(pname, params);
+ TestGLES2Interface::GetIntegerv(pname, params);
break;
}
}
@@ -59,7 +59,7 @@ class CopierTestGLES2Interface : public cc::TestGLES2Interface {
class GLRendererCopierTest : public testing::Test {
public:
void SetUp() override {
- auto context_provider = cc::TestContextProvider::Create(
+ auto context_provider = TestContextProvider::Create(
std::make_unique<CopierTestGLES2Interface>());
context_provider->BindToCurrentThread();
copier_ = std::make_unique<GLRendererCopier>(
diff --git a/chromium/components/viz/service/display/gl_renderer_unittest.cc b/chromium/components/viz/service/display/gl_renderer_unittest.cc
index 49c429e61c6..5fee46e9a51 100644
--- a/chromium/components/viz/service/display/gl_renderer_unittest.cc
+++ b/chromium/components/viz/service/display/gl_renderer_unittest.cc
@@ -18,15 +18,11 @@
#include "cc/resources/resource_provider.h"
#include "cc/test/fake_impl_task_runner_provider.h"
#include "cc/test/fake_layer_tree_host_impl.h"
-#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_resource_provider.h"
#include "cc/test/pixel_test.h"
#include "cc/test/render_pass_test_utils.h"
#include "cc/test/resource_provider_test_utils.h"
-#include "cc/test/test_gles2_interface.h"
-#include "cc/test/test_shared_bitmap_manager.h"
-#include "cc/test/test_web_graphics_context_3d.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
@@ -34,6 +30,10 @@
#include "components/viz/common/resources/transferable_resource.h"
#include "components/viz/service/display/overlay_strategy_single_on_top.h"
#include "components/viz/service/display/overlay_strategy_underlay.h"
+#include "components/viz/test/fake_output_surface.h"
+#include "components/viz/test/test_gles2_interface.h"
+#include "components/viz/test/test_shared_bitmap_manager.h"
+#include "components/viz/test/test_web_graphics_context_3d.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/context_support.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -471,10 +471,10 @@ class FakeRendererGL : public GLRenderer {
class GLRendererWithDefaultHarnessTest : public GLRendererTest {
protected:
GLRendererWithDefaultHarnessTest() {
- output_surface_ = cc::FakeOutputSurface::Create3d();
+ output_surface_ = FakeOutputSurface::Create3d();
output_surface_->BindToClient(&output_surface_client_);
- shared_bitmap_manager_.reset(new cc::TestSharedBitmapManager());
+ shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
resource_provider_ =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface_->context_provider(), shared_bitmap_manager_.get());
@@ -488,7 +488,7 @@ class GLRendererWithDefaultHarnessTest : public GLRendererTest {
RendererSettings settings_;
cc::FakeOutputSurfaceClient output_surface_client_;
- std::unique_ptr<cc::FakeOutputSurface> output_surface_;
+ std::unique_ptr<FakeOutputSurface> output_surface_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
std::unique_ptr<FakeRendererGL> renderer_;
@@ -502,10 +502,10 @@ class GLRendererWithDefaultHarnessTest : public GLRendererTest {
class GLRendererShaderTest : public GLRendererTest {
protected:
GLRendererShaderTest() {
- output_surface_ = cc::FakeOutputSurface::Create3d();
+ output_surface_ = FakeOutputSurface::Create3d();
output_surface_->BindToClient(&output_surface_client_);
- shared_bitmap_manager_.reset(new cc::TestSharedBitmapManager());
+ shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
resource_provider_ =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface_->context_provider(), shared_bitmap_manager_.get());
@@ -514,7 +514,7 @@ class GLRendererShaderTest : public GLRendererTest {
renderer_->Initialize();
renderer_->SetVisible(true);
- child_context_provider_ = cc::TestContextProvider::Create();
+ child_context_provider_ = TestContextProvider::Create();
child_context_provider_->BindToCurrentThread();
child_resource_provider_ =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
@@ -606,10 +606,10 @@ class GLRendererShaderTest : public GLRendererTest {
RendererSettings settings_;
cc::FakeOutputSurfaceClient output_surface_client_;
- std::unique_ptr<cc::FakeOutputSurface> output_surface_;
+ std::unique_ptr<FakeOutputSurface> output_surface_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
- scoped_refptr<cc::TestContextProvider> child_context_provider_;
+ scoped_refptr<TestContextProvider> child_context_provider_;
std::unique_ptr<cc::LayerTreeResourceProvider> child_resource_provider_;
std::unique_ptr<FakeRendererGL> renderer_;
};
@@ -631,7 +631,7 @@ TEST_F(GLRendererWithDefaultHarnessTest, ExternalStencil) {
EXPECT_TRUE(renderer_->stencil_enabled());
}
-class ForbidSynchronousCallContext : public cc::TestWebGraphicsContext3D {
+class ForbidSynchronousCallContext : public TestWebGraphicsContext3D {
public:
ForbidSynchronousCallContext() {}
@@ -730,16 +730,16 @@ class ForbidSynchronousCallContext : public cc::TestWebGraphicsContext3D {
};
TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) {
auto context = std::make_unique<ForbidSynchronousCallContext>();
- auto provider = cc::TestContextProvider::Create(std::move(context));
+ auto provider = TestContextProvider::Create(std::move(context));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
std::unique_ptr<OutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d(std::move(provider)));
+ FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -749,7 +749,7 @@ TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) {
resource_provider.get());
}
-class LoseContextOnFirstGetContext : public cc::TestWebGraphicsContext3D {
+class LoseContextOnFirstGetContext : public TestWebGraphicsContext3D {
public:
LoseContextOnFirstGetContext() {}
@@ -766,16 +766,16 @@ class LoseContextOnFirstGetContext : public cc::TestWebGraphicsContext3D {
TEST_F(GLRendererTest, InitializationWithQuicklyLostContextDoesNotAssert) {
auto context = std::make_unique<LoseContextOnFirstGetContext>();
- auto provider = cc::TestContextProvider::Create(std::move(context));
+ auto provider = TestContextProvider::Create(std::move(context));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
std::unique_ptr<OutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d(std::move(provider)));
+ FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -785,7 +785,7 @@ TEST_F(GLRendererTest, InitializationWithQuicklyLostContextDoesNotAssert) {
resource_provider.get());
}
-class ClearCountingContext : public cc::TestWebGraphicsContext3D {
+class ClearCountingContext : public TestWebGraphicsContext3D {
public:
ClearCountingContext() { test_capabilities_.discard_framebuffer = true; }
@@ -800,16 +800,16 @@ TEST_F(GLRendererTest, OpaqueBackground) {
std::unique_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
ClearCountingContext* context = context_owned.get();
- auto provider = cc::TestContextProvider::Create(std::move(context_owned));
+ auto provider = TestContextProvider::Create(std::move(context_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
std::unique_ptr<OutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d(std::move(provider)));
+ FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -844,16 +844,16 @@ TEST_F(GLRendererTest, TransparentBackground) {
std::unique_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
ClearCountingContext* context = context_owned.get();
- auto provider = cc::TestContextProvider::Create(std::move(context_owned));
+ auto provider = TestContextProvider::Create(std::move(context_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
std::unique_ptr<OutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d(std::move(provider)));
+ FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -881,16 +881,16 @@ TEST_F(GLRendererTest, OffscreenOutputSurface) {
std::unique_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
ClearCountingContext* context = context_owned.get();
- auto provider = cc::TestContextProvider::Create(std::move(context_owned));
+ auto provider = TestContextProvider::Create(std::move(context_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
std::unique_ptr<OutputSurface> output_surface(
- cc::FakeOutputSurface::CreateOffscreen(std::move(provider)));
+ FakeOutputSurface::CreateOffscreen(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -913,7 +913,7 @@ TEST_F(GLRendererTest, OffscreenOutputSurface) {
Mock::VerifyAndClearExpectations(context);
}
-class TextureStateTrackingContext : public cc::TestWebGraphicsContext3D {
+class TextureStateTrackingContext : public TestWebGraphicsContext3D {
public:
TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM) {
test_capabilities_.egl_image_external = true;
@@ -940,16 +940,16 @@ TEST_F(GLRendererTest, ActiveTextureState) {
new TextureStateTrackingContext);
TextureStateTrackingContext* context = context_owned.get();
- auto provider = cc::TestContextProvider::Create(std::move(context_owned));
+ auto provider = TestContextProvider::Create(std::move(context_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
std::unique_ptr<OutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d(std::move(provider)));
+ FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -967,7 +967,7 @@ TEST_F(GLRendererTest, ActiveTextureState) {
new TextureStateTrackingContext);
auto child_context_provider =
- cc::TestContextProvider::Create(std::move(child_context_owned));
+ TestContextProvider::Create(std::move(child_context_owned));
child_context_provider->BindToCurrentThread();
auto child_resource_provider =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
@@ -1022,7 +1022,7 @@ TEST_F(GLRendererTest, ActiveTextureState) {
Mock::VerifyAndClearExpectations(context);
}
-class NoClearRootRenderPassMockContext : public cc::TestWebGraphicsContext3D {
+class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D {
public:
MOCK_METHOD1(clear, void(GLbitfield mask));
MOCK_METHOD4(drawElements,
@@ -1034,17 +1034,16 @@ TEST_F(GLRendererTest, ShouldClearRootRenderPass) {
new NoClearRootRenderPassMockContext);
NoClearRootRenderPassMockContext* mock_context = mock_context_owned.get();
- auto provider =
- cc::TestContextProvider::Create(std::move(mock_context_owned));
+ auto provider = TestContextProvider::Create(std::move(mock_context_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
std::unique_ptr<OutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d(std::move(provider)));
+ FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -1102,7 +1101,7 @@ TEST_F(GLRendererTest, ShouldClearRootRenderPass) {
Mock::VerifyAndClearExpectations(&mock_context);
}
-class ScissorTestOnClearCheckingGLES2Interface : public cc::TestGLES2Interface {
+class ScissorTestOnClearCheckingGLES2Interface : public TestGLES2Interface {
public:
ScissorTestOnClearCheckingGLES2Interface() = default;
@@ -1125,16 +1124,16 @@ class ScissorTestOnClearCheckingGLES2Interface : public cc::TestGLES2Interface {
TEST_F(GLRendererTest, ScissorTestWhenClearing) {
auto gl_owned = std::make_unique<ScissorTestOnClearCheckingGLES2Interface>();
- auto provider = cc::TestContextProvider::Create(std::move(gl_owned));
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
std::unique_ptr<OutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d(std::move(provider)));
+ FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -1175,11 +1174,11 @@ TEST_F(GLRendererTest, ScissorTestWhenClearing) {
DrawFrame(&renderer, viewport_size);
}
-class DiscardCheckingGLES2Interface : public cc::TestGLES2Interface {
+class DiscardCheckingGLES2Interface : public TestGLES2Interface {
public:
DiscardCheckingGLES2Interface() = default;
- void InitializeTestContext(cc::TestWebGraphicsContext3D* context) override {
+ void InitializeTestContext(TestWebGraphicsContext3D* context) override {
context->set_have_post_sub_buffer(true);
context->set_have_discard_framebuffer(true);
}
@@ -1201,15 +1200,15 @@ TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
auto gl_owned = std::make_unique<DiscardCheckingGLES2Interface>();
auto* gl = gl_owned.get();
- auto provider = cc::TestContextProvider::Create(std::move(gl_owned));
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
- auto output_surface = cc::FakeOutputSurface::Create3d(std::move(provider));
+ auto output_surface = FakeOutputSurface::Create3d(std::move(provider));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -1271,7 +1270,7 @@ TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
}
}
-class ResourceTrackingGLES2Interface : public cc::TestGLES2Interface {
+class ResourceTrackingGLES2Interface : public TestGLES2Interface {
public:
ResourceTrackingGLES2Interface() = default;
~ResourceTrackingGLES2Interface() override { CheckNoResources(); }
@@ -1401,15 +1400,15 @@ TEST_F(GLRendererTest, NoResourceLeak) {
auto gl_owned = std::make_unique<ResourceTrackingGLES2Interface>();
auto* gl = gl_owned.get();
- auto provider = cc::TestContextProvider::Create(std::move(gl_owned));
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
- auto output_surface = cc::FakeOutputSurface::Create3d(std::move(provider));
+ auto output_surface = FakeOutputSurface::Create3d(std::move(provider));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -1436,9 +1435,9 @@ TEST_F(GLRendererTest, NoResourceLeak) {
gl->CheckNoResources();
}
-class DrawElementsGLES2Interface : public cc::TestGLES2Interface {
+class DrawElementsGLES2Interface : public TestGLES2Interface {
public:
- void InitializeTestContext(cc::TestWebGraphicsContext3D* context) override {
+ void InitializeTestContext(TestWebGraphicsContext3D* context) override {
context->set_have_post_sub_buffer(true);
}
@@ -1453,13 +1452,13 @@ class GLRendererSkipTest : public GLRendererTest {
auto gl_owned = std::make_unique<StrictMock<DrawElementsGLES2Interface>>();
gl_ = gl_owned.get();
- auto provider = cc::TestContextProvider::Create(std::move(gl_owned));
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
- output_surface_ = cc::FakeOutputSurface::Create3d(std::move(provider));
+ output_surface_ = FakeOutputSurface::Create3d(std::move(provider));
output_surface_->BindToClient(&output_surface_client_);
- shared_bitmap_manager_.reset(new cc::TestSharedBitmapManager());
+ shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
resource_provider_ =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface_->context_provider(), shared_bitmap_manager_.get());
@@ -1473,7 +1472,7 @@ class GLRendererSkipTest : public GLRendererTest {
StrictMock<DrawElementsGLES2Interface>* gl_;
RendererSettings settings_;
cc::FakeOutputSurfaceClient output_surface_client_;
- std::unique_ptr<cc::FakeOutputSurface> output_surface_;
+ std::unique_ptr<FakeOutputSurface> output_surface_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
std::unique_ptr<FakeRendererGL> renderer_;
@@ -1542,12 +1541,12 @@ TEST_F(GLRendererTest, DrawFramePreservesFramebuffer) {
// Note: there is one path that will set it to 0, but that is after the render
// has finished.
cc::FakeOutputSurfaceClient output_surface_client;
- std::unique_ptr<cc::FakeOutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d());
+ std::unique_ptr<FakeOutputSurface> output_surface(
+ FakeOutputSurface::Create3d());
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -1848,7 +1847,7 @@ TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
TestSolidColorProgramAA();
}
-class OutputSurfaceMockContext : public cc::TestWebGraphicsContext3D {
+class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
public:
OutputSurfaceMockContext() { test_capabilities_.post_sub_buffer = true; }
@@ -1899,7 +1898,7 @@ class MockOutputSurfaceTest : public GLRendererTest {
void SetUp() override {
auto context = std::make_unique<StrictMock<OutputSurfaceMockContext>>();
context_ = context.get();
- auto provider = cc::TestContextProvider::Create(std::move(context));
+ auto provider = TestContextProvider::Create(std::move(context));
provider->BindToCurrentThread();
output_surface_ =
std::make_unique<StrictMock<MockOutputSurface>>(std::move(provider));
@@ -1907,7 +1906,7 @@ class MockOutputSurfaceTest : public GLRendererTest {
cc::FakeOutputSurfaceClient output_surface_client_;
output_surface_->BindToClient(&output_surface_client_);
- shared_bitmap_manager_.reset(new cc::TestSharedBitmapManager());
+ shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
resource_provider_ =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface_->context_provider(), shared_bitmap_manager_.get());
@@ -2023,17 +2022,17 @@ static void CollectResources(std::vector<ReturnedResource>* array,
TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
cc::FakeOutputSurfaceClient output_surface_client;
- std::unique_ptr<cc::FakeOutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d());
+ std::unique_ptr<FakeOutputSurface> output_surface(
+ FakeOutputSurface::Create3d());
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
auto parent_resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
- auto child_context_provider = cc::TestContextProvider::Create();
+ auto child_context_provider = TestContextProvider::Create();
child_context_provider->BindToCurrentThread();
auto child_resource_provider =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
@@ -2187,7 +2186,7 @@ class SingleOverlayOnTopProcessor : public OverlayProcessor {
SingleOverlayValidator validator_;
};
-class WaitSyncTokenCountingContext : public cc::TestWebGraphicsContext3D {
+class WaitSyncTokenCountingContext : public TestWebGraphicsContext3D {
public:
MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token));
};
@@ -2207,7 +2206,7 @@ TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) {
new WaitSyncTokenCountingContext);
WaitSyncTokenCountingContext* context = context_owned.get();
- auto provider = cc::TestContextProvider::Create(std::move(context_owned));
+ auto provider = TestContextProvider::Create(std::move(context_owned));
provider->BindToCurrentThread();
MockOverlayScheduler overlay_scheduler;
@@ -2216,16 +2215,16 @@ TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) {
cc::FakeOutputSurfaceClient output_surface_client;
std::unique_ptr<OutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d(std::move(provider)));
+ FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
- new cc::TestSharedBitmapManager());
+ std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
+ std::make_unique<TestSharedBitmapManager>();
auto parent_resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
- auto child_context_provider = cc::TestContextProvider::Create();
+ auto child_context_provider = TestContextProvider::Create();
child_context_provider->BindToCurrentThread();
auto child_resource_provider =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
@@ -2318,7 +2317,7 @@ TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) {
ResourceIdSet());
}
-class OutputColorMatrixMockGLES2Interface : public cc::TestGLES2Interface {
+class OutputColorMatrixMockGLES2Interface : public TestGLES2Interface {
public:
OutputColorMatrixMockGLES2Interface() = default;
@@ -2333,10 +2332,10 @@ TEST_F(GLRendererTest, OutputColorMatrixTest) {
// Initialize the mock GL interface, the output surface and the renderer.
auto gl_owned = std::make_unique<OutputColorMatrixMockGLES2Interface>();
auto* gl = gl_owned.get();
- auto provider = cc::TestContextProvider::Create(std::move(gl_owned));
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
- std::unique_ptr<cc::FakeOutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d(std::move(provider)));
+ std::unique_ptr<FakeOutputSurface> output_surface(
+ FakeOutputSurface::Create3d(std::move(provider)));
cc::FakeOutputSurfaceClient output_surface_client;
output_surface->BindToClient(&output_surface_client);
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
@@ -2400,12 +2399,71 @@ TEST_F(GLRendererTest, OutputColorMatrixTest) {
EXPECT_TRUE(output_color_matrix_invoked);
}
-class PartialSwapMockGLES2Interface : public cc::TestGLES2Interface {
+class GenerateMipmapMockGLESInterface : public TestGLES2Interface {
+ public:
+ GenerateMipmapMockGLESInterface() = default;
+
+ MOCK_METHOD3(TexParameteri, void(GLenum target, GLenum pname, GLint param));
+ MOCK_METHOD1(GenerateMipmap, void(GLenum target));
+};
+
+// TODO(crbug.com/803286): Currently npot texture always return false on ubuntu
+// desktop. The npot texture check is probably failing on desktop GL. This test
+// crashes DCHECK npot texture to catch this. When
+// GLRendererPixelTest.DISABLED_TrilinearFiltering got passed, can remove this.
+TEST_F(GLRendererTest, GenerateMipmap) {
+ // Initialize the mock GL interface, the output surface and the renderer.
+ auto gl_owned = std::make_unique<GenerateMipmapMockGLESInterface>();
+ auto* gl = gl_owned.get();
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
+ provider->BindToCurrentThread();
+ provider->TestContext3d()->set_support_texture_npot(true);
+
+ std::unique_ptr<FakeOutputSurface> output_surface(
+ FakeOutputSurface::Create3d(std::move(provider)));
+ cc::FakeOutputSurfaceClient output_surface_client;
+ output_surface->BindToClient(&output_surface_client);
+ std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ cc::FakeResourceProvider::CreateDisplayResourceProvider(
+ output_surface->context_provider(), nullptr);
+ RendererSettings settings;
+ FakeRendererGL renderer(&settings, output_surface.get(),
+ resource_provider.get());
+ renderer.Initialize();
+ renderer.SetVisible(true);
+
+ gfx::Size viewport_size(100, 100);
+ RenderPassId child_pass_id = 2;
+ // Create a child pass with mipmap to verify that npot texture is enabled.
+ RenderPass* child_pass =
+ cc::AddRenderPass(&render_passes_in_draw_order_, child_pass_id,
+ gfx::Rect(viewport_size) + gfx::Vector2d(1, 2),
+ gfx::Transform(), cc::FilterOperations());
+ child_pass->generate_mipmap = true;
+
+ RenderPassId root_pass_id = 1;
+ RenderPass* root_pass = cc::AddRenderPass(
+ &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size),
+ gfx::Transform(), cc::FilterOperations());
+ root_pass->damage_rect = gfx::Rect(0, 0, 25, 25);
+ cc::AddRenderPassQuad(root_pass, child_pass);
+ renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
+
+ EXPECT_CALL(*gl, TexParameteri(_, _, _)).Times(4);
+ EXPECT_CALL(*gl, GenerateMipmap(GL_TEXTURE_2D)).Times(1);
+ // When generate_mipmap enabled, the GL_TEXTURE_MIN_FILTER should be
+ // GL_LINEAR_MIPMAP_LINEAR.
+ EXPECT_CALL(*gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR));
+ DrawFrame(&renderer, viewport_size);
+}
+
+class PartialSwapMockGLES2Interface : public TestGLES2Interface {
public:
explicit PartialSwapMockGLES2Interface(bool support_dc_layers)
: support_dc_layers_(support_dc_layers) {}
- void InitializeTestContext(cc::TestWebGraphicsContext3D* context) override {
+ void InitializeTestContext(TestWebGraphicsContext3D* context) override {
context->set_have_post_sub_buffer(true);
context->set_enable_dc_layers(support_dc_layers_);
}
@@ -2426,12 +2484,12 @@ class GLRendererPartialSwapTest : public GLRendererTest {
std::make_unique<PartialSwapMockGLES2Interface>(set_draw_rectangle);
auto* gl = gl_owned.get();
- auto provider = cc::TestContextProvider::Create(std::move(gl_owned));
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
- std::unique_ptr<cc::FakeOutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d(std::move(provider)));
+ std::unique_ptr<FakeOutputSurface> output_surface(
+ FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
@@ -2539,19 +2597,19 @@ TEST_F(GLRendererTest, DCLayerOverlaySwitch) {
auto gl_owned = std::make_unique<PartialSwapMockGLES2Interface>(true);
auto* gl = gl_owned.get();
- auto provider = cc::TestContextProvider::Create(std::move(gl_owned));
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
- std::unique_ptr<cc::FakeOutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d(std::move(provider)));
+ std::unique_ptr<FakeOutputSurface> output_surface(
+ FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
auto parent_resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), nullptr);
- auto child_context_provider = cc::TestContextProvider::Create();
+ auto child_context_provider = TestContextProvider::Create();
child_context_provider->BindToCurrentThread();
auto child_resource_provider =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
@@ -2652,7 +2710,7 @@ TEST_F(GLRendererTest, DCLayerOverlaySwitch) {
class GLRendererWithMockContextTest : public ::testing::Test {
protected:
- class MockContextSupport : public cc::TestContextSupport {
+ class MockContextSupport : public TestContextSupport {
public:
MockContextSupport() {}
MOCK_METHOD1(SetAggressivelyFreeResources,
@@ -2662,12 +2720,11 @@ class GLRendererWithMockContextTest : public ::testing::Test {
void SetUp() override {
auto context_support = std::make_unique<MockContextSupport>();
context_support_ptr_ = context_support.get();
- auto context_provider = cc::TestContextProvider::Create(
- cc::TestWebGraphicsContext3D::Create(), std::move(context_support));
+ auto context_provider = TestContextProvider::Create(
+ TestWebGraphicsContext3D::Create(), std::move(context_support));
ASSERT_EQ(context_provider->BindToCurrentThread(),
gpu::ContextResult::kSuccess);
- output_surface_ =
- cc::FakeOutputSurface::Create3d(std::move(context_provider));
+ output_surface_ = FakeOutputSurface::Create3d(std::move(context_provider));
output_surface_->BindToClient(&output_surface_client_);
resource_provider_ =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
@@ -2696,9 +2753,9 @@ TEST_F(GLRendererWithMockContextTest,
Mock::VerifyAndClearExpectations(context_support_ptr_);
}
-class SwapWithBoundsMockGLES2Interface : public cc::TestGLES2Interface {
+class SwapWithBoundsMockGLES2Interface : public TestGLES2Interface {
public:
- void InitializeTestContext(cc::TestWebGraphicsContext3D* context) override {
+ void InitializeTestContext(TestWebGraphicsContext3D* context) override {
context->set_have_swap_buffers_with_bounds(true);
}
};
@@ -2745,12 +2802,12 @@ class GLRendererSwapWithBoundsTest : public GLRendererTest {
void RunTest(const std::vector<gfx::Rect>& content_bounds) {
auto gl_owned = std::make_unique<SwapWithBoundsMockGLES2Interface>();
- auto provider = cc::TestContextProvider::Create(std::move(gl_owned));
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
- std::unique_ptr<cc::FakeOutputSurface> output_surface(
- cc::FakeOutputSurface::Create3d(std::move(provider)));
+ std::unique_ptr<FakeOutputSurface> output_surface(
+ FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
@@ -2809,7 +2866,7 @@ class CALayerValidator : public OverlayCandidateValidator {
void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override {}
};
-class MockCALayerGLES2Interface : public cc::TestGLES2Interface {
+class MockCALayerGLES2Interface : public TestGLES2Interface {
public:
MOCK_METHOD5(ScheduleCALayerSharedStateCHROMIUM,
void(GLfloat opacity,
@@ -2827,7 +2884,7 @@ class MockCALayerGLES2Interface : public cc::TestGLES2Interface {
MOCK_METHOD2(ScheduleCALayerInUseQueryCHROMIUM,
void(GLsizei count, const GLuint* textures));
- void InitializeTestContext(cc::TestWebGraphicsContext3D* context) override {
+ void InitializeTestContext(TestWebGraphicsContext3D* context) override {
// Support image storage for GpuMemoryBuffers, needed for
// CALayers/IOSurfaces backed by textures.
context->set_support_texture_storage_image(true);
@@ -2845,11 +2902,11 @@ class CALayerGLRendererTest : public GLRendererTest {
auto gles2_interface = std::make_unique<MockCALayerGLES2Interface>();
gl_ = gles2_interface.get();
- auto provider = cc::TestContextProvider::Create(std::move(gles2_interface));
+ auto provider = TestContextProvider::Create(std::move(gles2_interface));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
- output_surface_ = cc::FakeOutputSurface::Create3d(std::move(provider));
+ output_surface_ = FakeOutputSurface::Create3d(std::move(provider));
output_surface_->BindToClient(&output_surface_client);
// This validator allows the renderer to make CALayer overlays. If all
@@ -2884,12 +2941,12 @@ class CALayerGLRendererTest : public GLRendererTest {
MockCALayerGLES2Interface& gl() const { return *gl_; }
FakeRendererGL& renderer() const { return *renderer_; }
- cc::FakeOutputSurface& output_surface() const { return *output_surface_; }
+ FakeOutputSurface& output_surface() const { return *output_surface_; }
private:
MockCALayerGLES2Interface* gl_;
CALayerValidator validator_;
- std::unique_ptr<cc::FakeOutputSurface> output_surface_;
+ std::unique_ptr<FakeOutputSurface> output_surface_;
std::unique_ptr<cc::DisplayResourceProvider> display_resource_provider_;
std::unique_ptr<RendererSettings> settings_;
std::unique_ptr<FakeRendererGL> renderer_;
@@ -3695,12 +3752,12 @@ class FramebufferWatchingGLRenderer : public FakeRendererGL {
};
TEST_F(GLRendererTest, UndamagedRenderPassStillDrawnWhenNoPartialSwap) {
- auto provider = cc::TestContextProvider::Create();
+ auto provider = TestContextProvider::Create();
provider->UnboundTestContext3d()->set_have_post_sub_buffer(true);
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
- auto output_surface = cc::FakeOutputSurface::Create3d(std::move(provider));
+ auto output_surface = FakeOutputSurface::Create3d(std::move(provider));
output_surface->BindToClient(&output_surface_client);
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
diff --git a/chromium/components/viz/service/display/overlay_unittest.cc b/chromium/components/viz/service/display/overlay_unittest.cc
index 88f34997dfc..176f2104d6e 100644
--- a/chromium/components/viz/service/display/overlay_unittest.cc
+++ b/chromium/components/viz/service/display/overlay_unittest.cc
@@ -16,9 +16,6 @@
#include "cc/test/fake_resource_provider.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/resource_provider_test_utils.h"
-#include "cc/test/test_context_provider.h"
-#include "cc/test/test_shared_bitmap_manager.h"
-#include "cc/test/test_web_graphics_context_3d.h"
#include "components/viz/common/quads/render_pass.h"
#include "components/viz/common/quads/render_pass_draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
@@ -36,6 +33,9 @@
#include "components/viz/service/display/overlay_strategy_single_on_top.h"
#include "components/viz/service/display/overlay_strategy_underlay.h"
#include "components/viz/service/display/overlay_strategy_underlay_cast.h"
+#include "components/viz/test/test_context_provider.h"
+#include "components/viz/test/test_shared_bitmap_manager.h"
+#include "components/viz/test/test_web_graphics_context_3d.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rect_conversions.h"
@@ -179,7 +179,7 @@ template <typename OverlayCandidateValidatorType>
class OverlayOutputSurface : public OutputSurface {
public:
explicit OverlayOutputSurface(
- scoped_refptr<cc::TestContextProvider> context_provider)
+ scoped_refptr<TestContextProvider> context_provider)
: OutputSurface(std::move(context_provider)) {
is_displayed_as_overlay_plane_ = true;
}
@@ -499,19 +499,19 @@ class OverlayTest : public testing::Test {
protected:
void SetUp() override {
- provider_ = cc::TestContextProvider::Create();
+ provider_ = TestContextProvider::Create();
provider_->BindToCurrentThread();
output_surface_ = std::make_unique<OutputSurfaceType>(provider_);
output_surface_->BindToClient(&client_);
output_surface_->SetOverlayCandidateValidator(
new OverlayCandidateValidatorType);
- shared_bitmap_manager_ = std::make_unique<cc::TestSharedBitmapManager>();
+ shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
resource_provider_ =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
provider_.get(), shared_bitmap_manager_.get());
- child_provider_ = cc::TestContextProvider::Create();
+ child_provider_ = TestContextProvider::Create();
child_provider_->BindToCurrentThread();
child_resource_provider_ =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
@@ -522,12 +522,12 @@ class OverlayTest : public testing::Test {
overlay_processor_->Initialize();
}
- scoped_refptr<cc::TestContextProvider> provider_;
+ scoped_refptr<TestContextProvider> provider_;
std::unique_ptr<OutputSurfaceType> output_surface_;
cc::FakeOutputSurfaceClient client_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
- scoped_refptr<cc::TestContextProvider> child_provider_;
+ scoped_refptr<TestContextProvider> child_provider_;
std::unique_ptr<cc::LayerTreeResourceProvider> child_resource_provider_;
std::unique_ptr<OverlayProcessor> overlay_processor_;
gfx::Rect damage_rect_;
@@ -541,8 +541,7 @@ using UnderlayCastTest = OverlayTest<UnderlayCastOverlayValidator>;
using CALayerOverlayTest = OverlayTest<CALayerValidator>;
TEST(OverlayTest, NoOverlaysByDefault) {
- scoped_refptr<cc::TestContextProvider> provider =
- cc::TestContextProvider::Create();
+ scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
OverlayOutputSurface<OverlayCandidateValidator> output_surface(provider);
EXPECT_EQ(nullptr, output_surface.GetOverlayCandidateValidator());
@@ -551,15 +550,14 @@ TEST(OverlayTest, NoOverlaysByDefault) {
}
TEST(OverlayTest, OverlaysProcessorHasStrategy) {
- scoped_refptr<cc::TestContextProvider> provider =
- cc::TestContextProvider::Create();
+ scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
provider->BindToCurrentThread();
OverlayOutputSurface<OverlayCandidateValidator> output_surface(provider);
cc::FakeOutputSurfaceClient client;
output_surface.BindToClient(&client);
output_surface.SetOverlayCandidateValidator(new SingleOverlayValidator);
- auto shared_bitmap_manager = std::make_unique<cc::TestSharedBitmapManager>();
+ auto shared_bitmap_manager = std::make_unique<TestSharedBitmapManager>();
std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
provider.get(), shared_bitmap_manager.get());
@@ -2401,7 +2399,7 @@ class GLRendererWithOverlaysTest : public testing::Test {
protected:
GLRendererWithOverlaysTest() {
- provider_ = cc::TestContextProvider::Create();
+ provider_ = TestContextProvider::Create();
provider_->BindToCurrentThread();
output_surface_ = std::make_unique<OutputSurfaceType>(provider_);
output_surface_->BindToClient(&output_surface_client_);
@@ -2412,7 +2410,7 @@ class GLRendererWithOverlaysTest : public testing::Test {
provider_->support()->SetScheduleOverlayPlaneCallback(base::Bind(
&MockOverlayScheduler::Schedule, base::Unretained(&scheduler_)));
- child_provider_ = cc::TestContextProvider::Create();
+ child_provider_ = TestContextProvider::Create();
child_provider_->BindToCurrentThread();
child_resource_provider_ =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
@@ -2456,8 +2454,8 @@ class GLRendererWithOverlaysTest : public testing::Test {
std::unique_ptr<OutputSurfaceType> output_surface_;
std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
std::unique_ptr<OverlayInfoRendererGL> renderer_;
- scoped_refptr<cc::TestContextProvider> provider_;
- scoped_refptr<cc::TestContextProvider> child_provider_;
+ scoped_refptr<TestContextProvider> provider_;
+ scoped_refptr<TestContextProvider> child_provider_;
std::unique_ptr<cc::LayerTreeResourceProvider> child_resource_provider_;
MockOverlayScheduler scheduler_;
};
diff --git a/chromium/components/viz/service/display/program_binding.h b/chromium/components/viz/service/display/program_binding.h
index ff41ff85a6c..42fed4dc73f 100644
--- a/chromium/components/viz/service/display/program_binding.h
+++ b/chromium/components/viz/service/display/program_binding.h
@@ -322,9 +322,6 @@ class VIZ_SERVICE_EXPORT Program : public ProgramBindingBase {
private:
void InitializeDebugBorderProgram() {
- // Initialize vertex program.
- vertex_shader_.has_matrix_ = true;
-
// Initialize fragment program.
fragment_shader_.input_color_type_ = INPUT_COLOR_SOURCE_UNIFORM;
fragment_shader_.frag_color_mode_ = FRAG_COLOR_MODE_DEFAULT;
@@ -333,7 +330,6 @@ class VIZ_SERVICE_EXPORT Program : public ProgramBindingBase {
void InitializeSolidColorProgram(const ProgramKey& key) {
// Initialize vertex program.
vertex_shader_.position_source_ = POSITION_SOURCE_ATTRIBUTE_INDEXED_UNIFORM;
- vertex_shader_.has_matrix_ = true;
#if defined(OS_ANDROID)
if (key.aa_mode_ == NO_AA)
vertex_shader_.has_dummy_variables_ = true;
@@ -349,7 +345,6 @@ class VIZ_SERVICE_EXPORT Program : public ProgramBindingBase {
vertex_shader_.position_source_ = POSITION_SOURCE_ATTRIBUTE_INDEXED_UNIFORM;
vertex_shader_.tex_coord_transform_ = TEX_COORD_TRANSFORM_VEC4;
vertex_shader_.tex_coord_source_ = TEX_COORD_SOURCE_ATTRIBUTE;
- vertex_shader_.has_matrix_ = true;
// Initialize fragment program.
fragment_shader_.has_tex_clamp_rect_ = key.has_tex_clamp_rect_;
@@ -377,7 +372,6 @@ class VIZ_SERVICE_EXPORT Program : public ProgramBindingBase {
// Initialize vertex program.
vertex_shader_.tex_coord_source_ = TEX_COORD_SOURCE_ATTRIBUTE;
vertex_shader_.tex_coord_transform_ = TEX_COORD_TRANSFORM_VEC4;
- vertex_shader_.has_matrix_ = true;
vertex_shader_.has_vertex_opacity_ = true;
vertex_shader_.use_uniform_arrays_ = !key.has_tex_clamp_rect_;
@@ -389,7 +383,6 @@ class VIZ_SERVICE_EXPORT Program : public ProgramBindingBase {
void InitializeRenderPassProgram(const ProgramKey& key) {
// Initialize vertex program.
- vertex_shader_.has_matrix_ = true;
if (key.aa_mode_ == NO_AA) {
vertex_shader_.tex_coord_source_ = TEX_COORD_SOURCE_ATTRIBUTE;
vertex_shader_.tex_coord_transform_ = TEX_COORD_TRANSFORM_VEC4;
@@ -416,13 +409,11 @@ class VIZ_SERVICE_EXPORT Program : public ProgramBindingBase {
void InitializeVideoStreamProgram(const ProgramKey& key) {
vertex_shader_.tex_coord_source_ = TEX_COORD_SOURCE_ATTRIBUTE;
vertex_shader_.tex_coord_transform_ = TEX_COORD_TRANSFORM_MATRIX;
- vertex_shader_.has_matrix_ = true;
DCHECK_EQ(key.sampler_, SAMPLER_TYPE_EXTERNAL_OES);
}
void InitializeYUVVideo(const ProgramKey& key) {
vertex_shader_.tex_coord_source_ = TEX_COORD_SOURCE_ATTRIBUTE;
- vertex_shader_.has_matrix_ = true;
vertex_shader_.is_ya_uv_ = true;
fragment_shader_.input_color_type_ = INPUT_COLOR_SOURCE_YUV_TEXTURES;
diff --git a/chromium/components/viz/service/display/scoped_render_pass_texture.cc b/chromium/components/viz/service/display/scoped_render_pass_texture.cc
index b6e5b54e9f3..3d9a0abfca2 100644
--- a/chromium/components/viz/service/display/scoped_render_pass_texture.cc
+++ b/chromium/components/viz/service/display/scoped_render_pass_texture.cc
@@ -67,6 +67,7 @@ ScopedRenderPassTexture::ScopedRenderPassTexture(
mipmap_ = other.mipmap_;
color_space_ = other.color_space_;
gl_id_ = other.gl_id_;
+ mipmap_state_ = other.mipmap_state_;
// When being moved, other will no longer hold this gl_id_.
other.gl_id_ = 0;
@@ -81,6 +82,7 @@ ScopedRenderPassTexture& ScopedRenderPassTexture::operator=(
mipmap_ = other.mipmap_;
color_space_ = other.color_space_;
gl_id_ = other.gl_id_;
+ mipmap_state_ = other.mipmap_state_;
// When being moved, other will no longer hold this gl_id_.
other.gl_id_ = 0;
@@ -96,4 +98,24 @@ void ScopedRenderPassTexture::Free() {
gl_id_ = 0;
}
+void ScopedRenderPassTexture::BindForSampling() {
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->BindTexture(GL_TEXTURE_2D, gl_id_);
+ switch (mipmap_state_) {
+ case INVALID:
+ break;
+ case GENERATE:
+ // TODO(crbug.com/803286): npot texture always return false on ubuntu
+ // desktop. The npot texture check is probably failing on desktop GL.
+ DCHECK(context_provider_->ContextCapabilities().texture_npot);
+ gl->GenerateMipmap(GL_TEXTURE_2D);
+ mipmap_state_ = VALID;
+ FALLTHROUGH;
+ case VALID:
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR);
+ break;
+ }
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display/scoped_render_pass_texture.h b/chromium/components/viz/service/display/scoped_render_pass_texture.h
index addf61a0569..b3a79e2067d 100644
--- a/chromium/components/viz/service/display/scoped_render_pass_texture.h
+++ b/chromium/components/viz/service/display/scoped_render_pass_texture.h
@@ -31,11 +31,13 @@ class VIZ_SERVICE_EXPORT ScopedRenderPassTexture {
ScopedRenderPassTexture(ScopedRenderPassTexture&& other);
ScopedRenderPassTexture& operator=(ScopedRenderPassTexture&& other);
+ void BindForSampling();
GLuint id() const { return gl_id_; }
const gfx::Size& size() const { return size_; }
bool mipmap() const { return mipmap_; }
const gfx::ColorSpace& color_space() const { return color_space_; }
+ void set_generate_mipmap() { mipmap_state_ = GENERATE; }
private:
void Free();
@@ -51,6 +53,8 @@ class VIZ_SERVICE_EXPORT ScopedRenderPassTexture {
// TODO(xing.xu): Remove this and set the color space when we draw the
// RenderPassDrawQuad.
gfx::ColorSpace color_space_;
+ enum MipmapState { INVALID, GENERATE, VALID };
+ MipmapState mipmap_state_ = INVALID;
};
} // namespace viz
diff --git a/chromium/components/viz/service/display/shader.cc b/chromium/components/viz/service/display/shader.cc
index 2daf4dc2687..2389df741a7 100644
--- a/chromium/components/viz/service/display/shader.cc
+++ b/chromium/components/viz/service/display/shader.cc
@@ -207,8 +207,7 @@ void VertexShader::Init(GLES2Interface* context,
uniforms.push_back("uvTexScale");
uniforms.push_back("uvTexOffset");
}
- if (has_matrix_)
- uniforms.push_back("matrix");
+ uniforms.push_back("matrix");
if (has_vertex_opacity_)
uniforms.push_back("opacity");
if (aa_mode_ == USE_AA) {
@@ -241,8 +240,7 @@ void VertexShader::Init(GLES2Interface* context,
uv_tex_scale_location_ = locations[index++];
uv_tex_offset_location_ = locations[index++];
}
- if (has_matrix_)
- matrix_location_ = locations[index++];
+ matrix_location_ = locations[index++];
if (has_vertex_opacity_)
vertex_opacity_location_ = locations[index++];
if (aa_mode_ == USE_AA) {
@@ -290,7 +288,6 @@ std::string VertexShader::GetShaderString() const {
SRC("vec4 pos = vec4(quad[vertex_index], a_position.z, a_position.w);");
break;
}
- if (has_matrix_) {
if (use_uniform_arrays_) {
HDR("uniform mat4 matrix[NUM_QUADS];");
SRC("gl_Position = matrix[quad_index] * pos;");
@@ -298,9 +295,6 @@ std::string VertexShader::GetShaderString() const {
HDR("uniform mat4 matrix;");
SRC("gl_Position = matrix * pos;");
}
- } else {
- SRC("gl_Position = pos;");
- }
// Compute the anti-aliasing edge distances.
if (aa_mode_ == USE_AA) {
@@ -348,7 +342,7 @@ std::string VertexShader::GetShaderString() const {
break;
case TEX_COORD_TRANSFORM_TRANSLATED_VEC4:
SRC("texCoord = texCoord + vec2(0.5);");
- // Fall through...
+ FALLTHROUGH;
case TEX_COORD_TRANSFORM_VEC4:
if (use_uniform_arrays_) {
HDR("uniform TexCoordPrecision vec4 vertexTexTransform[NUM_QUADS];");
diff --git a/chromium/components/viz/service/display/shader.h b/chromium/components/viz/service/display/shader.h
index c9e6dcc1d63..7ab139c1e03 100644
--- a/chromium/components/viz/service/display/shader.h
+++ b/chromium/components/viz/service/display/shader.h
@@ -203,7 +203,6 @@ class VIZ_SERVICE_EXPORT VertexShader {
int uv_tex_offset_location_ = -1;
// Matrix to transform the position.
- bool has_matrix_ = false;
int matrix_location_ = -1;
// Used only with POSITION_SOURCE_ATTRIBUTE_INDEXED_UNIFORM.
diff --git a/chromium/components/viz/service/display/shader_unittest.cc b/chromium/components/viz/service/display/shader_unittest.cc
index 02c9382f141..c05da251fe5 100644
--- a/chromium/components/viz/service/display/shader_unittest.cc
+++ b/chromium/components/viz/service/display/shader_unittest.cc
@@ -4,8 +4,8 @@
#include "components/viz/service/display/shader.h"
-#include "cc/test/test_gles2_interface.h"
-#include "cc/test/test_web_graphics_context_3d.h"
+#include "components/viz/test/test_gles2_interface.h"
+#include "components/viz/test/test_web_graphics_context_3d.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
@@ -15,9 +15,9 @@ namespace viz {
TEST(ShaderTest, HighpThresholds) {
// The test context always uses a mediump precision of 10 bits which
// corresponds to a native highp threshold of 2^10 = 1024
- std::unique_ptr<cc::TestWebGraphicsContext3D> test_context =
- cc::TestWebGraphicsContext3D::Create();
- cc::TestGLES2Interface test_gl;
+ std::unique_ptr<TestWebGraphicsContext3D> test_context =
+ TestWebGraphicsContext3D::Create();
+ TestGLES2Interface test_gl;
test_gl.set_test_context(test_context.get());
int threshold_cache = 0;
diff --git a/chromium/components/viz/service/display/skia_renderer.cc b/chromium/components/viz/service/display/skia_renderer.cc
index a327ba1a5d3..aec23b7ec9e 100644
--- a/chromium/components/viz/service/display/skia_renderer.cc
+++ b/chromium/components/viz/service/display/skia_renderer.cc
@@ -34,7 +34,6 @@
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkShader.h"
-#include "third_party/skia/include/effects/SkLayerRasterizer.h"
#include "third_party/skia/include/effects/SkOverdrawColorFilter.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
@@ -66,6 +65,9 @@ SkiaRenderer::SkiaRenderer(const RendererSettings* settings,
const auto& context_caps =
output_surface_->context_provider()->ContextCapabilities();
use_swap_with_bounds_ = context_caps.swap_buffers_with_bounds;
+ if (context_caps.sync_query)
+ sync_queries_ = base::Optional<SyncQueryCollection>(
+ output_surface->context_provider()->ContextGL());
#endif
}
@@ -73,12 +75,6 @@ SkiaRenderer::~SkiaRenderer() {
#if BUILDFLAG(ENABLE_VULKAN)
return;
#endif
- gpu::gles2::GLES2Interface* gl =
- output_surface_->context_provider()->ContextGL();
- for (auto& pair : render_pass_backings_) {
- RenderPassBacking& backing = pair.second;
- gl->DeleteTextures(1, &backing.gl_id);
- }
}
bool SkiaRenderer::CanPartialSwap() {
@@ -97,11 +93,9 @@ void SkiaRenderer::BeginDrawingFrame() {
return;
#else
// Copied from GLRenderer.
- bool use_sync_query_ = false;
scoped_refptr<ResourceFence> read_lock_fence;
- // TODO(weiliangc): Implement use_sync_query_. (crbug.com/644851)
- if (use_sync_query_) {
- NOTIMPLEMENTED();
+ if (sync_queries_) {
+ read_lock_fence = sync_queries_->StartNewFrame();
} else {
read_lock_fence =
base::MakeRefCounted<cc::DisplayResourceProvider::SynchronousFence>(
@@ -122,6 +116,10 @@ void SkiaRenderer::BeginDrawingFrame() {
void SkiaRenderer::FinishDrawingFrame() {
TRACE_EVENT0("viz", "SkiaRenderer::FinishDrawingFrame");
+ if (sync_queries_) {
+ sync_queries_->EndCurrentFrame();
+ }
+
if (settings_->show_overdraw_feedback) {
sk_sp<SkImage> image = overdraw_surface_->makeImageSnapshot();
SkPaint paint;
@@ -246,27 +244,12 @@ void SkiaRenderer::BindFramebufferToOutputSurface() {
}
void SkiaRenderer::BindFramebufferToTexture(const RenderPassId render_pass_id) {
-#if BUILDFLAG(ENABLE_VULKAN)
- NOTIMPLEMENTED();
- return;
-#endif
-
- RenderPassBacking& backing = render_pass_backings_[render_pass_id];
- DCHECK(backing.gl_id);
-
- GrGLTextureInfo texture_info;
- texture_info.fID = backing.gl_id;
- texture_info.fTarget = GL_TEXTURE_2D;
- GrBackendTexture backend_texture(backing.size.width(), backing.size.height(),
- ToGrPixelConfig(backing.format),
- texture_info);
- constexpr uint32_t flags = 0;
- // LegacyFontHost will get LCD text and skia figures out what type to use.
- SkSurfaceProps surface_props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
- int msaa_sample_count = 0;
- non_root_surface_ = SkSurface::MakeFromBackendTextureAsRenderTarget(
- output_surface_->context_provider()->GrContext(), backend_texture,
- kTopLeft_GrSurfaceOrigin, msaa_sample_count, nullptr, &surface_props);
+ auto iter = render_pass_backings_.find(render_pass_id);
+ DCHECK(render_pass_backings_.end() != iter);
+ // This function is called after AllocateRenderPassResourceIfNeeded, so there
+ // should be backing ready.
+ RenderPassBacking& backing = iter->second;
+ non_root_surface_ = backing.render_pass_surface;
current_canvas_ = non_root_surface_->getCanvas();
}
@@ -336,19 +319,6 @@ void SkiaRenderer::PrepareSurfaceForPass(
}
}
-bool SkiaRenderer::IsSoftwareResource(ResourceId resource_id) const {
- switch (resource_provider_->GetResourceType(resource_id)) {
- case ResourceType::kGpuMemoryBuffer:
- case ResourceType::kTexture:
- return false;
- case ResourceType::kBitmap:
- return true;
- }
-
- LOG(FATAL) << "Invalid resource type.";
- return false;
-}
-
void SkiaRenderer::DoDrawQuad(const DrawQuad* quad,
const gfx::QuadF* draw_region) {
if (!current_canvas_)
@@ -523,11 +493,6 @@ void SkiaRenderer::DrawSolidColorQuad(const SolidColorDrawQuad* quad) {
}
void SkiaRenderer::DrawTextureQuad(const TextureDrawQuad* quad) {
- if (IsSoftwareResource(quad->resource_id())) {
- DrawUnsupportedQuad(quad);
- return;
- }
-
// TODO(skaslev): Add support for non-premultiplied alpha.
cc::DisplayResourceProvider::ScopedReadLockSkImage lock(resource_provider_,
quad->resource_id());
@@ -570,7 +535,6 @@ void SkiaRenderer::DrawTileQuad(const TileDrawQuad* quad) {
// |resource_provider_| can be NULL in resourceless software draws, which
// should never produce tile quads in the first place.
DCHECK(resource_provider_);
- DCHECK(!IsSoftwareResource(quad->resource_id()));
cc::DisplayResourceProvider::ScopedReadLockSkImage lock(resource_provider_,
quad->resource_id());
if (!lock.sk_image())
@@ -590,23 +554,14 @@ void SkiaRenderer::DrawTileQuad(const TileDrawQuad* quad) {
}
void SkiaRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad) {
-#if BUILDFLAG(ENABLE_VULKAN)
- NOTIMPLEMENTED();
- return;
-#endif
- RenderPassBacking& content_texture =
- render_pass_backings_[quad->render_pass_id];
- DCHECK(content_texture.gl_id);
-
- GrGLTextureInfo texture_info;
- texture_info.fID = content_texture.gl_id;
- texture_info.fTarget = GL_TEXTURE_2D;
- GrBackendTexture backend_texture(
- content_texture.size.width(), content_texture.size.height(),
- ToGrPixelConfig(content_texture.format), texture_info);
- sk_sp<SkImage> content = SkImage::MakeFromTexture(
- output_surface_->context_provider()->GrContext(), backend_texture,
- kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, nullptr);
+ auto iter = render_pass_backings_.find(quad->render_pass_id);
+ DCHECK(render_pass_backings_.end() != iter);
+ // This function is called after AllocateRenderPassResourceIfNeeded, so there
+ // should be backing ready.
+ RenderPassBacking& content_texture = iter->second;
+
+ sk_sp<SkImage> content =
+ content_texture.render_pass_surface->makeImageSnapshot();
SkRect dest_rect = gfx::RectFToSkRect(QuadVertexRect());
SkRect dest_visible_rect =
@@ -750,10 +705,6 @@ void SkiaRenderer::UpdateRenderPassTextures(
const RenderPassList& render_passes_in_draw_order,
const base::flat_map<RenderPassId, RenderPassRequirements>&
render_passes_in_frame) {
-#if BUILDFLAG(ENABLE_VULKAN)
- NOTIMPLEMENTED();
- return;
-#endif
std::vector<RenderPassId> passes_to_delete;
for (const auto& pair : render_pass_backings_) {
auto render_pass_it = render_passes_in_frame.find(pair.first);
@@ -764,22 +715,19 @@ void SkiaRenderer::UpdateRenderPassTextures(
const RenderPassRequirements& requirements = render_pass_it->second;
const RenderPassBacking& backing = pair.second;
- bool size_appropriate = backing.size.width() >= requirements.size.width() &&
- backing.size.height() >= requirements.size.height();
+ SkSurface* backing_surface = pair.second.render_pass_surface.get();
+ bool size_appropriate =
+ backing_surface->width() >= requirements.size.width() &&
+ backing_surface->height() >= requirements.size.height();
bool mipmap_appropriate = !requirements.mipmap || backing.mipmap;
if (!size_appropriate || !mipmap_appropriate)
passes_to_delete.push_back(pair.first);
}
- gpu::gles2::GLES2Interface* gl =
- output_surface_->context_provider()->ContextGL();
-
// Delete RenderPass backings from the previous frame that will not be used
// again.
for (size_t i = 0; i < passes_to_delete.size(); ++i) {
auto it = render_pass_backings_.find(passes_to_delete[i]);
- RenderPassBacking& backing = it->second;
- gl->DeleteTextures(1, &backing.gl_id);
render_pass_backings_.erase(it);
}
}
@@ -787,74 +735,74 @@ void SkiaRenderer::UpdateRenderPassTextures(
void SkiaRenderer::AllocateRenderPassResourceIfNeeded(
const RenderPassId& render_pass_id,
const RenderPassRequirements& requirements) {
-#if BUILDFLAG(ENABLE_VULKAN)
- NOTIMPLEMENTED();
- return;
-#endif
auto it = render_pass_backings_.find(render_pass_id);
if (it != render_pass_backings_.end())
return;
+#if BUILDFLAG(ENABLE_VULKAN)
+ GrContext* gr_context =
+ output_surface_->vulkan_context_provider()->GetGrContext();
+ // TODO(penghuang): check supported format correctly.
+ bool capability_bgra8888 = true;
+#else
ContextProvider* context_provider = output_surface_->context_provider();
- gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
- const gpu::Capabilities& caps = context_provider->ContextCapabilities();
-
- uint32_t texture_id;
- gl->GenTextures(1, &texture_id);
- gl->BindTexture(GL_TEXTURE_2D, texture_id);
-
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- // This texture will be bound as a framebuffer, so optimize for that.
- if (caps.texture_usage) {
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE,
- GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
- }
-
- ResourceFormat backbuffer_format;
- if (current_frame()->current_render_pass->color_space.IsHDR()) {
+ bool capability_bgra8888 =
+ context_provider->ContextCapabilities().texture_format_bgra8888;
+ GrContext* gr_context = context_provider->GrContext();
+#endif
+ render_pass_backings_.insert(std::pair<RenderPassId, RenderPassBacking>(
+ render_pass_id,
+ RenderPassBacking(gr_context, requirements.size, requirements.mipmap,
+ capability_bgra8888,
+ current_frame()->current_render_pass->color_space)));
+}
+
+SkiaRenderer::RenderPassBacking::RenderPassBacking(
+ GrContext* gr_context,
+ const gfx::Size& size,
+ bool mipmap,
+ bool capability_bgra8888,
+ const gfx::ColorSpace& color_space)
+ : mipmap(mipmap), color_space(color_space) {
+ ResourceFormat format;
+ if (color_space.IsHDR()) {
// If a platform does not support half-float renderbuffers then it should
// not should request HDR rendering.
- DCHECK(caps.texture_half_float_linear);
- DCHECK(caps.color_buffer_half_float_rgba);
- backbuffer_format = RGBA_F16;
+ // DCHECK(caps.texture_half_float_linear);
+ // DCHECK(caps.color_buffer_half_float_rgba);
+ format = RGBA_F16;
} else {
- backbuffer_format =
- PlatformColor::BestSupportedTextureFormat(caps.texture_format_bgra8888);
+ format = PlatformColor::BestSupportedTextureFormat(capability_bgra8888);
}
+ SkColorType color_type = ResourceFormatToClosestSkColorType(format);
- // If |texture_storage| is available, then we can use TexStorage2DEXT to make
- // an immutable texture backing, which allows for optimized usage. Otherwise
- // we must use the traditional TexImage2D to generate the texture backing.
- if (caps.texture_storage) {
- GLint levels = 1;
- // If |texture_npot| is availble, and mipmaps are desired, we generate a
- // mipmap for each power of 2 size. This is only done when using
- // TexStorage2DEXT.
- if (caps.texture_npot && requirements.mipmap) {
- levels += base::bits::Log2Floor(
- std::max(requirements.size.width(), requirements.size.height()));
- }
- gl->TexStorage2DEXT(GL_TEXTURE_2D, levels,
- TextureStorageFormat(backbuffer_format),
- requirements.size.width(), requirements.size.height());
- } else {
- gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(backbuffer_format),
- requirements.size.width(), requirements.size.height(), 0,
- GLDataFormat(backbuffer_format),
- GLDataType(backbuffer_format), nullptr);
- }
+ constexpr uint32_t flags = 0;
+ // LegacyFontHost will get LCD text and skia figures out what type to use.
+ SkSurfaceProps surface_props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
+ int msaa_sample_count = 0;
+ SkImageInfo image_info = SkImageInfo::Make(
+ size.width(), size.height(), color_type, kPremul_SkAlphaType, nullptr);
+ render_pass_surface = SkSurface::MakeRenderTarget(
+ gr_context, SkBudgeted::kNo, image_info, msaa_sample_count,
+ kTopLeft_GrSurfaceOrigin, &surface_props, mipmap);
+}
+
+SkiaRenderer::RenderPassBacking::~RenderPassBacking() {}
+
+SkiaRenderer::RenderPassBacking::RenderPassBacking(
+ SkiaRenderer::RenderPassBacking&& other)
+ : mipmap(other.mipmap), color_space(other.color_space) {
+ render_pass_surface = other.render_pass_surface;
+ other.render_pass_surface = nullptr;
+}
- RenderPassBacking& backing = render_pass_backings_[render_pass_id];
- backing.gl_id = texture_id;
- backing.size = requirements.size;
- backing.mipmap = requirements.mipmap;
- backing.format = backbuffer_format;
- backing.color_space = current_frame()->current_render_pass->color_space;
- gl->BindTexture(GL_TEXTURE_2D, 0);
+SkiaRenderer::RenderPassBacking& SkiaRenderer::RenderPassBacking::operator=(
+ SkiaRenderer::RenderPassBacking&& other) {
+ mipmap = other.mipmap;
+ color_space = other.color_space;
+ render_pass_surface = other.render_pass_surface;
+ other.render_pass_surface = nullptr;
+ return *this;
}
bool SkiaRenderer::IsRenderPassResourceAllocated(
@@ -863,11 +811,12 @@ bool SkiaRenderer::IsRenderPassResourceAllocated(
return it != render_pass_backings_.end();
}
-gfx::Size SkiaRenderer::GetRenderPassTextureSize(
+gfx::Size SkiaRenderer::GetRenderPassBackingPixelSize(
const RenderPassId& render_pass_id) {
auto it = render_pass_backings_.find(render_pass_id);
DCHECK(it != render_pass_backings_.end());
- return it->second.size;
+ SkSurface* texture = it->second.render_pass_surface.get();
+ return gfx::Size(texture->height(), texture->width());
}
} // namespace viz
diff --git a/chromium/components/viz/service/display/skia_renderer.h b/chromium/components/viz/service/display/skia_renderer.h
index 18358d44aba..3bdc6a9b760 100644
--- a/chromium/components/viz/service/display/skia_renderer.h
+++ b/chromium/components/viz/service/display/skia_renderer.h
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "cc/cc_export.h"
#include "components/viz/service/display/direct_renderer.h"
+#include "components/viz/service/display/sync_query_collection.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/vulkan/features.h"
#include "ui/latency/latency_info.h"
@@ -51,7 +52,7 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
const RenderPassRequirements& requirements) override;
bool IsRenderPassResourceAllocated(
const RenderPassId& render_pass_id) const override;
- gfx::Size GetRenderPassTextureSize(
+ gfx::Size GetRenderPassBackingPixelSize(
const RenderPassId& render_pass_id) override;
void BindFramebufferToOutputSurface() override;
void BindFramebufferToTexture(const RenderPassId render_pass_id) override;
@@ -74,7 +75,6 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
void ClearCanvas(SkColor color);
void ClearFramebuffer();
void SetClipRect(const gfx::Rect& rect);
- bool IsSoftwareResource(ResourceId resource_id) const;
void DrawDebugBorderQuad(const DebugBorderDrawQuad* quad);
void DrawPictureQuad(const PictureDrawQuad* quad);
@@ -101,11 +101,17 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
// A map from RenderPass id to the texture used to draw the RenderPass from.
struct RenderPassBacking {
- uint32_t gl_id;
- gfx::Size size;
+ sk_sp<SkSurface> render_pass_surface;
bool mipmap;
- ResourceFormat format;
gfx::ColorSpace color_space;
+ RenderPassBacking(GrContext* gr_context,
+ const gfx::Size& size,
+ bool mipmap,
+ bool capability_bgra8888,
+ const gfx::ColorSpace& color_space);
+ ~RenderPassBacking();
+ RenderPassBacking(RenderPassBacking&&);
+ RenderPassBacking& operator=(RenderPassBacking&&);
};
base::flat_map<RenderPassId, RenderPassBacking> render_pass_backings_;
@@ -123,6 +129,7 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
SkCanvas* current_canvas_ = nullptr;
SkPaint current_paint_;
+ base::Optional<SyncQueryCollection> sync_queries_;
bool use_swap_with_bounds_ = false;
gfx::Rect swap_buffer_rect_;
diff --git a/chromium/components/viz/service/display/software_renderer.cc b/chromium/components/viz/service/display/software_renderer.cc
index 65df0a29cbd..093ed46290e 100644
--- a/chromium/components/viz/service/display/software_renderer.cc
+++ b/chromium/components/viz/service/display/software_renderer.cc
@@ -31,7 +31,7 @@
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkShader.h"
-#include "third_party/skia/include/effects/SkLayerRasterizer.h"
+#include "third_party/skia/include/effects/SkShaderMaskFilter.h"
#include "ui/gfx/geometry/axis_transform2d.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/skia_util.h"
@@ -497,15 +497,9 @@ void SoftwareRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad) {
SkMatrix mask_mat;
mask_mat.setRectToRect(mask_rect, dest_rect, SkMatrix::kFill_ScaleToFit);
- SkPaint mask_paint;
- mask_paint.setShader(
+ current_paint_.setMaskFilter(SkShaderMaskFilter::Make(
SkShader::MakeBitmapShader(*mask, SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode, &mask_mat));
-
- SkLayerRasterizer::Builder builder;
- builder.addLayer(mask_paint);
-
- current_paint_.setRasterizer(builder.detach());
+ SkShader::kClamp_TileMode, &mask_mat)));
}
// If we have a background filter shader, render its results first.
@@ -514,7 +508,7 @@ void SoftwareRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad) {
if (background_filter_shader) {
SkPaint paint;
paint.setShader(std::move(background_filter_shader));
- paint.setRasterizer(current_paint_.refRasterizer());
+ paint.setMaskFilter(current_paint_.refMaskFilter());
current_canvas_->drawRect(dest_visible_rect, paint);
}
current_paint_.setShader(std::move(shader));
@@ -824,7 +818,7 @@ bool SoftwareRenderer::IsRenderPassResourceAllocated(
return it != render_pass_bitmaps_.end();
}
-gfx::Size SoftwareRenderer::GetRenderPassTextureSize(
+gfx::Size SoftwareRenderer::GetRenderPassBackingPixelSize(
const RenderPassId& render_pass_id) {
auto it = render_pass_bitmaps_.find(render_pass_id);
DCHECK(it != render_pass_bitmaps_.end());
diff --git a/chromium/components/viz/service/display/software_renderer.h b/chromium/components/viz/service/display/software_renderer.h
index adfc0c06dca..3e7d634b077 100644
--- a/chromium/components/viz/service/display/software_renderer.h
+++ b/chromium/components/viz/service/display/software_renderer.h
@@ -49,7 +49,7 @@ class VIZ_SERVICE_EXPORT SoftwareRenderer : public DirectRenderer {
const RenderPassRequirements& requirements) override;
bool IsRenderPassResourceAllocated(
const RenderPassId& render_pass_id) const override;
- gfx::Size GetRenderPassTextureSize(
+ gfx::Size GetRenderPassBackingPixelSize(
const RenderPassId& render_pass_id) override;
void BindFramebufferToOutputSurface() override;
void BindFramebufferToTexture(const RenderPassId render_pass_id) override;
diff --git a/chromium/components/viz/service/display/software_renderer_unittest.cc b/chromium/components/viz/service/display/software_renderer_unittest.cc
index 1ba2f6fe9fc..a82119beb1e 100644
--- a/chromium/components/viz/service/display/software_renderer_unittest.cc
+++ b/chromium/components/viz/service/display/software_renderer_unittest.cc
@@ -10,14 +10,12 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "cc/test/animation_test_common.h"
-#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_resource_provider.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/pixel_test_utils.h"
#include "cc/test/render_pass_test_utils.h"
#include "cc/test/resource_provider_test_utils.h"
-#include "cc/test/test_shared_bitmap_manager.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
@@ -26,6 +24,8 @@
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/tile_draw_quad.h"
#include "components/viz/service/display/software_output_device.h"
+#include "components/viz/test/fake_output_surface.h"
+#include "components/viz/test/test_shared_bitmap_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkCanvas.h"
@@ -39,11 +39,11 @@ class SoftwareRendererTest : public testing::Test {
public:
void InitializeRenderer(
std::unique_ptr<SoftwareOutputDevice> software_output_device) {
- output_surface_ = cc::FakeOutputSurface::CreateSoftware(
- std::move(software_output_device));
+ output_surface_ =
+ FakeOutputSurface::CreateSoftware(std::move(software_output_device));
output_surface_->BindToClient(&output_surface_client_);
- shared_bitmap_manager_ = std::make_unique<cc::TestSharedBitmapManager>();
+ shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
resource_provider_ =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
nullptr, shared_bitmap_manager_.get());
@@ -96,7 +96,7 @@ class SoftwareRendererTest : public testing::Test {
protected:
RendererSettings settings_;
cc::FakeOutputSurfaceClient output_surface_client_;
- std::unique_ptr<cc::FakeOutputSurface> output_surface_;
+ std::unique_ptr<FakeOutputSurface> output_surface_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
std::unique_ptr<cc::LayerTreeResourceProvider> child_resource_provider_;
diff --git a/chromium/components/viz/service/display/surface_aggregator.cc b/chromium/components/viz/service/display/surface_aggregator.cc
index 1b9a6533556..ee96f9063fb 100644
--- a/chromium/components/viz/service/display/surface_aggregator.cc
+++ b/chromium/components/viz/service/display/surface_aggregator.cc
@@ -25,7 +25,6 @@
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
-#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_client.h"
#include "components/viz/service/surfaces/surface_manager.h"
@@ -195,7 +194,6 @@ void SurfaceAggregator::HandleSurfaceQuad(
bool* damage_rect_in_quad_space_valid) {
SurfaceId primary_surface_id = surface_quad->primary_surface_id;
Surface* primary_surface = manager_->GetSurfaceForId(primary_surface_id);
-
if (primary_surface && primary_surface->HasActiveFrame()) {
EmitSurfaceContent(primary_surface, parent_device_scale_factor,
surface_quad->shared_quad_state, surface_quad->rect,
@@ -329,7 +327,10 @@ void SurfaceAggregator::EmitSurfaceContent(
const auto& child_to_parent_map =
provider_ ? provider_->GetChildToParentMap(ChildIdForSurface(surface))
: empty_map;
- bool merge_pass = source_sqs->opacity == 1.f && copy_requests.empty();
+ gfx::Transform combined_transform = scaled_quad_to_target_transform;
+ combined_transform.ConcatTransform(target_transform);
+ bool merge_pass = source_sqs->opacity == 1.f && copy_requests.empty() &&
+ combined_transform.Preserves2dAxisAlignment();
const RenderPassList& referenced_passes = render_pass_list;
// TODO(fsamuel): Move this to a separate helper function.
@@ -881,13 +882,15 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
bool has_moved_pixels,
RenderPassId parent_pass_id,
const gfx::Transform& target_to_surface_transform,
- const gfx::Rect& quad_rect)
+ const gfx::Rect& quad_rect,
+ bool stretch_content_to_fill_bounds)
: primary_id(primary_id),
fallback_id(fallback_id),
has_moved_pixels(has_moved_pixels),
parent_pass_id(parent_pass_id),
target_to_surface_transform(target_to_surface_transform),
- quad_rect(quad_rect) {}
+ quad_rect(quad_rect),
+ stretch_content_to_fill_bounds(stretch_content_to_fill_bounds) {}
SurfaceId primary_id;
base::Optional<SurfaceId> fallback_id;
@@ -895,6 +898,7 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
RenderPassId parent_pass_id;
gfx::Transform target_to_surface_transform;
gfx::Rect quad_rect;
+ bool stretch_content_to_fill_bounds;
};
std::vector<SurfaceInfo> child_surfaces;
@@ -936,7 +940,7 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
child_surfaces.emplace_back(
surface_quad->primary_surface_id, surface_quad->fallback_surface_id,
in_moved_pixel_pass, remapped_pass_id, target_to_surface_transform,
- surface_quad->rect);
+ surface_quad->rect, surface_quad->stretch_content_to_fill_bounds);
} else if (quad->material == DrawQuad::RENDER_PASS) {
const auto* render_pass_quad = RenderPassDrawQuad::MaterialCast(quad);
if (in_moved_pixel_pass) {
@@ -1003,9 +1007,26 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
}
if (child_surface) {
- surface_damage.Union(
- PrewalkTree(child_surface, surface_info.has_moved_pixels,
- surface_info.parent_pass_id, will_draw, result));
+ if (surface_info.stretch_content_to_fill_bounds) {
+ // Scale up the damage_quad generated by the child_surface to fit
+ // the containing quad_rect.
+ gfx::Rect child_rect =
+ PrewalkTree(child_surface, surface_info.has_moved_pixels,
+ surface_info.parent_pass_id, will_draw, result);
+ if (child_surface->size_in_pixels().GetCheckedArea().ValueOrDefault(0) >
+ 0) {
+ float y_scale = static_cast<float>(surface_info.quad_rect.height()) /
+ child_surface->size_in_pixels().height();
+ float x_scale = static_cast<float>(surface_info.quad_rect.width()) /
+ child_surface->size_in_pixels().width();
+ surface_damage.Union(
+ gfx::ScaleToEnclosingRect(child_rect, x_scale, y_scale));
+ }
+ } else {
+ surface_damage.Union(
+ PrewalkTree(child_surface, surface_info.has_moved_pixels,
+ surface_info.parent_pass_id, will_draw, result));
+ }
}
if (surface_damage.IsEmpty())
diff --git a/chromium/components/viz/service/display/surface_aggregator_perftest.cc b/chromium/components/viz/service/display/surface_aggregator_perftest.cc
index a0b4f09c935..2cb18bf1f94 100644
--- a/chromium/components/viz/service/display/surface_aggregator_perftest.cc
+++ b/chromium/components/viz/service/display/surface_aggregator_perftest.cc
@@ -6,8 +6,6 @@
#include "cc/resources/display_resource_provider.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_resource_provider.h"
-#include "cc/test/test_context_provider.h"
-#include "cc/test/test_shared_bitmap_manager.h"
#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"
@@ -16,6 +14,8 @@
#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_context_provider.h"
+#include "components/viz/test/test_shared_bitmap_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"
@@ -31,9 +31,9 @@ const base::UnguessableToken kArbitraryToken = base::UnguessableToken::Create();
class SurfaceAggregatorPerfTest : public testing::Test {
public:
SurfaceAggregatorPerfTest() {
- context_provider_ = cc::TestContextProvider::Create();
+ context_provider_ = TestContextProvider::Create();
context_provider_->BindToCurrentThread();
- shared_bitmap_manager_ = std::make_unique<cc::TestSharedBitmapManager>();
+ shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
resource_provider_ =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
@@ -139,14 +139,11 @@ class SurfaceAggregatorPerfTest : public testing::Test {
perf_test::PrintResult("aggregator_speed", "", name, timer_.LapsPerSecond(),
"runs/s", true);
- for (int i = 0; i < num_surfaces; i++)
- child_supports[i]->EvictCurrentSurface();
- root_support->EvictCurrentSurface();
}
protected:
FrameSinkManagerImpl manager_;
- scoped_refptr<cc::TestContextProvider> context_provider_;
+ scoped_refptr<TestContextProvider> context_provider_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
std::unique_ptr<SurfaceAggregator> aggregator_;
diff --git a/chromium/components/viz/service/display/surface_aggregator_pixeltest.cc b/chromium/components/viz/service/display/surface_aggregator_pixeltest.cc
index 7e2d9e9bcba..8b3bbbdf823 100644
--- a/chromium/components/viz/service/display/surface_aggregator_pixeltest.cc
+++ b/chromium/components/viz/service/display/surface_aggregator_pixeltest.cc
@@ -40,7 +40,7 @@ class SurfaceAggregatorPixelTest : public cc::RendererPixelTest<GLRenderer> {
kArbitraryRootFrameSinkId,
kIsRoot,
kNeedsSyncPoints)) {}
- ~SurfaceAggregatorPixelTest() override { support_->EvictCurrentSurface(); }
+ ~SurfaceAggregatorPixelTest() override {}
protected:
FrameSinkManagerImpl manager_;
@@ -169,8 +169,6 @@ TEST_F(SurfaceAggregatorPixelTest, DrawSimpleAggregatedFrame) {
EXPECT_TRUE(RunPixelTest(pass_list,
base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")),
pixel_comparator));
-
- child_support->EvictCurrentSurface();
}
// Tests a surface quad that has a non-identity transform into its pass.
@@ -298,9 +296,6 @@ TEST_F(SurfaceAggregatorPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
pass_list,
base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
pixel_comparator));
-
- left_support->EvictCurrentSurface();
- right_support->EvictCurrentSurface();
}
} // namespace
diff --git a/chromium/components/viz/service/display/surface_aggregator_unittest.cc b/chromium/components/viz/service/display/surface_aggregator_unittest.cc
index 35f34c681ea..eb12f6238ac 100644
--- a/chromium/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/chromium/components/viz/service/display/surface_aggregator_unittest.cc
@@ -16,7 +16,6 @@
#include "cc/resources/display_resource_provider.h"
#include "cc/test/fake_resource_provider.h"
#include "cc/test/render_pass_test_utils.h"
-#include "cc/test/test_shared_bitmap_manager.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/render_pass.h"
#include "components/viz/common/quads/render_pass_draw_quad.h"
@@ -32,6 +31,7 @@
#include "components/viz/test/compositor_frame_helpers.h"
#include "components/viz/test/fake_compositor_frame_sink_client.h"
#include "components/viz/test/fake_surface_observer.h"
+#include "components/viz/test/test_shared_bitmap_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -105,7 +105,6 @@ class SurfaceAggregatorTest : public testing::Test {
void TearDown() override {
observer_.Reset();
- support_->EvictCurrentSurface();
testing::Test::TearDown();
}
@@ -124,12 +123,29 @@ class SurfaceAggregatorTest : public testing::Test {
const SurfaceId& fallback_surface_id,
SkColor default_background_color,
const gfx::Rect& primary_surface_rect,
+ bool stretch_content_to_fill_bounds) {
+ Quad quad;
+ quad.material = DrawQuad::SURFACE_CONTENT;
+ quad.primary_surface_rect = primary_surface_rect;
+ quad.primary_surface_id = primary_surface_id;
+ quad.fallback_surface_id = fallback_surface_id;
+ quad.default_background_color = default_background_color;
+ quad.stretch_content_to_fill_bounds = stretch_content_to_fill_bounds;
+ return quad;
+ }
+
+ static Quad SurfaceQuad(const SurfaceId& primary_surface_id,
+ const SurfaceId& fallback_surface_id,
+ SkColor default_background_color,
+ const gfx::Rect& primary_surface_rect,
float opacity,
+ const gfx::Transform& transform,
bool stretch_content_to_fill_bounds) {
Quad quad;
quad.material = DrawQuad::SURFACE_CONTENT;
quad.primary_surface_rect = primary_surface_rect;
quad.opacity = opacity;
+ quad.to_target_transform = transform;
quad.primary_surface_id = primary_surface_id;
quad.fallback_surface_id = fallback_surface_id;
quad.default_background_color = default_background_color;
@@ -152,6 +168,7 @@ class SurfaceAggregatorTest : public testing::Test {
bool stretch_content_to_fill_bounds;
gfx::Rect primary_surface_rect;
float opacity;
+ gfx::Transform to_target_transform;
// Set when material==DrawQuad::SOLID_COLOR.
SkColor color;
gfx::Rect rect;
@@ -194,8 +211,8 @@ class SurfaceAggregatorTest : public testing::Test {
break;
case DrawQuad::SURFACE_CONTENT:
AddSurfaceQuad(pass, desc.primary_surface_rect, desc.opacity,
- desc.primary_surface_id, desc.fallback_surface_id,
- desc.default_background_color,
+ desc.to_target_transform, desc.primary_surface_id,
+ desc.fallback_surface_id, desc.default_background_color,
desc.stretch_content_to_fill_bounds);
break;
case DrawQuad::RENDER_PASS:
@@ -274,11 +291,12 @@ class SurfaceAggregatorTest : public testing::Test {
static void AddSurfaceQuad(RenderPass* pass,
const gfx::Rect& primary_surface_rect,
float opacity,
+ const gfx::Transform& transform,
const SurfaceId& primary_surface_id,
const SurfaceId& fallback_surface_id,
SkColor default_background_color,
bool stretch_content_to_fill_bounds) {
- gfx::Transform layer_to_target_transform;
+ 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);
@@ -331,7 +349,10 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
&manager_,
kArbitraryReservedFrameSinkId,
kChildIsRoot,
- kNeedsSyncPoints)) {}
+ kNeedsSyncPoints)) {
+ child_support_->set_allow_copy_output_requests_for_testing();
+ }
+
SurfaceAggregatorValidSurfaceTest()
: SurfaceAggregatorValidSurfaceTest(false) {}
@@ -343,7 +364,6 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
}
void TearDown() override {
- child_support_->EvictCurrentSurface();
SurfaceAggregatorTest::TearDown();
}
@@ -425,7 +445,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) {
// Add a callback for when the surface is damaged.
MockAggregatedDamageCallback aggregated_damage_callback;
- support_->SetAggregatedDamageCallback(
+ support_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
constexpr float device_scale_factor = 1.0f;
@@ -445,6 +465,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) {
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
}
+// Test that when surface is translucent and we need the render surface to apply
+// the opacity, we would keep the render surface.
TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) {
auto embedded_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kRootIsRoot,
@@ -465,7 +487,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) {
Quad quads[] = {Quad::SurfaceQuad(embedded_surface_id, InvalidSurfaceId(),
SK_ColorWHITE, gfx::Rect(5, 5), .5f,
- false)};
+ gfx::Transform(), false)};
Pass passes[] = {Pass(quads, arraysize(quads), SurfaceSize())};
SubmitCompositorFrame(support_.get(), passes, arraysize(passes),
@@ -484,8 +506,46 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) {
auto& shared_quad_state_list2 = render_pass_list[1]->shared_quad_state_list;
ASSERT_EQ(1u, shared_quad_state_list2.size());
EXPECT_EQ(.5f, shared_quad_state_list2.ElementAt(0)->opacity);
+}
+
+// Test that when surface is rotated and we need the render surface to apply the
+// clip, we would keep the render surface.
+TEST_F(SurfaceAggregatorValidSurfaceTest, RotatedClip) {
+ auto embedded_support = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, &manager_, kArbitraryFrameSinkId1, kRootIsRoot,
+ kNeedsSyncPoints);
+ LocalSurfaceId embedded_local_surface_id = allocator_.GenerateId();
+ SurfaceId embedded_surface_id(embedded_support->frame_sink_id(),
+ embedded_local_surface_id);
+
+ Quad embedded_quads[] = {Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5)),
+ Quad::SolidColorQuad(SK_ColorBLUE, gfx::Rect(5, 5))};
+ Pass embedded_passes[] = {
+ Pass(embedded_quads, arraysize(embedded_quads), SurfaceSize())};
+
+ constexpr float device_scale_factor = 1.0f;
+ SubmitCompositorFrame(embedded_support.get(), embedded_passes,
+ arraysize(embedded_passes), embedded_local_surface_id,
+ device_scale_factor);
+ gfx::Transform rotate;
+ rotate.Rotate(30);
+ Quad quads[] = {Quad::SurfaceQuad(embedded_surface_id, InvalidSurfaceId(),
+ SK_ColorWHITE, gfx::Rect(5, 5), 1.f, rotate,
+ false)};
+ Pass passes[] = {Pass(quads, arraysize(quads), SurfaceSize())};
+
+ SubmitCompositorFrame(support_.get(), passes, arraysize(passes),
+ root_local_surface_id_, device_scale_factor);
+
+ SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_);
+ CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id);
- embedded_support->EvictCurrentSurface();
+ auto& render_pass_list = aggregated_frame.render_pass_list;
+ EXPECT_EQ(2u, render_pass_list.size());
+
+ auto& shared_quad_state_list2 =
+ render_pass_list.back()->shared_quad_state_list;
+ EXPECT_EQ(rotate, shared_quad_state_list2.front()->quad_to_target_transform);
}
TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) {
@@ -584,7 +644,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
Quad root_quads[] = {
Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
Quad::SurfaceQuad(embedded_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false),
+ gfx::Rect(5, 5), false),
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
Pass root_passes[] = {Pass(root_quads, arraysize(root_quads), SurfaceSize())};
@@ -601,8 +661,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
SurfaceId ids[] = {root_surface_id, embedded_surface_id};
AggregateAndVerify(expected_passes, arraysize(expected_passes), ids,
arraysize(ids));
-
- embedded_support->EvictCurrentSurface();
}
// This test verifies that in the absence of a primary Surface,
@@ -642,16 +700,16 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReference) {
constexpr gfx::Rect surface_quad_rect(12, 15);
Quad root_quads[] = {
Quad::SurfaceQuad(primary_child_surface_id, fallback_child_surface_id,
- SK_ColorWHITE, surface_quad_rect, 1.f, false)};
+ SK_ColorWHITE, surface_quad_rect, false)};
Pass root_passes[] = {Pass(root_quads, arraysize(root_quads), SurfaceSize())};
MockAggregatedDamageCallback aggregated_damage_callback;
- support_->SetAggregatedDamageCallback(
+ support_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
- primary_child_support->SetAggregatedDamageCallback(
+ primary_child_support->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
- fallback_child_support->SetAggregatedDamageCallback(
+ fallback_child_support->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes),
@@ -693,6 +751,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReference) {
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
// Submit the fallback again to create some damage then aggregate again.
+ fallback_child_local_surface_id = allocator_.GenerateId();
SubmitCompositorFrame(fallback_child_support.get(), fallback_child_passes,
arraysize(fallback_child_passes),
fallback_child_local_surface_id, device_scale_factor_1);
@@ -747,9 +806,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReference) {
arraysize(ids2));
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
-
- primary_child_support->EvictCurrentSurface();
- fallback_child_support->EvictCurrentSurface();
}
// This test verifies that the appropriate transform will be applied to a
@@ -783,11 +839,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillBounds) {
constexpr gfx::Rect surface_quad_rect(10, 5);
Quad root_quads[] = {
Quad::SurfaceQuad(primary_child_surface_id, primary_child_surface_id,
- SK_ColorWHITE, surface_quad_rect, 1.f, true)};
+ SK_ColorWHITE, surface_quad_rect, true)};
Pass root_passes[] = {Pass(root_quads, arraysize(root_quads), SurfaceSize())};
MockAggregatedDamageCallback aggregated_damage_callback;
- support_->SetAggregatedDamageCallback(
+ support_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_);
@@ -816,6 +872,137 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillBounds) {
EXPECT_EQ(gfx::RectF(50.f, 25.f), output_rect);
}
+// 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 when the device_scale_factor is
+// greater than 1.
+TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillStretchedBounds) {
+ auto primary_child_support = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot,
+ kNeedsSyncPoints);
+ LocalSurfaceId primary_child_local_surface_id = allocator_.GenerateId();
+ SurfaceId primary_child_surface_id(primary_child_support->frame_sink_id(),
+ primary_child_local_surface_id);
+
+ {
+ auto pass = RenderPass::Create();
+ pass->SetNew(1, gfx::Rect(0, 0, 20, 20), gfx::Rect(), gfx::Transform());
+ auto* sqs = pass->CreateAndAppendSharedQuadState();
+ auto* solid_color_quad =
+ pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+
+ 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));
+ }
+
+ constexpr gfx::Rect surface_quad_rect(10, 5);
+ Quad root_quads[] = {
+ Quad::SurfaceQuad(primary_child_surface_id, primary_child_surface_id,
+ SK_ColorWHITE, surface_quad_rect, true)};
+ Pass root_passes[] = {Pass(root_quads, arraysize(root_quads), SurfaceSize())};
+
+ MockAggregatedDamageCallback aggregated_damage_callback;
+ support_->SetAggregatedDamageCallbackForTesting(
+ aggregated_damage_callback.GetCallback());
+
+ SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_);
+ SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes),
+ root_local_surface_id_, 2.0f);
+
+ EXPECT_CALL(aggregated_damage_callback,
+ OnAggregatedDamage(root_local_surface_id_, _));
+ CompositorFrame frame = aggregator_.Aggregate(root_surface_id);
+
+ testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
+
+ EXPECT_EQ(1u, frame.render_pass_list.size());
+ auto* render_pass = frame.render_pass_list.back().get();
+ EXPECT_EQ(1u, render_pass->quad_list.size());
+
+ auto* output_quad = render_pass->quad_list.back();
+
+ EXPECT_EQ(DrawQuad::SOLID_COLOR, output_quad->material);
+ gfx::RectF output_rect(200.f, 200.f);
+
+ // SurfaceAggregator should stretch the SolidColorDrawQuad to fit the bounds
+ // of the parent's SurfaceDrawQuad.
+ output_quad->shared_quad_state->quad_to_target_transform.TransformRect(
+ &output_rect);
+
+ EXPECT_EQ(gfx::RectF(100.f, 50.f), output_rect);
+}
+
+// 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 when the device_scale_factor is
+// less than 1.
+TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillSquashedBounds) {
+ auto primary_child_support = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot,
+ kNeedsSyncPoints);
+ LocalSurfaceId primary_child_local_surface_id = allocator_.GenerateId();
+ SurfaceId primary_child_surface_id(primary_child_support->frame_sink_id(),
+ primary_child_local_surface_id);
+
+ {
+ auto pass = RenderPass::Create();
+ pass->SetNew(1, gfx::Rect(0, 0, 20, 20), gfx::Rect(), gfx::Transform());
+ auto* sqs = pass->CreateAndAppendSharedQuadState();
+ auto* solid_color_quad =
+ pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+
+ 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));
+ }
+
+ constexpr gfx::Rect surface_quad_rect(10, 5);
+ Quad root_quads[] = {
+ Quad::SurfaceQuad(primary_child_surface_id, primary_child_surface_id,
+ SK_ColorWHITE, surface_quad_rect, true)};
+ Pass root_passes[] = {Pass(root_quads, arraysize(root_quads), SurfaceSize())};
+
+ MockAggregatedDamageCallback aggregated_damage_callback;
+ support_->SetAggregatedDamageCallbackForTesting(
+ aggregated_damage_callback.GetCallback());
+
+ SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_);
+ SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes),
+ root_local_surface_id_, 0.5f);
+
+ EXPECT_CALL(aggregated_damage_callback,
+ OnAggregatedDamage(root_local_surface_id_, _));
+ CompositorFrame frame = aggregator_.Aggregate(root_surface_id);
+ testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
+
+ EXPECT_EQ(1u, frame.render_pass_list.size());
+ auto* render_pass = frame.render_pass_list.back().get();
+ EXPECT_EQ(1u, render_pass->quad_list.size());
+
+ auto* output_quad = render_pass->quad_list.back();
+
+ EXPECT_EQ(DrawQuad::SOLID_COLOR, output_quad->material);
+ gfx::RectF output_rect(50.f, 50.f);
+
+ // SurfaceAggregator should stretch the SolidColorDrawQuad to fit the bounds
+ // of the parent's SurfaceDrawQuad.
+ output_quad->shared_quad_state->quad_to_target_transform.TransformRect(
+ &output_rect);
+
+ EXPECT_EQ(gfx::RectF(25.f, 12.5f), output_rect);
+}
+
// This test verifies that in the presence of both primary Surface and fallback
// Surface, the fallback will not be used.
TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReferenceWithPrimary) {
@@ -860,13 +1047,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReferenceWithPrimary) {
// |fallback_child_surface_id|.
Quad root_quads[] = {
Quad::SurfaceQuad(primary_child_surface_id, fallback_child_surface_id,
- SK_ColorWHITE, gfx::Rect(5, 5), 1.f, false)};
+ SK_ColorWHITE, gfx::Rect(5, 5), false)};
constexpr gfx::Size root_size(75, 75);
Pass root_passes[] = {
Pass(root_quads, arraysize(root_quads), root_size, NoDamage())};
MockAggregatedDamageCallback aggregated_damage_callback;
- support_->SetAggregatedDamageCallback(
+ support_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes),
@@ -907,9 +1094,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReferenceWithPrimary) {
arraysize(ids));
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
-
- primary_child_support->EvictCurrentSurface();
- fallback_child_support->EvictCurrentSurface();
}
TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
@@ -936,7 +1120,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
Quad root_quads[] = {
Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
Quad::SurfaceQuad(embedded_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false),
+ gfx::Rect(5, 5), false),
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
Pass root_passes[] = {Pass(root_quads, arraysize(root_quads), SurfaceSize())};
@@ -968,8 +1152,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
aggregator_.previous_contained_surfaces().end());
}
-
- embedded_support->EvictCurrentSurface();
}
// Root surface may contain copy requests.
@@ -998,7 +1180,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
Quad root_quads[] = {
Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
Quad::SurfaceQuad(embedded_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false),
+ gfx::Rect(5, 5), false),
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
Quad root_quads2[] = {Quad::SolidColorQuad(SK_ColorRED, gfx::Rect(5, 5))};
Pass root_passes[] = {
@@ -1051,8 +1233,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
ASSERT_EQ(2u, original_pass_list.size());
DCHECK(original_pass_list[0]->copy_requests.empty());
DCHECK(original_pass_list[1]->copy_requests.empty());
-
- embedded_support->EvictCurrentSurface();
}
TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) {
@@ -1088,7 +1268,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) {
Quad parent_quads[] = {
Quad::SolidColorQuad(SK_ColorGRAY, gfx::Rect(5, 5)),
Quad::SurfaceQuad(embedded_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false),
+ gfx::Rect(5, 5), false),
Quad::SolidColorQuad(SK_ColorLTGRAY, gfx::Rect(5, 5))};
Pass parent_passes[] = {
Pass(parent_quads, arraysize(parent_quads), SurfaceSize())};
@@ -1147,9 +1327,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) {
aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
aggregator_.previous_contained_surfaces().end());
}
-
- embedded_support->EvictCurrentSurface();
- parent_support->EvictCurrentSurface();
}
// This tests referencing a surface that has multiple render passes.
@@ -1183,7 +1360,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
{Quad::SolidColorQuad(5, gfx::Rect(5, 5)),
Quad::SolidColorQuad(6, gfx::Rect(5, 5))},
{Quad::SurfaceQuad(embedded_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false),
+ gfx::Rect(5, 5), false),
Quad::RenderPassQuad(pass_ids[0])},
{Quad::SolidColorQuad(7, gfx::Rect(5, 5)),
Quad::RenderPassQuad(pass_ids[1])}};
@@ -1303,7 +1480,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) {
Quad quads[] = {Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5)),
Quad::SurfaceQuad(InvalidSurfaceId(), InvalidSurfaceId(),
- SK_ColorWHITE, gfx::Rect(5, 5), 1.f, false),
+ SK_ColorWHITE, gfx::Rect(5, 5), false),
Quad::SolidColorQuad(SK_ColorBLUE, gfx::Rect(5, 5))};
Pass passes[] = {Pass(quads, arraysize(quads), SurfaceSize())};
@@ -1331,7 +1508,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) {
Quad quads[] = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5)),
Quad::SurfaceQuad(surface_with_no_frame_id, InvalidSurfaceId(),
- SK_ColorYELLOW, gfx::Rect(5, 5), 1.f, false),
+ SK_ColorYELLOW, gfx::Rect(5, 5), false),
Quad::SolidColorQuad(SK_ColorBLUE, gfx::Rect(5, 5))};
Pass passes[] = {Pass(quads, arraysize(quads), SurfaceSize())};
@@ -1361,7 +1538,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ValidFallbackWithNoFrame) {
Quad quads[] = {Quad::SurfaceQuad(surface_with_no_frame_id,
surface_with_no_frame_id, SK_ColorYELLOW,
- gfx::Rect(5, 5), 1.f, false)};
+ gfx::Rect(5, 5), false)};
Pass passes[] = {Pass(quads, arraysize(quads), SurfaceSize())};
constexpr float device_scale_factor = 1.0f;
@@ -1388,7 +1565,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ValidFallbackWithNoFrame) {
TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) {
SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_);
Quad quads[] = {Quad::SurfaceQuad(root_surface_id, InvalidSurfaceId(),
- SK_ColorWHITE, gfx::Rect(5, 5), 1.f, false),
+ SK_ColorWHITE, gfx::Rect(5, 5), false),
Quad::SolidColorQuad(SK_ColorYELLOW, gfx::Rect(5, 5))};
Pass passes[] = {Pass(quads, arraysize(quads), SurfaceSize())};
@@ -1414,7 +1591,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {
Quad parent_quads[] = {
Quad::SolidColorQuad(SK_ColorBLUE, gfx::Rect(5, 5)),
Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false),
+ gfx::Rect(5, 5), false),
Quad::SolidColorQuad(SK_ColorCYAN, gfx::Rect(5, 5))};
Pass parent_passes[] = {
Pass(parent_quads, arraysize(parent_quads), SurfaceSize())};
@@ -1427,7 +1604,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {
Quad child_quads[] = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5)),
Quad::SurfaceQuad(root_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false),
+ gfx::Rect(5, 5), false),
Quad::SolidColorQuad(SK_ColorMAGENTA, gfx::Rect(5, 5))};
Pass child_passes[] = {
Pass(child_quads, arraysize(child_quads), SurfaceSize())};
@@ -1479,7 +1656,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
RenderPassId parent_pass_id[] = {3u, 2u};
Quad parent_quad[][1] = {
{Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)},
+ gfx::Rect(5, 5), false)},
{Quad::RenderPassQuad(parent_pass_id[0])}};
Pass parent_passes[] = {Pass(parent_quad[0], arraysize(parent_quad[0]),
parent_pass_id[0], SurfaceSize()),
@@ -1681,10 +1858,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
EXPECT_EQ(blend_modes[iter.index()], iter->shared_quad_state->blend_mode)
<< iter.index();
}
-
- grandchild_support->EvictCurrentSurface();
- child_one_support->EvictCurrentSurface();
- child_two_support->EvictCurrentSurface();
}
// This tests that when aggregating a frame with multiple render passes that we
@@ -1751,7 +1924,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
{
Quad middle_quads[] = {Quad::SurfaceQuad(child_surface_id,
InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)};
+ gfx::Rect(5, 5), false)};
Pass middle_passes[] = {
Pass(middle_quads, arraysize(middle_quads), SurfaceSize()),
};
@@ -1776,7 +1949,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
Quad secondary_quads[] = {
Quad::SolidColorQuad(1, gfx::Rect(5, 5)),
Quad::SurfaceQuad(middle_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)};
+ gfx::Rect(5, 5), false)};
Quad root_quads[] = {Quad::SolidColorQuad(1, gfx::Rect(5, 5))};
Pass root_passes[] = {
Pass(secondary_quads, arraysize(secondary_quads), SurfaceSize()),
@@ -1870,8 +2043,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
aggregated_pass_list[1]
->shared_quad_state_list.ElementAt(1)
->clip_rect.ToString());
-
- middle_support->EvictCurrentSurface();
}
// Tests that damage rects are aggregated correctly when surfaces change.
@@ -1899,7 +2070,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
Quad parent_surface_quads[] = {
Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)};
+ gfx::Rect(5, 5), false)};
Pass parent_surface_passes[] = {Pass(
parent_surface_quads, arraysize(parent_surface_quads), 1, SurfaceSize())};
@@ -1917,7 +2088,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
Quad root_surface_quads[] = {
Quad::SurfaceQuad(parent_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)};
+ gfx::Rect(5, 5), false)};
Quad root_render_pass_quads[] = {Quad::RenderPassQuad(1)};
Pass root_passes[] = {
@@ -2042,8 +2213,212 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
EXPECT_TRUE(aggregated_pass_list[1]->damage_rect.Contains(
gfx::Rect(SurfaceSize())));
}
+}
+
+// Tests that damage rects are aggregated correctly when surfaces stretch to
+// fit and device size is less than 1.
+TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRectWithSquashToFit) {
+ auto parent_support = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot,
+ kNeedsSyncPoints);
+ Quad child_quads[] = {Quad::RenderPassQuad(1)};
+ Pass child_passes[] = {
+ Pass(child_quads, arraysize(child_quads), 1, gfx::Size(100, 100))};
+
+ CompositorFrame child_frame = MakeEmptyCompositorFrame();
+ AddPasses(&child_frame.render_pass_list, child_passes,
+ arraysize(child_passes));
+
+ auto* child_root_pass = child_frame.render_pass_list[0].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);
+
+ LocalSurfaceId child_local_surface_id = allocator_.GenerateId();
+ SurfaceId child_surface_id(child_support_->frame_sink_id(),
+ child_local_surface_id);
+ child_support_->SubmitCompositorFrame(child_local_surface_id,
+ std::move(child_frame));
+
+ Quad parent_surface_quads[] = {
+ Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
+ gfx::Rect(5, 5), false)};
+ Pass parent_surface_passes[] = {Pass(
+ parent_surface_quads, arraysize(parent_surface_quads), 1, SurfaceSize())};
+
+ // Parent surface is only used to test if the transform is applied correctly
+ // to the child surface's damage.
+ CompositorFrame parent_surface_frame = MakeEmptyCompositorFrame();
+ AddPasses(&parent_surface_frame.render_pass_list, parent_surface_passes,
+ arraysize(parent_surface_passes));
+
+ LocalSurfaceId parent_local_surface_id = allocator_.GenerateId();
+ SurfaceId parent_surface_id(parent_support->frame_sink_id(),
+ parent_local_surface_id);
+ parent_support->SubmitCompositorFrame(parent_local_surface_id,
+ std::move(parent_surface_frame));
+
+ Quad root_surface_quads[] = {
+ Quad::SurfaceQuad(parent_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
+ gfx::Rect(50, 50), true)};
+ Quad root_render_pass_quads[] = {Quad::RenderPassQuad(1)};
+
+ Pass root_passes[] = {
+ Pass(root_surface_quads, arraysize(root_surface_quads), 1, SurfaceSize()),
+ Pass(root_render_pass_quads, arraysize(root_render_pass_quads), 2,
+ SurfaceSize())};
+
+ CompositorFrame root_frame = MakeEmptyCompositorFrame();
+ AddPasses(&root_frame.render_pass_list, root_passes, arraysize(root_passes));
+
+ root_frame.render_pass_list[0]
+ ->shared_quad_state_list.front()
+ ->quad_to_target_transform.Translate(0, 10);
+ 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);
+
+ SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes),
+ root_local_surface_id_, 1.0f);
+
+ SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_);
+ CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id);
+
+ const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
+
+ ASSERT_EQ(2u, aggregated_pass_list.size());
+
+ // Damage rect for first aggregation should contain entire root surface.
+ EXPECT_TRUE(
+ aggregated_pass_list[1]->damage_rect.Contains(gfx::Rect(SurfaceSize())));
+
+ {
+ CompositorFrame child_frame = MakeEmptyCompositorFrame();
+ AddPasses(&child_frame.render_pass_list, child_passes,
+ arraysize(child_passes));
+
+ auto* child_root_pass = child_frame.render_pass_list[0].get();
+ child_root_pass->damage_rect = gfx::Rect(10, 20, 20, 30);
+
+ child_support_->SubmitCompositorFrame(child_local_surface_id,
+ std::move(child_frame));
+
+ SurfaceId root_surface_id(support_->frame_sink_id(),
+ root_local_surface_id_);
+ CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id);
+
+ const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
+
+ ASSERT_EQ(2u, aggregated_pass_list.size());
+
+ // 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.
+ EXPECT_EQ(gfx::Rect(5, 10, 10, 15).ToString(),
+ aggregated_pass_list[1]->damage_rect.ToString());
+ }
+}
+
+// Tests that damage rects are aggregated correctly when surfaces stretch to
+// fit and device size is greater than 1.
+TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRectWithStretchToFit) {
+ auto parent_support = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot,
+ kNeedsSyncPoints);
+ Quad child_quads[] = {Quad::RenderPassQuad(1)};
+ Pass child_passes[] = {
+ Pass(child_quads, arraysize(child_quads), 1, gfx::Size(100, 100))};
+
+ CompositorFrame child_frame = MakeEmptyCompositorFrame();
+ AddPasses(&child_frame.render_pass_list, child_passes,
+ arraysize(child_passes));
+
+ auto* child_root_pass = child_frame.render_pass_list[0].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);
+
+ LocalSurfaceId child_local_surface_id = allocator_.GenerateId();
+ SurfaceId child_surface_id(child_support_->frame_sink_id(),
+ child_local_surface_id);
+ child_support_->SubmitCompositorFrame(child_local_surface_id,
+ std::move(child_frame));
+
+ Quad parent_surface_quads[] = {
+ Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
+ gfx::Rect(5, 5), false)};
+ Pass parent_surface_passes[] = {Pass(
+ parent_surface_quads, arraysize(parent_surface_quads), 1, SurfaceSize())};
+
+ // Parent surface is only used to test if the transform is applied correctly
+ // to the child surface's damage.
+ CompositorFrame parent_surface_frame = MakeEmptyCompositorFrame();
+ AddPasses(&parent_surface_frame.render_pass_list, parent_surface_passes,
+ arraysize(parent_surface_passes));
+
+ LocalSurfaceId parent_local_surface_id = allocator_.GenerateId();
+ SurfaceId parent_surface_id(parent_support->frame_sink_id(),
+ parent_local_surface_id);
+ parent_support->SubmitCompositorFrame(parent_local_surface_id,
+ std::move(parent_surface_frame));
+
+ Quad root_surface_quads[] = {
+ Quad::SurfaceQuad(parent_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
+ gfx::Rect(200, 200), true)};
+ Quad root_render_pass_quads[] = {Quad::RenderPassQuad(1)};
+
+ Pass root_passes[] = {
+ Pass(root_surface_quads, arraysize(root_surface_quads), 1, SurfaceSize()),
+ Pass(root_render_pass_quads, arraysize(root_render_pass_quads), 2,
+ SurfaceSize())};
+
+ CompositorFrame root_frame = MakeEmptyCompositorFrame();
+ AddPasses(&root_frame.render_pass_list, root_passes, arraysize(root_passes));
+
+ root_frame.render_pass_list[0]
+ ->shared_quad_state_list.front()
+ ->quad_to_target_transform.Translate(0, 10);
+ 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);
+
+ SubmitCompositorFrame(support_.get(), root_passes, arraysize(root_passes),
+ root_local_surface_id_, 1.0f);
- parent_support->EvictCurrentSurface();
+ SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_);
+ CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id);
+
+ const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
+
+ ASSERT_EQ(2u, aggregated_pass_list.size());
+
+ // Damage rect for first aggregation should contain entire root surface.
+ EXPECT_TRUE(
+ aggregated_pass_list[1]->damage_rect.Contains(gfx::Rect(SurfaceSize())));
+
+ {
+ CompositorFrame child_frame = MakeEmptyCompositorFrame();
+ AddPasses(&child_frame.render_pass_list, child_passes,
+ arraysize(child_passes));
+
+ auto* child_root_pass = child_frame.render_pass_list[0].get();
+ child_root_pass->damage_rect = gfx::Rect(10, 15, 20, 30);
+
+ child_support_->SubmitCompositorFrame(child_local_surface_id,
+ std::move(child_frame));
+
+ SurfaceId root_surface_id(support_->frame_sink_id(),
+ root_local_surface_id_);
+ CompositorFrame aggregated_frame = aggregator_.Aggregate(root_surface_id);
+
+ const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
+
+ ASSERT_EQ(2u, aggregated_pass_list.size());
+
+ // 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.
+ EXPECT_EQ(gfx::Rect(20, 30, 40, 60).ToString(),
+ aggregated_pass_list[1]->damage_rect.ToString());
+ }
}
// Check that damage is correctly calculated for surfaces.
@@ -2174,7 +2549,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
{
Quad root_quads[] = {Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(),
- SK_ColorWHITE, gfx::Rect(5, 5), 1.f,
+ SK_ColorWHITE, gfx::Rect(5, 5),
false)};
Pass root_passes[] = {
@@ -2208,7 +2583,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
// Create a root surface with a smaller damage rect.
{
Quad root_quads[] = {Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(),
- SK_ColorWHITE, gfx::Rect(5, 5), 1.f,
+ SK_ColorWHITE, gfx::Rect(5, 5),
false)};
Pass root_passes[] = {
@@ -2311,7 +2686,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
int root_pass_ids[] = {1, 2, 3};
Quad root_quads1[] = {Quad::SurfaceQuad(child_surface_id,
InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)};
+ gfx::Rect(5, 5), false)};
Quad root_quads2[] = {Quad::RenderPassQuad(root_pass_ids[0])};
Quad root_quads3[] = {Quad::RenderPassQuad(root_pass_ids[1])};
Pass root_passes[] = {Pass(root_quads1, arraysize(root_quads1),
@@ -2363,7 +2738,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
Quad root_quads2[] = {
Quad::RenderPassQuad(root_pass_ids[0]),
Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)};
+ gfx::Rect(5, 5), false)};
Pass root_passes[] = {Pass(root_quads1, arraysize(root_quads1),
root_pass_ids[0], SurfaceSize()),
Pass(root_quads2, arraysize(root_quads2),
@@ -2414,7 +2789,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
Quad root_quads2[] = {
Quad::RenderPassQuad(root_pass_ids[0]),
Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)};
+ gfx::Rect(5, 5), false)};
Pass root_passes[] = {Pass(root_quads1, arraysize(root_quads1),
root_pass_ids[0], SurfaceSize()),
Pass(root_quads2, arraysize(root_quads2),
@@ -2457,7 +2832,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
class SurfaceAggregatorWithResourcesTest : public testing::Test {
public:
void SetUp() override {
- shared_bitmap_manager_ = std::make_unique<cc::TestSharedBitmapManager>();
+ shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
resource_provider_ =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
nullptr, shared_bitmap_manager_.get());
@@ -2548,8 +2923,6 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
}
EXPECT_THAT(returned_ids,
testing::WhenSorted(testing::ElementsAreArray(ids)));
-
- support->EvictCurrentSurface();
}
// This test verifies that when a CompositorFrame is submitted to a new surface
@@ -2589,8 +2962,6 @@ TEST_F(SurfaceAggregatorWithResourcesTest, ReturnResourcesAsSurfacesChange) {
}
EXPECT_THAT(returned_ids,
testing::WhenSorted(testing::ElementsAreArray(ids)));
-
- support->EvictCurrentSurface();
}
TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) {
@@ -2622,8 +2993,6 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) {
support.get(), surface_id);
ASSERT_EQ(1u, client.returned_resources().size());
EXPECT_EQ(11u, client.returned_resources()[0].id);
-
- support->EvictCurrentSurface();
}
TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) {
@@ -2664,9 +3033,6 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) {
EXPECT_THAT(returned_ids,
testing::WhenSorted(testing::ElementsAreArray(ids)));
EXPECT_EQ(3u, resource_provider_->num_resources());
-
- support1->EvictCurrentSurface();
- support2->EvictCurrentSurface();
}
// Ensure that aggregator completely ignores Surfaces that reference invalid
@@ -2722,10 +3088,6 @@ TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) {
ASSERT_EQ(1u, pass_list->size());
EXPECT_EQ(3u, pass_list->back()->shared_quad_state_list.size());
EXPECT_EQ(9u, pass_list->back()->quad_list.size());
-
- root_support->EvictCurrentSurface();
- middle_support->EvictCurrentSurface();
- child_support->EvictCurrentSurface();
}
TEST_F(SurfaceAggregatorWithResourcesTest, SecureOutputTexture) {
@@ -2733,6 +3095,7 @@ TEST_F(SurfaceAggregatorWithResourcesTest, SecureOutputTexture) {
nullptr, &manager_, FrameSinkId(1, 1), kChildIsRoot, kNeedsSyncPoints);
auto support2 = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, FrameSinkId(2, 2), kChildIsRoot, kNeedsSyncPoints);
+ support2->set_allow_copy_output_requests_for_testing();
LocalSurfaceId local_frame1_id(7u, base::UnguessableToken::Create());
SurfaceId surface1_id(support1->frame_sink_id(), local_frame1_id);
@@ -2788,9 +3151,6 @@ TEST_F(SurfaceAggregatorWithResourcesTest, SecureOutputTexture) {
// Output is insecure, so texture should be drawn.
EXPECT_EQ(DrawQuad::SOLID_COLOR, render_pass->quad_list.back()->material);
-
- support1->EvictCurrentSurface();
- support2->EvictCurrentSurface();
}
// Ensure that the render passes have correct color spaces.
@@ -2851,7 +3211,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageByChangingChildSurface) {
Quad root_surface_quads[] = {
Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)};
+ gfx::Rect(5, 5), false)};
Pass root_passes[] = {Pass(root_surface_quads, arraysize(root_surface_quads),
1, SurfaceSize())};
@@ -2927,7 +3287,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
Quad root_surface_quads[] = {
Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)};
+ gfx::Rect(5, 5), false)};
Pass root_passes[] = {Pass(root_surface_quads, arraysize(root_surface_quads),
1, SurfaceSize())};
@@ -2967,7 +3327,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
Quad new_child_surface_quads[] = {
child_surface_quads[0],
Quad::SurfaceQuad(grand_child_surface_id, InvalidSurfaceId(),
- SK_ColorWHITE, gfx::Rect(5, 5), 1.f, false)};
+ SK_ColorWHITE, gfx::Rect(5, 5), false)};
Pass new_child_surface_passes[] = {Pass(new_child_surface_quads,
arraysize(new_child_surface_quads),
1, SurfaceSize())};
@@ -3018,8 +3378,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
EXPECT_FALSE(aggregated_frame.render_pass_list[0]
->has_damage_from_contributing_content);
}
-
- grand_child_support->EvictCurrentSurface();
}
// Tests that has_damage_from_contributing_content is aggregated correctly from
@@ -3041,7 +3399,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageFromRenderPassQuads) {
Quad root_surface_quads[] = {
Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)};
+ gfx::Rect(5, 5), false)};
Quad root_render_pass_quads[] = {Quad::RenderPassQuad(1)};
Pass root_passes[] = {
@@ -3202,7 +3560,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
Quad root_surface_quads[] = {
Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)};
+ gfx::Rect(5, 5), false)};
Pass root_passes[] = {Pass(root_surface_quads, arraysize(root_surface_quads),
1, SurfaceSize())};
@@ -3324,7 +3682,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, NotIgnoreOutsideForCachedRenderPass) {
int pass_id[] = {1, 2};
Quad root_quads[][1] = {
{Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)},
+ gfx::Rect(5, 5), false)},
{Quad::RenderPassQuad(pass_id[0])},
};
Pass root_passes[] = {Pass(root_quads[0], arraysize(root_quads[0]),
@@ -3363,7 +3721,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, NotIgnoreOutsideForCachedRenderPass) {
int pass_id[] = {1, 2};
Quad root_quads[][1] = {
{Quad::SurfaceQuad(child_surface_id, InvalidSurfaceId(), SK_ColorWHITE,
- gfx::Rect(5, 5), 1.f, false)},
+ gfx::Rect(5, 5), false)},
{Quad::RenderPassQuad(pass_id[0])},
};
Pass root_passes[] = {Pass(root_quads[0], arraysize(root_quads[0]),
diff --git a/chromium/components/viz/service/display/sync_query_collection.cc b/chromium/components/viz/service/display/sync_query_collection.cc
new file mode 100644
index 00000000000..60af0839cec
--- /dev/null
+++ b/chromium/components/viz/service/display/sync_query_collection.cc
@@ -0,0 +1,148 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/service/display/sync_query_collection.h"
+
+#include "base/memory/weak_ptr.h"
+#include "cc/base/container_util.h"
+#include "components/viz/common/resources/resource_fence.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+
+namespace viz {
+namespace {
+// Block or crash if the number of pending sync queries reach this high as
+// something is seriously wrong on the service side if this happens.
+const size_t kMaxPendingSyncQueries = 16;
+} // anonymous namespace
+
+class SyncQuery {
+ public:
+ explicit SyncQuery(gpu::gles2::GLES2Interface* gl)
+ : gl_(gl), query_id_(0u), is_pending_(false), weak_ptr_factory_(this) {
+ gl_->GenQueriesEXT(1, &query_id_);
+ }
+ virtual ~SyncQuery() { gl_->DeleteQueriesEXT(1, &query_id_); }
+
+ scoped_refptr<ResourceFence> Begin() {
+ DCHECK(!IsPending());
+ // Invalidate weak pointer held by old fence.
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ // Note: In case the set of drawing commands issued before End() do not
+ // depend on the query, defer BeginQueryEXT call until Set() is called and
+ // query is required.
+ return base::MakeRefCounted<Fence>(weak_ptr_factory_.GetWeakPtr());
+ }
+
+ void Set() {
+ if (is_pending_)
+ return;
+
+ // Note: BeginQueryEXT on GL_COMMANDS_COMPLETED_CHROMIUM is effectively a
+ // noop relative to GL, so it doesn't matter where it happens but we still
+ // make sure to issue this command when Set() is called (prior to issuing
+ // any drawing commands that depend on query), in case some future extension
+ // can take advantage of this.
+ gl_->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query_id_);
+ is_pending_ = true;
+ }
+
+ void End() {
+ if (!is_pending_)
+ return;
+
+ gl_->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
+ }
+
+ bool IsPending() {
+ if (!is_pending_)
+ return false;
+
+ unsigned result_available = 1;
+ gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_AVAILABLE_EXT,
+ &result_available);
+ is_pending_ = !result_available;
+ return is_pending_;
+ }
+
+ void Wait() {
+ if (!is_pending_)
+ return;
+
+ unsigned result = 0;
+ gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &result);
+ is_pending_ = false;
+ }
+
+ private:
+ class Fence : public ResourceFence {
+ public:
+ explicit Fence(base::WeakPtr<SyncQuery> query) : query_(query) {}
+
+ // ResourceFence implementation.
+ void Set() override {
+ DCHECK(query_);
+ query_->Set();
+ }
+ bool HasPassed() override { return !query_ || !query_->IsPending(); }
+ void Wait() override {
+ if (query_)
+ query_->Wait();
+ }
+
+ private:
+ ~Fence() override {}
+
+ base::WeakPtr<SyncQuery> query_;
+
+ DISALLOW_COPY_AND_ASSIGN(Fence);
+ };
+
+ gpu::gles2::GLES2Interface* gl_;
+ unsigned query_id_;
+ bool is_pending_;
+ base::WeakPtrFactory<SyncQuery> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyncQuery);
+};
+
+SyncQueryCollection::SyncQueryCollection(gpu::gles2::GLES2Interface* gl)
+ : gl_(gl) {}
+
+SyncQueryCollection::~SyncQueryCollection() = default;
+SyncQueryCollection::SyncQueryCollection(SyncQueryCollection&&) = default;
+SyncQueryCollection& SyncQueryCollection::operator=(SyncQueryCollection&&) =
+ default;
+
+scoped_refptr<ResourceFence> SyncQueryCollection::StartNewFrame() {
+ // Block until oldest sync query has passed if the number of pending queries
+ // ever reach kMaxPendingSyncQueries.
+ if (pending_sync_queries_.size() >= kMaxPendingSyncQueries) {
+ LOG(ERROR) << "Reached limit of pending sync queries.";
+
+ pending_sync_queries_.front()->Wait();
+ DCHECK(!pending_sync_queries_.front()->IsPending());
+ }
+
+ while (!pending_sync_queries_.empty()) {
+ if (pending_sync_queries_.front()->IsPending())
+ break;
+
+ available_sync_queries_.push_back(cc::PopFront(&pending_sync_queries_));
+ }
+
+ current_sync_query_ = available_sync_queries_.empty()
+ ? std::make_unique<SyncQuery>(gl_)
+ : cc::PopFront(&available_sync_queries_);
+
+ return current_sync_query_->Begin();
+}
+
+void SyncQueryCollection::EndCurrentFrame() {
+ DCHECK(current_sync_query_);
+ current_sync_query_->End();
+ pending_sync_queries_.push_back(std::move(current_sync_query_));
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display/sync_query_collection.h b/chromium/components/viz/service/display/sync_query_collection.h
new file mode 100644
index 00000000000..eaf1d17278a
--- /dev/null
+++ b/chromium/components/viz/service/display/sync_query_collection.h
@@ -0,0 +1,41 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_SYNC_QUERY_COLLECTION_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_SYNC_QUERY_COLLECTION_H_
+
+#include <memory>
+
+#include "base/containers/circular_deque.h"
+#include "base/memory/ref_counted.h"
+
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+} // namespace gpu
+
+namespace viz {
+class SyncQuery;
+class ResourceFence;
+
+class SyncQueryCollection {
+ public:
+ explicit SyncQueryCollection(gpu::gles2::GLES2Interface* gl);
+ SyncQueryCollection(SyncQueryCollection&&);
+ SyncQueryCollection& operator=(SyncQueryCollection&&);
+ ~SyncQueryCollection();
+ scoped_refptr<ResourceFence> StartNewFrame();
+ void EndCurrentFrame();
+
+ private:
+ base::circular_deque<std::unique_ptr<SyncQuery>> pending_sync_queries_;
+ base::circular_deque<std::unique_ptr<SyncQuery>> available_sync_queries_;
+ std::unique_ptr<SyncQuery> current_sync_query_;
+ gpu::gles2::GLES2Interface* gl_;
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_SYNC_QUERY_COLLECTION_H_
diff --git a/chromium/components/viz/service/display/texture_deleter.cc b/chromium/components/viz/service/display/texture_deleter.cc
index e24b61b63ba..32416c4889f 100644
--- a/chromium/components/viz/service/display/texture_deleter.cc
+++ b/chromium/components/viz/service/display/texture_deleter.cc
@@ -5,6 +5,7 @@
#include "components/viz/service/display/texture_deleter.h"
#include <stddef.h>
+#include <utility>
#include "base/bind.h"
#include "base/location.h"
@@ -72,8 +73,8 @@ std::unique_ptr<SingleReleaseCallback> TextureDeleter::GetReleaseCallback(
std::unique_ptr<SingleReleaseCallback> main_callback;
if (impl_task_runner_) {
main_callback = SingleReleaseCallback::Create(
- base::Bind(&PostTaskFromMainToImplThread, impl_task_runner_,
- base::Passed(&run_impl_callback)));
+ base::BindOnce(&PostTaskFromMainToImplThread, impl_task_runner_,
+ std::move(run_impl_callback)));
} else {
main_callback = SingleReleaseCallback::Create(std::move(run_impl_callback));
}
diff --git a/chromium/components/viz/service/display/texture_deleter_unittest.cc b/chromium/components/viz/service/display/texture_deleter_unittest.cc
index 6f95181891d..e33a26eacd3 100644
--- a/chromium/components/viz/service/display/texture_deleter_unittest.cc
+++ b/chromium/components/viz/service/display/texture_deleter_unittest.cc
@@ -6,9 +6,9 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "cc/test/test_context_provider.h"
-#include "cc/test/test_web_graphics_context_3d.h"
#include "components/viz/common/resources/single_release_callback.h"
+#include "components/viz/test/test_context_provider.h"
+#include "components/viz/test/test_web_graphics_context_3d.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace viz {
@@ -18,8 +18,8 @@ TEST(TextureDeleterTest, Destroy) {
auto deleter =
std::make_unique<TextureDeleter>(base::ThreadTaskRunnerHandle::Get());
- scoped_refptr<cc::TestContextProvider> context_provider =
- cc::TestContextProvider::Create();
+ scoped_refptr<TestContextProvider> context_provider =
+ TestContextProvider::Create();
context_provider->BindToCurrentThread();
GLuint texture_id = 0u;
@@ -47,8 +47,8 @@ TEST(TextureDeleterTest, Destroy) {
TEST(TextureDeleterTest, NullTaskRunner) {
auto deleter = std::make_unique<TextureDeleter>(nullptr);
- scoped_refptr<cc::TestContextProvider> context_provider =
- cc::TestContextProvider::Create();
+ scoped_refptr<TestContextProvider> context_provider =
+ TestContextProvider::Create();
context_provider->BindToCurrentThread();
GLuint texture_id = 0u;
diff --git a/chromium/components/viz/service/display_embedder/DEPS b/chromium/components/viz/service/display_embedder/DEPS
index bcb4c01e275..5fc1a52037e 100644
--- a/chromium/components/viz/service/display_embedder/DEPS
+++ b/chromium/components/viz/service/display_embedder/DEPS
@@ -1,9 +1,16 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+cc/base",
"+cc/ipc",
"+cc/output",
"+cc/resources",
"+cc/scheduler",
+ "+components/viz/service/display/output_surface_client.h",
+ "+components/viz/service/display/output_surface_frame.h",
+ "+components/viz/service/display/output_surface.h",
+ "+components/viz/service/display/overlay_candidate_validator.h",
+ "+components/viz/service/display/software_output_device.h",
"+gpu/GLES2",
"+gpu/command_buffer/client",
"+gpu/command_buffer/common",
@@ -21,6 +28,13 @@ include_rules = [
"+ui/gl",
"+ui/latency",
"+ui/ozone/public",
+
+ # TODO(danakj): Double check the layering for these dependencies.
+ "+components/viz/service/display/overlay_processor.h",
+ "+components/viz/service/display/overlay_strategy_fullscreen.h",
+ "+components/viz/service/display/overlay_strategy_single_on_top.h",
+ "+components/viz/service/display/overlay_strategy_underlay_cast.h",
+ "+components/viz/service/display/overlay_strategy_underlay.h",
]
specific_include_rules = {
@@ -28,6 +42,15 @@ specific_include_rules = {
"+cc/test",
"+third_party/khronos/GLES2",
],
+ # TODO(kylechar): Move this class to components/viz/service/frame_sinks/.
+ "external_begin_frame_controller_impl.h": [
+ "+components/viz/service/display/display.h",
+ ],
+ # TODO(kylechar): Break these dependencies.
+ "gpu_display_provider.cc": [
+ "+components/viz/service/display/display.h",
+ "+components/viz/service/display/display_scheduler.h",
+ ],
"software_output_device_ozone_unittest.cc": [
"+ui/compositor",
"+ui/gl",
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 7a2e1dd64bb..ff4221f1094 100644
--- a/chromium/components/viz/service/display_embedder/buffer_queue_unittest.cc
+++ b/chromium/components/viz/service/display_embedder/buffer_queue_unittest.cc
@@ -12,10 +12,10 @@
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
-#include "cc/test/test_context_provider.h"
-#include "cc/test/test_web_graphics_context_3d.h"
#include "components/viz/common/gl_helper.h"
+#include "components/viz/test/test_context_provider.h"
#include "components/viz/test/test_gpu_memory_buffer_manager.h"
+#include "components/viz/test/test_web_graphics_context_3d.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -115,12 +115,10 @@ class BufferQueueTest : public ::testing::Test {
public:
BufferQueueTest() : doublebuffering_(true), first_frame_(true) {}
- void SetUp() override {
- InitWithContext(cc::TestWebGraphicsContext3D::Create());
- }
+ void SetUp() override { InitWithContext(TestWebGraphicsContext3D::Create()); }
- void InitWithContext(std::unique_ptr<cc::TestWebGraphicsContext3D> context) {
- context_provider_ = cc::TestContextProvider::Create(std::move(context));
+ void InitWithContext(std::unique_ptr<TestWebGraphicsContext3D> context) {
+ context_provider_ = TestContextProvider::Create(std::move(context));
context_provider_->BindToCurrentThread();
gpu_memory_buffer_manager_.reset(new StubGpuMemoryBufferManager);
mock_output_surface_ = new MockBufferQueue(context_provider_->ContextGL(),
@@ -203,7 +201,7 @@ class BufferQueueTest : public ::testing::Test {
return true;
}
- scoped_refptr<cc::TestContextProvider> context_provider_;
+ scoped_refptr<TestContextProvider> context_provider_;
std::unique_ptr<StubGpuMemoryBufferManager> gpu_memory_buffer_manager_;
std::unique_ptr<BufferQueue> output_surface_;
MockBufferQueue* mock_output_surface_;
@@ -223,7 +221,7 @@ GLuint CreateImageDefault() {
return ++id;
}
-class MockedContext : public cc::TestWebGraphicsContext3D {
+class MockedContext : public TestWebGraphicsContext3D {
public:
MockedContext() {
ON_CALL(*this, createImageCHROMIUM(_, _, _, _))
@@ -243,19 +241,19 @@ class BufferQueueMockedContextTest : public BufferQueueTest {
public:
void SetUp() override {
context_ = new MockedContext();
- InitWithContext(std::unique_ptr<cc::TestWebGraphicsContext3D>(context_));
+ InitWithContext(std::unique_ptr<TestWebGraphicsContext3D>(context_));
}
protected:
MockedContext* context_;
};
-scoped_refptr<cc::TestContextProvider> CreateMockedContextProvider(
+scoped_refptr<TestContextProvider> CreateMockedContextProvider(
MockedContext** context) {
std::unique_ptr<MockedContext> owned_context(new MockedContext);
*context = owned_context.get();
- scoped_refptr<cc::TestContextProvider> context_provider =
- cc::TestContextProvider::Create(std::move(owned_context));
+ scoped_refptr<TestContextProvider> context_provider =
+ TestContextProvider::Create(std::move(owned_context));
context_provider->BindToCurrentThread();
return context_provider;
}
@@ -273,7 +271,7 @@ std::unique_ptr<BufferQueue> CreateBufferQueue(
TEST(BufferQueueStandaloneTest, FboInitialization) {
MockedContext* context;
- scoped_refptr<cc::TestContextProvider> context_provider =
+ scoped_refptr<TestContextProvider> context_provider =
CreateMockedContextProvider(&context);
std::unique_ptr<StubGpuMemoryBufferManager> gpu_memory_buffer_manager(
new StubGpuMemoryBufferManager);
@@ -294,7 +292,7 @@ TEST(BufferQueueStandaloneTest, FboBinding) {
GLenum target = targets[i];
MockedContext* context;
- scoped_refptr<cc::TestContextProvider> context_provider =
+ scoped_refptr<TestContextProvider> context_provider =
CreateMockedContextProvider(&context);
std::unique_ptr<StubGpuMemoryBufferManager> gpu_memory_buffer_manager(
new StubGpuMemoryBufferManager);
@@ -322,8 +320,8 @@ TEST(BufferQueueStandaloneTest, FboBinding) {
}
TEST(BufferQueueStandaloneTest, CheckBoundFramebuffer) {
- scoped_refptr<cc::TestContextProvider> context_provider =
- cc::TestContextProvider::Create();
+ scoped_refptr<TestContextProvider> context_provider =
+ TestContextProvider::Create();
context_provider->BindToCurrentThread();
std::unique_ptr<StubGpuMemoryBufferManager> gpu_memory_buffer_manager;
std::unique_ptr<BufferQueue> output_surface;
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_mac.cc b/chromium/components/viz/service/display_embedder/gl_output_surface_mac.cc
index 4d0c3f84e46..e1a1c23f4dd 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_mac.cc
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_mac.cc
@@ -8,16 +8,12 @@
namespace viz {
-namespace {
-// TODO(ccameron): Plumb this appropriately.
-const bool kDisableRemoteCoreAnimation = false;
-} // namespace
-
GLOutputSurfaceMac::GLOutputSurfaceMac(
scoped_refptr<InProcessContextProvider> context_provider,
gpu::SurfaceHandle surface_handle,
SyntheticBeginFrameSource* synthetic_begin_frame_source,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ bool allow_overlays)
: GLOutputSurfaceBufferQueue(context_provider,
surface_handle,
synthetic_begin_frame_source,
@@ -25,8 +21,8 @@ GLOutputSurfaceMac::GLOutputSurfaceMac(
GL_TEXTURE_RECTANGLE_ARB,
GL_RGBA,
gfx::BufferFormat::RGBA_8888),
- overlay_validator_(new CompositorOverlayCandidateValidatorMac(
- kDisableRemoteCoreAnimation)) {}
+ overlay_validator_(
+ new CompositorOverlayCandidateValidatorMac(!allow_overlays)) {}
GLOutputSurfaceMac::~GLOutputSurfaceMac() {}
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_mac.h b/chromium/components/viz/service/display_embedder/gl_output_surface_mac.h
index 6a9cee3c94f..f26801f584b 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_mac.h
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_mac.h
@@ -15,7 +15,8 @@ class GLOutputSurfaceMac : public GLOutputSurfaceBufferQueue {
GLOutputSurfaceMac(scoped_refptr<InProcessContextProvider> context_provider,
gpu::SurfaceHandle surface_handle,
SyntheticBeginFrameSource* synthetic_begin_frame_source,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ bool allow_overlays);
~GLOutputSurfaceMac() override;
private:
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_win.cc b/chromium/components/viz/service/display_embedder/gl_output_surface_win.cc
new file mode 100644
index 00000000000..da3fde6007a
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_win.cc
@@ -0,0 +1,29 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/service/display_embedder/gl_output_surface_win.h"
+
+#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.h"
+
+namespace viz {
+
+GLOutputSurfaceWin::GLOutputSurfaceWin(
+ scoped_refptr<InProcessContextProvider> context_provider,
+ SyntheticBeginFrameSource* synthetic_begin_frame_source,
+ bool use_overlays)
+ : GLOutputSurface(context_provider, synthetic_begin_frame_source) {
+ if (use_overlays) {
+ overlay_validator_ =
+ std::make_unique<CompositorOverlayCandidateValidatorWin>();
+ }
+}
+
+GLOutputSurfaceWin::~GLOutputSurfaceWin() = default;
+
+OverlayCandidateValidator* GLOutputSurfaceWin::GetOverlayCandidateValidator()
+ const {
+ return overlay_validator_.get();
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_win.h b/chromium/components/viz/service/display_embedder/gl_output_surface_win.h
new file mode 100644
index 00000000000..c62a7498b47
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_win.h
@@ -0,0 +1,35 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_GL_OUTPUT_SURFACE_WIN_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_GL_OUTPUT_SURFACE_WIN_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "components/viz/service/display_embedder/gl_output_surface.h"
+
+namespace viz {
+
+class CompositorOverlayCandidateValidatorWin;
+
+class GLOutputSurfaceWin : public GLOutputSurface {
+ public:
+ GLOutputSurfaceWin(scoped_refptr<InProcessContextProvider> context_provider,
+ SyntheticBeginFrameSource* synthetic_begin_frame_source,
+ bool use_overlays);
+ ~GLOutputSurfaceWin() override;
+
+ // GLOutputSurface implementation:
+ OverlayCandidateValidator* GetOverlayCandidateValidator() const override;
+
+ private:
+ std::unique_ptr<CompositorOverlayCandidateValidatorWin> overlay_validator_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLOutputSurfaceWin);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_GL_OUTPUT_SURFACE_WIN_H_
diff --git a/chromium/components/viz/service/display_embedder/gpu_display_provider.cc b/chromium/components/viz/service/display_embedder/gpu_display_provider.cc
index 49a55dabfcd..6d2a3ad1002 100644
--- a/chromium/components/viz/service/display_embedder/gpu_display_provider.cc
+++ b/chromium/components/viz/service/display_embedder/gpu_display_provider.cc
@@ -29,12 +29,14 @@
#include "ui/base/ui_base_switches.h"
#if defined(OS_WIN)
+#include "components/viz/service/display_embedder/gl_output_surface_win.h"
#include "components/viz/service/display_embedder/software_output_device_win.h"
#endif
#if defined(OS_MACOSX)
#include "components/viz/service/display_embedder/gl_output_surface_mac.h"
#include "components/viz/service/display_embedder/software_output_device_mac.h"
+#include "ui/base/cocoa/remote_layer_api.h"
#endif
#if defined(USE_X11)
@@ -141,13 +143,23 @@ std::unique_ptr<Display> GpuDisplayProvider::CreateDisplay(
#elif defined(OS_MACOSX)
output_surface = std::make_unique<GLOutputSurfaceMac>(
std::move(context_provider), surface_handle,
- synthetic_begin_frame_source.get(), gpu_memory_buffer_manager_.get());
+ synthetic_begin_frame_source.get(), gpu_memory_buffer_manager_.get(),
+ renderer_settings.allow_overlays);
#else
NOTREACHED();
#endif
} else {
+#if defined(OS_WIN)
+ const auto& capabilities = context_provider->ContextCapabilities();
+ const bool use_overlays =
+ capabilities.dc_layers && capabilities.use_dc_overlays_for_video;
+ output_surface = std::make_unique<GLOutputSurfaceWin>(
+ std::move(context_provider), synthetic_begin_frame_source.get(),
+ use_overlays);
+#else
output_surface = std::make_unique<GLOutputSurface>(
std::move(context_provider), synthetic_begin_frame_source.get());
+#endif
}
}
@@ -157,7 +169,7 @@ std::unique_ptr<Display> GpuDisplayProvider::CreateDisplay(
auto scheduler = std::make_unique<DisplayScheduler>(
display_begin_frame_source, task_runner_.get(), max_frames_pending);
- // The ownership of the BeginFrameSource is transfered to the caller.
+ // The ownership of the BeginFrameSource is transferred to the caller.
*out_begin_frame_source = std::move(synthetic_begin_frame_source);
return std::make_unique<Display>(
@@ -171,8 +183,8 @@ GpuDisplayProvider::CreateSoftwareOutputDeviceForPlatform(
#if defined(OS_WIN)
if (!output_device_backing_)
output_device_backing_ = std::make_unique<OutputDeviceBacking>();
- auto device = std::make_unique<SoftwareOutputDeviceWin>(
- output_device_backing_.get(), widget);
+ return std::make_unique<SoftwareOutputDeviceWin>(output_device_backing_.get(),
+ widget);
#elif defined(OS_MACOSX)
// TODO(crbug.com/730660): We don't have a widget here, so what do we do to
// get something we can draw to? Can we use an IO surface? Can we use CA
@@ -182,25 +194,23 @@ GpuDisplayProvider::CreateSoftwareOutputDeviceForPlatform(
// Part of the SoftwareOutputDeviceMac::EndPaint probably needs to move to
// the browser process, and we need to set up transport of an IO surface to
// here?
- // auto device = std::make_unique<SoftwareOutputDeviceMac>(widget);
- std::unique_ptr<SoftwareOutputDevice> device;
+ // return std::make_unique<SoftwareOutputDeviceMac>(widget);
NOTIMPLEMENTED();
+ return nullptr;
#elif defined(OS_ANDROID)
// Android does not do software compositing, so we can't get here.
- std::unique_ptr<SoftwareOutputDevice> device;
NOTREACHED();
+ return nullptr;
#elif defined(USE_OZONE)
ui::SurfaceFactoryOzone* factory =
ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone();
std::unique_ptr<ui::SurfaceOzoneCanvas> surface_ozone =
factory->CreateCanvasForWidget(widget);
CHECK(surface_ozone);
- auto device =
- std::make_unique<SoftwareOutputDeviceOzone>(std::move(surface_ozone));
+ return std::make_unique<SoftwareOutputDeviceOzone>(std::move(surface_ozone));
#elif defined(USE_X11)
- auto device = std::make_unique<SoftwareOutputDeviceX11>(widget);
+ return std::make_unique<SoftwareOutputDeviceX11>(widget);
#endif
- return device;
}
} // namespace viz
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 fd4d44d5266..b562540ea91 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
@@ -5,6 +5,7 @@
#include "components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.h"
#include "gpu/ipc/client/gpu_memory_buffer_impl.h"
+#include "gpu/ipc/in_process_command_buffer.h"
#include "gpu/ipc/service/gpu_channel_manager.h"
#include "gpu/ipc/service/gpu_memory_buffer_factory.h"
@@ -12,7 +13,9 @@ namespace viz {
InProcessGpuMemoryBufferManager::InProcessGpuMemoryBufferManager(
gpu::GpuChannelManager* channel_manager)
- : client_id_(1), channel_manager_(channel_manager), weak_factory_(this) {
+ : client_id_(gpu::InProcessCommandBuffer::kGpuMemoryBufferClientId),
+ channel_manager_(channel_manager),
+ weak_factory_(this) {
weak_ptr_ = weak_factory_.GetWeakPtr();
}
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 5bf500a74d6..9477a5aa45f 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
@@ -14,6 +14,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/process_memory_dump.h"
+#include "mojo/public/cpp/system/platform_handle.h"
#include "ui/gfx/geometry/size.h"
namespace viz {
@@ -120,6 +121,52 @@ std::unique_ptr<SharedBitmap> ServerSharedBitmapManager::GetSharedBitmapFromId(
static_cast<uint8_t*>(data->memory->memory()), data, id, nullptr);
}
+bool ServerSharedBitmapManager::ChildAllocatedSharedBitmap(
+ mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) {
+ base::SharedMemoryHandle memory_handle;
+ size_t buffer_size;
+ MojoResult result = mojo::UnwrapSharedMemoryHandle(
+ std::move(buffer), &memory_handle, &buffer_size, nullptr);
+ DCHECK_EQ(result, MOJO_RESULT_OK);
+
+ auto data = base::MakeRefCounted<BitmapData>(buffer_size);
+ data->memory = std::make_unique<base::SharedMemory>(memory_handle, false);
+ // Map the memory to get a pointer to it, then close it to free up the fd so
+ // it can be reused. This doesn't unmap the memory. Some OS have a very
+ // limited number of fds and this avoids consuming them all.
+ data->memory->Map(data->buffer_size);
+ data->memory->Close();
+
+ base::AutoLock lock(lock_);
+ if (handle_map_.find(id) != handle_map_.end())
+ return false;
+ handle_map_[id] = std::move(data);
+ return true;
+}
+
+bool ServerSharedBitmapManager::ChildAllocatedSharedBitmapForTest(
+ size_t buffer_size,
+ const base::SharedMemoryHandle& memory_handle,
+ const SharedBitmapId& id) {
+ auto data = base::MakeRefCounted<BitmapData>(buffer_size);
+ data->memory = std::make_unique<base::SharedMemory>(memory_handle, false);
+ data->memory->Map(data->buffer_size);
+ data->memory->Close();
+
+ base::AutoLock lock(lock_);
+ if (handle_map_.find(id) != handle_map_.end())
+ return false;
+ handle_map_[id] = std::move(data);
+ return true;
+}
+
+void ServerSharedBitmapManager::ChildDeletedSharedBitmap(
+ const SharedBitmapId& id) {
+ base::AutoLock lock(lock_);
+ handle_map_.erase(id);
+}
+
bool ServerSharedBitmapManager::OnMemoryDump(
const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) {
@@ -157,27 +204,6 @@ bool ServerSharedBitmapManager::OnMemoryDump(
return true;
}
-bool ServerSharedBitmapManager::ChildAllocatedSharedBitmap(
- size_t buffer_size,
- const base::SharedMemoryHandle& handle,
- const SharedBitmapId& id) {
- base::AutoLock lock(lock_);
- if (handle_map_.find(id) != handle_map_.end())
- return false;
- auto data = base::MakeRefCounted<BitmapData>(buffer_size);
- data->memory = std::make_unique<base::SharedMemory>(handle, false);
- data->memory->Map(data->buffer_size);
- data->memory->Close();
- handle_map_[id] = std::move(data);
- return true;
-}
-
-void ServerSharedBitmapManager::ChildDeletedSharedBitmap(
- const SharedBitmapId& id) {
- base::AutoLock lock(lock_);
- handle_map_.erase(id);
-}
-
size_t ServerSharedBitmapManager::AllocatedBitmapCount() const {
base::AutoLock lock(lock_);
return handle_map_.size();
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 ebffeabcc09..369bec8bf9d 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
@@ -40,23 +40,22 @@ class VIZ_SERVICE_EXPORT ServerSharedBitmapManager
std::unique_ptr<SharedBitmap> GetSharedBitmapFromId(
const gfx::Size& size,
const SharedBitmapId&) override;
+ bool ChildAllocatedSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) override;
+ void ChildDeletedSharedBitmap(const SharedBitmapId& id) override;
// base::trace_event::MemoryDumpProvider implementation.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
size_t AllocatedBitmapCount() const;
-
void FreeSharedMemoryFromMap(const SharedBitmapId& id);
- private:
- friend class SharedBitmapAllocationNotifierImpl;
-
- bool ChildAllocatedSharedBitmap(size_t buffer_size,
- const base::SharedMemoryHandle& handle,
- const SharedBitmapId& id);
- void ChildDeletedSharedBitmap(const SharedBitmapId& id);
+ bool ChildAllocatedSharedBitmapForTest(size_t buffer_size,
+ const base::SharedMemoryHandle& handle,
+ const SharedBitmapId& id);
+ private:
mutable base::Lock lock_;
std::unordered_map<SharedBitmapId,
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 66ee4183dc4..662e0207815 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
@@ -5,6 +5,7 @@
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h"
+#include "mojo/public/cpp/system/platform_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace viz {
@@ -35,7 +36,10 @@ TEST_F(ServerSharedBitmapManagerTest, TestCreate) {
SharedBitmapAllocationNotifierImpl notifier(manager());
base::SharedMemoryHandle handle = bitmap->handle().Duplicate();
- notifier.ChildAllocatedSharedBitmap(size_in_bytes, handle, id);
+ mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
+ handle, size_in_bytes,
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
+ notifier.ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
std::unique_ptr<SharedBitmap> large_bitmap;
large_bitmap = manager()->GetSharedBitmapFromId(gfx::Size(1024, 1024), id);
@@ -97,7 +101,10 @@ TEST_F(ServerSharedBitmapManagerTest, ServiceDestroyed) {
{
SharedBitmapAllocationNotifierImpl notifier(manager());
base::SharedMemoryHandle handle = bitmap->handle().Duplicate();
- notifier.ChildAllocatedSharedBitmap(size_in_bytes, handle, id);
+ mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
+ handle, size_in_bytes,
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
+ notifier.ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
shared_bitmap = manager()->GetSharedBitmapFromId(bitmap_size, id);
ASSERT_TRUE(shared_bitmap.get() != nullptr);
@@ -125,13 +132,20 @@ TEST_F(ServerSharedBitmapManagerTest, AddDuplicate) {
SharedBitmapAllocationNotifierImpl notifier(manager());
base::SharedMemoryHandle handle = bitmap->handle().Duplicate();
- notifier.ChildAllocatedSharedBitmap(size_in_bytes, handle, id);
+ mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
+ handle, size_in_bytes,
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
+ notifier.ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
std::unique_ptr<base::SharedMemory> bitmap2(new base::SharedMemory());
bitmap2->CreateAndMapAnonymous(size_in_bytes);
memset(bitmap2->memory(), 0x00, size_in_bytes);
- notifier.ChildAllocatedSharedBitmap(size_in_bytes, bitmap2->handle(), id);
+ base::SharedMemoryHandle handle2 = bitmap->handle().Duplicate();
+ buffer_handle = mojo::WrapSharedMemoryHandle(
+ handle2, size_in_bytes,
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
+ notifier.ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
std::unique_ptr<SharedBitmap> shared_bitmap;
shared_bitmap = manager()->GetSharedBitmapFromId(bitmap_size, id);
@@ -154,7 +168,10 @@ TEST_F(ServerSharedBitmapManagerTest, SharedMemoryHandle) {
SharedBitmapAllocationNotifierImpl notifier(manager());
base::SharedMemoryHandle handle = bitmap->handle().Duplicate();
- notifier.ChildAllocatedSharedBitmap(size_in_bytes, handle, id);
+ mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
+ handle, size_in_bytes,
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
+ notifier.ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
std::unique_ptr<SharedBitmap> shared_bitmap;
shared_bitmap = manager()->GetSharedBitmapFromId(gfx::Size(1, 1), id);
diff --git a/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc b/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc
index 13dc24f4f00..fa5468d37a3 100644
--- a/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc
+++ b/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc
@@ -35,15 +35,10 @@ void SharedBitmapAllocationNotifierImpl::DidAllocateSharedBitmap(
mojo::ScopedSharedBufferHandle buffer,
const SharedBitmapId& id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- base::SharedMemoryHandle memory_handle;
- size_t size;
- MojoResult result = mojo::UnwrapSharedMemoryHandle(
- std::move(buffer), &memory_handle, &size, nullptr);
- DCHECK_EQ(result, MOJO_RESULT_OK);
- this->ChildAllocatedSharedBitmap(size, memory_handle, id);
+ this->ChildAllocatedSharedBitmap(std::move(buffer), id);
last_sequence_number_++;
for (SharedBitmapAllocationObserver& observer : observers_)
- observer.DidAllocateSharedBitmap(last_sequence_number_);
+ observer.OnSharedBitmapAllocatedByChild(last_sequence_number_);
}
void SharedBitmapAllocationNotifierImpl::DidDeleteSharedBitmap(
@@ -54,11 +49,10 @@ void SharedBitmapAllocationNotifierImpl::DidDeleteSharedBitmap(
}
void SharedBitmapAllocationNotifierImpl::ChildAllocatedSharedBitmap(
- size_t buffer_size,
- const base::SharedMemoryHandle& handle,
+ mojo::ScopedSharedBufferHandle buffer,
const SharedBitmapId& id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (manager_->ChildAllocatedSharedBitmap(buffer_size, handle, id))
+ if (manager_->ChildAllocatedSharedBitmap(std::move(buffer), id))
owned_bitmaps_.insert(id);
}
diff --git a/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h b/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h
index cd3faf241ae..0b4e32ddaf8 100644
--- a/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h
+++ b/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h
@@ -19,7 +19,7 @@ class ServerSharedBitmapManager;
class SharedBitmapAllocationObserver {
public:
- virtual void DidAllocateSharedBitmap(uint32_t sequence_number) = 0;
+ virtual void OnSharedBitmapAllocatedByChild(uint32_t sequence_number) = 0;
};
class VIZ_SERVICE_EXPORT SharedBitmapAllocationNotifierImpl
@@ -40,8 +40,7 @@ class VIZ_SERVICE_EXPORT SharedBitmapAllocationNotifierImpl
const SharedBitmapId& id) override;
void DidDeleteSharedBitmap(const SharedBitmapId& id) override;
- void ChildAllocatedSharedBitmap(size_t buffer_size,
- const base::SharedMemoryHandle& handle,
+ void ChildAllocatedSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
const SharedBitmapId& id);
void ChildDied();
diff --git a/chromium/components/viz/service/display_embedder/software_output_device_mac.cc b/chromium/components/viz/service/display_embedder/software_output_device_mac.cc
index ed3b7707402..b256bf2d60f 100644
--- a/chromium/components/viz/service/display_embedder/software_output_device_mac.cc
+++ b/chromium/components/viz/service/display_embedder/software_output_device_mac.cc
@@ -222,7 +222,11 @@ bool SoftwareOutputDeviceMac::GetVSyncParametersIfAvailable(
return false;
}
-bool SoftwareOutputDeviceMac::SupportGetVSyncParametersIfAvailable() {
+bool SoftwareOutputDeviceMac::SupportGetVSyncParametersIfAvailable() const {
+ return false;
+}
+
+bool SoftwareOutputDeviceMac::IsHWClock() const {
return false;
}
diff --git a/chromium/components/viz/service/display_embedder/software_output_device_mac.h b/chromium/components/viz/service/display_embedder/software_output_device_mac.h
index 0a4ebe52d4f..4066ac56600 100644
--- a/chromium/components/viz/service/display_embedder/software_output_device_mac.h
+++ b/chromium/components/viz/service/display_embedder/software_output_device_mac.h
@@ -40,7 +40,8 @@ class VIZ_SERVICE_EXPORT SoftwareOutputDeviceMac : public SoftwareOutputDevice,
const gfx::VSyncProvider::UpdateVSyncCallback& callback) override;
bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase,
base::TimeDelta* interval) override;
- bool SupportGetVSyncParametersIfAvailable() override;
+ bool SupportGetVSyncParametersIfAvailable() const override;
+ bool IsHWClock() const override;
// Testing methods.
SkRegion LastCopyRegionForTesting() const {
diff --git a/chromium/components/viz/service/frame_sinks/DEPS b/chromium/components/viz/service/frame_sinks/DEPS
index 7b7b9b0af38..90500834623 100644
--- a/chromium/components/viz/service/frame_sinks/DEPS
+++ b/chromium/components/viz/service/frame_sinks/DEPS
@@ -1,8 +1,13 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+cc/base",
"+cc/ipc",
"+cc/scheduler",
+ "+components/viz/service/display",
+ "+components/viz/service/display_embedder",
+ "+components/viz/service/hit_test",
"+components/viz/service/surfaces",
"+gpu/ipc/common",
- "+mojo/public/cpp/bindings",
+ "+mojo/public",
]
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 06e80911746..a562e9d7428 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,13 +43,18 @@ void CompositorFrameSinkImpl::SubmitCompositorFrame(
CompositorFrame frame,
mojom::HitTestRegionListPtr hit_test_region_list,
uint64_t submit_time) {
- if (!support_->SubmitCompositorFrame(local_surface_id, std::move(frame),
- std::move(hit_test_region_list))) {
- DLOG(ERROR) << "SubmitCompositorFrame failed for " << local_surface_id;
- compositor_frame_sink_binding_.CloseWithReason(
- 1, "Surface invariants violation");
- OnClientConnectionLost();
- }
+ const auto result = support_->MaybeSubmitCompositorFrame(
+ local_surface_id, std::move(frame), std::move(hit_test_region_list));
+ if (result == CompositorFrameSinkSupport::ACCEPTED)
+ return;
+
+ const char* reason =
+ CompositorFrameSinkSupport::GetSubmitResultAsString(result);
+ DLOG(ERROR) << "SubmitCompositorFrame failed for " << local_surface_id
+ << " because " << reason;
+ compositor_frame_sink_binding_.CloseWithReason(static_cast<uint32_t>(result),
+ reason);
+ OnClientConnectionLost();
}
void CompositorFrameSinkImpl::DidNotProduceFrame(
@@ -57,6 +62,21 @@ void CompositorFrameSinkImpl::DidNotProduceFrame(
support_->DidNotProduceFrame(begin_frame_ack);
}
+void CompositorFrameSinkImpl::DidAllocateSharedBitmap(
+ mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) {
+ if (!support_->DidAllocateSharedBitmap(std::move(buffer), id)) {
+ DLOG(ERROR) << "DidAllocateSharedBitmap failed for duplicate "
+ << "SharedBitmapId";
+ compositor_frame_sink_binding_.Close();
+ OnClientConnectionLost();
+ }
+}
+
+void CompositorFrameSinkImpl::DidDeleteSharedBitmap(const SharedBitmapId& id) {
+ support_->DidDeleteSharedBitmap(id);
+}
+
void CompositorFrameSinkImpl::OnClientConnectionLost() {
support_->frame_sink_manager()->OnClientConnectionLost(
support_->frame_sink_id());
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 0bd4e0c3daf..f1a497af1a5 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
@@ -35,6 +35,9 @@ class CompositorFrameSinkImpl : public mojom::CompositorFrameSink {
mojom::HitTestRegionListPtr hit_test_region_list,
uint64_t submit_time) override;
void DidNotProduceFrame(const BeginFrameAck& begin_frame_ack) override;
+ void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) override;
+ void DidDeleteSharedBitmap(const SharedBitmapId& id) override;
CompositorFrameSinkSupport* support() const { return support_.get(); }
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 20b29c9417f..52b8a67c75a 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
@@ -11,9 +11,11 @@
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/service/display/display.h"
+#include "components/viz/service/display_embedder/server_shared_bitmap_manager.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_reference.h"
+#include "mojo/public/cpp/system/platform_handle.h"
namespace viz {
@@ -30,6 +32,7 @@ CompositorFrameSinkSupport::CompositorFrameSinkSupport(
surface_resource_holder_(this),
is_root_(is_root),
needs_sync_tokens_(needs_sync_tokens),
+ allow_copy_output_requests_(is_root),
weak_factory_(this) {
// This may result in SetBeginFrameSource() being called.
frame_sink_manager_->RegisterCompositorFrameSinkSupport(frame_sink_id_, this);
@@ -51,14 +54,30 @@ CompositorFrameSinkSupport::~CompositorFrameSinkSupport() {
surface_manager_->RemoveSurfaceReferences({reference});
}
- EvictCurrentSurface();
+ EvictLastActivatedSurface();
+ if (last_created_surface_id_.is_valid())
+ surface_manager_->DestroySurface(last_created_surface_id_);
frame_sink_manager_->UnregisterCompositorFrameSinkSupport(frame_sink_id_);
- // No video capture clients should remain at this point.
+ // The display compositor has ownership of shared memory for each
+ // SharedBitmapId that has been reported from the client. Since the client is
+ // gone that memory can be freed. If we don't then it would leak.
+ for (const auto& id : owned_bitmaps_)
+ ServerSharedBitmapManager::current()->ChildDeletedSharedBitmap(id);
+
+ // No video capture clients should remain after calling
+ // UnregisterCompositorFrameSinkSupport().
DCHECK(capture_clients_.empty());
}
-void CompositorFrameSinkSupport::SetAggregatedDamageCallback(
+void CompositorFrameSinkSupport::SetUpHitTest() {
+ DCHECK(is_root_);
+ hit_test_aggregator_ = std::make_unique<HitTestAggregator>(
+ frame_sink_manager_->hit_test_manager(), frame_sink_manager_,
+ frame_sink_id_);
+}
+
+void CompositorFrameSinkSupport::SetAggregatedDamageCallbackForTesting(
AggregatedDamageCallback callback) {
aggregated_damage_callback_ = std::move(callback);
}
@@ -81,6 +100,17 @@ void CompositorFrameSinkSupport::SetBeginFrameSource(
void CompositorFrameSinkSupport::OnSurfaceActivated(Surface* surface) {
DCHECK(surface);
DCHECK(surface->HasActiveFrame());
+ if (last_activated_surface_id_ != surface->surface_id()) {
+ if (last_activated_surface_id_.is_valid()) {
+ Surface* prev_surface =
+ surface_manager_->GetSurfaceForId(last_activated_surface_id_);
+ DCHECK(prev_surface);
+ surface->SetPreviousFrameSurface(prev_surface);
+ surface_manager_->DestroySurface(prev_surface->surface_id());
+ }
+ last_activated_surface_id_ = surface->surface_id();
+ }
+
DCHECK(surface->active_referenced_surfaces());
UpdateSurfaceReferences(surface->surface_id().local_surface_id(),
*surface->active_referenced_surfaces());
@@ -89,6 +119,14 @@ void CompositorFrameSinkSupport::OnSurfaceActivated(Surface* surface) {
frame_sink_manager_->OnFrameTokenChanged(frame_sink_id_, frame_token);
}
+void CompositorFrameSinkSupport::OnSurfaceDiscarded(Surface* surface) {
+ if (surface->surface_id() == last_activated_surface_id_)
+ last_activated_surface_id_ = SurfaceId();
+
+ if (surface->surface_id() == last_created_surface_id_)
+ last_created_surface_id_ = SurfaceId();
+}
+
void CompositorFrameSinkSupport::RefResources(
const std::vector<TransferableResource>& resources) {
surface_resource_holder_.RefResources(resources);
@@ -117,12 +155,14 @@ void CompositorFrameSinkSupport::ReceiveFromChild(
surface_resource_holder_.ReceiveFromChild(resources);
}
-void CompositorFrameSinkSupport::EvictCurrentSurface() {
- if (!current_surface_id_.is_valid())
+void CompositorFrameSinkSupport::EvictLastActivatedSurface() {
+ if (!last_activated_surface_id_.is_valid())
return;
- SurfaceId to_destroy_surface_id = current_surface_id_;
- current_surface_id_ = SurfaceId();
+ SurfaceId to_destroy_surface_id = last_activated_surface_id_;
+ if (last_created_surface_id_ == last_activated_surface_id_)
+ last_created_surface_id_ = SurfaceId();
+ last_activated_surface_id_ = SurfaceId();
surface_manager_->DestroySurface(to_destroy_surface_id);
// For display root surfaces the surface is no longer going to be visible.
@@ -158,8 +198,8 @@ void CompositorFrameSinkSupport::DidNotProduceFrame(const BeginFrameAck& ack) {
BeginFrameAck modified_ack(ack);
modified_ack.has_damage = false;
- if (current_surface_id_.is_valid())
- surface_manager_->SurfaceModified(current_surface_id_, modified_ack);
+ if (last_activated_surface_id_.is_valid())
+ surface_manager_->SurfaceModified(last_activated_surface_id_, modified_ack);
if (begin_frame_source_)
begin_frame_source_->DidFinishFrame(this);
@@ -170,18 +210,45 @@ void CompositorFrameSinkSupport::SubmitCompositorFrame(
CompositorFrame frame,
mojom::HitTestRegionListPtr hit_test_region_list,
uint64_t submit_time) {
- SubmitCompositorFrame(local_surface_id, std::move(frame),
- std::move(hit_test_region_list));
+ const auto result = MaybeSubmitCompositorFrame(
+ local_surface_id, std::move(frame), std::move(hit_test_region_list));
+ DCHECK_EQ(result, ACCEPTED);
}
-bool CompositorFrameSinkSupport::SubmitCompositorFrame(
+bool CompositorFrameSinkSupport::DidAllocateSharedBitmap(
+ mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) {
+ if (!ServerSharedBitmapManager::current()->ChildAllocatedSharedBitmap(
+ std::move(buffer), id))
+ return false;
+
+ owned_bitmaps_.insert(id);
+ return true;
+}
+
+void CompositorFrameSinkSupport::DidDeleteSharedBitmap(
+ const SharedBitmapId& id) {
+ ServerSharedBitmapManager::current()->ChildDeletedSharedBitmap(id);
+ owned_bitmaps_.erase(id);
+}
+
+CompositorFrameSinkSupport::SubmitResult
+CompositorFrameSinkSupport::MaybeSubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
mojom::HitTestRegionListPtr hit_test_region_list) {
- TRACE_EVENT1("viz", "CompositorFrameSinkSupport::SubmitCompositorFrame",
+ TRACE_EVENT1("viz", "CompositorFrameSinkSupport::MaybeSubmitCompositorFrame",
"FrameSinkId", frame_sink_id_.ToString());
DCHECK(local_surface_id.is_valid());
DCHECK(!frame.render_pass_list.empty());
+ DCHECK(!frame.size_in_pixels().IsEmpty());
+
+ // Ensure no CopyOutputRequests have been submitted if they are banned.
+ if (!allow_copy_output_requests_ && frame.HasCopyOutputRequests()) {
+ TRACE_EVENT_INSTANT0("viz", "CopyOutputRequests not allowed",
+ TRACE_EVENT_SCOPE_THREAD);
+ return COPY_OUTPUT_REQUESTS_NOT_ALLOWED;
+ }
uint64_t frame_index = ++last_frame_index_;
++ack_pending_count_;
@@ -203,10 +270,10 @@ bool CompositorFrameSinkSupport::SubmitCompositorFrame(
}
Surface* prev_surface =
- surface_manager_->GetSurfaceForId(current_surface_id_);
+ surface_manager_->GetSurfaceForId(last_created_surface_id_);
Surface* current_surface = nullptr;
if (prev_surface &&
- local_surface_id == current_surface_id_.local_surface_id()) {
+ local_surface_id == last_created_surface_id_.local_surface_id()) {
current_surface = prev_surface;
} else {
SurfaceId surface_id(frame_sink_id_, local_surface_id);
@@ -215,19 +282,19 @@ bool CompositorFrameSinkSupport::SubmitCompositorFrame(
// LocalSurfaceIds should be monotonically increasing. This ID is used
// to determine the freshness of a surface at aggregation time.
- const LocalSurfaceId& current_local_surface_id =
- current_surface_id_.local_surface_id();
+ const LocalSurfaceId& last_created_local_surface_id =
+ last_created_surface_id_.local_surface_id();
// Neither sequence numbers of the LocalSurfaceId can decrease and at least
// one must increase.
bool monotonically_increasing_id =
(local_surface_id.parent_sequence_number() >=
- current_local_surface_id.parent_sequence_number() &&
+ last_created_local_surface_id.parent_sequence_number() &&
local_surface_id.child_sequence_number() >=
- current_local_surface_id.child_sequence_number()) &&
+ last_created_local_surface_id.child_sequence_number()) &&
(local_surface_id.parent_sequence_number() >
- current_local_surface_id.parent_sequence_number() ||
+ last_created_local_surface_id.parent_sequence_number() ||
local_surface_id.child_sequence_number() >
- current_local_surface_id.child_sequence_number());
+ last_created_local_surface_id.child_sequence_number());
if (!surface_info.is_valid() || !monotonically_increasing_id) {
TRACE_EVENT_INSTANT0("viz", "Surface Invariants Violation",
@@ -240,14 +307,20 @@ bool CompositorFrameSinkSupport::SubmitCompositorFrame(
DidPresentCompositorFrame(frame.metadata.presentation_token,
base::TimeTicks(), base::TimeDelta(), 0);
}
- return false;
+ return SURFACE_INVARIANTS_VIOLATION;
}
current_surface = CreateSurface(surface_info);
- current_surface_id_ = SurfaceId(frame_sink_id_, local_surface_id);
+ last_created_surface_id_ = SurfaceId(frame_sink_id_, local_surface_id);
surface_manager_->SurfaceDamageExpected(current_surface->surface_id(),
last_begin_frame_args_);
}
+
+ // QueueFrame can fail in unit tests, so SubmitHitTestRegionList has to be
+ // called before that.
+ frame_sink_manager()->SubmitHitTestRegionList(
+ last_created_surface_id_, frame_index, std::move(hit_test_region_list));
+
bool result = current_surface->QueueFrame(
std::move(frame), frame_index,
base::BindOnce(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck,
@@ -260,22 +333,14 @@ bool CompositorFrameSinkSupport::SubmitCompositorFrame(
weak_factory_.GetWeakPtr(), frame.metadata.presentation_token)
: Surface::PresentedCallback());
if (!result) {
- EvictCurrentSurface();
- return false;
- }
-
- if (prev_surface && prev_surface != current_surface) {
- current_surface->SetPreviousFrameSurface(prev_surface);
- surface_manager_->DestroySurface(prev_surface->surface_id());
+ TRACE_EVENT_INSTANT0("viz", "QueueFrame failed", TRACE_EVENT_SCOPE_THREAD);
+ return SURFACE_INVARIANTS_VIOLATION;
}
- frame_sink_manager()->SubmitHitTestRegionList(
- current_surface_id_, frame_index, std::move(hit_test_region_list));
-
if (begin_frame_source_)
begin_frame_source_->DidFinishFrame(this);
- return true;
+ return ACCEPTED;
}
void CompositorFrameSinkSupport::UpdateSurfaceReferences(
@@ -354,8 +419,8 @@ void CompositorFrameSinkSupport::DidPresentCompositorFrame(
void CompositorFrameSinkSupport::OnBeginFrame(const BeginFrameArgs& args) {
UpdateNeedsBeginFramesInternal();
- if (current_surface_id_.is_valid())
- surface_manager_->SurfaceDamageExpected(current_surface_id_, args);
+ if (last_activated_surface_id_.is_valid())
+ surface_manager_->SurfaceDamageExpected(last_activated_surface_id_, args);
last_begin_frame_args_ = args;
if (client_)
client_->OnBeginFrame(args);
@@ -409,22 +474,25 @@ void CompositorFrameSinkSupport::DetachCaptureClient(
capture_clients_.erase(it);
}
-gfx::Size CompositorFrameSinkSupport::GetSurfaceSize() {
- if (current_surface_id_.is_valid()) {
+gfx::Size CompositorFrameSinkSupport::GetActiveFrameSize() {
+ if (last_activated_surface_id_.is_valid()) {
Surface* current_surface =
- surface_manager_->GetSurfaceForId(current_surface_id_);
- if (current_surface)
+ surface_manager_->GetSurfaceForId(last_activated_surface_id_);
+ if (current_surface->HasActiveFrame()) {
+ DCHECK(current_surface->GetActiveFrame().size_in_pixels() ==
+ current_surface->size_in_pixels());
return current_surface->size_in_pixels();
+ }
}
return gfx::Size();
}
void CompositorFrameSinkSupport::RequestCopyOfSurface(
std::unique_ptr<CopyOutputRequest> copy_request) {
- if (!current_surface_id_.is_valid())
+ if (!last_activated_surface_id_.is_valid())
return;
Surface* current_surface =
- surface_manager_->GetSurfaceForId(current_surface_id_);
+ surface_manager_->GetSurfaceForId(last_activated_surface_id_);
current_surface->RequestCopyOfOutput(std::move(copy_request));
BeginFrameAck ack;
ack.has_damage = true;
@@ -432,8 +500,28 @@ void CompositorFrameSinkSupport::RequestCopyOfSurface(
surface_manager_->SurfaceModified(current_surface->surface_id(), ack);
}
-Surface* CompositorFrameSinkSupport::GetCurrentSurfaceForTesting() {
- return surface_manager_->GetSurfaceForId(current_surface_id_);
+HitTestAggregator* CompositorFrameSinkSupport::GetHitTestAggregator() {
+ DCHECK(is_root_);
+ return hit_test_aggregator_.get();
+}
+
+Surface* CompositorFrameSinkSupport::GetLastCreatedSurfaceForTesting() {
+ return surface_manager_->GetSurfaceForId(last_created_surface_id_);
+}
+
+// static
+const char* CompositorFrameSinkSupport::GetSubmitResultAsString(
+ SubmitResult result) {
+ switch (result) {
+ case CompositorFrameSinkSupport::ACCEPTED:
+ return "Accepted";
+ case CompositorFrameSinkSupport::COPY_OUTPUT_REQUESTS_NOT_ALLOWED:
+ return "CopyOutputRequests not allowed";
+ case CompositorFrameSinkSupport::SURFACE_INVARIANTS_VIOLATION:
+ return "Surface invariants violation";
+ }
+ NOTREACHED();
+ return nullptr;
}
void CompositorFrameSinkSupport::OnAggregatedDamage(
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 6151b6d9213..ff4bbda6081 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
@@ -18,6 +18,7 @@
#include "components/viz/service/frame_sinks/surface_resource_holder.h"
#include "components/viz/service/frame_sinks/surface_resource_holder_client.h"
#include "components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h"
+#include "components/viz/service/hit_test/hit_test_aggregator.h"
#include "components/viz/service/surfaces/surface_client.h"
#include "components/viz/service/viz_service_export.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
@@ -33,9 +34,15 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
: public BeginFrameObserver,
public SurfaceResourceHolderClient,
public SurfaceClient,
- public CapturableFrameSink,
- public mojom::CompositorFrameSink {
+ public CapturableFrameSink {
public:
+ // Possible outcomes of MaybeSubmitCompositorFrame().
+ enum SubmitResult {
+ ACCEPTED,
+ COPY_OUTPUT_REQUESTS_NOT_ALLOWED,
+ SURFACE_INVARIANTS_VIOLATION,
+ };
+
using AggregatedDamageCallback =
base::RepeatingCallback<void(const LocalSurfaceId& local_surface_id,
const gfx::Rect& damage_rect)>;
@@ -51,17 +58,23 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
const FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
- const SurfaceId& current_surface_id() const { return current_surface_id_; }
+ const SurfaceId& last_activated_surface_id() const {
+ return last_activated_surface_id_;
+ }
- const LocalSurfaceId& local_surface_id() const {
- return current_surface_id_.local_surface_id();
+ const LocalSurfaceId& last_activated_local_surface_id() const {
+ return last_activated_surface_id_.local_surface_id();
}
FrameSinkManagerImpl* frame_sink_manager() { return frame_sink_manager_; }
+ // Viz hit-test setup is only called when |is_root_| is true (except on
+ // android webview).
+ void SetUpHitTest();
+
// The provided callback will be run every time a surface owned by this object
// or one of its descendents is determined to be damaged at aggregation time.
- void SetAggregatedDamageCallback(AggregatedDamageCallback callback);
+ void SetAggregatedDamageCallbackForTesting(AggregatedDamageCallback callback);
// Sets callback called on destruction.
void SetDestructionCallback(base::OnceClosure callback);
@@ -71,6 +84,7 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
// SurfaceClient implementation.
void OnSurfaceActivated(Surface* surface) override;
+ void OnSurfaceDiscarded(Surface* surface) override;
void RefResources(
const std::vector<TransferableResource>& resources) override;
void UnrefResources(const std::vector<ReturnedResource>& resources) override;
@@ -78,34 +92,55 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
void ReceiveFromChild(
const std::vector<TransferableResource>& resources) override;
- // mojom::CompositorFrameSink implementation.
- void SetNeedsBeginFrame(bool needs_begin_frame) override;
- void SetWantsAnimateOnlyBeginFrames() override;
- void DidNotProduceFrame(const BeginFrameAck& ack) override;
- void SubmitCompositorFrame(const LocalSurfaceId& local_surface_id,
- CompositorFrame frame,
- mojom::HitTestRegionListPtr hit_test_region_list,
- uint64_t submit_time) override;
-
- void EvictCurrentSurface();
-
- // Submits a new CompositorFrame to |local_surface_id|. If |local_surface_id|
- // hasn't been submitted to before then a new Surface will be created for it.
- // Returns false if |frame| was rejected due to invalid data.
- // TODO(kylechar): Merge the two SubmitCompositorFrame() methods.
- bool SubmitCompositorFrame(
+ // mojom::CompositorFrameSink helpers.
+ void SetNeedsBeginFrame(bool needs_begin_frame);
+ void SetWantsAnimateOnlyBeginFrames();
+ void DidNotProduceFrame(const BeginFrameAck& ack);
+ void SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- mojom::HitTestRegionListPtr hit_test_region_list = nullptr);
+ mojom::HitTestRegionListPtr hit_test_region_list = nullptr,
+ uint64_t submit_time = 0);
+ // Returns false if the notification was not valid (a duplicate).
+ bool DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id);
+ void DidDeleteSharedBitmap(const SharedBitmapId& id);
+
+ void EvictLastActivatedSurface();
+
+ // Attempts to submit a new CompositorFrame to |local_surface_id| and returns
+ // whether the frame was accepted or the reason why it was rejected. If
+ // |local_surface_id| hasn't been submitted before then a new Surface will be
+ // created for it.
+ //
+ // This is called by SubmitCompositorFrame(), which DCHECK-fails on a
+ // non-accepted result. Prefer calling SubmitCompositorFrame() instead of this
+ // method unless the result value affects what the caller will do next.
+ SubmitResult MaybeSubmitCompositorFrame(
+ const LocalSurfaceId& local_surface_id,
+ CompositorFrame frame,
+ mojom::HitTestRegionListPtr hit_test_region_list);
// CapturableFrameSink implementation.
void AttachCaptureClient(CapturableFrameSink::Client* client) override;
void DetachCaptureClient(CapturableFrameSink::Client* client) override;
- gfx::Size GetSurfaceSize() override;
+ gfx::Size GetActiveFrameSize() override;
void RequestCopyOfSurface(
std::unique_ptr<CopyOutputRequest> request) override;
- Surface* GetCurrentSurfaceForTesting();
+ HitTestAggregator* GetHitTestAggregator();
+
+ // Permits submitted CompositorFrames to contain CopyOutputRequests, for
+ // special-case testing purposes only.
+ void set_allow_copy_output_requests_for_testing() {
+ allow_copy_output_requests_ = true;
+ }
+
+ Surface* GetLastCreatedSurfaceForTesting();
+
+ // Maps the |result| from MaybeSubmitCompositorFrame() to a human-readable
+ // string.
+ static const char* GetSubmitResultAsString(SubmitResult result);
private:
friend class FrameSinkManagerTest;
@@ -146,7 +181,8 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
SurfaceManager* const surface_manager_;
const FrameSinkId frame_sink_id_;
- SurfaceId current_surface_id_;
+ SurfaceId last_activated_surface_id_;
+ SurfaceId last_created_surface_id_;
// 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
@@ -155,6 +191,9 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
SurfaceResourceHolder surface_resource_holder_;
+ // This has a HitTestAggregator if and only if |is_root_| is true.
+ std::unique_ptr<HitTestAggregator> hit_test_aggregator_;
+
// Counts the number of CompositorFrames that have been submitted and have not
// yet received an ACK.
int ack_pending_count_ = 0;
@@ -177,6 +216,12 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
const bool is_root_;
const bool needs_sync_tokens_;
+ // By default, this is equivalent to |is_root_|, but may be overridden for
+ // testing. Generally, for non-roots, there must not be any CopyOutputRequests
+ // contained within submitted CompositorFrames. Otherwise, unprivileged
+ // clients would be able to capture content for which they are not authorized.
+ bool allow_copy_output_requests_;
+
// A callback that will be run at the start of the destructor if set.
base::OnceClosure destruction_callback_;
@@ -190,6 +235,11 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
// frames.
std::vector<CapturableFrameSink::Client*> capture_clients_;
+ // The set of SharedBitmapIds that have been reported as allocated to this
+ // interface. On closing this interface, the display compositor should drop
+ // ownership of the bitmaps with these ids to avoid leaking them.
+ std::set<SharedBitmapId> owned_bitmaps_;
+
base::WeakPtrFactory<CompositorFrameSinkSupport> weak_factory_;
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 80d2a220e68..252e1f2085e 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
@@ -65,8 +65,6 @@ class CompositorFrameSinkSupportTest : public testing::Test {
manager_.SetLocalClient(&frame_sink_manager_client_);
manager_.surface_manager()->AddObserver(&surface_observer_);
manager_.RegisterFrameSinkId(kArbitraryFrameSinkId);
- manager_.SetFrameSinkDebugLabel(kArbitraryFrameSinkId,
- "kArbitraryFrameSinkId");
support_ = std::make_unique<CompositorFrameSinkSupport>(
&fake_support_client_, &manager_, kArbitraryFrameSinkId, kIsRoot,
kNeedsSyncPoints);
@@ -75,7 +73,6 @@ class CompositorFrameSinkSupportTest : public testing::Test {
~CompositorFrameSinkSupportTest() override {
manager_.InvalidateFrameSinkId(kArbitraryFrameSinkId);
manager_.surface_manager()->RemoveObserver(&surface_observer_);
- support_->EvictCurrentSurface();
}
void SubmitCompositorFrameWithResources(ResourceId* resource_ids,
@@ -93,6 +90,26 @@ class CompositorFrameSinkSupportTest : public testing::Test {
local_surface_id_);
}
+ bool SubmitCompositorFrameWithCopyRequest(
+ std::unique_ptr<CopyOutputRequest> request) {
+ auto frame = MakeDefaultCompositorFrame();
+ frame.render_pass_list.back()->copy_requests.push_back(std::move(request));
+ const auto result = support_->MaybeSubmitCompositorFrame(
+ local_surface_id_, std::move(frame), nullptr);
+ switch (result) {
+ case CompositorFrameSinkSupport::ACCEPTED:
+ return true;
+ case CompositorFrameSinkSupport::COPY_OUTPUT_REQUESTS_NOT_ALLOWED:
+ return false;
+ default:
+ ADD_FAILURE()
+ << "Test broken; fail result not related to copy requests: "
+ << CompositorFrameSinkSupport::GetSubmitResultAsString(result);
+ break;
+ }
+ return false;
+ }
+
void UnrefResources(ResourceId* ids_to_unref,
int* counts_to_unref,
size_t num_ids_to_unref) {
@@ -456,8 +473,6 @@ TEST_F(CompositorFrameSinkSupportTest, ResourceLifetime) {
TEST_F(CompositorFrameSinkSupportTest, AddDuringEviction) {
manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId);
- manager_.SetFrameSinkDebugLabel(kAnotherArbitraryFrameSinkId,
- "kAnotherArbitraryFrameSinkId");
MockCompositorFrameSinkClient mock_client;
auto support = std::make_unique<CompositorFrameSinkSupport>(
&mock_client, &manager_, kAnotherArbitraryFrameSinkId, kIsRoot,
@@ -475,15 +490,13 @@ TEST_F(CompositorFrameSinkSupportTest, AddDuringEviction) {
surface_manager->GarbageCollectSurfaces();
}))
.WillRepeatedly(testing::Return());
- support->EvictCurrentSurface();
+ support->EvictLastActivatedSurface();
manager_.InvalidateFrameSinkId(kAnotherArbitraryFrameSinkId);
}
// Verifies that only monotonically increasing LocalSurfaceIds are accepted.
TEST_F(CompositorFrameSinkSupportTest, MonotonicallyIncreasingLocalSurfaceIds) {
manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId);
- manager_.SetFrameSinkDebugLabel(kAnotherArbitraryFrameSinkId,
- "kAnotherArbitraryFrameSinkId");
MockCompositorFrameSinkClient mock_client;
auto support = std::make_unique<CompositorFrameSinkSupport>(
&mock_client, &manager_, kAnotherArbitraryFrameSinkId, kIsRoot,
@@ -494,28 +507,54 @@ TEST_F(CompositorFrameSinkSupportTest, MonotonicallyIncreasingLocalSurfaceIds) {
LocalSurfaceId local_surface_id4(5, 3, kArbitraryToken);
LocalSurfaceId local_surface_id5(8, 1, kArbitraryToken);
LocalSurfaceId local_surface_id6(9, 3, kArbitraryToken);
- EXPECT_TRUE(support->SubmitCompositorFrame(local_surface_id1,
- MakeDefaultCompositorFrame()));
- EXPECT_TRUE(support->SubmitCompositorFrame(local_surface_id2,
- MakeDefaultCompositorFrame()));
- EXPECT_TRUE(support->SubmitCompositorFrame(local_surface_id3,
- MakeDefaultCompositorFrame()));
- EXPECT_FALSE(support->SubmitCompositorFrame(local_surface_id4,
- MakeDefaultCompositorFrame()));
- EXPECT_FALSE(support->SubmitCompositorFrame(local_surface_id5,
- MakeDefaultCompositorFrame()));
- EXPECT_TRUE(support->SubmitCompositorFrame(local_surface_id6,
- MakeDefaultCompositorFrame()));
-
- support->EvictCurrentSurface();
+ auto result = support->MaybeSubmitCompositorFrame(
+ local_surface_id1, MakeDefaultCompositorFrame(), nullptr);
+ EXPECT_EQ(CompositorFrameSinkSupport::ACCEPTED, result);
+ result = support->MaybeSubmitCompositorFrame(
+ local_surface_id2, MakeDefaultCompositorFrame(), nullptr);
+ EXPECT_EQ(CompositorFrameSinkSupport::ACCEPTED, result);
+ result = support->MaybeSubmitCompositorFrame(
+ local_surface_id3, MakeDefaultCompositorFrame(), nullptr);
+ EXPECT_EQ(CompositorFrameSinkSupport::ACCEPTED, result);
+ result = support->MaybeSubmitCompositorFrame(
+ local_surface_id4, MakeDefaultCompositorFrame(), nullptr);
+ EXPECT_EQ(CompositorFrameSinkSupport::SURFACE_INVARIANTS_VIOLATION, result);
+ result = support->MaybeSubmitCompositorFrame(
+ local_surface_id5, MakeDefaultCompositorFrame(), nullptr);
+ EXPECT_EQ(CompositorFrameSinkSupport::SURFACE_INVARIANTS_VIOLATION, result);
+ result = support->MaybeSubmitCompositorFrame(
+ local_surface_id6, MakeDefaultCompositorFrame(), nullptr);
+ EXPECT_EQ(CompositorFrameSinkSupport::ACCEPTED, result);
+
manager_.InvalidateFrameSinkId(kAnotherArbitraryFrameSinkId);
}
-// Tests doing an EvictCurrentSurface before shutting down the factory.
-TEST_F(CompositorFrameSinkSupportTest, EvictCurrentSurface) {
+// Verifies that CopyOutputRequests submitted by unprivileged clients are
+// rejected.
+TEST_F(CompositorFrameSinkSupportTest, ProhibitsUnprivilegedCopyRequests) {
+ manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId);
+ MockCompositorFrameSinkClient mock_client;
+ auto support = std::make_unique<CompositorFrameSinkSupport>(
+ &mock_client, &manager_, kAnotherArbitraryFrameSinkId,
+ false /* not root frame sink */, kNeedsSyncPoints);
+
+ bool did_receive_aborted_copy_result = false;
+ auto request = std::make_unique<CopyOutputRequest>(
+ CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ base::BindOnce(
+ [](bool* got_nothing, std::unique_ptr<CopyOutputResult> result) {
+ *got_nothing = result->IsEmpty();
+ },
+ &did_receive_aborted_copy_result));
+ EXPECT_FALSE(SubmitCompositorFrameWithCopyRequest(std::move(request)));
+ EXPECT_TRUE(did_receive_aborted_copy_result);
+
+ manager_.InvalidateFrameSinkId(kAnotherArbitraryFrameSinkId);
+}
+
+// Tests doing an EvictLastActivatedSurface before shutting down the factory.
+TEST_F(CompositorFrameSinkSupportTest, EvictLastActivatedSurface) {
manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId);
- manager_.SetFrameSinkDebugLabel(kAnotherArbitraryFrameSinkId,
- "kAnotherArbitraryFrameSinkId");
MockCompositorFrameSinkClient mock_client;
auto support = std::make_unique<CompositorFrameSinkSupport>(
&mock_client, &manager_, kAnotherArbitraryFrameSinkId, kIsRoot,
@@ -540,7 +579,7 @@ TEST_F(CompositorFrameSinkSupportTest, EvictCurrentSurface) {
EXPECT_TRUE(GetSurfaceForId(id));
EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(returned_resources))
.Times(1);
- support->EvictCurrentSurface();
+ support->EvictLastActivatedSurface();
manager_.surface_manager()->GarbageCollectSurfaces();
EXPECT_FALSE(GetSurfaceForId(id));
manager_.InvalidateFrameSinkId(kAnotherArbitraryFrameSinkId);
@@ -555,7 +594,6 @@ TEST_F(CompositorFrameSinkSupportTest, EvictSurfaceWithTemporaryReference) {
support_->frame_sink_id());
manager_.RegisterFrameSinkId(parent_frame_sink_id);
- manager_.SetFrameSinkDebugLabel(parent_frame_sink_id, "parent_frame_sink_id");
const LocalSurfaceId local_surface_id(5, kArbitraryToken);
const SurfaceId surface_id(support_->frame_sink_id(), local_surface_id);
@@ -567,7 +605,7 @@ TEST_F(CompositorFrameSinkSupportTest, EvictSurfaceWithTemporaryReference) {
// Verify the temporary reference has prevented the surface from getting
// destroyed.
- support_->EvictCurrentSurface();
+ support_->EvictLastActivatedSurface();
EXPECT_TRUE(GetSurfaceForId(surface_id));
// Verify the temporary reference is removed when the parent is invalidated.
@@ -624,7 +662,7 @@ TEST_F(CompositorFrameSinkSupportTest, DuplicateCopyRequest) {
EXPECT_FALSE(called2);
EXPECT_FALSE(called3);
- support_->EvictCurrentSurface();
+ support_->EvictLastActivatedSurface();
local_surface_id_ = LocalSurfaceId();
manager_.surface_manager()->GarbageCollectSurfaces();
EXPECT_TRUE(called1);
@@ -649,17 +687,6 @@ TEST_F(CompositorFrameSinkSupportTest, SurfaceInfo) {
surface_observer_.last_surface_info().size_in_pixels());
}
-// Check that if a CompositorFrame is received with size zero, we don't create
-// a Surface for it.
-TEST_F(CompositorFrameSinkSupportTest, ZeroFrameSize) {
- SurfaceId id(support_->frame_sink_id(), local_surface_id_);
- auto frame =
- CompositorFrameBuilder().AddRenderPass(gfx::Rect(), gfx::Rect()).Build();
- EXPECT_FALSE(
- support_->SubmitCompositorFrame(local_surface_id_, std::move(frame)));
- EXPECT_FALSE(GetSurfaceForId(id));
-}
-
// Check that if a CompositorFrame is received with device scale factor of 0, we
// don't create a Surface for it.
TEST_F(CompositorFrameSinkSupportTest, ZeroDeviceScaleFactor) {
@@ -668,8 +695,9 @@ TEST_F(CompositorFrameSinkSupportTest, ZeroDeviceScaleFactor) {
.AddDefaultRenderPass()
.SetDeviceScaleFactor(0.f)
.Build();
- EXPECT_FALSE(
- support_->SubmitCompositorFrame(local_surface_id_, std::move(frame)));
+ const auto result = support_->MaybeSubmitCompositorFrame(
+ local_surface_id_, std::move(frame), nullptr);
+ EXPECT_EQ(CompositorFrameSinkSupport::SURFACE_INVARIANTS_VIOLATION, result);
EXPECT_FALSE(GetSurfaceForId(id));
}
@@ -682,8 +710,9 @@ TEST_F(CompositorFrameSinkSupportTest, FrameSizeMismatch) {
auto frame = CompositorFrameBuilder()
.AddRenderPass(gfx::Rect(5, 5), gfx::Rect())
.Build();
- EXPECT_TRUE(
- support_->SubmitCompositorFrame(local_surface_id_, std::move(frame)));
+ auto result = support_->MaybeSubmitCompositorFrame(local_surface_id_,
+ std::move(frame), nullptr);
+ EXPECT_EQ(CompositorFrameSinkSupport::ACCEPTED, result);
EXPECT_TRUE(GetSurfaceForId(id));
// Submit a frame with size (5,4). This frame should be rejected and the
@@ -691,10 +720,9 @@ TEST_F(CompositorFrameSinkSupportTest, FrameSizeMismatch) {
frame = CompositorFrameBuilder()
.AddRenderPass(gfx::Rect(5, 4), gfx::Rect())
.Build();
- EXPECT_FALSE(
- support_->SubmitCompositorFrame(local_surface_id_, std::move(frame)));
- manager_.surface_manager()->GarbageCollectSurfaces();
- EXPECT_FALSE(GetSurfaceForId(id));
+ result = support_->MaybeSubmitCompositorFrame(local_surface_id_,
+ std::move(frame), nullptr);
+ EXPECT_EQ(CompositorFrameSinkSupport::SURFACE_INVARIANTS_VIOLATION, result);
}
// Check that if the device scale factor of a CompositorFrame doesn't match the
@@ -708,8 +736,9 @@ TEST_F(CompositorFrameSinkSupportTest, DeviceScaleFactorMismatch) {
.AddDefaultRenderPass()
.SetDeviceScaleFactor(0.5f)
.Build();
- EXPECT_TRUE(
- support_->SubmitCompositorFrame(local_surface_id_, std::move(frame)));
+ auto result = support_->MaybeSubmitCompositorFrame(local_surface_id_,
+ std::move(frame), nullptr);
+ EXPECT_EQ(CompositorFrameSinkSupport::ACCEPTED, result);
EXPECT_TRUE(GetSurfaceForId(id));
// Submit a frame with device scale factor of 0.4. This frame should be
@@ -718,10 +747,9 @@ TEST_F(CompositorFrameSinkSupportTest, DeviceScaleFactorMismatch) {
.AddDefaultRenderPass()
.SetDeviceScaleFactor(0.4f)
.Build();
- EXPECT_FALSE(
- support_->SubmitCompositorFrame(local_surface_id_, std::move(frame)));
- manager_.surface_manager()->GarbageCollectSurfaces();
- EXPECT_FALSE(GetSurfaceForId(id));
+ result = support_->MaybeSubmitCompositorFrame(local_surface_id_,
+ std::move(frame), nullptr);
+ EXPECT_EQ(CompositorFrameSinkSupport::SURFACE_INVARIANTS_VIOLATION, result);
}
TEST_F(CompositorFrameSinkSupportTest, PassesOnBeginFrameAcks) {
diff --git a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
index be4e7ab4fc1..bcd57aed7fb 100644
--- a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
+++ b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
@@ -9,6 +9,8 @@
#include "base/bind.h"
#include "cc/trees/layer_tree_frame_sink_client.h"
#include "components/viz/common/quads/compositor_frame.h"
+#include "components/viz/common/quads/draw_quad.h"
+#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/display/display.h"
@@ -28,7 +30,8 @@ DirectLayerTreeFrameSink::DirectLayerTreeFrameSink(
scoped_refptr<RasterContextProvider> worker_context_provider,
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- SharedBitmapManager* shared_bitmap_manager)
+ SharedBitmapManager* shared_bitmap_manager,
+ bool use_viz_hit_test)
: LayerTreeFrameSink(std::move(context_provider),
std::move(worker_context_provider),
std::move(compositor_task_runner),
@@ -38,7 +41,9 @@ DirectLayerTreeFrameSink::DirectLayerTreeFrameSink(
support_manager_(support_manager),
frame_sink_manager_(frame_sink_manager),
display_(display),
- display_client_(display_client) {
+ display_client_(display_client),
+ use_viz_hit_test_(use_viz_hit_test),
+ weak_factory_(this) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
capabilities_.must_always_swap = true;
// Display and DirectLayerTreeFrameSink share a GL context, so sync
@@ -46,23 +51,6 @@ DirectLayerTreeFrameSink::DirectLayerTreeFrameSink(
capabilities_.delegated_sync_points_required = false;
}
-DirectLayerTreeFrameSink::DirectLayerTreeFrameSink(
- const FrameSinkId& frame_sink_id,
- CompositorFrameSinkSupportManager* support_manager,
- FrameSinkManagerImpl* frame_sink_manager,
- Display* display,
- mojom::DisplayClient* display_client,
- scoped_refptr<VulkanContextProvider> vulkan_context_provider)
- : LayerTreeFrameSink(std::move(vulkan_context_provider)),
- frame_sink_id_(frame_sink_id),
- support_manager_(support_manager),
- frame_sink_manager_(frame_sink_manager),
- display_(display),
- display_client_(display_client) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- capabilities_.must_always_swap = true;
-}
-
DirectLayerTreeFrameSink::~DirectLayerTreeFrameSink() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
@@ -78,6 +66,8 @@ bool DirectLayerTreeFrameSink::BindToClient(
support_ = support_manager_->CreateCompositorFrameSinkSupport(
this, frame_sink_id_, is_root,
capabilities_.delegated_sync_points_required);
+ if (use_viz_hit_test_)
+ support_->SetUpHitTest();
begin_frame_source_ = std::make_unique<ExternalBeginFrameSource>(this);
client_->SetBeginFrameSource(begin_frame_source_.get());
@@ -112,9 +102,9 @@ void DirectLayerTreeFrameSink::SubmitCompositorFrame(CompositorFrame frame) {
display_->SetLocalSurfaceId(local_surface_id_, device_scale_factor_);
}
- bool result =
- support_->SubmitCompositorFrame(local_surface_id_, std::move(frame));
- DCHECK(result);
+ auto hit_test_region_list = CreateHitTestData(frame);
+ support_->SubmitCompositorFrame(local_surface_id_, std::move(frame),
+ std::move(hit_test_region_list));
}
void DirectLayerTreeFrameSink::DidNotProduceFrame(const BeginFrameAck& ack) {
@@ -123,6 +113,17 @@ void DirectLayerTreeFrameSink::DidNotProduceFrame(const BeginFrameAck& ack) {
support_->DidNotProduceFrame(ack);
}
+void DirectLayerTreeFrameSink::DidAllocateSharedBitmap(
+ mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) {
+ bool ok = support_->DidAllocateSharedBitmap(std::move(buffer), id);
+ DCHECK(ok);
+}
+
+void DirectLayerTreeFrameSink::DidDeleteSharedBitmap(const SharedBitmapId& id) {
+ support_->DidDeleteSharedBitmap(id);
+}
+
void DirectLayerTreeFrameSink::DisplayOutputSurfaceLost() {
is_lost_ = true;
client_->DidLoseLayerTreeFrameSink();
@@ -131,7 +132,8 @@ void DirectLayerTreeFrameSink::DisplayOutputSurfaceLost() {
void DirectLayerTreeFrameSink::DisplayWillDrawAndSwap(
bool will_draw_and_swap,
const RenderPassList& render_passes) {
- // This notification is not relevant to our client outside of tests.
+ if (support_->GetHitTestAggregator())
+ support_->GetHitTestAggregator()->Aggregate(display_->CurrentSurfaceId());
}
void DirectLayerTreeFrameSink::DisplayDidDrawAndSwap() {
@@ -151,6 +153,17 @@ void DirectLayerTreeFrameSink::DisplayDidReceiveCALayerParams(
void DirectLayerTreeFrameSink::DidReceiveCompositorFrameAck(
const std::vector<ReturnedResource>& resources) {
+ // Submitting a CompositorFrame can synchronously draw and dispatch a frame
+ // ack. PostTask to ensure the client is notified on a new stack frame.
+ compositor_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &DirectLayerTreeFrameSink::DidReceiveCompositorFrameAckInternal,
+ weak_factory_.GetWeakPtr(), resources));
+}
+
+void DirectLayerTreeFrameSink::DidReceiveCompositorFrameAckInternal(
+ const std::vector<ReturnedResource>& resources) {
client_->ReclaimResources(resources);
client_->DidReceiveCompositorFrameAck();
}
@@ -189,4 +202,39 @@ void DirectLayerTreeFrameSink::OnContextLost() {
// The display will be listening for OnContextLost(). Do nothing here.
}
+mojom::HitTestRegionListPtr DirectLayerTreeFrameSink::CreateHitTestData(
+ const CompositorFrame& frame) const {
+ auto hit_test_region_list = mojom::HitTestRegionList::New();
+ hit_test_region_list->flags =
+ mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestMine;
+ hit_test_region_list->bounds.set_size(frame.size_in_pixels());
+
+ for (const auto& render_pass : frame.render_pass_list) {
+ for (const DrawQuad* quad : render_pass->quad_list) {
+ if (quad->material == DrawQuad::SURFACE_CONTENT) {
+ // Skip the quad if the transform is not invertible (i.e. it will not
+ // be able to receive events).
+ gfx::Transform target_to_quad_transform;
+ if (!quad->shared_quad_state->quad_to_target_transform.GetInverse(
+ &target_to_quad_transform)) {
+ continue;
+ }
+
+ const SurfaceDrawQuad* surface_quad =
+ SurfaceDrawQuad::MaterialCast(quad);
+ auto hit_test_region = mojom::HitTestRegion::New();
+ const SurfaceId& surface_id = surface_quad->primary_surface_id;
+ hit_test_region->frame_sink_id = surface_id.frame_sink_id();
+ hit_test_region->local_surface_id = surface_id.local_surface_id();
+ hit_test_region->flags = mojom::kHitTestMouse | mojom::kHitTestTouch |
+ mojom::kHitTestChildSurface;
+ hit_test_region->rect = surface_quad->rect;
+ hit_test_region->transform = target_to_quad_transform;
+ hit_test_region_list->regions.push_back(std::move(hit_test_region));
+ }
+ }
+ }
+ return hit_test_region_list;
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
index 6c2d699db54..1bdfcf37560 100644
--- a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
+++ b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
@@ -45,14 +45,8 @@ class VIZ_SERVICE_EXPORT DirectLayerTreeFrameSink
scoped_refptr<RasterContextProvider> worker_context_provider,
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- SharedBitmapManager* shared_bitmap_manager);
- DirectLayerTreeFrameSink(
- const FrameSinkId& frame_sink_id,
- CompositorFrameSinkSupportManager* support_manager,
- FrameSinkManagerImpl* frame_sink_manager,
- Display* display,
- mojom::DisplayClient* display_client,
- scoped_refptr<VulkanContextProvider> vulkan_context_provider);
+ SharedBitmapManager* shared_bitmap_manager,
+ bool use_viz_hit_test);
~DirectLayerTreeFrameSink() override;
// LayerTreeFrameSink implementation.
@@ -60,6 +54,9 @@ class VIZ_SERVICE_EXPORT DirectLayerTreeFrameSink
void DetachFromClient() override;
void SubmitCompositorFrame(CompositorFrame frame) override;
void DidNotProduceFrame(const BeginFrameAck& ack) override;
+ void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) override;
+ void DidDeleteSharedBitmap(const SharedBitmapId& id) override;
// DisplayClient implementation.
void DisplayOutputSurfaceLost() override;
@@ -89,6 +86,11 @@ class VIZ_SERVICE_EXPORT DirectLayerTreeFrameSink
// ContextLostObserver implementation:
void OnContextLost() override;
+ mojom::HitTestRegionListPtr CreateHitTestData(
+ const CompositorFrame& frame) const;
+ void DidReceiveCompositorFrameAckInternal(
+ const std::vector<ReturnedResource>& resources);
+
// This class is only meant to be used on a single thread.
THREAD_CHECKER(thread_checker_);
@@ -102,10 +104,12 @@ class VIZ_SERVICE_EXPORT DirectLayerTreeFrameSink
Display* display_;
// |display_client_| may be nullptr on platforms that do not use it.
mojom::DisplayClient* display_client_ = nullptr;
+ bool use_viz_hit_test_ = false;
gfx::Size last_swap_frame_size_;
float device_scale_factor_ = 1.f;
bool is_lost_ = false;
std::unique_ptr<ExternalBeginFrameSource> begin_frame_source_;
+ base::WeakPtrFactory<DirectLayerTreeFrameSink> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DirectLayerTreeFrameSink);
};
diff --git a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
index 576f31b8b92..55ed23973c7 100644
--- a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
@@ -7,12 +7,11 @@
#include <memory>
#include "cc/test/fake_layer_tree_frame_sink_client.h"
-#include "cc/test/fake_output_surface.h"
-#include "cc/test/test_context_provider.h"
-#include "cc/test/test_shared_bitmap_manager.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/frame_sinks/delay_based_time_source.h"
+#include "components/viz/common/quads/solid_color_draw_quad.h"
+#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/display/display.h"
@@ -21,8 +20,11 @@
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/test/begin_frame_args_test.h"
#include "components/viz/test/compositor_frame_helpers.h"
+#include "components/viz/test/fake_output_surface.h"
#include "components/viz/test/ordered_simple_task_runner.h"
+#include "components/viz/test/test_context_provider.h"
#include "components/viz/test/test_gpu_memory_buffer_manager.h"
+#include "components/viz/test/test_shared_bitmap_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace viz {
@@ -66,8 +68,8 @@ class DirectLayerTreeFrameSinkTest : public testing::Test {
display_size_(1920, 1080),
display_rect_(display_size_),
support_manager_(&frame_sink_manager_),
- context_provider_(cc::TestContextProvider::Create()) {
- auto display_output_surface = cc::FakeOutputSurface::Create3d();
+ context_provider_(TestContextProvider::Create()) {
+ auto display_output_surface = FakeOutputSurface::Create3d();
display_output_surface_ = display_output_surface.get();
begin_frame_source_ = std::make_unique<BackToBackBeginFrameSource>(
@@ -83,7 +85,8 @@ class DirectLayerTreeFrameSinkTest : public testing::Test {
layer_tree_frame_sink_ = std::make_unique<TestDirectLayerTreeFrameSink>(
kArbitraryFrameSinkId, &support_manager_, &frame_sink_manager_,
display_.get(), nullptr /* display_client */, context_provider_,
- nullptr, task_runner_, &gpu_memory_buffer_manager_, &bitmap_manager_);
+ nullptr, task_runner_, &gpu_memory_buffer_manager_, &bitmap_manager_,
+ false /* use_viz_hit_test */);
layer_tree_frame_sink_->BindToClient(&layer_tree_frame_sink_client_);
display_->Resize(display_size_);
display_->SetVisible(true);
@@ -103,6 +106,14 @@ class DirectLayerTreeFrameSinkTest : public testing::Test {
layer_tree_frame_sink_->SubmitCompositorFrame(std::move(frame));
}
+ void SendRenderPassList(RenderPassList* pass_list) {
+ auto frame = CompositorFrameBuilder()
+ .SetRenderPassList(std::move(*pass_list))
+ .Build();
+ pass_list->clear();
+ layer_tree_frame_sink_->SubmitCompositorFrame(std::move(frame));
+ }
+
void SetUp() override {
// Draw the first frame to start in an "unlocked" state.
SwapBuffersWithDamage(display_rect_);
@@ -120,11 +131,11 @@ class DirectLayerTreeFrameSinkTest : public testing::Test {
const gfx::Rect display_rect_;
FrameSinkManagerImpl frame_sink_manager_;
TestCompositorFrameSinkSupportManager support_manager_;
- cc::TestSharedBitmapManager bitmap_manager_;
+ TestSharedBitmapManager bitmap_manager_;
TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
- scoped_refptr<cc::TestContextProvider> context_provider_;
- cc::FakeOutputSurface* display_output_surface_ = nullptr;
+ scoped_refptr<TestContextProvider> context_provider_;
+ FakeOutputSurface* display_output_surface_ = nullptr;
std::unique_ptr<BackToBackBeginFrameSource> begin_frame_source_;
std::unique_ptr<Display> display_;
cc::FakeLayerTreeFrameSinkClient layer_tree_frame_sink_client_;
@@ -160,5 +171,125 @@ TEST_F(DirectLayerTreeFrameSinkTest, SuspendedDoesNotTriggerSwapBuffers) {
EXPECT_EQ(2u, display_output_surface_->num_sent_frames());
}
+// Test that hit_test_region_list are created correctly for the browser.
+TEST_F(DirectLayerTreeFrameSinkTest, HitTestRegionList) {
+ RenderPassList pass_list;
+
+ // Add a DrawQuad that is not a SurfaceDrawQuad. |hit_test_region_list_|
+ // shouldn't have any child regions.
+ auto pass1 = RenderPass::Create();
+ pass1->output_rect = display_rect_;
+ pass1->id = 1;
+ auto* shared_quad_state1 = pass1->CreateAndAppendSharedQuadState();
+ gfx::Rect rect1(display_rect_);
+ shared_quad_state1->SetAll(
+ gfx::Transform(), rect1 /* quad_layer_rect */,
+ rect1 /* visible_quad_layer_rect */, rect1 /*clip_rect */,
+ false /* is_clipped */, false /* are_contents_opaque */,
+ 0.5f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
+ auto* quad1 = pass1->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
+ quad1->SetNew(shared_quad_state1, rect1 /* rect */, rect1 /* visible_rect */,
+ SK_ColorBLACK, false /* force_anti_aliasing_off */);
+ pass_list.push_back(std::move(pass1));
+ SendRenderPassList(&pass_list);
+ task_runner_->RunUntilIdle();
+
+ const auto* hit_test_region_list =
+ frame_sink_manager_.hit_test_manager()->GetActiveHitTestRegionList(
+ display_->CurrentSurfaceId());
+ EXPECT_TRUE(hit_test_region_list);
+ EXPECT_EQ(display_rect_, hit_test_region_list->bounds);
+ EXPECT_EQ(mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestMine,
+ hit_test_region_list->flags);
+ EXPECT_FALSE(hit_test_region_list->regions.size());
+
+ // Add a SurfaceDrawQuad to one render pass, and add a SolidColorDrawQuad to
+ // another render pass, and add a SurfaceDrawQuad with a transform that's not
+ // invertible. |hit_test_region_list_| should contain one child
+ // region corresponding to that first SurfaceDrawQuad.
+ const SurfaceId child_surface_id(
+ FrameSinkId(1, 1), LocalSurfaceId(1, base::UnguessableToken::Create()));
+ auto pass2 = RenderPass::Create();
+ pass2->output_rect = display_rect_;
+ pass2->id = 2;
+ auto* shared_quad_state2 = pass2->CreateAndAppendSharedQuadState();
+ gfx::Rect rect2 = gfx::Rect(20, 20);
+ gfx::Transform transform2;
+ transform2.Translate(-200, -100);
+ shared_quad_state2->SetAll(
+ transform2, rect2 /* quad_layer_rect */,
+ rect2 /* visible_quad_layer_rect */, rect2 /*clip_rect */,
+ false /* is_clipped */, false /* are_contents_opaque */,
+ 0.5f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
+ auto* quad2 = pass2->quad_list.AllocateAndConstruct<SurfaceDrawQuad>();
+ quad2->SetNew(shared_quad_state2, rect2 /* rect */, rect2 /* visible_rect */,
+ child_surface_id /* primary_surface_id */,
+ base::Optional<SurfaceId>() /* fallback_surface_id */,
+ SK_ColorBLACK, false /* stretch_content_to_fill_bounds */);
+ pass_list.push_back(std::move(pass2));
+
+ auto pass3 = RenderPass::Create();
+ pass3->output_rect = display_rect_;
+ pass3->id = 3;
+ auto* shared_quad_state3 = pass3->CreateAndAppendSharedQuadState();
+ gfx::Rect rect3(display_rect_);
+ shared_quad_state3->SetAll(
+ gfx::Transform(), rect3 /* quad_layer_rect */,
+ rect3 /* visible_quad_layer_rect */, rect3 /*clip_rect */,
+ false /* is_clipped */, false /* are_contents_opaque */,
+ 0.5f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
+ auto* quad3 = pass3->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
+ quad3->SetNew(shared_quad_state3, rect3 /* rect */, rect3 /* visible_rect */,
+ SK_ColorBLACK, false /* force_anti_aliasing_off */);
+ pass_list.push_back(std::move(pass3));
+ SendRenderPassList(&pass_list);
+ task_runner_->RunUntilIdle();
+
+ const SurfaceId child_surface_id4(
+ FrameSinkId(4, 1), LocalSurfaceId(1, base::UnguessableToken::Create()));
+ auto pass4 = RenderPass::Create();
+ pass4->output_rect = display_rect_;
+ pass4->id = 4;
+ auto* shared_quad_state4 = pass4->CreateAndAppendSharedQuadState();
+ gfx::Rect rect4(display_rect_);
+ // A degenerate matrix of all zeros is not invertible.
+ gfx::Transform transform4;
+ transform4.matrix().set(0, 0, 0.f);
+ transform4.matrix().set(1, 1, 0.f);
+ transform4.matrix().set(2, 2, 0.f);
+ transform4.matrix().set(3, 3, 0.f);
+ shared_quad_state4->SetAll(
+ transform4, rect4 /* quad_layer_rect */,
+ rect4 /* visible_quad_layer_rect */, rect4 /*clip_rect */,
+ false /* is_clipped */, false /* are_contents_opaque */,
+ 0.5f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
+ auto* quad4 = pass4->quad_list.AllocateAndConstruct<SurfaceDrawQuad>();
+ quad4->SetNew(shared_quad_state4, rect4 /* rect */, rect4 /* visible_rect */,
+ child_surface_id4 /* primary_surface_id */,
+ base::Optional<SurfaceId>() /* fallback_surface_id */,
+ SK_ColorBLACK, false /* stretch_content_to_fill_bounds */);
+ pass_list.push_back(std::move(pass4));
+
+ const auto* hit_test_region_list1 =
+ frame_sink_manager_.hit_test_manager()->GetActiveHitTestRegionList(
+ display_->CurrentSurfaceId());
+ EXPECT_TRUE(hit_test_region_list1);
+ EXPECT_EQ(display_rect_, hit_test_region_list1->bounds);
+ EXPECT_EQ(mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestMine,
+ hit_test_region_list1->flags);
+ EXPECT_EQ(1u, hit_test_region_list1->regions.size());
+ EXPECT_EQ(child_surface_id.frame_sink_id(),
+ hit_test_region_list1->regions[0]->frame_sink_id);
+ EXPECT_EQ(child_surface_id.local_surface_id(),
+ hit_test_region_list1->regions[0]->local_surface_id);
+ EXPECT_EQ(
+ mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestChildSurface,
+ hit_test_region_list1->regions[0]->flags);
+ EXPECT_EQ(gfx::Rect(20, 20), hit_test_region_list1->regions[0]->rect);
+ gfx::Transform transform2_inverse;
+ EXPECT_TRUE(transform2.GetInverse(&transform2_inverse));
+ EXPECT_EQ(transform2_inverse, hit_test_region_list1->regions[0]->transform);
+}
+
} // namespace
} // namespace viz
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 8617ed498b6..6e1df891b5a 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
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
#include "components/viz/service/display/display.h"
#include "components/viz/service/display_embedder/display_provider.h"
#include "components/viz/service/display_embedder/external_begin_frame_controller_impl.h"
@@ -37,23 +38,12 @@ FrameSinkManagerImpl::FrameSinkSourceMapping&
FrameSinkManagerImpl::FrameSinkSourceMapping::operator=(
FrameSinkSourceMapping&& other) = default;
-FrameSinkManagerImpl::SinkAndSupport::SinkAndSupport() = default;
-
-FrameSinkManagerImpl::SinkAndSupport::SinkAndSupport(SinkAndSupport&& other) =
- default;
-
-FrameSinkManagerImpl::SinkAndSupport::~SinkAndSupport() = default;
-
-FrameSinkManagerImpl::SinkAndSupport& FrameSinkManagerImpl::SinkAndSupport::
-operator=(SinkAndSupport&& other) = default;
-
FrameSinkManagerImpl::FrameSinkManagerImpl(
- SurfaceManager::LifetimeType lifetime_type,
- uint32_t number_of_frames_to_activation_deadline,
+ base::Optional<uint32_t> activation_deadline_in_frames,
DisplayProvider* display_provider)
: display_provider_(display_provider),
- surface_manager_(lifetime_type, number_of_frames_to_activation_deadline),
- hit_test_manager_(this),
+ surface_manager_(activation_deadline_in_frames),
+ hit_test_manager_(surface_manager()),
binding_(this) {
surface_manager_.AddObserver(&hit_test_manager_);
surface_manager_.AddObserver(this);
@@ -62,10 +52,17 @@ FrameSinkManagerImpl::FrameSinkManagerImpl(
FrameSinkManagerImpl::~FrameSinkManagerImpl() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
video_capturers_.clear();
- // All FrameSinks should be unregistered prior to FrameSinkManager
+
+ // Delete any remaining owned CompositorFrameSinks.
+ sink_map_.clear();
+
+ // All BeginFrameSources should be deleted before FrameSinkManagerImpl
// destruction.
- compositor_frame_sinks_.clear();
- DCHECK_EQ(registered_sources_.size(), 0u);
+ DCHECK(registered_sources_.empty());
+
+ // TODO(kylechar): Enforce that all CompositorFrameSinks are destroyed before
+ // ~FrameSinkManagerImpl() runs.
+
surface_manager_.RemoveObserver(this);
surface_manager_.RemoveObserver(&hit_test_manager_);
}
@@ -104,12 +101,22 @@ void FrameSinkManagerImpl::InvalidateFrameSinkId(
if (video_detector_)
video_detector_->OnFrameSinkIdInvalidated(frame_sink_id);
- // Destroy the [Root]CompositorFrameSinkImpl if there is one. This will result
- // in UnregisterCompositorFrameSinkSupport() being called and |iter| will be
- // invalidated afterwards
- auto iter = compositor_frame_sinks_.find(frame_sink_id);
- if (iter != compositor_frame_sinks_.end())
- iter->second.sink.reset();
+ synchronization_event_labels_.erase(frame_sink_id);
+
+ // Destroy the [Root]CompositorFrameSinkImpl if there is one.
+ sink_map_.erase(frame_sink_id);
+}
+
+void FrameSinkManagerImpl::EnableSynchronizationReporting(
+ const FrameSinkId& frame_sink_id,
+ const std::string& reporting_label) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // TODO(fsamuel): We should move FrameSink labels over to
+ // FrameSinkManagerImpl and unify them with synchronization event labels
+ // and other metadata about FrameSinks.
+ DCHECK_GT(surface_manager_.valid_frame_sink_labels().count(frame_sink_id),
+ 0u);
+ synchronization_event_labels_.emplace(frame_sink_id, reporting_label);
}
void FrameSinkManagerImpl::SetFrameSinkDebugLabel(
@@ -121,7 +128,7 @@ void FrameSinkManagerImpl::SetFrameSinkDebugLabel(
void FrameSinkManagerImpl::CreateRootCompositorFrameSink(
mojom::RootCompositorFrameSinkParamsPtr params) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK_EQ(0u, compositor_frame_sinks_.count(params->frame_sink_id));
+ DCHECK(!base::ContainsKey(sink_map_, params->frame_sink_id));
DCHECK(display_provider_);
std::unique_ptr<ExternalBeginFrameControllerImpl>
@@ -141,17 +148,16 @@ void FrameSinkManagerImpl::CreateRootCompositorFrameSink(
external_begin_frame_controller.get(), params->renderer_settings,
&begin_frame_source);
- auto frame_sink = std::make_unique<RootCompositorFrameSinkImpl>(
- this, params->frame_sink_id, std::move(display),
- std::move(begin_frame_source), std::move(external_begin_frame_controller),
- std::move(params->compositor_frame_sink),
- mojom::CompositorFrameSinkClientPtr(
- std::move(params->compositor_frame_sink_client)),
- std::move(params->display_private),
- mojom::DisplayClientPtr(std::move(params->display_client)));
- SinkAndSupport& entry = compositor_frame_sinks_[params->frame_sink_id];
- DCHECK(entry.support); // |entry| was created by RootCompositorFrameSinkImpl.
- entry.sink = std::move(frame_sink);
+ sink_map_[params->frame_sink_id] =
+ std::make_unique<RootCompositorFrameSinkImpl>(
+ this, params->frame_sink_id, std::move(display),
+ std::move(begin_frame_source),
+ std::move(external_begin_frame_controller),
+ std::move(params->compositor_frame_sink),
+ mojom::CompositorFrameSinkClientPtr(
+ std::move(params->compositor_frame_sink_client)),
+ std::move(params->display_private),
+ mojom::DisplayClientPtr(std::move(params->display_client)));
}
void FrameSinkManagerImpl::CreateCompositorFrameSink(
@@ -159,13 +165,17 @@ void FrameSinkManagerImpl::CreateCompositorFrameSink(
mojom::CompositorFrameSinkRequest request,
mojom::CompositorFrameSinkClientPtr client) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK_EQ(0u, compositor_frame_sinks_.count(frame_sink_id));
+ DCHECK(!base::ContainsKey(sink_map_, frame_sink_id));
- auto frame_sink = std::make_unique<CompositorFrameSinkImpl>(
+ sink_map_[frame_sink_id] = std::make_unique<CompositorFrameSinkImpl>(
this, frame_sink_id, std::move(request), std::move(client));
- SinkAndSupport& entry = compositor_frame_sinks_[frame_sink_id];
- DCHECK(entry.support); // |entry| was created by CompositorFrameSinkImpl.
- entry.sink = std::move(frame_sink);
+}
+
+void FrameSinkManagerImpl::DestroyCompositorFrameSink(
+ const FrameSinkId& frame_sink_id,
+ DestroyCompositorFrameSinkCallback callback) {
+ sink_map_.erase(frame_sink_id);
+ std::move(callback).Run();
}
void FrameSinkManagerImpl::RegisterFrameSinkHierarchy(
@@ -246,18 +256,104 @@ void FrameSinkManagerImpl::CreateVideoCapturer(
std::make_unique<FrameSinkVideoCapturerImpl>(this, std::move(request)));
}
+void FrameSinkManagerImpl::EvictSurfaces(
+ const std::vector<SurfaceId>& surface_ids) {
+ for (const SurfaceId& surface_id : surface_ids) {
+ auto it = support_map_.find(surface_id.frame_sink_id());
+ if (it == support_map_.end())
+ continue;
+ if (it->second->last_activated_surface_id() == surface_id)
+ it->second->EvictLastActivatedSurface();
+ }
+}
+
+void FrameSinkManagerImpl::OnSurfaceCreated(const SurfaceId& surface_id) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ if (client_) {
+ client_->OnSurfaceCreated(surface_id);
+ } else {
+ // There is no client to assign an owner for the temporary reference, so we
+ // can drop the temporary reference safely.
+ surface_manager_.DropTemporaryReference(surface_id);
+ }
+}
+
+void FrameSinkManagerImpl::OnFirstSurfaceActivation(
+ const SurfaceInfo& surface_info) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK_GT(surface_info.device_scale_factor(), 0.0f);
+
+ if (client_)
+ client_->OnFirstSurfaceActivation(surface_info);
+}
+
+void FrameSinkManagerImpl::OnSurfaceActivated(
+ const SurfaceId& surface_id,
+ base::Optional<base::TimeDelta> duration) {
+ if (!duration || !client_)
+ return;
+
+ // If |duration| is populated then there was a synchronization event prior
+ // to this activation.
+ auto it = synchronization_event_labels_.find(surface_id.frame_sink_id());
+ if (it != synchronization_event_labels_.end()) {
+ TRACE_EVENT_INSTANT2(
+ "viz", "SurfaceSynchronizationEvent", TRACE_EVENT_SCOPE_THREAD,
+ "duration_ms", duration->InMilliseconds(), "client_label", it->second);
+ base::UmaHistogramCustomCounts(it->second, duration->InMilliseconds(), 1,
+ 10000, 50);
+ }
+}
+
+bool FrameSinkManagerImpl::OnSurfaceDamaged(const SurfaceId& surface_id,
+ const BeginFrameAck& ack) {
+ return false;
+}
+
+void FrameSinkManagerImpl::OnSurfaceDiscarded(const SurfaceId& surface_id) {}
+
+void FrameSinkManagerImpl::OnSurfaceDestroyed(const SurfaceId& surface_id) {}
+
+void FrameSinkManagerImpl::OnSurfaceDamageExpected(const SurfaceId& surface_id,
+ const BeginFrameArgs& args) {
+}
+
+void FrameSinkManagerImpl::OnAggregatedHitTestRegionListUpdated(
+ const FrameSinkId& frame_sink_id,
+ mojo::ScopedSharedBufferHandle active_handle,
+ uint32_t active_handle_size,
+ mojo::ScopedSharedBufferHandle idle_handle,
+ uint32_t idle_handle_size) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (client_) {
+ client_->OnAggregatedHitTestRegionListUpdated(
+ frame_sink_id, std::move(active_handle), active_handle_size,
+ std::move(idle_handle), idle_handle_size);
+ }
+}
+
+void FrameSinkManagerImpl::SwitchActiveAggregatedHitTestRegionList(
+ const FrameSinkId& frame_sink_id,
+ uint8_t active_handle_index) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (client_) {
+ client_->SwitchActiveAggregatedHitTestRegionList(frame_sink_id,
+ active_handle_index);
+ }
+}
+
void FrameSinkManagerImpl::RegisterCompositorFrameSinkSupport(
const FrameSinkId& frame_sink_id,
CompositorFrameSinkSupport* support) {
DCHECK(support);
+ DCHECK(!base::ContainsKey(support_map_, frame_sink_id));
- SinkAndSupport& entry = compositor_frame_sinks_[frame_sink_id];
- DCHECK(!entry.support);
- entry.support = support;
+ support_map_[frame_sink_id] = support;
for (auto& capturer : video_capturers_) {
if (capturer->requested_target() == frame_sink_id)
- capturer->SetResolvedTarget(entry.support);
+ capturer->SetResolvedTarget(support);
}
auto it = frame_sink_source_map_.find(frame_sink_id);
@@ -267,14 +363,14 @@ void FrameSinkManagerImpl::RegisterCompositorFrameSinkSupport(
void FrameSinkManagerImpl::UnregisterCompositorFrameSinkSupport(
const FrameSinkId& frame_sink_id) {
- DCHECK_EQ(compositor_frame_sinks_.count(frame_sink_id), 1u);
+ DCHECK(base::ContainsKey(support_map_, frame_sink_id));
for (auto& capturer : video_capturers_) {
if (capturer->requested_target() == frame_sink_id)
capturer->OnTargetWillGoAway();
}
- compositor_frame_sinks_.erase(frame_sink_id);
+ support_map_.erase(frame_sink_id);
}
void FrameSinkManagerImpl::RegisterBeginFrameSource(
@@ -321,9 +417,9 @@ void FrameSinkManagerImpl::RecursivelyAttachBeginFrameSource(
FrameSinkSourceMapping& mapping = frame_sink_source_map_[frame_sink_id];
if (!mapping.source) {
mapping.source = source;
- auto iter = compositor_frame_sinks_.find(frame_sink_id);
- if (iter != compositor_frame_sinks_.end())
- iter->second.support->SetBeginFrameSource(source);
+ auto iter = support_map_.find(frame_sink_id);
+ if (iter != support_map_.end())
+ iter->second->SetBeginFrameSource(source);
}
// Copy the list of children because RecursivelyAttachBeginFrameSource() can
@@ -343,9 +439,9 @@ void FrameSinkManagerImpl::RecursivelyDetachBeginFrameSource(
auto& mapping = iter->second;
if (mapping.source == source) {
mapping.source = nullptr;
- auto client_iter = compositor_frame_sinks_.find(frame_sink_id);
- if (client_iter != compositor_frame_sinks_.end())
- client_iter->second.support->SetBeginFrameSource(nullptr);
+ auto client_iter = support_map_.find(frame_sink_id);
+ if (client_iter != support_map_.end())
+ client_iter->second->SetBeginFrameSource(nullptr);
}
// Delete the FrameSinkSourceMapping for |frame_sink_id| if empty.
@@ -363,10 +459,10 @@ void FrameSinkManagerImpl::RecursivelyDetachBeginFrameSource(
CapturableFrameSink* FrameSinkManagerImpl::FindCapturableFrameSink(
const FrameSinkId& frame_sink_id) {
- const auto it = compositor_frame_sinks_.find(frame_sink_id);
- if (it == compositor_frame_sinks_.end())
+ const auto it = support_map_.find(frame_sink_id);
+ if (it == support_map_.end())
return nullptr;
- return it->second.support;
+ return it->second;
}
void FrameSinkManagerImpl::OnCapturerConnectionLost(
@@ -390,43 +486,6 @@ bool FrameSinkManagerImpl::ChildContains(
return false;
}
-void FrameSinkManagerImpl::OnSurfaceCreated(const SurfaceId& surface_id) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
- if (client_) {
- client_->OnSurfaceCreated(surface_id);
- } else {
- // There is no client to assign an owner for the temporary reference, so we
- // can drop the temporary reference safely.
- if (surface_manager_.using_surface_references())
- surface_manager_.DropTemporaryReference(surface_id);
- }
-}
-
-void FrameSinkManagerImpl::OnFirstSurfaceActivation(
- const SurfaceInfo& surface_info) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK_GT(surface_info.device_scale_factor(), 0.0f);
-
- if (client_)
- client_->OnFirstSurfaceActivation(surface_info);
-}
-
-void FrameSinkManagerImpl::OnSurfaceActivated(const SurfaceId& surface_id) {}
-
-bool FrameSinkManagerImpl::OnSurfaceDamaged(const SurfaceId& surface_id,
- const BeginFrameAck& ack) {
- return false;
-}
-
-void FrameSinkManagerImpl::OnSurfaceDiscarded(const SurfaceId& surface_id) {}
-
-void FrameSinkManagerImpl::OnSurfaceDestroyed(const SurfaceId& surface_id) {}
-
-void FrameSinkManagerImpl::OnSurfaceDamageExpected(const SurfaceId& surface_id,
- const BeginFrameArgs& args) {
-}
-
void FrameSinkManagerImpl::OnClientConnectionLost(
const FrameSinkId& frame_sink_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -442,41 +501,12 @@ void FrameSinkManagerImpl::SubmitHitTestRegionList(
std::move(hit_test_region_list));
}
-uint64_t FrameSinkManagerImpl::GetActiveFrameIndex(
- const SurfaceId& surface_id) {
- return surface_manager_.GetSurfaceForId(surface_id)->GetActiveFrameIndex();
-}
-
void FrameSinkManagerImpl::OnFrameTokenChanged(const FrameSinkId& frame_sink_id,
uint32_t frame_token) {
if (client_)
client_->OnFrameTokenChanged(frame_sink_id, frame_token);
}
-void FrameSinkManagerImpl::OnAggregatedHitTestRegionListUpdated(
- const FrameSinkId& frame_sink_id,
- mojo::ScopedSharedBufferHandle active_handle,
- uint32_t active_handle_size,
- mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_size) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (client_) {
- client_->OnAggregatedHitTestRegionListUpdated(
- frame_sink_id, std::move(active_handle), active_handle_size,
- std::move(idle_handle), idle_handle_size);
- }
-}
-
-void FrameSinkManagerImpl::SwitchActiveAggregatedHitTestRegionList(
- const FrameSinkId& frame_sink_id,
- uint8_t active_handle_index) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (client_) {
- client_->SwitchActiveAggregatedHitTestRegionList(frame_sink_id,
- active_handle_index);
- }
-}
-
VideoDetector* FrameSinkManagerImpl::CreateVideoDetectorForTesting(
std::unique_ptr<base::TickClock> tick_clock,
scoped_refptr<base::SequencedTaskRunner> task_runner) {
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 58798be24a1..1e735273daf 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
@@ -9,17 +9,20 @@
#include <memory>
#include <string>
+#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
-#include "base/containers/unique_ptr_comparator.h"
+#include "base/containers/unique_ptr_adapters.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/threading/thread_checker.h"
+#include "components/viz/common/constants.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/service/frame_sinks/primary_begin_frame_source.h"
#include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_manager.h"
#include "components/viz/service/frame_sinks/video_detector.h"
+#include "components/viz/service/hit_test/hit_test_aggregator_delegate.h"
#include "components/viz/service/hit_test/hit_test_manager.h"
#include "components/viz/service/surfaces/surface_manager.h"
#include "components/viz/service/surfaces/surface_observer.h"
@@ -41,11 +44,11 @@ class DisplayProvider;
class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
: public SurfaceObserver,
public FrameSinkVideoCapturerManager,
- public mojom::FrameSinkManager {
+ public mojom::FrameSinkManager,
+ public HitTestAggregatorDelegate {
public:
- FrameSinkManagerImpl(SurfaceManager::LifetimeType lifetime_type =
- SurfaceManager::LifetimeType::REFERENCES,
- uint32_t number_of_frames_to_activation_deadline = 4u,
+ FrameSinkManagerImpl(base::Optional<uint32_t> activation_deadline_in_frames =
+ kDefaultActivationDeadlineInFrames,
DisplayProvider* display_provider = nullptr);
~FrameSinkManagerImpl() override;
@@ -62,6 +65,9 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
// mojom::FrameSinkManager implementation:
void RegisterFrameSinkId(const FrameSinkId& frame_sink_id) override;
void InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) override;
+ void EnableSynchronizationReporting(
+ const FrameSinkId& frame_sink_id,
+ const std::string& reporting_label) override;
void SetFrameSinkDebugLabel(const FrameSinkId& frame_sink_id,
const std::string& debug_label) override;
void CreateRootCompositorFrameSink(
@@ -70,6 +76,9 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
const FrameSinkId& frame_sink_id,
mojom::CompositorFrameSinkRequest request,
mojom::CompositorFrameSinkClientPtr client) override;
+ void DestroyCompositorFrameSink(
+ const FrameSinkId& frame_sink_id,
+ DestroyCompositorFrameSinkCallback callback) override;
void RegisterFrameSinkHierarchy(
const FrameSinkId& parent_frame_sink_id,
const FrameSinkId& child_frame_sink_id) override;
@@ -83,6 +92,30 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
mojom::VideoDetectorObserverPtr observer) override;
void CreateVideoCapturer(
mojom::FrameSinkVideoCapturerRequest request) override;
+ void EvictSurfaces(const std::vector<SurfaceId>& surface_ids) override;
+
+ // SurfaceObserver implementation.
+ void OnSurfaceCreated(const SurfaceId& surface_id) override;
+ void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override;
+ void OnSurfaceActivated(const SurfaceId& surface_id,
+ base::Optional<base::TimeDelta> duration) override;
+ bool OnSurfaceDamaged(const SurfaceId& surface_id,
+ const BeginFrameAck& ack) override;
+ void OnSurfaceDiscarded(const SurfaceId& surface_id) override;
+ void OnSurfaceDestroyed(const SurfaceId& surface_id) override;
+ void OnSurfaceDamageExpected(const SurfaceId& surface_id,
+ const BeginFrameArgs& args) override;
+
+ // HitTestAggregatorDelegate implementation:
+ void OnAggregatedHitTestRegionListUpdated(
+ const FrameSinkId& frame_sink_id,
+ mojo::ScopedSharedBufferHandle active_handle,
+ uint32_t active_handle_size,
+ mojo::ScopedSharedBufferHandle idle_handle,
+ uint32_t idle_handle_size) override;
+ void SwitchActiveAggregatedHitTestRegionList(
+ const FrameSinkId& frame_sink_id,
+ uint8_t active_handle_index) override;
// CompositorFrameSinkSupport, hierarchy, and BeginFrameSource can be
// registered and unregistered in any order with respect to each other.
@@ -113,43 +146,13 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
const HitTestManager* hit_test_manager() { return &hit_test_manager_; }
- // SurfaceObserver implementation.
- void OnSurfaceCreated(const SurfaceId& surface_id) override;
- void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override;
- void OnSurfaceActivated(const SurfaceId& surface_id) override;
- bool OnSurfaceDamaged(const SurfaceId& surface_id,
- const BeginFrameAck& ack) override;
- void OnSurfaceDiscarded(const SurfaceId& surface_id) override;
- void OnSurfaceDestroyed(const SurfaceId& surface_id) override;
- void OnSurfaceDamageExpected(const SurfaceId& surface_id,
- const BeginFrameArgs& args) override;
-
void OnClientConnectionLost(const FrameSinkId& frame_sink_id);
- void OnAggregatedHitTestRegionListUpdated(
- const FrameSinkId& frame_sink_id,
- mojo::ScopedSharedBufferHandle active_handle,
- uint32_t active_handle_size,
- mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_size);
- void SwitchActiveAggregatedHitTestRegionList(const FrameSinkId& frame_sink_id,
- uint8_t active_handle_index);
-
- // It is necessary to pass |frame_sink_id| by value because the id
- // is owned by the GpuCompositorFrameSink in the map. When the sink is
- // removed from the map, |frame_sink_id| would also be destroyed if it were a
- // reference. But the map can continue to iterate and try to use it. Passing
- // by value avoids this.
- void DestroyCompositorFrameSink(FrameSinkId frame_sink_id);
-
void SubmitHitTestRegionList(
const SurfaceId& surface_id,
uint64_t frame_index,
mojom::HitTestRegionListPtr hit_test_region_list);
- // This method is virtual so the implementation can be modified in unit tests.
- virtual uint64_t GetActiveFrameIndex(const SurfaceId& surface_id);
-
// Instantiates |video_detector_| for tests where we simulate the passage of
// time.
VideoDetector* CreateVideoDetectorForTesting(
@@ -180,23 +183,6 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
DISALLOW_COPY_AND_ASSIGN(FrameSinkSourceMapping);
};
- struct SinkAndSupport {
- SinkAndSupport();
- SinkAndSupport(SinkAndSupport&& other);
- ~SinkAndSupport();
- SinkAndSupport& operator=(SinkAndSupport&& other);
-
- // CompositorFrameSinks owned here. This will be null if a
- // CompositorFrameSinkSupport is owned externally.
- std::unique_ptr<mojom::CompositorFrameSink> sink;
-
- // This can be owned by |sink| or owned externally.
- CompositorFrameSinkSupport* support = nullptr;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SinkAndSupport);
- };
-
void RecursivelyAttachBeginFrameSource(const FrameSinkId& frame_sink_id,
BeginFrameSource* source);
void RecursivelyDetachBeginFrameSource(const FrameSinkId& frame_sink_id,
@@ -223,8 +209,17 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
// Contains FrameSinkId hierarchy and BeginFrameSource mapping.
base::flat_map<FrameSinkId, FrameSinkSourceMapping> frame_sink_source_map_;
- // Contains (and maybe owns) the CompositorFrameSinkSupport.
- base::flat_map<FrameSinkId, SinkAndSupport> compositor_frame_sinks_;
+ // CompositorFrameSinkSupports get added to this map on creation and removed
+ // on destruction.
+ base::flat_map<FrameSinkId, CompositorFrameSinkSupport*> support_map_;
+
+ // [Root]CompositorFrameSinkImpls are owned in this map.
+ base::flat_map<FrameSinkId, std::unique_ptr<mojom::CompositorFrameSink>>
+ sink_map_;
+
+ // The set of FrameSinkIds that the client wants synchronization event
+ // notifications for.
+ base::flat_map<FrameSinkId, std::string> synchronization_event_labels_;
PrimaryBeginFrameSource primary_source_;
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 9b5a2a6de89..5de7b02358f 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
@@ -2,25 +2,57 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+
#include <stddef.h>
+#include "components/viz/common/constants.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/surfaces/parent_local_surface_id_allocator.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/test/begin_frame_source_test.h"
+#include "components/viz/test/compositor_frame_helpers.h"
#include "components/viz/test/fake_external_begin_frame_source.h"
+#include "components/viz/test/mock_compositor_frame_sink_client.h"
+#include "components/viz/test/mock_display_client.h"
+#include "components/viz/test/test_display_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace viz {
namespace {
-constexpr FrameSinkId kArbitraryFrameSinkId(1, 1);
+constexpr FrameSinkId kFrameSinkIdRoot(1, 1);
+constexpr FrameSinkId kFrameSinkIdA(2, 1);
+constexpr FrameSinkId kFrameSinkIdB(3, 1);
+constexpr FrameSinkId kFrameSinkIdC(4, 1);
+
+// Holds the four interface objects needed to create a RootCompositorFrameSink.
+struct RootCompositorFrameSinkData {
+ mojom::RootCompositorFrameSinkParamsPtr BuildParams(
+ const FrameSinkId& frame_sink_id) {
+ auto params = mojom::RootCompositorFrameSinkParams::New();
+ params->frame_sink_id = frame_sink_id;
+ params->widget = gpu::kNullSurfaceHandle;
+ params->compositor_frame_sink = MakeRequest(&compositor_frame_sink);
+ params->compositor_frame_sink_client =
+ compositor_frame_sink_client.BindInterfacePtr().PassInterface();
+ params->display_private = MakeRequest(&display_private);
+ params->display_client = display_client.BindInterfacePtr().PassInterface();
+ return params;
+ }
+
+ mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink;
+ MockCompositorFrameSinkClient compositor_frame_sink_client;
+ mojom::DisplayPrivateAssociatedPtr display_private;
+ MockDisplayClient display_client;
+};
} // namespace
class FrameSinkManagerTest : public testing::Test {
public:
- FrameSinkManagerTest() = default;
+ FrameSinkManagerTest()
+ : manager_(kDefaultActivationDeadlineInFrames, &provider) {}
~FrameSinkManagerTest() override = default;
std::unique_ptr<CompositorFrameSinkSupport> CreateCompositorFrameSinkSupport(
@@ -34,16 +66,55 @@ class FrameSinkManagerTest : public testing::Test {
return support->begin_frame_source_;
}
+ // Checks if a [Root]CompositorFrameSinkImpl exists for |frame_sink_id|.
+ bool CompositorFrameSinkExists(const FrameSinkId& frame_sink_id) {
+ return base::ContainsKey(manager_.sink_map_, frame_sink_id);
+ }
+
// testing::Test implementation.
void TearDown() override {
// Make sure that all FrameSinkSourceMappings have been deleted.
EXPECT_TRUE(manager_.frame_sink_source_map_.empty());
+
+ // Make sure test cleans up all [Root]CompositorFrameSinkImpls.
+ EXPECT_TRUE(manager_.support_map_.empty());
}
protected:
+ TestDisplayProvider provider;
FrameSinkManagerImpl manager_;
};
+TEST_F(FrameSinkManagerTest, CreateRootCompositorFrameSink) {
+ manager_.RegisterFrameSinkId(kFrameSinkIdRoot);
+
+ // Create a RootCompositorFrameSinkImpl.
+ RootCompositorFrameSinkData root_data;
+ manager_.CreateRootCompositorFrameSink(
+ root_data.BuildParams(kFrameSinkIdRoot));
+ EXPECT_TRUE(CompositorFrameSinkExists(kFrameSinkIdRoot));
+
+ // Invalidating should destroy the RootCompositorFrameSinkImpl.
+ manager_.InvalidateFrameSinkId(kFrameSinkIdRoot);
+ EXPECT_FALSE(CompositorFrameSinkExists(kFrameSinkIdRoot));
+}
+
+TEST_F(FrameSinkManagerTest, CreateCompositorFrameSink) {
+ manager_.RegisterFrameSinkId(kFrameSinkIdA);
+
+ // Create a CompositorFrameSinkImpl.
+ MockCompositorFrameSinkClient compositor_frame_sink_client;
+ mojom::CompositorFrameSinkPtr compositor_frame_sink;
+ manager_.CreateCompositorFrameSink(
+ kFrameSinkIdA, MakeRequest(&compositor_frame_sink),
+ compositor_frame_sink_client.BindInterfacePtr());
+ EXPECT_TRUE(CompositorFrameSinkExists(kFrameSinkIdA));
+
+ // Invalidating should destroy the CompositorFrameSinkImpl.
+ manager_.InvalidateFrameSinkId(kFrameSinkIdA);
+ EXPECT_FALSE(CompositorFrameSinkExists(kFrameSinkIdA));
+}
+
TEST_F(FrameSinkManagerTest, SingleClients) {
auto client = CreateCompositorFrameSinkSupport(FrameSinkId(1, 1));
auto other_client = CreateCompositorFrameSinkSupport(FrameSinkId(2, 2));
@@ -78,16 +149,16 @@ TEST_F(FrameSinkManagerTest, SingleClients) {
// This test verifies that a client is still connected to the BeginFrameSource
// after restart.
TEST_F(FrameSinkManagerTest, ClientRestart) {
- auto client = CreateCompositorFrameSinkSupport(kArbitraryFrameSinkId);
+ auto client = CreateCompositorFrameSinkSupport(kFrameSinkIdRoot);
StubBeginFrameSource source;
- manager_.RegisterBeginFrameSource(&source, kArbitraryFrameSinkId);
+ manager_.RegisterBeginFrameSource(&source, kFrameSinkIdRoot);
EXPECT_EQ(&source, GetBeginFrameSource(client));
client.reset();
// |client| is reconnected with |source| after being recreated..
- client = CreateCompositorFrameSinkSupport(kArbitraryFrameSinkId);
+ client = CreateCompositorFrameSinkSupport(kFrameSinkIdRoot);
EXPECT_EQ(&source, GetBeginFrameSource(client));
manager_.UnregisterBeginFrameSource(&source);
@@ -233,11 +304,6 @@ TEST_F(FrameSinkManagerTest, MultipleDisplays) {
TEST_F(FrameSinkManagerTest, ParentWithoutClientRetained) {
StubBeginFrameSource root_source;
- constexpr FrameSinkId kFrameSinkIdRoot(1, 1);
- constexpr FrameSinkId kFrameSinkIdA(2, 2);
- constexpr FrameSinkId kFrameSinkIdB(3, 3);
- constexpr FrameSinkId kFrameSinkIdC(4, 4);
-
auto root = CreateCompositorFrameSinkSupport(kFrameSinkIdRoot);
auto client_b = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
auto client_c = CreateCompositorFrameSinkSupport(kFrameSinkIdC);
@@ -276,11 +342,6 @@ TEST_F(FrameSinkManagerTest,
ParentWithoutClientRetained_LateBeginFrameRegistration) {
StubBeginFrameSource root_source;
- constexpr FrameSinkId kFrameSinkIdRoot(1, 1);
- constexpr FrameSinkId kFrameSinkIdA(2, 2);
- constexpr FrameSinkId kFrameSinkIdB(3, 3);
- constexpr FrameSinkId kFrameSinkIdC(4, 4);
-
auto root = CreateCompositorFrameSinkSupport(kFrameSinkIdRoot);
auto client_b = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
auto client_c = CreateCompositorFrameSinkSupport(kFrameSinkIdC);
@@ -312,11 +373,35 @@ TEST_F(FrameSinkManagerTest,
manager_.UnregisterFrameSinkHierarchy(kFrameSinkIdA, kFrameSinkIdC);
}
-namespace {
+// Verifies that the SurfaceIds passed to EvictSurfaces will be destroyed in the
+// next garbage collection.
+TEST_F(FrameSinkManagerTest, EvictSurfaces) {
+ ParentLocalSurfaceIdAllocator allocator;
+ LocalSurfaceId local_surface_id1 = allocator.GenerateId();
+ LocalSurfaceId local_surface_id2 = allocator.GenerateId();
+ SurfaceId surface_id1(kFrameSinkIdA, local_surface_id1);
+ SurfaceId surface_id2(kFrameSinkIdB, local_surface_id2);
+
+ // Create two frame sinks. Each create a surface.
+ auto sink1 = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+ auto sink2 = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
+ sink1->SubmitCompositorFrame(local_surface_id1, MakeDefaultCompositorFrame());
+ sink2->SubmitCompositorFrame(local_surface_id2, MakeDefaultCompositorFrame());
+
+ // |surface_id1| and |surface_id2| should remain alive after garbage
+ // collection because they're not marked for destruction.
+ manager_.surface_manager()->GarbageCollectSurfaces();
+ EXPECT_TRUE(manager_.surface_manager()->GetSurfaceForId(surface_id1));
+ EXPECT_TRUE(manager_.surface_manager()->GetSurfaceForId(surface_id2));
+
+ // Call EvictSurfaces. Now the garbage collector can destroy the surfaces.
+ manager_.EvictSurfaces({surface_id1, surface_id2});
+ manager_.surface_manager()->GarbageCollectSurfaces();
+ EXPECT_FALSE(manager_.surface_manager()->GetSurfaceForId(surface_id1));
+ EXPECT_FALSE(manager_.surface_manager()->GetSurfaceForId(surface_id2));
+}
-constexpr FrameSinkId kClientIdA(1, 1);
-constexpr FrameSinkId kClientIdB(2, 2);
-constexpr FrameSinkId kClientIdC(3, 3);
+namespace {
enum RegisterOrder { REGISTER_HIERARCHY_FIRST, REGISTER_CLIENTS_FIRST };
enum UnregisterOrder { UNREGISTER_HIERARCHY_FIRST, UNREGISTER_CLIENTS_FIRST };
@@ -354,24 +439,24 @@ class FrameSinkManagerOrderingTest : public FrameSinkManagerTest {
void RegisterHierarchy() {
DCHECK(!hierarchy_registered_);
hierarchy_registered_ = true;
- manager_.RegisterFrameSinkHierarchy(kClientIdA, kClientIdB);
- manager_.RegisterFrameSinkHierarchy(kClientIdB, kClientIdC);
+ manager_.RegisterFrameSinkHierarchy(kFrameSinkIdA, kFrameSinkIdB);
+ manager_.RegisterFrameSinkHierarchy(kFrameSinkIdB, kFrameSinkIdC);
AssertCorrectBFSState();
}
void UnregisterHierarchy() {
DCHECK(hierarchy_registered_);
hierarchy_registered_ = false;
- manager_.UnregisterFrameSinkHierarchy(kClientIdA, kClientIdB);
- manager_.UnregisterFrameSinkHierarchy(kClientIdB, kClientIdC);
+ manager_.UnregisterFrameSinkHierarchy(kFrameSinkIdA, kFrameSinkIdB);
+ manager_.UnregisterFrameSinkHierarchy(kFrameSinkIdB, kFrameSinkIdC);
AssertCorrectBFSState();
}
void RegisterClients() {
DCHECK(!clients_registered_);
clients_registered_ = true;
- client_a_ = CreateCompositorFrameSinkSupport(kClientIdA);
- client_b_ = CreateCompositorFrameSinkSupport(kClientIdB);
- client_c_ = CreateCompositorFrameSinkSupport(kClientIdC);
+ client_a_ = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+ client_b_ = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
+ client_c_ = CreateCompositorFrameSinkSupport(kFrameSinkIdC);
AssertCorrectBFSState();
}
@@ -387,7 +472,7 @@ class FrameSinkManagerOrderingTest : public FrameSinkManagerTest {
void RegisterBFS() {
DCHECK(!bfs_registered_);
bfs_registered_ = true;
- manager_.RegisterBeginFrameSource(&source_, kClientIdA);
+ manager_.RegisterBeginFrameSource(&source_, kFrameSinkIdA);
AssertCorrectBFSState();
}
void UnregisterBFS() {
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 9f80d6145ad..293d6f02918 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
@@ -10,6 +10,7 @@
#include "components/viz/service/display/display.h"
#include "components/viz/service/display_embedder/external_begin_frame_controller_impl.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/service/hit_test/hit_test_aggregator.h"
namespace viz {
@@ -37,8 +38,7 @@ RootCompositorFrameSinkImpl::RootCompositorFrameSinkImpl(
synthetic_begin_frame_source_(std::move(synthetic_begin_frame_source)),
external_begin_frame_controller_(
std::move(external_begin_frame_controller)),
- display_(std::move(display)),
- hit_test_aggregator_(frame_sink_manager->hit_test_manager(), this) {
+ display_(std::move(display)) {
DCHECK(begin_frame_source());
DCHECK(display_);
@@ -50,6 +50,7 @@ RootCompositorFrameSinkImpl::RootCompositorFrameSinkImpl(
frame_sink_manager->RegisterBeginFrameSource(begin_frame_source(),
frame_sink_id);
display_->Initialize(this, frame_sink_manager->surface_manager());
+ support_->SetUpHitTest();
}
RootCompositorFrameSinkImpl::~RootCompositorFrameSinkImpl() {
@@ -84,6 +85,13 @@ void RootCompositorFrameSinkImpl::SetAuthoritativeVSyncInterval(
synthetic_begin_frame_source_->SetAuthoritativeVSyncInterval(interval);
}
+void RootCompositorFrameSinkImpl::SetDisplayVSyncParameters(
+ base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ if (synthetic_begin_frame_source_)
+ synthetic_begin_frame_source_->OnUpdateVSyncParameters(timebase, interval);
+}
+
void RootCompositorFrameSinkImpl::SetNeedsBeginFrame(bool needs_begin_frame) {
support_->SetNeedsBeginFrame(needs_begin_frame);
}
@@ -98,17 +106,23 @@ void RootCompositorFrameSinkImpl::SubmitCompositorFrame(
mojom::HitTestRegionListPtr hit_test_region_list,
uint64_t submit_time) {
// Update display when size or local surface id changes.
- if (support_->local_surface_id() != local_surface_id) {
+ if (support_->last_activated_local_surface_id() != local_surface_id) {
display_->Resize(frame.size_in_pixels());
display_->SetLocalSurfaceId(local_surface_id, frame.device_scale_factor());
}
- if (!support_->SubmitCompositorFrame(local_surface_id, std::move(frame),
- std::move(hit_test_region_list))) {
- DLOG(ERROR) << "SubmitCompositorFrame failed for " << local_surface_id;
- compositor_frame_sink_binding_.Close();
- OnClientConnectionLost();
- }
+ const auto result = support_->MaybeSubmitCompositorFrame(
+ local_surface_id, std::move(frame), std::move(hit_test_region_list));
+ if (result == CompositorFrameSinkSupport::ACCEPTED)
+ return;
+
+ const char* reason =
+ CompositorFrameSinkSupport::GetSubmitResultAsString(result);
+ DLOG(ERROR) << "SubmitCompositorFrame failed for " << local_surface_id
+ << " because " << reason;
+ compositor_frame_sink_binding_.CloseWithReason(static_cast<uint32_t>(result),
+ reason);
+ OnClientConnectionLost();
}
void RootCompositorFrameSinkImpl::DidNotProduceFrame(
@@ -116,20 +130,20 @@ void RootCompositorFrameSinkImpl::DidNotProduceFrame(
support_->DidNotProduceFrame(begin_frame_ack);
}
-void RootCompositorFrameSinkImpl::OnAggregatedHitTestRegionListUpdated(
- mojo::ScopedSharedBufferHandle active_handle,
- uint32_t active_handle_size,
- mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_size) {
- support_->frame_sink_manager()->OnAggregatedHitTestRegionListUpdated(
- support_->frame_sink_id(), std::move(active_handle), active_handle_size,
- std::move(idle_handle), idle_handle_size);
+void RootCompositorFrameSinkImpl::DidAllocateSharedBitmap(
+ mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) {
+ if (!support_->DidAllocateSharedBitmap(std::move(buffer), id)) {
+ DLOG(ERROR) << "DidAllocateSharedBitmap failed for duplicate "
+ << "SharedBitmapId";
+ compositor_frame_sink_binding_.Close();
+ OnClientConnectionLost();
+ }
}
-void RootCompositorFrameSinkImpl::SwitchActiveAggregatedHitTestRegionList(
- uint8_t active_handle_index) {
- support_->frame_sink_manager()->SwitchActiveAggregatedHitTestRegionList(
- support_->frame_sink_id(), active_handle_index);
+void RootCompositorFrameSinkImpl::DidDeleteSharedBitmap(
+ const SharedBitmapId& id) {
+ support_->DidDeleteSharedBitmap(id);
}
void RootCompositorFrameSinkImpl::DisplayOutputSurfaceLost() {
@@ -140,7 +154,8 @@ void RootCompositorFrameSinkImpl::DisplayOutputSurfaceLost() {
void RootCompositorFrameSinkImpl::DisplayWillDrawAndSwap(
bool will_draw_and_swap,
const RenderPassList& render_pass) {
- hit_test_aggregator_.Aggregate(display_->CurrentSurfaceId());
+ DCHECK(support_->GetHitTestAggregator());
+ support_->GetHitTestAggregator()->Aggregate(display_->CurrentSurfaceId());
}
void RootCompositorFrameSinkImpl::DisplayDidReceiveCALayerParams(
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 12b72f2abb2..1861476a049 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
@@ -11,8 +11,6 @@
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/service/display/display_client.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
-#include "components/viz/service/hit_test/hit_test_aggregator.h"
-#include "components/viz/service/hit_test/hit_test_aggregator_delegate.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
@@ -28,8 +26,7 @@ class SyntheticBeginFrameSource;
// for the mojom::CompositorFrameSink interface and owns the Display.
class RootCompositorFrameSinkImpl : public mojom::CompositorFrameSink,
public mojom::DisplayPrivate,
- public DisplayClient,
- public HitTestAggregatorDelegate {
+ public DisplayClient {
public:
RootCompositorFrameSinkImpl(
FrameSinkManagerImpl* frame_sink_manager,
@@ -54,6 +51,8 @@ class RootCompositorFrameSinkImpl : public mojom::CompositorFrameSink,
const gfx::ColorSpace& device_color_space) override;
void SetOutputIsSecure(bool secure) override;
void SetAuthoritativeVSyncInterval(base::TimeDelta interval) override;
+ void SetDisplayVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) override;
// mojom::CompositorFrameSink:
void SetNeedsBeginFrame(bool needs_begin_frame) override;
@@ -63,15 +62,9 @@ class RootCompositorFrameSinkImpl : public mojom::CompositorFrameSink,
mojom::HitTestRegionListPtr hit_test_region_list,
uint64_t submit_time) override;
void DidNotProduceFrame(const BeginFrameAck& begin_frame_ack) override;
-
- // HitTestAggregatorDelegate:
- void OnAggregatedHitTestRegionListUpdated(
- mojo::ScopedSharedBufferHandle active_handle,
- uint32_t active_handle_size,
- mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_size) override;
- void SwitchActiveAggregatedHitTestRegionList(
- uint8_t active_handle_index) override;
+ void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
+ const SharedBitmapId& id) override;
+ void DidDeleteSharedBitmap(const SharedBitmapId& id) override;
private:
// DisplayClient:
@@ -105,8 +98,6 @@ class RootCompositorFrameSinkImpl : public mojom::CompositorFrameSink,
external_begin_frame_controller_;
std::unique_ptr<Display> display_;
- HitTestAggregator hit_test_aggregator_;
-
DISALLOW_COPY_AND_ASSIGN(RootCompositorFrameSinkImpl);
};
diff --git a/chromium/components/viz/service/frame_sinks/surface_references_unittest.cc b/chromium/components/viz/service/frame_sinks/surface_references_unittest.cc
index 3c85840fefc..5d8bb5073d5 100644
--- a/chromium/components/viz/service/frame_sinks/surface_references_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/surface_references_unittest.cc
@@ -59,7 +59,7 @@ class SurfaceReferencesTest : public testing::Test {
// Destroy Surface with |surface_id|.
void DestroySurface(const SurfaceId& surface_id) {
GetCompositorFrameSinkSupport(surface_id.frame_sink_id())
- .EvictCurrentSurface();
+ .EvictLastActivatedSurface();
}
CompositorFrameSinkSupport& GetCompositorFrameSinkSupport(
@@ -119,6 +119,10 @@ class SurfaceReferencesTest : public testing::Test {
return manager_->surface_manager()->valid_frame_sink_labels_;
}
+ bool IsTemporaryReferenceTimerRunning() const {
+ return manager_->surface_manager()->expire_timer_->IsRunning();
+ }
+
protected:
// testing::Test:
void SetUp() override {
@@ -129,8 +133,6 @@ class SurfaceReferencesTest : public testing::Test {
manager_->SetLocalClient(frame_sink_manager_client_.get());
}
void TearDown() override {
- for (auto& support : supports_)
- support.second->EvictCurrentSurface();
supports_.clear();
manager_.reset();
}
@@ -643,20 +645,27 @@ TEST_F(SurfaceReferencesTest, MarkOldTemporaryReferences) {
constexpr base::TimeDelta kFastForwardTime = base::TimeDelta::FromSeconds(30);
- // Creating the surface should create a temporary reference.
+ // There are no temporary references so the timer should be stopped.
+ EXPECT_FALSE(IsTemporaryReferenceTimerRunning());
+
+ // Creating the surface should create a temporary reference and start timer.
const SurfaceId id = CreateSurface(kFrameSink2, 1);
ASSERT_THAT(GetAllTempReferences(), UnorderedElementsAre(id));
+ EXPECT_TRUE(IsTemporaryReferenceTimerRunning());
// The temporary reference should not be marked as old and then deleted
// because the surface is still alive.
task_runner_->FastForwardBy(kFastForwardTime);
ASSERT_THAT(GetAllTempReferences(), UnorderedElementsAre(id));
+ EXPECT_TRUE(IsTemporaryReferenceTimerRunning());
// After the surface is marked as destroyed, the temporary reference should
- // be marked as old then deleted.
+ // be marked as old then deleted. The timer should stop because there are no
+ // temporary references.
DestroySurface(id);
task_runner_->FastForwardBy(kFastForwardTime);
ASSERT_THAT(GetAllTempReferences(), IsEmpty());
+ EXPECT_FALSE(IsTemporaryReferenceTimerRunning());
}
} // namespace test
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 8333029bc8d..d727862930f 100644
--- a/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
@@ -49,13 +49,13 @@ CompositorFrame MakeCompositorFrame(
std::vector<SurfaceId> activation_dependencies,
std::vector<SurfaceId> referenced_surfaces,
std::vector<TransferableResource> resource_list,
- base::Optional<uint32_t> deadline_in_frames = base::nullopt) {
+ const FrameDeadline& deadline = FrameDeadline()) {
return CompositorFrameBuilder()
.AddDefaultRenderPass()
.SetActivationDependencies(std::move(activation_dependencies))
.SetReferencedSurfaces(std::move(referenced_surfaces))
.SetTransferableResources(std::move(resource_list))
- .SetDeadlineInFrames(deadline_in_frames)
+ .SetDeadline(deadline)
.Build();
}
@@ -94,28 +94,28 @@ class SurfaceSynchronizationTest : public testing::Test {
return *supports_[kDisplayFrameSink];
}
Surface* display_surface() {
- return display_support().GetCurrentSurfaceForTesting();
+ return display_support().GetLastCreatedSurfaceForTesting();
}
CompositorFrameSinkSupport& parent_support() {
return *supports_[kParentFrameSink];
}
Surface* parent_surface() {
- return parent_support().GetCurrentSurfaceForTesting();
+ return parent_support().GetLastCreatedSurfaceForTesting();
}
CompositorFrameSinkSupport& child_support1() {
return *supports_[kChildFrameSink1];
}
Surface* child_surface1() {
- return child_support1().GetCurrentSurfaceForTesting();
+ return child_support1().GetLastCreatedSurfaceForTesting();
}
CompositorFrameSinkSupport& child_support2() {
return *supports_[kChildFrameSink2];
}
Surface* child_surface2() {
- return child_support2().GetCurrentSurfaceForTesting();
+ return child_support2().GetLastCreatedSurfaceForTesting();
}
void CreateFrameSink(const FrameSinkId& frame_sink_id, bool is_root) {
@@ -157,6 +157,12 @@ class SurfaceSynchronizationTest : public testing::Test {
return begin_frame_source_.get();
}
+ base::TimeTicks Now() { return now_src_->NowTicks(); }
+
+ FrameDeadline MakeDefaultDeadline() {
+ return FrameDeadline(Now(), 4u, BeginFrameArgs::DefaultInterval(), false);
+ }
+
void SendNextBeginFrame() {
// Creep the time forward so that any BeginFrameArgs is not equal to the
// last one otherwise we violate the BeginFrameSource contract.
@@ -166,6 +172,15 @@ class SurfaceSynchronizationTest : public testing::Test {
begin_frame_source_->TestOnBeginFrame(args);
}
+ void SendLateBeginFrame() {
+ // Creep the time forward so that any BeginFrameArgs is not equal to the
+ // last one otherwise we violate the BeginFrameSource contract.
+ now_src_->Advance(4u * BeginFrameArgs::DefaultInterval());
+ BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
+ BEGINFRAME_FROM_HERE, now_src_.get());
+ begin_frame_source_->TestOnBeginFrame(args);
+ }
+
void SetFrameSinkHierarchy(const FrameSinkId& parent_frame_sink_id,
const FrameSinkId& child_frame_sink_id) {
frame_sink_manager_client_.SetFrameSinkHierarchy(parent_frame_sink_id,
@@ -186,6 +201,8 @@ class SurfaceSynchronizationTest : public testing::Test {
std::make_unique<FakeExternalBeginFrameSource>(0.f, false);
begin_frame_source_->SetClient(&begin_frame_source_client_);
now_src_ = std::make_unique<base::SimpleTestTickClock>();
+ frame_sink_manager_.surface_manager()->SetTickClockForTesting(
+ now_src_.get());
frame_sink_manager_.surface_manager()->AddObserver(&surface_observer_);
frame_sink_manager_.SetLocalClient(&frame_sink_manager_client_);
supports_[kDisplayFrameSink] = std::make_unique<CompositorFrameSinkSupport>(
@@ -239,12 +256,12 @@ class SurfaceSynchronizationTest : public testing::Test {
testing::NiceMock<MockCompositorFrameSinkClient> support_client_;
private:
+ std::unique_ptr<base::SimpleTestTickClock> now_src_;
FrameSinkManagerImpl frame_sink_manager_;
TestFrameSinkManagerClient frame_sink_manager_client_;
FakeSurfaceObserver surface_observer_;
FakeExternalBeginFrameSourceClient begin_frame_source_client_;
std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source_;
- std::unique_ptr<base::SimpleTestTickClock> now_src_;
std::unordered_map<FrameSinkId,
std::unique_ptr<CompositorFrameSinkSupport>,
FrameSinkIdHash>
@@ -456,7 +473,8 @@ TEST_F(SurfaceSynchronizationTest, DeadlineHits) {
parent_support().SubmitCompositorFrame(
parent_id.local_surface_id(),
MakeCompositorFrame({child_id1}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
// parent_support is blocked on |child_id1|.
EXPECT_TRUE(parent_surface()->has_deadline());
@@ -468,7 +486,8 @@ TEST_F(SurfaceSynchronizationTest, DeadlineHits) {
child_support1().SubmitCompositorFrame(
child_id1.local_surface_id(),
MakeCompositorFrame({child_id2}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
// child_support1 should now be blocked on |child_id2|.
EXPECT_TRUE(child_surface1()->has_deadline());
@@ -515,6 +534,84 @@ TEST_F(SurfaceSynchronizationTest, DeadlineHits) {
EXPECT_THAT(child_surface1()->activation_dependencies(), IsEmpty());
}
+// This test verifies that unlimited deadline mode works and that surfaces will
+// not activate until dependencies are resolved.
+TEST_F(SurfaceSynchronizationTest, UnlimitedDeadline) {
+ // Turn on unlimited deadline mode.
+ frame_sink_manager()
+ .surface_manager()
+ ->SetActivationDeadlineInFramesForTesting(base::nullopt);
+
+ const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+ const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+
+ // The deadline specified by the parent is ignored in unlimited deadline
+ // mode.
+ parent_support().SubmitCompositorFrame(
+ parent_id.local_surface_id(),
+ MakeCompositorFrame({child_id1}, empty_surface_ids(),
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
+
+ // parent_support is blocked on |child_id1|.
+ EXPECT_FALSE(parent_surface()->HasActiveFrame());
+ EXPECT_TRUE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(),
+ UnorderedElementsAre(child_id1));
+
+ for (int i = 0; i < 4; ++i) {
+ SendNextBeginFrame();
+ // parent_support is still blocked on |child_id1|.
+ EXPECT_FALSE(parent_surface()->HasActiveFrame());
+ EXPECT_TRUE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(),
+ UnorderedElementsAre(child_id1));
+ }
+
+ // parent_support is STILL blocked on |child_id1|.
+ EXPECT_FALSE(parent_surface()->HasActiveFrame());
+ EXPECT_TRUE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(),
+ UnorderedElementsAre(child_id1));
+
+ child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
+ MakeDefaultCompositorFrame());
+
+ // parent_surface has been activated.
+ EXPECT_TRUE(parent_surface()->HasActiveFrame());
+ EXPECT_FALSE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(), IsEmpty());
+}
+
+// parent_surface is blocked on |child_id1| until a late BeginFrame arrives and
+// triggers a deadline.
+TEST_F(SurfaceSynchronizationTest, LateBeginFrameTriggersDeadline) {
+ const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+ const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+
+ parent_support().SubmitCompositorFrame(
+ parent_id.local_surface_id(),
+ MakeCompositorFrame({child_id1}, empty_surface_ids(),
+ std::vector<TransferableResource>()));
+
+ // parent_support is blocked on |child_id1|.
+ EXPECT_TRUE(parent_surface()->has_deadline());
+ EXPECT_FALSE(parent_surface()->HasActiveFrame());
+ EXPECT_TRUE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(),
+ UnorderedElementsAre(child_id1));
+
+ SendLateBeginFrame();
+
+ // The deadline has passed.
+ EXPECT_FALSE(parent_surface()->has_deadline());
+
+ // parent_surface has been activated.
+ EXPECT_TRUE(parent_surface()->HasActiveFrame());
+ EXPECT_FALSE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(), IsEmpty());
+}
+
// This test verifies at the Surface activates once a CompositorFrame is
// submitted that has no unresolved dependencies.
TEST_F(SurfaceSynchronizationTest, NewFrameOverridesOldDependencies) {
@@ -1042,7 +1139,7 @@ TEST_F(SurfaceSynchronizationTest, SurfaceResurrection) {
// Attempt to destroy the child surface. The surface must still exist since
// the parent needs it but it will be marked as destroyed.
- child_support1().EvictCurrentSurface();
+ child_support1().EvictLastActivatedSurface();
surface = GetSurfaceForId(child_id);
EXPECT_NE(nullptr, surface);
EXPECT_TRUE(IsMarkedForDestruction(child_id));
@@ -1092,7 +1189,7 @@ TEST_F(SurfaceSynchronizationTest, SurfaceResurrectionAfterDestruction) {
// Attempt to destroy the child surface. The surface must still exist since
// the parent needs it but it will be marked as destroyed.
- child_support1().EvictCurrentSurface();
+ child_support1().EvictLastActivatedSurface();
surface = GetSurfaceForId(child_id);
EXPECT_NE(nullptr, surface);
EXPECT_TRUE(IsMarkedForDestruction(child_id));
@@ -1135,7 +1232,7 @@ TEST_F(SurfaceSynchronizationTest, LocalSurfaceIdIsReusable) {
MakeDefaultCompositorFrame());
// Destroy the surface.
- child_support1().EvictCurrentSurface();
+ child_support1().EvictLastActivatedSurface();
frame_sink_manager().surface_manager()->GarbageCollectSurfaces();
EXPECT_EQ(nullptr, GetSurfaceForId(child_id));
@@ -1163,11 +1260,13 @@ TEST_F(SurfaceSynchronizationTest, DependencyTrackingGarbageCollection) {
parent_support().SubmitCompositorFrame(
parent_id1.local_surface_id(),
MakeCompositorFrame({child_id}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
display_support().SubmitCompositorFrame(
display_id.local_surface_id(),
MakeCompositorFrame({parent_id1}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(parent_surface()->has_deadline());
@@ -1187,11 +1286,13 @@ TEST_F(SurfaceSynchronizationTest, DependencyTrackingGarbageCollection) {
parent_support().SubmitCompositorFrame(
parent_id2.local_surface_id(),
MakeCompositorFrame({child_id}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
display_support().SubmitCompositorFrame(
display_id.local_surface_id(),
MakeCompositorFrame({parent_id2}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
// The display surface now has two CompositorFrames. One that is pending,
// indirectly blocked on child_id and one that is active, also indirectly
@@ -1223,12 +1324,14 @@ TEST_F(SurfaceSynchronizationTest, GarbageCollectionOnDeadline) {
parent_support().SubmitCompositorFrame(
parent_id1.local_surface_id(),
MakeCompositorFrame({child_id}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
display_support().SubmitCompositorFrame(
display_id.local_surface_id(),
MakeCompositorFrame({parent_id1}, {parent_id1},
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(display_surface()->has_deadline());
EXPECT_TRUE(parent_surface()->has_deadline());
@@ -1254,14 +1357,16 @@ TEST_F(SurfaceSynchronizationTest, GarbageCollectionOnDeadline) {
display_support().SubmitCompositorFrame(
display_id.local_surface_id(),
MakeCompositorFrame({parent_id2}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(display_surface()->has_deadline());
// Now |parent_id1| is only kept alive by the active |display_id| frame.
parent_support().SubmitCompositorFrame(
parent_id2.local_surface_id(),
MakeCompositorFrame({child_id}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(display_surface()->has_deadline());
EXPECT_TRUE(parent_surface()->has_deadline());
@@ -1328,7 +1433,8 @@ TEST_F(SurfaceSynchronizationTest, LateArrivingDependency) {
display_support().SubmitCompositorFrame(
display_id.local_surface_id(),
MakeCompositorFrame({parent_id1}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(display_surface()->HasPendingFrame());
EXPECT_FALSE(display_surface()->HasActiveFrame());
@@ -1350,7 +1456,8 @@ TEST_F(SurfaceSynchronizationTest, LateArrivingDependency) {
parent_support().SubmitCompositorFrame(
parent_id1.local_surface_id(),
MakeCompositorFrame({child_id1}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_FALSE(parent_surface()->has_deadline());
EXPECT_FALSE(parent_surface()->HasPendingFrame());
EXPECT_TRUE(parent_surface()->HasActiveFrame());
@@ -1367,7 +1474,8 @@ TEST_F(SurfaceSynchronizationTest, MultiLevelLateArrivingDependency) {
display_support().SubmitCompositorFrame(
display_id.local_surface_id(),
MakeCompositorFrame({parent_id}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(display_surface()->HasPendingFrame());
EXPECT_FALSE(display_surface()->HasActiveFrame());
EXPECT_TRUE(display_surface()->has_deadline());
@@ -1388,7 +1496,8 @@ TEST_F(SurfaceSynchronizationTest, MultiLevelLateArrivingDependency) {
child_support1().SubmitCompositorFrame(
child_id.local_surface_id(),
MakeCompositorFrame({arbitrary_id}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(child_surface1()->HasPendingFrame());
EXPECT_FALSE(child_surface1()->HasActiveFrame());
EXPECT_TRUE(child_surface1()->has_deadline());
@@ -1400,7 +1509,8 @@ TEST_F(SurfaceSynchronizationTest, MultiLevelLateArrivingDependency) {
parent_support().SubmitCompositorFrame(
parent_id.local_surface_id(),
MakeCompositorFrame({child_id}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_FALSE(parent_surface()->HasPendingFrame());
EXPECT_TRUE(parent_surface()->HasActiveFrame());
EXPECT_FALSE(parent_surface()->has_deadline());
@@ -1423,7 +1533,8 @@ TEST_F(SurfaceSynchronizationTest, MissingActiveFrameWithLateDependencies) {
display_support().SubmitCompositorFrame(
display_id.local_surface_id(),
MakeCompositorFrame({parent_id1}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(display_surface()->HasPendingFrame());
EXPECT_FALSE(display_surface()->HasActiveFrame());
@@ -1440,18 +1551,20 @@ TEST_F(SurfaceSynchronizationTest, MissingActiveFrameWithLateDependencies) {
EXPECT_FALSE(display_surface()->HasPendingFrame());
EXPECT_TRUE(display_surface()->HasActiveFrame());
- display_support().EvictCurrentSurface();
+ display_support().EvictLastActivatedSurface();
display_support().SubmitCompositorFrame(
display_id.local_surface_id(),
MakeCompositorFrame({parent_id2}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
// A late arriving CompositorFrame will not activate immediately if the
// dependent CompositorFrame has been evicted.
parent_support().SubmitCompositorFrame(
parent_id1.local_surface_id(),
MakeCompositorFrame({child_id1}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(parent_surface()->has_deadline());
EXPECT_TRUE(parent_surface()->HasPendingFrame());
EXPECT_FALSE(parent_surface()->HasActiveFrame());
@@ -1483,8 +1596,8 @@ TEST_F(SurfaceSynchronizationTest, FallbackSurfacesClosed) {
Eq(std::vector<ReturnedResource>())));
child_support1().SubmitCompositorFrame(
child_id1.local_surface_id(),
- MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(),
- {resource}));
+ MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(), {resource},
+ MakeDefaultDeadline()));
EXPECT_FALSE(child_surface1()->has_deadline());
testing::Mock::VerifyAndClearExpectations(&support_client_);
@@ -1494,7 +1607,8 @@ TEST_F(SurfaceSynchronizationTest, FallbackSurfacesClosed) {
parent_support().SubmitCompositorFrame(
parent_id1.local_surface_id(),
MakeCompositorFrame({child_id2}, {child_id1},
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(parent_surface()->has_deadline());
EXPECT_TRUE(parent_surface()->HasPendingFrame());
EXPECT_FALSE(parent_surface()->HasActiveFrame());
@@ -1512,8 +1626,8 @@ TEST_F(SurfaceSynchronizationTest, FallbackSurfacesClosed) {
DidReceiveCompositorFrameAck(Eq(returned_resources2)));
child_support1().SubmitCompositorFrame(
child_id1.local_surface_id(),
- MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(),
- {resource2}));
+ MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(), {resource2},
+ MakeDefaultDeadline()));
testing::Mock::VerifyAndClearExpectations(&support_client_);
// Advance BeginFrames to trigger a deadline. This activates the
@@ -1533,8 +1647,8 @@ TEST_F(SurfaceSynchronizationTest, FallbackSurfacesClosed) {
DidReceiveCompositorFrameAck(Eq(returned_resources2)));
child_support1().SubmitCompositorFrame(
child_id1.local_surface_id(),
- MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(),
- {resource2}));
+ MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(), {resource2},
+ MakeDefaultDeadline()));
testing::Mock::VerifyAndClearExpectations(&support_client_);
}
@@ -1558,7 +1672,8 @@ TEST_F(SurfaceSynchronizationTest, IndependentDeadlines) {
parent_support().SubmitCompositorFrame(
parent_id1.local_surface_id(),
MakeCompositorFrame({child_id1, child_id2}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_FALSE(parent_surface()->HasPendingFrame());
EXPECT_TRUE(parent_surface()->HasActiveFrame());
@@ -1568,8 +1683,10 @@ TEST_F(SurfaceSynchronizationTest, IndependentDeadlines) {
// |arbitrary_id|.
child_support1().SubmitCompositorFrame(
child_id1.local_surface_id(),
- MakeCompositorFrame({arbitrary_id}, empty_surface_ids(),
- std::vector<TransferableResource>(), 3));
+ MakeCompositorFrame(
+ {arbitrary_id}, empty_surface_ids(),
+ std::vector<TransferableResource>(),
+ FrameDeadline(Now(), 3, BeginFrameArgs::DefaultInterval(), false)));
EXPECT_TRUE(child_surface1()->HasPendingFrame());
EXPECT_TRUE(child_surface1()->HasActiveFrame());
EXPECT_TRUE(child_surface1()->has_deadline());
@@ -1583,7 +1700,8 @@ TEST_F(SurfaceSynchronizationTest, IndependentDeadlines) {
child_support2().SubmitCompositorFrame(
child_id2.local_surface_id(),
MakeCompositorFrame({arbitrary_id}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(child_surface2()->HasPendingFrame());
EXPECT_TRUE(child_surface2()->HasActiveFrame());
EXPECT_TRUE(child_surface2()->has_deadline());
@@ -1625,10 +1743,13 @@ TEST_F(SurfaceSynchronizationTest, DeadlineInheritance) {
const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
const SurfaceId arbitrary_id = MakeSurfaceId(kArbitraryFrameSink, 1);
+ // Using the default lower bound deadline results in the deadline of 2 frames
+ // effectively being ignored because the default lower bound is 4 frames.
parent_support().SubmitCompositorFrame(
parent_id1.local_surface_id(),
- MakeCompositorFrame({child_id1}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ MakeCompositorFrame(
+ {child_id1}, empty_surface_ids(), std::vector<TransferableResource>(),
+ FrameDeadline(Now(), 2, BeginFrameArgs::DefaultInterval(), true)));
EXPECT_TRUE(parent_surface()->HasPendingFrame());
EXPECT_FALSE(parent_surface()->HasActiveFrame());
@@ -1641,7 +1762,8 @@ TEST_F(SurfaceSynchronizationTest, DeadlineInheritance) {
child_support1().SubmitCompositorFrame(
child_id1.local_surface_id(),
MakeCompositorFrame({arbitrary_id}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(child_surface1()->HasPendingFrame());
EXPECT_FALSE(child_surface1()->HasActiveFrame());
EXPECT_TRUE(child_surface1()->has_deadline());
@@ -1677,7 +1799,8 @@ TEST_F(SurfaceSynchronizationTest, MultiLevelDeadlineInheritance) {
display_support().SubmitCompositorFrame(
display_id.local_surface_id(),
MakeCompositorFrame({parent_id}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(display_surface()->HasPendingFrame());
EXPECT_FALSE(display_surface()->HasActiveFrame());
EXPECT_TRUE(display_surface()->has_deadline());
@@ -1690,7 +1813,8 @@ TEST_F(SurfaceSynchronizationTest, MultiLevelDeadlineInheritance) {
child_support1().SubmitCompositorFrame(
child_id.local_surface_id(),
MakeCompositorFrame({arbitrary_id}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(child_surface1()->HasPendingFrame());
EXPECT_FALSE(child_surface1()->HasActiveFrame());
EXPECT_TRUE(child_surface1()->has_deadline());
@@ -1701,7 +1825,8 @@ TEST_F(SurfaceSynchronizationTest, MultiLevelDeadlineInheritance) {
parent_support().SubmitCompositorFrame(
parent_id.local_surface_id(),
MakeCompositorFrame({child_id}, empty_surface_ids(),
- std::vector<TransferableResource>()));
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
EXPECT_TRUE(parent_surface()->HasPendingFrame());
EXPECT_FALSE(parent_surface()->HasActiveFrame());
EXPECT_TRUE(parent_surface()->has_deadline());
@@ -1818,11 +1943,10 @@ TEST_F(SurfaceSynchronizationTest, PreviousFrameSurfaceId) {
frame_sink_manager().surface_manager()->GetSurfaceForId(parent_id2);
EXPECT_FALSE(parent_surface2->HasActiveFrame());
EXPECT_TRUE(parent_surface2->HasPendingFrame());
- EXPECT_EQ(parent_id1, parent_surface2->previous_frame_surface_id());
// Activate the pending frame in |parent_id2|. previous_frame_surface_id()
// should still return |parent_id1|.
- parent_surface2->ActivatePendingFrameForDeadline();
+ parent_surface2->ActivatePendingFrameForDeadline(base::nullopt);
EXPECT_TRUE(parent_surface2->HasActiveFrame());
EXPECT_FALSE(parent_surface2->HasPendingFrame());
EXPECT_EQ(parent_id1, parent_surface2->previous_frame_surface_id());
@@ -1855,7 +1979,7 @@ TEST_F(SurfaceSynchronizationTest, FrameIndexWithPendingFrames) {
// Activate the pending frame. GetActiveFrameIndex should return the frame
// index of the newly activated frame.
- parent_surface->ActivatePendingFrameForDeadline();
+ parent_surface->ActivatePendingFrameForDeadline(base::nullopt);
EXPECT_EQ(initial_frame_index + n_iterations,
parent_surface->GetActiveFrameIndex());
}
@@ -1972,15 +2096,6 @@ TEST_F(SurfaceSynchronizationTest, LatestInFlightSurface) {
EXPECT_TRUE(HasTemporaryReference(child_id2));
EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1));
- // GetLatestInFlightSurface will not return child_id2's surface because it
- // does not yet have an owner.
- EXPECT_EQ(GetSurfaceForId(child_id1),
- GetLatestInFlightSurface(child_id3, child_id1));
-
- // Now that the owner of |child_id2| is known, GetLatestInFlightSurface will
- // return it as a possible fallback.
- frame_sink_manager().surface_manager()->AssignTemporaryReference(
- child_id2, parent_id.frame_sink_id());
EXPECT_EQ(GetSurfaceForId(child_id2),
GetLatestInFlightSurface(child_id3, child_id1));
@@ -1991,24 +2106,15 @@ TEST_F(SurfaceSynchronizationTest, LatestInFlightSurface) {
// Submit a child CompositorFrame to a new SurfaceId and verify that
// GetLatestInFlightSurface returns the right surface.
- EXPECT_TRUE(child_support1().SubmitCompositorFrame(
- child_id3.local_surface_id(), MakeDefaultCompositorFrame()));
+ child_support1().SubmitCompositorFrame(child_id3.local_surface_id(),
+ MakeDefaultCompositorFrame());
// Verify that there is a temporary reference for child_id3.
EXPECT_TRUE(HasTemporaryReference(child_id3));
- // GetLatestInFlightSurface will not return child_id3's surface because it
- // does not yet have an owner.
- EXPECT_EQ(GetSurfaceForId(child_id2),
- GetLatestInFlightSurface(child_id4, child_id1));
- EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1));
-
- // Now that the owner of |child_id3| is known, GetLatestInFlightSurface will
- // return it as a possible fallback.
- frame_sink_manager().surface_manager()->AssignTemporaryReference(
- child_id3, parent_id.frame_sink_id());
EXPECT_EQ(GetSurfaceForId(child_id3),
GetLatestInFlightSurface(child_id4, child_id1));
+ EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1));
// If the primary surface is old, then we shouldn't return an in-flight
// surface that is newer than the primary.
@@ -2101,28 +2207,69 @@ TEST_F(SurfaceSynchronizationTest, LatestInFlightSurfaceSkipPrimary) {
child_support1().SubmitCompositorFrame(child_id2.local_surface_id(),
MakeDefaultCompositorFrame());
- // |child_id2| will not be returned until its temporary reference is
- // assigned.
- EXPECT_EQ(GetSurfaceForId(child_id1),
+ EXPECT_EQ(GetSurfaceForId(child_id2),
GetLatestInFlightSurface(child_id3, child_id1));
- // Verify that there is a temporary reference for |child_id2|.
- EXPECT_TRUE(HasTemporaryReference(child_id2));
- frame_sink_manager().surface_manager()->AssignTemporaryReference(
- child_id2, parent_id.frame_sink_id());
+ child_support1().SubmitCompositorFrame(child_id3.local_surface_id(),
+ MakeDefaultCompositorFrame());
+ // GetLatestInFlightSurface will never return the primary surface ID
+ // even if it's available.
EXPECT_EQ(GetSurfaceForId(child_id2),
GetLatestInFlightSurface(child_id3, child_id1));
+}
+
+// This test verifies that GetLatestInFlightSurface will skip a surface if
+// its nonce is different.
+TEST_F(SurfaceSynchronizationTest, LatestInFlightSurfaceSkipDifferentNonce) {
+ const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+ const base::UnguessableToken nonce1(
+ base::UnguessableToken::Deserialize(0, 1));
+ const base::UnguessableToken nonce2(
+ base::UnguessableToken::Deserialize(1, 1));
+ const base::UnguessableToken nonce3(
+ base::UnguessableToken::Deserialize(2, 1));
+ const SurfaceId child_id1 =
+ SurfaceId(kChildFrameSink1, LocalSurfaceId(1, nonce1));
+ const SurfaceId child_id2 =
+ SurfaceId(kChildFrameSink1, LocalSurfaceId(2, nonce1));
+ const SurfaceId child_id3 =
+ SurfaceId(kChildFrameSink1, LocalSurfaceId(3, nonce2));
+ const SurfaceId child_id4 =
+ SurfaceId(kChildFrameSink1, LocalSurfaceId(4, nonce2));
+ const SurfaceId child_id5 =
+ SurfaceId(kChildFrameSink1, LocalSurfaceId(5, nonce3));
+
+ // Don't automatically assign temporary references.
+ DisableAssignTemporaryReferences();
+
+ child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
+ MakeDefaultCompositorFrame());
+
+ // Create a reference from |parent_id| to |child_id|.
+ parent_support().SubmitCompositorFrame(
+ parent_id.local_surface_id(),
+ MakeCompositorFrame(empty_surface_ids(), {child_id1},
+ std::vector<TransferableResource>()));
+
+ child_support1().SubmitCompositorFrame(child_id2.local_surface_id(),
+ MakeDefaultCompositorFrame());
+
+ EXPECT_EQ(GetSurfaceForId(child_id2),
+ GetLatestInFlightSurface(child_id4, child_id1));
child_support1().SubmitCompositorFrame(child_id3.local_surface_id(),
MakeDefaultCompositorFrame());
- frame_sink_manager().surface_manager()->AssignTemporaryReference(
- child_id3, parent_id.frame_sink_id());
- // Even though there is a valid temporary reference with an owner for
- // the primary, we never pick the primary.
+ // GetLatestInFlightSurface will return child_id3 because the nonce
+ // matches that of child_id4.
+ EXPECT_EQ(GetSurfaceForId(child_id3),
+ GetLatestInFlightSurface(child_id4, child_id1));
+
+ // GetLatestInFlightSurface will return child_id2 because the nonce
+ // doesn't match |child_id1| or |child_id5|.
EXPECT_EQ(GetSurfaceForId(child_id2),
- GetLatestInFlightSurface(child_id3, child_id1));
+ GetLatestInFlightSurface(child_id5, child_id1));
}
// This test verifies that if a child submits a LocalSurfaceId newer that the
@@ -2200,5 +2347,117 @@ TEST_F(SurfaceSynchronizationTest, ObserveDependenciesUntilArrival) {
EXPECT_THAT(parent_surface()->activation_dependencies(), IsEmpty());
}
+// This test verifies that we don't mark the previous active surface for
+// destruction until the new surface activates.
+TEST_F(SurfaceSynchronizationTest,
+ MarkPreviousSurfaceForDestructionAfterActivation) {
+ const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
+ const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
+ const SurfaceId arbitrary_id = MakeSurfaceId(kArbitraryFrameSink, 1);
+
+ // Submit a CompositorFrame that has no dependencies.
+ parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
+ MakeDefaultCompositorFrame());
+
+ // Verify that the CompositorFrame has been activated.
+ Surface* parent_surface1 = GetSurfaceForId(parent_id1);
+ EXPECT_TRUE(parent_surface1->HasActiveFrame());
+ EXPECT_FALSE(parent_surface1->HasPendingFrame());
+ EXPECT_THAT(parent_surface1->activation_dependencies(), IsEmpty());
+ EXPECT_FALSE(IsMarkedForDestruction(parent_id1));
+
+ parent_support().SubmitCompositorFrame(
+ parent_id2.local_surface_id(),
+ MakeCompositorFrame({arbitrary_id}, empty_surface_ids(),
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
+
+ // Verify that the CompositorFrame to the new surface has not been activated.
+ Surface* parent_surface2 = GetSurfaceForId(parent_id2);
+ EXPECT_FALSE(parent_surface2->HasActiveFrame());
+ EXPECT_TRUE(parent_surface2->HasPendingFrame());
+ EXPECT_THAT(parent_surface2->activation_dependencies(),
+ UnorderedElementsAre(arbitrary_id));
+ EXPECT_FALSE(IsMarkedForDestruction(parent_id1));
+ EXPECT_FALSE(IsMarkedForDestruction(parent_id2));
+
+ // Advance BeginFrames to trigger a deadline.
+ for (int i = 0; i < 3; ++i) {
+ SendNextBeginFrame();
+ EXPECT_TRUE(parent_surface2->has_deadline());
+ }
+ SendNextBeginFrame();
+ EXPECT_FALSE(parent_surface2->has_deadline());
+
+ // Verify that the CompositorFrame has been activated.
+ EXPECT_TRUE(parent_surface2->HasActiveFrame());
+ EXPECT_FALSE(parent_surface2->HasPendingFrame());
+ EXPECT_THAT(parent_surface2->activation_dependencies(), IsEmpty());
+
+ // Verify that the old surface is now marked for destruction.
+ EXPECT_TRUE(IsMarkedForDestruction(parent_id1));
+ EXPECT_FALSE(IsMarkedForDestruction(parent_id2));
+}
+
+// This test verifies that CompositorFrameSinkSupport does not refer to
+// a valid but non-existant |last_activated_surface_id_|.
+TEST_F(SurfaceSynchronizationTest, SetPreviousFrameSurfaceDoesntCrash) {
+ const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+ const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
+ const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
+
+ // The parent CompositorFrame is not blocked on anything and so it should
+ // immediately activate.
+ EXPECT_FALSE(parent_support().last_activated_surface_id().is_valid());
+ parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
+ MakeDefaultCompositorFrame());
+
+ // Verify that the parent CompositorFrame has activated.
+ EXPECT_FALSE(parent_surface()->has_deadline());
+ EXPECT_TRUE(parent_surface()->HasActiveFrame());
+ EXPECT_FALSE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(), IsEmpty());
+ EXPECT_TRUE(parent_support().last_activated_surface_id().is_valid());
+
+ // Submit another CompositorFrame to |parent_id|, but this time block it
+ // on |child_id1|.
+ parent_support().SubmitCompositorFrame(
+ parent_id.local_surface_id(),
+ MakeCompositorFrame({child_id1}, empty_surface_ids(),
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
+
+ // Verify that the surface has both a pending and activate CompositorFrame.
+ EXPECT_TRUE(parent_surface()->has_deadline());
+ EXPECT_TRUE(parent_surface()->HasActiveFrame());
+ EXPECT_TRUE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(),
+ UnorderedElementsAre(child_id1));
+
+ // Evict the activated surface in the parent_support.
+ EXPECT_TRUE(parent_support().last_activated_surface_id().is_valid());
+ parent_support().EvictLastActivatedSurface();
+ EXPECT_FALSE(parent_support().last_activated_surface_id().is_valid());
+
+ // The CompositorFrame in the evicted |parent_id| activates here because it
+ // was blocked on |child_id1|.
+ child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
+ MakeDefaultCompositorFrame());
+
+ // parent_support will be informed of the activation of a CompositorFrame
+ // associated with |parent_id|.
+ EXPECT_TRUE(parent_support().last_activated_surface_id().is_valid());
+
+ // Perform a garbage collection. |parent_id| should no longer exist.
+ EXPECT_NE(nullptr, GetSurfaceForId(parent_id));
+ frame_sink_manager().surface_manager()->GarbageCollectSurfaces();
+ EXPECT_EQ(nullptr, GetSurfaceForId(parent_id));
+
+ // This should not crash as the previous surface was cleared in
+ // CompositorFrameSinkSupport.
+ parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(),
+ MakeDefaultCompositorFrame());
+}
+
} // namespace test
} // namespace viz
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/DEPS b/chromium/components/viz/service/frame_sinks/video_capture/DEPS
index 6365bee3a0c..41479637d4c 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/DEPS
+++ b/chromium/components/viz/service/frame_sinks/video_capture/DEPS
@@ -1,3 +1,5 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+media/base",
"+media/capture",
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 db4a2ae2b8f..200201d7f7b 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
@@ -49,8 +49,9 @@ class CapturableFrameSink {
virtual void AttachCaptureClient(Client* client) = 0;
virtual void DetachCaptureClient(Client* client) = 0;
- // Returns the current surface size.
- virtual gfx::Size GetSurfaceSize() = 0;
+ // Returns the currently-active frame size, or an empty size if there is no
+ // active frame.
+ virtual gfx::Size GetActiveFrameSize() = 0;
// Issues a request for a copy of the next composited frame.
virtual void RequestCopyOfSurface(
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 50c187e5af1..0bdeff0167e 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
@@ -5,6 +5,7 @@
#include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h"
#include <algorithm>
+#include <limits>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -17,7 +18,6 @@
#include "media/base/limits.h"
#include "media/base/video_util.h"
#include "media/capture/mojo/video_capture_types.mojom.h"
-#include "media/mojo/common/mojo_shared_buffer_video_frame.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size.h"
@@ -29,6 +29,13 @@ using media::VideoFrameMetadata;
namespace viz {
namespace {
+
+// The largest Rect possible.
+constexpr gfx::Rect kMaxRect = gfx::Rect(0,
+ 0,
+ std::numeric_limits<int>::max(),
+ std::numeric_limits<int>::max());
+
// Returns |raw_size| truncated to positive even-numbered values.
gfx::Size AdjustSizeForI420(const gfx::Size& raw_size) {
gfx::Size result(raw_size.width() & ~1, raw_size.height() & ~1);
@@ -40,6 +47,7 @@ gfx::Size AdjustSizeForI420(const gfx::Size& raw_size) {
}
return result;
}
+
} // namespace
// static
@@ -51,10 +59,6 @@ constexpr media::ColorSpace FrameSinkVideoCapturerImpl::kDefaultColorSpace;
// static
constexpr base::TimeDelta
- FrameSinkVideoCapturerImpl::kRefreshFrameRetryInterval;
-
-// static
-constexpr base::TimeDelta
FrameSinkVideoCapturerImpl::kDisplayTimeCacheKeepAliveInterval;
FrameSinkVideoCapturerImpl::FrameSinkVideoCapturerImpl(
@@ -70,6 +74,9 @@ FrameSinkVideoCapturerImpl::FrameSinkVideoCapturerImpl(
capture_weak_factory_(this) {
DCHECK(frame_sink_manager_);
+ // Instantiate a default base::OneShotTimer instance.
+ refresh_frame_retry_timer_.emplace();
+
if (request.is_pending()) {
binding_.Bind(std::move(request));
binding_.set_connection_error_handler(
@@ -99,12 +106,7 @@ void FrameSinkVideoCapturerImpl::SetResolvedTarget(
resolved_target_ = target;
if (resolved_target_) {
resolved_target_->AttachCaptureClient(this);
- const gfx::Size& source_size = resolved_target_->GetSurfaceSize();
- if (source_size != oracle_.source_size()) {
- oracle_.SetSourceSize(source_size);
- }
- MaybeCaptureFrame(VideoCaptureOracle::kActiveRefreshRequest,
- gfx::Rect(source_size), clock_->NowTicks());
+ RefreshEntireSourceSoon();
} else {
// Not calling consumer_->OnTargetLost() because SetResolvedTarget() should
// be called by FrameSinkManagerImpl with a valid target very soon.
@@ -114,17 +116,13 @@ void FrameSinkVideoCapturerImpl::SetResolvedTarget(
void FrameSinkVideoCapturerImpl::OnTargetWillGoAway() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!resolved_target_) {
- return;
- }
- resolved_target_->DetachCaptureClient(this);
- resolved_target_ = nullptr;
+ SetResolvedTarget(nullptr);
- if (requested_target_.is_valid()) {
- if (consumer_) {
- consumer_->OnTargetLost(requested_target_);
- }
- requested_target_ = FrameSinkId();
+ // TODO(crbug/754872): Remove this, since it's misleading: Resolved targets
+ // can be temporarily deleted and then re-created. So, the target really isn't
+ // lost.
+ if (requested_target_.is_valid() && consumer_) {
+ consumer_->OnTargetLost(requested_target_);
}
}
@@ -132,9 +130,12 @@ void FrameSinkVideoCapturerImpl::SetFormat(media::VideoPixelFormat format,
media::ColorSpace color_space) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ bool format_changed = false;
+
if (format != media::PIXEL_FORMAT_I420) {
LOG(DFATAL) << "Invalid pixel format: Only I420 supported.";
} else {
+ format_changed |= (pixel_format_ != format);
pixel_format_ = format;
}
@@ -146,8 +147,13 @@ void FrameSinkVideoCapturerImpl::SetFormat(media::VideoPixelFormat format,
if (color_space != media::COLOR_SPACE_HD_REC709) {
LOG(DFATAL) << "Unsupported color space: Only BT.709 is supported.";
} else {
+ format_changed |= (color_space_ != color_space);
color_space_ = color_space;
}
+
+ if (format_changed) {
+ RefreshEntireSourceSoon();
+ }
}
void FrameSinkVideoCapturerImpl::SetMinCapturePeriod(
@@ -174,6 +180,11 @@ void FrameSinkVideoCapturerImpl::SetMinCapturePeriod(
}
oracle_.SetMinCapturePeriod(min_capture_period);
+ if (refresh_frame_retry_timer_->IsRunning()) {
+ // With the change in the minimum capture period, a pending refresh might
+ // be ready to execute now (or sooner than it would have been).
+ RefreshSoon();
+ }
}
void FrameSinkVideoCapturerImpl::SetResolutionConstraints(
@@ -194,6 +205,7 @@ void FrameSinkVideoCapturerImpl::SetResolutionConstraints(
}
oracle_.SetCaptureSizeConstraints(min_size, max_size, use_fixed_aspect_ratio);
+ RefreshEntireSourceSoon();
}
void FrameSinkVideoCapturerImpl::ChangeTarget(
@@ -216,14 +228,13 @@ void FrameSinkVideoCapturerImpl::Start(
// Stop(), make that call on its behalf.
consumer_.set_connection_error_handler(base::BindOnce(
&FrameSinkVideoCapturerImpl::Stop, base::Unretained(this)));
- MaybeCaptureFrame(VideoCaptureOracle::kActiveRefreshRequest,
- gfx::Rect(oracle_.source_size()), clock_->NowTicks());
+ RefreshEntireSourceSoon();
}
void FrameSinkVideoCapturerImpl::Stop() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- refresh_frame_retry_timer_.Stop();
+ refresh_frame_retry_timer_->Stop();
// Cancel any captures in-flight and any captured frames pending delivery.
capture_weak_factory_.InvalidateWeakPtrs();
@@ -242,7 +253,67 @@ void FrameSinkVideoCapturerImpl::Stop() {
void FrameSinkVideoCapturerImpl::RequestRefreshFrame() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- MaybeCaptureFrame(VideoCaptureOracle::kPassiveRefreshRequest,
+ if (!refresh_frame_retry_timer_->IsRunning()) {
+ RefreshSoon();
+ }
+}
+
+void FrameSinkVideoCapturerImpl::ScheduleRefreshFrame() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ refresh_frame_retry_timer_->Start(
+ FROM_HERE, GetDelayBeforeNextRefreshAttempt(),
+ base::BindRepeating(&FrameSinkVideoCapturerImpl::RefreshSoon,
+ base::Unretained(this)));
+}
+
+base::TimeDelta FrameSinkVideoCapturerImpl::GetDelayBeforeNextRefreshAttempt()
+ const {
+ // The delay should be long enough to prevent interrupting the smooth timing
+ // of frame captures that are expected to take place due to compositor update
+ // events. However, the delay should not be excessively long either. Two frame
+ // periods should be "just right."
+ return 2 * std::max(oracle_.estimated_frame_duration(),
+ oracle_.min_capture_period());
+}
+
+void FrameSinkVideoCapturerImpl::RefreshEntireSourceSoon() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ dirty_rect_ = kMaxRect;
+ RefreshSoon();
+}
+
+void FrameSinkVideoCapturerImpl::RefreshSoon() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // If consumption is stopped, cancel the refresh.
+ if (!consumer_) {
+ return;
+ }
+
+ // If the capture target has not yet been resolved, the refresh must be
+ // attempted later.
+ if (!resolved_target_) {
+ ScheduleRefreshFrame();
+ return;
+ }
+
+ // Detect whether the source size changed before attempting capture.
+ const gfx::Size& source_size = resolved_target_->GetActiveFrameSize();
+ if (source_size.IsEmpty()) {
+ // If the target's surface size is empty, that indicates it has not yet had
+ // its first frame composited. Since having content is obviously a
+ // requirement for video capture, the refresh must be attempted later.
+ ScheduleRefreshFrame();
+ return;
+ }
+ if (source_size != oracle_.source_size()) {
+ oracle_.SetSourceSize(source_size);
+ dirty_rect_ = kMaxRect;
+ }
+
+ MaybeCaptureFrame(VideoCaptureOracle::kRefreshRequest,
gfx::Rect(oracle_.source_size()), clock_->NowTicks());
}
@@ -295,13 +366,20 @@ void FrameSinkVideoCapturerImpl::OnFrameDamaged(const BeginFrameAck& ack,
}
if (display_time.is_null()) {
// This can sometimes occur for the first few frames when capture starts,
- // but should not happen thereafter.
- DLOG(WARNING) << "OnFrameDamaged() called without prior OnBeginFrame().";
- return;
+ // or whenever Surfaces are changed; but should not otherwise happen. If
+ // this is too frequent, the oracle will be making suboptimal decisions.
+ VLOG(1)
+ << "OnFrameDamaged() called without prior OnBeginFrame() for source_id="
+ << ack.source_id << " and sequence_number=" << ack.sequence_number
+ << ". Using NOW as a substitute display time.";
+ display_time = clock_->NowTicks();
}
- if (frame_size != oracle_.source_size()) {
+ if (frame_size == oracle_.source_size()) {
+ dirty_rect_.Union(damage_rect);
+ } else {
oracle_.SetSourceSize(frame_size);
+ dirty_rect_ = kMaxRect;
}
MaybeCaptureFrame(VideoCaptureOracle::kCompositorUpdate, damage_rect,
@@ -313,33 +391,22 @@ void FrameSinkVideoCapturerImpl::MaybeCaptureFrame(
const gfx::Rect& damage_rect,
base::TimeTicks event_time) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(resolved_target_);
// Consult the oracle to determine whether this frame should be captured.
if (oracle_.ObserveEventAndDecideCapture(event, damage_rect, event_time)) {
// Regardless of the type of |event|, there is no longer a need for the
// refresh frame retry timer to fire. The following is a no-op, if the timer
// was not running.
- refresh_frame_retry_timer_.Stop();
+ refresh_frame_retry_timer_->Stop();
} else {
TRACE_EVENT_INSTANT1("gpu.capture", "FpsRateLimited",
TRACE_EVENT_SCOPE_THREAD, "trigger",
VideoCaptureOracle::EventAsString(event));
- // If the oracle rejected a "refresh frame" request, schedule a later retry.
- if (event == VideoCaptureOracle::kPassiveRefreshRequest ||
- event == VideoCaptureOracle::kActiveRefreshRequest) {
- refresh_frame_retry_timer_.Start(
- FROM_HERE,
- std::max(kRefreshFrameRetryInterval, oracle_.min_capture_period()),
- base::BindRepeating(
- [](FrameSinkVideoCapturerImpl* self,
- VideoCaptureOracle::Event event) {
- self->MaybeCaptureFrame(event,
- gfx::Rect(self->oracle_.source_size()),
- self->clock_->NowTicks());
- },
- this, event));
- }
+ // Whether the oracle rejected a compositor update or a refresh event,
+ // the consumer needs to be provided an update in the near future.
+ ScheduleRefreshFrame();
return;
}
@@ -357,20 +424,18 @@ void FrameSinkVideoCapturerImpl::MaybeCaptureFrame(
const OracleFrameNumber oracle_frame_number = oracle_.next_frame_number();
const gfx::Size i420_capture_size = AdjustSizeForI420(oracle_.capture_size());
scoped_refptr<VideoFrame> frame;
- if (event == VideoCaptureOracle::kPassiveRefreshRequest) {
+ if (dirty_rect_.IsEmpty()) {
frame =
- frame_pool_.ResurrectLastVideoFrame(i420_capture_size, pixel_format_);
- // If the resurrection failed, promote the passive refresh request to an
- // active refresh request and retry.
+ frame_pool_.ResurrectLastVideoFrame(pixel_format_, i420_capture_size);
+ // If the resurrection failed, promote to a full frame capture.
if (!frame) {
TRACE_EVENT_INSTANT0("gpu.capture", "ResurrectionFailed",
TRACE_EVENT_SCOPE_THREAD);
- MaybeCaptureFrame(VideoCaptureOracle::kActiveRefreshRequest, damage_rect,
- event_time);
- return;
+ dirty_rect_ = kMaxRect;
+ frame = frame_pool_.ReserveVideoFrame(pixel_format_, i420_capture_size);
}
} else {
- frame = frame_pool_.ReserveVideoFrame(i420_capture_size, pixel_format_);
+ frame = frame_pool_.ReserveVideoFrame(pixel_format_, i420_capture_size);
}
// Compute the current in-flight utilization and attenuate it: The utilization
@@ -387,6 +452,15 @@ void FrameSinkVideoCapturerImpl::MaybeCaptureFrame(
VideoCaptureOracle::EventAsString(event), "atten_util_percent",
base::saturated_cast<int>(utilization * 100.0f + 0.5f));
oracle_.RecordWillNotCapture(utilization);
+ if (next_capture_frame_number_ == 0) {
+ // The pool was unable to provide a buffer for the very first capture, and
+ // so there is no expectation of recovery. Thus, treat this as a fatal
+ // memory allocation issue instead of a transient one.
+ LOG(ERROR) << "Unable to allocate shmem for first frame capture: OOM?";
+ Stop();
+ } else {
+ ScheduleRefreshFrame();
+ }
return;
}
@@ -420,21 +494,22 @@ void FrameSinkVideoCapturerImpl::MaybeCaptureFrame(
"frame_number", frame_number, "trigger",
VideoCaptureOracle::EventAsString(event));
- // If there is currently no resolved target (or the target has zero area),
- // deliver a blank black frame.
const gfx::Size& source_size = oracle_.source_size();
- if (!resolved_target_ || source_size.IsEmpty()) {
+ DCHECK(!source_size.IsEmpty());
+ const gfx::Rect content_rect =
+ media::ComputeLetterboxRegionForI420(frame->visible_rect(), source_size);
+ // Extreme edge-case: If somehow the source size is so tiny that the content
+ // region becomes empty, just deliver a frame filled with black.
+ if (content_rect.IsEmpty()) {
media::FillYUV(frame.get(), 0x00, 0x80, 0x80);
+ dirty_rect_ = gfx::Rect();
DidCaptureFrame(frame_number, oracle_frame_number, std::move(frame),
gfx::Rect());
return;
}
- const gfx::Rect content_rect =
- media::ComputeLetterboxRegionForI420(frame->visible_rect(), source_size);
-
- // For passive refresh requests, just deliver the resurrected frame.
- if (event == VideoCaptureOracle::kPassiveRefreshRequest) {
+ // For passive refreshes, just deliver the resurrected frame.
+ if (dirty_rect_.IsEmpty()) {
DidCaptureFrame(frame_number, oracle_frame_number, std::move(frame),
content_rect);
return;
@@ -455,6 +530,7 @@ void FrameSinkVideoCapturerImpl::MaybeCaptureFrame(
// just the part of the result that would have changed due to aggregated
// damage over all the frames that weren't captured.
request->set_result_selection(gfx::Rect(content_rect.size()));
+ dirty_rect_ = gfx::Rect();
resolved_target_->RequestCopyOfSurface(std::move(request));
}
@@ -556,6 +632,10 @@ void FrameSinkVideoCapturerImpl::MaybeDeliverFrame(
(media_ticks - base::TimeTicks()).InMicroseconds());
if (!should_deliver_frame) {
+ // Mark the whole source as dirty, since this frame may have contained
+ // updated content that will not be delivered.
+ dirty_rect_ = kMaxRect;
+ ScheduleRefreshFrame();
return;
}
@@ -569,13 +649,8 @@ void FrameSinkVideoCapturerImpl::MaybeDeliverFrame(
// send to the consumer. The handle is READ_WRITE because the consumer is free
// to modify the content further (so long as it undoes its changes before the
// InFlightFrameDelivery::Done() call).
- DCHECK_EQ(frame->storage_type(),
- media::VideoFrame::STORAGE_MOJO_SHARED_BUFFER);
- auto* const mojo_frame =
- static_cast<media::MojoSharedBufferVideoFrame*>(frame.get());
- mojo::ScopedSharedBufferHandle buffer = mojo_frame->Handle().Clone(
- mojo::SharedBufferHandle::AccessMode::READ_WRITE);
- const uint32_t buffer_size = static_cast<uint32_t>(mojo_frame->MappedSize());
+ auto buffer_and_size = frame_pool_.CloneHandleForDelivery(frame.get());
+ DCHECK(buffer_and_size.first.is_valid());
// Assemble frame layout, format, and metadata into a mojo struct to send to
// the consumer.
@@ -595,14 +670,19 @@ void FrameSinkVideoCapturerImpl::MaybeDeliverFrame(
mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks;
mojo::MakeStrongBinding(
std::make_unique<InFlightFrameDelivery>(
- frame_pool_.HoldFrameForDelivery(frame.get()),
+ base::BindOnce(
+ [](scoped_refptr<VideoFrame> frame) {
+ DCHECK(frame->HasOneRef());
+ },
+ std::move(frame)),
base::BindOnce(&VideoCaptureOracle::RecordConsumerFeedback,
feedback_weak_factory_.GetWeakPtr(),
oracle_frame_number)),
mojo::MakeRequest(&callbacks));
// Send the frame to the consumer.
- consumer_->OnFrameCaptured(std::move(buffer), buffer_size, std::move(info),
+ consumer_->OnFrameCaptured(std::move(buffer_and_size.first),
+ buffer_and_size.second, std::move(info),
update_rect, content_rect, std::move(callbacks));
}
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 5aa90f3909b..14ab4617fda 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
@@ -125,10 +125,6 @@ class VIZ_SERVICE_EXPORT FrameSinkVideoCapturerImpl final
// exceeding 60% of the design limit is considered "red line" operation.
static constexpr float kTargetPipelineUtilization = 0.6f;
- // The amount of time to wait before retrying a refresh frame request.
- static constexpr base::TimeDelta kRefreshFrameRetryInterval =
- base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond / 4);
-
private:
friend class FrameSinkVideoCapturerTest;
@@ -136,6 +132,29 @@ class VIZ_SERVICE_EXPORT FrameSinkVideoCapturerImpl final
using OracleFrameNumber =
decltype(std::declval<media::VideoCaptureOracle>().next_frame_number());
+ // Starts the refresh frame timer to guarantee a frame representing the most
+ // up-to-date content will be sent to the consumer in the near future. This
+ // refresh operation will be canceled if a compositing event triggers a frame
+ // capture in the meantime.
+ void ScheduleRefreshFrame();
+
+ // Returns the delay that should be used when setting the refresh timer. This
+ // is based on the current oracle prediction for frame duration.
+ base::TimeDelta GetDelayBeforeNextRefreshAttempt() const;
+
+ // Called whenever a major damage event, such as a capture parameter change, a
+ // resolved target change, etc., occurs. This marks the entire source as dirty
+ // and ensures the consumer will receive a refresh frame with up-to-date
+ // content.
+ void RefreshEntireSourceSoon();
+
+ // Executes a refresh capture, if conditions permit. Otherwise, schedules a
+ // later retry. Note that the retry "polling" should be a short-term state,
+ // since it only occurs until the oracle allows the next frame capture to take
+ // place. If a refresh was already pending, it is canceled in favor of this
+ // new refresh.
+ void RefreshSoon();
+
// CapturableFrameSink::Client implementation:
void OnBeginFrame(const BeginFrameArgs& args) final;
void OnFrameDamaged(const BeginFrameAck& ack,
@@ -216,15 +235,23 @@ class VIZ_SERVICE_EXPORT FrameSinkVideoCapturerImpl final
using TimeRingBuffer = std::array<base::TimeTicks, kDesignLimitMaxFrames>;
base::flat_map<BeginFrameSourceId, TimeRingBuffer> frame_display_times_;
+ // The portion of the source content that has changed, but has not yet been
+ // captured.
+ gfx::Rect dirty_rect_;
+
// These are sequence counters used to ensure that the frames are being
// delivered in the same order they are captured.
int64_t next_capture_frame_number_ = 0;
int64_t next_delivery_frame_number_ = 0;
- // When the oracle rejects a "refresh frame" request, this timer is set to
- // auto-retry the refresh at a later point. This ensures refresh frame
- // requests eventually result in a frame being delivered to the consumer.
- base::OneShotTimer refresh_frame_retry_timer_;
+ // This timer is started whenever the consumer needs another frame delivered.
+ // This might be because: 1) the consumer was just started and needs an
+ // initial frame; 2) the capture target changed; 3) the oracle rejected
+ // an event for timing reasons; 4) to satisfy explicit requests for a refresh
+ // 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_;
// 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
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 62e6faaa360..c3443125076 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
@@ -4,12 +4,13 @@
#include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/callback.h"
#include "base/optional.h"
#include "base/run_loop.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "base/test/test_simple_task_runner.h"
+#include "base/test/test_mock_time_task_runner.h"
#include "base/time/time.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
@@ -135,7 +136,7 @@ class MockConsumer : public mojom::FrameSinkVideoConsumer {
frames_.push_back(std::move(frame));
done_callbacks_.push_back(
base::BindOnce(&mojom::FrameSinkVideoConsumerFrameCallbacks::Done,
- base::Passed(&callbacks)));
+ std::move(callbacks)));
}
mojo::Binding<mojom::FrameSinkVideoConsumer> binding_;
@@ -195,7 +196,7 @@ class FakeCapturableFrameSink : public CapturableFrameSink {
client_ = nullptr;
}
- gfx::Size GetSurfaceSize() override { return kSourceSize; }
+ gfx::Size GetActiveFrameSize() override { return kSourceSize; }
void RequestCopyOfSurface(
std::unique_ptr<CopyOutputRequest> request) override {
@@ -211,7 +212,7 @@ class FakeCapturableFrameSink : public CapturableFrameSink {
std::unique_ptr<CopyOutputResult> result) {
request->SendResult(std::move(result));
},
- base::Passed(&request), base::Passed(&result)));
+ std::move(request), std::move(result)));
}
void SetCopyOutputColor(YUVColor color) { color_ = color; }
@@ -273,19 +274,23 @@ MATCHER_P(IsLetterboxedFrame, color, "") {
class FrameSinkVideoCapturerTest : public testing::Test {
public:
FrameSinkVideoCapturerTest()
- : retry_timer_task_runner_(new base::TestSimpleTaskRunner()),
- capturer_(&frame_sink_manager_,
+ : capturer_(&frame_sink_manager_,
mojom::FrameSinkVideoCapturerRequest()) {}
void SetUp() override {
- // Override the capturer's TickClock with the one controlled by the tests.
- start_time_ = base::TimeTicks() + base::TimeDelta::FromSeconds(1);
- clock_.SetNowTicks(start_time_);
- capturer_.clock_ = &clock_;
-
- // Point the retry timer at this test's manually-controlled task runner.
- capturer_.refresh_frame_retry_timer_.SetTaskRunner(
- retry_timer_task_runner_);
+ // Override the capturer's TickClock with a virtual clock managed by a
+ // manually-driven task runner.
+ task_runner_ = new base::TestMockTimeTaskRunner(
+ base::Time::Now(), base::TimeTicks() + base::TimeDelta::FromSeconds(1),
+ base::TestMockTimeTaskRunner::Type::kStandalone);
+ start_time_ = task_runner_->NowTicks();
+ clock_ = task_runner_->GetMockTickClock();
+ capturer_.clock_ = clock_.get();
+
+ // Replace the retry timer with one that uses this test's fake clock and
+ // task runner.
+ capturer_.refresh_frame_retry_timer_.emplace(clock_.get());
+ capturer_.refresh_frame_retry_timer_->SetTaskRunner(task_runner_);
// Before setting the format, ensure the defaults are in-place. Then, for
// these tests, set a specific format and color space.
@@ -307,7 +312,7 @@ class FrameSinkVideoCapturerTest : public testing::Test {
capturer_.SetResolutionConstraints(kCaptureSize, kCaptureSize, false);
}
- void TearDown() override { retry_timer_task_runner_->ClearPendingTasks(); }
+ void TearDown() override { task_runner_->ClearPendingTasks(); }
void StartCapture(MockConsumer* consumer) {
capturer_.Start(consumer->BindVideoConsumer());
@@ -320,17 +325,17 @@ class FrameSinkVideoCapturerTest : public testing::Test {
}
void AdvanceClockToNextVsync() {
- const auto num_vsyncs_elapsed =
- (clock_.NowTicks() - start_time_) / kVsyncInterval;
+ const auto now = task_runner_->NowTicks();
+ const auto num_vsyncs_elapsed = (now - start_time_) / kVsyncInterval;
const auto advance_to_time =
start_time_ + (num_vsyncs_elapsed + 1) * kVsyncInterval;
- clock_.Advance(advance_to_time - clock_.NowTicks());
+ task_runner_->FastForwardBy(advance_to_time - now);
}
void NotifyBeginFrame(int source_id, int frame_number) {
BeginFrameArgs args;
args.interval = kVsyncInterval;
- args.frame_time = clock_.NowTicks();
+ args.frame_time = task_runner_->NowTicks();
args.sequence_number = BeginFrameArgs::kStartingFrameNumber + frame_number;
args.source_id = source_id;
capturer_.OnBeginFrame(args);
@@ -349,13 +354,12 @@ class FrameSinkVideoCapturerTest : public testing::Test {
}
bool IsRefreshRetryTimerRunning() {
- return capturer_.refresh_frame_retry_timer_.IsRunning();
+ return capturer_.refresh_frame_retry_timer_->IsRunning();
}
- void FireRefreshRetryTimer() {
- ASSERT_TRUE(IsRefreshRetryTimerRunning());
- ASSERT_TRUE(retry_timer_task_runner_->HasPendingTask());
- retry_timer_task_runner_->RunPendingTasks();
+ void AdvanceClockForRefreshTimer() {
+ task_runner_->FastForwardBy(capturer_.GetDelayBeforeNextRefreshAttempt());
+ PropagateMojoTasks();
}
bool HasCacheEntryForSource(int source_id) {
@@ -368,9 +372,9 @@ class FrameSinkVideoCapturerTest : public testing::Test {
}
protected:
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
base::TimeTicks start_time_;
- base::SimpleTestTickClock clock_;
- scoped_refptr<base::TestSimpleTaskRunner> retry_timer_task_runner_;
+ std::unique_ptr<base::TickClock> clock_;
MockFrameSinkManager frame_sink_manager_;
FakeCapturableFrameSink frame_sink_;
FrameSinkVideoCapturerImpl capturer_;
@@ -434,28 +438,40 @@ TEST_F(FrameSinkVideoCapturerTest, ReportsTargetLost) {
StopCapture();
}
-// Tests that an initial black frame is sent, in the case where a target is not
-// resolved at the time Start() is called.
-TEST_F(FrameSinkVideoCapturerTest, SendsBlackFrameOnStartWithoutATarget) {
+// Tests that no initial frame is sent after Start() is called until after the
+// target has been resolved.
+TEST_F(FrameSinkVideoCapturerTest, PostponesCaptureWithoutATarget) {
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
MockConsumer consumer;
- EXPECT_CALL(
- consumer,
- OnFrameCapturedMock(IsLetterboxedFrame(YUVColor{0x00, 0x80, 0x80}), _, _))
- .Times(1);
+ EXPECT_CALL(consumer, OnFrameCapturedMock(_, _, _)).Times(0);
EXPECT_CALL(consumer, OnTargetLost(kFrameSinkId)).Times(0);
EXPECT_CALL(consumer, OnStopped()).Times(1);
StartCapture(&consumer);
- // A copy request was not necessary.
+ // No copy requests should have been issued/executed.
EXPECT_EQ(0, frame_sink_.num_copy_results());
- // The initial black frame is the initial refresh frame. Since that was
- // supposed to have been sent, the timer should not be running to retry
- // later.
+ // The refresh timer is running, which represents the need for an initial
+ // frame to be sent.
+ EXPECT_TRUE(IsRefreshRetryTimerRunning());
+
+ // Simulate several refresh timer intervals elapsing and the timer firing.
+ // Nothing should happen because the capture target was never set.
+ for (int i = 0; i < 5; ++i) {
+ AdvanceClockForRefreshTimer();
+ ASSERT_EQ(0, frame_sink_.num_copy_results());
+ ASSERT_TRUE(IsRefreshRetryTimerRunning());
+ }
+
+ // Now, set the target. As it resolves, the capturer will immediately attempt
+ // a refresh capture, which will cancel the timer and trigger a copy request.
+ capturer_.ChangeTarget(kFrameSinkId);
+ EXPECT_EQ(1, frame_sink_.num_copy_results());
EXPECT_FALSE(IsRefreshRetryTimerRunning());
+
StopCapture();
+ EXPECT_FALSE(IsRefreshRetryTimerRunning());
}
// An end-to-end pipeline test where compositor updates trigger the capturer to
@@ -467,6 +483,7 @@ TEST_F(FrameSinkVideoCapturerTest, CapturesCompositedFrames) {
.WillRepeatedly(Return(&frame_sink_));
capturer_.ChangeTarget(kFrameSinkId);
+ EXPECT_FALSE(IsRefreshRetryTimerRunning());
MockConsumer consumer;
const int num_refresh_frames = 1;
@@ -478,11 +495,13 @@ TEST_F(FrameSinkVideoCapturerTest, CapturesCompositedFrames) {
EXPECT_CALL(consumer, OnStopped()).Times(1);
StartCapture(&consumer);
- // To start, the capturer will make a copy request for the initial refresh
- // frame. Simulate a copy result and expect to see the refresh frame delivered
- // to the consumer.
+ // Since the target was already resolved at start, the capturer will have
+ // immediately executed a refresh capture and triggered a copy request.
ASSERT_EQ(num_refresh_frames, frame_sink_.num_copy_results());
EXPECT_FALSE(IsRefreshRetryTimerRunning());
+
+ // Simulate execution of the copy request and expect to see the initial
+ // refresh frame delivered to the consumer.
frame_sink_.SendCopyOutputResult(0);
ASSERT_EQ(num_refresh_frames, consumer.num_frames_received());
EXPECT_THAT(consumer.TakeFrame(0),
@@ -499,23 +518,24 @@ TEST_F(FrameSinkVideoCapturerTest, CapturesCompositedFrames) {
// compositing of the frame has begun.
AdvanceClockToNextVsync();
const base::TimeTicks expected_reference_time =
- clock_.NowTicks() + kVsyncInterval;
+ task_runner_->NowTicks() + kVsyncInterval;
NotifyBeginFrame(1, i);
// Change the content of the frame sink and notify the capturer of the
// damage.
const YUVColor color = {i << 4, (i << 4) + 0x10, (i << 4) + 0x20};
frame_sink_.SetCopyOutputColor(color);
- clock_.Advance(kVsyncInterval / 4);
- const base::TimeTicks expected_capture_begin_time = clock_.NowTicks();
+ task_runner_->FastForwardBy(kVsyncInterval / 4);
+ const base::TimeTicks expected_capture_begin_time =
+ task_runner_->NowTicks();
NotifyFrameDamaged(1, i);
// The frame sink should have received a CopyOutputRequest. Simulate a short
// pause before the result is sent back to the capturer, and the capturer
// should then deliver the frame.
ASSERT_EQ(i + 1, frame_sink_.num_copy_results());
- clock_.Advance(kVsyncInterval / 4);
- const base::TimeTicks expected_capture_end_time = clock_.NowTicks();
+ task_runner_->FastForwardBy(kVsyncInterval / 4);
+ const base::TimeTicks expected_capture_end_time = task_runner_->NowTicks();
frame_sink_.SendCopyOutputResult(i);
ASSERT_EQ(i + 1, consumer.num_frames_received());
@@ -574,24 +594,32 @@ TEST_F(FrameSinkVideoCapturerTest, HaltsWhenPipelineIsFull) {
NiceMock<MockConsumer> consumer;
StartCapture(&consumer);
+ // With the start, an immediate refresh occurred.
+ const int num_refresh_frames = 1;
+ ASSERT_EQ(num_refresh_frames, frame_sink_.num_copy_results());
+ EXPECT_FALSE(IsRefreshRetryTimerRunning());
// Saturate the pipeline with CopyOutputRequests that have not yet executed.
- const int num_refresh_frames = 1;
int num_frames = FrameSinkVideoCapturerImpl::kDesignLimitMaxFrames;
for (int i = num_refresh_frames; i < num_frames; ++i) {
AdvanceClockToNextVsync();
NotifyBeginFrame(1, i);
NotifyFrameDamaged(1, i);
+ // The oracle should not be rejecting captures caused by compositor updates.
+ ASSERT_FALSE(IsRefreshRetryTimerRunning());
}
ASSERT_EQ(num_frames, frame_sink_.num_copy_results());
// Notifying the capturer of new compositor updates should cause no new copy
- // requests to be issued at this point.
+ // requests to be issued at this point. However, the refresh timer should be
+ // scheduled to account for the capture of changed content that could not take
+ // place.
const int first_uncaptured_frame = num_frames;
AdvanceClockToNextVsync();
NotifyBeginFrame(1, first_uncaptured_frame);
NotifyFrameDamaged(1, first_uncaptured_frame);
ASSERT_EQ(num_frames, frame_sink_.num_copy_results());
+ EXPECT_TRUE(IsRefreshRetryTimerRunning());
// Complete the first copy request. When notifying the capturer of another
// compositor update, no new copy requests should be issued because the first
@@ -603,10 +631,12 @@ TEST_F(FrameSinkVideoCapturerTest, HaltsWhenPipelineIsFull) {
NotifyBeginFrame(1, second_uncaptured_frame);
NotifyFrameDamaged(1, second_uncaptured_frame);
ASSERT_EQ(num_frames, frame_sink_.num_copy_results());
+ EXPECT_TRUE(IsRefreshRetryTimerRunning());
// Notify the capturer that the first frame has been consumed. Then, with
// another compositor update, the capturer should issue another new copy
- // request.
+ // request. The refresh timer should no longer be running because the next
+ // capture will satisfy the need to send updated content to the consumer.
EXPECT_TRUE(consumer.TakeFrame(0));
consumer.SendDoneNotification(0);
const int first_capture_resumed_frame = second_uncaptured_frame + 1;
@@ -615,14 +645,17 @@ TEST_F(FrameSinkVideoCapturerTest, HaltsWhenPipelineIsFull) {
NotifyFrameDamaged(1, first_capture_resumed_frame);
++num_frames;
ASSERT_EQ(num_frames, frame_sink_.num_copy_results());
+ EXPECT_FALSE(IsRefreshRetryTimerRunning());
// With yet another compositor update, no new copy requests should be issued
- // because the pipeline became saturated again.
+ // because the pipeline became saturated again. Once again, the refresh timer
+ // should be started to account for the need to capture at some future point.
const int third_uncaptured_frame = first_capture_resumed_frame + 1;
AdvanceClockToNextVsync();
NotifyBeginFrame(1, third_uncaptured_frame);
NotifyFrameDamaged(1, third_uncaptured_frame);
ASSERT_EQ(num_frames, frame_sink_.num_copy_results());
+ EXPECT_TRUE(IsRefreshRetryTimerRunning());
// Complete all pending copy requests. Another compositor update should not
// cause any new copy requests to be issued because all frames are being
@@ -637,6 +670,7 @@ TEST_F(FrameSinkVideoCapturerTest, HaltsWhenPipelineIsFull) {
NotifyBeginFrame(1, fourth_uncaptured_frame);
NotifyFrameDamaged(1, fourth_uncaptured_frame);
ASSERT_EQ(num_frames, frame_sink_.num_copy_results());
+ EXPECT_TRUE(IsRefreshRetryTimerRunning());
// Notify the capturer that all frames have been consumed. Finally, with
// another compositor update, capture should resume.
@@ -653,6 +687,7 @@ TEST_F(FrameSinkVideoCapturerTest, HaltsWhenPipelineIsFull) {
ASSERT_EQ(num_frames, frame_sink_.num_copy_results());
frame_sink_.SendCopyOutputResult(frame_sink_.num_copy_results() - 1);
ASSERT_EQ(frame_sink_.num_copy_results(), consumer.num_frames_received());
+ EXPECT_FALSE(IsRefreshRetryTimerRunning());
StopCapture();
}
@@ -671,11 +706,11 @@ TEST_F(FrameSinkVideoCapturerTest, DeliversFramesInOrder) {
NiceMock<MockConsumer> consumer;
StartCapture(&consumer);
- // Issue five CopyOutputRequests (1 refresh frame plus 4 compositor
- // updates). Each composited frame has its content region set to a different
- // color to check that the video frames are being delivered in-order.
- const int num_refresh_frames = 1;
- int num_frames = 5;
+ // Simulate five compositor updates. Each composited frame has its content
+ // region set to a different color to check that the video frames are being
+ // delivered in-order.
+ constexpr int num_refresh_frames = 1;
+ constexpr int num_frames = 5;
ASSERT_EQ(num_refresh_frames, frame_sink_.num_copy_results());
for (int i = num_refresh_frames; i < num_frames; ++i) {
colors.push_back(YUVColor{static_cast<uint8_t>(i << 4),
@@ -727,12 +762,13 @@ TEST_F(FrameSinkVideoCapturerTest, CancelsInFlightCapturesOnStop) {
EXPECT_CALL(consumer, OnTargetLost(_)).Times(0);
EXPECT_CALL(consumer, OnStopped()).Times(1);
StartCapture(&consumer);
-
- // Issue three additional CopyOutputRequests. With the initial refresh frame,
- // the total should be four.
- int num_refresh_frames = 1;
+ // With the start, an immediate refresh should have occurred.
+ const int num_refresh_frames = 1;
ASSERT_EQ(num_refresh_frames, frame_sink_.num_copy_results());
- int num_copy_requests = 4;
+ EXPECT_FALSE(IsRefreshRetryTimerRunning());
+
+ // Simulate two compositor updates following the initial refresh.
+ int num_copy_requests = 3;
for (int i = num_refresh_frames; i < num_copy_requests; ++i) {
SCOPED_TRACE(testing::Message() << "frame #" << i);
AdvanceClockToNextVsync();
@@ -763,6 +799,10 @@ TEST_F(FrameSinkVideoCapturerTest, CancelsInFlightCapturesOnStop) {
EXPECT_CALL(consumer2, OnTargetLost(_)).Times(0);
EXPECT_CALL(consumer2, OnStopped()).Times(1);
StartCapture(&consumer2);
+ // With the start, a refresh was attempted, but since the attempt occurred so
+ // soon after the last frame capture, the oracle should have rejected it.
+ // Thus, the refresh timer should be running.
+ EXPECT_TRUE(IsRefreshRetryTimerRunning());
// Complete the copy requests for the first consumer. Expect that they have no
// effect on the second consumer.
@@ -770,22 +810,20 @@ TEST_F(FrameSinkVideoCapturerTest, CancelsInFlightCapturesOnStop) {
frame_sink_.SendCopyOutputResult(i);
ASSERT_EQ(0, consumer2.num_frames_received());
}
- num_completed_captures = 0;
- // Note: Because the clock hasn't advanced while switching consumers, the
- // capturer won't send a refresh frame. This is because the VideoCaptureOracle
- // thinks the frame rate would be too fast. However, the refresh frame retry
- // timer should be running. It will be canceled when the next composite-
- // triggered capture occurs (in the loop below).
- num_refresh_frames = 0;
- EXPECT_TRUE(IsRefreshRetryTimerRunning());
+ // Reset the counter for |consumer2|.
+ num_completed_captures = 0;
// From here, any new copy requests should be executed with video frames
// delivered to the consumer containing |color2|.
- for (int i = num_refresh_frames; i < num_captures_for_second_consumer; ++i) {
+ for (int i = 0; i < num_captures_for_second_consumer; ++i) {
AdvanceClockToNextVsync();
- NotifyBeginFrame(1, num_copy_requests);
- NotifyFrameDamaged(1, num_copy_requests);
+ if (i == 0) {
+ // Expect that advancing the clock caused the refresh timer to fire.
+ } else {
+ NotifyBeginFrame(1, num_copy_requests);
+ NotifyFrameDamaged(1, num_copy_requests);
+ }
++num_copy_requests;
ASSERT_EQ(num_copy_requests, frame_sink_.num_copy_results());
ASSERT_FALSE(IsRefreshRetryTimerRunning());
@@ -817,10 +855,8 @@ TEST_F(FrameSinkVideoCapturerTest, EventuallySendsARefreshFrame) {
EXPECT_CALL(consumer, OnStopped()).Times(1);
StartCapture(&consumer);
- // To start, the capturer will make a copy request for the initial refresh
- // frame. Simulate a copy result and expect to see the refresh frame delivered
- // to the consumer. The capturer should not have started the retry timer for
- // this initial refresh frame.
+ // With the start, an immediate refresh occurred. Simulate a copy result and
+ // expect to see the refresh frame delivered to the consumer.
ASSERT_EQ(1, frame_sink_.num_copy_results());
EXPECT_FALSE(IsRefreshRetryTimerRunning());
frame_sink_.SendCopyOutputResult(0);
@@ -834,28 +870,25 @@ TEST_F(FrameSinkVideoCapturerTest, EventuallySendsARefreshFrame) {
NotifyBeginFrame(1, i);
NotifyFrameDamaged(1, i);
ASSERT_EQ(i + 1, frame_sink_.num_copy_results());
+ ASSERT_FALSE(IsRefreshRetryTimerRunning());
frame_sink_.SendCopyOutputResult(i);
ASSERT_EQ(i + 1, consumer.num_frames_received());
consumer.SendDoneNotification(i);
}
- // Without advancing the clock, request a refresh frame. The oracle will
- // reject the request, and the retry timer will be started.
+ // Request a refresh frame. Because the refresh request was made just after
+ // the last frame capture, the refresh retry timer should be started.
capturer_.RequestRefreshFrame();
ASSERT_EQ(num_frames, frame_sink_.num_copy_results());
EXPECT_TRUE(IsRefreshRetryTimerRunning());
- // Simulate the elapse of time and the firing of the refresh retry timer. The
- // oracle should allow this later retry request and deliver a refresh frame.
- clock_.Advance(FrameSinkVideoCapturerImpl::kRefreshFrameRetryInterval);
- FireRefreshRetryTimer();
- if (frame_sink_.num_copy_results() == num_frames + 1) {
- frame_sink_.SendCopyOutputResult(num_frames);
- } else {
- // No copy request was made, because the implementation successfully
- // resurrected the buffer from the prior capture.
- }
- ASSERT_EQ(num_frames, consumer.num_frames_received());
+ // Simulate the elapse of time and the firing of the refresh retry timer.
+ // Since no compositor updates occurred in the meantime, this will execute a
+ // passive refresh, which resurrects the last buffer instead of spawning an
+ // additional copy request.
+ AdvanceClockForRefreshTimer();
+ ASSERT_EQ(num_frames, frame_sink_.num_copy_results());
+ ASSERT_EQ(num_frames + 1, consumer.num_frames_received());
EXPECT_FALSE(IsRefreshRetryTimerRunning());
StopCapture();
@@ -881,10 +914,10 @@ TEST_F(FrameSinkVideoCapturerTest, CachesAndPrunesDisplayTimes) {
// Make a sequence of OnBeginFrame() calls for source_id=2. The cache entries
// for both sources should remain.
const base::TimeTicks end_time =
- clock_.NowTicks() + GetDisplayTimeCacheKeepAliveInterval();
+ task_runner_->NowTicks() + GetDisplayTimeCacheKeepAliveInterval();
int seq = 2;
- while (clock_.NowTicks() < end_time) {
- clock_.Advance(kVsyncInterval);
+ while (task_runner_->NowTicks() < end_time) {
+ task_runner_->FastForwardBy(kVsyncInterval);
NotifyBeginFrame(2, seq++);
ASSERT_TRUE(HasCacheEntryForSource(1));
ASSERT_TRUE(HasCacheEntryForSource(2));
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc b/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc
index eccd000a734..cb888449836 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc
+++ b/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc
@@ -4,139 +4,213 @@
#include "components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h"
+#include <algorithm>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "media/base/video_frame.h"
-#include "media/capture/video/video_capture_buffer_tracker_factory_impl.h"
-#include "media/mojo/common/mojo_shared_buffer_video_frame.h"
-#include "ui/gfx/geometry/size.h"
-using media::VideoCaptureBufferPool;
-using media::VideoCaptureBufferPoolImpl;
using media::VideoFrame;
using media::VideoPixelFormat;
namespace viz {
+// static
+constexpr base::TimeDelta InterprocessFramePool::kMinLoggingPeriod;
+
InterprocessFramePool::InterprocessFramePool(int capacity)
- : buffer_pool_(new VideoCaptureBufferPoolImpl(
- std::make_unique<media::VideoCaptureBufferTrackerFactoryImpl>(),
- capacity)),
- weak_factory_(this) {}
+ : capacity_(std::max(capacity, 0)), weak_factory_(this) {
+ DCHECK_GT(capacity_, 0u);
+}
InterprocessFramePool::~InterprocessFramePool() = default;
scoped_refptr<VideoFrame> InterprocessFramePool::ReserveVideoFrame(
- const gfx::Size& size,
- VideoPixelFormat format) {
+ VideoPixelFormat format,
+ const gfx::Size& size) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- BufferId ignored; // Not applicable to this buffer pool use case.
- const BufferId buffer_id = buffer_pool_->ReserveForProducer(
- size, format, media::VideoPixelStorage::CPU,
- 0 /* unused: frame_feedback_id */, &ignored);
- if (buffer_id == VideoCaptureBufferPool::kInvalidId) {
+ // Calling this method is a signal that there is no intention of resurrecting
+ // the last frame.
+ resurrectable_handle_ = MOJO_HANDLE_INVALID;
+
+ const size_t bytes_required = VideoFrame::AllocationSize(format, size);
+
+ // Look for an available buffer that's large enough. If one is found, wrap it
+ // in a VideoFrame and return it.
+ for (auto it = available_buffers_.rbegin(); it != available_buffers_.rend();
+ ++it) {
+ if (it->bytes_allocated < bytes_required) {
+ continue;
+ }
+ PooledBuffer taken = std::move(*it);
+ available_buffers_.erase(it.base() - 1);
+ return WrapBuffer(std::move(taken), format, size);
+ }
+
+ // Look for the largest available buffer, reallocate it, wrap it in a
+ // VideoFrame and return it.
+ while (!available_buffers_.empty()) {
+ const auto it =
+ std::max_element(available_buffers_.rbegin(), available_buffers_.rend(),
+ [this](const PooledBuffer& a, const PooledBuffer& b) {
+ return a.bytes_allocated < b.bytes_allocated;
+ });
+ available_buffers_.erase(it.base() - 1); // Release before allocating more.
+ PooledBuffer reallocated;
+ reallocated.buffer = mojo::SharedBufferHandle::Create(bytes_required);
+ if (!reallocated.buffer.is_valid()) {
+ LOG_IF(WARNING, CanLogSharedMemoryFailure())
+ << "Failed to re-allocate " << bytes_required << " bytes.";
+ continue; // Try again after freeing the next-largest buffer.
+ }
+ reallocated.bytes_allocated = bytes_required;
+ return WrapBuffer(std::move(reallocated), format, size);
+ }
+
+ // There are no available buffers. If the pool is at max capacity, punt.
+ // Otherwise, allocate a new buffer, wrap it in a VideoFrame and return it.
+ if (utilized_buffers_.size() >= capacity_) {
+ return nullptr;
+ }
+ PooledBuffer additional;
+ additional.buffer = mojo::SharedBufferHandle::Create(bytes_required);
+ if (!additional.buffer.is_valid()) {
+ LOG_IF(WARNING, CanLogSharedMemoryFailure())
+ << "Failed to allocate " << bytes_required << " bytes.";
return nullptr;
}
- resurrectable_buffer_id_ = VideoCaptureBufferPool::kInvalidId;
- return WrapBuffer(buffer_id, size, format);
+ additional.bytes_allocated = bytes_required;
+ return WrapBuffer(std::move(additional), format, size);
}
scoped_refptr<VideoFrame> InterprocessFramePool::ResurrectLastVideoFrame(
- const gfx::Size& expected_size,
- VideoPixelFormat expected_format) {
+ VideoPixelFormat expected_format,
+ const gfx::Size& expected_size) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- const BufferId buffer_id = buffer_pool_->ResurrectLastForProducer(
- expected_size, expected_format, media::VideoPixelStorage::CPU);
- if (buffer_id != resurrectable_buffer_id_ ||
- buffer_id == VideoCaptureBufferPool::kInvalidId) {
+ // Find the tracking entry for the resurrectable buffer. If it is still being
+ // used, or is not of the expected format and size, punt.
+ if (resurrectable_handle_ == MOJO_HANDLE_INVALID ||
+ last_delivered_format_ != expected_format ||
+ last_delivered_size_ != expected_size) {
return nullptr;
}
- return WrapBuffer(buffer_id, expected_size, expected_format);
+ const auto it = std::find_if(
+ available_buffers_.rbegin(), available_buffers_.rend(),
+ [this](const PooledBuffer& candidate) {
+ return candidate.buffer.get().value() == resurrectable_handle_;
+ });
+ if (it == available_buffers_.rend()) {
+ return nullptr;
+ }
+
+ // Wrap the buffer in a VideoFrame and return it.
+ PooledBuffer resurrected = std::move(*it);
+ available_buffers_.erase(it.base() - 1);
+ return WrapBuffer(std::move(resurrected), expected_format, expected_size);
}
-base::OnceClosure InterprocessFramePool::HoldFrameForDelivery(
- const VideoFrame* frame) {
+InterprocessFramePool::BufferAndSize
+InterprocessFramePool::CloneHandleForDelivery(const VideoFrame* frame) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- const auto it = buffer_map_.find(frame);
- DCHECK(it != buffer_map_.end());
- const BufferId buffer_id = it->second;
- resurrectable_buffer_id_ = buffer_id;
- buffer_pool_->HoldForConsumers(buffer_id, 1);
- return base::BindOnce(&VideoCaptureBufferPoolImpl::RelinquishConsumerHold,
- buffer_pool_, buffer_id, 1);
+ // Record that this frame is the last-delivered one, for possible future calls
+ // to ResurrectLastVideoFrame().
+ const auto it = utilized_buffers_.find(frame);
+ DCHECK(it != utilized_buffers_.end());
+ resurrectable_handle_ = it->second.buffer.get().value();
+ last_delivered_format_ = frame->format();
+ last_delivered_size_ = frame->coded_size();
+
+ return BufferAndSize(it->second.buffer->Clone(
+ mojo::SharedBufferHandle::AccessMode::READ_WRITE),
+ it->second.bytes_allocated);
}
float InterprocessFramePool::GetUtilization() const {
- // Note: Technically, the |buffer_pool_| is completely thread-safe; so no
- // sequence check is needed here.
- return buffer_pool_->GetBufferPoolUtilization();
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ return static_cast<float>(utilized_buffers_.size()) / capacity_;
}
scoped_refptr<VideoFrame> InterprocessFramePool::WrapBuffer(
- BufferId buffer_id,
- const gfx::Size& size,
- VideoPixelFormat format) {
+ PooledBuffer pooled_buffer,
+ VideoPixelFormat format,
+ const gfx::Size& size) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- // Mojo takes ownership of shared memory handles. Here, the pool has created
- // and owns the original shared memory handle, but will duplicate it for Mojo.
- mojo::ScopedSharedBufferHandle buffer =
- buffer_pool_->GetHandleForInterProcessTransit(buffer_id,
- false /* read-write */);
- if (!buffer.is_valid()) {
- return nullptr;
+ DCHECK(pooled_buffer.buffer.is_valid());
+
+ // Map the shared memory into the current process, or move an existing
+ // "scoped mapping" into the local variable. The mapping will be owned by the
+ // VideoFrame wrapper (below) until the VideoFrame goes out-of-scope; and this
+ // might be after InterprocessFramePool is destroyed.
+ mojo::ScopedSharedBufferMapping mapping;
+ if (pooled_buffer.mapping) {
+ mapping = std::move(pooled_buffer.mapping);
+ } else {
+ mapping = pooled_buffer.buffer->Map(pooled_buffer.bytes_allocated);
+ if (!mapping) {
+ LOG_IF(WARNING, CanLogSharedMemoryFailure())
+ << "Failed to map shared memory to back the VideoFrame ("
+ << pooled_buffer.bytes_allocated << " bytes).";
+ // The shared memory will be freed when pooled_buffer goes out-of-scope
+ // here:
+ return nullptr;
+ }
}
- const gfx::Size& y_plane_size =
- VideoFrame::PlaneSize(format, VideoFrame::kYPlane, size);
- const int y_plane_bytes = y_plane_size.GetArea();
- const gfx::Size& u_plane_size =
- VideoFrame::PlaneSize(format, VideoFrame::kUPlane, size);
- const int u_plane_bytes = u_plane_size.GetArea();
- const gfx::Size& v_plane_size =
- VideoFrame::PlaneSize(format, VideoFrame::kVPlane, size);
- const int v_plane_bytes = v_plane_size.GetArea();
- // TODO(miu): This could all be made much simpler if we had our own ctor in
- // MojoSharedBufferVideoFrame.
- const scoped_refptr<VideoFrame> frame =
- media::MojoSharedBufferVideoFrame::Create(
- format, size, gfx::Rect(size), size, std::move(buffer),
- y_plane_bytes + u_plane_bytes + v_plane_bytes, 0 /* y_offset */,
- y_plane_bytes /* u_offset */,
- y_plane_bytes + u_plane_bytes /* v_offset */, y_plane_size.width(),
- u_plane_size.width(), v_plane_size.width(), base::TimeDelta());
+ // Create the VideoFrame wrapper, add tracking in |utilized_buffers_|, and add
+ // a destruction observer to return the buffer to the pool once the VideoFrame
+ // goes out-of-scope.
+ //
+ // The VideoFrame could be held, externally, beyond the lifetime of this
+ // InterprocessFramePool. However, this is safe because 1) the use of a
+ // WeakPtr cancels the callback that would return the buffer back to the pool,
+ // and 2) the mapped memory remains valid until the ScopedSharedBufferMapping
+ // goes out-of-scope (when the OnceClosure is destroyed).
+ scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalData(
+ format, size, gfx::Rect(size), size, static_cast<uint8_t*>(mapping.get()),
+ pooled_buffer.bytes_allocated, base::TimeDelta());
DCHECK(frame);
-
- // Add an entry so that HoldFrameForDelivery() can identify the buffer backing
- // this VideoFrame.
- buffer_map_[frame.get()] = buffer_id;
-
- // Add a destruction observer to update |buffer_map_|. A WeakPtr is used for
- // safety, just in case the VideoFrame's scope extends beyond that of this
- // InterprocessFramePool.
- frame->AddDestructionObserver(base::BindOnce(
- &InterprocessFramePool::OnFrameWrapperDestroyed,
- weak_factory_.GetWeakPtr(), base::Unretained(frame.get())));
-
- // The second destruction observer is a callback to the
- // VideoCaptureBufferPoolImpl directly. Since |buffer_pool_| is ref-counted,
- // this means InterprocessFramePool can be safely destroyed even if there are
- // still outstanding VideoFrames.
+ utilized_buffers_.emplace(frame.get(), std::move(pooled_buffer));
frame->AddDestructionObserver(
- base::BindOnce(&VideoCaptureBufferPoolImpl::RelinquishProducerReservation,
- buffer_pool_, buffer_id));
+ base::BindOnce(&InterprocessFramePool::OnFrameWrapperDestroyed,
+ weak_factory_.GetWeakPtr(), base::Unretained(frame.get()),
+ std::move(mapping)));
return frame;
}
-void InterprocessFramePool::OnFrameWrapperDestroyed(const VideoFrame* frame) {
+void InterprocessFramePool::OnFrameWrapperDestroyed(
+ const VideoFrame* frame,
+ mojo::ScopedSharedBufferMapping mapping) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- const auto it = buffer_map_.find(frame);
- DCHECK(it != buffer_map_.end());
- buffer_map_.erase(it);
+ // Return the buffer to the pool by moving the PooledBuffer back into
+ // |available_buffers_|.
+ const auto it = utilized_buffers_.find(frame);
+ DCHECK(it != utilized_buffers_.end());
+ available_buffers_.emplace_back(std::move(it->second));
+ available_buffers_.back().mapping = std::move(mapping);
+ utilized_buffers_.erase(it);
+ DCHECK_LE(available_buffers_.size() + utilized_buffers_.size(), capacity_);
}
+bool InterprocessFramePool::CanLogSharedMemoryFailure() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ const base::TimeTicks now = base::TimeTicks::Now();
+ if ((now - last_fail_log_time_) >= kMinLoggingPeriod) {
+ last_fail_log_time_ = now;
+ return true;
+ }
+ return false;
+}
+
+InterprocessFramePool::PooledBuffer::PooledBuffer() = default;
+InterprocessFramePool::PooledBuffer::PooledBuffer(PooledBuffer&& other) =
+ default;
+InterprocessFramePool::PooledBuffer& InterprocessFramePool::PooledBuffer::
+operator=(PooledBuffer&& other) = default;
+InterprocessFramePool::PooledBuffer::~PooledBuffer() = default;
+
} // namespace viz
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h b/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h
index 59c7ec07e08..f75d9214bfe 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h
+++ b/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h
@@ -5,23 +5,21 @@
#ifndef COMPONENTS_VIZ_SERVICE_FRAME_SINKS_VIDEO_CAPTURE_INTERPROCESS_FRAME_POOL_H_
#define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_VIDEO_CAPTURE_INTERPROCESS_FRAME_POOL_H_
+#include <utility>
+#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/sequence_checker.h"
+#include "base/time/time.h"
#include "components/viz/service/viz_service_export.h"
+#include "media/base/video_frame.h"
#include "media/base/video_types.h"
-#include "media/capture/video/video_capture_buffer_pool_impl.h"
-
-namespace gfx {
-class Size;
-}
-
-namespace media {
-class VideoFrame;
-}
+#include "mojo/public/cpp/system/buffer.h"
+#include "ui/gfx/geometry/size.h"
namespace viz {
@@ -29,58 +27,100 @@ namespace viz {
// efficiently across mojo service boundaries.
class VIZ_SERVICE_EXPORT InterprocessFramePool {
public:
+ using BufferAndSize = std::pair<mojo::ScopedSharedBufferHandle, size_t>;
+
+ // |capacity| is the maximum number of pooled VideoFrames; but they can be of
+ // any byte size.
explicit InterprocessFramePool(int capacity);
~InterprocessFramePool();
- // Reserves a buffer from the pool and creates a I420 VideoFrame to wrap its
- // shared memory. When the ref-count of the returned VideoFrame goes to zero,
- // the reservation is released. Returns null if the pool is fully utilized.
+ // Reserves a buffer from the pool and creates a VideoFrame to wrap its shared
+ // memory. When the ref-count of the returned VideoFrame goes to zero, the
+ // reservation is released and the frame becomes available for re-use. Returns
+ // null if the pool is fully utilized.
scoped_refptr<media::VideoFrame> ReserveVideoFrame(
- const gfx::Size& size,
- media::VideoPixelFormat format);
-
- // Finds the last VideoFrame delivered, and attempts to re-materialize it. If
- // the attempt fails, null is returned. This is used when the client knows the
- // content of the video frame has not changed and is trying to avoid having to
- // re-populate a new VideoFrame with the same content.
+ media::VideoPixelFormat format,
+ const gfx::Size& size);
+
+ // Finds the last VideoFrame delivered, and if it has been returned back to
+ // this pool already, re-materializes it. Otherwise, null is returned. This is
+ // used when the client knows the content of the video frame has not changed
+ // and is trying to avoid having to re-populate a new VideoFrame with the same
+ // content.
scoped_refptr<media::VideoFrame> ResurrectLastVideoFrame(
- const gfx::Size& expected_size,
- media::VideoPixelFormat expected_format);
-
- // Pins the memory buffer backing the given |frame| while it is being
- // delivered to, and read by, downstream consumers. This prevents the memory
- // buffer from being reserved until after the returned closure is run. The
- // caller must guarantee the returned closure is run to prevent memory leaks.
- base::OnceClosure HoldFrameForDelivery(const media::VideoFrame* frame);
-
- // Returns the current pool utilization, consisting of all reserved frames
- // plus those being held for delivery.
+ media::VideoPixelFormat expected_format,
+ const gfx::Size& expected_size);
+
+ // Returns a cloned handle to the shared memory backing |frame| and its size
+ // in bytes. Note that the client should not allow the ref-count of the
+ // VideoFrame to reach zero until downstream consumers are finished using it,
+ // as this would allow the shared memory to be re-used for a later frame.
+ //
+ // Calling this method is a signal that |frame| should be considered the
+ // last-delivered frame, for the purposes of ResurrectLastVideoFrame().
+ BufferAndSize CloneHandleForDelivery(const media::VideoFrame* frame);
+
+ // Returns the current pool utilization, based on the number of VideoFrames
+ // being held by the client.
float GetUtilization() const;
private:
- using BufferId = decltype(media::VideoCaptureBufferPool::kInvalidId + 0);
-
- // Helper to build a media::MojoSharedBufferVideoFrame instance backed by a
- // specific buffer from the |buffer_pool_|.
- scoped_refptr<media::VideoFrame> WrapBuffer(BufferId buffer_id,
- const gfx::Size& size,
- media::VideoPixelFormat format);
+ // Tracking data for pooled buffers.
+ struct PooledBuffer {
+ mojo::ScopedSharedBufferHandle buffer;
+ size_t bytes_allocated;
+ mojo::ScopedSharedBufferMapping mapping;
+
+ PooledBuffer();
+ PooledBuffer(PooledBuffer&&);
+ PooledBuffer& operator=(PooledBuffer&&);
+ ~PooledBuffer();
+ };
+
+ // Creates a media::VideoFrame backed by a specific pooled buffer.
+ scoped_refptr<media::VideoFrame> WrapBuffer(PooledBuffer pooled_buffer,
+ media::VideoPixelFormat format,
+ const gfx::Size& size);
// Called when a reserved/resurrected VideoFrame goes out of scope, to remove
- // the entry from |buffer_map_|.
- void OnFrameWrapperDestroyed(const media::VideoFrame* frame);
-
- // Maintains a pool of shared memory buffers for inter-process delivery of
- // video frame data.
- const scoped_refptr<media::VideoCaptureBufferPoolImpl> buffer_pool_;
-
- // The VideoFrames that are currently wrapping a specific buffer in the pool.
- base::flat_map<const media::VideoFrame*, BufferId> buffer_map_;
-
- // The ID of the buffer that was last delivered. This is used to determine
- // whether the previous VideoFrame was actually populated, and should be
- // resurrected by ResurrectLastVideoFrame().
- BufferId resurrectable_buffer_id_ = media::VideoCaptureBufferPool::kInvalidId;
+ // the entry from |utilized_buffers_| and place the PooledBuffer back into
+ // |available_buffers_|.
+ void OnFrameWrapperDestroyed(const media::VideoFrame* frame,
+ mojo::ScopedSharedBufferMapping mapping);
+
+ // Returns true if a shared memory failure can be logged. This is a rate
+ // throttle, to ensure the logs aren't spammed in chronically low-memory
+ // environments.
+ bool CanLogSharedMemoryFailure();
+
+ // The maximum number of buffers. However, the buffers themselves can be of
+ // any byte size.
+ const size_t capacity_;
+
+ // Buffers available for immediate re-use. Generally, it is best to push and
+ // pop from the back of this vector so that the most-recently-used buffers are
+ // re-used. This will help prevent excessive operating system paging in low-
+ // memory situations.
+ std::vector<PooledBuffer> available_buffers_;
+
+ // A map of externally-owned VideoFrames and the tracking information about
+ // the shared memory buffer backing them.
+ base::flat_map<const media::VideoFrame*, PooledBuffer> utilized_buffers_;
+
+ // The handle of the buffer that was last delivered, along with its format and
+ // size. ResurrectLastVideoFrame() uses this information to locate and confirm
+ // that a prior frame can be resurrected.
+ MojoHandle resurrectable_handle_ = MOJO_HANDLE_INVALID;
+ media::VideoPixelFormat last_delivered_format_ = media::PIXEL_FORMAT_UNKNOWN;
+ gfx::Size last_delivered_size_;
+
+ // The time at which the last shared memory allocation or mapping failed.
+ base::TimeTicks last_fail_log_time_;
+
+ // The amount of time that should elapsed between log warnings about shared
+ // memory allocation/mapping failures.
+ static constexpr base::TimeDelta kMinLoggingPeriod =
+ base::TimeDelta::FromSeconds(10);
SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc b/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc
index 22b50d42aeb..4263bd40015 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool_unittest.cc
@@ -18,40 +18,107 @@ namespace {
constexpr gfx::Size kSize = gfx::Size(32, 18);
constexpr media::VideoPixelFormat kFormat = media::PIXEL_FORMAT_I420;
+void ExpectValidBufferForDelivery(
+ const InterprocessFramePool::BufferAndSize& buffer_and_size) {
+ EXPECT_TRUE(buffer_and_size.first.is_valid());
+ constexpr int kI420BitsPerPixel = 12;
+ EXPECT_LE(static_cast<size_t>(kSize.GetArea() * kI420BitsPerPixel / 8),
+ buffer_and_size.second);
+}
+
TEST(InterprocessFramePoolTest, FramesConfiguredCorrectly) {
InterprocessFramePool pool(1);
const scoped_refptr<media::VideoFrame> frame =
- pool.ReserveVideoFrame(kSize, kFormat);
+ pool.ReserveVideoFrame(kFormat, kSize);
ASSERT_TRUE(frame);
ASSERT_EQ(kSize, frame->coded_size());
ASSERT_EQ(gfx::Rect(kSize), frame->visible_rect());
ASSERT_EQ(kSize, frame->natural_size());
- ASSERT_EQ(frame->storage_type(), VideoFrame::STORAGE_MOJO_SHARED_BUFFER);
ASSERT_TRUE(frame->IsMappable());
}
+TEST(InterprocessFramePool, UsesAvailableBuffersIfPossible) {
+ constexpr gfx::Size kSmallerSize =
+ gfx::Size(kSize.width() / 2, kSize.height() / 2);
+ constexpr gfx::Size kBiggerSize =
+ gfx::Size(kSize.width() * 2, kSize.height() * 2);
+
+ InterprocessFramePool pool(1);
+
+ // Reserve a frame of baseline size and then free it to return it to the pool.
+ scoped_refptr<media::VideoFrame> frame =
+ pool.ReserveVideoFrame(kFormat, kSize);
+ ASSERT_TRUE(frame);
+ size_t baseline_bytes_allocated;
+ {
+ auto buffer_and_size = pool.CloneHandleForDelivery(frame.get());
+ ExpectValidBufferForDelivery(buffer_and_size);
+ baseline_bytes_allocated = buffer_and_size.second;
+ }
+ frame = nullptr; // Returns frame to pool.
+
+ // Now, attempt to reserve a smaller-sized frame. Expect that the same buffer
+ // is backing the frame because it's large enough.
+ frame = pool.ReserveVideoFrame(kFormat, kSmallerSize);
+ ASSERT_TRUE(frame);
+ {
+ auto buffer_and_size = pool.CloneHandleForDelivery(frame.get());
+ ExpectValidBufferForDelivery(buffer_and_size);
+ EXPECT_EQ(baseline_bytes_allocated, buffer_and_size.second);
+ }
+ frame = nullptr; // Returns frame to pool.
+
+ // Now, attempt to reserve a larger-than-baseline-sized frame. Expect that a
+ // different buffer is backing the frame because a larger one had to be
+ // allocated.
+ frame = pool.ReserveVideoFrame(kFormat, kBiggerSize);
+ ASSERT_TRUE(frame);
+ size_t larger_buffer_bytes_allocated;
+ {
+ auto buffer_and_size = pool.CloneHandleForDelivery(frame.get());
+ ExpectValidBufferForDelivery(buffer_and_size);
+ larger_buffer_bytes_allocated = buffer_and_size.second;
+ EXPECT_LT(baseline_bytes_allocated, larger_buffer_bytes_allocated);
+ }
+ frame = nullptr; // Returns frame to pool.
+
+ // Finally, if either a baseline-sized or a smaller-than-baseline-sized frame
+ // is reserved, expect that the same larger buffer is backing the frames.
+ constexpr gfx::Size kTheSmallerSizes[] = {kSmallerSize, kSize};
+ for (const auto& size : kTheSmallerSizes) {
+ frame = pool.ReserveVideoFrame(kFormat, size);
+ ASSERT_TRUE(frame);
+ {
+ auto buffer_and_size = pool.CloneHandleForDelivery(frame.get());
+ ExpectValidBufferForDelivery(buffer_and_size);
+ EXPECT_EQ(larger_buffer_bytes_allocated, buffer_and_size.second);
+ }
+ frame = nullptr; // Returns frame to pool.
+ }
+}
+
TEST(InterprocessFramePoolTest, ReachesCapacityLimit) {
InterprocessFramePool pool(2);
scoped_refptr<media::VideoFrame> frames[5];
// Reserve two frames from a pool of capacity 2.
- frames[0] = pool.ReserveVideoFrame(kSize, kFormat);
+ frames[0] = pool.ReserveVideoFrame(kFormat, kSize);
ASSERT_TRUE(frames[0]);
- frames[1] = pool.ReserveVideoFrame(kSize, kFormat);
+ frames[1] = pool.ReserveVideoFrame(kFormat, kSize);
ASSERT_TRUE(frames[1]);
// Now, try to reserve a third frame. This should fail (return null).
- frames[2] = pool.ReserveVideoFrame(kSize, kFormat);
+ frames[2] = pool.ReserveVideoFrame(kFormat, kSize);
ASSERT_FALSE(frames[2]);
// Release the first frame. Then, retry reserving a frame. This should
// succeed.
frames[0] = nullptr;
- frames[3] = pool.ReserveVideoFrame(kSize, kFormat);
+ frames[3] = pool.ReserveVideoFrame(kFormat, kSize);
ASSERT_TRUE(frames[3]);
// Finally, try to reserve yet another frame. This should fail.
- frames[4] = pool.ReserveVideoFrame(kSize, kFormat);
+ frames[4] = pool.ReserveVideoFrame(kFormat, kSize);
ASSERT_FALSE(frames[4]);
}
@@ -81,61 +148,64 @@ TEST(InterprocessFramePoolTest, ResurrectsDeliveredFramesOnly) {
// Reserve a frame, populate it, but release it before delivery.
scoped_refptr<media::VideoFrame> frame =
- pool.ReserveVideoFrame(kSize, kFormat);
+ pool.ReserveVideoFrame(kFormat, kSize);
ASSERT_TRUE(frame);
media::FillYUV(frame.get(), 0x11, 0x22, 0x33);
- frame = nullptr;
+ frame = nullptr; // Returns frame to pool.
// The pool should fail to resurrect the last frame because it was never
// delivered.
- frame = pool.ResurrectLastVideoFrame(kSize, kFormat);
+ frame = pool.ResurrectLastVideoFrame(kFormat, kSize);
ASSERT_FALSE(frame);
// Reserve a frame and populate it with different color values; only this
- // time, deliver it before releasing it.
- frame = pool.ReserveVideoFrame(kSize, kFormat);
+ // time, signal that it will be delivered before releasing it.
+ frame = pool.ReserveVideoFrame(kFormat, kSize);
ASSERT_TRUE(frame);
const uint8_t kValues[3] = {0x44, 0x55, 0x66};
media::FillYUV(frame.get(), kValues[0], kValues[1], kValues[2]);
- base::OnceClosure post_delivery_callback =
- pool.HoldFrameForDelivery(frame.get());
- frame = nullptr;
- std::move(post_delivery_callback).Run();
+ {
+ auto buffer_and_size = pool.CloneHandleForDelivery(frame.get());
+ ExpectValidBufferForDelivery(buffer_and_size);
+ }
+ frame = nullptr; // Returns frame to pool.
// Confirm that the last frame can be resurrected repeatedly.
for (int i = 0; i < 3; ++i) {
- frame = pool.ResurrectLastVideoFrame(kSize, kFormat);
+ frame = pool.ResurrectLastVideoFrame(kFormat, kSize);
ASSERT_TRUE(frame);
ASSERT_TRUE(PlanesAreFilledWithValues(*frame, kValues));
- frame = nullptr;
+ frame = nullptr; // Returns frame to pool.
}
// A frame that is being delivered cannot be resurrected.
for (int i = 0; i < 2; ++i) {
if (i == 0) { // Test this for a resurrected frame.
- frame = pool.ResurrectLastVideoFrame(kSize, kFormat);
+ frame = pool.ResurrectLastVideoFrame(kFormat, kSize);
ASSERT_TRUE(frame);
ASSERT_TRUE(PlanesAreFilledWithValues(*frame, kValues));
} else { // Test this for a normal frame.
- frame = pool.ReserveVideoFrame(kSize, kFormat);
+ frame = pool.ReserveVideoFrame(kFormat, kSize);
ASSERT_TRUE(frame);
media::FillYUV(frame.get(), 0x77, 0x88, 0x99);
}
- post_delivery_callback = pool.HoldFrameForDelivery(frame.get());
- frame = nullptr;
+ {
+ auto buffer_and_size = pool.CloneHandleForDelivery(frame.get());
+ ExpectValidBufferForDelivery(buffer_and_size);
+ }
scoped_refptr<media::VideoFrame> should_be_null =
- pool.ResurrectLastVideoFrame(kSize, kFormat);
+ pool.ResurrectLastVideoFrame(kFormat, kSize);
ASSERT_FALSE(should_be_null);
- std::move(post_delivery_callback).Run();
+ frame = nullptr; // Returns frame to pool.
}
// Finally, reserve a frame, populate it, and don't deliver it. Expect that,
// still, undelivered frames cannot be resurrected.
- frame = pool.ReserveVideoFrame(kSize, kFormat);
+ frame = pool.ReserveVideoFrame(kFormat, kSize);
ASSERT_TRUE(frame);
media::FillYUV(frame.get(), 0xaa, 0xbb, 0xcc);
- frame = nullptr;
- frame = pool.ResurrectLastVideoFrame(kSize, kFormat);
+ frame = nullptr; // Returns frame to pool.
+ frame = pool.ResurrectLastVideoFrame(kFormat, kSize);
ASSERT_FALSE(frame);
}
@@ -148,24 +218,23 @@ TEST(InterprocessFramePoolTest, ReportsCorrectUtilization) {
for (int i = 0; i < 2; ++i) {
// Reserve the frame and expect 1/2 the pool to be utilized.
scoped_refptr<media::VideoFrame> frame =
- (i == 0) ? pool.ReserveVideoFrame(kSize, kFormat)
- : pool.ResurrectLastVideoFrame(kSize, kFormat);
+ (i == 0) ? pool.ReserveVideoFrame(kFormat, kSize)
+ : pool.ResurrectLastVideoFrame(kFormat, kSize);
ASSERT_TRUE(frame);
ASSERT_EQ(0.5f, pool.GetUtilization());
- // Hold the frame for delivery. This should not change the utilization.
- base::OnceClosure post_delivery_callback =
- pool.HoldFrameForDelivery(frame.get());
+ // Signal that the frame will be delivered. This should not change the
+ // utilization.
+ {
+ auto buffer_and_size = pool.CloneHandleForDelivery(frame.get());
+ ExpectValidBufferForDelivery(buffer_and_size);
+ }
ASSERT_EQ(0.5f, pool.GetUtilization());
- // Release the frame. Since it is being held for delivery, this should not
- // change the utilization.
+ // Finally, release the frame to indicate it has been delivered and is no
+ // longer in-use by downstream consumers. This should cause the utilization
+ // to go back down to zero.
frame = nullptr;
- ASSERT_EQ(0.5f, pool.GetUtilization());
-
- // Finally, run the callback to indicate the frame has been delivered. This
- // should cause the utilization to go back down to zero.
- std::move(post_delivery_callback).Run();
ASSERT_EQ(0.0f, pool.GetUtilization());
}
}
diff --git a/chromium/components/viz/service/frame_sinks/video_detector.h b/chromium/components/viz/service/frame_sinks/video_detector.h
index 2b7fb72871f..319a6790667 100644
--- a/chromium/components/viz/service/frame_sinks/video_detector.h
+++ b/chromium/components/viz/service/frame_sinks/video_detector.h
@@ -73,7 +73,8 @@ class VIZ_SERVICE_EXPORT VideoDetector : public SurfaceObserver {
// SurfaceObserver implementation.
void OnSurfaceCreated(const SurfaceId& surface_id) override {}
void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override {}
- void OnSurfaceActivated(const SurfaceId& surface_id) override {}
+ void OnSurfaceActivated(const SurfaceId& surface_id,
+ base::Optional<base::TimeDelta> duration) override {}
void OnSurfaceDestroyed(const SurfaceId& surface_id) override {}
bool OnSurfaceDamaged(const SurfaceId& surface_id,
const BeginFrameAck& ack) override;
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 843a0f4c1dc..b7e87cefee4 100644
--- a/chromium/components/viz/service/frame_sinks/video_detector_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/video_detector_unittest.cc
@@ -112,7 +112,8 @@ class VideoDetectorTest : public testing::Test {
}
void CreateDisplayFrame() {
- surface_aggregator_.Aggregate(root_frame_sink_->current_surface_id());
+ surface_aggregator_.Aggregate(
+ root_frame_sink_->last_activated_surface_id());
}
void EmbedClient(CompositorFrameSinkSupport* frame_sink) {
@@ -129,18 +130,19 @@ class VideoDetectorTest : public testing::Test {
SurfaceDrawQuad* quad =
render_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
quad->SetNew(shared_quad_state, gfx::Rect(0, 0, 10, 10),
- gfx::Rect(0, 0, 5, 5), frame_sink->current_surface_id(),
- base::nullopt, SK_ColorMAGENTA, false);
+ gfx::Rect(0, 0, 5, 5),
+ frame_sink->last_activated_surface_id(), base::nullopt,
+ SK_ColorMAGENTA, false);
}
root_frame_sink_->SubmitCompositorFrame(
- root_frame_sink_->local_surface_id(), std::move(frame));
+ root_frame_sink_->last_activated_local_surface_id(), std::move(frame));
}
void SendUpdate(CompositorFrameSinkSupport* frame_sink,
const gfx::Rect& damage) {
LocalSurfaceId local_surface_id =
- frame_sink->local_surface_id().is_valid()
- ? frame_sink->local_surface_id()
+ frame_sink->last_activated_local_surface_id().is_valid()
+ ? frame_sink->last_activated_local_surface_id()
: parent_local_surface_id_allocator_.GenerateId();
frame_sink->SubmitCompositorFrame(local_surface_id,
MakeDamagedCompositorFrame(damage));
diff --git a/chromium/components/viz/service/gl/DEPS b/chromium/components/viz/service/gl/DEPS
index df9c3464cca..55cd3a78ac7 100644
--- a/chromium/components/viz/service/gl/DEPS
+++ b/chromium/components/viz/service/gl/DEPS
@@ -1,3 +1,5 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+components/arc/video_accelerator",
"+components/crash/core/common/crash_key.h",
diff --git a/chromium/components/viz/service/gl/gpu_service_impl.cc b/chromium/components/viz/service/gl/gpu_service_impl.cc
index b1693250121..29adbb573f5 100644
--- a/chromium/components/viz/service/gl/gpu_service_impl.cc
+++ b/chromium/components/viz/service/gl/gpu_service_impl.cc
@@ -5,6 +5,7 @@
#include "components/viz/service/gl/gpu_service_impl.h"
#include <memory>
+#include <utility>
#include "base/bind.h"
#include "base/command_line.h"
@@ -221,8 +222,8 @@ void GpuServiceImpl::Bind(mojom::GpuServiceRequest request) {
if (main_runner_->BelongsToCurrentThread()) {
bind_task_tracker_.PostTask(
io_runner_.get(), FROM_HERE,
- base::Bind(&GpuServiceImpl::Bind, base::Unretained(this),
- base::Passed(std::move(request))));
+ base::BindOnce(&GpuServiceImpl::Bind, base::Unretained(this),
+ std::move(request)));
return;
}
bindings_->AddBinding(this, std::move(request));
@@ -426,21 +427,10 @@ void GpuServiceImpl::UpdateGpuInfoPlatform(
if (in_host_process())
return;
- DCHECK_EQ(gpu::kCollectInfoNone, gpu_info_.context_info_state);
- gpu::CollectInfoResult result = gpu::CollectContextGraphicsInfo(&gpu_info_);
- switch (result) {
- case gpu::kCollectInfoFatalFailure:
- LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal).";
- // TODO(piman): can we signal overall failure?
- break;
- case gpu::kCollectInfoNonFatalFailure:
- DVLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal).";
- break;
- case gpu::kCollectInfoNone:
- NOTREACHED();
- break;
- case gpu::kCollectInfoSuccess:
- break;
+ bool success = gpu::CollectContextGraphicsInfo(&gpu_info_);
+ if (!success) {
+ LOG(ERROR) << "gpu::CollectGraphicsInfo failed.";
+ // TODO(piman): can we signal overall failure?
}
gpu::SetKeysForCrashLogging(gpu_info_);
std::move(on_gpu_info_updated).Run();
@@ -470,8 +460,6 @@ void GpuServiceImpl::UpdateGpuInfoPlatform(
[](GpuServiceImpl* gpu_service, base::OnceClosure on_gpu_info_updated,
const gpu::DxDiagNode& dx_diag_node) {
gpu_service->gpu_info_.dx_diagnostics = dx_diag_node;
- gpu_service->gpu_info_.dx_diagnostics_info_state =
- gpu::kCollectInfoSuccess;
std::move(on_gpu_info_updated).Run();
},
this, std::move(on_gpu_info_updated)));
diff --git a/chromium/components/viz/service/hit_test/DEPS b/chromium/components/viz/service/hit_test/DEPS
index 38ff3f7e806..363efa2c6ba 100644
--- a/chromium/components/viz/service/hit_test/DEPS
+++ b/chromium/components/viz/service/hit_test/DEPS
@@ -1,3 +1,5 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
"+components/viz/service/surfaces",
]
@@ -5,5 +7,6 @@ include_rules = [
specific_include_rules = {
"hit_test_aggregator_unittest.cc": [
"+components/viz/host/host_frame_sink_manager.h",
- ]
+ "+components/viz/service/frame_sinks",
+ ],
}
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 63fcc2a8404..aaab034778e 100644
--- a/chromium/components/viz/service/hit_test/hit_test_aggregator.cc
+++ b/chromium/components/viz/service/hit_test/hit_test_aggregator.cc
@@ -4,6 +4,7 @@
#include "components/viz/service/hit_test/hit_test_aggregator.h"
+#include "base/metrics/histogram_macros.h"
#include "components/viz/common/hit_test/aggregated_hit_test_region.h"
#include "components/viz/service/hit_test/hit_test_aggregator_delegate.h"
#include "third_party/skia/include/core/SkMatrix44.h"
@@ -31,9 +32,11 @@ void PrepareTransformForReadOnlySharedMemory(gfx::Transform* transform) {
} // namespace
HitTestAggregator::HitTestAggregator(const HitTestManager* hit_test_manager,
- HitTestAggregatorDelegate* delegate)
+ HitTestAggregatorDelegate* delegate,
+ const FrameSinkId& frame_sink_id)
: hit_test_manager_(hit_test_manager),
delegate_(delegate),
+ root_frame_sink_id_(frame_sink_id),
weak_ptr_factory_(this) {
AllocateHitTestRegionArray();
}
@@ -52,11 +55,13 @@ void HitTestAggregator::GrowRegionList() {
void HitTestAggregator::Swap() {
SwapHandles();
if (!handle_replaced_) {
- delegate_->SwitchActiveAggregatedHitTestRegionList(active_handle_index_);
+ delegate_->SwitchActiveAggregatedHitTestRegionList(root_frame_sink_id_,
+ active_handle_index_);
return;
}
delegate_->OnAggregatedHitTestRegionListUpdated(
+ root_frame_sink_id_,
read_handle_->Clone(mojo::SharedBufferHandle::AccessMode::READ_ONLY),
read_size_,
write_handle_->Clone(mojo::SharedBufferHandle::AccessMode::READ_ONLY),
@@ -74,7 +79,9 @@ void HitTestAggregator::AllocateHitTestRegionArray() {
void HitTestAggregator::ResizeHitTestRegionArray(uint32_t size) {
size_t num_bytes = size * sizeof(AggregatedHitTestRegion);
write_handle_ = mojo::SharedBufferHandle::Create(num_bytes);
+ DCHECK(write_handle_.is_valid());
auto new_buffer_ = write_handle_->Map(num_bytes);
+ DCHECK(new_buffer_);
handle_replaced_ = true;
AggregatedHitTestRegion* region = (AggregatedHitTestRegion*)new_buffer_.get();
@@ -97,6 +104,8 @@ void HitTestAggregator::SwapHandles() {
}
void HitTestAggregator::AppendRoot(const SurfaceId& surface_id) {
+ SCOPED_UMA_HISTOGRAM_TIMER("Event.VizHitTest.AggregateTime");
+
const mojom::HitTestRegionList* hit_test_region_list =
hit_test_manager_->GetActiveHitTestRegionList(surface_id);
if (!hit_test_region_list)
@@ -111,6 +120,7 @@ void HitTestAggregator::AppendRoot(const SurfaceId& surface_id) {
DCHECK_GE(region_index, 1u);
int32_t child_count = region_index - 1;
+ UMA_HISTOGRAM_COUNTS_1000("Event.VizHitTest.HitTestRegions", region_index);
SetRegionAt(0, surface_id.frame_sink_id(), hit_test_region_list->flags,
hit_test_region_list->bounds, hit_test_region_list->transform,
child_count);
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 f62386c2b3a..3119691ae40 100644
--- a/chromium/components/viz/service/hit_test/hit_test_aggregator.h
+++ b/chromium/components/viz/service/hit_test/hit_test_aggregator.h
@@ -27,7 +27,8 @@ class VIZ_SERVICE_EXPORT HitTestAggregator {
public:
// |delegate| owns and outlives HitTestAggregator.
HitTestAggregator(const HitTestManager* hit_test_manager,
- HitTestAggregatorDelegate* delegate);
+ HitTestAggregatorDelegate* delegate,
+ const FrameSinkId& frame_sink_id);
~HitTestAggregator();
// Called after surfaces have been aggregated into the DisplayFrame.
@@ -43,25 +44,6 @@ class VIZ_SERVICE_EXPORT HitTestAggregator {
private:
friend class TestHitTestAggregator;
- const HitTestManager* const hit_test_manager_;
-
- mojo::ScopedSharedBufferHandle read_handle_;
- mojo::ScopedSharedBufferHandle write_handle_;
-
- // The number of elements allocated.
- uint32_t read_size_ = 0;
- uint32_t write_size_ = 0;
-
- mojo::ScopedSharedBufferMapping read_buffer_;
- mojo::ScopedSharedBufferMapping write_buffer_;
-
- bool handle_replaced_ = false;
-
- // Can only be 0 or 1 when we only have two buffers.
- uint8_t active_handle_index_ = 0;
-
- HitTestAggregatorDelegate* const delegate_;
-
// Allocates memory for the AggregatedHitTestRegion array.
void AllocateHitTestRegionArray();
@@ -93,6 +75,28 @@ class VIZ_SERVICE_EXPORT HitTestAggregator {
// Marks the element at the given index as the end of list.
void MarkEndAt(size_t index);
+ const HitTestManager* const hit_test_manager_;
+
+ mojo::ScopedSharedBufferHandle read_handle_;
+ mojo::ScopedSharedBufferHandle write_handle_;
+
+ // The number of elements allocated.
+ uint32_t read_size_ = 0;
+ uint32_t write_size_ = 0;
+
+ mojo::ScopedSharedBufferMapping read_buffer_;
+ mojo::ScopedSharedBufferMapping write_buffer_;
+
+ bool handle_replaced_ = false;
+
+ // Can only be 0 or 1 when we only have two buffers.
+ uint8_t active_handle_index_ = 0;
+
+ HitTestAggregatorDelegate* const delegate_;
+
+ // This is the FrameSinkId for the corresponding root CompositorFrameSink.
+ const FrameSinkId root_frame_sink_id_;
+
// Handles the case when this object is deleted after
// the PostTaskAggregation call is scheduled but before invocation.
base::WeakPtrFactory<HitTestAggregator> weak_ptr_factory_;
diff --git a/chromium/components/viz/service/hit_test/hit_test_aggregator_delegate.h b/chromium/components/viz/service/hit_test/hit_test_aggregator_delegate.h
index 4d990d287d2..51b9b338c79 100644
--- a/chromium/components/viz/service/hit_test/hit_test_aggregator_delegate.h
+++ b/chromium/components/viz/service/hit_test/hit_test_aggregator_delegate.h
@@ -6,19 +6,21 @@
#define COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_AGGREGATOR_DELEGATE_H_
namespace viz {
-// Used by HitTestAggregator to talk to GpuRootCompositorFrameSink.
+// Used by HitTestAggregator to talk to FrameSinkManagerImpl.
class HitTestAggregatorDelegate {
public:
// Called if any of the buffer that stores the aggregated hit-test data is
// updated (e.g. destroyed, reallocated etc.). |active_handle| and
// |idle_handle| both must be valid.
virtual void OnAggregatedHitTestRegionListUpdated(
+ const FrameSinkId& frame_sink_id,
mojo::ScopedSharedBufferHandle active_handle,
uint32_t active_handle_size,
mojo::ScopedSharedBufferHandle idle_handle,
uint32_t idle_handle_size) = 0;
virtual void SwitchActiveAggregatedHitTestRegionList(
+ const FrameSinkId& frame_sink_id,
uint8_t active_handle_index) = 0;
protected:
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 57cd1d326bc..af7fc3b3a87 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
@@ -11,114 +11,28 @@
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/host/host_frame_sink_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/hit_test/hit_test_aggregator_delegate.h"
+#include "components/viz/service/surfaces/surface_manager.h"
+#include "components/viz/test/compositor_frame_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace viz {
namespace {
-constexpr FrameSinkId kDisplayFrameSink(2, 0);
+constexpr uint32_t kDisplayClientId = 2;
+constexpr FrameSinkId kDisplayFrameSink(kDisplayClientId, 0);
-SurfaceId MakeSurfaceId(const FrameSinkId& frame_sink_id, uint32_t parent_id) {
+SurfaceId MakeSurfaceId(uint32_t frame_sink_id_client_id) {
return SurfaceId(
- frame_sink_id,
- LocalSurfaceId(parent_id, base::UnguessableToken::Deserialize(0, 1u)));
+ FrameSinkId(frame_sink_id_client_id, 0),
+ LocalSurfaceId(1, base::UnguessableToken::Deserialize(0, 1u)));
}
-} // namespace
-
-class TestHitTestAggregator final : public HitTestAggregator {
- public:
- TestHitTestAggregator(HitTestManager* manager,
- HitTestAggregatorDelegate* delegate)
- : HitTestAggregator(manager, delegate) {}
- ~TestHitTestAggregator() = default;
-
- int GetRegionCount() const {
- AggregatedHitTestRegion* start =
- static_cast<AggregatedHitTestRegion*>(read_buffer_.get());
- AggregatedHitTestRegion* end = start;
- while (end->child_count != kEndOfList)
- end++;
- return end - start;
- }
- int GetHitTestRegionListSize() { return read_size_; }
- void SwapHandles() {
- delegate_->SwitchActiveAggregatedHitTestRegionList(active_handle_index_);
- }
-
- void Reset() {
- AggregatedHitTestRegion* regions =
- static_cast<AggregatedHitTestRegion*>(write_buffer_.get());
- regions[0].child_count = kEndOfList;
-
- regions = static_cast<AggregatedHitTestRegion*>(read_buffer_.get());
- regions[0].child_count = kEndOfList;
- }
-};
-
-namespace {
-
-class TestFrameSinkManagerImpl;
-
-} // namespace
-
-class TestHitTestManager : public HitTestManager {
- public:
- explicit TestHitTestManager(TestFrameSinkManagerImpl* frame_sink_manager);
- ~TestHitTestManager() override = default;
-
- void CallOnSurfaceActivated(const SurfaceId surface_id) {
- OnSurfaceActivated(surface_id);
- }
- void CallOnSurfaceDiscarded(const SurfaceId surface_id) {
- OnSurfaceDiscarded(surface_id);
- }
- void Reset() { hit_test_region_lists_.clear(); }
-
- int GetRegionCount() {
- int count = 0;
- for (auto& i : hit_test_region_lists_) {
- count += i.second.size();
- }
- return count;
- }
-};
-
-namespace {
-
-class TestGpuRootCompositorFrameSink : public HitTestAggregatorDelegate {
- public:
- TestGpuRootCompositorFrameSink(TestHitTestManager* hit_test_manager,
- TestFrameSinkManagerImpl* frame_sink_manager,
- const FrameSinkId& frame_sink_id)
- : frame_sink_manager_(frame_sink_manager),
- frame_sink_id_(frame_sink_id),
- aggregator_(
- std::make_unique<TestHitTestAggregator>(hit_test_manager, this)) {}
- ~TestGpuRootCompositorFrameSink() override = default;
-
- // HitTestAggregatorDelegate:
- void OnAggregatedHitTestRegionListUpdated(
- mojo::ScopedSharedBufferHandle active_handle,
- uint32_t active_handle_size,
- mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_size) override;
- void SwitchActiveAggregatedHitTestRegionList(
- uint8_t active_handle_index) override;
-
- TestHitTestAggregator* aggregator() { return aggregator_.get(); }
-
- private:
- TestFrameSinkManagerImpl* frame_sink_manager_;
- FrameSinkId frame_sink_id_;
- std::unique_ptr<TestHitTestAggregator> aggregator_;
-
- DISALLOW_COPY_AND_ASSIGN(TestGpuRootCompositorFrameSink);
-};
-
+// TODO(riajiang): TestHostFrameSinkManager should be based on
+// mojom::FrameSinkManagerClient instead.
class TestHostFrameSinkManager : public HostFrameSinkManager {
public:
TestHostFrameSinkManager() = default;
@@ -172,7 +86,7 @@ class TestFrameSinkManagerImpl : public FrameSinkManagerImpl {
mojo::ScopedSharedBufferHandle active_handle,
uint32_t active_handle_size,
mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_size) {
+ uint32_t idle_handle_size) override {
// Do not check if it's on valid thread for tests.
if (host_client_) {
host_client_->OnAggregatedHitTestRegionListUpdated(
@@ -181,8 +95,9 @@ class TestFrameSinkManagerImpl : public FrameSinkManagerImpl {
}
}
- void SwitchActiveAggregatedHitTestRegionList(const FrameSinkId& frame_sink_id,
- uint8_t active_handle_index) {
+ void SwitchActiveAggregatedHitTestRegionList(
+ const FrameSinkId& frame_sink_id,
+ uint8_t active_handle_index) override {
// Do not check if it's on valid thread for tests.
if (host_client_) {
host_client_->SwitchActiveAggregatedHitTestRegionList(
@@ -190,51 +105,49 @@ class TestFrameSinkManagerImpl : public FrameSinkManagerImpl {
}
}
- void CreateRootCompositorFrameSinkLocal(TestHitTestManager* hit_test_manager,
- const FrameSinkId& frame_sink_id) {
- compositor_frame_sinks_[frame_sink_id] =
- std::make_unique<TestGpuRootCompositorFrameSink>(hit_test_manager, this,
- frame_sink_id);
- }
-
- const std::map<FrameSinkId, std::unique_ptr<TestGpuRootCompositorFrameSink>>&
- compositor_frame_sinks() {
- return compositor_frame_sinks_;
- }
-
- uint64_t GetActiveFrameIndex(const SurfaceId& surface_id) override {
- return 0;
- }
-
private:
- std::map<FrameSinkId, std::unique_ptr<TestGpuRootCompositorFrameSink>>
- compositor_frame_sinks_;
TestHostFrameSinkManager* host_client_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(TestFrameSinkManagerImpl);
};
-void TestGpuRootCompositorFrameSink::OnAggregatedHitTestRegionListUpdated(
- mojo::ScopedSharedBufferHandle active_handle,
- uint32_t active_handle_size,
- mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_size) {
- frame_sink_manager_->OnAggregatedHitTestRegionListUpdated(
- frame_sink_id_, std::move(active_handle), active_handle_size,
- std::move(idle_handle), idle_handle_size);
-}
+} // namespace
-void TestGpuRootCompositorFrameSink::SwitchActiveAggregatedHitTestRegionList(
- uint8_t active_handle_index) {
- frame_sink_manager_->SwitchActiveAggregatedHitTestRegionList(
- frame_sink_id_, active_handle_index);
-}
+class TestHitTestAggregator final : public HitTestAggregator {
+ public:
+ TestHitTestAggregator(const HitTestManager* manager,
+ HitTestAggregatorDelegate* delegate,
+ const FrameSinkId& frame_sink_id)
+ : HitTestAggregator(manager, delegate, frame_sink_id),
+ frame_sink_id_(frame_sink_id) {}
+ ~TestHitTestAggregator() = default;
-} // namespace
+ int GetRegionCount() const {
+ AggregatedHitTestRegion* start =
+ static_cast<AggregatedHitTestRegion*>(read_buffer_.get());
+ AggregatedHitTestRegion* end = start;
+ while (end->child_count != kEndOfList)
+ end++;
+ return end - start;
+ }
+ int GetHitTestRegionListSize() { return read_size_; }
+ void SwapHandles() {
+ delegate_->SwitchActiveAggregatedHitTestRegionList(frame_sink_id_,
+ active_handle_index_);
+ }
-TestHitTestManager::TestHitTestManager(
- TestFrameSinkManagerImpl* frame_sink_manager)
- : HitTestManager(frame_sink_manager) {}
+ void Reset() {
+ AggregatedHitTestRegion* regions =
+ static_cast<AggregatedHitTestRegion*>(write_buffer_.get());
+ regions[0].child_count = kEndOfList;
+
+ regions = static_cast<AggregatedHitTestRegion*>(read_buffer_.get());
+ regions[0].child_count = kEndOfList;
+ }
+
+ private:
+ const FrameSinkId frame_sink_id_;
+};
class HitTestAggregatorTest : public testing::Test {
public:
@@ -245,24 +158,26 @@ class HitTestAggregatorTest : public testing::Test {
void SetUp() override {
frame_sink_manager_ = std::make_unique<TestFrameSinkManagerImpl>();
host_frame_sink_manager_ = std::make_unique<TestHostFrameSinkManager>();
- hit_test_manager_ =
- std::make_unique<TestHitTestManager>(frame_sink_manager_.get());
frame_sink_manager_->SetLocalClient(host_frame_sink_manager_.get());
- frame_sink_manager_->CreateRootCompositorFrameSinkLocal(
- hit_test_manager_.get(), kDisplayFrameSink);
+ support_ = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr /* client */, frame_sink_manager_.get(), kDisplayFrameSink,
+ true /* is_root */, false /* needs_sync_points */);
+ hit_test_aggregator_ = std::make_unique<TestHitTestAggregator>(
+ hit_test_manager(), frame_sink_manager(), kDisplayFrameSink);
}
void TearDown() override {
+ support_.reset();
frame_sink_manager_.reset();
host_frame_sink_manager_.reset();
- hit_test_manager_.reset();
}
// Creates a hit test data element with 8 children recursively to
// the specified depth. SurfaceIds are generated in sequential order and
// the method returns the next unused id.
- int CreateAndSubmitHitTestRegionListWith8Children(int id, int depth) {
- SurfaceId surface_id = MakeSurfaceId(kDisplayFrameSink, id);
- id++;
+ int CreateAndSubmitHitTestRegionListWith8Children(uint32_t client_id,
+ int depth) {
+ SurfaceId surface_id = MakeSurfaceId(client_id);
+ client_id++;
auto hit_test_region_list = mojom::HitTestRegionList::New();
hit_test_region_list->flags = mojom::kHitTestMine;
@@ -271,30 +186,38 @@ class HitTestAggregatorTest : public testing::Test {
for (int i = 0; i < 8; i++) {
auto hit_test_region = mojom::HitTestRegion::New();
hit_test_region->rect.SetRect(100, 100, 100, 100);
- SurfaceId child_surface_id = MakeSurfaceId(kDisplayFrameSink, id);
+ SurfaceId child_surface_id = MakeSurfaceId(client_id);
hit_test_region->frame_sink_id = child_surface_id.frame_sink_id();
hit_test_region->local_surface_id = child_surface_id.local_surface_id();
if (depth > 0) {
hit_test_region->flags = mojom::kHitTestChildSurface;
- id = CreateAndSubmitHitTestRegionListWith8Children(id, depth - 1);
+ client_id =
+ CreateAndSubmitHitTestRegionListWith8Children(client_id, depth - 1);
} else {
hit_test_region->flags = mojom::kHitTestMine;
}
hit_test_region_list->regions.push_back(std::move(hit_test_region));
}
- hit_test_manager()->SubmitHitTestRegionList(
- surface_id, 0, std::move(hit_test_region_list));
- return id;
+ if (surface_id.frame_sink_id() == kDisplayFrameSink) {
+ support()->SubmitCompositorFrame(surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(hit_test_region_list));
+ } else {
+ auto support = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, frame_sink_manager(), surface_id.frame_sink_id(),
+ false /* is_root */, false /* needs_sync_points */);
+ support->SubmitCompositorFrame(surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(hit_test_region_list));
+ }
+ return client_id;
}
protected:
- TestHitTestAggregator* GetAggregator(const FrameSinkId& frame_sink_id) {
- DCHECK(frame_sink_manager_->compositor_frame_sinks().count(frame_sink_id));
- return frame_sink_manager_->compositor_frame_sinks()
- .at(frame_sink_id)
- ->aggregator();
+ TestHitTestAggregator* hit_test_aggregator() {
+ return hit_test_aggregator_.get();
}
AggregatedHitTestRegion* host_regions() {
@@ -305,12 +228,25 @@ class HitTestAggregatorTest : public testing::Test {
return host_frame_sink_manager_->buffer_frame_sink_id();
}
- TestHitTestManager* hit_test_manager() { return hit_test_manager_.get(); }
+ const HitTestManager* hit_test_manager() const {
+ return frame_sink_manager_->hit_test_manager();
+ }
+
+ CompositorFrameSinkSupport* support() const { return support_.get(); }
+
+ FrameSinkManagerImpl* frame_sink_manager() const {
+ return frame_sink_manager_.get();
+ }
+
+ SurfaceManager* surface_manager() const {
+ return frame_sink_manager_->surface_manager();
+ }
private:
- std::unique_ptr<TestHitTestManager> hit_test_manager_;
+ std::unique_ptr<TestHitTestAggregator> hit_test_aggregator_;
std::unique_ptr<TestFrameSinkManagerImpl> frame_sink_manager_;
std::unique_ptr<TestHostFrameSinkManager> host_frame_sink_manager_;
+ std::unique_ptr<CompositorFrameSinkSupport> support_;
DISALLOW_COPY_AND_ASSIGN(HitTestAggregatorTest);
};
@@ -327,17 +263,18 @@ class HitTestAggregatorTest : public testing::Test {
// +----------+
//
TEST_F(HitTestAggregatorTest, OneSurface) {
- TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
+ TestHitTestAggregator* aggregator = hit_test_aggregator();
EXPECT_EQ(aggregator->GetRegionCount(), 0);
- SurfaceId display_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
+ SurfaceId display_surface_id = MakeSurfaceId(kDisplayClientId);
auto hit_test_region_list = mojom::HitTestRegionList::New();
hit_test_region_list->flags = mojom::kHitTestMine;
hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
- hit_test_manager()->SubmitHitTestRegionList(display_surface_id, 0,
- std::move(hit_test_region_list));
+ support()->SubmitCompositorFrame(display_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(hit_test_region_list));
aggregator->Aggregate(display_surface_id);
aggregator->SwapHandles();
@@ -366,10 +303,10 @@ TEST_F(HitTestAggregatorTest, OneSurface) {
// +--------------+
//
TEST_F(HitTestAggregatorTest, OneEmbedderTwoRegions) {
- TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
+ TestHitTestAggregator* aggregator = hit_test_aggregator();
EXPECT_EQ(aggregator->GetRegionCount(), 0);
- SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
+ SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
auto e_hit_test_region_list = mojom::HitTestRegionList::New();
e_hit_test_region_list->flags = mojom::kHitTestMine;
@@ -390,10 +327,9 @@ TEST_F(HitTestAggregatorTest, OneEmbedderTwoRegions) {
e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_r1));
e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_r2));
- // Submit in unexpected order.
-
- hit_test_manager()->SubmitHitTestRegionList(
- e_surface_id, 0, std::move(e_hit_test_region_list));
+ support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(e_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
aggregator->SwapHandles();
@@ -433,12 +369,12 @@ TEST_F(HitTestAggregatorTest, OneEmbedderTwoRegions) {
//
TEST_F(HitTestAggregatorTest, OneEmbedderTwoChildren) {
- TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
+ TestHitTestAggregator* aggregator = hit_test_aggregator();
EXPECT_EQ(aggregator->GetRegionCount(), 0);
- SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
- SurfaceId c1_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
- SurfaceId c2_surface_id = MakeSurfaceId(kDisplayFrameSink, 3);
+ SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
+ SurfaceId c1_surface_id = MakeSurfaceId(kDisplayClientId + 1);
+ SurfaceId c2_surface_id = MakeSurfaceId(kDisplayClientId + 2);
auto e_hit_test_region_list = mojom::HitTestRegionList::New();
e_hit_test_region_list->flags = mojom::kHitTestMine;
@@ -465,12 +401,21 @@ TEST_F(HitTestAggregatorTest, OneEmbedderTwoChildren) {
// Submit in unexpected order.
- hit_test_manager()->SubmitHitTestRegionList(
- c1_surface_id, 0, std::move(c1_hit_test_region_list));
- hit_test_manager()->SubmitHitTestRegionList(
- e_surface_id, 0, std::move(e_hit_test_region_list));
- hit_test_manager()->SubmitHitTestRegionList(
- c2_surface_id, 0, std::move(c2_hit_test_region_list));
+ auto support2 = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, frame_sink_manager(), c1_surface_id.frame_sink_id(),
+ false /* is_root */, false /* needs_sync_points */);
+ support2->SubmitCompositorFrame(c1_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(c1_hit_test_region_list));
+ support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(e_hit_test_region_list));
+ auto support3 = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, frame_sink_manager(), c2_surface_id.frame_sink_id(),
+ false /* is_root */, false /* needs_sync_points */);
+ support3->SubmitCompositorFrame(c2_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(c2_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
aggregator->SwapHandles();
@@ -513,11 +458,11 @@ TEST_F(HitTestAggregatorTest, OneEmbedderTwoChildren) {
//
TEST_F(HitTestAggregatorTest, OccludedChildFrame) {
- TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
+ TestHitTestAggregator* aggregator = hit_test_aggregator();
EXPECT_EQ(aggregator->GetRegionCount(), 0);
- SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
- SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
+ SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
+ SurfaceId c_surface_id = MakeSurfaceId(kDisplayClientId + 1);
auto e_hit_test_region_list = mojom::HitTestRegionList::New();
e_hit_test_region_list->flags = mojom::kHitTestMine;
@@ -543,11 +488,15 @@ TEST_F(HitTestAggregatorTest, OccludedChildFrame) {
c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500);
// Submit in unexpected order.
-
- hit_test_manager()->SubmitHitTestRegionList(
- c_surface_id, 0, std::move(c_hit_test_region_list));
- hit_test_manager()->SubmitHitTestRegionList(
- e_surface_id, 0, std::move(e_hit_test_region_list));
+ auto support2 = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, frame_sink_manager(), c_surface_id.frame_sink_id(),
+ false /* is_root */, false /* needs_sync_points */);
+ support2->SubmitCompositorFrame(c_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(c_hit_test_region_list));
+ support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(e_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
aggregator->SwapHandles();
@@ -591,11 +540,11 @@ TEST_F(HitTestAggregatorTest, OccludedChildFrame) {
//
TEST_F(HitTestAggregatorTest, ForegroundChildFrame) {
- TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
+ TestHitTestAggregator* aggregator = hit_test_aggregator();
EXPECT_EQ(aggregator->GetRegionCount(), 0);
- SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
- SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
+ SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
+ SurfaceId c_surface_id = MakeSurfaceId(kDisplayClientId + 1);
auto e_hit_test_region_list = mojom::HitTestRegionList::New();
e_hit_test_region_list->flags = mojom::kHitTestMine;
@@ -622,10 +571,15 @@ TEST_F(HitTestAggregatorTest, ForegroundChildFrame) {
// Submit in unexpected order.
- hit_test_manager()->SubmitHitTestRegionList(
- c_surface_id, 0, std::move(c_hit_test_region_list));
- hit_test_manager()->SubmitHitTestRegionList(
- e_surface_id, 0, std::move(e_hit_test_region_list));
+ auto support2 = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, frame_sink_manager(), c_surface_id.frame_sink_id(),
+ false /* is_root */, false /* needs_sync_points */);
+ support2->SubmitCompositorFrame(c_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(c_hit_test_region_list));
+ support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(e_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
aggregator->SwapHandles();
@@ -669,13 +623,13 @@ TEST_F(HitTestAggregatorTest, ForegroundChildFrame) {
//
TEST_F(HitTestAggregatorTest, ClippedChildWithTabAndTransparentBackground) {
- TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
+ TestHitTestAggregator* aggregator = hit_test_aggregator();
EXPECT_EQ(aggregator->GetRegionCount(), 0);
- SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
- SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
- SurfaceId a_surface_id = MakeSurfaceId(kDisplayFrameSink, 3);
- SurfaceId b_surface_id = MakeSurfaceId(kDisplayFrameSink, 4);
+ SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
+ SurfaceId c_surface_id = MakeSurfaceId(kDisplayClientId + 1);
+ SurfaceId a_surface_id = MakeSurfaceId(kDisplayClientId + 2);
+ SurfaceId b_surface_id = MakeSurfaceId(kDisplayClientId + 3);
auto e_hit_test_region_list = mojom::HitTestRegionList::New();
e_hit_test_region_list->flags = mojom::kHitTestMine;
@@ -719,14 +673,27 @@ TEST_F(HitTestAggregatorTest, ClippedChildWithTabAndTransparentBackground) {
// Submit in unexpected order.
- hit_test_manager()->SubmitHitTestRegionList(
- c_surface_id, 0, std::move(c_hit_test_region_list));
- hit_test_manager()->SubmitHitTestRegionList(
- a_surface_id, 0, std::move(a_hit_test_region_list));
- hit_test_manager()->SubmitHitTestRegionList(
- b_surface_id, 0, std::move(b_hit_test_region_list));
- hit_test_manager()->SubmitHitTestRegionList(
- e_surface_id, 0, std::move(e_hit_test_region_list));
+ auto support2 = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, frame_sink_manager(), c_surface_id.frame_sink_id(),
+ false /* is_root */, false /* needs_sync_points */);
+ support2->SubmitCompositorFrame(c_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(c_hit_test_region_list));
+ auto support3 = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, frame_sink_manager(), a_surface_id.frame_sink_id(),
+ false /* is_root */, false /* needs_sync_points */);
+ support3->SubmitCompositorFrame(a_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(a_hit_test_region_list));
+ auto support4 = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, frame_sink_manager(), b_surface_id.frame_sink_id(),
+ false /* is_root */, false /* needs_sync_points */);
+ support4->SubmitCompositorFrame(b_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(b_hit_test_region_list));
+ support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(e_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
aggregator->SwapHandles();
@@ -782,13 +749,13 @@ TEST_F(HitTestAggregatorTest, ClippedChildWithTabAndTransparentBackground) {
//
TEST_F(HitTestAggregatorTest, ThreeChildrenDeep) {
- TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
+ TestHitTestAggregator* aggregator = hit_test_aggregator();
EXPECT_EQ(aggregator->GetRegionCount(), 0);
- SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
- SurfaceId c1_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
- SurfaceId c2_surface_id = MakeSurfaceId(kDisplayFrameSink, 3);
- SurfaceId c3_surface_id = MakeSurfaceId(kDisplayFrameSink, 4);
+ SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
+ SurfaceId c1_surface_id = MakeSurfaceId(kDisplayClientId + 1);
+ SurfaceId c2_surface_id = MakeSurfaceId(kDisplayClientId + 2);
+ SurfaceId c3_surface_id = MakeSurfaceId(kDisplayClientId + 3);
auto e_hit_test_region_list = mojom::HitTestRegionList::New();
e_hit_test_region_list->flags = mojom::kHitTestMine;
@@ -832,14 +799,27 @@ TEST_F(HitTestAggregatorTest, ThreeChildrenDeep) {
// Submit in unexpected order.
- hit_test_manager()->SubmitHitTestRegionList(
- c1_surface_id, 0, std::move(c1_hit_test_region_list));
- hit_test_manager()->SubmitHitTestRegionList(
- c3_surface_id, 0, std::move(c3_hit_test_region_list));
- hit_test_manager()->SubmitHitTestRegionList(
- e_surface_id, 0, std::move(e_hit_test_region_list));
- hit_test_manager()->SubmitHitTestRegionList(
- c2_surface_id, 0, std::move(c2_hit_test_region_list));
+ auto support2 = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, frame_sink_manager(), c1_surface_id.frame_sink_id(),
+ false /* is_root */, false /* needs_sync_points */);
+ support2->SubmitCompositorFrame(c1_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(c1_hit_test_region_list));
+ auto support3 = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, frame_sink_manager(), c3_surface_id.frame_sink_id(),
+ false /* is_root */, false /* needs_sync_points */);
+ support3->SubmitCompositorFrame(c3_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(c3_hit_test_region_list));
+ support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(e_hit_test_region_list));
+ auto support4 = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, frame_sink_manager(), c2_surface_id.frame_sink_id(),
+ false /* is_root */, false /* needs_sync_points */);
+ support4->SubmitCompositorFrame(c2_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(c2_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
aggregator->SwapHandles();
@@ -888,11 +868,11 @@ TEST_F(HitTestAggregatorTest, ThreeChildrenDeep) {
//
TEST_F(HitTestAggregatorTest, MissingChildFrame) {
- TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
+ TestHitTestAggregator* aggregator = hit_test_aggregator();
EXPECT_EQ(aggregator->GetRegionCount(), 0);
- SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
- SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
+ SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
+ SurfaceId c_surface_id = MakeSurfaceId(kDisplayClientId + 1);
auto e_hit_test_region_list = mojom::HitTestRegionList::New();
e_hit_test_region_list->flags = mojom::kHitTestMine;
@@ -919,8 +899,9 @@ TEST_F(HitTestAggregatorTest, MissingChildFrame) {
// Submit in unexpected order.
- hit_test_manager()->SubmitHitTestRegionList(
- e_surface_id, 0, std::move(e_hit_test_region_list));
+ support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(e_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
aggregator->SwapHandles();
@@ -975,14 +956,14 @@ TEST_F(HitTestAggregatorTest, MissingChildFrame) {
//
TEST_F(HitTestAggregatorTest, ExceedLimits) {
- TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
+ TestHitTestAggregator* aggregator = hit_test_aggregator();
EXPECT_EQ(aggregator->GetRegionCount(), 0);
EXPECT_LT(aggregator->GetHitTestRegionListSize(), 4096);
- SurfaceId display_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
+ SurfaceId display_surface_id = MakeSurfaceId(kDisplayClientId);
- CreateAndSubmitHitTestRegionListWith8Children(1, 3);
+ CreateAndSubmitHitTestRegionListWith8Children(kDisplayClientId, 3);
aggregator->Aggregate(display_surface_id);
aggregator->SwapHandles();
@@ -1007,11 +988,10 @@ TEST_F(HitTestAggregatorTest, ExceedLimits) {
}
TEST_F(HitTestAggregatorTest, DiscardedSurfaces) {
- TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
- EXPECT_EQ(hit_test_manager()->GetRegionCount(), 0);
+ TestHitTestAggregator* aggregator = hit_test_aggregator();
- SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
- SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
+ SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
+ SurfaceId c_surface_id = MakeSurfaceId(kDisplayClientId + 1);
auto e_hit_test_region_list = mojom::HitTestRegionList::New();
e_hit_test_region_list->flags = mojom::kHitTestMine;
@@ -1036,27 +1016,37 @@ TEST_F(HitTestAggregatorTest, DiscardedSurfaces) {
c_hit_test_region_list->flags = mojom::kHitTestMine;
c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500);
- EXPECT_EQ(hit_test_manager()->GetRegionCount(), 0);
+ EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(e_surface_id));
+ EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(c_surface_id));
// Submit in unexpected order.
- hit_test_manager()->SubmitHitTestRegionList(
- c_surface_id, 0, std::move(c_hit_test_region_list));
- hit_test_manager()->SubmitHitTestRegionList(
- e_surface_id, 0, std::move(e_hit_test_region_list));
+ auto support2 = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, frame_sink_manager(), c_surface_id.frame_sink_id(),
+ false /* is_root */, false /* needs_sync_points */);
+ support2->SubmitCompositorFrame(c_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(c_hit_test_region_list));
+ support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
+ MakeDefaultCompositorFrame(),
+ std::move(e_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
aggregator->SwapHandles();
- EXPECT_EQ(hit_test_manager()->GetRegionCount(), 2);
+ EXPECT_TRUE(hit_test_manager()->GetActiveHitTestRegionList(e_surface_id));
+ EXPECT_TRUE(hit_test_manager()->GetActiveHitTestRegionList(c_surface_id));
// Discard Surface and ensure active count goes down.
-
- hit_test_manager()->CallOnSurfaceDiscarded(c_surface_id);
- EXPECT_EQ(hit_test_manager()->GetRegionCount(), 1);
-
- hit_test_manager()->CallOnSurfaceDiscarded(e_surface_id);
- EXPECT_EQ(hit_test_manager()->GetRegionCount(), 0);
+ support2->EvictLastActivatedSurface();
+ surface_manager()->GarbageCollectSurfaces();
+ EXPECT_TRUE(hit_test_manager()->GetActiveHitTestRegionList(e_surface_id));
+ EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(c_surface_id));
+
+ support()->EvictLastActivatedSurface();
+ surface_manager()->GarbageCollectSurfaces();
+ EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(e_surface_id));
+ EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(c_surface_id));
}
} // namespace viz
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 e661659dca0..86f562baf69 100644
--- a/chromium/components/viz/service/hit_test/hit_test_manager.cc
+++ b/chromium/components/viz/service/hit_test/hit_test_manager.cc
@@ -5,7 +5,6 @@
#include "components/viz/service/hit_test/hit_test_aggregator.h"
#include "components/viz/common/hit_test/aggregated_hit_test_region.h"
-#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/hit_test/hit_test_aggregator_delegate.h"
namespace viz {
@@ -16,8 +15,8 @@ namespace {
constexpr uint32_t kMaxRegionsPerSurface = 1024;
} // namespace
-HitTestManager::HitTestManager(FrameSinkManagerImpl* frame_sink_manager)
- : frame_sink_manager_(frame_sink_manager) {}
+HitTestManager::HitTestManager(SurfaceManager* surface_manager)
+ : surface_manager_(surface_manager) {}
HitTestManager::~HitTestManager() = default;
@@ -80,14 +79,18 @@ void HitTestManager::OnSurfaceDiscarded(const SurfaceId& surface_id) {
hit_test_region_lists_.erase(surface_id);
}
-void HitTestManager::OnSurfaceActivated(const SurfaceId& surface_id) {
+void HitTestManager::OnSurfaceActivated(
+ const SurfaceId& surface_id,
+ base::Optional<base::TimeDelta> duration) {
// When a Surface is activated we can confidently remove all
// associated HitTestRegionList objects with an older frame_index.
auto search = hit_test_region_lists_.find(surface_id);
if (search == hit_test_region_lists_.end())
return;
- uint64_t frame_index = frame_sink_manager_->GetActiveFrameIndex(surface_id);
+ Surface* surface = surface_manager_->GetSurfaceForId(surface_id);
+ DCHECK(surface);
+ uint64_t frame_index = surface->GetActiveFrameIndex();
auto& frame_index_map = search->second;
for (auto it = frame_index_map.begin(); it != frame_index_map.end();) {
@@ -104,7 +107,9 @@ const mojom::HitTestRegionList* HitTestManager::GetActiveHitTestRegionList(
if (search == hit_test_region_lists_.end())
return nullptr;
- uint64_t frame_index = frame_sink_manager_->GetActiveFrameIndex(surface_id);
+ Surface* surface = surface_manager_->GetSurfaceForId(surface_id);
+ DCHECK(surface);
+ uint64_t frame_index = surface->GetActiveFrameIndex();
auto& frame_index_map = search->second;
auto search2 = frame_index_map.find(frame_index);
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 82965db5f99..dc5ba7fb46f 100644
--- a/chromium/components/viz/service/hit_test/hit_test_manager.h
+++ b/chromium/components/viz/service/hit_test/hit_test_manager.h
@@ -14,14 +14,12 @@
namespace viz {
-class FrameSinkManagerImpl;
-
// HitTestManager manages the collection of HitTestRegionList objects
// submitted in calls to SubmitCompositorFrame. This collection is
// used by HitTestAggregator.
class VIZ_SERVICE_EXPORT HitTestManager : public SurfaceObserver {
public:
- explicit HitTestManager(FrameSinkManagerImpl* frame_sink_manager);
+ explicit HitTestManager(SurfaceManager* surface_manager);
virtual ~HitTestManager();
// Called when HitTestRegionList is submitted along with every call
@@ -39,7 +37,8 @@ class VIZ_SERVICE_EXPORT HitTestManager : public SurfaceObserver {
// SurfaceObserver:
void OnSurfaceCreated(const SurfaceId& surface_id) override {}
void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override {}
- void OnSurfaceActivated(const SurfaceId& surface_id) override;
+ void OnSurfaceActivated(const SurfaceId& surface_id,
+ base::Optional<base::TimeDelta> duration) override;
void OnSurfaceDestroyed(const SurfaceId& surface_id) override {}
bool OnSurfaceDamaged(const SurfaceId& surface_id,
const BeginFrameAck& ack) override;
@@ -48,15 +47,13 @@ class VIZ_SERVICE_EXPORT HitTestManager : public SurfaceObserver {
const BeginFrameArgs& args) override {}
private:
- friend class TestHitTestManager;
-
bool ValidateHitTestRegionList(
const SurfaceId& surface_id,
const mojom::HitTestRegionListPtr& hit_test_region_list);
bool ValidateHitTestRegion(const SurfaceId& surface_id,
const mojom::HitTestRegionPtr& hit_test_region);
- FrameSinkManagerImpl* const frame_sink_manager_;
+ SurfaceManager* const surface_manager_;
std::map<SurfaceId, base::flat_map<uint64_t, mojom::HitTestRegionListPtr>>
hit_test_region_lists_;
diff --git a/chromium/components/viz/service/main/BUILD.gn b/chromium/components/viz/service/main/BUILD.gn
index 3c29166b00b..43ac3d9168e 100644
--- a/chromium/components/viz/service/main/BUILD.gn
+++ b/chromium/components/viz/service/main/BUILD.gn
@@ -17,6 +17,8 @@ source_set("main") {
deps = [
"//cc",
+ "//components/discardable_memory/client",
+ "//components/discardable_memory/public/interfaces",
"//components/viz/service",
"//gpu/ipc:gl_in_process_context",
"//gpu/ipc/common",
@@ -25,7 +27,7 @@ source_set("main") {
"//ipc",
"//mojo/public/cpp/system",
"//services/metrics/public/cpp:metrics_cpp",
- "//services/metrics/public/interfaces",
+ "//services/metrics/public/mojom",
"//services/service_manager/public/cpp",
"//services/viz/privileged/interfaces",
"//ui/gfx:memory_buffer",
diff --git a/chromium/components/viz/service/main/DEPS b/chromium/components/viz/service/main/DEPS
index db0cb4b0337..0b4f0cfe749 100644
--- a/chromium/components/viz/service/main/DEPS
+++ b/chromium/components/viz/service/main/DEPS
@@ -1,4 +1,7 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
include_rules = [
+ "+components/discardable_memory/client",
"+components/viz/service",
"+gpu/command_buffer",
"+gpu/config",
diff --git a/chromium/components/viz/service/main/viz_main_impl.cc b/chromium/components/viz/service/main/viz_main_impl.cc
index 9066f834277..973e9867647 100644
--- a/chromium/components/viz/service/main/viz_main_impl.cc
+++ b/chromium/components/viz/service/main/viz_main_impl.cc
@@ -5,6 +5,7 @@
#include "components/viz/service/main/viz_main_impl.h"
#include <memory>
+#include <utility>
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
@@ -26,17 +27,22 @@
#include "media/gpu/features.h"
#include "services/metrics/public/cpp/delegating_ukm_recorder.h"
#include "services/metrics/public/cpp/mojo_ukm_recorder.h"
-#include "services/metrics/public/interfaces/constants.mojom.h"
+#include "services/metrics/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#if defined(OS_CHROMEOS) && BUILDFLAG(USE_VAAPI)
#include "media/gpu/vaapi/vaapi_wrapper.h"
#endif
+#if defined(USE_OZONE)
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/ozone_switches.h"
+#endif
+
namespace {
std::unique_ptr<base::Thread> CreateAndStartCompositorThread() {
- auto thread = std::make_unique<base::Thread>("CompositorThread");
+ auto thread = std::make_unique<base::Thread>("VizCompositorThread");
base::Thread::Options thread_options;
thread_options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
@@ -86,7 +92,7 @@ VizMainImpl::VizMainImpl(Delegate* delegate,
associated_binding_(this) {
// TODO(crbug.com/609317): Remove this when Mus Window Server and GPU are
// split into separate processes. Until then this is necessary to be able to
- // run Mushrome (chrome --mus) with Mus running in the browser process.
+ // run Mushrome (chrome with mus) with Mus running in the browser process.
if (!base::PowerMonitor::Get()) {
power_monitor_ = std::make_unique<base::PowerMonitor>(
std::make_unique<base::PowerMonitorDeviceSource>());
@@ -112,6 +118,11 @@ VizMainImpl::VizMainImpl(Delegate* delegate,
// Initialize GpuInit before starting the IO or compositor threads.
gpu_init_ = std::make_unique<gpu::GpuInit>();
gpu_init_->set_sandbox_helper(this);
+
+#if defined(USE_OZONE)
+ command_line->AppendSwitch(switches::kEnableDrmMojo);
+#endif
+
// TODO(crbug.com/609317): Use InitializeAndStartSandbox() when gpu-mus is
// split into a separate process.
gpu_init_->InitializeInProcess(command_line, gpu_preferences);
@@ -127,18 +138,34 @@ VizMainImpl::VizMainImpl(Delegate* delegate,
CreateUkmRecorderIfNeeded(dependencies.connector);
gpu_service_ = std::make_unique<GpuServiceImpl>(
- gpu_init_->gpu_info(), gpu_init_->TakeWatchdogThread(),
- io_thread_ ? io_thread_->task_runner()
- : dependencies_.io_thread_task_runner,
+ gpu_init_->gpu_info(), gpu_init_->TakeWatchdogThread(), io_task_runner(),
gpu_init_->gpu_feature_info(), gpu_init_->gpu_preferences());
}
VizMainImpl::~VizMainImpl() {
DCHECK(gpu_thread_task_runner_->BelongsToCurrentThread());
+
+ // The compositor holds on to some resources from gpu service. So destroy the
+ // compositor first, before destroying the gpu service. However, before the
+ // compositor is destroyed, close the binding, so that the gpu service doesn't
+ // need to process commands from the host as it is shutting down.
+ binding_.Close();
+ associated_binding_.Close();
+
+ if (compositor_thread_) {
+ // Destroy all objects owned on the compositor thread before shutting down
+ // the thread. All RootCompositorFrameSinks must be destroyed before now,
+ // otherwise the compositor thread will deadlock waiting for a response from
+ // the blocked GPU thread.
+ compositor_thread_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&VizMainImpl::TearDownOnCompositorThread,
+ base::Unretained(this)));
+ compositor_thread_.reset();
+ compositor_thread_task_runner_ = nullptr;
+ }
+
if (ukm_recorder_)
ukm::DelegatingUkmRecorder::Get()->RemoveDelegate(ukm_recorder_.get());
- if (io_thread_)
- io_thread_->Stop();
}
void VizMainImpl::SetLogMessagesForHost(LogMessages log_messages) {
@@ -153,40 +180,11 @@ void VizMainImpl::BindAssociated(mojom::VizMainAssociatedRequest request) {
associated_binding_.Bind(std::move(request));
}
-void VizMainImpl::TearDown() {
- DCHECK(!gpu_thread_task_runner_->BelongsToCurrentThread());
- DCHECK(!compositor_thread_task_runner_->BelongsToCurrentThread());
- // The compositor holds on to some resources from gpu service. So destroy the
- // compositor first, before destroying the gpu service. However, before the
- // compositor is destroyed, close the binding, so that the gpu service doesn't
- // need to process commands from the compositor as it is shutting down.
- base::WaitableEvent binding_wait(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- gpu_thread_task_runner_->PostTask(
- FROM_HERE, base::Bind(&VizMainImpl::CloseVizMainBindingOnGpuThread,
- base::Unretained(this), &binding_wait));
- binding_wait.Wait();
-
- base::WaitableEvent compositor_wait(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- compositor_thread_task_runner_->PostTask(
- FROM_HERE, base::Bind(&VizMainImpl::TearDownOnCompositorThread,
- base::Unretained(this), &compositor_wait));
- compositor_wait.Wait();
-
- base::WaitableEvent gpu_wait(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- gpu_thread_task_runner_->PostTask(
- FROM_HERE, base::Bind(&VizMainImpl::TearDownOnGpuThread,
- base::Unretained(this), &gpu_wait));
- gpu_wait.Wait();
-}
-
void VizMainImpl::CreateGpuService(
mojom::GpuServiceRequest request,
mojom::GpuHostPtr gpu_host,
+ discardable_memory::mojom::DiscardableSharedMemoryManagerPtr
+ discardable_memory_manager,
mojo::ScopedSharedBufferHandle activity_flags) {
DCHECK(gpu_thread_task_runner_->BelongsToCurrentThread());
gpu_service_->UpdateGPUInfo();
@@ -202,6 +200,16 @@ void VizMainImpl::CreateGpuService(
return;
}
+ if (!gpu_init_->gpu_info().in_process_gpu) {
+ // If the GPU is running in the browser process, discardable memory manager
+ // has already been initialized.
+ discardable_shared_memory_manager_ = std::make_unique<
+ discardable_memory::ClientDiscardableSharedMemoryManager>(
+ std::move(discardable_memory_manager), io_task_runner());
+ base::DiscardableMemoryAllocator::SetInstance(
+ discardable_shared_memory_manager_.get());
+ }
+
gpu_service_->Bind(std::move(request));
gpu_service_->InitializeWithHost(
std::move(gpu_host),
@@ -246,15 +254,18 @@ void VizMainImpl::CreateFrameSinkManagerInternal(
DCHECK(!gpu_command_service_);
DCHECK(gpu_service_);
DCHECK(gpu_thread_task_runner_->BelongsToCurrentThread());
+
+ constexpr bool use_virtualized_gl_context = false;
gpu_command_service_ = base::MakeRefCounted<gpu::GpuInProcessThreadService>(
- gpu_thread_task_runner_, gpu_service_->sync_point_manager(),
- gpu_service_->mailbox_manager(), gpu_service_->share_group(),
- gpu_service_->gpu_feature_info());
+ use_virtualized_gl_context, gpu_thread_task_runner_,
+ gpu_service_->sync_point_manager(), gpu_service_->mailbox_manager(),
+ gpu_service_->share_group(), gpu_service_->gpu_feature_info(),
+ gpu_service_->gpu_channel_manager()->gpu_preferences());
compositor_thread_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&VizMainImpl::CreateFrameSinkManagerOnCompositorThread,
- base::Unretained(this), base::Passed(&params)));
+ base::BindOnce(&VizMainImpl::CreateFrameSinkManagerOnCompositorThread,
+ base::Unretained(this), std::move(params)));
}
void VizMainImpl::CreateFrameSinkManagerOnCompositorThread(
@@ -276,31 +287,19 @@ void VizMainImpl::CreateFrameSinkManagerOnCompositorThread(
mojom::FrameSinkManagerClientPtr client(
std::move(params->frame_sink_manager_client));
+ base::Optional<uint32_t> activation_deadline_in_frames;
+ if (params->use_activation_deadline)
+ activation_deadline_in_frames = params->activation_deadline_in_frames;
frame_sink_manager_ = std::make_unique<FrameSinkManagerImpl>(
- SurfaceManager::LifetimeType::REFERENCES,
- params->number_of_frames_to_activation_deadline, display_provider_.get());
+ activation_deadline_in_frames, display_provider_.get());
frame_sink_manager_->BindAndSetClient(std::move(params->frame_sink_manager),
nullptr, std::move(client));
}
-void VizMainImpl::CloseVizMainBindingOnGpuThread(base::WaitableEvent* wait) {
- binding_.Close();
- wait->Signal();
-}
-
-void VizMainImpl::TearDownOnCompositorThread(base::WaitableEvent* wait) {
+void VizMainImpl::TearDownOnCompositorThread() {
compositing_mode_reporter_.reset();
frame_sink_manager_.reset();
display_provider_.reset();
- wait->Signal();
-}
-
-void VizMainImpl::TearDownOnGpuThread(base::WaitableEvent* wait) {
- gpu_command_service_ = nullptr;
- gpu_service_.reset();
- gpu_memory_buffer_factory_.reset();
- gpu_init_.reset();
- wait->Signal();
}
void VizMainImpl::PreSandboxStartup() {
diff --git a/chromium/components/viz/service/main/viz_main_impl.h b/chromium/components/viz/service/main/viz_main_impl.h
index 43c1fc9afcf..c7823692f59 100644
--- a/chromium/components/viz/service/main/viz_main_impl.h
+++ b/chromium/components/viz/service/main/viz_main_impl.h
@@ -7,6 +7,7 @@
#include "base/power_monitor/power_monitor.h"
#include "base/threading/thread.h"
+#include "components/discardable_memory/client/client_discardable_shared_memory_manager.h"
#include "gpu/ipc/in_process_command_buffer.h"
#include "gpu/ipc/service/gpu_init.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
@@ -15,7 +16,6 @@
#include "services/viz/privileged/interfaces/viz_main.mojom.h"
namespace gpu {
-class GpuMemoryBufferFactory;
class SyncPointManager;
} // namespace gpu
@@ -71,6 +71,7 @@ class VizMainImpl : public gpu::GpuSandboxHelper, public mojom::VizMain {
VizMainImpl(Delegate* delegate,
ExternalDependencies dependencies,
std::unique_ptr<gpu::GpuInit> gpu_init = nullptr);
+ // Destruction must happen on the GPU thread.
~VizMainImpl() override;
void SetLogMessagesForHost(LogMessages messages);
@@ -78,16 +79,13 @@ class VizMainImpl : public gpu::GpuSandboxHelper, public mojom::VizMain {
void Bind(mojom::VizMainRequest request);
void BindAssociated(mojom::VizMainAssociatedRequest request);
- // Calling this from the gpu or compositor thread can lead to crash/deadlock.
- // So this must be called from a different thread.
- // TODO(crbug.com/609317): After the process split, we should revisit to make
- // this cleaner.
- void TearDown();
-
// mojom::VizMain implementation:
- void CreateGpuService(mojom::GpuServiceRequest request,
- mojom::GpuHostPtr gpu_host,
- mojo::ScopedSharedBufferHandle activity_flags) override;
+ void CreateGpuService(
+ mojom::GpuServiceRequest request,
+ mojom::GpuHostPtr gpu_host,
+ discardable_memory::mojom::DiscardableSharedMemoryManagerPtr
+ discardable_memory_manager,
+ mojo::ScopedSharedBufferHandle activity_flags) override;
void CreateFrameSinkManager(mojom::FrameSinkManagerParamsPtr params) override;
GpuServiceImpl* gpu_service() { return gpu_service_.get(); }
@@ -101,9 +99,7 @@ class VizMainImpl : public gpu::GpuSandboxHelper, public mojom::VizMain {
void CreateFrameSinkManagerOnCompositorThread(
mojom::FrameSinkManagerParamsPtr params);
- void CloseVizMainBindingOnGpuThread(base::WaitableEvent* wait);
- void TearDownOnCompositorThread(base::WaitableEvent* wait);
- void TearDownOnGpuThread(base::WaitableEvent* wait);
+ void TearDownOnCompositorThread();
// gpu::GpuSandboxHelper:
void PreSandboxStartup() override;
@@ -111,11 +107,18 @@ class VizMainImpl : public gpu::GpuSandboxHelper, public mojom::VizMain {
const gpu::GPUInfo* gpu_info,
const gpu::GpuPreferences& gpu_prefs) override;
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner() const {
+ return io_thread_ ? io_thread_->task_runner()
+ : dependencies_.io_thread_task_runner;
+ }
+
Delegate* const delegate_;
const ExternalDependencies dependencies_;
// The thread that handles IO events for Gpu (if one isn't already provided).
+ // |io_thread_| must be ordered above GPU service related variables so it's
+ // destroyed after they are.
std::unique_ptr<base::Thread> io_thread_;
LogMessages log_messages_;
@@ -136,8 +139,6 @@ class VizMainImpl : public gpu::GpuSandboxHelper, public mojom::VizMain {
std::unique_ptr<CompositingModeReporterImpl> compositing_mode_reporter_;
std::unique_ptr<DisplayProvider> display_provider_;
- std::unique_ptr<gpu::GpuMemoryBufferFactory> gpu_memory_buffer_factory_;
-
const scoped_refptr<base::SingleThreadTaskRunner> gpu_thread_task_runner_;
// The main thread for the display compositor.
@@ -149,6 +150,9 @@ class VizMainImpl : public gpu::GpuSandboxHelper, public mojom::VizMain {
mojo::Binding<mojom::VizMain> binding_;
mojo::AssociatedBinding<mojom::VizMain> associated_binding_;
+ std::unique_ptr<discardable_memory::ClientDiscardableSharedMemoryManager>
+ discardable_shared_memory_manager_;
+
DISALLOW_COPY_AND_ASSIGN(VizMainImpl);
};
diff --git a/chromium/components/viz/service/surfaces/DEPS b/chromium/components/viz/service/surfaces/DEPS
index d2568d7dd11..ee2455358ed 100644
--- a/chromium/components/viz/service/surfaces/DEPS
+++ b/chromium/components/viz/service/surfaces/DEPS
@@ -1,9 +1,4 @@
-include_rules = [
- "+components/viz/common",
- "+components/viz/service/display",
- "+components/viz/service/frame_sinks",
- "+mojo/public/cpp/bindings/struct_traits.h",
-]
+# Please consult components/viz/README.md about allowable dependencies.
specific_include_rules = {
".*_unittest\.cc": [
diff --git a/chromium/components/viz/service/surfaces/direct_surface_reference_factory.cc b/chromium/components/viz/service/surfaces/direct_surface_reference_factory.cc
deleted file mode 100644
index 1cde4a6b05c..00000000000
--- a/chromium/components/viz/service/surfaces/direct_surface_reference_factory.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/service/surfaces/direct_surface_reference_factory.h"
-
-#include <vector>
-
-#include "components/viz/service/surfaces/surface.h"
-
-namespace viz {
-
-DirectSurfaceReferenceFactory::DirectSurfaceReferenceFactory(
- base::WeakPtr<SurfaceManager> manager)
- : manager_(manager) {}
-
-DirectSurfaceReferenceFactory::~DirectSurfaceReferenceFactory() = default;
-void DirectSurfaceReferenceFactory::SatisfySequence(
- const SurfaceSequence& sequence) const {
- if (!manager_)
- return;
- manager_->SatisfySequence(sequence);
-}
-
-void DirectSurfaceReferenceFactory::RequireSequence(
- const SurfaceId& surface_id,
- const SurfaceSequence& sequence) const {
- manager_->RequireSequence(surface_id, sequence);
-}
-
-} // namespace viz
diff --git a/chromium/components/viz/service/surfaces/direct_surface_reference_factory.h b/chromium/components/viz/service/surfaces/direct_surface_reference_factory.h
deleted file mode 100644
index 13485785828..00000000000
--- a/chromium/components/viz/service/surfaces/direct_surface_reference_factory.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_SERVICE_SURFACES_DIRECT_SURFACE_REFERENCE_FACTORY_H_
-#define COMPONENTS_VIZ_SERVICE_SURFACES_DIRECT_SURFACE_REFERENCE_FACTORY_H_
-
-#include "base/compiler_specific.h"
-#include "components/viz/common/surfaces/sequence_surface_reference_factory.h"
-#include "components/viz/common/surfaces/surface_id.h"
-#include "components/viz/common/surfaces/surface_sequence.h"
-#include "components/viz/service/surfaces/surface_manager.h"
-#include "components/viz/service/viz_service_export.h"
-
-namespace viz {
-
-class SurfaceManager;
-
-// The surface reference factory that interacts directly with SurfaceManager.
-// You probably don't need to instantiate this class directly.
-// Use SurfaceManager::reference_factory() instead.
-class VIZ_SERVICE_EXPORT DirectSurfaceReferenceFactory final
- : public SequenceSurfaceReferenceFactory {
- public:
- explicit DirectSurfaceReferenceFactory(base::WeakPtr<SurfaceManager> manager);
-
- private:
- ~DirectSurfaceReferenceFactory() override;
-
- // SequenceSurfaceReferenceFactory implementation:
- void SatisfySequence(const SurfaceSequence& sequence) const override;
- void RequireSequence(const SurfaceId& surface_id,
- const SurfaceSequence& sequence) const override;
-
- base::WeakPtr<SurfaceManager> manager_;
-
- DISALLOW_COPY_AND_ASSIGN(DirectSurfaceReferenceFactory);
-};
-
-} // namespace viz
-
-#endif // COMPONENTS_VIZ_SERVICE_SURFACES_DIRECT_SURFACE_REFERENCE_FACTORY_H_
diff --git a/chromium/components/viz/service/surfaces/surface.cc b/chromium/components/viz/service/surfaces/surface.cc
index beccc683e77..770677e2896 100644
--- a/chromium/components/viz/service/surfaces/surface.cc
+++ b/chromium/components/viz/service/surfaces/surface.cc
@@ -10,6 +10,7 @@
#include <algorithm>
#include "base/stl_util.h"
+#include "base/time/tick_clock.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/common/resources/transferable_resource.h"
@@ -23,22 +24,29 @@ namespace viz {
Surface::Surface(const SurfaceInfo& surface_info,
SurfaceManager* surface_manager,
base::WeakPtr<SurfaceClient> surface_client,
- BeginFrameSource* begin_frame_source,
bool needs_sync_tokens)
: surface_info_(surface_info),
surface_manager_(surface_manager),
surface_client_(std::move(surface_client)),
- deadline_(this, begin_frame_source),
needs_sync_tokens_(needs_sync_tokens) {}
Surface::~Surface() {
ClearCopyRequests();
+
+ if (surface_client_)
+ surface_client_->OnSurfaceDiscarded(this);
surface_manager_->SurfaceDiscarded(this);
UnrefFrameResourcesAndRunCallbacks(std::move(pending_frame_data_));
UnrefFrameResourcesAndRunCallbacks(std::move(active_frame_data_));
- deadline_.Cancel();
+ if (deadline_)
+ deadline_->Cancel();
+}
+
+void Surface::SetDependencyDeadline(
+ std::unique_ptr<SurfaceDependencyDeadline> deadline) {
+ deadline_ = std::move(deadline);
}
void Surface::Reset(base::WeakPtr<SurfaceClient> client) {
@@ -52,17 +60,13 @@ void Surface::Reset(base::WeakPtr<SurfaceClient> client) {
active_frame_data_.reset();
}
-bool Surface::InheritActivationDeadlineFrom(
- const SurfaceDependencyDeadline& deadline) {
+bool Surface::InheritActivationDeadlineFrom(Surface* surface) {
TRACE_EVENT1("viz", "Surface::InheritActivationDeadlineFrom", "FrameSinkId",
surface_id().frame_sink_id().ToString());
- return deadline_.InheritFrom(deadline);
-}
+ if (!deadline_ || !surface->deadline_)
+ return false;
-void Surface::SetActivationDeadline(uint32_t number_of_frames_to_deadline) {
- TRACE_EVENT1("viz", "Surface::SetActivationDeadline", "FrameSinkId",
- surface_id().frame_sink_id().ToString());
- deadline_.Set(number_of_frames_to_deadline);
+ return deadline_->InheritFrom(*surface->deadline_);
}
void Surface::SetPreviousFrameSurface(Surface* surface) {
@@ -158,31 +162,31 @@ bool Surface::QueueFrame(
std::move(pending_frame_data_);
pending_frame_data_.reset();
- UpdateActivationDependencies(frame);
+ FrameDeadline deadline = UpdateActivationDependencies(frame);
// Receive and track the resources referenced from the CompositorFrame
// regardless of whether it's pending or active.
surface_client_->ReceiveFromChild(frame.resource_list);
- if (activation_dependencies_.empty()) {
+ if (activation_dependencies_.empty() ||
+ (deadline_ && !deadline.deadline_in_frames())) {
// If there are no blockers, then immediately activate the frame.
- ActivateFrame(FrameData(std::move(frame), frame_index, std::move(callback),
- aggregated_damage_callback,
- std::move(presented_callback)));
+ ActivateFrame(
+ FrameData(std::move(frame), frame_index, std::move(callback),
+ aggregated_damage_callback, std::move(presented_callback)),
+ base::nullopt);
} else {
pending_frame_data_ =
FrameData(std::move(frame), frame_index, std::move(callback),
aggregated_damage_callback, std::move(presented_callback));
RejectCompositorFramesToFallbackSurfaces();
- base::Optional<uint32_t> deadline_in_frames =
- GetPendingFrame().metadata.deadline_in_frames;
- if (deadline_in_frames)
- deadline_.Set(*deadline_in_frames);
-
- // Ask the surface manager to inform |this| when its dependencies are
- // resolved.
- surface_manager_->RequestSurfaceResolution(this);
+ // If the deadline is in the past, then we will activate immediately.
+ if (!deadline_ || deadline_->Set(deadline)) {
+ // Ask the SurfaceDependencyTracker to inform |this| when its dependencies
+ // are resolved.
+ surface_manager_->dependency_tracker()->RequestSurfaceResolution(this);
+ }
}
// Returns resources for the previous pending frame.
@@ -244,10 +248,11 @@ void Surface::NotifySurfaceIdAvailable(const SurfaceId& surface_id) {
DCHECK(frame_sink_id_dependencies_.empty());
// All blockers have been cleared. The surface can be activated now.
- ActivatePendingFrame();
+ ActivatePendingFrame(base::nullopt);
}
-void Surface::ActivatePendingFrameForDeadline() {
+void Surface::ActivatePendingFrameForDeadline(
+ base::Optional<base::TimeDelta> duration) {
if (!pending_frame_data_)
return;
@@ -256,7 +261,7 @@ void Surface::ActivatePendingFrameForDeadline() {
late_activation_dependencies_ = std::move(activation_dependencies_);
activation_dependencies_.clear();
frame_sink_id_dependencies_.clear();
- ActivatePendingFrame();
+ ActivatePendingFrame(duration);
}
Surface::FrameData::FrameData(
@@ -277,19 +282,27 @@ Surface::FrameData& Surface::FrameData::operator=(FrameData&& other) = default;
Surface::FrameData::~FrameData() = default;
-void Surface::ActivatePendingFrame() {
+void Surface::ActivatePendingFrame(base::Optional<base::TimeDelta> duration) {
DCHECK(pending_frame_data_);
FrameData frame_data = std::move(*pending_frame_data_);
pending_frame_data_.reset();
- ActivateFrame(std::move(frame_data));
+
+ DCHECK(!duration || !deadline_ || !deadline_->has_deadline());
+ if (!duration && deadline_)
+ duration = deadline_->Cancel();
+
+ ActivateFrame(std::move(frame_data), duration);
}
// A frame is activated if all its Surface ID dependences are active or a
-// deadline has hit and the frame was forcibly activated.
-void Surface::ActivateFrame(FrameData frame_data) {
+// deadline has hit and the frame was forcibly activated. |duration| is a
+// measure of the time the frame has spent waiting on dependencies to arrive.
+// If |duration| is base::nullopt, then that indicates that this frame was not
+// blocked on dependencies.
+void Surface::ActivateFrame(FrameData frame_data,
+ base::Optional<base::TimeDelta> duration) {
TRACE_EVENT1("viz", "Surface::ActivateFrame", "FrameSinkId",
surface_id().frame_sink_id().ToString());
- deadline_.Cancel();
// Save root pass copy requests.
std::vector<std::unique_ptr<CopyOutputRequest>> old_copy_requests;
@@ -311,19 +324,36 @@ void Surface::ActivateFrame(FrameData frame_data) {
UnrefFrameResourcesAndRunCallbacks(std::move(previous_frame_data));
+ // This should happen before calling SurfaceManager::FirstSurfaceActivation(),
+ // as that notifies observers which may have side effects for
+ // |surface_client_|. See https://crbug.com/821855.
+ if (surface_client_)
+ surface_client_->OnSurfaceActivated(this);
+
if (!seen_first_frame_activation_) {
seen_first_frame_activation_ = true;
surface_manager_->FirstSurfaceActivation(surface_info_);
}
- if (surface_client_)
- surface_client_->OnSurfaceActivated(this);
-
- surface_manager_->SurfaceActivated(this);
+ surface_manager_->SurfaceActivated(this, duration);
}
-void Surface::UpdateActivationDependencies(
+FrameDeadline Surface::UpdateActivationDependencies(
const CompositorFrame& current_frame) {
+ const base::Optional<uint32_t>& default_deadline =
+ surface_manager_->activation_deadline_in_frames();
+ FrameDeadline deadline = current_frame.metadata.deadline;
+
+ uint32_t deadline_in_frames = deadline.deadline_in_frames();
+ if (default_deadline && deadline.use_default_lower_bound_deadline())
+ deadline_in_frames = std::max(deadline_in_frames, *default_deadline);
+
+ deadline = FrameDeadline(deadline.frame_start_time(), deadline_in_frames,
+ deadline.frame_interval(),
+ false /* use_default_lower_bound_deadline */);
+
+ bool track_dependencies = !default_deadline || deadline_in_frames > 0;
+
base::flat_map<FrameSinkId, SequenceNumbers> new_frame_sink_id_dependencies;
base::flat_set<SurfaceId> new_activation_dependencies;
@@ -333,6 +363,10 @@ void Surface::UpdateActivationDependencies(
// If a activation dependency does not have a corresponding active frame in
// the display compositor, then it blocks this frame.
if (!dependency || !dependency->HasActiveFrame()) {
+ new_activation_dependencies.insert(surface_id);
+ if (!track_dependencies)
+ continue;
+
// Record the latest |parent_sequence_number| this surface is interested
// in observing for the provided FrameSinkId.
uint32_t& parent_sequence_number =
@@ -348,8 +382,6 @@ void Surface::UpdateActivationDependencies(
child_sequence_number =
std::max(child_sequence_number,
surface_id.local_surface_id().child_sequence_number());
-
- new_activation_dependencies.insert(surface_id);
}
}
@@ -358,8 +390,16 @@ void Surface::UpdateActivationDependencies(
// map.
ComputeChangeInDependencies(new_frame_sink_id_dependencies);
- activation_dependencies_ = std::move(new_activation_dependencies);
+ if (track_dependencies) {
+ activation_dependencies_ = std::move(new_activation_dependencies);
+ } else {
+ // If the deadline is zero, then all dependencies are late.
+ activation_dependencies_.clear();
+ late_activation_dependencies_ = std::move(new_activation_dependencies);
+ }
+
frame_sink_id_dependencies_ = std::move(new_frame_sink_id_dependencies);
+ return deadline;
}
void Surface::ComputeChangeInDependencies(
@@ -436,24 +476,10 @@ void Surface::NotifyAggregatedDamage(const gfx::Rect& damage_rect) {
surface_id().local_surface_id(), damage_rect, active_frame_data_->frame);
}
-void Surface::AddDestructionDependency(SurfaceSequence sequence) {
- destruction_dependencies_.push_back(sequence);
-}
-
-void Surface::SatisfyDestructionDependencies(
- base::flat_set<SurfaceSequence>* sequences,
- base::flat_map<FrameSinkId, std::string>* valid_frame_sink_ids) {
- base::EraseIf(destruction_dependencies_,
- [sequences, valid_frame_sink_ids](SurfaceSequence seq) {
- return (!!sequences->erase(seq) ||
- !valid_frame_sink_ids->count(seq.frame_sink_id));
- });
-}
-
-void Surface::OnDeadline() {
+void Surface::OnDeadline(base::TimeDelta duration) {
TRACE_EVENT1("viz", "Surface::OnDeadline", "FrameSinkId",
surface_id().frame_sink_id().ToString());
- ActivatePendingFrameForDeadline();
+ ActivatePendingFrameForDeadline(duration);
}
void Surface::UnrefFrameResourcesAndRunCallbacks(
diff --git a/chromium/components/viz/service/surfaces/surface.h b/chromium/components/viz/service/surfaces/surface.h
index 637aa862450..e65ccb4a451 100644
--- a/chromium/components/viz/service/surfaces/surface.h
+++ b/chromium/components/viz/service/surfaces/surface.h
@@ -22,7 +22,6 @@
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/surface_info.h"
-#include "components/viz/common/surfaces/surface_sequence.h"
#include "components/viz/service/surfaces/surface_dependency_deadline.h"
#include "components/viz/service/viz_service_export.h"
#include "ui/gfx/geometry/size.h"
@@ -80,10 +79,12 @@ class VIZ_SERVICE_EXPORT Surface final : public SurfaceDeadlineClient {
Surface(const SurfaceInfo& surface_info,
SurfaceManager* surface_manager,
base::WeakPtr<SurfaceClient> surface_client,
- BeginFrameSource* begin_frame_source,
bool needs_sync_tokens);
~Surface();
+ void SetDependencyDeadline(
+ std::unique_ptr<SurfaceDependencyDeadline> deadline);
+
// Clears the pending and active frame data as well as the
// |seen_first_frame_activation_| bit causing a FirstSurfaceActivation to be
// triggered on the next CompositorFrame activation.
@@ -99,14 +100,9 @@ class VIZ_SERVICE_EXPORT Surface final : public SurfaceDeadlineClient {
base::WeakPtr<SurfaceClient> client() { return surface_client_; }
- bool has_deadline() const { return deadline_.has_deadline(); }
- const SurfaceDependencyDeadline& deadline() const { return deadline_; }
-
- bool InheritActivationDeadlineFrom(const SurfaceDependencyDeadline& deadline);
+ bool has_deadline() const { return deadline_ && deadline_->has_deadline(); }
- // Sets a deadline a number of frames ahead to active the currently pending
- // CompositorFrame held by this surface.
- void SetActivationDeadline(uint32_t number_of_frames_to_deadline);
+ bool InheritActivationDeadlineFrom(Surface* surface);
void SetPreviousFrameSurface(Surface* surface);
@@ -139,7 +135,8 @@ class VIZ_SERVICE_EXPORT Surface final : public SurfaceDeadlineClient {
// Called if a deadline has been hit and this surface is not yet active but
// it's marked as respecting deadlines.
- void ActivatePendingFrameForDeadline();
+ void ActivatePendingFrameForDeadline(
+ base::Optional<base::TimeDelta> duration);
using CopyRequestsMap =
std::multimap<RenderPassId, std::unique_ptr<CopyOutputRequest>>;
@@ -168,19 +165,6 @@ class VIZ_SERVICE_EXPORT Surface final : public SurfaceDeadlineClient {
void RunDrawCallback();
void NotifyAggregatedDamage(const gfx::Rect& damage_rect);
- // Add a SurfaceSequence that must be satisfied before the Surface is
- // destroyed.
- void AddDestructionDependency(SurfaceSequence sequence);
-
- // Satisfy all destruction dependencies that are contained in sequences, and
- // remove them from sequences.
- void SatisfyDestructionDependencies(
- base::flat_set<SurfaceSequence>* sequences,
- base::flat_map<FrameSinkId, std::string>* valid_id_namespaces);
- size_t GetDestructionDependencyCount() const {
- return destruction_dependencies_.size();
- }
-
const std::vector<SurfaceId>* active_referenced_surfaces() const {
return active_frame_data_
? &active_frame_data_->frame.metadata.referenced_surfaces
@@ -207,7 +191,7 @@ class VIZ_SERVICE_EXPORT Surface final : public SurfaceDeadlineClient {
}
// SurfaceDeadlineClient implementation:
- void OnDeadline() override;
+ void OnDeadline(base::TimeDelta duration) override;
private:
struct SequenceNumbers {
@@ -240,10 +224,17 @@ class VIZ_SERVICE_EXPORT Surface final : public SurfaceDeadlineClient {
// surface. Once a Surface is closed, it cannot accept CompositorFrames again.
void Close();
- void ActivatePendingFrame();
+ void ActivatePendingFrame(base::Optional<base::TimeDelta> duration);
+
// Called when all of the surface's dependencies have been resolved.
- void ActivateFrame(FrameData frame_data);
- void UpdateActivationDependencies(const CompositorFrame& current_frame);
+ void ActivateFrame(FrameData frame_data,
+ base::Optional<base::TimeDelta> duration);
+
+ // Updates the set of unresolved activation dependenices of the
+ // |current_frame|. If the deadline requested by the frame is 0 then no
+ // dependencies will be added even if they're not yet available.
+ FrameDeadline UpdateActivationDependencies(
+ const CompositorFrame& current_frame);
void ComputeChangeInDependencies(
const base::flat_map<FrameSinkId, SequenceNumbers>& new_dependencies);
@@ -260,14 +251,13 @@ class VIZ_SERVICE_EXPORT Surface final : public SurfaceDeadlineClient {
SurfaceId previous_frame_surface_id_;
SurfaceManager* const surface_manager_;
base::WeakPtr<SurfaceClient> surface_client_;
- SurfaceDependencyDeadline deadline_;
+ std::unique_ptr<SurfaceDependencyDeadline> deadline_;
base::Optional<FrameData> pending_frame_data_;
base::Optional<FrameData> active_frame_data_;
bool closed_ = false;
bool seen_first_frame_activation_ = false;
const bool needs_sync_tokens_;
- std::vector<SurfaceSequence> destruction_dependencies_;
base::flat_set<SurfaceId> activation_dependencies_;
base::flat_set<SurfaceId> late_activation_dependencies_;
diff --git a/chromium/components/viz/service/surfaces/surface_client.h b/chromium/components/viz/service/surfaces/surface_client.h
index 599564f5c25..cb8740596c7 100644
--- a/chromium/components/viz/service/surfaces/surface_client.h
+++ b/chromium/components/viz/service/surfaces/surface_client.h
@@ -28,6 +28,9 @@ class VIZ_SERVICE_EXPORT SurfaceClient {
// Called when |surface| has a new CompositorFrame available for display.
virtual void OnSurfaceActivated(Surface* surface) = 0;
+ // Called when |surface| is about to be destroyed.
+ virtual void OnSurfaceDiscarded(Surface* surface) = 0;
+
// Increments the reference count on resources specified by |resources|.
virtual void RefResources(
const std::vector<TransferableResource>& resources) = 0;
diff --git a/chromium/components/viz/service/surfaces/surface_deadline_client.h b/chromium/components/viz/service/surfaces/surface_deadline_client.h
index 59e35c0d897..3e4366f5235 100644
--- a/chromium/components/viz/service/surfaces/surface_deadline_client.h
+++ b/chromium/components/viz/service/surfaces/surface_deadline_client.h
@@ -10,7 +10,7 @@ namespace viz {
class SurfaceDeadlineClient {
public:
// Called when a deadline passes for a set of dependencies.
- virtual void OnDeadline() = 0;
+ virtual void OnDeadline(base::TimeDelta duration) = 0;
};
} // namespace viz
diff --git a/chromium/components/viz/service/surfaces/surface_dependency_deadline.cc b/chromium/components/viz/service/surfaces/surface_dependency_deadline.cc
index f13cf327aec..bd28f505af8 100644
--- a/chromium/components/viz/service/surfaces/surface_dependency_deadline.cc
+++ b/chromium/components/viz/service/surfaces/surface_dependency_deadline.cc
@@ -5,32 +5,41 @@
#include "components/viz/service/surfaces/surface_dependency_deadline.h"
#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/time/tick_clock.h"
+#include "components/viz/common/quads/frame_deadline.h"
namespace viz {
SurfaceDependencyDeadline::SurfaceDependencyDeadline(
SurfaceDeadlineClient* client,
- BeginFrameSource* begin_frame_source)
- : client_(client), begin_frame_source_(begin_frame_source) {
+ BeginFrameSource* begin_frame_source,
+ base::TickClock* tick_clock)
+ : client_(client),
+ begin_frame_source_(begin_frame_source),
+ tick_clock_(tick_clock) {
DCHECK(client_);
DCHECK(begin_frame_source_);
+ DCHECK(tick_clock_);
}
SurfaceDependencyDeadline::~SurfaceDependencyDeadline() {
// The deadline must be canceled before destruction.
- DCHECK(!number_of_frames_to_deadline_);
+ DCHECK(!deadline_);
}
-void SurfaceDependencyDeadline::Set(uint32_t number_of_frames_to_deadline) {
- DCHECK_GT(number_of_frames_to_deadline, 0u);
+bool SurfaceDependencyDeadline::Set(const FrameDeadline& frame_deadline) {
+ DCHECK_GT(frame_deadline.deadline_in_frames(), 0u);
CancelInternal(false);
- number_of_frames_to_deadline_ = number_of_frames_to_deadline;
- start_time_ = base::TimeTicks::Now();
+ start_time_ = frame_deadline.frame_start_time();
+ deadline_ = start_time_ + frame_deadline.deadline_in_frames() *
+ frame_deadline.frame_interval();
begin_frame_source_->AddObserver(this);
+ return has_deadline();
}
-void SurfaceDependencyDeadline::Cancel() {
- CancelInternal(false);
+base::Optional<base::TimeDelta> SurfaceDependencyDeadline::Cancel() {
+ return CancelInternal(false);
}
bool SurfaceDependencyDeadline::InheritFrom(
@@ -38,21 +47,21 @@ bool SurfaceDependencyDeadline::InheritFrom(
if (*this == other)
return false;
+ DCHECK(has_deadline());
+
CancelInternal(false);
last_begin_frame_args_ = other.last_begin_frame_args_;
begin_frame_source_ = other.begin_frame_source_;
- number_of_frames_to_deadline_ = other.number_of_frames_to_deadline_;
- if (number_of_frames_to_deadline_) {
- start_time_ = base::TimeTicks::Now();
+ deadline_ = other.deadline_;
+ if (deadline_)
begin_frame_source_->AddObserver(this);
- }
return true;
}
bool SurfaceDependencyDeadline::operator==(
const SurfaceDependencyDeadline& other) {
return begin_frame_source_ == other.begin_frame_source_ &&
- number_of_frames_to_deadline_ == other.number_of_frames_to_deadline_;
+ deadline_ == other.deadline_;
}
// BeginFrameObserver implementation.
@@ -60,15 +69,16 @@ void SurfaceDependencyDeadline::OnBeginFrame(const BeginFrameArgs& args) {
last_begin_frame_args_ = args;
// OnBeginFrame might get called immediately after cancellation if some other
// deadline triggered this deadline to be canceled.
- if (!number_of_frames_to_deadline_ || args.type == BeginFrameArgs::MISSED)
+ if (!deadline_)
return;
- if (--(*number_of_frames_to_deadline_) > 0)
+ if (deadline_ > tick_clock_->NowTicks())
return;
- CancelInternal(true);
+ base::Optional<base::TimeDelta> duration = CancelInternal(true);
+ DCHECK(duration);
- client_->OnDeadline();
+ client_->OnDeadline(*duration);
}
const BeginFrameArgs& SurfaceDependencyDeadline::LastUsedBeginFrameArgs()
@@ -82,17 +92,23 @@ bool SurfaceDependencyDeadline::WantsAnimateOnlyBeginFrames() const {
void SurfaceDependencyDeadline::OnBeginFrameSourcePausedChanged(bool paused) {}
-void SurfaceDependencyDeadline::CancelInternal(bool deadline) {
- if (!number_of_frames_to_deadline_)
- return;
+base::Optional<base::TimeDelta> SurfaceDependencyDeadline::CancelInternal(
+ bool deadline) {
+ if (!deadline_)
+ return base::nullopt;
+
begin_frame_source_->RemoveObserver(this);
- number_of_frames_to_deadline_.reset();
+ deadline_.reset();
+
+ base::TimeDelta duration = tick_clock_->NowTicks() - start_time_;
UMA_HISTOGRAM_TIMES("Compositing.SurfaceDependencyDeadline.Duration",
- base::TimeTicks::Now() - start_time_);
+ duration);
UMA_HISTOGRAM_BOOLEAN("Compositing.SurfaceDependencyDeadline.DeadlineHit",
deadline);
+
+ return duration;
}
} // namespace viz
diff --git a/chromium/components/viz/service/surfaces/surface_dependency_deadline.h b/chromium/components/viz/service/surfaces/surface_dependency_deadline.h
index 1e33b6b1468..a2be0927713 100644
--- a/chromium/components/viz/service/surfaces/surface_dependency_deadline.h
+++ b/chromium/components/viz/service/surfaces/surface_dependency_deadline.h
@@ -8,21 +8,35 @@
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/service/surfaces/surface_deadline_client.h"
+#include "components/viz/service/viz_service_export.h"
+
+namespace base {
+class TickClock;
+} // namespace base
namespace viz {
-class SurfaceDependencyDeadline : public BeginFrameObserver {
+class FrameDeadline;
+
+class VIZ_SERVICE_EXPORT SurfaceDependencyDeadline : public BeginFrameObserver {
public:
SurfaceDependencyDeadline(SurfaceDeadlineClient* client,
- BeginFrameSource* begin_frame_source);
+ BeginFrameSource* begin_frame_source,
+ base::TickClock* tick_clock);
~SurfaceDependencyDeadline() override;
- void Set(uint32_t number_of_frames_to_deadline);
- void Cancel();
+ // Sets up a deadline in wall time where
+ // deadline = frame_start_time + deadline_in_frames * frame_interval.
+ // It's possible for the deadline to already be in the past. In that case,
+ // this method will return false. Otherwise, it will return true.
+ bool Set(const FrameDeadline& frame_deadline);
- bool has_deadline() const {
- return number_of_frames_to_deadline_.has_value();
- }
+ // 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();
+
+ bool has_deadline() const { return deadline_.has_value(); }
// Takes on the same BeginFrameSource and deadline as |other|. Returns
// false if they're already the same, and true otherwise.
@@ -40,12 +54,13 @@ class SurfaceDependencyDeadline : public BeginFrameObserver {
bool WantsAnimateOnlyBeginFrames() const override;
private:
- void CancelInternal(bool deadline);
+ base::Optional<base::TimeDelta> CancelInternal(bool deadline);
SurfaceDeadlineClient* const client_;
BeginFrameSource* begin_frame_source_ = nullptr;
- base::Optional<uint32_t> number_of_frames_to_deadline_;
+ base::TickClock* tick_clock_;
base::TimeTicks start_time_;
+ base::Optional<base::TimeTicks> deadline_;
BeginFrameArgs last_begin_frame_args_;
diff --git a/chromium/components/viz/service/surfaces/surface_dependency_deadline_unittest.cc b/chromium/components/viz/service/surfaces/surface_dependency_deadline_unittest.cc
new file mode 100644
index 00000000000..ce631b2f50d
--- /dev/null
+++ b/chromium/components/viz/service/surfaces/surface_dependency_deadline_unittest.cc
@@ -0,0 +1,132 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/service/surfaces/surface_dependency_deadline.h"
+#include "components/viz/common/quads/frame_deadline.h"
+#include "components/viz/service/surfaces/surface_deadline_client.h"
+#include "components/viz/test/begin_frame_args_test.h"
+#include "components/viz/test/fake_external_begin_frame_source.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace viz {
+namespace test {
+
+class FakeSurfaceDeadlineClient : public SurfaceDeadlineClient {
+ public:
+ FakeSurfaceDeadlineClient() = default;
+ ~FakeSurfaceDeadlineClient() = default;
+
+ // SurfaceDeadlineClient implementation:
+ void OnDeadline(base::TimeDelta duration) override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FakeSurfaceDeadlineClient);
+};
+
+class FakeSlowBeginFrameSource : public FakeExternalBeginFrameSource {
+ public:
+ FakeSlowBeginFrameSource(double refresh_rate,
+ bool tick_automatically,
+ base::SimpleTestTickClock* tick_clock)
+ : FakeExternalBeginFrameSource(refresh_rate, tick_automatically),
+ tick_clock_(tick_clock) {}
+
+ ~FakeSlowBeginFrameSource() override {}
+
+ // FakeExternalBeginFrameSource overrides:
+ void AddObserver(BeginFrameObserver* obs) override {
+ // Advancing time here simulates a slow AddObserver operation.
+ tick_clock_->Advance(BeginFrameArgs::DefaultInterval());
+ FakeExternalBeginFrameSource::AddObserver(obs);
+ }
+
+ private:
+ base::SimpleTestTickClock* const tick_clock_;
+ DISALLOW_COPY_AND_ASSIGN(FakeSlowBeginFrameSource);
+};
+
+class SurfaceDependencyDeadlineTest : public testing::Test {
+ public:
+ SurfaceDependencyDeadlineTest() = default;
+
+ ~SurfaceDependencyDeadlineTest() override {}
+
+ FakeSlowBeginFrameSource* begin_frame_source() {
+ return begin_frame_source_.get();
+ }
+
+ FrameDeadline MakeDefaultDeadline() {
+ return FrameDeadline(now_src_->NowTicks(), 4u,
+ BeginFrameArgs::DefaultInterval(), false);
+ }
+
+ SurfaceDependencyDeadline* deadline() { return deadline_.get(); }
+
+ void SendLateBeginFrame(uint32_t frames_late) {
+ // Creep the time forward so that any BeginFrameArgs is not equal to the
+ // last one otherwise we violate the BeginFrameSource contract.
+ now_src_->Advance(frames_late * BeginFrameArgs::DefaultInterval());
+ BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
+ BEGINFRAME_FROM_HERE, now_src_.get());
+ begin_frame_source_->TestOnBeginFrame(args);
+ }
+
+ // testing::Test:
+ void SetUp() override {
+ testing::Test::SetUp();
+
+ now_src_ = std::make_unique<base::SimpleTestTickClock>();
+ begin_frame_source_ =
+ std::make_unique<FakeSlowBeginFrameSource>(0.f, false, now_src_.get());
+
+ deadline_ = std::make_unique<SurfaceDependencyDeadline>(
+ &client_, begin_frame_source_.get(), now_src_.get());
+ }
+
+ void TearDown() override {
+ deadline_->Cancel();
+ deadline_.reset();
+ begin_frame_source_.reset();
+ now_src_.reset();
+ }
+
+ private:
+ std::unique_ptr<base::SimpleTestTickClock> now_src_;
+ std::unique_ptr<FakeSlowBeginFrameSource> begin_frame_source_;
+ FakeSurfaceDeadlineClient client_;
+ std::unique_ptr<SurfaceDependencyDeadline> deadline_;
+
+ DISALLOW_COPY_AND_ASSIGN(SurfaceDependencyDeadlineTest);
+};
+
+// This test verifies that if the FrameDeadline is in the past then
+// SurfaceDependencyDeadline::Set will return false.
+TEST_F(SurfaceDependencyDeadlineTest, DeadlineInPast) {
+ FrameDeadline frame_deadline = MakeDefaultDeadline();
+ SendLateBeginFrame(4u);
+ EXPECT_FALSE(deadline()->Set(frame_deadline));
+ EXPECT_FALSE(deadline()->has_deadline());
+}
+
+// This test verifies that if Set returns false, then SurfaceDependencyDeadline
+// does not have a pending deadline.
+TEST_F(SurfaceDependencyDeadlineTest, SetMatchesHasDeadlineIfFalse) {
+ FrameDeadline frame_deadline = MakeDefaultDeadline();
+ SendLateBeginFrame(3u);
+ EXPECT_FALSE(deadline()->Set(frame_deadline));
+ EXPECT_FALSE(deadline()->has_deadline());
+}
+
+// This test verifies that if Set returns true, then SurfaceDependencyDeadline
+// has a pending deadline.
+TEST_F(SurfaceDependencyDeadlineTest, SetMatchesHasDeadlineIfTrue) {
+ FrameDeadline frame_deadline = MakeDefaultDeadline();
+ SendLateBeginFrame(2u);
+ EXPECT_TRUE(deadline()->Set(frame_deadline));
+ EXPECT_TRUE(deadline()->has_deadline());
+}
+
+} // namespace test
+} // namespace viz
diff --git a/chromium/components/viz/service/surfaces/surface_dependency_tracker.cc b/chromium/components/viz/service/surfaces/surface_dependency_tracker.cc
index f7b17236cd3..a419397ab1f 100644
--- a/chromium/components/viz/service/surfaces/surface_dependency_tracker.cc
+++ b/chromium/components/viz/service/surfaces/surface_dependency_tracker.cc
@@ -11,10 +11,8 @@
namespace viz {
SurfaceDependencyTracker::SurfaceDependencyTracker(
- SurfaceManager* surface_manager,
- uint32_t number_of_frames_to_deadline)
- : surface_manager_(surface_manager),
- number_of_frames_to_deadline_(number_of_frames_to_deadline) {}
+ SurfaceManager* surface_manager)
+ : surface_manager_(surface_manager) {}
SurfaceDependencyTracker::~SurfaceDependencyTracker() = default;
@@ -115,7 +113,7 @@ void SurfaceDependencyTracker::ActivateLateSurfaceSubtree(Surface* surface) {
ActivateLateSurfaceSubtree(dependency);
}
- surface->ActivatePendingFrameForDeadline();
+ surface->ActivatePendingFrameForDeadline(base::nullopt);
}
void SurfaceDependencyTracker::UpdateSurfaceDeadline(Surface* surface) {
@@ -135,21 +133,14 @@ void SurfaceDependencyTracker::UpdateSurfaceDeadline(Surface* surface) {
Surface* parent = surface_manager_->GetSurfaceForId(parent_id);
if (parent && parent->has_deadline() &&
parent->activation_dependencies().count(surface->surface_id())) {
- deadline_changed =
- surface->InheritActivationDeadlineFrom(parent->deadline());
+ deadline_changed = surface->InheritActivationDeadlineFrom(parent);
break;
}
}
}
- // If there are no CompositorFrames currently blocked on this surface, then
- // set a default deadline for this surface.
- if (!surface->has_deadline()) {
- surface->SetActivationDeadline(number_of_frames_to_deadline_);
- deadline_changed = true;
- }
- if (!deadline_changed)
- return;
+ DCHECK(!surface_manager_->activation_deadline_in_frames() ||
+ surface->has_deadline());
// Recursively propagate the newly set deadline to children.
for (const SurfaceId& surface_id :
diff --git a/chromium/components/viz/service/surfaces/surface_dependency_tracker.h b/chromium/components/viz/service/surfaces/surface_dependency_tracker.h
index 9558ac58d83..a18251a2c11 100644
--- a/chromium/components/viz/service/surfaces/surface_dependency_tracker.h
+++ b/chromium/components/viz/service/surfaces/surface_dependency_tracker.h
@@ -27,8 +27,7 @@ class SurfaceManager;
// BeginFrames.
class VIZ_SERVICE_EXPORT SurfaceDependencyTracker {
public:
- SurfaceDependencyTracker(SurfaceManager* surface_manager,
- uint32_t number_of_frames_to_deadline);
+ explicit SurfaceDependencyTracker(SurfaceManager* surface_manager);
~SurfaceDependencyTracker();
// Called when |surface| has a pending CompositorFrame and it wishes to be
@@ -63,8 +62,6 @@ class VIZ_SERVICE_EXPORT SurfaceDependencyTracker {
SurfaceManager* const surface_manager_;
- const uint32_t number_of_frames_to_deadline_;
-
// A map from a FrameSinkId to the set of Surfaces that are blocked on
// surfaces associated with that FrameSinkId.
std::unordered_map<FrameSinkId, base::flat_set<SurfaceId>, FrameSinkIdHash>
diff --git a/chromium/components/viz/service/surfaces/surface_hittest_unittest.cc b/chromium/components/viz/service/surfaces/surface_hittest_unittest.cc
index 3411980c567..ed2cf41fd84 100644
--- a/chromium/components/viz/service/surfaces/surface_hittest_unittest.cc
+++ b/chromium/components/viz/service/surfaces/surface_hittest_unittest.cc
@@ -135,8 +135,6 @@ TEST_F(SurfaceHittestTest, Hittest_BadCompositorFrameDoesNotCrash) {
root_surface_id, gfx::Point(100, 100),
&transform, &query_renderer));
}
-
- root_support().EvictCurrentSurface();
}
TEST_F(SurfaceHittestTest, Hittest_SingleSurface) {
@@ -157,8 +155,6 @@ TEST_F(SurfaceHittestTest, Hittest_SingleSurface) {
};
RunTests(nullptr, surface_manager(), tests, arraysize(tests));
-
- root_support().EvictCurrentSurface();
}
TEST_F(SurfaceHittestTest, Hittest_ChildSurface) {
@@ -249,9 +245,6 @@ TEST_F(SurfaceHittestTest, Hittest_ChildSurface) {
EXPECT_NE(transform, target_transform);
EXPECT_EQ(gfx::Point(25, 25), point_in_target_space);
}
-
- root_support().EvictCurrentSurface();
- child_support().EvictCurrentSurface();
}
TEST_F(SurfaceHittestTest, Hittest_OccludedChildSurface) {
@@ -316,9 +309,6 @@ TEST_F(SurfaceHittestTest, Hittest_OccludedChildSurface) {
gfx::Point(290, 290), false}};
RunTests(nullptr, surface_manager(), tests, arraysize(tests));
-
- root_support().EvictCurrentSurface();
- child_support().EvictCurrentSurface();
}
// This test verifies that hit testing will progress to the next quad if it
@@ -382,9 +372,6 @@ TEST_F(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) {
gfx::Point(290, 290), false}};
RunTests(nullptr, surface_manager(), tests, arraysize(tests));
-
- root_support().EvictCurrentSurface();
- child_support().EvictCurrentSurface();
}
TEST_F(SurfaceHittestTest, Hittest_RenderPassDrawQuad) {
@@ -446,8 +433,6 @@ TEST_F(SurfaceHittestTest, Hittest_RenderPassDrawQuad) {
gfx::Point(100, 100), false}};
RunTests(nullptr, surface_manager(), tests, arraysize(tests));
-
- root_support().EvictCurrentSurface();
}
TEST_F(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) {
@@ -571,9 +556,6 @@ TEST_F(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) {
// Verify that insets have affected hit targeting.
EXPECT_EQ(0, accept_delegate.reject_target_overrides());
EXPECT_EQ(2, accept_delegate.accept_target_overrides());
-
- root_support().EvictCurrentSurface();
- child_support().EvictCurrentSurface();
}
} // namespace viz
diff --git a/chromium/components/viz/service/surfaces/surface_manager.cc b/chromium/components/viz/service/surfaces/surface_manager.cc
index f8f667e52f0..48b4b4ecc01 100644
--- a/chromium/components/viz/service/surfaces/surface_manager.cc
+++ b/chromium/components/viz/service/surfaces/surface_manager.cc
@@ -15,10 +15,9 @@
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/time/default_tick_clock.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
-#include "components/viz/common/surfaces/stub_surface_reference_factory.h"
#include "components/viz/common/surfaces/surface_info.h"
-#include "components/viz/service/surfaces/direct_surface_reference_factory.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_client.h"
@@ -29,11 +28,10 @@
namespace viz {
namespace {
-// Maximum bucket size for the UMA stat.
-constexpr int kUmaStatMax = 10;
+constexpr base::TimeDelta kExpireInterval = base::TimeDelta::FromSeconds(10);
-const char kUmaNumOldTemporaryReferences[] =
- "Compositing.SurfaceManager.NumOldTemporaryReferences";
+const char kUmaRemovedTemporaryReference[] =
+ "Compositing.SurfaceManager.RemovedTemporaryReference";
} // namespace
@@ -45,30 +43,19 @@ SurfaceManager::TemporaryReferenceData::TemporaryReferenceData() = default;
SurfaceManager::TemporaryReferenceData::~TemporaryReferenceData() = default;
-SurfaceManager::SurfaceManager(LifetimeType lifetime_type,
- uint32_t number_of_frames_to_activation_deadline)
- : lifetime_type_(lifetime_type),
- dependency_tracker_(this, number_of_frames_to_activation_deadline),
+SurfaceManager::SurfaceManager(
+ base::Optional<uint32_t> activation_deadline_in_frames)
+ : activation_deadline_in_frames_(activation_deadline_in_frames),
+ dependency_tracker_(this),
root_surface_id_(FrameSinkId(0u, 0u),
LocalSurfaceId(1u, base::UnguessableToken::Create())),
+ tick_clock_(base::DefaultTickClock::GetInstance()),
weak_factory_(this) {
thread_checker_.DetachFromThread();
- if (using_surface_references()) {
- reference_factory_ = new StubSurfaceReferenceFactory();
-
- // Android WebView doesn't have a task runner and doesn't need the timer.
- if (base::SequencedTaskRunnerHandle::IsSet()) {
- temporary_reference_timer_.Start(
- FROM_HERE, base::TimeDelta::FromSeconds(10), this,
- &SurfaceManager::MarkOldTemporaryReferences);
- }
- // TODO(kylechar): After collecting UMA stats on the number of old temporary
- // references, we may want to turn the timer off when there are no temporary
- // references to avoid waking the thread unnecessarily.
- } else {
- reference_factory_ =
- new DirectSurfaceReferenceFactory(weak_factory_.GetWeakPtr());
- }
+
+ // Android WebView doesn't have a task runner and doesn't need the timer.
+ if (base::SequencedTaskRunnerHandle::IsSet())
+ expire_timer_.emplace();
}
SurfaceManager::~SurfaceManager() {
@@ -104,8 +91,13 @@ std::string SurfaceManager::SurfaceReferencesToString() {
}
#endif
-void SurfaceManager::RequestSurfaceResolution(Surface* surface) {
- dependency_tracker_.RequestSurfaceResolution(surface);
+void SurfaceManager::SetActivationDeadlineInFramesForTesting(
+ base::Optional<uint32_t> activation_deadline_in_frames) {
+ activation_deadline_in_frames_ = activation_deadline_in_frames;
+}
+
+void SurfaceManager::SetTickClockForTesting(base::TickClock* tick_clock) {
+ tick_clock_ = tick_clock;
}
Surface* SurfaceManager::CreateSurface(
@@ -121,18 +113,23 @@ Surface* SurfaceManager::CreateSurface(
// and return.
auto it = surface_map_.find(surface_info.id());
if (it == surface_map_.end()) {
- surface_map_[surface_info.id()] =
- std::make_unique<Surface>(surface_info, this, surface_client,
- begin_frame_source, needs_sync_tokens);
- if (lifetime_type_ == LifetimeType::REFERENCES) {
- // We can get into a situation where multiple CompositorFrames arrive for
- // a FrameSink before the client can add any references for the frame.
- // When the second frame with a new size arrives, the first will be
- // destroyed in SurfaceFactory and then if there are no references it will
- // be deleted during surface GC. A temporary reference, removed when a
- // real reference is received, is added to prevent this from happening.
- AddTemporaryReference(surface_info.id());
+ std::unique_ptr<Surface> surface = std::make_unique<Surface>(
+ surface_info, this, surface_client, needs_sync_tokens);
+ // If no default deadline is specified then don't track deadlines.
+ if (activation_deadline_in_frames_) {
+ surface->SetDependencyDeadline(
+ std::make_unique<SurfaceDependencyDeadline>(
+ surface.get(), begin_frame_source, tick_clock_));
}
+ surface_map_[surface_info.id()] = std::move(surface);
+ // We can get into a situation where multiple CompositorFrames arrive for a
+ // FrameSink before the client can add any references for the frame. When
+ // the second frame with a new size arrives, the first will be destroyed in
+ // SurfaceFactory and then if there are no references it will be deleted
+ // during surface GC. A temporary reference, removed when a real reference
+ // is received, is added to prevent this from happening.
+ AddTemporaryReference(surface_info.id());
+
for (auto& observer : observer_list_)
observer.OnSurfaceCreated(surface_info.id());
return surface_map_[surface_info.id()].get();
@@ -161,23 +158,6 @@ void SurfaceManager::DestroySurface(const SurfaceId& surface_id) {
surfaces_to_destroy_.insert(surface_id);
}
-void SurfaceManager::RequireSequence(const SurfaceId& surface_id,
- const SurfaceSequence& sequence) {
- DCHECK_EQ(lifetime_type_, LifetimeType::SEQUENCES);
- auto* surface = GetSurfaceForId(surface_id);
- if (!surface) {
- DLOG(ERROR) << "Attempting to require callback on nonexistent surface";
- return;
- }
- surface->AddDestructionDependency(sequence);
-}
-
-void SurfaceManager::SatisfySequence(const SurfaceSequence& sequence) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK_EQ(lifetime_type_, LifetimeType::SEQUENCES);
- satisfied_sequences_.insert(sequence);
-}
-
void SurfaceManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) {
bool inserted = valid_frame_sink_labels_.emplace(frame_sink_id, "").second;
DCHECK(inserted);
@@ -195,7 +175,7 @@ void SurfaceManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) {
}
for (auto& surface_id : temp_refs_to_clear)
- RemoveTemporaryReference(surface_id, false);
+ RemoveTemporaryReference(surface_id, RemovedReason::INVALIDATED);
GarbageCollectSurfaces();
}
@@ -238,7 +218,6 @@ void SurfaceManager::RemoveSurfaceReferences(
void SurfaceManager::AssignTemporaryReference(const SurfaceId& surface_id,
const FrameSinkId& owner) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES);
if (!HasTemporaryReference(surface_id))
return;
@@ -249,12 +228,10 @@ void SurfaceManager::AssignTemporaryReference(const SurfaceId& surface_id,
void SurfaceManager::DropTemporaryReference(const SurfaceId& surface_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (lifetime_type_ != LifetimeType::REFERENCES ||
- !HasTemporaryReference(surface_id)) {
+ if (!HasTemporaryReference(surface_id))
return;
- }
- RemoveTemporaryReference(surface_id, false);
+ RemoveTemporaryReference(surface_id, RemovedReason::DROPPED);
}
void SurfaceManager::GarbageCollectSurfaces() {
@@ -262,9 +239,7 @@ void SurfaceManager::GarbageCollectSurfaces() {
if (surfaces_to_destroy_.empty())
return;
- SurfaceIdSet reachable_surfaces = using_surface_references()
- ? GetLiveSurfacesForReferences()
- : GetLiveSurfacesForSequences();
+ SurfaceIdSet reachable_surfaces = GetLiveSurfacesForReferences();
std::vector<SurfaceId> surfaces_to_delete;
@@ -301,8 +276,6 @@ const base::flat_set<SurfaceId>& SurfaceManager::GetSurfacesThatReferenceChild(
}
SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForReferences() {
- DCHECK(using_surface_references());
-
SurfaceIdSet reachable_surfaces;
// Walk down from the root and mark each SurfaceId we encounter as
@@ -339,52 +312,6 @@ SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForReferences() {
return reachable_surfaces;
}
-SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForSequences() {
- DCHECK_EQ(lifetime_type_, LifetimeType::SEQUENCES);
-
- // Simple mark and sweep GC.
- // TODO(jbauman): Reduce the amount of work when nothing needs to be
- // destroyed.
- std::vector<SurfaceId> live_surfaces;
- std::unordered_set<SurfaceId, SurfaceIdHash> live_surfaces_set;
-
- // GC roots are surfaces that have not been destroyed, or have not had all
- // their destruction dependencies satisfied.
- for (auto& map_entry : surface_map_) {
- const SurfaceId& surface_id = map_entry.first;
- Surface* surface = map_entry.second.get();
- surface->SatisfyDestructionDependencies(&satisfied_sequences_,
- &valid_frame_sink_labels_);
-
- if (!IsMarkedForDestruction(surface_id) ||
- surface->GetDestructionDependencyCount() > 0) {
- live_surfaces_set.insert(surface_id);
- live_surfaces.push_back(surface_id);
- }
- }
-
- // Mark all surfaces reachable from live surfaces by adding them to
- // live_surfaces and live_surfaces_set.
- for (size_t i = 0; i < live_surfaces.size(); i++) {
- Surface* surf = surface_map_[live_surfaces[i]].get();
- DCHECK(surf);
-
- const auto& children = GetSurfacesReferencedByParent(surf->surface_id());
- for (const SurfaceId& id : children) {
- if (live_surfaces_set.count(id))
- continue;
-
- Surface* surf2 = GetSurfaceForId(id);
- if (surf2) {
- live_surfaces.push_back(id);
- live_surfaces_set.insert(id);
- }
- }
- }
-
- return live_surfaces_set;
-}
-
void SurfaceManager::AddSurfaceReferenceImpl(const SurfaceId& parent_id,
const SurfaceId& child_id) {
if (parent_id.frame_sink_id() == child_id.frame_sink_id()) {
@@ -404,7 +331,7 @@ void SurfaceManager::AddSurfaceReferenceImpl(const SurfaceId& parent_id,
references_[child_id].parents.insert(parent_id);
if (HasTemporaryReference(child_id))
- RemoveTemporaryReference(child_id, true);
+ RemoveTemporaryReference(child_id, RemovedReason::EMBEDDED);
}
void SurfaceManager::RemoveSurfaceReferenceImpl(const SurfaceId& parent_id,
@@ -448,43 +375,64 @@ void SurfaceManager::AddTemporaryReference(const SurfaceId& surface_id) {
temporary_references_[surface_id].owner = base::Optional<FrameSinkId>();
temporary_reference_ranges_[surface_id.frame_sink_id()].push_back(
surface_id.local_surface_id());
+
+ // Start timer to expire temporary references if it's not running.
+ if (expire_timer_ && !expire_timer_->IsRunning()) {
+ expire_timer_->Start(FROM_HERE, kExpireInterval, this,
+ &SurfaceManager::ExpireOldTemporaryReferences);
+ }
}
void SurfaceManager::RemoveTemporaryReference(const SurfaceId& surface_id,
- bool remove_range) {
+ RemovedReason reason) {
DCHECK(HasTemporaryReference(surface_id));
const FrameSinkId& frame_sink_id = surface_id.frame_sink_id();
std::vector<LocalSurfaceId>& frame_sink_temp_refs =
temporary_reference_ranges_[frame_sink_id];
+ // If the temporary reference to |surface_id| is being removed because it was
+ // embedded, then remove older temporary references with the same FrameSinkId.
+ const bool remove_older = (reason == RemovedReason::EMBEDDED);
+
// Find the iterator to the range tracking entry for |surface_id|. Use that
- // iterator and |remove_range| to find the right begin and end iterators for
+ // iterator and |remove_older| to find the right begin and end iterators for
// the temporary references we want to remove.
auto surface_id_iter =
std::find(frame_sink_temp_refs.begin(), frame_sink_temp_refs.end(),
surface_id.local_surface_id());
auto begin_iter =
- remove_range ? frame_sink_temp_refs.begin() : surface_id_iter;
+ remove_older ? frame_sink_temp_refs.begin() : surface_id_iter;
auto end_iter = surface_id_iter + 1;
// Remove temporary references and range tracking information.
- for (auto iter = begin_iter; iter != end_iter; ++iter)
+ for (auto iter = begin_iter; iter != end_iter; ++iter) {
temporary_references_.erase(SurfaceId(frame_sink_id, *iter));
+
+ // If removing more than the temporary reference to |surface_id| then the
+ // reason for removing others is because they are being skipped.
+ const bool was_skipped = (*iter != surface_id.local_surface_id());
+ UMA_HISTOGRAM_ENUMERATION(kUmaRemovedTemporaryReference,
+ was_skipped ? RemovedReason::SKIPPED : reason,
+ RemovedReason::COUNT);
+ }
frame_sink_temp_refs.erase(begin_iter, end_iter);
// If last temporary reference is removed for |frame_sink_id| then cleanup
// range tracking map entry.
if (frame_sink_temp_refs.empty())
temporary_reference_ranges_.erase(frame_sink_id);
+
+ // Stop the timer if there are no temporary references that could expire.
+ if (temporary_references_.empty()) {
+ if (expire_timer_ && expire_timer_->IsRunning())
+ expire_timer_->Stop();
+ }
}
Surface* SurfaceManager::GetLatestInFlightSurface(
const SurfaceId& primary_surface_id,
const SurfaceId& fallback_surface_id) {
- if (!using_surface_references())
- return nullptr;
-
// The fallback surface must exist before we begin looking for more recent
// surfaces. This guarantees that the |parent| is allowed to embed the
// |fallback_surface_id| and is not guessing surface IDs.
@@ -503,9 +451,6 @@ Surface* SurfaceManager::GetLatestInFlightSurface(
if (it == temporary_reference_ranges_.end())
return fallback_surface;
- const base::flat_set<SurfaceId>& fallback_parents =
- GetSurfacesThatReferenceChild(fallback_surface_id);
-
const std::vector<LocalSurfaceId>& temp_surfaces = it->second;
for (const LocalSurfaceId& local_surface_id : base::Reversed(temp_surfaces)) {
// The in-flight surface must be older than the primary surface ID.
@@ -517,14 +462,16 @@ Surface* SurfaceManager::GetLatestInFlightSurface(
continue;
}
- SurfaceId surface_id(fallback_surface_id.frame_sink_id(), local_surface_id);
- base::Optional<FrameSinkId> owner = temporary_references_[surface_id].owner;
- // Determine if the owner of this temporary reference matches one of the
- // parents of the fallback surface. Typically a surface has a single parent
- // so this operation should be cheap.
- if (!IsOwnerAmongFallbackParents(fallback_parents, owner))
+ // If the nonce doesn't match the primary or fallback's then the parent does
+ // not have permission to embed this surface.
+ if (local_surface_id.nonce() !=
+ fallback_surface_id.local_surface_id().nonce() &&
+ local_surface_id.nonce() !=
+ primary_surface_id.local_surface_id().nonce()) {
continue;
+ }
+ SurfaceId surface_id(fallback_surface_id.frame_sink_id(), local_surface_id);
Surface* surface = GetSurfaceForId(surface_id);
if (surface && surface->HasActiveFrame())
return surface;
@@ -533,11 +480,9 @@ Surface* SurfaceManager::GetLatestInFlightSurface(
return fallback_surface;
}
-void SurfaceManager::MarkOldTemporaryReferences() {
- if (temporary_references_.empty()) {
- UMA_HISTOGRAM_EXACT_LINEAR(kUmaNumOldTemporaryReferences, 0, kUmaStatMax);
+void SurfaceManager::ExpireOldTemporaryReferences() {
+ if (temporary_references_.empty())
return;
- }
std::vector<SurfaceId> temporary_references_to_delete;
for (auto& map_entry : temporary_references_) {
@@ -555,14 +500,8 @@ void SurfaceManager::MarkOldTemporaryReferences() {
}
}
- // This number would ideally always be zero always but there is potential for
- // a frame sink to get assigned a temporary reference and never use it.
- UMA_HISTOGRAM_EXACT_LINEAR(kUmaNumOldTemporaryReferences,
- temporary_references_to_delete.size(),
- kUmaStatMax);
-
for (auto& surface_id : temporary_references_to_delete)
- RemoveTemporaryReference(surface_id, false);
+ RemoveTemporaryReference(surface_id, RemovedReason::EXPIRED);
}
Surface* SurfaceManager::GetSurfaceForId(const SurfaceId& surface_id) {
@@ -589,7 +528,9 @@ void SurfaceManager::FirstSurfaceActivation(const SurfaceInfo& surface_info) {
observer.OnFirstSurfaceActivation(surface_info);
}
-void SurfaceManager::SurfaceActivated(Surface* surface) {
+void SurfaceManager::SurfaceActivated(
+ Surface* surface,
+ base::Optional<base::TimeDelta> duration) {
// Trigger a display frame if necessary.
const CompositorFrame& frame = surface->GetActiveFrame();
if (!SurfaceModified(surface->surface_id(), frame.metadata.begin_frame_ack)) {
@@ -598,7 +539,7 @@ void SurfaceManager::SurfaceActivated(Surface* surface) {
}
for (auto& observer : observer_list_)
- observer.OnSurfaceActivated(surface->surface_id());
+ observer.OnSurfaceActivated(surface->surface_id(), duration);
dependency_tracker_.OnSurfaceActivated(surface);
}
@@ -680,18 +621,6 @@ bool SurfaceManager::IsMarkedForDestruction(const SurfaceId& surface_id) {
return surfaces_to_destroy_.count(surface_id) != 0;
}
-bool SurfaceManager::IsOwnerAmongFallbackParents(
- const base::flat_set<SurfaceId>& fallback_parents,
- const base::Optional<FrameSinkId>& owner) const {
- if (!owner)
- return false;
-
- return std::find_if(fallback_parents.begin(), fallback_parents.end(),
- [owner](const SurfaceId& parent) {
- return parent.frame_sink_id() == owner;
- }) != fallback_parents.end();
-}
-
void SurfaceManager::SurfaceWillBeDrawn(Surface* surface) {
for (auto& observer : observer_list_)
observer.OnSurfaceWillBeDrawn(surface);
diff --git a/chromium/components/viz/service/surfaces/surface_manager.h b/chromium/components/viz/service/surfaces/surface_manager.h
index b555701b7e4..11bf3d3077d 100644
--- a/chromium/components/viz/service/surfaces/surface_manager.h
+++ b/chromium/components/viz/service/surfaces/surface_manager.h
@@ -18,12 +18,11 @@
#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 "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/surface_id.h"
-#include "components/viz/common/surfaces/surface_reference_factory.h"
-#include "components/viz/common/surfaces/surface_sequence.h"
#include "components/viz/service/surfaces/surface_dependency_tracker.h"
#include "components/viz/service/surfaces/surface_observer.h"
#include "components/viz/service/surfaces/surface_reference.h"
@@ -33,6 +32,10 @@
#include <string>
#endif
+namespace base {
+class TickClock;
+} // namespace base
+
namespace viz {
namespace test {
@@ -45,13 +48,8 @@ struct BeginFrameArgs;
class VIZ_SERVICE_EXPORT SurfaceManager {
public:
- enum class LifetimeType {
- REFERENCES,
- SEQUENCES,
- };
-
- SurfaceManager(LifetimeType lifetime_type,
- uint32_t number_of_frames_to_activation_deadline);
+ explicit SurfaceManager(
+ base::Optional<uint32_t> activation_deadline_in_frames);
~SurfaceManager();
#if DCHECK_IS_ON()
@@ -59,13 +57,31 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
std::string SurfaceReferencesToString();
#endif
- void RequestSurfaceResolution(Surface* surface);
+ // Sets an alternative system default frame activation deadline for unit
+ // tests. base::nullopt indicates no deadline (in other words, an unlimited
+ // deadline).
+ void SetActivationDeadlineInFramesForTesting(
+ base::Optional<uint32_t> deadline);
+
+ base::Optional<uint32_t> activation_deadline_in_frames() const {
+ return activation_deadline_in_frames_;
+ }
+
+ SurfaceDependencyTracker* dependency_tracker() {
+ return &dependency_tracker_;
+ }
+
+ // Sets an alternative base::TickClock to pass into surfaces for surface
+ // synchronization deadlines. This allows unit tests to mock the wall clock.
+ void SetTickClockForTesting(base::TickClock* tick_clock);
+
+ // Returns the base::TickClock used to set surface synchronization deadlines.
+ base::TickClock* tick_clock() { return tick_clock_; }
// Creates a Surface for the given SurfaceClient. The surface will be
// destroyed when DestroySurface is called, all of its destruction
// dependencies are satisfied, and it is not reachable from the root surface.
- // If LifetimeType=REFERENCES, then a temporary reference will be added to
- // the new Surface.
+ // A temporary reference will be added to the new Surface.
Surface* CreateSurface(base::WeakPtr<SurfaceClient> surface_client,
const SurfaceInfo& surface_info,
BeginFrameSource* begin_frame_source,
@@ -92,8 +108,12 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
// Called when a surface has an active frame for the first time.
void FirstSurfaceActivation(const SurfaceInfo& surface_info);
- // Called when a CompositorFrame within |surface| has activated.
- void SurfaceActivated(Surface* surface);
+ // Called when a CompositorFrame within |surface| has activated. |duration| is
+ // a measure of the time the frame has spent waiting on dependencies to
+ // arrive. If |duration| is base::nullopt, then that indicates that this frame
+ // was not blocked on dependencies.
+ void SurfaceActivated(Surface* surface,
+ base::Optional<base::TimeDelta> duration);
// Called when the dependencies of a pending CompositorFrame within |surface|
// has changed.
@@ -110,15 +130,6 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
void SurfaceDamageExpected(const SurfaceId& surface_id,
const BeginFrameArgs& args);
- // Require that the given sequence number must be satisfied (using
- // SatisfySequence) before the given surface can be destroyed.
- void RequireSequence(const SurfaceId& surface_id,
- const SurfaceSequence& sequence);
-
- // Satisfies the given sequence number. Once all sequence numbers that
- // a surface depends on are satisfied, the surface can be destroyed.
- void SatisfySequence(const SurfaceSequence& sequence);
-
void RegisterFrameSinkId(const FrameSinkId& frame_sink_id);
// Invalidate a frame_sink_id that might still have associated sequences,
@@ -186,14 +197,6 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
const base::flat_set<SurfaceId>& GetSurfacesThatReferenceChild(
const SurfaceId& surface_id) const;
- const scoped_refptr<SurfaceReferenceFactory>& reference_factory() {
- return reference_factory_;
- }
-
- bool using_surface_references() const {
- return lifetime_type_ == LifetimeType::REFERENCES;
- }
-
// Returns the most recent surface associated with the |fallback_surface_id|'s
// FrameSinkId that was created prior to the current primary surface and
// verified by the viz host to be owned by the fallback surface's parent. If
@@ -214,6 +217,16 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
using SurfaceIdSet = std::unordered_set<SurfaceId, SurfaceIdHash>;
+ // The reason for removing a temporary reference.
+ enum class RemovedReason {
+ EMBEDDED, // The surface was embedded.
+ DROPPED, // The surface won't be embedded so it was dropped.
+ SKIPPED, // A newer surface was embedded and the surface was skipped.
+ INVALIDATED, // The expected embedder was invalidated.
+ EXPIRED, // The surface was never embedded and expired.
+ COUNT
+ };
+
struct SurfaceReferenceInfo {
SurfaceReferenceInfo();
~SurfaceReferenceInfo();
@@ -263,13 +276,15 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
// owner initially.
void AddTemporaryReference(const SurfaceId& surface_id);
- // Removes temporary reference to |surface_id|. If |remove_range| is true then
- // all temporary references to surfaces with the same FrameSinkId as
- // |surface_id| that were added before |surface_id| will also be removed.
- void RemoveTemporaryReference(const SurfaceId& surface_id, bool remove_range);
+ // Removes temporary reference to |surface_id|. The |reason| for removing will
+ // be recorded with UMA. If |reason| is EMBEDDED then older temporary
+ // references from the same FrameSinkId will also be removed.
+ void RemoveTemporaryReference(const SurfaceId& surface_id,
+ RemovedReason reason);
- // Marks old temporary references for logging and deletion.
- void MarkOldTemporaryReferences();
+ // Marks and then expires old temporary references. This function is run
+ // periodically by a timer.
+ void ExpireOldTemporaryReferences();
// Removes the surface from the surface map and destroys it.
void DestroySurfaceInternal(const SurfaceId& surface_id);
@@ -284,14 +299,7 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
// Returns true if |surface_id| is in the garbage collector's queue.
bool IsMarkedForDestruction(const SurfaceId& surface_id);
- // Determines if the provided |owner| FrameSinkId matches the FrameSinkId of
- // a surface in the set of |fallback_parents|.
- bool IsOwnerAmongFallbackParents(
- const base::flat_set<SurfaceId>& fallback_parents,
- const base::Optional<FrameSinkId>& owner) const;
-
- // Use reference or sequence based lifetime management.
- LifetimeType lifetime_type_;
+ base::Optional<uint32_t> activation_deadline_in_frames_;
// SurfaceDependencyTracker needs to be destroyed after Surfaces are destroyed
// because they will call back into the dependency tracker.
@@ -303,10 +311,6 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
base::flat_set<SurfaceId> surfaces_to_destroy_;
- // Set of SurfaceSequences that have been satisfied by a frame but not yet
- // waited on.
- base::flat_set<SurfaceSequence> satisfied_sequences_;
-
// Set of valid FrameSinkIds and their labels. When a FrameSinkId is removed
// from this set, any remaining (surface) sequences with that FrameSinkId are
// considered satisfied.
@@ -320,9 +324,8 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
// for a SurfaceId.
const base::flat_set<SurfaceId> empty_surface_id_set_;
- // The DirectSurfaceReferenceFactory that uses this manager to create surface
- // references.
- scoped_refptr<SurfaceReferenceFactory> reference_factory_;
+ // Used for setting deadlines for surface synchronization.
+ base::TickClock* tick_clock_;
// Keeps track of surface references for a surface. The graph of references is
// stored in both directions, so we know the parents and children for each
@@ -346,8 +349,10 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
std::unordered_map<FrameSinkId, std::vector<LocalSurfaceId>, FrameSinkIdHash>
temporary_reference_ranges_;
- // Timer that ticks every 10 seconds and calls MarkTemporaryReference().
- base::RepeatingTimer temporary_reference_timer_;
+ // 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_;
base::WeakPtrFactory<SurfaceManager> weak_factory_;
diff --git a/chromium/components/viz/service/surfaces/surface_observer.h b/chromium/components/viz/service/surfaces/surface_observer.h
index c02498b2cf3..f9ce1816281 100644
--- a/chromium/components/viz/service/surfaces/surface_observer.h
+++ b/chromium/components/viz/service/surfaces/surface_observer.h
@@ -5,6 +5,9 @@
#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"
+
namespace viz {
class Surface;
@@ -22,8 +25,12 @@ class SurfaceObserver {
// time.
virtual void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) = 0;
- // Called when a CompositorFrame within |surface| activates.
- virtual void OnSurfaceActivated(const SurfaceId& surface_id) = 0;
+ // Called when a CompositorFrame within a surface corresponding to
+ // |surface_id| activates. If the CompositorFrame was blocked on activation
+ // dependencies then |duration| specifies the amount of time that frame was
+ // blocked.
+ virtual void OnSurfaceActivated(const SurfaceId& surface_id,
+ base::Optional<base::TimeDelta> duration) = 0;
// Called when a Surface was marked to be destroyed.
virtual void OnSurfaceDestroyed(const SurfaceId& surface_id) = 0;
diff --git a/chromium/components/viz/service/surfaces/surface_unittest.cc b/chromium/components/viz/service/surfaces/surface_unittest.cc
index 1745dd664ac..e4aeb448f20 100644
--- a/chromium/components/viz/service/surfaces/surface_unittest.cc
+++ b/chromium/components/viz/service/surfaces/surface_unittest.cc
@@ -58,51 +58,6 @@ TEST(SurfaceTest, PresentationCallback) {
support->SubmitCompositorFrame(local_surface_id, std::move(frame));
testing::Mock::VerifyAndClearExpectations(&client);
}
-
- {
- // Submits a frame with token 3 and different size. This frame with token 3
- // will be discarded immediately.
- CompositorFrame frame = CompositorFrameBuilder()
- .AddRenderPass(gfx::Rect(400, 400), kDamageRect)
- .SetPresentationToken(3)
- .Build();
- EXPECT_CALL(client, DidDiscardCompositorFrame(3)).Times(1);
- support->SubmitCompositorFrame(local_surface_id, std::move(frame));
- testing::Mock::VerifyAndClearExpectations(&client);
- }
-
- {
- // Submits a frame with token 4 and different scale factor, this frame with
- // token 4 will be discarded immediately.
- CompositorFrame frame =
- CompositorFrameBuilder()
- .AddRenderPass(gfx::Rect(kSurfaceSize), kDamageRect)
- .SetDeviceScaleFactor(2.f)
- .SetPresentationToken(4)
- .Build();
- EXPECT_CALL(client, DidDiscardCompositorFrame(2)).Times(1);
- EXPECT_CALL(client, DidDiscardCompositorFrame(4)).Times(1);
- support->SubmitCompositorFrame(local_surface_id, std::move(frame));
- }
-}
-
-TEST(SurfaceTest, SurfaceLifetime) {
- FrameSinkManagerImpl frame_sink_manager(
- SurfaceManager::LifetimeType::SEQUENCES);
- SurfaceManager* surface_manager = frame_sink_manager.surface_manager();
- auto support = std::make_unique<CompositorFrameSinkSupport>(
- nullptr, &frame_sink_manager, kArbitraryFrameSinkId, kIsRoot,
- kNeedsSyncPoints);
-
- LocalSurfaceId local_surface_id(6, base::UnguessableToken::Create());
- SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id);
- support->SubmitCompositorFrame(local_surface_id,
- MakeDefaultCompositorFrame());
- EXPECT_TRUE(surface_manager->GetSurfaceForId(surface_id));
- support->EvictCurrentSurface();
- frame_sink_manager.surface_manager()->GarbageCollectSurfaces();
-
- EXPECT_EQ(nullptr, surface_manager->GetSurfaceForId(surface_id));
}
TEST(SurfaceTest, SurfaceIds) {
@@ -172,8 +127,6 @@ TEST(SurfaceTest, CopyRequestLifetime) {
EXPECT_FALSE(copy_called);
copy_requests.clear(); // Deleted requests will auto-send an empty result.
EXPECT_TRUE(copy_called);
-
- support->EvictCurrentSurface();
}
} // namespace
diff --git a/chromium/components/viz/test/BUILD.gn b/chromium/components/viz/test/BUILD.gn
index edfa6754479..6dbd5cae4de 100644
--- a/chromium/components/viz/test/BUILD.gn
+++ b/chromium/components/viz/test/BUILD.gn
@@ -21,6 +21,8 @@ viz_static_library("test_support") {
"fake_external_begin_frame_source.h",
"fake_host_frame_sink_client.cc",
"fake_host_frame_sink_client.h",
+ "fake_output_surface.cc",
+ "fake_output_surface.h",
"fake_surface_observer.cc",
"fake_surface_observer.h",
"mock_compositor_frame_sink_client.cc",
@@ -30,18 +32,34 @@ viz_static_library("test_support") {
"mock_helper.h",
"ordered_simple_task_runner.cc",
"ordered_simple_task_runner.h",
+ "ordered_texture_map.cc",
+ "ordered_texture_map.h",
"paths.cc",
"paths.h",
"surface_hittest_test_helpers.cc",
"surface_hittest_test_helpers.h",
+ "test_context_provider.cc",
+ "test_context_provider.h",
+ "test_context_support.cc",
+ "test_context_support.h",
+ "test_display_provider.cc",
+ "test_display_provider.h",
"test_frame_sink_manager.cc",
"test_frame_sink_manager.h",
"test_frame_sink_manager_client.cc",
"test_frame_sink_manager_client.h",
+ "test_gles2_interface.cc",
+ "test_gles2_interface.h",
"test_gpu_memory_buffer_manager.cc",
"test_gpu_memory_buffer_manager.h",
"test_layer_tree_frame_sink.cc",
"test_layer_tree_frame_sink.h",
+ "test_shared_bitmap_manager.cc",
+ "test_shared_bitmap_manager.h",
+ "test_texture.cc",
+ "test_texture.h",
+ "test_web_graphics_context_3d.cc",
+ "test_web_graphics_context_3d.h",
]
deps = [
"//base",
@@ -49,10 +67,14 @@ viz_static_library("test_support") {
"//cc",
"//components/viz/host",
"//components/viz/service",
+ "//gpu:raster",
+ "//gpu:test_support",
+ "//gpu/skia_bindings",
"//services/viz/privileged/interfaces/compositing",
"//testing/gmock",
"//testing/gtest",
"//ui/gfx/geometry",
+ "//ui/gl",
]
}
@@ -76,6 +98,7 @@ viz_source_set("unit_tests") {
"begin_frame_source_test_unittest.cc",
"mock_helper_unittest.cc",
"ordered_simple_task_runner_unittest.cc",
+ "test_web_graphics_context_3d_unittest.cc",
]
deps = [
":test_support",
diff --git a/chromium/components/wallpaper/OWNERS b/chromium/components/wallpaper/OWNERS
index a9af8c98de7..663b89a6601 100644
--- a/chromium/components/wallpaper/OWNERS
+++ b/chromium/components/wallpaper/OWNERS
@@ -1,4 +1,5 @@
bshe@chromium.org
+wzang@chromium.org
xdai@chromium.org
# COMPONENT: UI>Shell>Wallpaper
diff --git a/chromium/components/wallpaper/wallpaper_color_calculator_unittest.cc b/chromium/components/wallpaper/wallpaper_color_calculator_unittest.cc
index fa7007d9731..0245d09b06b 100644
--- a/chromium/components/wallpaper/wallpaper_color_calculator_unittest.cc
+++ b/chromium/components/wallpaper/wallpaper_color_calculator_unittest.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/test/histogram_tester.h"
#include "base/test/null_task_runner.h"
@@ -126,7 +125,7 @@ void WallPaperColorCalculatorTest::InstallTaskRunner(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
task_runner_handle_.reset();
task_runner_handle_ =
- base::MakeUnique<base::ThreadTaskRunnerHandle>(task_runner);
+ std::make_unique<base::ThreadTaskRunnerHandle>(task_runner);
if (calculator_)
calculator_->SetTaskRunnerForTest(task_runner);
}
@@ -136,7 +135,7 @@ void WallPaperColorCalculatorTest::CreateCalculator(
std::vector<color_utils::ColorProfile> color_profiles;
color_profiles.emplace_back(color_utils::LumaRange::NORMAL,
color_utils::SaturationRange::VIBRANT);
- calculator_ = base::MakeUnique<WallpaperColorCalculator>(
+ calculator_ = std::make_unique<WallpaperColorCalculator>(
image, color_profiles, task_runner_);
calculator_->AddObserver(&observer_);
}
diff --git a/chromium/components/wallpaper/wallpaper_resizer_unittest.cc b/chromium/components/wallpaper/wallpaper_resizer_unittest.cc
index 8e8145508cd..295c656fc29 100644
--- a/chromium/components/wallpaper/wallpaper_resizer_unittest.cc
+++ b/chromium/components/wallpaper/wallpaper_resizer_unittest.cc
@@ -9,7 +9,6 @@
#include <memory>
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/threading/thread.h"
@@ -89,7 +88,7 @@ class WallpaperResizerTest : public testing::Test,
}
void WaitForResize() {
- active_runloop_ = base::MakeUnique<base::RunLoop>();
+ active_runloop_ = std::make_unique<base::RunLoop>();
active_runloop_->Run();
}
diff --git a/chromium/components/web_cache/renderer/web_cache_impl.cc b/chromium/components/web_cache/renderer/web_cache_impl.cc
index 23a815466b2..332ec6aaf4a 100644
--- a/chromium/components/web_cache/renderer/web_cache_impl.cc
+++ b/chromium/components/web_cache/renderer/web_cache_impl.cc
@@ -5,6 +5,7 @@
#include "components/web_cache/renderer/web_cache_impl.h"
#include <limits>
+#include <memory>
#include "base/bind.h"
#include "base/numerics/safe_conversions.h"
@@ -18,14 +19,14 @@
namespace web_cache {
WebCacheImpl::WebCacheImpl() : clear_cache_state_(kInit) {
- auto registry = base::MakeUnique<service_manager::BinderRegistry>();
+ auto registry = std::make_unique<service_manager::BinderRegistry>();
registry->AddInterface(
base::Bind(&WebCacheImpl::BindRequest, base::Unretained(this)),
base::ThreadTaskRunnerHandle::Get());
if (content::ChildThread::Get()) {
content::ChildThread::Get()
->GetServiceManagerConnection()
- ->AddConnectionFilter(base::MakeUnique<content::SimpleConnectionFilter>(
+ ->AddConnectionFilter(std::make_unique<content::SimpleConnectionFilter>(
std::move(registry)));
}
}
diff --git a/chromium/components/web_contents_delegate_android/DEPS b/chromium/components/web_contents_delegate_android/DEPS
index a02205147e0..23a65e31661 100644
--- a/chromium/components/web_contents_delegate_android/DEPS
+++ b/chromium/components/web_contents_delegate_android/DEPS
@@ -2,7 +2,7 @@ include_rules = [
"+content/public/browser",
"+content/public/common",
"+jni",
- "+third_party/WebKit/common",
+ "+third_party/WebKit/public/mojom",
"+ui/android",
"+ui/base",
"+ui/gfx"
diff --git a/chromium/components/web_contents_delegate_android/color_chooser_android.h b/chromium/components/web_contents_delegate_android/color_chooser_android.h
index 03dd7e51c69..2b871e73dec 100644
--- a/chromium/components/web_contents_delegate_android/color_chooser_android.h
+++ b/chromium/components/web_contents_delegate_android/color_chooser_android.h
@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "base/strings/string16.h"
#include "content/public/browser/color_chooser.h"
-#include "third_party/WebKit/common/color_chooser/color_chooser.mojom.h"
+#include "third_party/WebKit/public/mojom/color_chooser/color_chooser.mojom.h"
using base::android::AttachCurrentThread;
using base::android::ScopedJavaLocalRef;
diff --git a/chromium/components/web_contents_delegate_android/web_contents_delegate_android.cc b/chromium/components/web_contents_delegate_android/web_contents_delegate_android.cc
index 296832bf808..0d77a101184 100644
--- a/chromium/components/web_contents_delegate_android/web_contents_delegate_android.cc
+++ b/chromium/components/web_contents_delegate_android/web_contents_delegate_android.cc
@@ -167,7 +167,9 @@ void WebContentsDelegateAndroid::LoadProgressChanged(WebContents* source,
Java_WebContentsDelegateAndroid_notifyLoadProgressChanged(env, obj, progress);
}
-void WebContentsDelegateAndroid::RendererUnresponsive(WebContents* source) {
+void WebContentsDelegateAndroid::RendererUnresponsive(
+ WebContents* source,
+ content::RenderWidgetHost* render_widget_host) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
if (obj.is_null())
@@ -175,7 +177,9 @@ void WebContentsDelegateAndroid::RendererUnresponsive(WebContents* source) {
Java_WebContentsDelegateAndroid_rendererUnresponsive(env, obj);
}
-void WebContentsDelegateAndroid::RendererResponsive(WebContents* source) {
+void WebContentsDelegateAndroid::RendererResponsive(
+ WebContents* source,
+ content::RenderWidgetHost* render_widget_host) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
if (obj.is_null())
diff --git a/chromium/components/web_contents_delegate_android/web_contents_delegate_android.h b/chromium/components/web_contents_delegate_android/web_contents_delegate_android.h
index 20be76009d9..81c3ae00a35 100644
--- a/chromium/components/web_contents_delegate_android/web_contents_delegate_android.h
+++ b/chromium/components/web_contents_delegate_android/web_contents_delegate_android.h
@@ -63,8 +63,12 @@ class WebContentsDelegateAndroid : public content::WebContentsDelegate {
bool to_different_document) override;
void LoadProgressChanged(content::WebContents* source,
double load_progress) override;
- void RendererUnresponsive(content::WebContents* source) override;
- void RendererResponsive(content::WebContents* source) override;
+ void RendererUnresponsive(
+ content::WebContents* source,
+ content::RenderWidgetHost* render_widget_host) override;
+ void RendererResponsive(
+ content::WebContents* source,
+ content::RenderWidgetHost* render_widget_host) override;
void WebContentsCreated(content::WebContents* source_contents,
int opener_render_process_id,
int opener_render_frame_id,
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 89f5a347a59..ab6663fa568 100644
--- a/chromium/components/web_modal/web_contents_modal_dialog_manager.cc
+++ b/chromium/components/web_modal/web_contents_modal_dialog_manager.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <utility>
+#include "base/logging.h"
#include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_view_host.h"
@@ -90,6 +91,8 @@ WebContentsModalDialogManager::WebContentsModalDialogManager(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
delegate_(nullptr),
+ web_contents_is_hidden_(web_contents->GetVisibility() ==
+ content::Visibility::HIDDEN),
closing_all_dialogs_(false) {}
WebContentsModalDialogManager::DialogState::DialogState(
@@ -150,14 +153,21 @@ void WebContentsModalDialogManager::DidGetIgnoredUIEvent() {
}
}
-void WebContentsModalDialogManager::WasShown() {
- if (!child_dialogs_.empty())
- child_dialogs_.front().manager->Show();
-}
+void WebContentsModalDialogManager::OnVisibilityChanged(
+ content::Visibility visibility) {
+ const bool web_contents_was_hidden = web_contents_is_hidden_;
+ web_contents_is_hidden_ = visibility == content::Visibility::HIDDEN;
+
+ // Avoid reshowing on transitions between VISIBLE and OCCLUDED.
+ if (child_dialogs_.empty() ||
+ web_contents_is_hidden_ == web_contents_was_hidden) {
+ return;
+ }
-void WebContentsModalDialogManager::WasHidden() {
- if (!child_dialogs_.empty())
+ if (web_contents_is_hidden_)
child_dialogs_.front().manager->Hide();
+ else
+ child_dialogs_.front().manager->Show();
}
void WebContentsModalDialogManager::WebContentsDestroyed() {
diff --git a/chromium/components/web_modal/web_contents_modal_dialog_manager.h b/chromium/components/web_modal/web_contents_modal_dialog_manager.h
index 8c2de6434d8..4636b8c815f 100644
--- a/chromium/components/web_modal/web_contents_modal_dialog_manager.h
+++ b/chromium/components/web_modal/web_contents_modal_dialog_manager.h
@@ -63,8 +63,9 @@ class WebContentsModalDialogManager
void CloseAllDialogs() { manager_->CloseAllDialogs(); }
void DidAttachInterstitialPage() { manager_->DidAttachInterstitialPage(); }
- void WebContentsWasShown() { manager_->WasShown(); }
- void WebContentsWasHidden() { manager_->WasHidden(); }
+ void WebContentsVisibilityChanged(content::Visibility visibility) {
+ manager_->OnVisibilityChanged(visibility);
+ }
private:
WebContentsModalDialogManager* manager_;
@@ -100,8 +101,7 @@ class WebContentsModalDialogManager
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
void DidGetIgnoredUIEvent() override;
- void WasShown() override;
- void WasHidden() override;
+ void OnVisibilityChanged(content::Visibility visibility) override;
void WebContentsDestroyed() override;
void DidAttachInterstitialPage() override;
@@ -111,6 +111,9 @@ class WebContentsModalDialogManager
// All active dialogs.
WebContentsModalDialogList child_dialogs_;
+ // Whether the WebContents' visibility is content::Visibility::HIDDEN.
+ bool web_contents_is_hidden_;
+
// True while closing the dialogs on WebContents close.
bool closing_all_dialogs_;
diff --git a/chromium/components/web_modal/web_contents_modal_dialog_manager_unittest.cc b/chromium/components/web_modal/web_contents_modal_dialog_manager_unittest.cc
index 3cb810f2f91..526ab207aac 100644
--- a/chromium/components/web_modal/web_contents_modal_dialog_manager_unittest.cc
+++ b/chromium/components/web_modal/web_contents_modal_dialog_manager_unittest.cc
@@ -200,13 +200,13 @@ TEST_F(WebContentsModalDialogManagerTest, VisibilityObservation) {
EXPECT_TRUE(delegate->web_contents_blocked());
EXPECT_EQ(NativeManagerTracker::SHOWN, tracker.state_);
- test_api->WebContentsWasHidden();
+ test_api->WebContentsVisibilityChanged(content::Visibility::HIDDEN);
EXPECT_TRUE(manager->IsDialogActive());
EXPECT_TRUE(delegate->web_contents_blocked());
EXPECT_EQ(NativeManagerTracker::HIDDEN, tracker.state_);
- test_api->WebContentsWasShown();
+ test_api->WebContentsVisibilityChanged(content::Visibility::VISIBLE);
EXPECT_TRUE(manager->IsDialogActive());
EXPECT_TRUE(delegate->web_contents_blocked());
diff --git a/chromium/components/web_resource/web_resource_service.cc b/chromium/components/web_resource/web_resource_service.cc
index 0e94cabe210..148ba724ea4 100644
--- a/chromium/components/web_resource/web_resource_service.cc
+++ b/chromium/components/web_resource/web_resource_service.cc
@@ -4,6 +4,8 @@
#include "components/web_resource/web_resource_service.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
@@ -84,7 +86,7 @@ void WebResourceService::OnURLFetchComplete(const net::URLFetcher* source) {
// (on Android in particular) we short-cut the full parsing in the case of
// trivially "empty" JSONs.
if (data.empty() || data == "{}") {
- OnUnpackFinished(base::MakeUnique<base::DictionaryValue>());
+ OnUnpackFinished(std::make_unique<base::DictionaryValue>());
} else {
parse_json_callback_.Run(data,
base::Bind(&WebResourceService::OnUnpackFinished,
diff --git a/chromium/components/web_restrictions/BUILD.gn b/chromium/components/web_restrictions/BUILD.gn
index 80ef8d189da..a78173e73c3 100644
--- a/chromium/components/web_restrictions/BUILD.gn
+++ b/chromium/components/web_restrictions/BUILD.gn
@@ -30,6 +30,7 @@ if (is_android) {
":client_java",
":provider_java",
"//base:base_java",
+ "//base:base_junit_test_support",
"//third_party/hamcrest:hamcrest_java",
]
}
diff --git a/chromium/components/web_restrictions/browser/web_restrictions_mojo_implementation.cc b/chromium/components/web_restrictions/browser/web_restrictions_mojo_implementation.cc
index a30f427305a..05e2c15b384 100644
--- a/chromium/components/web_restrictions/browser/web_restrictions_mojo_implementation.cc
+++ b/chromium/components/web_restrictions/browser/web_restrictions_mojo_implementation.cc
@@ -4,10 +4,10 @@
#include "components/web_restrictions/browser/web_restrictions_mojo_implementation.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
-#include "base/memory/ptr_util.h"
#include "components/web_restrictions/browser/web_restrictions_client.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -33,7 +33,7 @@ void WebRestrictionsMojoImplementation::Create(
WebRestrictionsClient* client,
mojom::WebRestrictionsRequest request) {
mojo::MakeStrongBinding(
- base::MakeUnique<WebRestrictionsMojoImplementation>(client),
+ std::make_unique<WebRestrictionsMojoImplementation>(client),
std::move(request));
}
diff --git a/chromium/components/webcrypto/algorithms/aes_cbc_unittest.cc b/chromium/components/webcrypto/algorithms/aes_cbc_unittest.cc
index 88204984a12..9f7257e52f1 100644
--- a/chromium/components/webcrypto/algorithms/aes_cbc_unittest.cc
+++ b/chromium/components/webcrypto/algorithms/aes_cbc_unittest.cc
@@ -6,10 +6,10 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <utility>
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "components/webcrypto/algorithm_dispatch.h"
#include "components/webcrypto/algorithms/test_helpers.h"
@@ -222,7 +222,7 @@ TEST_F(WebCryptoAesCbcTest, ImportKeyJwkEmptyKeyOps) {
dict.SetString("kty", "oct");
dict.SetBoolean("ext", false);
dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
- dict.Set("key_ops", base::MakeUnique<base::ListValue>());
+ dict.Set("key_ops", std::make_unique<base::ListValue>());
// The JWK does not contain encrypt usages.
EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(),
@@ -264,7 +264,7 @@ TEST_F(WebCryptoAesCbcTest, ImportKeyJwkKeyOpsEncryptDecrypt) {
dict.SetString("kty", "oct");
dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
base::ListValue* key_ops =
- dict.SetList("key_ops", base::MakeUnique<base::ListValue>());
+ dict.SetList("key_ops", std::make_unique<base::ListValue>());
key_ops->AppendString("encrypt");
@@ -301,7 +301,7 @@ TEST_F(WebCryptoAesCbcTest, ImportKeyJwkKeyOpsNotSuperset) {
base::DictionaryValue dict;
dict.SetString("kty", "oct");
dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
- auto key_ops = base::MakeUnique<base::ListValue>();
+ auto key_ops = std::make_unique<base::ListValue>();
key_ops->AppendString("encrypt");
dict.Set("key_ops", std::move(key_ops));
@@ -366,7 +366,7 @@ TEST_F(WebCryptoAesCbcTest, ImportJwkKeyOpsLacksUsages) {
dict.SetString("kty", "oct");
dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
- auto key_ops = base::MakeUnique<base::ListValue>();
+ auto key_ops = std::make_unique<base::ListValue>();
key_ops->AppendString("foo");
dict.Set("key_ops", std::move(key_ops));
EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(),
diff --git a/chromium/components/webcrypto/algorithms/aes_kw_unittest.cc b/chromium/components/webcrypto/algorithms/aes_kw_unittest.cc
index 12dea24036a..e8a96071778 100644
--- a/chromium/components/webcrypto/algorithms/aes_kw_unittest.cc
+++ b/chromium/components/webcrypto/algorithms/aes_kw_unittest.cc
@@ -5,8 +5,9 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "components/webcrypto/algorithm_dispatch.h"
@@ -60,7 +61,7 @@ TEST_F(WebCryptoAesKwTest, ImportKeyJwkKeyOpsWrapUnwrap) {
dict.SetString("kty", "oct");
dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
base::ListValue* key_ops =
- dict.SetList("key_ops", base::MakeUnique<base::ListValue>());
+ dict.SetList("key_ops", std::make_unique<base::ListValue>());
key_ops->AppendString("wrapKey");
diff --git a/chromium/components/webcrypto/algorithms/hmac_unittest.cc b/chromium/components/webcrypto/algorithms/hmac_unittest.cc
index 6765714b671..774db860b02 100644
--- a/chromium/components/webcrypto/algorithms/hmac_unittest.cc
+++ b/chromium/components/webcrypto/algorithms/hmac_unittest.cc
@@ -6,10 +6,10 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <utility>
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "components/webcrypto/algorithm_dispatch.h"
#include "components/webcrypto/algorithms/test_helpers.h"
@@ -232,7 +232,7 @@ TEST_F(WebCryptoHmacTest, ImportKeyJwkKeyOpsSignVerify) {
dict.SetString("kty", "oct");
dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
base::ListValue* key_ops =
- dict.SetList("key_ops", base::MakeUnique<base::ListValue>());
+ dict.SetList("key_ops", std::make_unique<base::ListValue>());
key_ops->AppendString("sign");
@@ -264,7 +264,7 @@ TEST_F(WebCryptoHmacTest, ImportKeyJwkUseInconsisteWithKeyOps) {
dict.SetString("alg", "HS256");
dict.SetString("use", "sig");
- auto key_ops = base::MakeUnique<base::ListValue>();
+ auto key_ops = std::make_unique<base::ListValue>();
key_ops->AppendString("sign");
key_ops->AppendString("verify");
key_ops->AppendString("encrypt");
diff --git a/chromium/components/webcrypto/algorithms/sha.cc b/chromium/components/webcrypto/algorithms/sha.cc
index a81130f8e9b..e1ed20aeef9 100644
--- a/chromium/components/webcrypto/algorithms/sha.cc
+++ b/chromium/components/webcrypto/algorithms/sha.cc
@@ -119,7 +119,7 @@ class ShaImplementation : public AlgorithmImplementation {
} // namespace
std::unique_ptr<AlgorithmImplementation> CreateShaImplementation() {
- return base::MakeUnique<ShaImplementation>();
+ return std::make_unique<ShaImplementation>();
}
std::unique_ptr<blink::WebCryptoDigestor> CreateDigestorImplementation(
diff --git a/chromium/components/webcrypto/webcrypto_impl.cc b/chromium/components/webcrypto/webcrypto_impl.cc
index a96aeb35132..bdda3a73421 100644
--- a/chromium/components/webcrypto/webcrypto_impl.cc
+++ b/chromium/components/webcrypto/webcrypto_impl.cc
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <memory>
+#include <utility>
#include "base/bind.h"
#include "base/lazy_instance.h"
@@ -78,8 +79,7 @@ class CryptoThreadPool {
worker_thread_.StartWithOptions(options);
}
- static bool PostTask(const base::Location& from_here,
- const base::Closure& task);
+ static bool PostTask(const base::Location& from_here, base::OnceClosure task);
private:
// TODO(gab): the pool is currently using a single non-joinable thread to
@@ -96,9 +96,9 @@ base::LazyInstance<CryptoThreadPool>::Leaky crypto_thread_pool =
LAZY_INSTANCE_INITIALIZER;
bool CryptoThreadPool::PostTask(const base::Location& from_here,
- const base::Closure& task) {
+ base::OnceClosure task) {
return crypto_thread_pool.Get().worker_thread_.task_runner()->PostTask(
- from_here, task);
+ from_here, std::move(task));
}
void CompleteWithThreadPoolError(blink::WebCryptoResult* result) {
@@ -393,7 +393,7 @@ void DoEncrypt(std::unique_ptr<EncryptState> passed_state) {
webcrypto::Encrypt(state->algorithm, state->key,
webcrypto::CryptoData(state->data), &state->buffer);
state->origin_thread->PostTask(
- FROM_HERE, base::Bind(DoEncryptReply, base::Passed(&passed_state)));
+ FROM_HERE, base::BindOnce(DoEncryptReply, std::move(passed_state)));
}
void DoDecryptReply(std::unique_ptr<DecryptState> state) {
@@ -411,7 +411,7 @@ void DoDecrypt(std::unique_ptr<DecryptState> passed_state) {
webcrypto::Decrypt(state->algorithm, state->key,
webcrypto::CryptoData(state->data), &state->buffer);
state->origin_thread->PostTask(
- FROM_HERE, base::Bind(DoDecryptReply, base::Passed(&passed_state)));
+ FROM_HERE, base::BindOnce(DoDecryptReply, std::move(passed_state)));
}
void DoDigestReply(std::unique_ptr<DigestState> state) {
@@ -427,7 +427,7 @@ void DoDigest(std::unique_ptr<DigestState> passed_state) {
state->status = webcrypto::Digest(
state->algorithm, webcrypto::CryptoData(state->data), &state->buffer);
state->origin_thread->PostTask(
- FROM_HERE, base::Bind(DoDigestReply, base::Passed(&passed_state)));
+ FROM_HERE, base::BindOnce(DoDigestReply, std::move(passed_state)));
}
void DoGenerateKeyReply(std::unique_ptr<GenerateKeyState> state) {
@@ -449,7 +449,7 @@ void DoGenerateKey(std::unique_ptr<GenerateKeyState> passed_state) {
webcrypto::GenerateKey(state->algorithm, state->extractable,
state->usages, &state->generate_key_result);
state->origin_thread->PostTask(
- FROM_HERE, base::Bind(DoGenerateKeyReply, base::Passed(&passed_state)));
+ FROM_HERE, base::BindOnce(DoGenerateKeyReply, std::move(passed_state)));
}
void DoImportKeyReply(std::unique_ptr<ImportKeyState> state) {
@@ -473,7 +473,7 @@ void DoImportKey(std::unique_ptr<ImportKeyState> passed_state) {
}
state->origin_thread->PostTask(
- FROM_HERE, base::Bind(DoImportKeyReply, base::Passed(&passed_state)));
+ FROM_HERE, base::BindOnce(DoImportKeyReply, std::move(passed_state)));
}
void DoExportKeyReply(std::unique_ptr<ExportKeyState> state) {
@@ -501,7 +501,7 @@ void DoExportKey(std::unique_ptr<ExportKeyState> passed_state) {
state->status =
webcrypto::ExportKey(state->format, state->key, &state->buffer);
state->origin_thread->PostTask(
- FROM_HERE, base::Bind(DoExportKeyReply, base::Passed(&passed_state)));
+ FROM_HERE, base::BindOnce(DoExportKeyReply, std::move(passed_state)));
}
void DoSignReply(std::unique_ptr<SignState> state) {
@@ -519,7 +519,7 @@ void DoSign(std::unique_ptr<SignState> passed_state) {
webcrypto::CryptoData(state->data), &state->buffer);
state->origin_thread->PostTask(
- FROM_HERE, base::Bind(DoSignReply, base::Passed(&passed_state)));
+ FROM_HERE, base::BindOnce(DoSignReply, std::move(passed_state)));
}
void DoVerifyReply(std::unique_ptr<VerifySignatureState> state) {
@@ -541,7 +541,7 @@ void DoVerify(std::unique_ptr<VerifySignatureState> passed_state) {
webcrypto::CryptoData(state->data), &state->verify_result);
state->origin_thread->PostTask(
- FROM_HERE, base::Bind(DoVerifyReply, base::Passed(&passed_state)));
+ FROM_HERE, base::BindOnce(DoVerifyReply, std::move(passed_state)));
}
void DoWrapKeyReply(std::unique_ptr<WrapKeyState> state) {
@@ -560,7 +560,7 @@ void DoWrapKey(std::unique_ptr<WrapKeyState> passed_state) {
state->wrap_algorithm, &state->buffer);
state->origin_thread->PostTask(
- FROM_HERE, base::Bind(DoWrapKeyReply, base::Passed(&passed_state)));
+ FROM_HERE, base::BindOnce(DoWrapKeyReply, std::move(passed_state)));
}
void DoUnwrapKeyReply(std::unique_ptr<UnwrapKeyState> state) {
@@ -581,7 +581,7 @@ void DoUnwrapKey(std::unique_ptr<UnwrapKeyState> passed_state) {
&state->unwrapped_key);
state->origin_thread->PostTask(
- FROM_HERE, base::Bind(DoUnwrapKeyReply, base::Passed(&passed_state)));
+ FROM_HERE, base::BindOnce(DoUnwrapKeyReply, std::move(passed_state)));
}
void DoDeriveBitsReply(std::unique_ptr<DeriveBitsState> state) {
@@ -600,7 +600,7 @@ void DoDeriveBits(std::unique_ptr<DeriveBitsState> passed_state) {
webcrypto::DeriveBits(state->algorithm, state->base_key,
state->length_bits, &state->derived_bytes);
state->origin_thread->PostTask(
- FROM_HERE, base::Bind(DoDeriveBitsReply, base::Passed(&passed_state)));
+ FROM_HERE, base::BindOnce(DoDeriveBitsReply, std::move(passed_state)));
}
void DoDeriveKeyReply(std::unique_ptr<DeriveKeyState> state) {
@@ -619,7 +619,7 @@ void DoDeriveKey(std::unique_ptr<DeriveKeyState> passed_state) {
state->key_length_algorithm, state->extractable, state->usages,
&state->derived_key);
state->origin_thread->PostTask(
- FROM_HERE, base::Bind(DoDeriveKeyReply, base::Passed(&passed_state)));
+ FROM_HERE, base::BindOnce(DoDeriveKeyReply, std::move(passed_state)));
}
} // namespace
@@ -641,7 +641,7 @@ void WebCryptoImpl::Encrypt(
std::unique_ptr<EncryptState> state(new EncryptState(
algorithm, key, std::move(data), result, std::move(task_runner)));
if (!CryptoThreadPool::PostTask(
- FROM_HERE, base::Bind(DoEncrypt, base::Passed(&state)))) {
+ FROM_HERE, base::BindOnce(DoEncrypt, std::move(state)))) {
CompleteWithThreadPoolError(&result);
}
}
@@ -657,7 +657,7 @@ void WebCryptoImpl::Decrypt(
std::unique_ptr<DecryptState> state(new DecryptState(
algorithm, key, std::move(data), result, std::move(task_runner)));
if (!CryptoThreadPool::PostTask(
- FROM_HERE, base::Bind(DoDecrypt, base::Passed(&state)))) {
+ FROM_HERE, base::BindOnce(DoDecrypt, std::move(state)))) {
CompleteWithThreadPoolError(&result);
}
}
@@ -673,7 +673,7 @@ void WebCryptoImpl::Digest(
new DigestState(algorithm, blink::WebCryptoKey::CreateNull(),
std::move(data), result, std::move(task_runner)));
if (!CryptoThreadPool::PostTask(FROM_HERE,
- base::Bind(DoDigest, base::Passed(&state)))) {
+ base::BindOnce(DoDigest, std::move(state)))) {
CompleteWithThreadPoolError(&result);
}
}
@@ -689,7 +689,7 @@ void WebCryptoImpl::GenerateKey(
std::unique_ptr<GenerateKeyState> state(new GenerateKeyState(
algorithm, extractable, usages, result, std::move(task_runner)));
if (!CryptoThreadPool::PostTask(
- FROM_HERE, base::Bind(DoGenerateKey, base::Passed(&state)))) {
+ FROM_HERE, base::BindOnce(DoGenerateKey, std::move(state)))) {
CompleteWithThreadPoolError(&result);
}
}
@@ -706,7 +706,7 @@ void WebCryptoImpl::ImportKey(
new ImportKeyState(format, std::move(key_data), algorithm, extractable,
usages, result, std::move(task_runner)));
if (!CryptoThreadPool::PostTask(
- FROM_HERE, base::Bind(DoImportKey, base::Passed(&state)))) {
+ FROM_HERE, base::BindOnce(DoImportKey, std::move(state)))) {
CompleteWithThreadPoolError(&result);
}
}
@@ -719,7 +719,7 @@ void WebCryptoImpl::ExportKey(
std::unique_ptr<ExportKeyState> state(
new ExportKeyState(format, key, result, std::move(task_runner)));
if (!CryptoThreadPool::PostTask(
- FROM_HERE, base::Bind(DoExportKey, base::Passed(&state)))) {
+ FROM_HERE, base::BindOnce(DoExportKey, std::move(state)))) {
CompleteWithThreadPoolError(&result);
}
}
@@ -733,7 +733,7 @@ void WebCryptoImpl::Sign(
std::unique_ptr<SignState> state(new SignState(
algorithm, key, std::move(data), result, std::move(task_runner)));
if (!CryptoThreadPool::PostTask(FROM_HERE,
- base::Bind(DoSign, base::Passed(&state)))) {
+ base::BindOnce(DoSign, std::move(state)))) {
CompleteWithThreadPoolError(&result);
}
}
@@ -749,7 +749,7 @@ void WebCryptoImpl::VerifySignature(
algorithm, key, std::move(signature), std::move(data), result,
std::move(task_runner)));
if (!CryptoThreadPool::PostTask(FROM_HERE,
- base::Bind(DoVerify, base::Passed(&state)))) {
+ base::BindOnce(DoVerify, std::move(state)))) {
CompleteWithThreadPoolError(&result);
}
}
@@ -765,7 +765,7 @@ void WebCryptoImpl::WrapKey(
new WrapKeyState(format, key, wrapping_key, wrap_algorithm, result,
std::move(task_runner)));
if (!CryptoThreadPool::PostTask(
- FROM_HERE, base::Bind(DoWrapKey, base::Passed(&state)))) {
+ FROM_HERE, base::BindOnce(DoWrapKey, std::move(state)))) {
CompleteWithThreadPoolError(&result);
}
}
@@ -785,7 +785,7 @@ void WebCryptoImpl::UnwrapKey(
unwrap_algorithm, unwrapped_key_algorithm, extractable,
usages, result, std::move(task_runner)));
if (!CryptoThreadPool::PostTask(
- FROM_HERE, base::Bind(DoUnwrapKey, base::Passed(&state)))) {
+ FROM_HERE, base::BindOnce(DoUnwrapKey, std::move(state)))) {
CompleteWithThreadPoolError(&result);
}
}
@@ -799,7 +799,7 @@ void WebCryptoImpl::DeriveBits(
std::unique_ptr<DeriveBitsState> state(new DeriveBitsState(
algorithm, base_key, length_bits, result, std::move(task_runner)));
if (!CryptoThreadPool::PostTask(
- FROM_HERE, base::Bind(DoDeriveBits, base::Passed(&state)))) {
+ FROM_HERE, base::BindOnce(DoDeriveBits, std::move(state)))) {
CompleteWithThreadPoolError(&result);
}
}
@@ -817,7 +817,7 @@ void WebCryptoImpl::DeriveKey(
algorithm, base_key, import_algorithm, key_length_algorithm, extractable,
usages, result, std::move(task_runner)));
if (!CryptoThreadPool::PostTask(
- FROM_HERE, base::Bind(DoDeriveKey, base::Passed(&state)))) {
+ FROM_HERE, base::BindOnce(DoDeriveKey, std::move(state)))) {
CompleteWithThreadPoolError(&result);
}
}
diff --git a/chromium/components/webdata/common/web_data_request_manager.cc b/chromium/components/webdata/common/web_data_request_manager.cc
index 991ff7412d6..5c74f24499a 100644
--- a/chromium/components/webdata/common/web_data_request_manager.cc
+++ b/chromium/components/webdata/common/web_data_request_manager.cc
@@ -105,9 +105,8 @@ void WebDataRequestManager::RequestCompleted(
// effectively does a std::move() on |request|!
scoped_refptr<base::SequencedTaskRunner> task_runner =
request->GetTaskRunner();
- auto task =
- base::BindOnce(&WebDataRequestManager::RequestCompletedOnThread, this,
- base::Passed(&request), base::Passed(&result));
+ auto task = base::BindOnce(&WebDataRequestManager::RequestCompletedOnThread,
+ this, std::move(request), std::move(result));
if (task_runner)
task_runner->PostTask(FROM_HERE, std::move(task));
else
diff --git a/chromium/components/webdata/common/web_database_service.cc b/chromium/components/webdata/common/web_database_service.cc
index 052a3ad03aa..c7f41fe5a47 100644
--- a/chromium/components/webdata/common/web_database_service.cc
+++ b/chromium/components/webdata/common/web_database_service.cc
@@ -95,8 +95,8 @@ void WebDatabaseService::ScheduleDBTask(const base::Location& from_here,
std::unique_ptr<WebDataRequest> request =
web_db_backend_->request_manager()->NewRequest(nullptr);
db_task_runner_->PostTask(
- from_here, Bind(&WebDatabaseBackend::DBWriteTaskWrapper, web_db_backend_,
- task, base::Passed(&request)));
+ from_here, BindOnce(&WebDatabaseBackend::DBWriteTaskWrapper,
+ web_db_backend_, task, std::move(request)));
}
WebDataServiceBase::Handle WebDatabaseService::ScheduleDBTaskWithResult(
@@ -109,8 +109,8 @@ WebDataServiceBase::Handle WebDatabaseService::ScheduleDBTaskWithResult(
web_db_backend_->request_manager()->NewRequest(consumer);
WebDataServiceBase::Handle handle = request->GetHandle();
db_task_runner_->PostTask(
- from_here, Bind(&WebDatabaseBackend::DBReadTaskWrapper, web_db_backend_,
- task, base::Passed(&request)));
+ from_here, BindOnce(&WebDatabaseBackend::DBReadTaskWrapper,
+ web_db_backend_, task, std::move(request)));
return handle;
}
diff --git a/chromium/components/webdata_services/web_data_service_wrapper.cc b/chromium/components/webdata_services/web_data_service_wrapper.cc
index 86939a98d22..6f6d495a4cc 100644
--- a/chromium/components/webdata_services/web_data_service_wrapper.cc
+++ b/chromium/components/webdata_services/web_data_service_wrapper.cc
@@ -4,16 +4,16 @@
#include "components/webdata_services/web_data_service_wrapper.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/callback.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/webdata/autocomplete_sync_bridge.h"
-#include "components/autofill/core/browser/webdata/autocomplete_syncable_service.h"
#include "components/autofill/core/browser/webdata/autofill_profile_syncable_service.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h"
@@ -51,16 +51,8 @@ void InitSyncableServicesOnDBSequence(
// Currently only Autocomplete and Autofill profiles use the new Sync API, but
// all the database data should migrate to this API over time.
- if (base::FeatureList::IsEnabled(switches::kSyncUSSAutocomplete)) {
- autofill::AutocompleteSyncBridge::CreateForWebDataServiceAndBackend(
- autofill_web_data.get(), autofill_backend);
- } else {
- autofill::AutocompleteSyncableService::CreateForWebDataServiceAndBackend(
- autofill_web_data.get(), autofill_backend);
- autofill::AutocompleteSyncableService::FromWebDataService(
- autofill_web_data.get())
- ->InjectStartSyncFlare(sync_flare);
- }
+ autofill::AutocompleteSyncBridge::CreateForWebDataServiceAndBackend(
+ autofill_web_data.get(), autofill_backend);
autofill::AutofillProfileSyncableService::CreateForWebDataServiceAndBackend(
autofill_web_data.get(), autofill_backend, app_locale);
@@ -99,18 +91,18 @@ WebDataServiceWrapper::WebDataServiceWrapper(
// All tables objects that participate in managing the database must
// be added here.
- web_database_->AddTable(base::MakeUnique<autofill::AutofillTable>());
- web_database_->AddTable(base::MakeUnique<KeywordTable>());
+ web_database_->AddTable(std::make_unique<autofill::AutofillTable>());
+ web_database_->AddTable(std::make_unique<KeywordTable>());
// TODO(mdm): We only really need the LoginsTable on Windows for IE7 password
// access, but for now, we still create it on all platforms since it deletes
// the old logins table. We can remove this after a while, e.g. in M22 or so.
- web_database_->AddTable(base::MakeUnique<LoginsTable>());
- web_database_->AddTable(base::MakeUnique<TokenServiceTable>());
+ web_database_->AddTable(std::make_unique<LoginsTable>());
+ web_database_->AddTable(std::make_unique<TokenServiceTable>());
#if !defined(OS_IOS)
web_database_->AddTable(
- base::MakeUnique<payments::PaymentMethodManifestTable>());
+ std::make_unique<payments::PaymentMethodManifestTable>());
web_database_->AddTable(
- base::MakeUnique<payments::WebAppManifestSectionTable>());
+ std::make_unique<payments::WebAppManifestSectionTable>());
#endif
web_database_->LoadDatabase();
diff --git a/chromium/components/webdata_services/web_data_service_wrapper.h b/chromium/components/webdata_services/web_data_service_wrapper.h
index 135dd2bf702..d01c34f0f46 100644
--- a/chromium/components/webdata_services/web_data_service_wrapper.h
+++ b/chromium/components/webdata_services/web_data_service_wrapper.h
@@ -57,9 +57,10 @@ class WebDataServiceWrapper : public KeyedService {
// database.
// |diagnostics| contains information about the underlying database
// which can help in identifying the cause of the error.
- using ShowErrorCallback = void (*)(ErrorType error_type,
- sql::InitStatus init_status,
- const std::string& diagnostics);
+ using ShowErrorCallback =
+ base::RepeatingCallback<void(ErrorType error_type,
+ sql::InitStatus init_status,
+ const std::string& diagnostics)>;
// Constructor for WebDataServiceWrapper that initializes the different
// WebDataServices and starts the synchronization services using |flare|.
diff --git a/chromium/components/webrtc_logging/OWNERS b/chromium/components/webrtc_logging/OWNERS
new file mode 100644
index 00000000000..aa82f4fd437
--- /dev/null
+++ b/chromium/components/webrtc_logging/OWNERS
@@ -0,0 +1,4 @@
+grunell@chromium.org
+tommi@chromium.org
+
+# COMPONENT: Blink>WebRTC>Tools
diff --git a/chromium/components/webrtc_logging/README.md b/chromium/components/webrtc_logging/README.md
new file mode 100644
index 00000000000..bfd5dc3d157
--- /dev/null
+++ b/chromium/components/webrtc_logging/README.md
@@ -0,0 +1,4 @@
+# WebRTC Logging
+
+This component provides helpers for uploading WebRTC message logs for diagnostic
+purposes.
diff --git a/chromium/components/webrtc_logging/browser/BUILD.gn b/chromium/components/webrtc_logging/browser/BUILD.gn
new file mode 100644
index 00000000000..b1f22936dcd
--- /dev/null
+++ b/chromium/components/webrtc_logging/browser/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//media/media_options.gni")
+
+assert(enable_webrtc)
+
+source_set("browser") {
+ sources = [
+ "log_cleanup.cc",
+ "log_cleanup.h",
+ "log_list.cc",
+ "log_list.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/upload_list",
+ "//content/public/browser",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "log_cleanup_unittest.cc",
+ ]
+ deps = [
+ ":browser",
+ "//base",
+ "//content/test:test_support",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/webrtc_logging/browser/DEPS b/chromium/components/webrtc_logging/browser/DEPS
new file mode 100644
index 00000000000..9d7ae7d804a
--- /dev/null
+++ b/chromium/components/webrtc_logging/browser/DEPS
@@ -0,0 +1,10 @@
+include_rules = [
+ "+components/upload_list",
+ "+content/public/browser",
+]
+
+specific_include_rules = {
+ ".*test\.cc": [
+ "+content/public/test",
+ ]
+}
diff --git a/chromium/components/webrtc_logging/browser/log_cleanup.cc b/chromium/components/webrtc_logging/browser/log_cleanup.cc
new file mode 100644
index 00000000000..2f3fc805a97
--- /dev/null
+++ b/chromium/components/webrtc_logging/browser/log_cleanup.cc
@@ -0,0 +1,104 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/webrtc_logging/browser/log_cleanup.h"
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
+#include "components/webrtc_logging/browser/log_list.h"
+
+namespace webrtc_logging {
+
+namespace {
+
+const int kDaysToKeepLogs = 5;
+
+// Remove any empty entries from the log list. One line is one log entry, see
+// WebRtcLogUploader::AddLocallyStoredLogInfoToUploadListFile for more
+// information about the format.
+void RemoveEmptyEntriesInLogList(std::string* log_list) {
+ static const char kEmptyLine[] = ",,\n";
+ size_t pos = 0;
+ do {
+ pos = log_list->find(kEmptyLine, pos);
+ if (pos == std::string::npos)
+ break;
+ DCHECK(pos == 0 || (*log_list)[pos - 1] == '\n');
+ log_list->erase(pos, arraysize(kEmptyLine) - 1);
+ } while (true);
+}
+
+} // namespace
+
+void DeleteOldWebRtcLogFiles(const base::FilePath& log_dir) {
+ DeleteOldAndRecentWebRtcLogFiles(log_dir, base::Time::Max());
+}
+
+void DeleteOldAndRecentWebRtcLogFiles(const base::FilePath& log_dir,
+ const base::Time& delete_begin_time) {
+ base::AssertBlockingAllowed();
+
+ if (!base::PathExists(log_dir)) {
+ // This will happen if no logs have been stored or uploaded.
+ DVLOG(3) << "Could not find directory: " << log_dir.value();
+ return;
+ }
+
+ const base::Time now = base::Time::Now();
+ const base::TimeDelta time_to_keep_logs =
+ base::TimeDelta::FromDays(kDaysToKeepLogs);
+
+ base::FilePath log_list_path =
+ LogList::GetWebRtcLogListFileForDirectory(log_dir);
+ std::string log_list;
+ const bool update_log_list = base::PathExists(log_list_path);
+ if (update_log_list) {
+ bool read_ok = base::ReadFileToString(log_list_path, &log_list);
+ DPCHECK(read_ok);
+ }
+
+ base::FileEnumerator log_files(log_dir, false, base::FileEnumerator::FILES);
+ bool delete_ok = true;
+ for (base::FilePath name = log_files.Next(); !name.empty();
+ name = log_files.Next()) {
+ if (name == log_list_path)
+ continue;
+ base::FileEnumerator::FileInfo file_info(log_files.GetInfo());
+ base::TimeDelta file_age = now - file_info.GetLastModifiedTime();
+ if (file_age > time_to_keep_logs ||
+ (!delete_begin_time.is_max() &&
+ file_info.GetLastModifiedTime() > delete_begin_time)) {
+ if (!base::DeleteFile(name, false))
+ delete_ok = false;
+
+ // Remove the local ID from the log list file. The ID is guaranteed to be
+ // unique.
+ std::string id = file_info.GetName().RemoveExtension().MaybeAsASCII();
+ size_t id_pos = log_list.find(id);
+ if (id_pos == std::string::npos)
+ continue;
+ log_list.erase(id_pos, id.size());
+ }
+ }
+
+ if (!delete_ok)
+ LOG(WARNING) << "Could not delete all old WebRTC logs.";
+
+ RemoveEmptyEntriesInLogList(&log_list);
+
+ if (update_log_list) {
+ int written = base::WriteFile(log_list_path, &log_list[0], log_list.size());
+ DPCHECK(written == static_cast<int>(log_list.size()));
+ }
+}
+
+} // namespace webrtc_logging
diff --git a/chromium/components/webrtc_logging/browser/log_cleanup.h b/chromium/components/webrtc_logging/browser/log_cleanup.h
new file mode 100644
index 00000000000..dc8fdd9a787
--- /dev/null
+++ b/chromium/components/webrtc_logging/browser/log_cleanup.h
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_WEBRTC_LOGGING_BROWSER_LOG_CLEANUP_H_
+#define COMPONENTS_WEBRTC_LOGGING_BROWSER_LOG_CLEANUP_H_
+
+namespace base {
+class FilePath;
+class Time;
+} // namespace base
+
+namespace webrtc_logging {
+
+// Deletes logs files older that 5 days. Updates the log file list. Must be
+// called on the FILE thread.
+void DeleteOldWebRtcLogFiles(const base::FilePath& log_dir);
+
+// Deletes logs files older that 5 days and logs younger than
+// |delete_begin_time|. Updates the log file list. If |delete_begin_time| is
+// base::time::Max(), no recent logs will be deleted, and the function is
+// equal to DeleteOldWebRtcLogFiles(). Must be called on the FILE thread.
+void DeleteOldAndRecentWebRtcLogFiles(const base::FilePath& log_dir,
+ const base::Time& delete_begin_time);
+
+} // namespace webrtc_logging
+
+#endif // COMPONENTS_WEBRTC_LOGGING_BROWSER_LOG_CLEANUP_H_
diff --git a/chromium/components/webrtc_logging/browser/log_cleanup_unittest.cc b/chromium/components/webrtc_logging/browser/log_cleanup_unittest.cc
new file mode 100644
index 00000000000..5d6ec15b4be
--- /dev/null
+++ b/chromium/components/webrtc_logging/browser/log_cleanup_unittest.cc
@@ -0,0 +1,76 @@
+// 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/webrtc_logging/browser/log_cleanup.h"
+
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/time/time.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace webrtc_logging {
+
+namespace {
+
+const int kExpectedDaysToKeepLogFiles = 5;
+
+} // namespace
+
+class WebRtcLogCleanupTest : public testing::Test {
+ public:
+ WebRtcLogCleanupTest() = default;
+
+ void SetUp() override {
+ // Create three files. One with modified date as of now, one with date one
+ // day younger than the keep limit, one with date one day older than the
+ // limit. The two former are expected to be kept and the last to be deleted
+ // when deleting old logs.
+ ASSERT_TRUE(dir_.CreateUniqueTempDir());
+ base::FilePath file;
+ ASSERT_TRUE(CreateTemporaryFileInDir(dir_.GetPath(), &file));
+ ASSERT_TRUE(CreateTemporaryFileInDir(dir_.GetPath(), &file));
+ base::Time time_expect_to_keep =
+ base::Time::Now() -
+ base::TimeDelta::FromDays(kExpectedDaysToKeepLogFiles - 1);
+ TouchFile(file, time_expect_to_keep, time_expect_to_keep);
+ ASSERT_TRUE(CreateTemporaryFileInDir(dir_.GetPath(), &file));
+ base::Time time_expect_to_delete =
+ base::Time::Now() -
+ base::TimeDelta::FromDays(kExpectedDaysToKeepLogFiles + 1);
+ TouchFile(file, time_expect_to_delete, time_expect_to_delete);
+ }
+
+ void VerifyFiles(int expected_files) {
+ base::FileEnumerator files(dir_.GetPath(), false,
+ base::FileEnumerator::FILES);
+ int file_counter = 0;
+ for (base::FilePath name = files.Next(); !name.empty();
+ name = files.Next()) {
+ EXPECT_LT(base::Time::Now() - files.GetInfo().GetLastModifiedTime(),
+ base::TimeDelta::FromDays(kExpectedDaysToKeepLogFiles));
+ ++file_counter;
+ }
+ EXPECT_EQ(expected_files, file_counter);
+ }
+
+ content::TestBrowserThreadBundle test_browser_thread_bundle_;
+ base::ScopedTempDir dir_;
+};
+
+TEST_F(WebRtcLogCleanupTest, DeleteOldWebRtcLogFiles) {
+ DeleteOldWebRtcLogFiles(dir_.GetPath());
+ VerifyFiles(2);
+}
+
+TEST_F(WebRtcLogCleanupTest, DeleteOldAndRecentWebRtcLogFiles) {
+ base::Time time_begin_delete =
+ base::Time::Now() - base::TimeDelta::FromDays(1);
+ DeleteOldAndRecentWebRtcLogFiles(dir_.GetPath(), time_begin_delete);
+ VerifyFiles(1);
+}
+
+} // namespace webrtc_logging
diff --git a/chromium/components/webrtc_logging/browser/log_list.cc b/chromium/components/webrtc_logging/browser/log_list.cc
new file mode 100644
index 00000000000..4d25b271631
--- /dev/null
+++ b/chromium/components/webrtc_logging/browser/log_list.cc
@@ -0,0 +1,44 @@
+// 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/webrtc_logging/browser/log_list.h"
+
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/task_scheduler/post_task.h"
+#include "components/upload_list/text_log_upload_list.h"
+#include "content/public/browser/browser_context.h"
+
+namespace webrtc_logging {
+
+namespace {
+
+const char kWebRtcLogDirectory[] = "WebRTC Logs";
+const char kWebRtcLogListFilename[] = "Log List";
+
+} // namespace
+
+// static
+UploadList* LogList::CreateWebRtcLogList(
+ content::BrowserContext* browser_context) {
+ base::FilePath log_list_path = GetWebRtcLogListFileForDirectory(
+ GetWebRtcLogDirectoryForBrowserContextPath(browser_context->GetPath()));
+ return new TextLogUploadList(log_list_path);
+}
+
+// static
+base::FilePath LogList::GetWebRtcLogDirectoryForBrowserContextPath(
+ const base::FilePath& browser_context_path) {
+ DCHECK(!browser_context_path.empty());
+ return browser_context_path.AppendASCII(kWebRtcLogDirectory);
+}
+
+// static
+base::FilePath LogList::GetWebRtcLogListFileForDirectory(
+ const base::FilePath& dir) {
+ DCHECK(!dir.empty());
+ return dir.AppendASCII(kWebRtcLogListFilename);
+}
+
+} // namespace webrtc_logging
diff --git a/chromium/components/webrtc_logging/browser/log_list.h b/chromium/components/webrtc_logging/browser/log_list.h
new file mode 100644
index 00000000000..6a4b00a94fb
--- /dev/null
+++ b/chromium/components/webrtc_logging/browser/log_list.h
@@ -0,0 +1,39 @@
+// 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_WEBRTC_LOGGING_BROWSER_LOG_LIST_H_
+#define COMPONENTS_WEBRTC_LOGGING_BROWSER_LOG_LIST_H_
+
+#include "base/files/file_path.h"
+
+class UploadList;
+
+namespace content {
+class BrowserContext;
+} // namespace content
+
+namespace webrtc_logging {
+
+class LogList {
+ public:
+ // Creates the upload list with the given callback delegate for a
+ // browser context. The upload list loads and parses a text file list of
+ // WebRTC logs stored locally and/or uploaded.
+ static UploadList* CreateWebRtcLogList(
+ content::BrowserContext* browser_context);
+
+ // Gets the file path for the log directory in a browser context's directory.
+ // The directory name will be appended to |browser_context_path| and returned.
+ static base::FilePath GetWebRtcLogDirectoryForBrowserContextPath(
+ const base::FilePath& browser_context_path);
+
+ // Gets the file path for the log list file in a directory. The log list file
+ // name will be appended to |dir| and returned.
+ static base::FilePath GetWebRtcLogListFileForDirectory(
+ const base::FilePath& dir);
+};
+
+} // namespace webrtc_logging
+
+#endif // COMPONENTS_WEBRTC_LOGGING_BROWSER_LOG_LIST_H_
diff --git a/chromium/components/webrtc_logging/common/BUILD.gn b/chromium/components/webrtc_logging/common/BUILD.gn
new file mode 100644
index 00000000000..9df6f3b6e02
--- /dev/null
+++ b/chromium/components/webrtc_logging/common/BUILD.gn
@@ -0,0 +1,30 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//media/media_options.gni")
+
+assert(enable_webrtc)
+
+source_set("common") {
+ sources = [
+ "partial_circular_buffer.cc",
+ "partial_circular_buffer.h",
+ ]
+
+ deps = [
+ "//base",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "partial_circular_buffer_unittest.cc",
+ ]
+ deps = [
+ ":common",
+ "//base",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/webrtc_logging/common/partial_circular_buffer.cc b/chromium/components/webrtc_logging/common/partial_circular_buffer.cc
new file mode 100644
index 00000000000..9a35d8651e1
--- /dev/null
+++ b/chromium/components/webrtc_logging/common/partial_circular_buffer.cc
@@ -0,0 +1,190 @@
+// 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/webrtc_logging/common/partial_circular_buffer.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+
+namespace webrtc_logging {
+
+namespace {
+
+inline uint32_t Min3(uint32_t a, uint32_t b, uint32_t c) {
+ return std::min(a, std::min(b, c));
+}
+
+} // namespace
+
+PartialCircularBuffer::PartialCircularBuffer(void* buffer, uint32_t buffer_size)
+ : buffer_data_(reinterpret_cast<BufferData*>(buffer)),
+ memory_buffer_size_(buffer_size),
+ data_size_(0),
+ position_(0),
+ total_read_(0) {
+ uint32_t header_size =
+ buffer_data_->data - reinterpret_cast<uint8_t*>(buffer_data_);
+ data_size_ = memory_buffer_size_ - header_size;
+
+ DCHECK(buffer_data_);
+ DCHECK_GE(memory_buffer_size_, header_size);
+ DCHECK_LE(buffer_data_->total_written, data_size_);
+ DCHECK_LT(buffer_data_->wrap_position, data_size_);
+ DCHECK_LT(buffer_data_->end_position, data_size_);
+}
+
+PartialCircularBuffer::PartialCircularBuffer(void* buffer,
+ uint32_t buffer_size,
+ uint32_t wrap_position,
+ bool append)
+ : buffer_data_(reinterpret_cast<BufferData*>(buffer)),
+ memory_buffer_size_(buffer_size),
+ data_size_(0),
+ position_(0),
+ total_read_(0) {
+ uint32_t header_size =
+ buffer_data_->data - reinterpret_cast<uint8_t*>(buffer_data_);
+ data_size_ = memory_buffer_size_ - header_size;
+
+ DCHECK(buffer_data_);
+ DCHECK_GE(memory_buffer_size_, header_size);
+
+ if (append) {
+ DCHECK_LT(buffer_data_->wrap_position, data_size_);
+ position_ = buffer_data_->end_position;
+ } else {
+ DCHECK_LT(wrap_position, data_size_);
+ buffer_data_->total_written = 0;
+ buffer_data_->wrap_position = wrap_position;
+ buffer_data_->end_position = 0;
+ }
+}
+
+uint32_t PartialCircularBuffer::Read(void* buffer, uint32_t buffer_size) {
+ DCHECK(buffer_data_);
+ if (total_read_ >= buffer_data_->total_written)
+ return 0;
+
+ uint8_t* buffer_uint8 = reinterpret_cast<uint8_t*>(buffer);
+ uint32_t read = 0;
+
+ // Read from beginning part.
+ if (position_ < buffer_data_->wrap_position) {
+ uint32_t to_wrap_pos = buffer_data_->wrap_position - position_;
+ uint32_t to_eow = buffer_data_->total_written - total_read_;
+ uint32_t to_read = Min3(buffer_size, to_wrap_pos, to_eow);
+ memcpy(buffer_uint8, buffer_data_->data + position_, to_read);
+ position_ += to_read;
+ total_read_ += to_read;
+ read += to_read;
+ if (position_ == buffer_data_->wrap_position &&
+ buffer_data_->total_written == data_size_) {
+ // We've read all the beginning part, set the position to the middle part.
+ // (The second condition above checks if the wrapping part is filled, i.e.
+ // writing has wrapped.)
+ position_ = buffer_data_->end_position;
+ }
+ if (read >= buffer_size) {
+ DCHECK_EQ(read, buffer_size);
+ return read;
+ }
+ if (read >= to_eow) {
+ DCHECK_EQ(read, to_eow);
+ DCHECK_EQ(total_read_, buffer_data_->total_written);
+ return read;
+ }
+ }
+
+ // Read from middle part.
+ DCHECK_GE(position_, buffer_data_->wrap_position);
+ if (position_ >= buffer_data_->end_position) {
+ uint32_t remaining_buffer_size = buffer_size - read;
+ uint32_t to_eof = data_size_ - position_;
+ uint32_t to_eow = buffer_data_->total_written - total_read_;
+ uint32_t to_read = Min3(remaining_buffer_size, to_eof, to_eow);
+ memcpy(buffer_uint8 + read, buffer_data_->data + position_, to_read);
+ position_ += to_read;
+ total_read_ += to_read;
+ read += to_read;
+ if (position_ == data_size_) {
+ // We've read all the middle part, set position to the end part.
+ position_ = buffer_data_->wrap_position;
+ }
+ if (read >= buffer_size) {
+ DCHECK_EQ(read, buffer_size);
+ return read;
+ }
+ if (total_read_ >= buffer_data_->total_written) {
+ DCHECK_EQ(total_read_, buffer_data_->total_written);
+ return read;
+ }
+ }
+
+ // Read from end part.
+ DCHECK_GE(position_, buffer_data_->wrap_position);
+ DCHECK_LT(position_, buffer_data_->end_position);
+ uint32_t remaining_buffer_size = buffer_size - read;
+ uint32_t to_eob = buffer_data_->end_position - position_;
+ uint32_t to_eow = buffer_data_->total_written - total_read_;
+ uint32_t to_read = Min3(remaining_buffer_size, to_eob, to_eow);
+ memcpy(buffer_uint8 + read, buffer_data_->data + position_, to_read);
+ position_ += to_read;
+ total_read_ += to_read;
+ read += to_read;
+ DCHECK_LE(read, buffer_size);
+ DCHECK_LE(total_read_, buffer_data_->total_written);
+ return read;
+}
+
+void PartialCircularBuffer::Write(const void* buffer, uint32_t buffer_size) {
+ DCHECK(buffer_data_);
+ const uint8_t* input = static_cast<const uint8_t*>(buffer);
+ uint32_t wrap_position = buffer_data_->wrap_position;
+ uint32_t cycle_size = data_size_ - wrap_position;
+
+ // First write the non-wrapping part.
+ if (position_ < wrap_position) {
+ uint32_t space_left = wrap_position - position_;
+ uint32_t write_size = std::min(buffer_size, space_left);
+ DoWrite(input, write_size);
+ input += write_size;
+ buffer_size -= write_size;
+ }
+
+ // Skip the part that would overlap.
+ if (buffer_size > cycle_size) {
+ uint32_t skip = buffer_size - cycle_size;
+ input += skip;
+ buffer_size -= skip;
+ position_ = wrap_position + (position_ - wrap_position + skip) % cycle_size;
+ }
+
+ // Finally write the wrapping part.
+ DoWrite(input, buffer_size);
+}
+
+void PartialCircularBuffer::DoWrite(const uint8_t* input, uint32_t input_size) {
+ DCHECK_LT(position_, data_size_);
+ buffer_data_->total_written =
+ std::min(buffer_data_->total_written + input_size, data_size_);
+
+ // Write() skips any overlapping part, so this loop will run at most twice.
+ while (input_size > 0) {
+ uint32_t space_left = data_size_ - position_;
+ uint32_t write_size = std::min(input_size, space_left);
+ memcpy(buffer_data_->data + position_, input, write_size);
+ input += write_size;
+ input_size -= write_size;
+ position_ += write_size;
+ if (position_ >= data_size_) {
+ DCHECK_EQ(position_, data_size_);
+ position_ = buffer_data_->wrap_position;
+ }
+ }
+
+ buffer_data_->end_position = position_;
+}
+
+} // namespace webrtc_logging
diff --git a/chromium/components/webrtc_logging/common/partial_circular_buffer.h b/chromium/components/webrtc_logging/common/partial_circular_buffer.h
new file mode 100644
index 00000000000..e78411ab23a
--- /dev/null
+++ b/chromium/components/webrtc_logging/common/partial_circular_buffer.h
@@ -0,0 +1,70 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_WEBRTC_LOGGING_COMMON_PARTIAL_CIRCULAR_BUFFER_H_
+#define COMPONENTS_WEBRTC_LOGGING_COMMON_PARTIAL_CIRCULAR_BUFFER_H_
+
+#include <stdint.h>
+
+namespace webrtc_logging {
+
+// A wrapper around a memory buffer that allows circular read and write with a
+// selectable wrapping position. Buffer layout (after wrap; H is header):
+// -----------------------------------------------------------
+// | H | Beginning | End | Middle |
+// -----------------------------------------------------------
+// ^---- Non-wrapping -----^ ^--------- Wrapping ----------^
+// The non-wrapping part is never overwritten. The wrapping part will be
+// circular. The very first part is the header (see the BufferData struct
+// below). It consists of the following information:
+// - Length written to the buffer (not including header).
+// - Wrapping position.
+// - End position of buffer. (If the last byte is at x, this will be x + 1.)
+// Users of wrappers around the same underlying buffer must ensure that writing
+// is finished before reading is started.
+class PartialCircularBuffer {
+ public:
+ // Use for reading. |buffer_size| is in bytes and must be larger than the
+ // header size (see above).
+ PartialCircularBuffer(void* buffer, uint32_t buffer_size);
+
+ // Use for writing. |buffer_size| is in bytes and must be larger than the
+ // header size (see above). If |append| is true, the header data is not reset
+ // and writing will continue were left off, |wrap_position| is then ignored.
+ PartialCircularBuffer(void* buffer,
+ uint32_t buffer_size,
+ uint32_t wrap_position,
+ bool append);
+
+ uint32_t Read(void* buffer, uint32_t buffer_size);
+ void Write(const void* buffer, uint32_t buffer_size);
+
+ private:
+ friend class PartialCircularBufferTest;
+
+#pragma pack(push)
+#pragma pack(4)
+ struct BufferData {
+ uint32_t total_written;
+ uint32_t wrap_position;
+ uint32_t end_position;
+ uint8_t data[1];
+ };
+#pragma pack(pop)
+
+ void DoWrite(const uint8_t* input, uint32_t input_size);
+
+ // Used for reading and writing.
+ BufferData* buffer_data_;
+ uint32_t memory_buffer_size_;
+ uint32_t data_size_;
+ uint32_t position_;
+
+ // Used for reading.
+ uint32_t total_read_;
+};
+
+} // namespace webrtc_logging
+
+#endif // COMPONENTS_WEBRTC_LOGGING_COMMON_PARTIAL_CIRCULAR_BUFFER_H_
diff --git a/chromium/components/webrtc_logging/common/partial_circular_buffer_unittest.cc b/chromium/components/webrtc_logging/common/partial_circular_buffer_unittest.cc
new file mode 100644
index 00000000000..a01e074845b
--- /dev/null
+++ b/chromium/components/webrtc_logging/common/partial_circular_buffer_unittest.cc
@@ -0,0 +1,223 @@
+// 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.
+
+// The test buffer data is 52 bytes, wrap position is set to 20 (this is
+// arbitrarily chosen). The total buffer size is allocated dynamically based on
+// the actual header size. This gives:
+// Header of some size, non-wrapping part 20 bytes, wrapping part 32 bytes.
+// As input data, a 14 byte array is used and repeatedly written. It's chosen
+// not to be an integer factor smaller than the wrapping part. This ensures that
+// the wrapped data isn't repeated at the same position.
+// Note that desipte the number of wraps (if one or more), the reference output
+// data is the same since the offset at each wrap is always the same.
+
+#include "components/webrtc_logging/common/partial_circular_buffer.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace webrtc_logging {
+
+namespace {
+
+const uint32_t kWrapPosition = 20;
+const uint8_t kInputData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+const uint8_t kOutputRefDataWrap[] =
+ // The 20 bytes in the non-wrapping part.
+ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2, 3, 4, 5, 6,
+ // The 32 bytes in wrapping part.
+ 11, 12, 13, 14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+
+} // namespace
+
+class PartialCircularBufferTest : public testing::Test {
+ public:
+ PartialCircularBufferTest() {
+ PartialCircularBuffer::BufferData test_struct;
+ buffer_header_size_ =
+ &test_struct.data[0] - reinterpret_cast<uint8_t*>(&test_struct);
+
+ buffer_.reset(
+ new uint8_t[buffer_header_size_ + sizeof(kOutputRefDataWrap)]);
+ }
+
+ void InitWriteBuffer(bool append) {
+ pcb_write_.reset(new PartialCircularBuffer(
+ buffer_.get(), buffer_header_size_ + sizeof(kOutputRefDataWrap),
+ kWrapPosition, append));
+ }
+
+ void WriteToBuffer(int num) {
+ for (int i = 0; i < num; ++i)
+ pcb_write_->Write(kInputData, sizeof(kInputData));
+ }
+
+ void InitReadBuffer() {
+ pcb_read_.reset(new PartialCircularBuffer(
+ buffer_.get(), buffer_header_size_ + sizeof(kOutputRefDataWrap)));
+ }
+
+ protected:
+ std::unique_ptr<PartialCircularBuffer> pcb_write_;
+ std::unique_ptr<PartialCircularBuffer> pcb_read_;
+ std::unique_ptr<uint8_t[]> buffer_;
+ uint32_t buffer_header_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(PartialCircularBufferTest);
+};
+
+TEST_F(PartialCircularBufferTest, NoWrapBeginningPartOnly) {
+ InitWriteBuffer(false);
+ WriteToBuffer(1);
+ InitReadBuffer();
+
+ uint8_t output_data[sizeof(kInputData)] = {0};
+ EXPECT_EQ(sizeof(output_data),
+ pcb_read_->Read(output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0, memcmp(kInputData, output_data, sizeof(kInputData)));
+
+ EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+TEST_F(PartialCircularBufferTest, NoWrapBeginningAndEndParts) {
+ InitWriteBuffer(false);
+ WriteToBuffer(2);
+ InitReadBuffer();
+
+ uint8_t output_data[2 * sizeof(kInputData)] = {0};
+ EXPECT_EQ(sizeof(output_data),
+ pcb_read_->Read(output_data, sizeof(output_data)));
+
+ const uint8_t output_ref_data[2 * sizeof(kInputData)] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+ EXPECT_EQ(0, memcmp(output_ref_data, output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+TEST_F(PartialCircularBufferTest, WrapOnce) {
+ InitWriteBuffer(false);
+ WriteToBuffer(4);
+ InitReadBuffer();
+
+ uint8_t output_data[sizeof(kOutputRefDataWrap)] = {0};
+ EXPECT_EQ(sizeof(output_data),
+ pcb_read_->Read(output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0, memcmp(kOutputRefDataWrap, output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+TEST_F(PartialCircularBufferTest, WrapTwice) {
+ InitWriteBuffer(false);
+ WriteToBuffer(7);
+ InitReadBuffer();
+
+ uint8_t output_data[sizeof(kOutputRefDataWrap)] = {0};
+ EXPECT_EQ(sizeof(output_data),
+ pcb_read_->Read(output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0, memcmp(kOutputRefDataWrap, output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+TEST_F(PartialCircularBufferTest, WrapOnceSmallerOutputBuffer) {
+ InitWriteBuffer(false);
+ WriteToBuffer(4);
+ InitReadBuffer();
+
+ uint8_t output_data[sizeof(kOutputRefDataWrap)] = {0};
+ const uint32_t size_per_read = 16;
+ uint32_t read = 0;
+ for (; read + size_per_read <= sizeof(output_data); read += size_per_read) {
+ EXPECT_EQ(size_per_read,
+ pcb_read_->Read(output_data + read, size_per_read));
+ }
+ EXPECT_EQ(sizeof(output_data) - read,
+ pcb_read_->Read(output_data + read, size_per_read));
+
+ EXPECT_EQ(0, memcmp(kOutputRefDataWrap, output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+TEST_F(PartialCircularBufferTest, WrapOnceWithAppend) {
+ InitWriteBuffer(false);
+ WriteToBuffer(2);
+ InitWriteBuffer(true);
+ WriteToBuffer(2);
+ InitReadBuffer();
+
+ uint8_t output_data[sizeof(kOutputRefDataWrap)] = {0};
+ EXPECT_EQ(sizeof(output_data),
+ pcb_read_->Read(output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0, memcmp(kOutputRefDataWrap, output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+TEST_F(PartialCircularBufferTest, WrapTwiceWithAppend) {
+ InitWriteBuffer(false);
+ WriteToBuffer(4);
+ InitWriteBuffer(true);
+ WriteToBuffer(3);
+ InitReadBuffer();
+
+ uint8_t output_data[sizeof(kOutputRefDataWrap)] = {0};
+ EXPECT_EQ(sizeof(output_data),
+ pcb_read_->Read(output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0, memcmp(kOutputRefDataWrap, output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+TEST_F(PartialCircularBufferTest, WrapOnceThenOverwriteWithNoWrap) {
+ InitWriteBuffer(false);
+ WriteToBuffer(4);
+ InitWriteBuffer(false);
+ WriteToBuffer(1);
+ InitReadBuffer();
+
+ uint8_t output_data[sizeof(kInputData)] = {0};
+ EXPECT_EQ(sizeof(output_data),
+ pcb_read_->Read(output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0, memcmp(kInputData, output_data, sizeof(kInputData)));
+
+ EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+TEST_F(PartialCircularBufferTest, WrapTwiceWithSingleWrite) {
+ const size_t kInputSize = sizeof(kInputData);
+ const size_t kLargeSize = kInputSize * 7;
+ uint8_t large_input[kLargeSize] = {0};
+ for (size_t offset = 0; offset < kLargeSize; offset += kInputSize)
+ memcpy(large_input + offset, kInputData, kInputSize);
+
+ InitWriteBuffer(false);
+ pcb_write_->Write(large_input, kLargeSize);
+ InitReadBuffer();
+
+ uint8_t output_data[sizeof(kOutputRefDataWrap)] = {0};
+ EXPECT_EQ(sizeof(output_data),
+ pcb_read_->Read(output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0, memcmp(kOutputRefDataWrap, output_data, sizeof(output_data)));
+
+ EXPECT_EQ(0u, pcb_read_->Read(output_data, sizeof(output_data)));
+}
+
+} // namespace webrtc_logging
diff --git a/chromium/components/zoom/zoom_event_manager.cc b/chromium/components/zoom/zoom_event_manager.cc
index cdb88db6401..a4b086088fc 100644
--- a/chromium/components/zoom/zoom_event_manager.cc
+++ b/chromium/components/zoom/zoom_event_manager.cc
@@ -4,7 +4,8 @@
#include "components/zoom/zoom_event_manager.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "components/zoom/zoom_event_manager_observer.h"
#include "content/public/browser/browser_context.h"
@@ -18,7 +19,7 @@ ZoomEventManager* ZoomEventManager::GetForBrowserContext(
content::BrowserContext* context) {
if (!context->GetUserData(kBrowserZoomEventManager)) {
context->SetUserData(kBrowserZoomEventManager,
- base::MakeUnique<ZoomEventManager>());
+ std::make_unique<ZoomEventManager>());
}
return static_cast<ZoomEventManager*>(
context->GetUserData(kBrowserZoomEventManager));